@openhands/agent-canvas 1.16.0 → 1.18.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 (1093) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{acp-providers-CX3Lh9gj.js → acp-providers-DcY_mKYa.js} +1 -1
  4. package/build/assets/active-backend-context-BnH4-L8h.js +2 -0
  5. package/build/assets/{agent-context-settings-DSZlXrLj.js → agent-context-settings-D3peZkjX.js} +1 -1
  6. package/build/assets/agent-profiles-service.api-DkeZaqIl.js +1 -0
  7. package/build/assets/agent-profiles-settings-7yMWYjGF.js +1 -0
  8. package/build/assets/agent-server-client-options-EHB23gyx.js +1 -0
  9. package/build/assets/agent-server-config-C_x8Otd9.js +1 -0
  10. package/build/assets/agent-server-conversation-service.api-jiCopc2E.js +88 -0
  11. package/build/assets/agent-settings-BF8hM6wb.js +2 -0
  12. package/build/assets/agent-settings-YPutBAeR.js +1 -0
  13. package/build/assets/alert-banner-eYyqvHL3.js +1 -0
  14. package/build/assets/{api-error-message-B-XdSk3b.js → api-error-message-BXo0lCI5.js} +1 -1
  15. package/build/assets/api-key-entry-screen-CCBvBD8u.js +1 -0
  16. package/build/assets/app-settings-BtYDs-Be.js +1 -0
  17. package/build/assets/automation-detail-BxXhb_m2.js +3 -0
  18. package/build/assets/{automation-export-D3a3of4G.js → automation-export-BJsfi7n2.js} +1 -1
  19. package/build/assets/automation-git-sync-B7o_Nbl-.js +1 -0
  20. package/build/assets/automation-setup-route-qaJ6lLCf.js +3 -0
  21. package/build/assets/{automation-templates-BRppNh99.js → automation-templates-Bb98r-kx.js} +1 -1
  22. package/build/assets/automations-list-DEPVNud3.js +1 -0
  23. package/build/assets/{back-nav-button-Cjl_hoxq.js → back-nav-button-B2yBiVMB.js} +1 -1
  24. package/build/assets/backend-form-modal-DxisQV_6.js +1 -0
  25. package/build/assets/backend-synced-settings-badge-DLEp6cq7.js +1 -0
  26. package/build/assets/badge-ehL-kgeO.js +1 -0
  27. package/build/assets/{base-modal-D_L0oEbG.js → base-modal-C1a0TsSx.js} +1 -1
  28. package/build/assets/bot-ByolqPEr.js +1 -0
  29. package/build/assets/{brand-button-BAfk4wGP.js → brand-button-CUMfjb99.js} +1 -1
  30. package/build/assets/browser-SE24Tk8g.js +46 -0
  31. package/build/assets/browser-tab-HjJxHA0V.js +1 -0
  32. package/build/assets/canvas-extension-page-BsUGBb1T.js +1 -0
  33. package/build/assets/canvas-extensions-C9Tm6s_E.js +1 -0
  34. package/build/assets/{canvas-extensions-runtime-2_x5Ezmi.js → canvas-extensions-runtime-B8kxM4rO.js} +1 -1
  35. package/build/assets/{chat-send-button-MUQqCZCS.js → chat-send-button-CGvc2wpE.js} +1 -1
  36. package/build/assets/check-Bo8s5Ylg.js +1 -0
  37. package/build/assets/chevron-down-Cr6Fn_wS.js +1 -0
  38. package/build/assets/chevron-right-CfdfRn-8.js +1 -0
  39. package/build/assets/circle-check-5pH3qCji.js +1 -0
  40. package/build/assets/circle-plus-check-toggle-BDX_ctNs.js +1 -0
  41. package/build/assets/{cloud-funnel-analytics-CztBCCPp.js → cloud-funnel-analytics-D5uJ_4JE.js} +1 -1
  42. package/build/assets/{cog-D-MPQW6G.js → cog-CAEugqtV.js} +1 -1
  43. package/build/assets/command-menu-CQxs4mtX.js +1 -0
  44. package/build/assets/commits-tab-D0xgjipP.js +1 -0
  45. package/build/assets/{condenser-settings-DmEOje-7.js → condenser-settings-D63NJRBT.js} +1 -1
  46. package/build/assets/confirmation-modal-78sd9Vny.js +1 -0
  47. package/build/assets/{context-menu-list-item-I86vKcmM.js → context-menu-list-item-Cm7-7Y-7.js} +1 -1
  48. package/build/assets/conversation-B_nweu5p.js +93 -0
  49. package/build/assets/conversation-edjzrv5w.js +1 -0
  50. package/build/assets/conversation-panel-edjzrv5w.js +1 -0
  51. package/build/assets/conversation-state-store-9D_3P7q4.js +1 -0
  52. package/build/assets/conversation-store-DC-JlJuq.js +6 -0
  53. package/build/assets/{conversation-tab-empty-state-FIbh_lc8.js → conversation-tab-empty-state-B3dpJXX0.js} +1 -1
  54. package/build/assets/copy-to-clipboard-button-B1ljgNxO.js +1 -0
  55. package/build/assets/device-verify-D5QRIS_x.js +1 -0
  56. package/build/assets/{dropdown-classes-Bc1djN0-.js → dropdown-classes-BGvOvW2_.js} +1 -1
  57. package/build/assets/edit-automation-modal-D_JWSmxT.js +1 -0
  58. package/build/assets/empty-state-FK_s1B60.js +1 -0
  59. package/build/assets/{entry.client-CqyPPjOq.js → entry.client-BMafTpjO.js} +2 -2
  60. package/build/assets/enum-filter-dropdown-UNaom12H.js +1 -0
  61. package/build/assets/environment-switch-overlay-COibRUA-.js +1 -0
  62. package/build/assets/error-state-Cf8LRuuY.js +1 -0
  63. package/build/assets/extensions-hub-C_6ahIua.js +1 -0
  64. package/build/assets/extensions-navigation-C5GfpzFe.js +1 -0
  65. package/build/assets/external-link-Bd7Tga-1.js +1 -0
  66. package/build/assets/files-tab-D5PPIWI1.js +1 -0
  67. package/build/assets/{form-control-classes-Bkh5FGrD.js → form-control-classes-Dbq-7YP_.js} +1 -1
  68. package/build/assets/format-model-name-Dfh9Udrx.js +1 -0
  69. package/build/assets/get-git-path-jU2zjqIB.js +1 -0
  70. package/build/assets/git-repo-dropdown-BoDDWXfX.js +1 -0
  71. package/build/assets/git-repo-dropdown-uxlFw2gn.js +1 -0
  72. package/build/assets/highlighted-source-view-C7pAXrT0.js +1 -0
  73. package/build/assets/home-BM5_Wz_R.js +1 -0
  74. package/build/assets/home-Ivfm7KC4.js +1 -0
  75. package/build/assets/home-automation-run-tooltip-B1N2uO9p.js +1 -0
  76. package/build/assets/home-store-DCbei3DX.js +1 -0
  77. package/build/assets/hooks-service-Dnmhqc0Z.js +1 -0
  78. package/build/assets/index-home-td9BN2T3.js +1 -0
  79. package/build/assets/info-BcajzHn1.js +1 -0
  80. package/build/assets/install-server-modal-B81I-5OE.js +1 -0
  81. package/build/assets/kebab-menu-item-content-SCJBwZnp.js +1 -0
  82. package/build/assets/{key-BmVyxs-2.js → key-O84CMFHb.js} +1 -1
  83. package/build/assets/launch-ZLxI4opd.js +1 -0
  84. package/build/assets/list-filter-B8PQk3RA.js +1 -0
  85. package/build/assets/{list-todo-apgLVjMw.js → list-todo-Caa8E1X_.js} +1 -1
  86. package/build/assets/llm-not-configured-banner-Dh_ajcM8.js +27 -0
  87. package/build/assets/llm-settings-CODhjQzy.js +1 -0
  88. package/build/assets/llm-settings-CZaXYgtw.js +1 -0
  89. package/build/assets/llm-subscription-service-CgIDc38n.js +1 -0
  90. package/build/assets/loader-circle-BxJgk73D.js +1 -0
  91. package/build/assets/{loading-spinner-BY9N3pOe.js → loading-spinner-BeLV0IXf.js} +1 -1
  92. package/build/assets/manage-backends-modal-cMXqCb-B.js +1 -0
  93. package/build/assets/manifest-bfeccb98.js +1 -0
  94. package/build/assets/manifest-subpage-layout-CVZgVKoY.js +1 -0
  95. package/build/assets/{map-provider-Cu3Zgumb.js → map-provider-iRs80q_6.js} +1 -1
  96. package/build/assets/markdown-renderer-DyFl9-mL.js +8 -0
  97. package/build/assets/mcp-CraxoXQv.js +1 -0
  98. package/build/assets/{mcp-marketplace-utils-AIBzzHTO.js → mcp-marketplace-utils-C7PYr293.js} +1 -1
  99. package/build/assets/mcp-page-CteH_K0N.js +9 -0
  100. package/build/assets/messages-Bk1xhbU2.js +41 -0
  101. package/build/assets/{modal-body-BxZjsju9.js → modal-body-C24WsdFb.js} +1 -1
  102. package/build/assets/{modal-classes-C8eycCwG.js → modal-classes-B0b9eiL8.js} +1 -1
  103. package/build/assets/modal-close-button-DfqfB2Nj.js +1 -0
  104. package/build/assets/{mouse-pointer-click-Co2uyaPA.js → mouse-pointer-click-BXlRN92t.js} +1 -1
  105. package/build/assets/onboarding-DXFBRqEy.js +1 -0
  106. package/build/assets/onboarding-modal-BT3Gx_sZ.js +1 -0
  107. package/build/assets/organization-service.api-B5CvmnYQ.js +1 -0
  108. package/build/assets/pencil-q-ihqDYv.js +1 -0
  109. package/build/assets/pin-BdroVQdN.js +1 -0
  110. package/build/assets/planner-tab-CstoOlAB.js +1 -0
  111. package/build/assets/plug-7ACOEbMs.js +1 -0
  112. package/build/assets/plugins-management-service-5rqVPEGN.js +1 -0
  113. package/build/assets/plus-C2e21TFC.js +1 -0
  114. package/build/assets/profiles-service.api-D1XKMgr0.js +1 -0
  115. package/build/assets/providers-XmZ9HM4Q.js +1 -0
  116. package/build/assets/proxy-XP6U1Dhv.js +1 -0
  117. package/build/assets/{puzzle-JM_QaRm0.js → puzzle-LJYnuxKe.js} +1 -1
  118. package/build/assets/react-BX7IV650.js +1 -0
  119. package/build/assets/recommended-automations-launcher-DEHRKIAg.js +1 -0
  120. package/build/assets/refresh-cw-BtdC3T8P.js +1 -0
  121. package/build/assets/root-CM6IZHlg.css +1 -0
  122. package/build/assets/root-DdFkodKW.js +2 -0
  123. package/build/assets/root-layout-DUquNZTU.js +2 -0
  124. package/build/assets/schema-field-Y3F8JvXd.js +1 -0
  125. package/build/assets/scroll-fade-state-Dt_fx2kf.js +1 -0
  126. package/build/assets/sdk-section-page-CNZTLwH9.js +1 -0
  127. package/build/assets/secret-form-9-BoGA40.js +1 -0
  128. package/build/assets/secrets-service-BOIsfD9j.js +1 -0
  129. package/build/assets/secrets-settings-CBJgFr42.js +1 -0
  130. package/build/assets/settings-D4hdToD4.js +1 -0
  131. package/build/assets/settings-dropdown-input-DBvsZ7-Q.js +1 -0
  132. package/build/assets/settings-index-DeQphyBK.js +1 -0
  133. package/build/assets/settings-input-dVuzapBA.js +1 -0
  134. package/build/assets/{settings-list-classes-BzeSZbF2.js → settings-list-classes-DhAPuXm6.js} +1 -1
  135. package/build/assets/settings-modal-tHiJ8iYV.js +1 -0
  136. package/build/assets/settings-nav-GAQjW1a-.js +16 -0
  137. package/build/assets/settings-service.api-C1vZH9Vh.js +1 -0
  138. package/build/assets/settings-switch-DDd1cQ8t.js +1 -0
  139. package/build/assets/{settings-utils-UYpEdPuD.js → settings-utils-BTaaRhLZ.js} +1 -1
  140. package/build/assets/shared-conversation-Cyg7m7ns.js +1 -0
  141. package/build/assets/shield-check-C3Rl0NF8.js +1 -0
  142. package/build/assets/{sidebar-layout-D6fS8-Gl.js → sidebar-layout-DH0E-5KW.js} +1 -1
  143. package/build/assets/sidebar-mobile-menu-toggle-CQ4iky__.js +1 -0
  144. package/build/assets/{sidebar-nav-link-DQQcMf1A.js → sidebar-nav-link-oLQiKUBu.js} +1 -1
  145. package/build/assets/{sidebar-onboarding-checklist-storage-BBkeI6Bp.js → sidebar-onboarding-checklist-storage-TfvNNnnr.js} +1 -1
  146. package/build/assets/sidebar-store-DAZVH-DR.js +1 -0
  147. package/build/assets/skill-card-pill-row-DfjIfj0K.js +1 -0
  148. package/build/assets/{skill-filter-w__3UCEE.js → skill-filter-DsNLmn76.js} +2 -2
  149. package/build/assets/{skill-icon-badge-RQkq8wvl.js → skill-icon-badge-0MK_68Nc.js} +1 -1
  150. package/build/assets/skill-scope-BE-H9TSZ.js +1 -0
  151. package/build/assets/skills-plugins-vzSdxSk_.js +1 -0
  152. package/build/assets/skills-settings-BiPOH9H9.js +1 -0
  153. package/build/assets/styled-tooltip-CejG0rqv.js +1 -0
  154. package/build/assets/task-list-tab-OkZSqnTp.js +1 -0
  155. package/build/assets/{terminal-CNElN42a.js → terminal-Dph60VFZ.js} +2 -2
  156. package/build/assets/toggle-switch-B2uXaAUS.js +1 -0
  157. package/build/assets/trash-2-Bb40zQzs.js +1 -0
  158. package/build/assets/trash-Ckh7yCaB.js +1 -0
  159. package/build/assets/triangle-alert-DEdu-b_L.js +1 -0
  160. package/build/assets/{typography-v1KN0tzi.js → typography-DgcLGdHk.js} +1 -1
  161. package/build/assets/usage-tab-MCmNRAnR.js +1 -0
  162. package/build/assets/use-acp-credential-form-ychoGqjC.js +1 -0
  163. package/build/assets/use-activate-agent-profile-8L8Xdghy.js +1 -0
  164. package/build/assets/use-agent-profiles-Bi8hSkze.js +1 -0
  165. package/build/assets/{use-automation-health-E6NZi9rb.js → use-automation-health-U99vvHxx.js} +1 -1
  166. package/build/assets/use-automation-permissions-Buus0R6h.js +1 -0
  167. package/build/assets/{use-automations-xijQKIl9.js → use-automations-Bq5hVuv0.js} +1 -1
  168. package/build/assets/{use-can-manage-org-profiles-CrJP5262.js → use-can-manage-org-profiles-MzIeEV8F.js} +1 -1
  169. package/build/assets/use-canvas-extensions-Ca9KoVEm.js +1 -0
  170. package/build/assets/{use-cloud-current-user-id-CDfAHpPX.js → use-cloud-current-user-id-B4ZLUZSa.js} +1 -1
  171. package/build/assets/use-config-l5tkDHyD.js +1 -0
  172. package/build/assets/use-create-conversation-i_PdFdIs.js +1 -0
  173. package/build/assets/use-create-secret-CjWq0J4O.js +1 -0
  174. package/build/assets/use-free-models-gCsJ5BV0.js +1 -0
  175. package/build/assets/{use-get-secrets-K3jmk-LH.js → use-get-secrets-CMTuWEp_.js} +1 -1
  176. package/build/assets/use-is-authed-A2Yinlt0.js +1 -0
  177. package/build/assets/{use-launch-skill-in-chat-BYjYihBP.js → use-launch-skill-in-chat-QbXDhiHr.js} +1 -1
  178. package/build/assets/use-llm-configured-Dl4zg8ht.js +1 -0
  179. package/build/assets/use-llm-profiles-SWsuFmFu.js +1 -0
  180. package/build/assets/use-manifest-capabilities-CdqYfUAC.js +1 -0
  181. package/build/assets/use-onboarding-completion-Xl63ZvzQ.js +1 -0
  182. package/build/assets/use-pinned-home-route-BXDIUaxQ.js +1 -0
  183. package/build/assets/use-plugins-marketplace-BIIaPiaB.js +1 -0
  184. package/build/assets/use-save-agent-profile-D-ZHHE94.js +1 -0
  185. package/build/assets/{use-save-settings-DYqkKv7T.js → use-save-settings-Dapkf4cC.js} +1 -1
  186. package/build/assets/use-settings-C2KKQKVC.js +1 -0
  187. package/build/assets/use-settings-nav-items-TOc0Rsfd.js +1 -0
  188. package/build/assets/use-tracking-j4uo9VEW.js +3 -0
  189. package/build/assets/{use-user-conversation-B9Gebw_g.js → use-user-conversation-5UFqMoO4.js} +1 -1
  190. package/build/assets/{useInfiniteQuery-C926xzY4.js → useInfiniteQuery-CtSRG7uW.js} +1 -1
  191. package/build/assets/{useMutation-B-qc391N.js → useMutation-Cszf8mKy.js} +1 -1
  192. package/build/assets/useQueries-pUohFMSP.js +1 -0
  193. package/build/assets/useQuery-DAAacS7O.js +1 -0
  194. package/build/assets/useTranslation-CCgUjPJF.js +1 -0
  195. package/build/assets/utils-BgLSZdyy.js +1 -0
  196. package/build/assets/{vendor~conversation-panel~conversation-C8Fn4XOf.js → vendor~conversation-panel~conversation-C22sJuWZ.js} +1 -1
  197. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-Z0lly3FE.js +2 -0
  198. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-BXXGJNDU.js +185 -0
  199. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew9ih1s8-40UR63Gt.js +1 -0
  200. package/build/assets/{vendor~index-home~home~conversation-panel~conversation-hWywRBaR.js → vendor~index-home~home~conversation-panel~conversation-UTl7gUo9.js} +1 -1
  201. package/build/assets/vendor~root-layout-CcdIqs-C.js +1 -0
  202. package/build/assets/{vendor~root-layout~conversation-panel~conversation-BMbMgaGu.js → vendor~root-layout~conversation-panel~conversation-C3EBV3kp.js} +1 -1
  203. package/build/assets/vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-BCe0JJVy.js +1 -0
  204. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation-j5MFqfSy.js → vendor~root-layout~index-home~home~conversation-panel~conversation-BGGbPcYh.js} +1 -1
  205. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-CxhwKuAd.js +1 -0
  206. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~nj1hli3r-DP9wmsjo.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-CnsDDzeE.js} +1 -1
  207. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-CUmIwQCN.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-3eJ4ExtV.js} +12 -6
  208. package/build/assets/{verification-settings-gw_q6vkL.js → verification-settings-DdBpaVPz.js} +1 -1
  209. package/build/assets/{wrench-CUEI1krB.js → wrench-B8Wg_nbp.js} +1 -1
  210. package/build/assets/x-CX8lVGwm.js +1 -0
  211. package/build/index.html +4 -4
  212. package/build/locales/ar/openhands.json +79 -22
  213. package/build/locales/ca/openhands.json +79 -22
  214. package/build/locales/de/openhands.json +79 -22
  215. package/build/locales/en/openhands.json +79 -22
  216. package/build/locales/es/openhands.json +79 -22
  217. package/build/locales/fr/openhands.json +79 -22
  218. package/build/locales/it/openhands.json +79 -22
  219. package/build/locales/ja/openhands.json +79 -22
  220. package/build/locales/ko-KR/openhands.json +79 -22
  221. package/build/locales/no/openhands.json +79 -22
  222. package/build/locales/pt/openhands.json +79 -22
  223. package/build/locales/tr/openhands.json +79 -22
  224. package/build/locales/uk/openhands.json +79 -22
  225. package/build/locales/zh-CN/openhands.json +79 -22
  226. package/build/locales/zh-TW/openhands.json +79 -22
  227. package/config/defaults.json +3 -3
  228. package/dist/api/agent-server-adapter.cjs +3 -3
  229. package/dist/api/agent-server-adapter.cjs.map +1 -1
  230. package/dist/api/agent-server-adapter.d.ts +72 -12
  231. package/dist/api/agent-server-adapter.js +234 -132
  232. package/dist/api/agent-server-adapter.js.map +1 -1
  233. package/dist/api/agent-server-config.cjs +1 -1
  234. package/dist/api/agent-server-config.cjs.map +1 -1
  235. package/dist/api/agent-server-config.d.ts +6 -0
  236. package/dist/api/agent-server-config.js +6 -3
  237. package/dist/api/agent-server-config.js.map +1 -1
  238. package/dist/api/automation-service/automation-service.api.cjs +1 -1
  239. package/dist/api/automation-service/automation-service.api.cjs.map +1 -1
  240. package/dist/api/automation-service/automation-service.api.d.ts +2 -2
  241. package/dist/api/automation-service/automation-service.api.js +7 -7
  242. package/dist/api/automation-service/automation-service.api.js.map +1 -1
  243. package/dist/api/cloud/organization-service.api.cjs.map +1 -1
  244. package/dist/api/cloud/organization-service.api.d.ts +9 -1
  245. package/dist/api/cloud/organization-service.api.js.map +1 -1
  246. package/dist/api/cloud/provider-connections-service.api.cjs +2 -0
  247. package/dist/api/cloud/provider-connections-service.api.cjs.map +1 -0
  248. package/dist/api/cloud/provider-connections-service.api.d.ts +5 -0
  249. package/dist/api/cloud/provider-connections-service.api.js +50 -0
  250. package/dist/api/cloud/provider-connections-service.api.js.map +1 -0
  251. package/dist/api/cloud/skills-service.api.cjs +1 -1
  252. package/dist/api/cloud/skills-service.api.cjs.map +1 -1
  253. package/dist/api/cloud/skills-service.api.d.ts +10 -0
  254. package/dist/api/cloud/skills-service.api.js +11 -1
  255. package/dist/api/cloud/skills-service.api.js.map +1 -1
  256. package/dist/api/config-service/config-service.api.cjs +1 -1
  257. package/dist/api/config-service/config-service.api.cjs.map +1 -1
  258. package/dist/api/config-service/config-service.api.js +6 -2
  259. package/dist/api/config-service/config-service.api.js.map +1 -1
  260. package/dist/api/config-service/config-service.types.d.ts +13 -0
  261. package/dist/api/conversation-metadata-store.cjs +1 -1
  262. package/dist/api/conversation-metadata-store.cjs.map +1 -1
  263. package/dist/api/conversation-metadata-store.d.ts +24 -0
  264. package/dist/api/conversation-metadata-store.js +10 -2
  265. package/dist/api/conversation-metadata-store.js.map +1 -1
  266. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
  267. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
  268. package/dist/api/conversation-service/agent-server-conversation-service.api.d.ts +20 -0
  269. package/dist/api/conversation-service/agent-server-conversation-service.api.js +126 -77
  270. package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
  271. package/dist/api/hooks-service.cjs +2 -0
  272. package/dist/api/hooks-service.cjs.map +1 -0
  273. package/dist/api/hooks-service.d.ts +13 -0
  274. package/dist/api/hooks-service.js +20 -0
  275. package/dist/api/hooks-service.js.map +1 -0
  276. package/dist/api/provider-connections-service/provider-connections-service.api.cjs +1 -1
  277. package/dist/api/provider-connections-service/provider-connections-service.api.cjs.map +1 -1
  278. package/dist/api/provider-connections-service/provider-connections-service.api.js +25 -16
  279. package/dist/api/provider-connections-service/provider-connections-service.api.js.map +1 -1
  280. package/dist/api/settings-service/settings-service.api.cjs +1 -1
  281. package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
  282. package/dist/api/settings-service/settings-service.api.d.ts +2 -0
  283. package/dist/api/settings-service/settings-service.api.js +18 -10
  284. package/dist/api/settings-service/settings-service.api.js.map +1 -1
  285. package/dist/api/skills-service.cjs +1 -1
  286. package/dist/api/skills-service.cjs.map +1 -1
  287. package/dist/api/skills-service.d.ts +7 -0
  288. package/dist/api/skills-service.js +11 -8
  289. package/dist/api/skills-service.js.map +1 -1
  290. package/dist/components/conversation-events/chat/event-message-components/critic-result-display.cjs +1 -1
  291. package/dist/components/conversation-events/chat/event-message-components/critic-result-display.js +5 -5
  292. package/dist/components/conversation-events/chat/event-message-components/finish-event-message.cjs +1 -1
  293. package/dist/components/conversation-events/chat/event-message-components/finish-event-message.cjs.map +1 -1
  294. package/dist/components/conversation-events/chat/event-message-components/finish-event-message.js +2 -1
  295. package/dist/components/conversation-events/chat/event-message-components/finish-event-message.js.map +1 -1
  296. package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.cjs +1 -1
  297. package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.cjs.map +1 -1
  298. package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.d.ts +1 -1
  299. package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.js +28 -28
  300. package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.js.map +1 -1
  301. package/dist/components/conversation-events/chat/event-message-components/thought-event-message.cjs +1 -1
  302. package/dist/components/conversation-events/chat/event-message-components/thought-event-message.cjs.map +1 -1
  303. package/dist/components/conversation-events/chat/event-message-components/thought-event-message.js +2 -1
  304. package/dist/components/conversation-events/chat/event-message-components/thought-event-message.js.map +1 -1
  305. package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.cjs +1 -1
  306. package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.cjs.map +1 -1
  307. package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.d.ts +1 -1
  308. package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.js +37 -37
  309. package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.js.map +1 -1
  310. package/dist/components/conversation-events/chat/event-message.cjs +2 -2
  311. package/dist/components/conversation-events/chat/event-message.cjs.map +1 -1
  312. package/dist/components/conversation-events/chat/event-message.js +79 -70
  313. package/dist/components/conversation-events/chat/event-message.js.map +1 -1
  314. package/dist/components/conversation-events/chat/messages.cjs +1 -1
  315. package/dist/components/conversation-events/chat/messages.cjs.map +1 -1
  316. package/dist/components/conversation-events/chat/messages.js +28 -27
  317. package/dist/components/conversation-events/chat/messages.js.map +1 -1
  318. package/dist/components/features/automations/automation-card.cjs +1 -1
  319. package/dist/components/features/automations/automation-card.cjs.map +1 -1
  320. package/dist/components/features/automations/automation-card.js +104 -97
  321. package/dist/components/features/automations/automation-card.js.map +1 -1
  322. package/dist/components/features/automations/automation-list-row.cjs +1 -1
  323. package/dist/components/features/automations/automation-list-row.cjs.map +1 -1
  324. package/dist/components/features/automations/automation-list-row.js +89 -77
  325. package/dist/components/features/automations/automation-list-row.js.map +1 -1
  326. package/dist/components/features/automations/build-automation-menu-items.cjs +1 -1
  327. package/dist/components/features/automations/build-automation-menu-items.cjs.map +1 -1
  328. package/dist/components/features/automations/build-automation-menu-items.d.ts +3 -1
  329. package/dist/components/features/automations/build-automation-menu-items.js +12 -11
  330. package/dist/components/features/automations/build-automation-menu-items.js.map +1 -1
  331. package/dist/components/features/automations/detail/configuration-section.d.ts +7 -1
  332. package/dist/components/features/automations/detail/detail-header.d.ts +10 -5
  333. package/dist/components/features/automations/detail/run-status-badge.cjs +1 -1
  334. package/dist/components/features/automations/detail/run-status-badge.cjs.map +1 -1
  335. package/dist/components/features/automations/detail/run-status-badge.d.ts +2 -2
  336. package/dist/components/features/automations/detail/run-status-badge.js +82 -53
  337. package/dist/components/features/automations/detail/run-status-badge.js.map +1 -1
  338. package/dist/components/features/automations/kebab-menu.cjs +1 -1
  339. package/dist/components/features/automations/kebab-menu.cjs.map +1 -1
  340. package/dist/components/features/automations/kebab-menu.js +9 -5
  341. package/dist/components/features/automations/kebab-menu.js.map +1 -1
  342. package/dist/components/features/automations/recommended-automations-launcher.cjs +1 -1
  343. package/dist/components/features/automations/recommended-automations-launcher.cjs.map +1 -1
  344. package/dist/components/features/automations/recommended-automations-launcher.js +12 -12
  345. package/dist/components/features/automations/recommended-automations-launcher.js.map +1 -1
  346. package/dist/components/features/automations/recommended-automations-section.cjs +1 -1
  347. package/dist/components/features/automations/recommended-automations-section.js +9 -9
  348. package/dist/components/features/backends/backend-selector.cjs +1 -1
  349. package/dist/components/features/backends/backend-selector.cjs.map +1 -1
  350. package/dist/components/features/backends/backend-selector.js +123 -112
  351. package/dist/components/features/backends/backend-selector.js.map +1 -1
  352. package/dist/components/features/backends/manage-backends-modal.cjs +1 -1
  353. package/dist/components/features/backends/manage-backends-modal.cjs.map +1 -1
  354. package/dist/components/features/backends/manage-backends-modal.js +29 -29
  355. package/dist/components/features/backends/manage-backends-modal.js.map +1 -1
  356. package/dist/components/features/chat/change-agent-button.cjs +1 -1
  357. package/dist/components/features/chat/change-agent-button.js +4 -4
  358. package/dist/components/features/chat/chat-interface.cjs +2 -2
  359. package/dist/components/features/chat/chat-interface.cjs.map +1 -1
  360. package/dist/components/features/chat/chat-interface.js +137 -137
  361. package/dist/components/features/chat/chat-interface.js.map +1 -1
  362. package/dist/components/features/chat/chat-message.cjs +1 -1
  363. package/dist/components/features/chat/chat-message.cjs.map +1 -1
  364. package/dist/components/features/chat/chat-message.d.ts +2 -1
  365. package/dist/components/features/chat/chat-message.js +88 -79
  366. package/dist/components/features/chat/chat-message.js.map +1 -1
  367. package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs +1 -1
  368. package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs.map +1 -1
  369. package/dist/components/features/chat/components/chat-input-llm-profile-picker.js +62 -61
  370. package/dist/components/features/chat/components/chat-input-llm-profile-picker.js.map +1 -1
  371. package/dist/components/features/chat/components/context-window-meter.cjs +1 -1
  372. package/dist/components/features/chat/components/context-window-meter.js +4 -4
  373. package/dist/components/features/chat/confirmation-mode-enabled.cjs +1 -1
  374. package/dist/components/features/chat/confirmation-mode-enabled.js +4 -4
  375. package/dist/components/features/chat/generic-event-message.cjs +1 -1
  376. package/dist/components/features/chat/generic-event-message.cjs.map +1 -1
  377. package/dist/components/features/chat/generic-event-message.d.ts +2 -1
  378. package/dist/components/features/chat/generic-event-message.js +41 -22
  379. package/dist/components/features/chat/generic-event-message.js.map +1 -1
  380. package/dist/components/features/chat/interactive-chat-box.cjs +1 -1
  381. package/dist/components/features/chat/interactive-chat-box.cjs.map +1 -1
  382. package/dist/components/features/chat/interactive-chat-box.js +20 -19
  383. package/dist/components/features/chat/interactive-chat-box.js.map +1 -1
  384. package/dist/components/features/chat/model-messages.cjs +1 -1
  385. package/dist/components/features/chat/model-messages.cjs.map +1 -1
  386. package/dist/components/features/chat/model-messages.js +27 -26
  387. package/dist/components/features/chat/model-messages.js.map +1 -1
  388. package/dist/components/features/conversation/conversation-overview-git-section.cjs +1 -1
  389. package/dist/components/features/conversation/conversation-overview-git-section.js +4 -4
  390. package/dist/components/features/conversation/conversation-overview-skills-panel.cjs +1 -1
  391. package/dist/components/features/conversation/conversation-overview-skills-panel.js +4 -4
  392. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs +1 -1
  393. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs.map +1 -1
  394. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js +77 -78
  395. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js.map +1 -1
  396. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs +1 -1
  397. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs.map +1 -1
  398. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js +88 -88
  399. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js.map +1 -1
  400. package/dist/components/features/conversation-panel/advanced-conversation-options-modal.cjs +2 -0
  401. package/dist/components/features/conversation-panel/advanced-conversation-options-modal.cjs.map +1 -0
  402. package/dist/components/features/conversation-panel/advanced-conversation-options-modal.d.ts +21 -0
  403. package/dist/components/features/conversation-panel/advanced-conversation-options-modal.js +239 -0
  404. package/dist/components/features/conversation-panel/advanced-conversation-options-modal.js.map +1 -0
  405. package/dist/components/features/conversation-panel/budget-display.cjs +1 -1
  406. package/dist/components/features/conversation-panel/budget-display.cjs.map +1 -1
  407. package/dist/components/features/conversation-panel/budget-display.d.ts +1 -2
  408. package/dist/components/features/conversation-panel/budget-display.js +12 -19
  409. package/dist/components/features/conversation-panel/budget-display.js.map +1 -1
  410. package/dist/components/features/conversation-panel/conversation-active-tag-filters.cjs +2 -0
  411. package/dist/components/features/conversation-panel/conversation-active-tag-filters.cjs.map +1 -0
  412. package/dist/components/features/conversation-panel/conversation-active-tag-filters.d.ts +28 -0
  413. package/dist/components/features/conversation-panel/conversation-active-tag-filters.js +69 -0
  414. package/dist/components/features/conversation-panel/conversation-active-tag-filters.js.map +1 -0
  415. package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.cjs +1 -1
  416. package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.cjs.map +1 -1
  417. package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.d.ts +2 -1
  418. package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.js +19 -18
  419. package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.js.map +1 -1
  420. package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.cjs +1 -1
  421. package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.cjs.map +1 -1
  422. package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.d.ts +2 -1
  423. package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.js +91 -80
  424. package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.js.map +1 -1
  425. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs +1 -1
  426. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs.map +1 -1
  427. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js +45 -44
  428. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js.map +1 -1
  429. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs +1 -1
  430. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs.map +1 -1
  431. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js +1 -1
  432. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js.map +1 -1
  433. package/dist/components/features/conversation-panel/conversation-card/conversation-card.cjs +1 -1
  434. package/dist/components/features/conversation-panel/conversation-card/conversation-card.cjs.map +1 -1
  435. package/dist/components/features/conversation-panel/conversation-card/conversation-card.d.ts +7 -1
  436. package/dist/components/features/conversation-panel/conversation-card/conversation-card.js +87 -81
  437. package/dist/components/features/conversation-panel/conversation-card/conversation-card.js.map +1 -1
  438. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs +1 -1
  439. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs.map +1 -1
  440. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.d.ts +2 -1
  441. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js +1 -1
  442. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js.map +1 -1
  443. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs +1 -1
  444. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs.map +1 -1
  445. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.d.ts +2 -1
  446. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js +2 -1
  447. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js.map +1 -1
  448. package/dist/components/features/conversation-panel/conversation-layouts-menu.cjs +2 -0
  449. package/dist/components/features/conversation-panel/conversation-layouts-menu.cjs.map +1 -0
  450. package/dist/components/features/conversation-panel/conversation-layouts-menu.d.ts +29 -0
  451. package/dist/components/features/conversation-panel/conversation-layouts-menu.js +177 -0
  452. package/dist/components/features/conversation-panel/conversation-layouts-menu.js.map +1 -0
  453. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs +1 -1
  454. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs.map +1 -1
  455. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.d.ts +37 -0
  456. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js +85 -45
  457. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js.map +1 -1
  458. package/dist/components/features/conversation-panel/conversation-panel.cjs +1 -1
  459. package/dist/components/features/conversation-panel/conversation-panel.cjs.map +1 -1
  460. package/dist/components/features/conversation-panel/conversation-panel.js +296 -290
  461. package/dist/components/features/conversation-panel/conversation-panel.js.map +1 -1
  462. package/dist/components/features/conversation-panel/edit-conversation-tags-modal.cjs +2 -0
  463. package/dist/components/features/conversation-panel/edit-conversation-tags-modal.cjs.map +1 -0
  464. package/dist/components/features/conversation-panel/edit-conversation-tags-modal.d.ts +22 -0
  465. package/dist/components/features/conversation-panel/edit-conversation-tags-modal.js +153 -0
  466. package/dist/components/features/conversation-panel/edit-conversation-tags-modal.js.map +1 -0
  467. package/dist/components/features/conversation-panel/hide-older-conversations-row.cjs +2 -0
  468. package/dist/components/features/conversation-panel/hide-older-conversations-row.cjs.map +1 -0
  469. package/dist/components/features/conversation-panel/hide-older-conversations-row.d.ts +6 -0
  470. package/dist/components/features/conversation-panel/hide-older-conversations-row.js +65 -0
  471. package/dist/components/features/conversation-panel/hide-older-conversations-row.js.map +1 -0
  472. package/dist/components/features/conversation-panel/menu-row.cjs +1 -1
  473. package/dist/components/features/conversation-panel/menu-row.cjs.map +1 -1
  474. package/dist/components/features/conversation-panel/menu-row.d.ts +11 -1
  475. package/dist/components/features/conversation-panel/menu-row.js +27 -16
  476. package/dist/components/features/conversation-panel/menu-row.js.map +1 -1
  477. package/dist/components/features/home/featured-automations/automation-health-indicator.cjs +1 -1
  478. package/dist/components/features/home/featured-automations/automation-health-indicator.cjs.map +1 -1
  479. package/dist/components/features/home/featured-automations/automation-health-indicator.js +1 -1
  480. package/dist/components/features/home/featured-automations/automation-health-indicator.js.map +1 -1
  481. package/dist/components/features/home/featured-automations/automation-run-activity-metrics.cjs +1 -1
  482. package/dist/components/features/home/featured-automations/automation-run-activity-metrics.cjs.map +1 -1
  483. package/dist/components/features/home/featured-automations/automation-run-activity-metrics.d.ts +4 -3
  484. package/dist/components/features/home/featured-automations/automation-run-activity-metrics.js +22 -25
  485. package/dist/components/features/home/featured-automations/automation-run-activity-metrics.js.map +1 -1
  486. package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.cjs +1 -1
  487. package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.cjs.map +1 -1
  488. package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.d.ts +1 -1
  489. package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.js +15 -15
  490. package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.js.map +1 -1
  491. package/dist/components/features/home/featured-automations/automation-run-health.cjs +1 -1
  492. package/dist/components/features/home/featured-automations/automation-run-health.cjs.map +1 -1
  493. package/dist/components/features/home/featured-automations/automation-run-health.d.ts +5 -3
  494. package/dist/components/features/home/featured-automations/automation-run-health.js +30 -23
  495. package/dist/components/features/home/featured-automations/automation-run-health.js.map +1 -1
  496. package/dist/components/features/home/featured-automations/build-home-automation-menu-items.d.ts +1 -2
  497. package/dist/components/features/home/featured-automations/build-pinned-automation-menu-items.d.ts +0 -1
  498. package/dist/components/features/home/featured-automations/home-automation-activity.d.ts +3 -2
  499. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs +1 -1
  500. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs.map +1 -1
  501. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.d.ts +1 -1
  502. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js +42 -42
  503. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js.map +1 -1
  504. package/dist/components/features/images/image-lightbox.cjs +2 -0
  505. package/dist/components/features/images/image-lightbox.cjs.map +1 -0
  506. package/dist/components/features/images/image-lightbox.d.ts +11 -0
  507. package/dist/components/features/images/image-lightbox.js +37 -0
  508. package/dist/components/features/images/image-lightbox.js.map +1 -0
  509. package/dist/components/features/images/image-preview.cjs +1 -1
  510. package/dist/components/features/images/image-preview.cjs.map +1 -1
  511. package/dist/components/features/images/image-preview.d.ts +2 -1
  512. package/dist/components/features/images/image-preview.js +33 -13
  513. package/dist/components/features/images/image-preview.js.map +1 -1
  514. package/dist/components/features/manifest/manifest-form-field.d.ts +3 -1
  515. package/dist/components/features/manifest/manifest-review-step.d.ts +3 -1
  516. package/dist/components/features/onboarding/steps/setup-llm-step.d.ts +3 -4
  517. package/dist/components/features/settings/cloud-settings-link.cjs +1 -1
  518. package/dist/components/features/settings/cloud-settings-link.cjs.map +1 -1
  519. package/dist/components/features/settings/cloud-settings-link.d.ts +3 -1
  520. package/dist/components/features/settings/cloud-settings-link.js +22 -19
  521. package/dist/components/features/settings/cloud-settings-link.js.map +1 -1
  522. package/dist/components/features/settings/integrations-settings-link.cjs +1 -1
  523. package/dist/components/features/settings/integrations-settings-link.cjs.map +1 -1
  524. package/dist/components/features/settings/integrations-settings-link.d.ts +3 -1
  525. package/dist/components/features/settings/integrations-settings-link.js +20 -17
  526. package/dist/components/features/settings/integrations-settings-link.js.map +1 -1
  527. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.cjs +1 -1
  528. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.js +3 -2
  529. package/dist/components/features/settings/llm-profiles/profile-row.cjs +1 -1
  530. package/dist/components/features/settings/llm-profiles/profile-row.js +1 -1
  531. package/dist/components/features/settings/llm-profiles/profiles-body.d.ts +2 -2
  532. package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs +1 -1
  533. package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs.map +1 -1
  534. package/dist/components/features/settings/sdk-settings/sdk-section-page.d.ts +8 -7
  535. package/dist/components/features/settings/sdk-settings/sdk-section-page.js +172 -142
  536. package/dist/components/features/settings/sdk-settings/sdk-section-page.js.map +1 -1
  537. package/dist/components/features/settings/secrets-settings/secret-form.cjs +1 -1
  538. package/dist/components/features/settings/secrets-settings/secret-form.cjs.map +1 -1
  539. package/dist/components/features/settings/secrets-settings/secret-form.js +38 -25
  540. package/dist/components/features/settings/secrets-settings/secret-form.js.map +1 -1
  541. package/dist/components/features/settings/settings-dropdown-input.cjs +1 -1
  542. package/dist/components/features/settings/settings-dropdown-input.js +6 -6
  543. package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
  544. package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
  545. package/dist/components/features/sidebar/sidebar-rail-body.d.ts +4 -1
  546. package/dist/components/features/sidebar/sidebar-rail-body.js +157 -139
  547. package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
  548. package/dist/components/features/sidebar/sidebar.cjs +1 -1
  549. package/dist/components/features/sidebar/sidebar.cjs.map +1 -1
  550. package/dist/components/features/sidebar/sidebar.js +28 -26
  551. package/dist/components/features/sidebar/sidebar.js.map +1 -1
  552. package/dist/components/features/sidebar/use-sidebar-onboarding-checklist.cjs +1 -1
  553. package/dist/components/features/sidebar/use-sidebar-onboarding-checklist.js +3 -3
  554. package/dist/components/features/skills/extensions-navigation.cjs +1 -1
  555. package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
  556. package/dist/components/features/skills/extensions-navigation.js +3 -3
  557. package/dist/components/features/skills/extensions-navigation.js.map +1 -1
  558. package/dist/components/providers/agent-server-ui-providers.cjs +1 -1
  559. package/dist/components/providers/agent-server-ui-providers.cjs.map +1 -1
  560. package/dist/components/providers/agent-server-ui-providers.js +33 -29
  561. package/dist/components/providers/agent-server-ui-providers.js.map +1 -1
  562. package/dist/components/shared/buttons/remove-button.cjs +1 -1
  563. package/dist/components/shared/buttons/remove-button.cjs.map +1 -1
  564. package/dist/components/shared/buttons/remove-button.d.ts +2 -1
  565. package/dist/components/shared/buttons/remove-button.js +2 -1
  566. package/dist/components/shared/buttons/remove-button.js.map +1 -1
  567. package/dist/components/shared/buttons/styled-tooltip.cjs +1 -1
  568. package/dist/components/shared/buttons/styled-tooltip.cjs.map +1 -1
  569. package/dist/components/shared/buttons/styled-tooltip.d.ts +2 -1
  570. package/dist/components/shared/buttons/styled-tooltip.js +2 -1
  571. package/dist/components/shared/buttons/styled-tooltip.js.map +1 -1
  572. package/dist/components/shared/filters/enum-filter-dropdown.cjs +1 -1
  573. package/dist/components/shared/filters/enum-filter-dropdown.cjs.map +1 -1
  574. package/dist/components/shared/filters/enum-filter-dropdown.d.ts +5 -1
  575. package/dist/components/shared/filters/enum-filter-dropdown.js +14 -14
  576. package/dist/components/shared/filters/enum-filter-dropdown.js.map +1 -1
  577. package/dist/components/shared/free-models-note.cjs +2 -0
  578. package/dist/components/shared/free-models-note.cjs.map +1 -0
  579. package/dist/components/shared/free-models-note.d.ts +3 -0
  580. package/dist/components/shared/free-models-note.js +20 -0
  581. package/dist/components/shared/free-models-note.js.map +1 -0
  582. package/dist/components/shared/modals/confirmation-modal.cjs +1 -1
  583. package/dist/components/shared/modals/confirmation-modal.cjs.map +1 -1
  584. package/dist/components/shared/modals/confirmation-modal.d.ts +2 -1
  585. package/dist/components/shared/modals/confirmation-modal.js +8 -8
  586. package/dist/components/shared/modals/confirmation-modal.js.map +1 -1
  587. package/dist/components/shared/modals/settings/model-selector.cjs +1 -1
  588. package/dist/components/shared/modals/settings/model-selector.cjs.map +1 -1
  589. package/dist/components/shared/modals/settings/model-selector.js +102 -112
  590. package/dist/components/shared/modals/settings/model-selector.js.map +1 -1
  591. package/dist/config/defaults.cjs +1 -1
  592. package/dist/config/defaults.cjs.map +1 -1
  593. package/dist/config/defaults.js +3 -3
  594. package/dist/config/defaults.js.map +1 -1
  595. package/dist/constants/acp-providers.cjs.map +1 -1
  596. package/dist/constants/acp-providers.d.ts +12 -0
  597. package/dist/constants/acp-providers.js.map +1 -1
  598. package/dist/constants/settings-nav.d.ts +8 -0
  599. package/dist/contexts/conversation-websocket-context.cjs +3 -3
  600. package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
  601. package/dist/contexts/conversation-websocket-context.d.ts +5 -0
  602. package/dist/contexts/conversation-websocket-context.js +194 -198
  603. package/dist/contexts/conversation-websocket-context.js.map +1 -1
  604. package/dist/contexts/websocket-provider-wrapper.cjs +1 -1
  605. package/dist/contexts/websocket-provider-wrapper.cjs.map +1 -1
  606. package/dist/contexts/websocket-provider-wrapper.js +31 -15
  607. package/dist/contexts/websocket-provider-wrapper.js.map +1 -1
  608. package/dist/hooks/chat/record-model-switch-message.cjs +1 -1
  609. package/dist/hooks/chat/record-model-switch-message.cjs.map +1 -1
  610. package/dist/hooks/chat/record-model-switch-message.d.ts +31 -0
  611. package/dist/hooks/chat/record-model-switch-message.js +25 -12
  612. package/dist/hooks/chat/record-model-switch-message.js.map +1 -1
  613. package/dist/hooks/chat/use-plan-mode-interceptor.cjs +2 -0
  614. package/dist/hooks/chat/use-plan-mode-interceptor.cjs.map +1 -0
  615. package/dist/hooks/chat/use-plan-mode-interceptor.d.ts +16 -0
  616. package/dist/hooks/chat/use-plan-mode-interceptor.js +43 -0
  617. package/dist/hooks/chat/use-plan-mode-interceptor.js.map +1 -0
  618. package/dist/hooks/chat/use-slash-command.cjs +1 -1
  619. package/dist/hooks/chat/use-slash-command.cjs.map +1 -1
  620. package/dist/hooks/chat/use-slash-command.js +63 -62
  621. package/dist/hooks/chat/use-slash-command.js.map +1 -1
  622. package/dist/hooks/mutation/use-create-conversation.cjs +1 -1
  623. package/dist/hooks/mutation/use-create-conversation.cjs.map +1 -1
  624. package/dist/hooks/mutation/use-create-conversation.js +5 -1
  625. package/dist/hooks/mutation/use-create-conversation.js.map +1 -1
  626. package/dist/hooks/mutation/use-read-conversation-file.cjs +1 -1
  627. package/dist/hooks/mutation/use-read-conversation-file.cjs.map +1 -1
  628. package/dist/hooks/mutation/use-read-conversation-file.js +11 -4
  629. package/dist/hooks/mutation/use-read-conversation-file.js.map +1 -1
  630. package/dist/hooks/mutation/use-save-settings.cjs +1 -1
  631. package/dist/hooks/mutation/use-save-settings.js +3 -3
  632. package/dist/hooks/mutation/use-switch-llm-profile.cjs +1 -1
  633. package/dist/hooks/mutation/use-switch-llm-profile.cjs.map +1 -1
  634. package/dist/hooks/mutation/use-switch-llm-profile.js +13 -25
  635. package/dist/hooks/mutation/use-switch-llm-profile.js.map +1 -1
  636. package/dist/hooks/mutation/use-update-conversation-tags.cjs +2 -0
  637. package/dist/hooks/mutation/use-update-conversation-tags.cjs.map +1 -0
  638. package/dist/hooks/mutation/use-update-conversation-tags.d.ts +8 -0
  639. package/dist/hooks/mutation/use-update-conversation-tags.js +45 -0
  640. package/dist/hooks/mutation/use-update-conversation-tags.js.map +1 -0
  641. package/dist/hooks/query/query-keys.cjs +1 -1
  642. package/dist/hooks/query/query-keys.cjs.map +1 -1
  643. package/dist/hooks/query/query-keys.d.ts +6 -0
  644. package/dist/hooks/query/query-keys.js +2 -2
  645. package/dist/hooks/query/query-keys.js.map +1 -1
  646. package/dist/hooks/query/use-automation-sdk-version.cjs +1 -1
  647. package/dist/hooks/query/use-automation-sdk-version.cjs.map +1 -1
  648. package/dist/hooks/query/use-automation-sdk-version.d.ts +0 -1
  649. package/dist/hooks/query/use-automation-sdk-version.js +30 -55
  650. package/dist/hooks/query/use-automation-sdk-version.js.map +1 -1
  651. package/dist/hooks/query/use-conversation-skills.cjs +1 -1
  652. package/dist/hooks/query/use-conversation-skills.cjs.map +1 -1
  653. package/dist/hooks/query/use-conversation-skills.d.ts +14 -5
  654. package/dist/hooks/query/use-conversation-skills.js +20 -4
  655. package/dist/hooks/query/use-conversation-skills.js.map +1 -1
  656. package/dist/hooks/query/use-free-models.cjs +2 -0
  657. package/dist/hooks/query/use-free-models.cjs.map +1 -0
  658. package/dist/hooks/query/use-free-models.d.ts +23 -0
  659. package/dist/hooks/query/use-free-models.js +67 -0
  660. package/dist/hooks/query/use-free-models.js.map +1 -0
  661. package/dist/hooks/query/use-local-git-info.cjs.map +1 -1
  662. package/dist/hooks/query/use-local-git-info.js.map +1 -1
  663. package/dist/hooks/query/use-provider-connections.cjs +1 -1
  664. package/dist/hooks/query/use-provider-connections.cjs.map +1 -1
  665. package/dist/hooks/query/use-provider-connections.d.ts +6 -3
  666. package/dist/hooks/query/use-provider-connections.js +7 -3
  667. package/dist/hooks/query/use-provider-connections.js.map +1 -1
  668. package/dist/hooks/query/use-provider-models.cjs +1 -1
  669. package/dist/hooks/query/use-provider-models.cjs.map +1 -1
  670. package/dist/hooks/query/use-provider-models.js +34 -25
  671. package/dist/hooks/query/use-provider-models.js.map +1 -1
  672. package/dist/hooks/query/use-search-providers.cjs +1 -1
  673. package/dist/hooks/query/use-search-providers.cjs.map +1 -1
  674. package/dist/hooks/query/use-search-providers.js +31 -19
  675. package/dist/hooks/query/use-search-providers.js.map +1 -1
  676. package/dist/hooks/query/use-sub-conversations.cjs +1 -1
  677. package/dist/hooks/query/use-sub-conversations.cjs.map +1 -1
  678. package/dist/hooks/query/use-sub-conversations.js +16 -16
  679. package/dist/hooks/query/use-sub-conversations.js.map +1 -1
  680. package/dist/hooks/use-acp-model-context.cjs +1 -1
  681. package/dist/hooks/use-acp-model-context.js +3 -3
  682. package/dist/hooks/use-agent-state.cjs +1 -1
  683. package/dist/hooks/use-agent-state.cjs.map +1 -1
  684. package/dist/hooks/use-agent-state.d.ts +17 -1
  685. package/dist/hooks/use-agent-state.js +19 -9
  686. package/dist/hooks/use-agent-state.js.map +1 -1
  687. package/dist/hooks/use-automation-permissions.cjs +2 -0
  688. package/dist/hooks/use-automation-permissions.cjs.map +1 -0
  689. package/dist/hooks/use-automation-permissions.d.ts +43 -0
  690. package/dist/hooks/use-automation-permissions.js +52 -0
  691. package/dist/hooks/use-automation-permissions.js.map +1 -0
  692. package/dist/hooks/use-chat-input-model-state.cjs +1 -1
  693. package/dist/hooks/use-chat-input-model-state.js +3 -3
  694. package/dist/hooks/use-handle-plan-click.cjs +1 -1
  695. package/dist/hooks/use-handle-plan-click.cjs.map +1 -1
  696. package/dist/hooks/use-handle-plan-click.d.ts +3 -1
  697. package/dist/hooks/use-handle-plan-click.js +85 -26
  698. package/dist/hooks/use-handle-plan-click.js.map +1 -1
  699. package/dist/hooks/use-home-automation-actions.cjs +1 -1
  700. package/dist/hooks/use-home-automation-actions.cjs.map +1 -1
  701. package/dist/hooks/use-home-automation-actions.d.ts +1 -2
  702. package/dist/hooks/use-home-automation-actions.js +1 -1
  703. package/dist/hooks/use-home-automation-actions.js.map +1 -1
  704. package/dist/hooks/use-llm-configured.cjs +1 -1
  705. package/dist/hooks/use-llm-configured.js +3 -3
  706. package/dist/hooks/use-manifest-preflight.d.ts +1 -1
  707. package/dist/hooks/use-unified-websocket-status.cjs +1 -1
  708. package/dist/hooks/use-unified-websocket-status.cjs.map +1 -1
  709. package/dist/hooks/use-unified-websocket-status.d.ts +7 -0
  710. package/dist/hooks/use-unified-websocket-status.js +5 -1
  711. package/dist/hooks/use-unified-websocket-status.js.map +1 -1
  712. package/dist/i18n/declaration.cjs +1 -1
  713. package/dist/i18n/declaration.cjs.map +1 -1
  714. package/dist/i18n/declaration.d.ts +71 -14
  715. package/dist/i18n/declaration.js +1 -1
  716. package/dist/i18n/declaration.js.map +1 -1
  717. package/dist/i18n/translation.cjs +2 -2
  718. package/dist/i18n/translation.cjs.map +1 -1
  719. package/dist/i18n/translation.js +1281 -312
  720. package/dist/i18n/translation.js.map +1 -1
  721. package/dist/locales/ar/openhands.json +79 -22
  722. package/dist/locales/ca/openhands.json +79 -22
  723. package/dist/locales/de/openhands.json +79 -22
  724. package/dist/locales/en/openhands.json +79 -22
  725. package/dist/locales/es/openhands.json +79 -22
  726. package/dist/locales/fr/openhands.json +79 -22
  727. package/dist/locales/it/openhands.json +79 -22
  728. package/dist/locales/ja/openhands.json +79 -22
  729. package/dist/locales/ko-KR/openhands.json +79 -22
  730. package/dist/locales/no/openhands.json +79 -22
  731. package/dist/locales/pt/openhands.json +79 -22
  732. package/dist/locales/tr/openhands.json +79 -22
  733. package/dist/locales/uk/openhands.json +79 -22
  734. package/dist/locales/zh-CN/openhands.json +79 -22
  735. package/dist/locales/zh-TW/openhands.json +79 -22
  736. package/dist/manifests/automation-insights.cjs.map +1 -1
  737. package/dist/manifests/automation-insights.d.ts +10 -2
  738. package/dist/manifests/automation-insights.js.map +1 -1
  739. package/dist/manifests/automation-setup.cjs +1 -1
  740. package/dist/manifests/automation-setup.cjs.map +1 -1
  741. package/dist/manifests/automation-setup.d.ts +9 -16
  742. package/dist/manifests/automation-setup.js +17 -7
  743. package/dist/manifests/automation-setup.js.map +1 -1
  744. package/dist/manifests/manifest-actions.d.ts +1 -1
  745. package/dist/manifests/manifest-capabilities.d.ts +3 -1
  746. package/dist/manifests/manifest-local-validation.cjs +2 -0
  747. package/dist/manifests/manifest-local-validation.cjs.map +1 -0
  748. package/dist/manifests/manifest-local-validation.d.ts +15 -11
  749. package/dist/manifests/manifest-local-validation.js +8 -0
  750. package/dist/manifests/manifest-local-validation.js.map +1 -0
  751. package/dist/manifests/manifest-template.cjs +2 -0
  752. package/dist/manifests/manifest-template.cjs.map +1 -0
  753. package/dist/manifests/manifest-template.d.ts +4 -4
  754. package/dist/manifests/manifest-template.js +12 -0
  755. package/dist/manifests/manifest-template.js.map +1 -0
  756. package/dist/manifests/manifest-validation.cjs +1 -1
  757. package/dist/manifests/manifest-validation.cjs.map +1 -1
  758. package/dist/manifests/manifest-validation.js +106 -28
  759. package/dist/manifests/manifest-validation.js.map +1 -1
  760. package/dist/manifests/types.cjs.map +1 -1
  761. package/dist/manifests/types.d.ts +39 -4
  762. package/dist/manifests/types.js.map +1 -1
  763. package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.cjs +8 -0
  764. package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.cjs.map +1 -0
  765. package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.js +221 -0
  766. package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.js.map +1 -0
  767. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs +1 -1
  768. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs.map +1 -1
  769. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js +1 -1
  770. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js.map +1 -1
  771. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +1 -1
  772. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -1
  773. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +1 -1
  774. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -1
  775. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.cjs +1 -1
  776. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.cjs.map +1 -1
  777. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.js +1 -1
  778. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.js.map +1 -1
  779. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +1 -1
  780. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -1
  781. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +22 -20
  782. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -1
  783. package/dist/node_modules/@openhands/extensions/automations/interface.cjs +1 -1
  784. package/dist/node_modules/@openhands/extensions/automations/interface.cjs.map +1 -1
  785. package/dist/node_modules/@openhands/extensions/automations/interface.js +2 -1
  786. package/dist/node_modules/@openhands/extensions/automations/interface.js.map +1 -1
  787. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.cjs +1 -1
  788. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.cjs.map +1 -1
  789. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.js +24 -5
  790. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.js.map +1 -1
  791. package/dist/node_modules/@tanstack/react-query/build/modern/QueryClientProvider.cjs +1 -1
  792. package/dist/node_modules/@tanstack/react-query/build/modern/QueryClientProvider.js +1 -1
  793. package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.cjs +2 -0
  794. package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.cjs.map +1 -0
  795. package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.js +21 -0
  796. package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.js.map +1 -0
  797. package/dist/node_modules/lucide-react/dist/esm/icons/shrink.cjs +2 -0
  798. package/dist/node_modules/lucide-react/dist/esm/icons/shrink.cjs.map +1 -0
  799. package/dist/node_modules/lucide-react/dist/esm/icons/shrink.js +23 -0
  800. package/dist/node_modules/lucide-react/dist/esm/icons/shrink.js.map +1 -0
  801. package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.cjs +2 -0
  802. package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.cjs.map +1 -0
  803. package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.js +43 -0
  804. package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.js.map +1 -0
  805. package/dist/node_modules/lucide-react/dist/esm/icons/tags.cjs +2 -0
  806. package/dist/node_modules/lucide-react/dist/esm/icons/tags.cjs.map +1 -0
  807. package/dist/node_modules/lucide-react/dist/esm/icons/tags.js +22 -0
  808. package/dist/node_modules/lucide-react/dist/esm/icons/tags.js.map +1 -0
  809. package/dist/package.cjs +1 -1
  810. package/dist/package.cjs.map +1 -1
  811. package/dist/package.js +4 -4
  812. package/dist/package.js.map +1 -1
  813. package/dist/routes/agent-settings.d.ts +2 -0
  814. package/dist/routes/app-settings.cjs +1 -1
  815. package/dist/routes/app-settings.cjs.map +1 -1
  816. package/dist/routes/app-settings.js +53 -48
  817. package/dist/routes/app-settings.js.map +1 -1
  818. package/dist/routes/llm-settings.cjs +1 -1
  819. package/dist/routes/llm-settings.cjs.map +1 -1
  820. package/dist/routes/llm-settings.d.ts +3 -1
  821. package/dist/routes/llm-settings.js +120 -127
  822. package/dist/routes/llm-settings.js.map +1 -1
  823. package/dist/routes/planner-tab.cjs +1 -1
  824. package/dist/routes/planner-tab.cjs.map +1 -1
  825. package/dist/routes/planner-tab.js +44 -28
  826. package/dist/routes/planner-tab.js.map +1 -1
  827. package/dist/services/telemetry.cjs +1 -1
  828. package/dist/services/telemetry.cjs.map +1 -1
  829. package/dist/services/telemetry.d.ts +5 -0
  830. package/dist/services/telemetry.js +122 -115
  831. package/dist/services/telemetry.js.map +1 -1
  832. package/dist/stores/conversation-panel-preferences-store.cjs +1 -1
  833. package/dist/stores/conversation-panel-preferences-store.cjs.map +1 -1
  834. package/dist/stores/conversation-panel-preferences-store.d.ts +32 -5
  835. package/dist/stores/conversation-panel-preferences-store.js +29 -12
  836. package/dist/stores/conversation-panel-preferences-store.js.map +1 -1
  837. package/dist/stores/conversation-state-store.cjs +1 -1
  838. package/dist/stores/conversation-state-store.cjs.map +1 -1
  839. package/dist/stores/conversation-state-store.d.ts +9 -3
  840. package/dist/stores/conversation-state-store.js +6 -3
  841. package/dist/stores/conversation-state-store.js.map +1 -1
  842. package/dist/stores/conversation-store.cjs +1 -1
  843. package/dist/stores/conversation-store.cjs.map +1 -1
  844. package/dist/stores/conversation-store.d.ts +2 -0
  845. package/dist/stores/conversation-store.js +3 -0
  846. package/dist/stores/conversation-store.js.map +1 -1
  847. package/dist/stores/free-models-store.cjs +2 -0
  848. package/dist/stores/free-models-store.cjs.map +1 -0
  849. package/dist/stores/free-models-store.d.ts +30 -0
  850. package/dist/stores/free-models-store.js +22 -0
  851. package/dist/stores/free-models-store.js.map +1 -0
  852. package/dist/stores/model-store.cjs +1 -1
  853. package/dist/stores/model-store.cjs.map +1 -1
  854. package/dist/stores/model-store.d.ts +7 -0
  855. package/dist/stores/model-store.js +4 -0
  856. package/dist/stores/model-store.js.map +1 -1
  857. package/dist/types/automation.cjs.map +1 -1
  858. package/dist/types/automation.d.ts +46 -1
  859. package/dist/types/automation.js.map +1 -1
  860. package/dist/ui/context-menu.d.ts +1 -1
  861. package/dist/ui/toggle-switch.cjs +1 -1
  862. package/dist/ui/toggle-switch.cjs.map +1 -1
  863. package/dist/ui/toggle-switch.d.ts +4 -1
  864. package/dist/ui/toggle-switch.js +4 -3
  865. package/dist/ui/toggle-switch.js.map +1 -1
  866. package/dist/utils/automation-catalog.cjs +1 -1
  867. package/dist/utils/automation-catalog.cjs.map +1 -1
  868. package/dist/utils/automation-catalog.d.ts +12 -1
  869. package/dist/utils/automation-catalog.js +42 -12
  870. package/dist/utils/automation-catalog.js.map +1 -1
  871. package/dist/utils/automation-run-display.cjs +2 -0
  872. package/dist/utils/automation-run-display.cjs.map +1 -0
  873. package/dist/utils/automation-run-display.d.ts +20 -0
  874. package/dist/utils/automation-run-display.js +85 -0
  875. package/dist/utils/automation-run-display.js.map +1 -0
  876. package/dist/utils/automation-schedule.cjs +1 -1
  877. package/dist/utils/automation-schedule.cjs.map +1 -1
  878. package/dist/utils/automation-schedule.d.ts +16 -0
  879. package/dist/utils/automation-schedule.js +2 -0
  880. package/dist/utils/automation-schedule.js.map +1 -1
  881. package/dist/utils/constants.cjs +1 -1
  882. package/dist/utils/constants.cjs.map +1 -1
  883. package/dist/utils/constants.d.ts +4 -0
  884. package/dist/utils/constants.js +23 -3
  885. package/dist/utils/constants.js.map +1 -1
  886. package/dist/utils/format-event-timestamp.cjs +2 -0
  887. package/dist/utils/format-event-timestamp.cjs.map +1 -0
  888. package/dist/utils/format-event-timestamp.d.ts +1 -0
  889. package/dist/utils/format-event-timestamp.js +13 -0
  890. package/dist/utils/format-event-timestamp.js.map +1 -0
  891. package/dist/utils/format-model-name.cjs +1 -1
  892. package/dist/utils/format-model-name.cjs.map +1 -1
  893. package/dist/utils/format-model-name.d.ts +27 -6
  894. package/dist/utils/format-model-name.js +14 -6
  895. package/dist/utils/format-model-name.js.map +1 -1
  896. package/dist/utils/git-diff-stats.cjs +2 -2
  897. package/dist/utils/git-diff-stats.cjs.map +1 -1
  898. package/dist/utils/git-diff-stats.d.ts +4 -0
  899. package/dist/utils/git-diff-stats.js +12 -2
  900. package/dist/utils/git-diff-stats.js.map +1 -1
  901. package/dist/utils/plan-file.cjs +4 -0
  902. package/dist/utils/plan-file.cjs.map +1 -0
  903. package/dist/utils/plan-file.d.ts +18 -0
  904. package/dist/utils/plan-file.js +58 -0
  905. package/dist/utils/plan-file.js.map +1 -0
  906. package/dist/utils/recommended-automation-rail.cjs +1 -1
  907. package/dist/utils/recommended-automation-rail.cjs.map +1 -1
  908. package/dist/utils/recommended-automation-rail.js +1 -0
  909. package/dist/utils/recommended-automation-rail.js.map +1 -1
  910. package/dist/utils/scroll-fade-state.cjs +1 -1
  911. package/dist/utils/scroll-fade-state.cjs.map +1 -1
  912. package/dist/utils/scroll-fade-state.d.ts +6 -0
  913. package/dist/utils/scroll-fade-state.js +8 -1
  914. package/dist/utils/scroll-fade-state.js.map +1 -1
  915. package/dist/utils/sdk-settings-schema.cjs +1 -1
  916. package/dist/utils/sdk-settings-schema.cjs.map +1 -1
  917. package/dist/utils/sdk-settings-schema.d.ts +1 -0
  918. package/dist/utils/sdk-settings-schema.js +25 -22
  919. package/dist/utils/sdk-settings-schema.js.map +1 -1
  920. package/dist/utils/utils.cjs +1 -1
  921. package/dist/utils/utils.cjs.map +1 -1
  922. package/dist/utils/utils.js +11 -11
  923. package/dist/utils/utils.js.map +1 -1
  924. package/package.json +4 -4
  925. package/scripts/check-sdk-version-sync.mjs +6 -6
  926. package/scripts/dev-safe.mjs +1 -1
  927. package/scripts/dev-with-automation.mjs +1 -1
  928. package/scripts/static-server.mjs +33 -1
  929. package/build/assets/active-backend-context-CrHTlgvN.js +0 -2
  930. package/build/assets/agent-profiles-settings-Dzgb7G9z.js +0 -1
  931. package/build/assets/agent-server-conversation-service.api-tnqNjbpE.js +0 -86
  932. package/build/assets/agent-settings-DLtsqaOs.js +0 -2
  933. package/build/assets/agent-settings-fFvR-XC2.js +0 -1
  934. package/build/assets/alert-banner-HP6mX-Vr.js +0 -1
  935. package/build/assets/api-key-entry-screen-qTzrmJcr.js +0 -1
  936. package/build/assets/app-settings-dbnneVaV.js +0 -1
  937. package/build/assets/automation-detail-BmwlCUAB.js +0 -3
  938. package/build/assets/automation-git-sync-CprN5DcU.js +0 -1
  939. package/build/assets/automation-setup-route-C40kXjMY.js +0 -1
  940. package/build/assets/automations-list-DuNcRawl.js +0 -1
  941. package/build/assets/backend-form-modal-lhGwzXFI.js +0 -1
  942. package/build/assets/backend-synced-settings-badge-DPkz30BE.js +0 -1
  943. package/build/assets/badge-BU3S0VtE.js +0 -1
  944. package/build/assets/bot-dMYHVfYM.js +0 -1
  945. package/build/assets/browser-DSAo0tz1.js +0 -46
  946. package/build/assets/browser-tab-C9vy56R5.js +0 -1
  947. package/build/assets/canvas-extension-page-dx1gFrfW.js +0 -1
  948. package/build/assets/canvas-extensions-8A-XhpgP.js +0 -1
  949. package/build/assets/check-CS0vmpQQ.js +0 -1
  950. package/build/assets/chevron-down-e1QBpjVy.js +0 -1
  951. package/build/assets/chevron-right-ZG4R5G4Q.js +0 -1
  952. package/build/assets/circle-check-DzWLNsbE.js +0 -1
  953. package/build/assets/circle-plus-check-toggle-BO_kFZt3.js +0 -1
  954. package/build/assets/command-menu--UIlGL72.js +0 -1
  955. package/build/assets/commits-tab-AnZwLvh-.js +0 -1
  956. package/build/assets/confirmation-modal-Dv1ktp8K.js +0 -1
  957. package/build/assets/conversation-BbGrAO4Z.js +0 -93
  958. package/build/assets/conversation-mYT6NAoj.js +0 -1
  959. package/build/assets/conversation-panel-mYT6NAoj.js +0 -1
  960. package/build/assets/conversation-state-store-B0ImPLHO.js +0 -1
  961. package/build/assets/conversation-store-Ca3ghXap.js +0 -6
  962. package/build/assets/copy-to-clipboard-button-Ca8iSkkA.js +0 -1
  963. package/build/assets/device-verify-Bhn2e_Ye.js +0 -1
  964. package/build/assets/edit-automation-modal-DadGbJ2u.js +0 -1
  965. package/build/assets/empty-state-BoGVDecT.js +0 -1
  966. package/build/assets/enum-filter-dropdown-Bgca129f.js +0 -1
  967. package/build/assets/environment-switch-overlay-BmBRT7gv.js +0 -1
  968. package/build/assets/error-state-Body8Ngd.js +0 -1
  969. package/build/assets/extensions-hub-CcDqq_vR.js +0 -1
  970. package/build/assets/extensions-navigation-Cr4yzYk4.js +0 -1
  971. package/build/assets/external-link-DKUlnCQV.js +0 -1
  972. package/build/assets/files-tab-D4o2VyE_.js +0 -1
  973. package/build/assets/format-model-name-CasAP3nd.js +0 -1
  974. package/build/assets/get-git-path-ChKDVHZp.js +0 -1
  975. package/build/assets/git-repo-dropdown-4ROKl2cB.js +0 -1
  976. package/build/assets/git-repo-dropdown-BkqzkMmM.js +0 -1
  977. package/build/assets/highlighted-source-view-BFRxGT_Q.js +0 -1
  978. package/build/assets/home-ChpSuepX.js +0 -1
  979. package/build/assets/home-DIsB440S.js +0 -1
  980. package/build/assets/home-automation-run-tooltip-BVNDWjAH.js +0 -1
  981. package/build/assets/home-store-CY9Ej0ux.js +0 -1
  982. package/build/assets/index-home-BdlrFIif.js +0 -1
  983. package/build/assets/info-B6RQawoW.js +0 -1
  984. package/build/assets/install-server-modal-Dpy89p4g.js +0 -1
  985. package/build/assets/kebab-menu-item-content-D8hSNGmm.js +0 -1
  986. package/build/assets/launch-IrTDEFCs.js +0 -1
  987. package/build/assets/list-filter-DsEK7NFC.js +0 -1
  988. package/build/assets/llm-not-configured-banner-CIFABh3K.js +0 -27
  989. package/build/assets/llm-settings-B9juXhIa.js +0 -1
  990. package/build/assets/llm-settings-De1d5dfr.js +0 -1
  991. package/build/assets/llm-subscription-service-BpJ0ouQo.js +0 -1
  992. package/build/assets/loader-circle-CC1au6hc.js +0 -1
  993. package/build/assets/manage-backends-modal-BrPV3oB-.js +0 -1
  994. package/build/assets/manifest-80fb1c29.js +0 -1
  995. package/build/assets/manifest-subpage-layout-CAOYzrYp.js +0 -1
  996. package/build/assets/markdown-renderer-BzTlxI8x.js +0 -8
  997. package/build/assets/mcp-BTs_SXfZ.js +0 -1
  998. package/build/assets/mcp-page-BEBYqH_K.js +0 -9
  999. package/build/assets/messages-DKV9cRc2.js +0 -41
  1000. package/build/assets/modal-close-button-DDzdRvCs.js +0 -1
  1001. package/build/assets/onboarding-DV_OXoeP.js +0 -1
  1002. package/build/assets/onboarding-modal-rkyBYkeQ.js +0 -1
  1003. package/build/assets/organization-service.api-DrYNkEN_.js +0 -1
  1004. package/build/assets/pencil-47jAZH_V.js +0 -1
  1005. package/build/assets/pin-By41Vl5J.js +0 -1
  1006. package/build/assets/planner-tab-C9uZmhme.js +0 -1
  1007. package/build/assets/plug-CG5HFcNG.js +0 -1
  1008. package/build/assets/plugins-management-service-BMJgC3Ga.js +0 -1
  1009. package/build/assets/plus-C7Slq-0I.js +0 -1
  1010. package/build/assets/profiles-service.api-ChoKrL0l.js +0 -1
  1011. package/build/assets/providers-BhMcY5nv.js +0 -1
  1012. package/build/assets/proxy-9Fe1v5na.js +0 -1
  1013. package/build/assets/recommended-automations-launcher-6ABrI9Cy.js +0 -1
  1014. package/build/assets/refresh-cw-3q3Frrii.js +0 -1
  1015. package/build/assets/root-Dc8YmC9F.js +0 -2
  1016. package/build/assets/root-VDaypvK4.css +0 -1
  1017. package/build/assets/root-layout-CXkhSPYh.js +0 -2
  1018. package/build/assets/schema-field-D-y9-LDb.js +0 -1
  1019. package/build/assets/scroll-fade-state-Dw-i4SGq.js +0 -1
  1020. package/build/assets/sdk-section-page-BlFiizlG.js +0 -1
  1021. package/build/assets/secret-form-BB7the8W.js +0 -1
  1022. package/build/assets/secrets-service-ByZVENbp.js +0 -1
  1023. package/build/assets/secrets-settings-B_GpxKW2.js +0 -1
  1024. package/build/assets/settings-C0EWuBtA.js +0 -1
  1025. package/build/assets/settings-dropdown-input-BcwylHs2.js +0 -1
  1026. package/build/assets/settings-index-5w5UW2K3.js +0 -1
  1027. package/build/assets/settings-input-Db-1g8Ql.js +0 -1
  1028. package/build/assets/settings-modal-DfJ3tcJQ.js +0 -1
  1029. package/build/assets/settings-service.api-DJ1r62Zr.js +0 -1
  1030. package/build/assets/settings-switch-CS-dJDmA.js +0 -1
  1031. package/build/assets/shared-conversation-CA5ISEDy.js +0 -1
  1032. package/build/assets/shield-check-D2aCRd16.js +0 -1
  1033. package/build/assets/sidebar-mobile-menu-toggle-C_fb0Jki.js +0 -1
  1034. package/build/assets/sidebar-store-DGqHkVLw.js +0 -1
  1035. package/build/assets/skill-card-pill-row-B27-xyig.js +0 -1
  1036. package/build/assets/skill-scope-B42H-XOc.js +0 -1
  1037. package/build/assets/skills-plugins-tgF8EiXC.js +0 -1
  1038. package/build/assets/skills-settings-BgJ9PaOe.js +0 -1
  1039. package/build/assets/styled-tooltip-C4jf5Fv9.js +0 -1
  1040. package/build/assets/task-list-tab-C5zcaktH.js +0 -1
  1041. package/build/assets/toggle-switch-ChOLXv2n.js +0 -1
  1042. package/build/assets/trash-2-D7K26eDO.js +0 -1
  1043. package/build/assets/trash-D-HYiVYM.js +0 -1
  1044. package/build/assets/triangle-alert-CtdXWHUI.js +0 -1
  1045. package/build/assets/usage-tab-CVDffLPt.js +0 -1
  1046. package/build/assets/use-acp-credential-form-XIQmpX6M.js +0 -1
  1047. package/build/assets/use-activate-agent-profile-BLfmvDiG.js +0 -1
  1048. package/build/assets/use-agent-profiles-Bd9Bvvp1.js +0 -1
  1049. package/build/assets/use-canvas-extensions-Bi693ujJ.js +0 -1
  1050. package/build/assets/use-config-A9QovgXO.js +0 -1
  1051. package/build/assets/use-create-conversation-Dx3l7mFZ.js +0 -1
  1052. package/build/assets/use-create-secret-B9cUFWRG.js +0 -1
  1053. package/build/assets/use-has-permission-B3C8rQmR.js +0 -1
  1054. package/build/assets/use-is-authed-nTBcM7dE.js +0 -1
  1055. package/build/assets/use-llm-configured-BV9nZ1_j.js +0 -1
  1056. package/build/assets/use-llm-profiles-BO-P4Oyo.js +0 -1
  1057. package/build/assets/use-manifest-capabilities-Cw_flwEz.js +0 -1
  1058. package/build/assets/use-onboarding-completion-D8U7k4Qb.js +0 -1
  1059. package/build/assets/use-pinned-home-route-CckOZrmb.js +0 -1
  1060. package/build/assets/use-plugins-marketplace-7i94Zu3Z.js +0 -1
  1061. package/build/assets/use-save-agent-profile-BUjSsDXK.js +0 -1
  1062. package/build/assets/use-settings-DSXLbvBl.js +0 -1
  1063. package/build/assets/use-settings-nav-items-CwRw-CmX.js +0 -16
  1064. package/build/assets/use-tracking-D53y3TH9.js +0 -3
  1065. package/build/assets/useQueries-DlbhlH9I.js +0 -1
  1066. package/build/assets/useQuery-BSTgq1rl.js +0 -1
  1067. package/build/assets/utils-CN5ZfZy1.js +0 -1
  1068. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-DqZDXfg2.js +0 -186
  1069. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew9ih1s8-rfV8mQ9m.js +0 -1
  1070. package/build/assets/vendor~root-layout-C9Ju9DQg.js +0 -1
  1071. package/build/assets/vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-BWir3rJs.js +0 -1
  1072. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-cDuKr-WD.js +0 -1
  1073. package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iyia17eu-Chf7vmKB.js +0 -1
  1074. package/build/assets/x-DJdhbdmt.js +0 -1
  1075. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs +0 -2
  1076. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs.map +0 -1
  1077. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.d.ts +0 -35
  1078. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js +0 -247
  1079. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js.map +0 -1
  1080. package/dist/hooks/query/use-skills.cjs +0 -2
  1081. package/dist/hooks/query/use-skills.cjs.map +0 -1
  1082. package/dist/hooks/query/use-skills.d.ts +0 -7
  1083. package/dist/hooks/query/use-skills.js +0 -13
  1084. package/dist/hooks/query/use-skills.js.map +0 -1
  1085. package/dist/hooks/use-has-permission.cjs +0 -2
  1086. package/dist/hooks/use-has-permission.cjs.map +0 -1
  1087. package/dist/hooks/use-has-permission.d.ts +0 -1
  1088. package/dist/hooks/use-has-permission.js +0 -8
  1089. package/dist/hooks/use-has-permission.js.map +0 -1
  1090. package/dist/node_modules/lucide-react/dist/esm/icons/eye.cjs +0 -2
  1091. package/dist/node_modules/lucide-react/dist/esm/icons/eye.cjs.map +0 -1
  1092. package/dist/node_modules/lucide-react/dist/esm/icons/eye.js +0 -14
  1093. package/dist/node_modules/lucide-react/dist/esm/icons/eye.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"agent-server-adapter.cjs","names":[],"sources":["../../src/api/agent-server-adapter.ts"],"sourcesContent":["import { ACP_SETTINGS_KEYS } from \"@openhands/typescript-client\";\nimport { ServerClient } from \"@openhands/typescript-client/clients\";\nimport { SKILLS_CATALOG } from \"@openhands/extensions/skills\";\nimport { DEFAULT_SETTINGS } from \"#/services/settings\";\nimport { ExecutionStatus } from \"#/types/agent-server/core\";\nimport { AgentKind, Settings, SettingsValue } from \"#/types/settings\";\nimport {\n getAcpPreferredDefaultModel,\n getAcpProvider,\n resolveEffectiveAcpModel,\n} from \"#/constants/acp-providers\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport {\n getCachedAgentServerInfo,\n isAgentServerToolAvailable,\n} from \"./agent-server-compatibility\";\nimport { getAgentServerWorkingDir } from \"./agent-server-config\";\nimport { getEffectiveLocalBackend } from \"./backend-registry/active-store\";\nimport { buildAuthHeaders } from \"./backend-registry/auth\";\nimport {\n GetHooksResponse,\n PluginSpec,\n AppConversation,\n AppConversationPage,\n RuntimeConversationStats,\n SandboxStatus,\n} from \"./conversation-service/agent-server-conversation-service.types\";\nimport { combineUsageMetrics } from \"#/utils/conversation-metrics\";\nimport {\n buildSkillEnablementFilter,\n findInvokedCatalogSkill,\n toSkillEnablement,\n type SkillEnablement,\n} from \"#/utils/skill-enablement\";\nimport SettingsService from \"./settings-service/settings-service.api\";\nimport { getStoredConversationMetadata } from \"./conversation-metadata-store\";\nimport LLMSubscriptionService from \"./llm-subscription-service\";\nimport {\n LLM_AUTH_TYPE_SUBSCRIPTION,\n OPENAI_SUBSCRIPTION_VENDOR,\n isSubscriptionLlmConfig,\n} from \"#/constants/llm-subscription\";\nimport {\n CANVAS_UI_CLIENT_TOOL,\n CANVAS_UI_CLIENT_TOOL_NAME,\n LEGACY_CANVAS_UI_TOOL_NAME,\n type ClientToolSpec,\n} from \"./canvas-ui-client-tool\";\nimport {\n LAUNCH_CHILD_CONVERSATION_CLIENT_TOOL,\n LAUNCH_CHILD_CONVERSATION_TOOL_NAME,\n} from \"./launch-child-conversation-client-tool\";\n\nexport interface DirectConversationInfo {\n id: string;\n title?: string | null;\n created_at: string;\n updated_at: string;\n execution_status?: string | null;\n /** Cloud-only sandbox lifecycle state. Omitted / null for local agent-server conversations. */\n sandbox_status?: string | null;\n metrics?: {\n accumulated_cost?: number | null;\n max_budget_per_task?: number | null;\n accumulated_token_usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n cache_read_tokens?: number;\n cache_write_tokens?: number;\n context_window?: number;\n per_turn_token?: number;\n } | null;\n } | null;\n /**\n * Raw per-usage-id LLM stats from the agent-server. Search/list responses\n * often carry real usage here even when `metrics` above comes back unset;\n * {@link toAppConversation} combines this as a fallback in that case.\n */\n stats?: RuntimeConversationStats | null;\n agent?: {\n /**\n * Pydantic discriminator from the SDK union: ``\"ACPAgent\"`` for ACP CLI\n * subprocesses (model lives on the subprocess via ``acp_model``),\n * ``\"Agent\"`` for direct litellm. Read by {@link toAppConversation}.\n */\n kind?: string | null;\n acp_model?: string | null;\n /**\n * ACP CLI identity (``claude-code`` / ``codex`` / ``gemini-cli``) from the\n * SDK's ``ACPAgent.acp_server`` (#3692). Preferred fallback when the\n * ``acpserver`` tag is absent — e.g. a profile launch doesn't stamp the tag\n * client-side and the server may not repopulate it. Read by {@link toAppConversation}.\n */\n acp_server?: string | null;\n llm?: {\n model?: string | null;\n } | null;\n } | null;\n current_model_id?: string | null;\n current_model_name?: string | null;\n workspace?: {\n working_dir?: string | null;\n } | null;\n /**\n * Arbitrary string-keyed conversation tags surfaced by the agent-server\n * (see ``ConversationInfo.tags``). Canvas only consumes one key today —\n * ``ACP_SERVER_TAG_KEY`` (\"acpserver\") — but the field is typed as a\n * generic record so future readers don't need another wire-shape change.\n * Keys are constrained to ``^[a-z0-9]+$`` by the agent-server validator;\n * values are opaque strings.\n */\n tags?: Record<string, string> | null;\n launched_agent_profile?: {\n agent_profile_id: string;\n revision: number;\n } | null;\n}\n\nconst DEFAULT_TOOL_NAMES = [\"terminal\", \"file_editor\", \"task_tracker\"];\nconst BROWSER_TOOL_SET_NAME = \"browser_tool_set\";\nconst TASK_TOOL_SET_NAME = \"task_tool_set\";\n\nfunction browserToolsEnabled() {\n return import.meta.env.VITE_ENABLE_BROWSER_TOOLS !== \"false\";\n}\n\n/**\n * Shape of the runtime services info served by Agent Canvas backends in\n * `/server_info.runtime_services`. All URLs are written from the agent's point of\n * view, not the browser's. The block is rendered into the agent's system prompt\n * via `AgentContext.system_message_suffix` so the agent knows what's reachable\n * from inside its sandbox without having to probe.\n */\nexport interface RuntimeServicesInfo {\n mode?: string;\n agent_host_alias?: string;\n services?: {\n agent_server?: { description?: string; url_from_agent?: string };\n ingress?: { description?: string; url_from_agent?: string };\n frontend?: {\n kind?: \"vite\" | \"static\";\n description?: string;\n url_from_agent?: string;\n };\n // `vite` is the legacy key name for the frontend entry, accepted for\n // one release while older dev-stack launchers may still emit it.\n vite?: { description?: string; url_from_agent?: string };\n automation?: {\n description?: string;\n url_from_agent?: string;\n api_prefix?: string;\n docs_url?: string;\n openapi_url?: string;\n auth_env_var?: string;\n };\n };\n}\n\nexport function parseRuntimeServicesInfo(\n value: unknown,\n): RuntimeServicesInfo | null {\n if (typeof value === \"string\") {\n const raw = value.trim();\n if (!raw) return null;\n try {\n return parseRuntimeServicesInfo(JSON.parse(raw));\n } catch {\n return null;\n }\n }\n\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return null;\n }\n\n const parsed = value as RuntimeServicesInfo;\n if (!parsed.services || typeof parsed.services !== \"object\") return null;\n return parsed;\n}\n\nexport async function fetchBackendRuntimeServicesInfo(): Promise<RuntimeServicesInfo | null> {\n let clientOptions: ReturnType<typeof getAgentServerClientOptions>;\n try {\n clientOptions = getAgentServerClientOptions({ timeout: 3000 });\n } catch {\n return null;\n }\n\n const cached = parseRuntimeServicesInfo(\n getCachedAgentServerInfo({ host: clientOptions.host })?.runtime_services,\n );\n if (cached) return cached;\n\n try {\n const serverInfo = await new ServerClient(clientOptions).getServerInfo();\n return parseRuntimeServicesInfo(\n (serverInfo as { runtime_services?: unknown }).runtime_services,\n );\n } catch {\n return null;\n }\n}\n\n/**\n * Return the deployment mode from the runtime services info, e.g. \"docker\",\n * \"dev:automation\", etc. Returns `null` when no runtime info is supplied.\n */\nexport function getDeploymentMode(\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n): string | null {\n return runtimeServicesInfo?.mode ?? null;\n}\n\n/**\n * Render the runtime services info into a markdown block suitable for\n * appending to the system prompt via `AgentContext.system_message_suffix`.\n *\n * Returns `undefined` when no runtime info is available, so callers can safely\n * omit the field when the selected backend does not advertise runtime services.\n */\nexport function buildRuntimeServicesSystemSuffix(\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n): string | undefined {\n const info = parseRuntimeServicesInfo(runtimeServicesInfo);\n if (!info?.services) return undefined;\n\n const lines: string[] = [];\n lines.push(\"<RUNTIME_SERVICES>\");\n if (info.mode) {\n lines.push(\n `You are running inside an agent-canvas dev stack started in '${info.mode}' mode.`,\n );\n } else {\n lines.push(\"You are running inside an agent-canvas dev stack.\");\n }\n lines.push(\n \"The following services are reachable from your sandbox. URLs are written\",\n \"from your point of view (i.e., as you should curl/fetch them).\",\n \"\",\n );\n\n const { agent_server, ingress, automation } = info.services;\n const { frontend } = info.services;\n\n if (agent_server?.url_from_agent) {\n lines.push(\n `* Agent Server (you): ${agent_server.url_from_agent}`,\n ` ${agent_server.description ?? \"The agent-server hosting your tool calls.\"}`,\n );\n }\n if (ingress?.url_from_agent) {\n lines.push(\n `* Ingress: ${ingress.url_from_agent}`,\n ` ${ingress.description ?? \"Unified entry point for browser-facing traffic.\"}`,\n );\n }\n if (frontend?.url_from_agent) {\n lines.push(\n `* Frontend: ${frontend.url_from_agent}`,\n ` ${frontend.description ?? \"Frontend dev server.\"}`,\n );\n }\n if (automation?.url_from_agent) {\n lines.push(\n `* Automation backend: ${automation.url_from_agent}`,\n ` ${automation.description ?? \"OpenHands Automations service.\"}`,\n );\n if (automation.docs_url) {\n lines.push(` Docs: ${automation.docs_url}`);\n }\n if (automation.openapi_url) {\n lines.push(` OpenAPI: ${automation.openapi_url}`);\n }\n if (automation.auth_env_var) {\n // X-Session-API-Key is the local convention shared by the agent-server\n // and automation backend (see openhands-automation auth.py).\n lines.push(\n ` Auth: header 'X-Session-API-Key: $${automation.auth_env_var}'`,\n );\n }\n } else {\n lines.push(\n \"* Automation backend: not running in this dev mode (skip /api/automation calls).\",\n );\n }\n\n // Anchor the \"don't guess\" warning to the actual agent-server URL for\n // this stack instead of a hardcoded port. The agent-server listens on\n // different ports across dev modes, and baking the wrong port into the\n // system prompt is exactly the kind of confusion this block is meant to\n // prevent.\n const agentServerUrl = agent_server?.url_from_agent;\n lines.push(\n \"\",\n \"Trust this block over guessing: do not assume any other URLs are running.\",\n );\n if (agentServerUrl) {\n lines.push(\n `In particular, ${agentServerUrl} inside your sandbox is the Agent Server`,\n \"you are running inside of — NOT the automation backend.\",\n );\n }\n lines.push(\"</RUNTIME_SERVICES>\");\n\n return lines.join(\"\\n\");\n}\n\nexport function toConversationUrl(conversationId: string): string {\n // Local-format conversation URL — points at whichever local agent-server\n // is actually serving the conversation (the bundled one when the active\n // selection is cloud).\n const { host } = getAgentServerClientOptions();\n return `${host}/api/conversations/${conversationId}`;\n}\n\n// TODO(i18n): extract \"Conversation\" once we add CONVERSATION$DEFAULT_TITLE\n// with `{{shortId}}` interpolation. Kept as a literal for now to keep the\n// fallback inside this pure adapter rather than fanning out to display sites.\nexport function getDefaultConversationTitle(conversationId: string): string {\n return `Conversation ${conversationId.slice(0, 5)}`;\n}\n\nexport function toAppConversation(\n info: DirectConversationInfo,\n): AppConversation {\n const metadata = getStoredConversationMetadata(info.id);\n // ACPAgent conversations carry a sentinel ``llm`` on older SDKs. Prefer the\n // runtime model fields when available, then the configured ``acp_model`` that\n // Canvas saves for built-in providers. ``agent_kind`` still gates model\n // switching, so surfacing this string is display-only.\n const isAcp = info.agent?.kind === \"ACPAgent\";\n // Only surface ``acp_server`` for ACP conversations even if the wire\n // payload accidentally carries an ``acpserver`` tag on an OpenHands\n // conversation — the chip is identity info for the ACP CLI subprocess,\n // and showing it on a non-ACP conversation would be a lie. Fall back to the\n // agent's own ``acp_server`` (#3692) when the tag is missing — a profile\n // launch doesn't stamp the tag, so tag-only reads would drop the ACP model\n // picker and degrade the chip to a generic \"ACP\" (#1571).\n const acpServer = isAcp\n ? (info.tags?.[ACP_SERVER_TAG_KEY] ?? info.agent?.acp_server ?? null)\n : null;\n return {\n id: info.id,\n created_by_user_id: null,\n selected_repository: metadata?.selected_repository ?? null,\n selected_branch: metadata?.selected_branch ?? null,\n git_provider: metadata?.git_provider ?? null,\n selected_workspace: metadata?.selected_workspace ?? null,\n active_profile: metadata?.active_profile ?? null,\n title: info.title?.trim()\n ? info.title\n : getDefaultConversationTitle(info.id),\n trigger: null,\n pr_number: [],\n agent_kind: isAcp ? \"acp\" : \"openhands\",\n acp_server: acpServer,\n tags: info.tags ?? null,\n launched_agent_profile: info.launched_agent_profile ?? null,\n // Chip path: omit ``providerDefault`` so that when no concrete model\n // resolves, the chip falls back to the provider display name in\n // ConversationCardFooter rather than a registry default the session may\n // not actually be running.\n llm_model: isAcp\n ? resolveEffectiveAcpModel({\n runtimeName: info.current_model_name,\n runtimeId: info.current_model_id,\n configured: info.agent?.acp_model,\n sdkLlm: info.agent?.llm?.model,\n })\n : (info.agent?.llm?.model ?? DEFAULT_SETTINGS.llm_model),\n metrics: info.metrics\n ? {\n accumulated_cost: info.metrics.accumulated_cost ?? null,\n max_budget_per_task: info.metrics.max_budget_per_task ?? null,\n accumulated_token_usage: info.metrics.accumulated_token_usage\n ? {\n prompt_tokens:\n info.metrics.accumulated_token_usage.prompt_tokens ?? 0,\n completion_tokens:\n info.metrics.accumulated_token_usage.completion_tokens ?? 0,\n cache_read_tokens:\n info.metrics.accumulated_token_usage.cache_read_tokens ?? 0,\n cache_write_tokens:\n info.metrics.accumulated_token_usage.cache_write_tokens ?? 0,\n context_window:\n info.metrics.accumulated_token_usage.context_window ?? 0,\n per_turn_token:\n info.metrics.accumulated_token_usage.per_turn_token ?? 0,\n }\n : null,\n }\n : combineUsageMetrics(info.stats),\n created_at: info.created_at,\n updated_at: info.updated_at,\n execution_status:\n (info.execution_status as AppConversation[\"execution_status\"]) ??\n ExecutionStatus.IDLE,\n sandbox_status: (info.sandbox_status as SandboxStatus | null) ?? null,\n conversation_url: toConversationUrl(info.id),\n session_api_key: getAgentServerClientOptions().apiKey ?? null,\n sandbox_id: null,\n workspace: {\n working_dir: info.workspace?.working_dir ?? getAgentServerWorkingDir(),\n },\n public: false,\n sub_conversation_ids: [],\n };\n}\n\nexport function toConversationPage(data: {\n items: DirectConversationInfo[];\n next_page_id?: string | null;\n}): AppConversationPage {\n return {\n items: data.items.map(toAppConversation),\n next_page_id: data.next_page_id ?? null,\n };\n}\n\ntype SettingsRecord = Record<string, unknown>;\n\ninterface AgentToolSpec {\n name: string;\n params: SettingsRecord;\n}\n\ntype AgentSettingsPayload = SettingsRecord & {\n llm?: SettingsRecord;\n agent_context: SettingsRecord;\n tools?: AgentToolSpec[];\n};\n\ninterface LocalWorkspacePayload {\n kind: \"LocalWorkspace\";\n working_dir: string;\n}\n\ninterface InitialMessagePayload {\n role: \"user\";\n content: Array<{ type: \"text\"; text: string }>;\n run: true;\n}\n\ntype ConversationSettingsPayload = SettingsRecord & {\n workspace: LocalWorkspacePayload;\n initial_message?: InitialMessagePayload;\n};\n\nexport const ACP_SERVER_TAG_KEY = \"acpserver\";\nexport const CLIENT_SOURCE_TAG_KEY = \"clientsource\";\nexport const AGENT_CANVAS_SOURCE = \"agentcanvas\";\n\nexport const AUTOMATION_TRIGGER_TAG_KEY = \"automationtrigger\";\nexport const AUTOMATION_ID_TAG_KEY = \"automationid\";\nexport const AUTOMATION_NAME_TAG_KEY = \"automationname\";\nexport const AUTOMATION_RUN_ID_TAG_KEY = \"automationrunid\";\n\n/**\n * Tag keys stamped on conversations created by automation runs (see the SDK's\n * `RemoteWorkspace.default_conversation_tags`). The presence of any of these\n * marks a conversation as automation-born.\n */\nexport const AUTOMATION_TAG_KEYS: readonly string[] = [\n AUTOMATION_TRIGGER_TAG_KEY,\n AUTOMATION_ID_TAG_KEY,\n AUTOMATION_NAME_TAG_KEY,\n AUTOMATION_RUN_ID_TAG_KEY,\n];\n\n/**\n * Conversation tag keys that must not appear as generic chips / hovercard\n * rows. Each is either already surfaced by a first-class UI source or is\n * internal routing data:\n * - ``acpserver`` → ACP provider chip\n * - ``clientsource`` → telemetry attribution\n * - ``title`` → conversation card heading\n * - git / repo / branch / workspace stamps → repo-branch metadata + directory\n * footer / hovercard rows (``selected_repository``, ``selected_branch``,\n * ``git_provider``, ``workspace.working_dir``)\n * - ``automationid`` / ``automationrunid`` → raw UUIDs consumed by the\n * conversation panel's automation filter (chip noise), while\n * ``automationname`` / ``automationtrigger`` stay visible\n */\nexport const RESERVED_CONVERSATION_TAG_KEYS: ReadonlySet<string> = new Set([\n ACP_SERVER_TAG_KEY,\n CLIENT_SOURCE_TAG_KEY,\n AUTOMATION_ID_TAG_KEY,\n AUTOMATION_RUN_ID_TAG_KEY,\n \"title\",\n \"git_provider\",\n \"repo_name\",\n \"repo\",\n \"repository\",\n \"selected_branch\",\n \"branch\",\n \"archiveworkspacepath\",\n \"workspace\",\n \"working_dir\",\n]);\n\n/**\n * High-signal tag keys shown first in the chip row (before A–Z). Automations\n * often stamp ``origin``; remaining free-form tags sort alphabetically.\n */\nexport const PRIORITY_CONVERSATION_TAG_KEYS: readonly string[] = [\"origin\"];\n\n/**\n * User-facing subset of a conversation's server-side tags: everything except\n * {@link RESERVED_CONVERSATION_TAG_KEYS}, as stable ``[key, value]`` entries.\n * Priority keys come first (in {@link PRIORITY_CONVERSATION_TAG_KEYS} order);\n * the rest sort A–Z so chip order doesn't shuffle between refetches.\n */\nexport function getDisplayConversationTags(\n tags: Record<string, string> | null | undefined,\n): Array<[string, string]> {\n if (!tags) {\n return [];\n }\n // Both the reserved-key check and the priority lookup must see the same\n // normalized key: a cloud backend can stamp ``Origin`` / `` origin``, and\n // ranking those off the raw key would silently drop them out of first place.\n const priorityRank = (key: string): number => {\n const index = PRIORITY_CONVERSATION_TAG_KEYS.indexOf(\n key.trim().toLowerCase(),\n );\n return index === -1 ? Number.POSITIVE_INFINITY : index;\n };\n\n return Object.entries(tags)\n .filter(\n ([key, value]) =>\n !RESERVED_CONVERSATION_TAG_KEYS.has(key.trim().toLowerCase()) &&\n typeof value === \"string\" &&\n value.trim().length > 0,\n )\n .sort(([a], [b]) => {\n const aRank = priorityRank(a);\n const bRank = priorityRank(b);\n if (aRank !== bRank) {\n return aRank - bRank;\n }\n return a.localeCompare(b);\n });\n}\n\nconst FERNET_TOKEN_PREFIX = \"gAAAAA\";\n\nconst CONVERSATION_SETTINGS_METADATA_KEYS = new Set([\n \"schema_version\",\n \"agent_settings\",\n \"workspace\",\n \"conversation_id\",\n \"initial_message\",\n \"plugins\",\n]);\n\nfunction toRecord(value: unknown): SettingsRecord {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return {};\n }\n\n return structuredClone(value as SettingsRecord);\n}\n\nfunction normalizeSecretString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction hasEncryptedString(value: unknown): boolean {\n if (typeof value === \"string\") {\n return value.startsWith(FERNET_TOKEN_PREFIX);\n }\n if (Array.isArray(value)) {\n return value.some(hasEncryptedString);\n }\n if (isPlainRecord(value)) {\n return Object.values(value).some(hasEncryptedString);\n }\n return false;\n}\n\nfunction hasEncryptedMcpSecrets(mcpConfig: unknown): boolean {\n if (!isPlainRecord(mcpConfig)) {\n return false;\n }\n\n return Object.values(mcpConfig).some(hasEncryptedString);\n}\n\nfunction getConversationConfirmationPolicy(\n conversationSettings: SettingsRecord,\n) {\n if (conversationSettings.confirmation_mode !== true) {\n return { kind: \"NeverConfirm\" };\n }\n\n if (conversationSettings.security_analyzer === \"llm\") {\n return { kind: \"ConfirmRisky\", threshold: \"HIGH\", confirm_unknown: true };\n }\n\n return { kind: \"AlwaysConfirm\" };\n}\n\nfunction getConversationSecurityAnalyzer(conversationSettings: SettingsRecord) {\n switch (conversationSettings.security_analyzer) {\n case \"llm\":\n return { kind: \"LLMSecurityAnalyzer\" };\n case \"pattern\":\n return { kind: \"PatternSecurityAnalyzer\" };\n case \"policy_rail\":\n return { kind: \"PolicyRailSecurityAnalyzer\" };\n default:\n return undefined;\n }\n}\n\nfunction isToolRecord(\n value: unknown,\n): value is { name: string; params?: unknown } {\n return (\n !!value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n typeof (value as { name?: unknown }).name === \"string\"\n );\n}\n\nfunction shouldIncludeTool(name: string, agentSettings: SettingsRecord) {\n if (name === BROWSER_TOOL_SET_NAME) {\n return browserToolsEnabled() && isAgentServerToolAvailable(name);\n }\n\n if (name === TASK_TOOL_SET_NAME) {\n return (\n agentSettings.enable_sub_agents === true &&\n isAgentServerToolAvailable(name)\n );\n }\n\n return true;\n}\n\nfunction getAgentTools(agentSettings: SettingsRecord): AgentToolSpec[] {\n const tools = new Map<string, AgentToolSpec>();\n\n for (const name of DEFAULT_TOOL_NAMES) {\n if (shouldIncludeTool(name, agentSettings)) {\n tools.set(name, { name, params: {} });\n }\n }\n\n for (const name of [BROWSER_TOOL_SET_NAME, TASK_TOOL_SET_NAME]) {\n if (shouldIncludeTool(name, agentSettings)) {\n tools.set(name, { name, params: {} });\n }\n }\n\n const configuredTools = agentSettings.tools;\n if (\n Array.isArray(configuredTools) &&\n configuredTools.every((tool) => isToolRecord(tool))\n ) {\n for (const tool of configuredTools) {\n if (shouldIncludeTool(tool.name, agentSettings)) {\n tools.set(tool.name, {\n name: tool.name,\n params: toRecord(tool.params),\n });\n }\n }\n }\n\n return Array.from(tools.values());\n}\n\nfunction buildInitialMessage(\n query?: string,\n conversationInstructions?: string,\n): InitialMessagePayload | null {\n const parts = [query?.trim(), conversationInstructions?.trim()].filter(\n Boolean,\n );\n if (parts.length === 0) {\n return null;\n }\n\n return {\n role: \"user\",\n content: [{ type: \"text\", text: parts.join(\"\\n\\n\") }],\n run: true,\n };\n}\n\n/**\n * Shape of a bundled skill entry passed to the agent-server SDK via\n * `agent_context.skills`. Mirrors the SDK's `Skill` model fields that\n * the server uses for trigger matching, activation, and system-prompt\n * injection.\n */\ninterface BundledSkill {\n name: string;\n content: string;\n trigger: { type: \"keyword\"; keywords: string[] } | null;\n source: string;\n description: string | null;\n is_agentskills_format: true;\n license?: string;\n compatibility?: string;\n}\n\n/**\n * Convert the bundled `SKILLS_CATALOG` entries into the SDK `Skill` JSON\n * shape so the agent-server can perform trigger matching, skill activation,\n * and system-prompt injection without cloning the extensions repo.\n *\n * The SDK discriminates triggers via `{ type: \"keyword\", keywords: [...] }`.\n * Skills with no triggers get `trigger: null` (always-active / on-demand).\n */\nfunction buildBundledSkills(): BundledSkill[] {\n return SKILLS_CATALOG.map((entry) => {\n const trigger: BundledSkill[\"trigger\"] =\n entry.triggers?.length > 0\n ? { type: \"keyword\", keywords: entry.triggers }\n : null;\n\n // Use the absolute path to the skill's SKILL.md so the Python\n // agent-server can resolve bundled resources (scripts/, references/).\n // Falls back to \"public\" in library builds where the path isn't known.\n const source = __EXTENSIONS_SKILLS_DIR__\n ? `${__EXTENSIONS_SKILLS_DIR__}/${entry.name}/SKILL.md`\n : \"public\";\n\n return {\n name: entry.name,\n content: entry.content,\n trigger,\n source,\n description: entry.description ?? null,\n is_agentskills_format: true as const,\n ...(entry.license ? { license: entry.license } : {}),\n ...(entry.compatibility ? { compatibility: entry.compatibility } : {}),\n };\n });\n}\n\nfunction buildAgentContext(\n agentSettings: SettingsRecord,\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n enablement: SkillEnablement = {},\n invokedCatalogSkill?: string,\n): SettingsRecord {\n const runtimeServicesSuffix =\n buildRuntimeServicesSystemSuffix(runtimeServicesInfo);\n const existingContext = toRecord(agentSettings.agent_context);\n\n // Merge bundled public skills with any skills already present in the\n // agent context (e.g. user-defined skills set via the settings API).\n const existingSkills = Array.isArray(existingContext.skills)\n ? (existingContext.skills as SettingsRecord[])\n : [];\n const disabledSkills = enablement.disabledSkills ?? [];\n const disabledSkillNames = new Set(disabledSkills);\n const isSkillEnabled = buildSkillEnablementFilter(enablement);\n\n // The bundled catalog is allow-listed, not deny-listed: it is a build-time\n // snapshot of ~60 skills, so a deny-list puts every future addition into\n // every system prompt (OpenHands#16302). Skills the agent context already\n // carries are user-authored and stay opt-out. A skill the opening message\n // invokes by name overrides both, for this conversation only.\n const mergedSkills = [\n ...existingSkills.filter(\n (skill) =>\n typeof skill.name !== \"string\" || !disabledSkillNames.has(skill.name),\n ),\n ...buildBundledSkills().filter(\n (skill) =>\n skill.name === invokedCatalogSkill || isSkillEnabled(skill.name),\n ),\n ];\n\n return {\n ...existingContext,\n // Public skills are bundled at build time from the @openhands/extensions\n // npm package and passed directly in agent_context.skills. Setting\n // load_public_skills to false tells the agent-server SDK to skip its own\n // extensions-repo clone — the frontend is the sole source of public\n // skills now.\n //\n // Migration: the former VITE_LOAD_PUBLIC_SKILLS env var was removed\n // because bundled skills have no clone latency. Users who previously set\n // VITE_LOAD_PUBLIC_SKILLS=false to avoid clone delays no longer need it.\n skills: mergedSkills,\n load_public_skills: false,\n load_user_skills: true,\n load_project_skills: true,\n // The backend also auto-loads user/project skills; the deny-list must\n // travel with the context so those skills are excluded from the system\n // prompt too. The allow-list has no counterpart to send: the backend\n // loads no catalog skills of its own (`load_public_skills` is false).\n disabled_skills: disabledSkills,\n ...(runtimeServicesSuffix\n ? { system_message_suffix: runtimeServicesSuffix }\n : {}),\n };\n}\n\nfunction isAcpAgent(settings: Settings): boolean {\n const agentSettings = toRecord(settings.agent_settings);\n return agentSettings.agent_kind === \"acp\";\n}\n\nfunction getAcpServerTag(settings: Settings): string | undefined {\n const agentSettings = toRecord(settings.agent_settings);\n const value = agentSettings.acp_server;\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction resolveAcpCommand(agentSettings: SettingsRecord): unknown {\n const cmd = agentSettings.acp_command;\n const isEmpty = Array.isArray(cmd) && cmd.length === 0;\n const noCommand = cmd === undefined;\n if (!isEmpty && !noCommand) {\n return cmd;\n }\n\n const serverKey =\n typeof agentSettings.acp_server === \"string\"\n ? agentSettings.acp_server\n : undefined;\n const provider = getAcpProvider(serverKey);\n return provider ? [...provider.default_command] : cmd;\n}\n\nfunction buildConfiguredAcpAgentSettings(\n settings: Settings,\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n query?: string,\n): AgentSettingsPayload {\n const agentSettings = toRecord(settings.agent_settings);\n const payload: AgentSettingsPayload = {\n agent_kind: \"acp\",\n agent_context: buildAgentContext(\n agentSettings,\n runtimeServicesInfo,\n toSkillEnablement(settings),\n findInvokedCatalogSkill(query),\n ),\n };\n\n // TODO(#1019): set ``acp_isolate_data_dir: true`` here for a containerized\n // backend so concurrent same-provider conversations don't race on a shared\n // HOME. The SDK supports it (software-agent-sdk#3492), but the released\n // ``@openhands/typescript-client`` (1.24.3) doesn't surface it on\n // ``ACPAgentSettings`` yet, so sending it risks a validation error on older\n // servers. Cloud grouping isolation is separate (agent-canvas#1016).\n\n for (const key of ACP_SETTINGS_KEYS) {\n // ``acp_model`` is resolved separately below so a saved ``null`` still\n // falls back to the provider's default rather than being dropped.\n if (key === \"acp_model\") continue;\n // ``acp_env`` is deprecated — provider creds now route via ``request.secrets``.\n if (key === \"acp_env\") continue;\n const value =\n key === \"acp_command\"\n ? resolveAcpCommand(agentSettings)\n : agentSettings[key];\n if (value !== undefined && value !== null) {\n payload[key] = value;\n }\n }\n\n // ``mcp_config`` is a shared field (not in ACP_SETTINGS_KEYS): forward it\n // so the ACP subprocess connects to the configured MCP servers at session\n // creation. Only include it when it actually carries servers — an empty or\n // malformed value is dropped rather than sending ``mcp_config: {}``.\n const mcpConfig = toRecord(agentSettings.mcp_config);\n if (Object.keys(mcpConfig).length > 0) {\n payload.mcp_config = mcpConfig;\n }\n\n // Saved settings may carry ``acp_model: null`` (existing users predating\n // the default-model registry, or saved fields the agent-server stripped).\n // Fall back to the *preferred* default (Vertex-safe for Gemini) so the\n // conversation starts with whatever the Settings → Agent UI shows — without\n // that, the form's displayed default would silently not take effect at\n // runtime until the user re-saved the page.\n const serverKey =\n typeof agentSettings.acp_server === \"string\"\n ? agentSettings.acp_server\n : undefined;\n const effectiveModel = resolveEffectiveAcpModel({\n configured: agentSettings.acp_model as string | null | undefined,\n providerDefault: getAcpPreferredDefaultModel(serverKey),\n });\n if (effectiveModel) {\n payload.acp_model = effectiveModel;\n }\n\n return payload;\n}\n\nfunction buildConfiguredOpenHandsAgentSettings(\n settings: Settings,\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n query?: string,\n): AgentSettingsPayload {\n const agentSettings = toRecord(settings.agent_settings);\n const llm = toRecord(agentSettings.llm);\n\n llm.model =\n typeof llm.model === \"string\" && llm.model.trim().length > 0\n ? llm.model\n : DEFAULT_SETTINGS.llm_model;\n\n // Stream assistant tokens (parity with ACP agents). The agent-server only\n // emits StreamingDeltaEvents for SDK LLM agents when an LLM has stream=True.\n llm.stream = true;\n\n const apiKey = normalizeSecretString(llm.api_key);\n if (apiKey) {\n llm.api_key = apiKey;\n } else {\n delete llm.api_key;\n }\n\n const baseUrl = normalizeSecretString(llm.base_url);\n if (baseUrl) {\n llm.base_url = baseUrl;\n } else {\n delete llm.base_url;\n }\n\n if (isSubscriptionLlmConfig(llm)) {\n llm.auth_type = LLM_AUTH_TYPE_SUBSCRIPTION;\n llm.subscription_vendor = OPENAI_SUBSCRIPTION_VENDOR;\n delete llm.api_key;\n delete llm.base_url;\n } else {\n delete llm.auth_type;\n delete llm.subscription_vendor;\n }\n\n const mcpConfig = toRecord(agentSettings.mcp_config);\n if (Object.keys(mcpConfig).length === 0) {\n delete agentSettings.mcp_config;\n }\n\n delete agentSettings.acp_server;\n for (const key of ACP_SETTINGS_KEYS) {\n delete agentSettings[key];\n }\n // ``acp_env`` is no longer a forwarded ACP setting (provider creds ride the\n // Secrets panel), but a legacy value may linger on persisted settings —\n // scrub it so it never leaks onto the OpenHands payload.\n delete agentSettings.acp_env;\n\n return {\n ...agentSettings,\n llm,\n agent_context: buildAgentContext(\n agentSettings,\n runtimeServicesInfo,\n toSkillEnablement(settings),\n findInvokedCatalogSkill(query),\n ),\n tools: getAgentTools(agentSettings),\n };\n}\n\nfunction buildConfiguredAgentSettings(\n settings: Settings,\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n query?: string,\n): AgentSettingsPayload {\n return isAcpAgent(settings)\n ? buildConfiguredAcpAgentSettings(settings, runtimeServicesInfo, query)\n : buildConfiguredOpenHandsAgentSettings(\n settings,\n runtimeServicesInfo,\n query,\n );\n}\n\nfunction buildConfiguredConversationSettings(options: {\n settings: Settings;\n query?: string;\n conversationInstructions?: string;\n plugins?: PluginSpec[];\n workingDir?: string;\n}): ConversationSettingsPayload {\n const { settings, query, conversationInstructions, plugins, workingDir } =\n options;\n const conversationSettings = toRecord(settings.conversation_settings);\n const initialMessage = buildInitialMessage(query, conversationInstructions);\n\n CONVERSATION_SETTINGS_METADATA_KEYS.forEach(\n (key) => delete conversationSettings[key],\n );\n\n const payload: ConversationSettingsPayload = {\n ...conversationSettings,\n workspace: {\n kind: \"LocalWorkspace\",\n working_dir: workingDir ?? getAgentServerWorkingDir(),\n },\n ...(initialMessage ? { initial_message: initialMessage } : {}),\n ...(plugins?.length\n ? {\n plugins: plugins.map((plugin) => ({\n source: plugin.source,\n ...(plugin.ref ? { ref: plugin.ref } : {}),\n ...(plugin.repo_path ? { repo_path: plugin.repo_path } : {}),\n })),\n }\n : {}),\n };\n\n return payload;\n}\n\ninterface LookupSecret {\n kind: \"LookupSecret\";\n url: string;\n headers?: Record<string, string>;\n description?: string;\n}\n\ntype StartConversationPayload = Record<string, unknown> & {\n // Omitted when launching via ``agent_profile_id`` — the two are mutually\n // exclusive agent sources; the server resolves the profile server-side.\n agent_settings?: AgentSettingsPayload;\n agent_profile_id?: string;\n workspace: LocalWorkspacePayload;\n confirmation_policy: SettingsRecord;\n security_analyzer?: SettingsRecord;\n initial_message?: InitialMessagePayload;\n max_iterations: number;\n stuck_detection: true;\n autotitle: true;\n title_llm_profile?: string;\n worktree: boolean;\n secrets_encrypted?: true;\n conversation_id?: string;\n parent_conversation_id?: string;\n secrets?: Record<string, LookupSecret>;\n tags?: Record<string, string>;\n client_tools: ClientToolSpec[];\n tool_module_qualnames?: Record<string, string>;\n};\n\nexport interface StartConversationOptions {\n settings: Settings;\n query?: string;\n conversationInstructions?: string;\n plugins?: PluginSpec[];\n conversationId?: string;\n // Links the new conversation to an existing one as its child. The\n // agent-server requires the parent to exist and to share this\n // conversation's requested `workspace.working_dir` (software-agent-sdk\n // #4188, agent-server >= 1.37.1); older servers ignore the field.\n parentConversationId?: string;\n workingDir?: string;\n worktree?: boolean;\n encryptedAgentSettings?: Record<string, SettingsValue>;\n encryptedConversationSettings?: Record<string, SettingsValue>;\n secretsEncrypted?: boolean;\n customSecrets?: Array<{ name: string; description?: string }>;\n // When set, the conversation launches from this AgentProfile (resolved\n // server-side) instead of an inline ``agent_settings`` dump (#3727).\n agentProfileId?: string;\n agentProfileKind?: AgentKind;\n titleLlmProfile?: string;\n runtimeServicesInfo?: RuntimeServicesInfo | null;\n}\n\nexport function buildStartConversationRequest(\n options: StartConversationOptions,\n): StartConversationPayload {\n const sourceAgentSettings = options.encryptedAgentSettings\n ? { ...options.settings, agent_settings: options.encryptedAgentSettings }\n : options.settings;\n\n const acpMode = isAcpAgent(sourceAgentSettings);\n const launchAgentKind = options.agentProfileId\n ? options.agentProfileKind\n : acpMode\n ? \"acp\"\n : \"openhands\";\n const agentSettings = buildConfiguredAgentSettings(\n sourceAgentSettings,\n options.runtimeServicesInfo,\n options.query,\n );\n const acpServerTag = acpMode\n ? getAcpServerTag(sourceAgentSettings)\n : undefined;\n\n const sourceConversationOptions = options.encryptedConversationSettings\n ? {\n ...options,\n settings: {\n ...options.settings,\n conversation_settings: options.encryptedConversationSettings,\n },\n }\n : options;\n\n const conversationSettings = buildConfiguredConversationSettings(\n sourceConversationOptions,\n );\n\n const payload: StartConversationPayload = {\n // ``agent_profile_id`` and ``agent_settings`` are mutually exclusive agent\n // sources; the profile path lets the server resolve the profile (#3727).\n //\n // Enrichment boundary: on the profile path the server rebuilds the agent\n // purely from the stored profile fields, so the client-owned enrichments\n // this adapter folds into ``agent_settings`` do NOT apply. The exec toolset\n // (terminal/file_editor/task_tracker) and public-skill loading are the\n // server/SDK's responsibility to restore on the profile path — tracked in\n // software-agent-sdk#3967 (profile resolution must attach the default\n // toolset + public skills, else a profile-launched OpenHands agent has only\n // Finish/Think). The dev ``RUNTIME_SERVICES`` system-message suffix remains\n // agent-settings-only; the Canvas UI tool is a top-level client tool and\n // therefore works on both inline-agent and profile launch paths.\n //\n // Persistent memory is NOT on that boundary: ``load_memory`` is a global\n // user preference, so the agent-server stamps the stored\n // ``agent_settings.agent_context.load_memory`` onto the profile-resolved\n // agent the same way it already applies the global ``mcp_config``. The\n // toggle therefore applies to both launch paths, and the client must not\n // re-send it here (``agent_profile_id`` and ``agent_settings`` are\n // mutually exclusive).\n ...(options.agentProfileId\n ? { agent_profile_id: options.agentProfileId }\n : { agent_settings: agentSettings }),\n workspace: conversationSettings.workspace,\n // The agent-server caches each client tool's schema per tool *name* for the\n // life of the process and rejects a re-registration with a different schema\n // (`ClientToolSchemaConflictError`). Editing either schema below therefore\n // requires restarting a long-running dev agent-server before new\n // conversations can start.\n client_tools:\n launchAgentKind === \"openhands\"\n ? [CANVAS_UI_CLIENT_TOOL, LAUNCH_CHILD_CONVERSATION_CLIENT_TOOL]\n : [],\n confirmation_policy:\n getConversationConfirmationPolicy(conversationSettings),\n max_iterations:\n typeof conversationSettings.max_iterations === \"number\"\n ? conversationSettings.max_iterations\n : 500,\n stuck_detection: true,\n autotitle: true,\n ...(options.titleLlmProfile\n ? { title_llm_profile: options.titleLlmProfile }\n : {}),\n worktree: options.worktree ?? true,\n };\n\n // Stamp the client source tag so the agent-server can attribute the\n // conversation to Canvas in telemetry (conversation_source = \"canvas\").\n // A profile launch resolves the ACP server server-side, so don't stamp the\n // tag from current settings (it may not match the launched profile).\n if (!options.agentProfileId && acpServerTag) {\n payload.tags = {\n [ACP_SERVER_TAG_KEY]: acpServerTag,\n [CLIENT_SOURCE_TAG_KEY]: AGENT_CANVAS_SOURCE,\n };\n } else {\n payload.tags = { [CLIENT_SOURCE_TAG_KEY]: AGENT_CANVAS_SOURCE };\n }\n\n // ``secrets_encrypted`` makes the agent-server decrypt request secrets at\n // conversation start. Non-ACP conversations need it for encrypted LLM keys.\n // ACP normally carries provider credentials as LookupSecrets, so avoid\n // forcing a cipher on fresh ACP-only backends. The exception is MCP:\n // encrypted settings round-trip mcp_config secrets as Fernet tokens,\n // and ACP forwards mcp_config directly to the subprocess.\n if (\n !options.agentProfileId &&\n options.secretsEncrypted &&\n (!acpMode || hasEncryptedMcpSecrets(agentSettings.mcp_config))\n ) {\n payload.secrets_encrypted = true;\n }\n\n if (options.conversationId) {\n payload.conversation_id = options.conversationId;\n }\n\n if (options.parentConversationId) {\n payload.parent_conversation_id = options.parentConversationId;\n }\n\n const securityAnalyzer =\n getConversationSecurityAnalyzer(conversationSettings);\n if (securityAnalyzer) {\n payload.security_analyzer = securityAnalyzer;\n }\n\n if (conversationSettings.initial_message) {\n payload.initial_message = conversationSettings.initial_message;\n }\n\n if (conversationSettings.plugins) {\n payload.plugins = conversationSettings.plugins;\n }\n\n if (conversationSettings.hook_config) {\n payload.hook_config = conversationSettings.hook_config;\n }\n\n const toolModuleQualnames = {\n ...((conversationSettings.tool_module_qualnames as\n | Record<string, string>\n | undefined) ?? {}),\n };\n delete toolModuleQualnames[LEGACY_CANVAS_UI_TOOL_NAME];\n delete toolModuleQualnames[CANVAS_UI_CLIENT_TOOL_NAME];\n delete toolModuleQualnames[LAUNCH_CHILD_CONVERSATION_TOOL_NAME];\n if (Object.keys(toolModuleQualnames).length > 0) {\n payload.tool_module_qualnames = toolModuleQualnames;\n }\n\n if (conversationSettings.agent_definitions) {\n payload.agent_definitions = conversationSettings.agent_definitions;\n }\n\n // Every saved secret rides as a LookupSecret the agent-server resolves back\n // from its own store at spawn time — ``request.secrets`` is the sole channel,\n // uniform for ACP and non-ACP (agent-canvas#1039). For ACP the resolution\n // runs off the event loop (software-agent-sdk#3510, >=1.25.0), so the loopback\n // fetch can't deadlock.\n if (options.customSecrets && options.customSecrets.length > 0) {\n const backend = getEffectiveLocalBackend();\n const headers = backend ? buildAuthHeaders(backend) : {};\n\n const secrets: Record<string, LookupSecret> = {};\n for (const secret of options.customSecrets) {\n const lookupSecret: LookupSecret = {\n kind: \"LookupSecret\",\n url: `/api/settings/secrets/${encodeURIComponent(secret.name)}`,\n description: secret.description,\n };\n\n if (Object.keys(headers).length > 0) {\n lookupSecret.headers = headers;\n }\n\n secrets[secret.name] = lookupSecret;\n }\n\n payload.secrets = secrets;\n }\n\n return payload;\n}\n\nexport const SUBSCRIPTION_LOGIN_REQUIRED_ERROR =\n \"Connect your ChatGPT subscription before starting a conversation with this LLM profile.\";\n\n/**\n * Throws if a ChatGPT subscription LLM profile is not connected.\n * Called before conversation creation and LLM profile switch only — not on\n * subsequent message sends or conversation resume. The agent-server must handle\n * mid-conversation token expiry gracefully.\n */\nexport async function assertSubscriptionAuthReady(\n agentSettings: Record<string, unknown>,\n): Promise<void> {\n const llm = toRecord(agentSettings.llm);\n if (!isSubscriptionLlmConfig(llm)) return;\n\n const status = await LLMSubscriptionService.getOpenAIStatus();\n if (!status.connected) {\n throw new Error(SUBSCRIPTION_LOGIN_REQUIRED_ERROR);\n }\n}\n\nexport async function buildStartConversationRequestWithEncryptedSettings(options: {\n settings: Settings;\n query?: string;\n conversationInstructions?: string;\n plugins?: PluginSpec[];\n conversationId?: string;\n parentConversationId?: string;\n workingDir?: string;\n worktree?: boolean;\n agentProfileId?: string;\n agentProfileKind?: AgentKind;\n titleLlmProfile?: string;\n}): Promise<Record<string, unknown>> {\n const { SecretsService } = await import(\"./secrets-service\");\n\n const [settingsResult, customSecrets, runtimeServicesInfo] =\n await Promise.all([\n SettingsService.getSettingsForConversation(),\n SecretsService.getSecrets(),\n fetchBackendRuntimeServicesInfo(),\n ]);\n\n const { agentSettings, conversationSettings, secretsEncrypted } =\n settingsResult;\n\n // A profile launch resolves the LLM server-side, so the current-settings\n // subscription check doesn't apply (and can't see the profile's LLM).\n if (!options.agentProfileId) {\n await assertSubscriptionAuthReady(agentSettings);\n }\n\n return buildStartConversationRequest({\n ...options,\n encryptedAgentSettings: agentSettings,\n encryptedConversationSettings: conversationSettings,\n secretsEncrypted,\n customSecrets,\n runtimeServicesInfo,\n });\n}\n\nexport function emptyHooksResponse(): GetHooksResponse {\n return { hooks: [] };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agent-server-adapter.cjs","names":[],"sources":["../../src/api/agent-server-adapter.ts"],"sourcesContent":["import { ACP_SETTINGS_KEYS } from \"@openhands/typescript-client\";\nimport type { HookConfig } from \"@openhands/typescript-client\";\nimport { ServerClient } from \"@openhands/typescript-client/clients\";\nimport { SKILLS_CATALOG } from \"@openhands/extensions/skills\";\nimport { DEFAULT_SETTINGS } from \"#/services/settings\";\nimport { ExecutionStatus } from \"#/types/agent-server/core\";\nimport { AgentKind, Settings, SettingsValue } from \"#/types/settings\";\nimport {\n getAcpPreferredDefaultModel,\n getAcpProvider,\n resolveEffectiveAcpModel,\n} from \"#/constants/acp-providers\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport {\n getCachedAgentServerInfo,\n isAgentServerToolAvailable,\n} from \"./agent-server-compatibility\";\nimport { getAgentServerWorkingDir } from \"./agent-server-config\";\nimport { getEffectiveLocalBackend } from \"./backend-registry/active-store\";\nimport { buildAuthHeaders } from \"./backend-registry/auth\";\nimport {\n GetHooksResponse,\n PluginSpec,\n AppConversation,\n AppConversationPage,\n RuntimeConversationStats,\n SandboxStatus,\n} from \"./conversation-service/agent-server-conversation-service.types\";\nimport { combineUsageMetrics } from \"#/utils/conversation-metrics\";\nimport {\n buildSkillEnablementFilter,\n findInvokedCatalogSkill,\n toSkillEnablement,\n type SkillEnablement,\n} from \"#/utils/skill-enablement\";\nimport SettingsService from \"./settings-service/settings-service.api\";\nimport { getStoredConversationMetadata } from \"./conversation-metadata-store\";\nimport LLMSubscriptionService from \"./llm-subscription-service\";\nimport {\n LLM_AUTH_TYPE_SUBSCRIPTION,\n OPENAI_SUBSCRIPTION_VENDOR,\n isSubscriptionLlmConfig,\n} from \"#/constants/llm-subscription\";\nimport {\n CANVAS_UI_CLIENT_TOOL,\n CANVAS_UI_CLIENT_TOOL_NAME,\n LEGACY_CANVAS_UI_TOOL_NAME,\n type ClientToolSpec,\n} from \"./canvas-ui-client-tool\";\nimport {\n LAUNCH_CHILD_CONVERSATION_CLIENT_TOOL,\n LAUNCH_CHILD_CONVERSATION_TOOL_NAME,\n} from \"./launch-child-conversation-client-tool\";\nimport {\n buildPlanPath,\n LOCAL_PLANNER_PARENT_TAG_KEY,\n PLAN_STRUCTURE_TEXT,\n PLANNING_AGENT_INSTRUCTION,\n PLANNING_FILE_EDITOR_TOOL_NAME,\n PLANNING_SYSTEM_PROMPT_FILENAME,\n} from \"#/utils/plan-file\";\n\nexport interface DirectConversationInfo {\n id: string;\n title?: string | null;\n created_at: string;\n updated_at: string;\n execution_status?: string | null;\n /** Cloud-only sandbox lifecycle state. Omitted / null for local agent-server conversations. */\n sandbox_status?: string | null;\n metrics?: {\n accumulated_cost?: number | null;\n max_budget_per_task?: number | null;\n accumulated_token_usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n cache_read_tokens?: number;\n cache_write_tokens?: number;\n context_window?: number;\n per_turn_token?: number;\n } | null;\n } | null;\n /**\n * Raw per-usage-id LLM stats from the agent-server. Search/list responses\n * often carry real usage here even when `metrics` above comes back unset;\n * {@link toAppConversation} combines this as a fallback in that case.\n */\n stats?: RuntimeConversationStats | null;\n agent?: {\n /**\n * Pydantic discriminator from the SDK union: ``\"ACPAgent\"`` for ACP CLI\n * subprocesses (model lives on the subprocess via ``acp_model``),\n * ``\"Agent\"`` for direct litellm. Read by {@link toAppConversation}.\n */\n kind?: string | null;\n acp_model?: string | null;\n /**\n * ACP CLI identity (``claude-code`` / ``codex`` / ``gemini-cli``) from the\n * SDK's ``ACPAgent.acp_server`` (#3692). Preferred fallback when the\n * ``acpserver`` tag is absent — e.g. a profile launch doesn't stamp the tag\n * client-side and the server may not repopulate it. Read by {@link toAppConversation}.\n */\n acp_server?: string | null;\n llm?: {\n model?: string | null;\n } | null;\n } | null;\n current_model_id?: string | null;\n current_model_name?: string | null;\n workspace?: {\n working_dir?: string | null;\n } | null;\n /**\n * Arbitrary string-keyed conversation tags surfaced by the agent-server\n * (see ``ConversationInfo.tags``). Canvas only consumes one key today —\n * ``ACP_SERVER_TAG_KEY`` (\"acpserver\") — but the field is typed as a\n * generic record so future readers don't need another wire-shape change.\n * Keys are constrained to ``^[a-z0-9]+$`` by the agent-server validator;\n * values are opaque strings.\n */\n tags?: Record<string, string> | null;\n launched_agent_profile?: {\n agent_profile_id: string;\n revision: number;\n } | null;\n /**\n * Server-owned, derived from the catalog's ``parent_conversation_id`` link\n * (agent-server >= 1.37.1, SDK #4188) — a conversation started with a\n * parent is discoverable here on any browser, which is what makes the\n * local planner's relationship server state rather than a browser-local\n * hint. Absent on older agent-servers and on the cloud wire shape.\n */\n sub_conversation_ids?: string[] | null;\n}\n\nconst DEFAULT_TOOL_NAMES = [\"terminal\", \"file_editor\", \"task_tracker\"];\nconst BROWSER_TOOL_SET_NAME = \"browser_tool_set\";\nconst TASK_TOOL_SET_NAME = \"task_tool_set\";\n// Falls back to the same default the code agent uses when the user has not\n// configured `conversation_settings.max_iterations` (see buildConfiguredConversationSettings).\nconst DEFAULT_MAX_ITERATIONS = 500;\n\nfunction resolveMaxIterations(value: unknown): number {\n return typeof value === \"number\" ? value : DEFAULT_MAX_ITERATIONS;\n}\n\nfunction browserToolsEnabled() {\n return import.meta.env.VITE_ENABLE_BROWSER_TOOLS !== \"false\";\n}\n\n/**\n * Shape of the runtime services info served by Agent Canvas backends in\n * `/server_info.runtime_services`. All URLs are written from the agent's point of\n * view, not the browser's. The block is rendered into the agent's system prompt\n * via `AgentContext.system_message_suffix` so the agent knows what's reachable\n * from inside its sandbox without having to probe.\n */\nexport interface RuntimeServicesInfo {\n mode?: string;\n agent_host_alias?: string;\n services?: {\n agent_server?: { description?: string; url_from_agent?: string };\n ingress?: { description?: string; url_from_agent?: string };\n frontend?: {\n kind?: \"vite\" | \"static\";\n description?: string;\n url_from_agent?: string;\n };\n // `vite` is the legacy key name for the frontend entry, accepted for\n // one release while older dev-stack launchers may still emit it.\n vite?: { description?: string; url_from_agent?: string };\n automation?: {\n description?: string;\n url_from_agent?: string;\n api_prefix?: string;\n docs_url?: string;\n openapi_url?: string;\n auth_env_var?: string;\n };\n };\n}\n\nexport function parseRuntimeServicesInfo(\n value: unknown,\n): RuntimeServicesInfo | null {\n if (typeof value === \"string\") {\n const raw = value.trim();\n if (!raw) return null;\n try {\n return parseRuntimeServicesInfo(JSON.parse(raw));\n } catch {\n return null;\n }\n }\n\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return null;\n }\n\n const parsed = value as RuntimeServicesInfo;\n if (!parsed.services || typeof parsed.services !== \"object\") return null;\n return parsed;\n}\n\nexport async function fetchBackendRuntimeServicesInfo(): Promise<RuntimeServicesInfo | null> {\n let clientOptions: ReturnType<typeof getAgentServerClientOptions>;\n try {\n clientOptions = getAgentServerClientOptions({ timeout: 3000 });\n } catch {\n return null;\n }\n\n const cached = parseRuntimeServicesInfo(\n getCachedAgentServerInfo({ host: clientOptions.host })?.runtime_services,\n );\n if (cached) return cached;\n\n try {\n const serverInfo = await new ServerClient(clientOptions).getServerInfo();\n return parseRuntimeServicesInfo(\n (serverInfo as { runtime_services?: unknown }).runtime_services,\n );\n } catch {\n return null;\n }\n}\n\n/**\n * Return the deployment mode from the runtime services info, e.g. \"docker\",\n * \"dev:automation\", etc. Returns `null` when no runtime info is supplied.\n */\nexport function getDeploymentMode(\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n): string | null {\n return runtimeServicesInfo?.mode ?? null;\n}\n\n/**\n * Render the runtime services info into a markdown block suitable for\n * appending to the system prompt via `AgentContext.system_message_suffix`.\n *\n * Returns `undefined` when no runtime info is available, so callers can safely\n * omit the field when the selected backend does not advertise runtime services.\n */\nexport function buildRuntimeServicesSystemSuffix(\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n): string | undefined {\n const info = parseRuntimeServicesInfo(runtimeServicesInfo);\n if (!info?.services) return undefined;\n\n const lines: string[] = [];\n lines.push(\"<RUNTIME_SERVICES>\");\n if (info.mode) {\n lines.push(\n `You are running inside an agent-canvas dev stack started in '${info.mode}' mode.`,\n );\n } else {\n lines.push(\"You are running inside an agent-canvas dev stack.\");\n }\n lines.push(\n \"The following services are reachable from your sandbox. URLs are written\",\n \"from your point of view (i.e., as you should curl/fetch them).\",\n \"\",\n );\n\n const { agent_server, ingress, automation } = info.services;\n const { frontend } = info.services;\n\n if (agent_server?.url_from_agent) {\n lines.push(\n `* Agent Server (you): ${agent_server.url_from_agent}`,\n ` ${agent_server.description ?? \"The agent-server hosting your tool calls.\"}`,\n );\n }\n if (ingress?.url_from_agent) {\n lines.push(\n `* Ingress: ${ingress.url_from_agent}`,\n ` ${ingress.description ?? \"Unified entry point for browser-facing traffic.\"}`,\n );\n }\n if (frontend?.url_from_agent) {\n lines.push(\n `* Frontend: ${frontend.url_from_agent}`,\n ` ${frontend.description ?? \"Frontend dev server.\"}`,\n );\n }\n if (automation?.url_from_agent) {\n lines.push(\n `* Automation backend: ${automation.url_from_agent}`,\n ` ${automation.description ?? \"OpenHands Automations service.\"}`,\n );\n if (automation.docs_url) {\n lines.push(` Docs: ${automation.docs_url}`);\n }\n if (automation.openapi_url) {\n lines.push(` OpenAPI: ${automation.openapi_url}`);\n }\n if (automation.auth_env_var) {\n // X-Session-API-Key is the local convention shared by the agent-server\n // and automation backend (see openhands-automation auth.py).\n lines.push(\n ` Auth: header 'X-Session-API-Key: $${automation.auth_env_var}'`,\n );\n }\n } else {\n lines.push(\n \"* Automation backend: not running in this dev mode (skip /api/automation calls).\",\n );\n }\n\n // Anchor the \"don't guess\" warning to the actual agent-server URL for\n // this stack instead of a hardcoded port. The agent-server listens on\n // different ports across dev modes, and baking the wrong port into the\n // system prompt is exactly the kind of confusion this block is meant to\n // prevent.\n const agentServerUrl = agent_server?.url_from_agent;\n lines.push(\n \"\",\n \"Trust this block over guessing: do not assume any other URLs are running.\",\n );\n if (agentServerUrl) {\n lines.push(\n `In particular, ${agentServerUrl} inside your sandbox is the Agent Server`,\n \"you are running inside of — NOT the automation backend.\",\n );\n }\n lines.push(\"</RUNTIME_SERVICES>\");\n\n return lines.join(\"\\n\");\n}\n\nexport function toConversationUrl(conversationId: string): string {\n // Local-format conversation URL — points at whichever local agent-server\n // is actually serving the conversation (the bundled one when the active\n // selection is cloud).\n const { host } = getAgentServerClientOptions();\n return `${host}/api/conversations/${conversationId}`;\n}\n\n// TODO(i18n): extract \"Conversation\" once we add CONVERSATION$DEFAULT_TITLE\n// with `{{shortId}}` interpolation. Kept as a literal for now to keep the\n// fallback inside this pure adapter rather than fanning out to display sites.\nexport function getDefaultConversationTitle(conversationId: string): string {\n return `Conversation ${conversationId.slice(0, 5)}`;\n}\n\nexport function toAppConversation(\n info: DirectConversationInfo,\n): AppConversation {\n const metadata = getStoredConversationMetadata(info.id);\n // ACPAgent conversations carry a sentinel ``llm`` on older SDKs. Prefer the\n // runtime model fields when available, then the configured ``acp_model`` that\n // Canvas saves for built-in providers. ``agent_kind`` still gates model\n // switching, so surfacing this string is display-only.\n const isAcp = info.agent?.kind === \"ACPAgent\";\n // Only surface ``acp_server`` for ACP conversations even if the wire\n // payload accidentally carries an ``acpserver`` tag on an OpenHands\n // conversation — the chip is identity info for the ACP CLI subprocess,\n // and showing it on a non-ACP conversation would be a lie. Fall back to the\n // agent's own ``acp_server`` (#3692) when the tag is missing — a profile\n // launch doesn't stamp the tag, so tag-only reads would drop the ACP model\n // picker and degrade the chip to a generic \"ACP\" (#1571).\n const acpServer = isAcp\n ? (info.tags?.[ACP_SERVER_TAG_KEY] ?? info.agent?.acp_server ?? null)\n : null;\n return {\n id: info.id,\n created_by_user_id: null,\n selected_repository: metadata?.selected_repository ?? null,\n selected_branch: metadata?.selected_branch ?? null,\n git_provider: metadata?.git_provider ?? null,\n selected_workspace: metadata?.selected_workspace ?? null,\n active_profile: metadata?.active_profile ?? null,\n title: info.title?.trim()\n ? info.title\n : getDefaultConversationTitle(info.id),\n trigger: null,\n pr_number: [],\n agent_kind: isAcp ? \"acp\" : \"openhands\",\n acp_server: acpServer,\n tags: info.tags ?? null,\n launched_agent_profile: info.launched_agent_profile ?? null,\n // Chip path: omit ``providerDefault`` so that when no concrete model\n // resolves, the chip falls back to the provider display name in\n // ConversationCardFooter rather than a registry default the session may\n // not actually be running.\n llm_model: isAcp\n ? resolveEffectiveAcpModel({\n runtimeName: info.current_model_name,\n runtimeId: info.current_model_id,\n configured: info.agent?.acp_model,\n sdkLlm: info.agent?.llm?.model,\n })\n : (info.agent?.llm?.model ?? DEFAULT_SETTINGS.llm_model),\n metrics: info.metrics\n ? {\n accumulated_cost: info.metrics.accumulated_cost ?? null,\n max_budget_per_task: info.metrics.max_budget_per_task ?? null,\n accumulated_token_usage: info.metrics.accumulated_token_usage\n ? {\n prompt_tokens:\n info.metrics.accumulated_token_usage.prompt_tokens ?? 0,\n completion_tokens:\n info.metrics.accumulated_token_usage.completion_tokens ?? 0,\n cache_read_tokens:\n info.metrics.accumulated_token_usage.cache_read_tokens ?? 0,\n cache_write_tokens:\n info.metrics.accumulated_token_usage.cache_write_tokens ?? 0,\n context_window:\n info.metrics.accumulated_token_usage.context_window ?? 0,\n per_turn_token:\n info.metrics.accumulated_token_usage.per_turn_token ?? 0,\n }\n : null,\n }\n : combineUsageMetrics(info.stats),\n created_at: info.created_at,\n updated_at: info.updated_at,\n execution_status:\n (info.execution_status as AppConversation[\"execution_status\"]) ??\n ExecutionStatus.IDLE,\n sandbox_status: (info.sandbox_status as SandboxStatus | null) ?? null,\n conversation_url: toConversationUrl(info.id),\n session_api_key: getAgentServerClientOptions().apiKey ?? null,\n sandbox_id: null,\n workspace: {\n working_dir: info.workspace?.working_dir ?? getAgentServerWorkingDir(),\n },\n public: false,\n sub_conversation_ids: info.sub_conversation_ids ?? [],\n };\n}\n\nexport function toConversationPage(data: {\n items: DirectConversationInfo[];\n next_page_id?: string | null;\n}): AppConversationPage {\n return {\n items: data.items\n .filter((item) => !item.tags?.[LOCAL_PLANNER_PARENT_TAG_KEY])\n .map(toAppConversation),\n next_page_id: data.next_page_id ?? null,\n };\n}\n\ntype SettingsRecord = Record<string, unknown>;\n\ninterface AgentToolSpec {\n name: string;\n params: SettingsRecord;\n}\n\ntype AgentSettingsPayload = SettingsRecord & {\n llm?: SettingsRecord;\n agent_context: SettingsRecord;\n tools?: AgentToolSpec[];\n};\n\ninterface LocalWorkspacePayload {\n kind: \"LocalWorkspace\";\n working_dir: string;\n}\n\ninterface InitialMessagePayload {\n role: \"user\";\n content: Array<{ type: \"text\"; text: string }>;\n run: true;\n}\n\ntype ConversationSettingsPayload = SettingsRecord & {\n workspace: LocalWorkspacePayload;\n initial_message?: InitialMessagePayload;\n};\n\nexport const ACP_SERVER_TAG_KEY = \"acpserver\";\nexport const CLIENT_SOURCE_TAG_KEY = \"clientsource\";\nexport const AGENT_CANVAS_SOURCE = \"agentcanvas\";\n\nexport const AUTOMATION_TRIGGER_TAG_KEY = \"automationtrigger\";\nexport const AUTOMATION_ID_TAG_KEY = \"automationid\";\nexport const AUTOMATION_NAME_TAG_KEY = \"automationname\";\nexport const AUTOMATION_RUN_ID_TAG_KEY = \"automationrunid\";\n\n/**\n * Tag keys stamped on conversations created by automation runs (see the SDK's\n * `RemoteWorkspace.default_conversation_tags`). The presence of any of these\n * marks a conversation as automation-born.\n */\nexport const AUTOMATION_TAG_KEYS: readonly string[] = [\n AUTOMATION_TRIGGER_TAG_KEY,\n AUTOMATION_ID_TAG_KEY,\n AUTOMATION_NAME_TAG_KEY,\n AUTOMATION_RUN_ID_TAG_KEY,\n];\n\n/**\n * Conversation tag keys that must not appear as generic chips / hovercard\n * rows. Each is either already surfaced by a first-class UI source or is\n * internal routing data:\n * - ``acpserver`` → ACP provider chip\n * - ``clientsource`` → telemetry attribution\n * - ``title`` → conversation card heading\n * - git / repo / branch / workspace stamps → repo-branch metadata + directory\n * footer / hovercard rows (``selected_repository``, ``selected_branch``,\n * ``git_provider``, ``workspace.working_dir``)\n * - the automation family (``automationtrigger`` / ``automationid`` /\n * ``automationname`` / ``automationrunid``) → provenance the SDK stamps at\n * creation; the conversation panel's automation filter is its first-class\n * UI source. The tag surface is user organization data, so machine stamps\n * stay out of it — and users can't edit or spoof automation classification.\n * - ``localplannerparent`` → internal routing for the local planner; already\n * surfaced by the hidden-from-list planner filter\n */\nexport const RESERVED_CONVERSATION_TAG_KEYS: ReadonlySet<string> = new Set([\n ACP_SERVER_TAG_KEY,\n CLIENT_SOURCE_TAG_KEY,\n AUTOMATION_TRIGGER_TAG_KEY,\n AUTOMATION_ID_TAG_KEY,\n AUTOMATION_NAME_TAG_KEY,\n AUTOMATION_RUN_ID_TAG_KEY,\n \"title\",\n \"git_provider\",\n \"repo_name\",\n \"repo\",\n \"repository\",\n \"selected_branch\",\n \"branch\",\n \"archiveworkspacepath\",\n \"workspace\",\n \"working_dir\",\n LOCAL_PLANNER_PARENT_TAG_KEY,\n]);\n\n/**\n * High-signal tag keys shown first in the chip row (before A–Z). Automations\n * often stamp ``origin``; remaining free-form tags sort alphabetically.\n */\nexport const PRIORITY_CONVERSATION_TAG_KEYS: readonly string[] = [\"origin\"];\n\n/**\n * User-facing subset of a conversation's server-side tags: everything except\n * {@link RESERVED_CONVERSATION_TAG_KEYS}, as stable ``[key, value]`` entries.\n * Priority keys come first (in {@link PRIORITY_CONVERSATION_TAG_KEYS} order);\n * the rest sort A–Z so chip order doesn't shuffle between refetches.\n */\nexport function getDisplayConversationTags(\n tags: Record<string, string> | null | undefined,\n): Array<[string, string]> {\n if (!tags) {\n return [];\n }\n // Both the reserved-key check and the priority lookup must see the same\n // normalized key: a cloud backend can stamp ``Origin`` / `` origin``, and\n // ranking those off the raw key would silently drop them out of first place.\n const priorityRank = (key: string): number => {\n const index = PRIORITY_CONVERSATION_TAG_KEYS.indexOf(\n key.trim().toLowerCase(),\n );\n return index === -1 ? Number.POSITIVE_INFINITY : index;\n };\n\n return Object.entries(tags)\n .filter(\n ([key, value]) =>\n !RESERVED_CONVERSATION_TAG_KEYS.has(key.trim().toLowerCase()) &&\n typeof value === \"string\" &&\n // Bare tags (empty value) are displayable — chips/tooltips render\n // the key. Whitespace-only values stay dropped (raw-write junk).\n (value === \"\" || value.trim().length > 0),\n )\n .sort(([a], [b]) => {\n const aRank = priorityRank(a);\n const bRank = priorityRank(b);\n if (aRank !== bRank) {\n return aRank - bRank;\n }\n return a.localeCompare(b);\n });\n}\n\nconst FERNET_TOKEN_PREFIX = \"gAAAAA\";\n\nconst CONVERSATION_SETTINGS_METADATA_KEYS = new Set([\n \"schema_version\",\n \"agent_settings\",\n \"workspace\",\n \"conversation_id\",\n \"initial_message\",\n \"plugins\",\n]);\n\nfunction toRecord(value: unknown): SettingsRecord {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return {};\n }\n\n return structuredClone(value as SettingsRecord);\n}\n\nfunction normalizeSecretString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction buildNormalizedLlmSettings(value: unknown): SettingsRecord {\n const llm = toRecord(value);\n\n llm.model =\n typeof llm.model === \"string\" && llm.model.trim().length > 0\n ? llm.model\n : DEFAULT_SETTINGS.llm_model;\n\n const apiKey = normalizeSecretString(llm.api_key);\n if (apiKey) {\n llm.api_key = apiKey;\n } else {\n delete llm.api_key;\n }\n\n const baseUrl = normalizeSecretString(llm.base_url);\n if (baseUrl) {\n llm.base_url = baseUrl;\n } else {\n delete llm.base_url;\n }\n\n if (isSubscriptionLlmConfig(llm)) {\n llm.auth_type = LLM_AUTH_TYPE_SUBSCRIPTION;\n llm.subscription_vendor = OPENAI_SUBSCRIPTION_VENDOR;\n delete llm.api_key;\n } else {\n delete llm.auth_type;\n delete llm.subscription_vendor;\n }\n\n return llm;\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction hasEncryptedString(value: unknown): boolean {\n if (typeof value === \"string\") {\n return value.startsWith(FERNET_TOKEN_PREFIX);\n }\n if (Array.isArray(value)) {\n return value.some(hasEncryptedString);\n }\n if (isPlainRecord(value)) {\n return Object.values(value).some(hasEncryptedString);\n }\n return false;\n}\n\nfunction hasEncryptedMcpSecrets(mcpConfig: unknown): boolean {\n if (!isPlainRecord(mcpConfig)) {\n return false;\n }\n\n return Object.values(mcpConfig).some(hasEncryptedString);\n}\n\nfunction getConversationConfirmationPolicy(\n conversationSettings: SettingsRecord,\n) {\n if (conversationSettings.confirmation_mode !== true) {\n return { kind: \"NeverConfirm\" };\n }\n\n if (conversationSettings.security_analyzer === \"llm\") {\n return { kind: \"ConfirmRisky\", threshold: \"HIGH\", confirm_unknown: true };\n }\n\n return { kind: \"AlwaysConfirm\" };\n}\n\nfunction getConversationSecurityAnalyzer(conversationSettings: SettingsRecord) {\n switch (conversationSettings.security_analyzer) {\n case \"llm\":\n return { kind: \"LLMSecurityAnalyzer\" };\n case \"pattern\":\n return { kind: \"PatternSecurityAnalyzer\" };\n case \"policy_rail\":\n return { kind: \"PolicyRailSecurityAnalyzer\" };\n default:\n return undefined;\n }\n}\n\nfunction isToolRecord(\n value: unknown,\n): value is { name: string; params?: unknown } {\n return (\n !!value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n typeof (value as { name?: unknown }).name === \"string\"\n );\n}\n\nfunction shouldIncludeTool(name: string, agentSettings: SettingsRecord) {\n if (name === BROWSER_TOOL_SET_NAME) {\n return browserToolsEnabled() && isAgentServerToolAvailable(name);\n }\n\n if (name === TASK_TOOL_SET_NAME) {\n return (\n agentSettings.enable_sub_agents === true &&\n isAgentServerToolAvailable(name)\n );\n }\n\n return true;\n}\n\nfunction getAgentTools(agentSettings: SettingsRecord): AgentToolSpec[] {\n const tools = new Map<string, AgentToolSpec>();\n\n for (const name of DEFAULT_TOOL_NAMES) {\n if (shouldIncludeTool(name, agentSettings)) {\n tools.set(name, { name, params: {} });\n }\n }\n\n for (const name of [BROWSER_TOOL_SET_NAME, TASK_TOOL_SET_NAME]) {\n if (shouldIncludeTool(name, agentSettings)) {\n tools.set(name, { name, params: {} });\n }\n }\n\n const configuredTools = agentSettings.tools;\n if (\n Array.isArray(configuredTools) &&\n configuredTools.every((tool) => isToolRecord(tool))\n ) {\n for (const tool of configuredTools) {\n if (shouldIncludeTool(tool.name, agentSettings)) {\n tools.set(tool.name, {\n name: tool.name,\n params: toRecord(tool.params),\n });\n }\n }\n }\n\n return Array.from(tools.values());\n}\n\nfunction buildInitialMessage(\n query?: string,\n conversationInstructions?: string,\n): InitialMessagePayload | null {\n const parts = [query?.trim(), conversationInstructions?.trim()].filter(\n Boolean,\n );\n if (parts.length === 0) {\n return null;\n }\n\n return {\n role: \"user\",\n content: [{ type: \"text\", text: parts.join(\"\\n\\n\") }],\n run: true,\n };\n}\n\n/**\n * Shape of a bundled skill entry passed to the agent-server SDK via\n * `agent_context.skills`. Mirrors the SDK's `Skill` model fields that\n * the server uses for trigger matching, activation, and system-prompt\n * injection.\n */\ninterface BundledSkill {\n name: string;\n content: string;\n trigger: { type: \"keyword\"; keywords: string[] } | null;\n source: string;\n description: string | null;\n is_agentskills_format: true;\n license?: string;\n compatibility?: string;\n}\n\n/**\n * Convert the bundled `SKILLS_CATALOG` entries into the SDK `Skill` JSON\n * shape so the agent-server can perform trigger matching, skill activation,\n * and system-prompt injection without cloning the extensions repo.\n *\n * The SDK discriminates triggers via `{ type: \"keyword\", keywords: [...] }`.\n * Skills with no triggers get `trigger: null` (always-active / on-demand).\n */\nfunction buildBundledSkills(): BundledSkill[] {\n return SKILLS_CATALOG.map((entry) => {\n const trigger: BundledSkill[\"trigger\"] =\n entry.triggers?.length > 0\n ? { type: \"keyword\", keywords: entry.triggers }\n : null;\n\n // Use the absolute path to the skill's SKILL.md so the Python\n // agent-server can resolve bundled resources (scripts/, references/).\n // Falls back to \"public\" in library builds where the path isn't known.\n const source = __EXTENSIONS_SKILLS_DIR__\n ? `${__EXTENSIONS_SKILLS_DIR__}/${entry.name}/SKILL.md`\n : \"public\";\n\n return {\n name: entry.name,\n content: entry.content,\n trigger,\n source,\n description: entry.description ?? null,\n is_agentskills_format: true as const,\n ...(entry.license ? { license: entry.license } : {}),\n ...(entry.compatibility ? { compatibility: entry.compatibility } : {}),\n };\n });\n}\n\nfunction buildAgentContext(\n agentSettings: SettingsRecord,\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n enablement: SkillEnablement = {},\n invokedCatalogSkill?: string,\n): SettingsRecord {\n const runtimeServicesSuffix =\n buildRuntimeServicesSystemSuffix(runtimeServicesInfo);\n const existingContext = toRecord(agentSettings.agent_context);\n\n // Merge bundled public skills with any skills already present in the\n // agent context (e.g. user-defined skills set via the settings API).\n const existingSkills = Array.isArray(existingContext.skills)\n ? (existingContext.skills as SettingsRecord[])\n : [];\n const disabledSkills = enablement.disabledSkills ?? [];\n const disabledSkillNames = new Set(disabledSkills);\n const isSkillEnabled = buildSkillEnablementFilter(enablement);\n\n // The bundled catalog is allow-listed, not deny-listed: it is a build-time\n // snapshot of ~60 skills, so a deny-list puts every future addition into\n // every system prompt (OpenHands#16302). Skills the agent context already\n // carries are user-authored and stay opt-out. A skill the opening message\n // invokes by name overrides both, for this conversation only.\n const mergedSkills = [\n ...existingSkills.filter(\n (skill) =>\n typeof skill.name !== \"string\" || !disabledSkillNames.has(skill.name),\n ),\n ...buildBundledSkills().filter(\n (skill) =>\n skill.name === invokedCatalogSkill || isSkillEnabled(skill.name),\n ),\n ];\n\n return {\n ...existingContext,\n // Public skills are bundled at build time from the @openhands/extensions\n // npm package and passed directly in agent_context.skills. Setting\n // load_public_skills to false tells the agent-server SDK to skip its own\n // extensions-repo clone — the frontend is the sole source of public\n // skills now.\n //\n // Migration: the former VITE_LOAD_PUBLIC_SKILLS env var was removed\n // because bundled skills have no clone latency. Users who previously set\n // VITE_LOAD_PUBLIC_SKILLS=false to avoid clone delays no longer need it.\n skills: mergedSkills,\n load_public_skills: false,\n load_user_skills: true,\n load_project_skills: true,\n // The backend also auto-loads user/project skills; the deny-list must\n // travel with the context so those skills are excluded from the system\n // prompt too. The allow-list has no counterpart to send: the backend\n // loads no catalog skills of its own (`load_public_skills` is false).\n disabled_skills: disabledSkills,\n ...(runtimeServicesSuffix\n ? { system_message_suffix: runtimeServicesSuffix }\n : {}),\n };\n}\n\nfunction isAcpAgent(settings: Settings): boolean {\n const agentSettings = toRecord(settings.agent_settings);\n return agentSettings.agent_kind === \"acp\";\n}\n\nfunction getAcpServerTag(settings: Settings): string | undefined {\n const agentSettings = toRecord(settings.agent_settings);\n const value = agentSettings.acp_server;\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction resolveAcpCommand(agentSettings: SettingsRecord): unknown {\n const cmd = agentSettings.acp_command;\n const isEmpty = Array.isArray(cmd) && cmd.length === 0;\n const noCommand = cmd === undefined;\n if (!isEmpty && !noCommand) {\n return cmd;\n }\n\n const serverKey =\n typeof agentSettings.acp_server === \"string\"\n ? agentSettings.acp_server\n : undefined;\n const provider = getAcpProvider(serverKey);\n return provider ? [...provider.default_command] : cmd;\n}\n\nfunction buildConfiguredAcpAgentSettings(\n settings: Settings,\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n query?: string,\n): AgentSettingsPayload {\n const agentSettings = toRecord(settings.agent_settings);\n const payload: AgentSettingsPayload = {\n agent_kind: \"acp\",\n agent_context: buildAgentContext(\n agentSettings,\n runtimeServicesInfo,\n toSkillEnablement(settings),\n findInvokedCatalogSkill(query),\n ),\n };\n\n // TODO(#1019): set ``acp_isolate_data_dir: true`` here for a containerized\n // backend so concurrent same-provider conversations don't race on a shared\n // HOME. The SDK supports it (software-agent-sdk#3492), but the released\n // ``@openhands/typescript-client`` (1.24.3) doesn't surface it on\n // ``ACPAgentSettings`` yet, so sending it risks a validation error on older\n // servers. Cloud grouping isolation is separate (agent-canvas#1016).\n\n for (const key of ACP_SETTINGS_KEYS) {\n // ``acp_model`` is resolved separately below so a saved ``null`` still\n // falls back to the provider's default rather than being dropped.\n if (key === \"acp_model\") continue;\n // ``acp_env`` is deprecated — provider creds now route via ``request.secrets``.\n if (key === \"acp_env\") continue;\n const value =\n key === \"acp_command\"\n ? resolveAcpCommand(agentSettings)\n : agentSettings[key];\n if (value !== undefined && value !== null) {\n payload[key] = value;\n }\n }\n\n // ``mcp_config`` is a shared field (not in ACP_SETTINGS_KEYS): forward it\n // so the ACP subprocess connects to the configured MCP servers at session\n // creation. Only include it when it actually carries servers — an empty or\n // malformed value is dropped rather than sending ``mcp_config: {}``.\n const mcpConfig = toRecord(agentSettings.mcp_config);\n if (Object.keys(mcpConfig).length > 0) {\n payload.mcp_config = mcpConfig;\n }\n\n // Saved settings may carry ``acp_model: null`` (existing users predating\n // the default-model registry, or saved fields the agent-server stripped).\n // Fall back to the *preferred* default (Vertex-safe for Gemini) so the\n // conversation starts with whatever the Settings → Agent UI shows — without\n // that, the form's displayed default would silently not take effect at\n // runtime until the user re-saved the page.\n const serverKey =\n typeof agentSettings.acp_server === \"string\"\n ? agentSettings.acp_server\n : undefined;\n const effectiveModel = resolveEffectiveAcpModel({\n configured: agentSettings.acp_model as string | null | undefined,\n providerDefault: getAcpPreferredDefaultModel(serverKey),\n });\n if (effectiveModel) {\n payload.acp_model = effectiveModel;\n }\n\n return payload;\n}\n\nfunction buildConfiguredOpenHandsAgentSettings(\n settings: Settings,\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n query?: string,\n): AgentSettingsPayload {\n const agentSettings = toRecord(settings.agent_settings);\n const llm = buildNormalizedLlmSettings(agentSettings.llm);\n\n // Stream assistant tokens (parity with ACP agents). The agent-server only\n // emits StreamingDeltaEvents for SDK LLM agents when an LLM has stream=True.\n llm.stream = true;\n\n const mcpConfig = toRecord(agentSettings.mcp_config);\n if (Object.keys(mcpConfig).length === 0) {\n delete agentSettings.mcp_config;\n }\n\n delete agentSettings.acp_server;\n for (const key of ACP_SETTINGS_KEYS) {\n delete agentSettings[key];\n }\n // ``acp_env`` is no longer a forwarded ACP setting (provider creds ride the\n // Secrets panel), but a legacy value may linger on persisted settings —\n // scrub it so it never leaks onto the OpenHands payload.\n delete agentSettings.acp_env;\n\n return {\n ...agentSettings,\n llm,\n agent_context: buildAgentContext(\n agentSettings,\n runtimeServicesInfo,\n toSkillEnablement(settings),\n findInvokedCatalogSkill(query),\n ),\n tools: getAgentTools(agentSettings),\n };\n}\n\nfunction buildConfiguredAgentSettings(\n settings: Settings,\n runtimeServicesInfo?: RuntimeServicesInfo | null,\n query?: string,\n): AgentSettingsPayload {\n return isAcpAgent(settings)\n ? buildConfiguredAcpAgentSettings(settings, runtimeServicesInfo, query)\n : buildConfiguredOpenHandsAgentSettings(\n settings,\n runtimeServicesInfo,\n query,\n );\n}\n\nfunction buildConfiguredConversationSettings(options: {\n settings: Settings;\n query?: string;\n conversationInstructions?: string;\n plugins?: PluginSpec[];\n workingDir?: string;\n}): ConversationSettingsPayload {\n const { settings, query, conversationInstructions, plugins, workingDir } =\n options;\n const conversationSettings = toRecord(settings.conversation_settings);\n const initialMessage = buildInitialMessage(query, conversationInstructions);\n\n CONVERSATION_SETTINGS_METADATA_KEYS.forEach(\n (key) => delete conversationSettings[key],\n );\n\n const payload: ConversationSettingsPayload = {\n ...conversationSettings,\n workspace: {\n kind: \"LocalWorkspace\",\n working_dir: workingDir ?? getAgentServerWorkingDir(),\n },\n ...(initialMessage ? { initial_message: initialMessage } : {}),\n ...(plugins?.length\n ? {\n plugins: plugins.map((plugin) => ({\n source: plugin.source,\n ...(plugin.ref ? { ref: plugin.ref } : {}),\n ...(plugin.repo_path ? { repo_path: plugin.repo_path } : {}),\n })),\n }\n : {}),\n };\n\n return payload;\n}\n\ninterface LookupSecret {\n kind: \"LookupSecret\";\n url: string;\n headers?: Record<string, string>;\n description?: string;\n}\n\n/** A custom secret's public identity — name + optional description, no value. */\ntype CustomSecretInput = { name: string; description?: string };\n\ntype StartConversationPayloadBase = Record<string, unknown> & {\n workspace: LocalWorkspacePayload;\n confirmation_policy: SettingsRecord;\n security_analyzer?: SettingsRecord;\n initial_message?: InitialMessagePayload;\n max_iterations: number;\n stuck_detection: true;\n autotitle: boolean;\n title_llm_profile?: string;\n worktree: boolean;\n secrets_encrypted?: true;\n conversation_id?: string;\n parent_conversation_id?: string;\n secrets?: Record<string, LookupSecret>;\n tags?: Record<string, string>;\n client_tools: ClientToolSpec[];\n tool_module_qualnames?: Record<string, string>;\n};\n\ntype AgentSettingsStartConversationPayload = StartConversationPayloadBase & {\n // Omitted when launching via ``agent_profile_id`` — the two are mutually\n // exclusive agent sources; the server resolves the profile server-side.\n agent_settings?: AgentSettingsPayload;\n agent_profile_id?: string;\n agent?: never;\n};\n\n// The local planner bypasses agent assembly entirely and sends a raw agent\n// spec, so neither of the two managed agent sources applies.\ntype RawAgentStartConversationPayload = StartConversationPayloadBase & {\n agent: SettingsRecord;\n agent_settings?: never;\n agent_profile_id?: never;\n parent_conversation_id?: string;\n};\n\nexport interface StartConversationOptions {\n settings: Settings;\n query?: string;\n conversationInstructions?: string;\n plugins?: PluginSpec[];\n conversationId?: string;\n // Links the new conversation to an existing one as its child. The\n // agent-server requires the parent to exist and to share this\n // conversation's requested `workspace.working_dir` (software-agent-sdk\n // #4188, agent-server >= 1.37.1); older servers ignore the field.\n parentConversationId?: string;\n workingDir?: string;\n worktree?: boolean;\n encryptedAgentSettings?: Record<string, SettingsValue>;\n encryptedConversationSettings?: Record<string, SettingsValue>;\n secretsEncrypted?: boolean;\n customSecrets?: CustomSecretInput[];\n // When set, the conversation launches from this AgentProfile (resolved\n // server-side) instead of an inline ``agent_settings`` dump (#3727).\n agentProfileId?: string;\n agentProfileKind?: AgentKind;\n titleLlmProfile?: string;\n runtimeServicesInfo?: RuntimeServicesInfo | null;\n workspaceHookConfig?: HookConfig | null;\n}\n\n/**\n * Build the `request.secrets` map shared by the standard and planning\n * conversation builders. Every saved secret rides as a LookupSecret the\n * agent-server resolves from its own store at spawn time — `request.secrets` is\n * the sole channel, uniform for ACP and non-ACP (agent-canvas#1039). For ACP the\n * resolution runs off the event loop (software-agent-sdk#3510, >=1.25.0), so the\n * loopback fetch can't deadlock. Returns `undefined` when there are no custom\n * secrets so callers can omit the field.\n */\nfunction buildCustomSecrets(\n customSecrets: CustomSecretInput[] | undefined,\n): Record<string, LookupSecret> | undefined {\n if (!customSecrets?.length) return undefined;\n\n const backend = getEffectiveLocalBackend();\n const headers = backend ? buildAuthHeaders(backend) : {};\n\n const secrets: Record<string, LookupSecret> = {};\n for (const secret of customSecrets) {\n const lookupSecret: LookupSecret = {\n kind: \"LookupSecret\",\n url: `/api/settings/secrets/${encodeURIComponent(secret.name)}`,\n description: secret.description,\n };\n if (Object.keys(headers).length > 0) {\n lookupSecret.headers = headers;\n }\n secrets[secret.name] = lookupSecret;\n }\n return secrets;\n}\n\nexport function buildStartConversationRequest(\n options: StartConversationOptions,\n): AgentSettingsStartConversationPayload {\n const sourceAgentSettings = options.encryptedAgentSettings\n ? { ...options.settings, agent_settings: options.encryptedAgentSettings }\n : options.settings;\n\n const acpMode = isAcpAgent(sourceAgentSettings);\n const launchAgentKind = options.agentProfileId\n ? options.agentProfileKind\n : acpMode\n ? \"acp\"\n : \"openhands\";\n const agentSettings = buildConfiguredAgentSettings(\n sourceAgentSettings,\n options.runtimeServicesInfo,\n options.query,\n );\n const acpServerTag = acpMode\n ? getAcpServerTag(sourceAgentSettings)\n : undefined;\n\n const sourceConversationOptions = options.encryptedConversationSettings\n ? {\n ...options,\n settings: {\n ...options.settings,\n conversation_settings: options.encryptedConversationSettings,\n },\n }\n : options;\n\n const conversationSettings = buildConfiguredConversationSettings(\n sourceConversationOptions,\n );\n\n const payload: AgentSettingsStartConversationPayload = {\n // ``agent_profile_id`` and ``agent_settings`` are mutually exclusive agent\n // sources; the profile path lets the server resolve the profile (#3727).\n //\n // Enrichment boundary: on the profile path the server rebuilds the agent\n // purely from the stored profile fields, so the client-owned enrichments\n // this adapter folds into ``agent_settings`` do NOT apply. The exec toolset\n // (terminal/file_editor/task_tracker) and public-skill loading are the\n // server/SDK's responsibility to restore on the profile path — tracked in\n // software-agent-sdk#3967 (profile resolution must attach the default\n // toolset + public skills, else a profile-launched OpenHands agent has only\n // Finish/Think). The dev ``RUNTIME_SERVICES`` system-message suffix remains\n // agent-settings-only; the Canvas UI tool is a top-level client tool and\n // therefore works on both inline-agent and profile launch paths.\n //\n // Persistent memory is NOT on that boundary: ``load_memory`` is a global\n // user preference, so the agent-server stamps the stored\n // ``agent_settings.agent_context.load_memory`` onto the profile-resolved\n // agent the same way it already applies the global ``mcp_config``. The\n // toggle therefore applies to both launch paths, and the client must not\n // re-send it here (``agent_profile_id`` and ``agent_settings`` are\n // mutually exclusive).\n ...(options.agentProfileId\n ? { agent_profile_id: options.agentProfileId }\n : { agent_settings: agentSettings }),\n workspace: conversationSettings.workspace,\n // The agent-server caches each client tool's schema per tool *name* for the\n // life of the process and rejects a re-registration with a different schema\n // (`ClientToolSchemaConflictError`). Editing either schema below therefore\n // requires restarting a long-running dev agent-server before new\n // conversations can start.\n client_tools:\n launchAgentKind === \"openhands\"\n ? [CANVAS_UI_CLIENT_TOOL, LAUNCH_CHILD_CONVERSATION_CLIENT_TOOL]\n : [],\n confirmation_policy:\n getConversationConfirmationPolicy(conversationSettings),\n max_iterations: resolveMaxIterations(conversationSettings.max_iterations),\n stuck_detection: true,\n autotitle: true,\n ...(options.titleLlmProfile\n ? { title_llm_profile: options.titleLlmProfile }\n : {}),\n worktree: options.worktree ?? true,\n };\n\n // Stamp the client source tag so the agent-server can attribute the\n // conversation to Canvas in telemetry (conversation_source = \"canvas\").\n // A profile launch resolves the ACP server server-side, so don't stamp the\n // tag from current settings (it may not match the launched profile).\n if (!options.agentProfileId && acpServerTag) {\n payload.tags = {\n [ACP_SERVER_TAG_KEY]: acpServerTag,\n [CLIENT_SOURCE_TAG_KEY]: AGENT_CANVAS_SOURCE,\n };\n } else {\n payload.tags = { [CLIENT_SOURCE_TAG_KEY]: AGENT_CANVAS_SOURCE };\n }\n\n // ``secrets_encrypted`` makes the agent-server decrypt request secrets at\n // conversation start. Non-ACP conversations need it for encrypted LLM keys.\n // ACP normally carries provider credentials as LookupSecrets, so avoid\n // forcing a cipher on fresh ACP-only backends. The exception is MCP:\n // encrypted settings round-trip mcp_config secrets as Fernet tokens,\n // and ACP forwards mcp_config directly to the subprocess.\n if (\n !options.agentProfileId &&\n options.secretsEncrypted &&\n (!acpMode || hasEncryptedMcpSecrets(agentSettings.mcp_config))\n ) {\n payload.secrets_encrypted = true;\n }\n\n if (options.conversationId) {\n payload.conversation_id = options.conversationId;\n }\n\n if (options.parentConversationId) {\n payload.parent_conversation_id = options.parentConversationId;\n }\n\n const securityAnalyzer =\n getConversationSecurityAnalyzer(conversationSettings);\n if (securityAnalyzer) {\n payload.security_analyzer = securityAnalyzer;\n }\n\n if (conversationSettings.initial_message) {\n payload.initial_message = conversationSettings.initial_message;\n }\n\n if (conversationSettings.plugins) {\n payload.plugins = conversationSettings.plugins;\n }\n\n if (conversationSettings.hook_config) {\n payload.hook_config = conversationSettings.hook_config;\n } else if (options.workspaceHookConfig) {\n payload.hook_config = options.workspaceHookConfig;\n }\n\n const toolModuleQualnames = {\n ...((conversationSettings.tool_module_qualnames as\n | Record<string, string>\n | undefined) ?? {}),\n };\n delete toolModuleQualnames[LEGACY_CANVAS_UI_TOOL_NAME];\n delete toolModuleQualnames[CANVAS_UI_CLIENT_TOOL_NAME];\n delete toolModuleQualnames[LAUNCH_CHILD_CONVERSATION_TOOL_NAME];\n if (Object.keys(toolModuleQualnames).length > 0) {\n payload.tool_module_qualnames = toolModuleQualnames;\n }\n\n if (conversationSettings.agent_definitions) {\n payload.agent_definitions = conversationSettings.agent_definitions;\n }\n\n const secrets = buildCustomSecrets(options.customSecrets);\n if (secrets) {\n payload.secrets = secrets;\n }\n\n return payload;\n}\n\nexport function buildStartPlanningConversationRequest(options: {\n encryptedAgentSettings: Record<string, SettingsValue>;\n workingDir: string;\n parentConversationId: string;\n initialMessage?: string;\n secretsEncrypted?: boolean;\n customSecrets?: CustomSecretInput[];\n /** Mirrors the parent's configured `conversation_settings.max_iterations` — see DEFAULT_MAX_ITERATIONS. */\n maxIterations?: number;\n /** Mirrors the code agent's skill filtering — see buildConfiguredOpenHandsAgentSettings. */\n skillEnablement?: SkillEnablement;\n}): RawAgentStartConversationPayload {\n const agentSettings = toRecord(options.encryptedAgentSettings);\n const llm = buildNormalizedLlmSettings(agentSettings.llm);\n // Stream assistant tokens, matching the code agent (see\n // buildConfiguredOpenHandsAgentSettings) — otherwise the agent-server never\n // emits StreamingDeltaEvents for the planner and its replies would appear\n // all at once instead of token-by-token.\n llm.stream = true;\n\n const planPath = buildPlanPath(options.workingDir);\n\n // Put the planner's directive + boundaries in the system prompt (matching the\n // OpenHands app-server's PLANNING_AGENT_INSTRUCTION), preserving any suffix\n // buildAgentContext already set (e.g. the runtime-services block).\n const agentContext = buildAgentContext(\n agentSettings,\n undefined,\n options.skillEnablement,\n );\n const existingSuffix = agentContext.system_message_suffix;\n agentContext.system_message_suffix =\n typeof existingSuffix === \"string\"\n ? `${PLANNING_AGENT_INSTRUCTION}\\n\\n${existingSuffix}`\n : PLANNING_AGENT_INSTRUCTION;\n\n // Idle planner: \"Create a Plan\" only switches to plan mode and provisions\n // this conversation; the user sends the first message themselves, so nothing\n // is injected into the chat. An explicit initialMessage is still honored.\n const initialMessage = buildInitialMessage(options.initialMessage);\n\n const payload: RawAgentStartConversationPayload = {\n agent: {\n kind: \"Agent\",\n llm,\n tools: [\n { name: \"glob\", params: {} },\n { name: \"grep\", params: {} },\n {\n name: PLANNING_FILE_EDITOR_TOOL_NAME,\n params: { plan_path: planPath },\n },\n ],\n system_prompt_filename: PLANNING_SYSTEM_PROMPT_FILENAME,\n system_prompt_kwargs: { plan_structure: PLAN_STRUCTURE_TEXT },\n // agent_context (skills + project context) is intentionally included so\n // the planner shares the code agent's project context. This goes beyond\n // the bare SDK `get_planning_agent()` preset (which sets no context); it\n // mirrors how the frontend builds every agent, so the local planner is\n // not context-starved relative to the code agent.\n agent_context: agentContext,\n // Mirror the SDK planning preset's condenser (openhands-tools preset\n // `get_planning_condenser`): a larger rolling window and more pinned\n // initial context than the default, with its own usage_id so its\n // summarization LLM calls are attributed separately. The planning\n // conversation is sent as a raw agent spec (it bypasses the agent-server's\n // default agent assembly), so without this it would never condense —\n // diverging from the canonical planning agent on long sessions.\n condenser: {\n kind: \"LLMSummarizingCondenser\",\n llm: { ...llm, usage_id: \"planning_condenser\" },\n max_size: 100,\n keep_first: 6,\n },\n },\n workspace: {\n kind: \"LocalWorkspace\",\n working_dir: options.workingDir,\n },\n // No Canvas UI client tool: the planner's only output is PLAN.md, which the\n // Planner tab surfaces on its own via PlanningFileEditorObservation. Handing\n // it the panel-control tool would only let it navigate the right-side panel\n // away from the plan the user is reading.\n client_tools: [],\n confirmation_policy: { kind: \"NeverConfirm\" },\n max_iterations: options.maxIterations ?? DEFAULT_MAX_ITERATIONS,\n stuck_detection: true,\n autotitle: false,\n worktree: false,\n // Two independent links to the parent, for two different jobs:\n //\n // - ``parent_conversation_id`` is the server-owned relationship (SDK\n // #4188, agent-server >= 1.37.1). The parent's ``sub_conversation_ids``\n // is derived from it, so the planner is recoverable from the server on\n // any browser and after storage loss. Older agent-servers ignore the\n // field (``StartConversationRequest`` does not forbid extras), which is\n // why the client-side metadata hint is still written as a fallback.\n // - The tag is what hides the helper from the conversation list; it is\n // also the only marker on agent-servers too old for the parent link.\n parent_conversation_id: options.parentConversationId,\n tags: { [LOCAL_PLANNER_PARENT_TAG_KEY]: options.parentConversationId },\n ...(initialMessage ? { initial_message: initialMessage } : {}),\n };\n\n if (options.secretsEncrypted) {\n payload.secrets_encrypted = true;\n }\n\n const secrets = buildCustomSecrets(options.customSecrets);\n if (secrets) {\n payload.secrets = secrets;\n }\n\n return payload;\n}\n\n/**\n * Resolve the encrypted LLM config for a named LLM profile, so a planner can\n * run the parent conversation's *current* model (`active_profile`, tracking\n * `/model` and `SwitchLLMTool`) rather than a stale launch-time value.\n * Returns `null` — caller falls back further — if unknown or lookup fails.\n */\nasync function resolveLlmProfileSettings(\n profileName: string,\n): Promise<SettingsRecord | null> {\n try {\n const { default: ProfilesService } =\n await import(\"./profiles-service/profiles-service.api\");\n // ``encrypted`` matches ``secrets_encrypted`` on the payload: the\n // agent-server decrypts with the same cipher it encrypted with.\n const detail = await ProfilesService.getProfile(profileName, \"encrypted\");\n return isPlainRecord(detail.config) ? detail.config : null;\n } catch (error) {\n console.warn(\n `Falling back: could not resolve LLM profile ${profileName}`,\n error,\n );\n return null;\n }\n}\n\n/**\n * Resolve the encrypted LLM config the given AgentProfile launches with, as a\n * fallback for `resolveLlmProfileSettings`. AgentProfiles hold a reference\n * (`llm_profile_ref`), not credentials, so this is a two-hop lookup: profile\n * id -> llm profile name -> encrypted LLM config. Returns `null` — caller\n * falls back to global settings — for an unknown/ACP/dangling-ref profile or\n * a failed lookup, none of which should block plan creation outright.\n */\nasync function resolveAgentProfileLlmSettings(\n agentProfileId: string,\n): Promise<SettingsRecord | null> {\n try {\n const { default: AgentProfilesService } =\n await import(\"./agent-profiles-service/agent-profiles-service.api\");\n\n const { profiles } = await AgentProfilesService.listProfiles();\n const summary = profiles.find(\n (profile) => profile.id === agentProfileId && profile.llm_profile_ref,\n );\n if (!summary?.llm_profile_ref) return null;\n\n return await resolveLlmProfileSettings(summary.llm_profile_ref);\n } catch (error) {\n console.warn(\n `Falling back to global agent settings: could not resolve the LLM for agent profile ${agentProfileId}`,\n error,\n );\n return null;\n }\n}\n\nexport async function buildStartPlanningConversationRequestWithEncryptedSettings(options: {\n workingDir: string;\n parentConversationId: string;\n /**\n * The parent conversation's current LLM profile (`AppConversation.active_profile`,\n * tracking `/model` and `SwitchLLMTool`). Takes priority over\n * `parentAgentProfileId` so a model switch on the parent carries over to a\n * planner created afterward, without a *different* conversation's global\n * profile activation repointing it.\n */\n parentActiveProfileName?: string | null;\n /**\n * `launched_agent_profile.agent_profile_id` of the parent, when started\n * from an AgentProfile. Fallback for when `parentActiveProfileName` can't\n * be resolved (e.g. an ACP parent, whose `active_profile` is a stale\n * launch-time snapshot rather than anything the ACP agent itself runs).\n */\n parentAgentProfileId?: string | null;\n initialMessage?: string;\n}): Promise<RawAgentStartConversationPayload> {\n const { SecretsService } = await import(\"./secrets-service\");\n\n const [settingsResult, customSecrets] = await Promise.all([\n SettingsService.getSettingsForConversation(),\n SecretsService.getSecrets(),\n ]);\n\n const profileLlm =\n (options.parentActiveProfileName\n ? await resolveLlmProfileSettings(options.parentActiveProfileName)\n : null) ??\n (options.parentAgentProfileId\n ? await resolveAgentProfileLlmSettings(options.parentAgentProfileId)\n : null);\n const encryptedAgentSettings: Record<string, SettingsValue> = profileLlm\n ? { ...settingsResult.agentSettings, llm: profileLlm as SettingsValue }\n : settingsResult.agentSettings;\n\n await assertSubscriptionAuthReady(encryptedAgentSettings);\n\n // Mirror the code agent's configured cap (see DEFAULT_MAX_ITERATIONS) rather\n // than hardcoding a different value the planner could silently stop against.\n const maxIterations = resolveMaxIterations(\n settingsResult.conversationSettings.max_iterations,\n );\n\n return buildStartPlanningConversationRequest({\n ...options,\n encryptedAgentSettings,\n secretsEncrypted: settingsResult.secretsEncrypted,\n customSecrets,\n maxIterations,\n skillEnablement: settingsResult.skillEnablement,\n });\n}\n\nexport const SUBSCRIPTION_LOGIN_REQUIRED_ERROR =\n \"Connect your ChatGPT subscription before starting a conversation with this LLM profile.\";\n\n/**\n * Throws if a ChatGPT subscription LLM profile is not connected.\n * Called before conversation creation and LLM profile switch only — not on\n * subsequent message sends or conversation resume. The agent-server must handle\n * mid-conversation token expiry gracefully.\n */\nexport async function assertSubscriptionAuthReady(\n agentSettings: Record<string, unknown>,\n): Promise<void> {\n const llm = toRecord(agentSettings.llm);\n if (!isSubscriptionLlmConfig(llm)) return;\n\n const status = await LLMSubscriptionService.getOpenAIStatus();\n if (!status.connected) {\n throw new Error(SUBSCRIPTION_LOGIN_REQUIRED_ERROR);\n }\n}\n\nexport async function buildStartConversationRequestWithEncryptedSettings(options: {\n settings: Settings;\n query?: string;\n conversationInstructions?: string;\n plugins?: PluginSpec[];\n conversationId?: string;\n parentConversationId?: string;\n workingDir?: string;\n /** Workspace root for the hooks lookup, not the per-conversation `workingDir` (#16907). */\n hooksProjectDir?: string;\n worktree?: boolean;\n agentProfileId?: string;\n agentProfileKind?: AgentKind;\n titleLlmProfile?: string;\n}): Promise<Record<string, unknown>> {\n const [{ SecretsService }, { default: HooksService }] = await Promise.all([\n import(\"./secrets-service\"),\n import(\"./hooks-service\"),\n ]);\n\n const [\n settingsResult,\n customSecrets,\n runtimeServicesInfo,\n workspaceHookConfig,\n ] = await Promise.all([\n SettingsService.getSettingsForConversation(),\n SecretsService.getSecrets(),\n fetchBackendRuntimeServicesInfo(),\n HooksService.loadWorkspaceHooks(options.hooksProjectDir),\n ]);\n\n const { agentSettings, conversationSettings, secretsEncrypted } =\n settingsResult;\n\n // A profile launch resolves the LLM server-side, so the current-settings\n // subscription check doesn't apply (and can't see the profile's LLM).\n if (!options.agentProfileId) {\n await assertSubscriptionAuthReady(agentSettings);\n }\n\n return buildStartConversationRequest({\n ...options,\n encryptedAgentSettings: agentSettings,\n encryptedConversationSettings: conversationSettings,\n secretsEncrypted,\n customSecrets,\n runtimeServicesInfo,\n workspaceHookConfig,\n });\n}\n\nexport function emptyHooksResponse(): GetHooksResponse {\n return { hooks: [] };\n}\n"],"mappings":"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"}
@@ -1,5 +1,7 @@
1
+ import type { HookConfig } from "@openhands/typescript-client";
1
2
  import { AgentKind, Settings, SettingsValue } from "#/types/settings";
2
3
  import { GetHooksResponse, PluginSpec, AppConversation, AppConversationPage, RuntimeConversationStats } from "./conversation-service/agent-server-conversation-service.types";
4
+ import { type SkillEnablement } from "#/utils/skill-enablement";
3
5
  import { type ClientToolSpec } from "./canvas-ui-client-tool";
4
6
  export interface DirectConversationInfo {
5
7
  id: string;
@@ -64,6 +66,14 @@ export interface DirectConversationInfo {
64
66
  agent_profile_id: string;
65
67
  revision: number;
66
68
  } | null;
69
+ /**
70
+ * Server-owned, derived from the catalog's ``parent_conversation_id`` link
71
+ * (agent-server >= 1.37.1, SDK #4188) — a conversation started with a
72
+ * parent is discoverable here on any browser, which is what makes the
73
+ * local planner's relationship server state rather than a browser-local
74
+ * hint. Absent on older agent-servers and on the cloud wire shape.
75
+ */
76
+ sub_conversation_ids?: string[] | null;
67
77
  }
68
78
  /**
69
79
  * Shape of the runtime services info served by Agent Canvas backends in
@@ -170,9 +180,13 @@ export declare const AUTOMATION_TAG_KEYS: readonly string[];
170
180
  * - git / repo / branch / workspace stamps → repo-branch metadata + directory
171
181
  * footer / hovercard rows (``selected_repository``, ``selected_branch``,
172
182
  * ``git_provider``, ``workspace.working_dir``)
173
- * - ``automationid`` / ``automationrunid`` → raw UUIDs consumed by the
174
- * conversation panel's automation filter (chip noise), while
175
- * ``automationname`` / ``automationtrigger`` stay visible
183
+ * - the automation family (``automationtrigger`` / ``automationid`` /
184
+ * ``automationname`` / ``automationrunid``) provenance the SDK stamps at
185
+ * creation; the conversation panel's automation filter is its first-class
186
+ * UI source. The tag surface is user organization data, so machine stamps
187
+ * stay out of it — and users can't edit or spoof automation classification.
188
+ * - ``localplannerparent`` → internal routing for the local planner; already
189
+ * surfaced by the hidden-from-list planner filter
176
190
  */
177
191
  export declare const RESERVED_CONVERSATION_TAG_KEYS: ReadonlySet<string>;
178
192
  /**
@@ -193,16 +207,19 @@ interface LookupSecret {
193
207
  headers?: Record<string, string>;
194
208
  description?: string;
195
209
  }
196
- type StartConversationPayload = Record<string, unknown> & {
197
- agent_settings?: AgentSettingsPayload;
198
- agent_profile_id?: string;
210
+ /** A custom secret's public identity — name + optional description, no value. */
211
+ type CustomSecretInput = {
212
+ name: string;
213
+ description?: string;
214
+ };
215
+ type StartConversationPayloadBase = Record<string, unknown> & {
199
216
  workspace: LocalWorkspacePayload;
200
217
  confirmation_policy: SettingsRecord;
201
218
  security_analyzer?: SettingsRecord;
202
219
  initial_message?: InitialMessagePayload;
203
220
  max_iterations: number;
204
221
  stuck_detection: true;
205
- autotitle: true;
222
+ autotitle: boolean;
206
223
  title_llm_profile?: string;
207
224
  worktree: boolean;
208
225
  secrets_encrypted?: true;
@@ -213,6 +230,17 @@ type StartConversationPayload = Record<string, unknown> & {
213
230
  client_tools: ClientToolSpec[];
214
231
  tool_module_qualnames?: Record<string, string>;
215
232
  };
233
+ type AgentSettingsStartConversationPayload = StartConversationPayloadBase & {
234
+ agent_settings?: AgentSettingsPayload;
235
+ agent_profile_id?: string;
236
+ agent?: never;
237
+ };
238
+ type RawAgentStartConversationPayload = StartConversationPayloadBase & {
239
+ agent: SettingsRecord;
240
+ agent_settings?: never;
241
+ agent_profile_id?: never;
242
+ parent_conversation_id?: string;
243
+ };
216
244
  export interface StartConversationOptions {
217
245
  settings: Settings;
218
246
  query?: string;
@@ -225,16 +253,46 @@ export interface StartConversationOptions {
225
253
  encryptedAgentSettings?: Record<string, SettingsValue>;
226
254
  encryptedConversationSettings?: Record<string, SettingsValue>;
227
255
  secretsEncrypted?: boolean;
228
- customSecrets?: Array<{
229
- name: string;
230
- description?: string;
231
- }>;
256
+ customSecrets?: CustomSecretInput[];
232
257
  agentProfileId?: string;
233
258
  agentProfileKind?: AgentKind;
234
259
  titleLlmProfile?: string;
235
260
  runtimeServicesInfo?: RuntimeServicesInfo | null;
261
+ workspaceHookConfig?: HookConfig | null;
236
262
  }
237
- export declare function buildStartConversationRequest(options: StartConversationOptions): StartConversationPayload;
263
+ export declare function buildStartConversationRequest(options: StartConversationOptions): AgentSettingsStartConversationPayload;
264
+ export declare function buildStartPlanningConversationRequest(options: {
265
+ encryptedAgentSettings: Record<string, SettingsValue>;
266
+ workingDir: string;
267
+ parentConversationId: string;
268
+ initialMessage?: string;
269
+ secretsEncrypted?: boolean;
270
+ customSecrets?: CustomSecretInput[];
271
+ /** Mirrors the parent's configured `conversation_settings.max_iterations` — see DEFAULT_MAX_ITERATIONS. */
272
+ maxIterations?: number;
273
+ /** Mirrors the code agent's skill filtering — see buildConfiguredOpenHandsAgentSettings. */
274
+ skillEnablement?: SkillEnablement;
275
+ }): RawAgentStartConversationPayload;
276
+ export declare function buildStartPlanningConversationRequestWithEncryptedSettings(options: {
277
+ workingDir: string;
278
+ parentConversationId: string;
279
+ /**
280
+ * The parent conversation's current LLM profile (`AppConversation.active_profile`,
281
+ * tracking `/model` and `SwitchLLMTool`). Takes priority over
282
+ * `parentAgentProfileId` so a model switch on the parent carries over to a
283
+ * planner created afterward, without a *different* conversation's global
284
+ * profile activation repointing it.
285
+ */
286
+ parentActiveProfileName?: string | null;
287
+ /**
288
+ * `launched_agent_profile.agent_profile_id` of the parent, when started
289
+ * from an AgentProfile. Fallback for when `parentActiveProfileName` can't
290
+ * be resolved (e.g. an ACP parent, whose `active_profile` is a stale
291
+ * launch-time snapshot rather than anything the ACP agent itself runs).
292
+ */
293
+ parentAgentProfileId?: string | null;
294
+ initialMessage?: string;
295
+ }): Promise<RawAgentStartConversationPayload>;
238
296
  export declare const SUBSCRIPTION_LOGIN_REQUIRED_ERROR = "Connect your ChatGPT subscription before starting a conversation with this LLM profile.";
239
297
  /**
240
298
  * Throws if a ChatGPT subscription LLM profile is not connected.
@@ -251,6 +309,8 @@ export declare function buildStartConversationRequestWithEncryptedSettings(optio
251
309
  conversationId?: string;
252
310
  parentConversationId?: string;
253
311
  workingDir?: string;
312
+ /** Workspace root for the hooks lookup, not the per-conversation `workingDir` (#16907). */
313
+ hooksProjectDir?: string;
254
314
  worktree?: boolean;
255
315
  agentProfileId?: string;
256
316
  agentProfileKind?: AgentKind;