@openhands/agent-canvas 1.0.0-rc.2 → 1.0.0-rc.4

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 (305) hide show
  1. package/README.md +2 -2
  2. package/README.windows.md +2 -2
  3. package/build/assets/acp-providers-C55k29rf.js +1 -0
  4. package/build/assets/{add-backend-modal-CIfhseZn.js → add-backend-modal-BdYxoUdL.js} +1 -1
  5. package/build/assets/agent-server-conversation-service.api-js3oYcdU.js +5 -0
  6. package/build/assets/{agent-settings-B6htMeS2.js → agent-settings-BNrffu3I.js} +1 -1
  7. package/build/assets/{alert-banner-D41ZKDZT.js → alert-banner-BzU93oDh.js} +1 -1
  8. package/build/assets/{analytics-consent-form-modal-TINgM_jV.js → analytics-consent-form-modal-DIfCKp6g.js} +1 -1
  9. package/build/assets/{api-key-entry-screen-Di1vHgIU.js → api-key-entry-screen-CGyS-Cna.js} +1 -1
  10. package/build/assets/{app-settings-CjCa1MOB.js → app-settings-DmOs4oik.js} +1 -1
  11. package/build/assets/{automation-detail-DPoxzTdV.js → automation-detail-DLbCVJCw.js} +1 -1
  12. package/build/assets/{automations-list-DwUEe2Ea.js → automations-list-CoYj4o97.js} +1 -1
  13. package/build/assets/{backend-form-modal-B6q897ZX.js → backend-form-modal-BUy-PzZN.js} +1 -1
  14. package/build/assets/{backend-synced-settings-badge-BwTawSCE.js → backend-synced-settings-badge-1A63yxGs.js} +1 -1
  15. package/build/assets/browser-B8bp1IqT.js +5 -0
  16. package/build/assets/{browser-tab-DiRTKik8.js → browser-tab-CiBRWB4X.js} +1 -1
  17. package/build/assets/chat-send-button-qKFZuB9E.js +1 -0
  18. package/build/assets/{circle-plus-check-toggle-B3_W6-nt.js → circle-plus-check-toggle-CboDp7XB.js} +1 -1
  19. package/build/assets/{condenser-settings-DczjwkIp.js → condenser-settings-FCBjvqSo.js} +1 -1
  20. package/build/assets/conversation-CT8AvxEH.js +1 -0
  21. package/build/assets/conversation-panel-DqDDs4WZ.js +1 -0
  22. package/build/assets/conversation-service.api-y_eB_43m.js +1 -0
  23. package/build/assets/conversation-store-CiYGBud3.js +6 -0
  24. package/build/assets/conversation-vNuLKgz6.js +19 -0
  25. package/build/assets/conversation-websocket-context-Bb4XBXoc.js +3 -0
  26. package/build/assets/{device-verify-BVl4GEvt.js → device-verify-BOQz2LJQ.js} +1 -1
  27. package/build/assets/{edit-automation-modal-kc_FzbzK.js → edit-automation-modal-C-oC5tis.js} +1 -1
  28. package/build/assets/{entry.client-CWkbusD1.js → entry.client-Db3BpFL_.js} +2 -2
  29. package/build/assets/{enum-filter-dropdown-DlY0Q3fj.js → enum-filter-dropdown-DFwoVtOw.js} +1 -1
  30. package/build/assets/{extensions-hub-NbQnt-cn.js → extensions-hub-BxZbAtjP.js} +1 -1
  31. package/build/assets/extensions-navigation-BIb-vAa2.js +1 -0
  32. package/build/assets/{files-tab-mK7Mdyuf.js → files-tab-DpulQlIo.js} +1 -1
  33. package/build/assets/{git-control-bar-branch-button-C1qmab0K.js → git-control-bar-branch-button-D1uam-nI.js} +1 -1
  34. package/build/assets/home-D77Xasws.js +1 -0
  35. package/build/assets/install-server-modal-BjmEphcZ.js +1 -0
  36. package/build/assets/{launch-BADsYeGp.js → launch-DgtB1JTX.js} +1 -1
  37. package/build/assets/llm-settings-B8kPJ0Of.js +1 -0
  38. package/build/assets/llm-settings-CjUpPsvA.js +1 -0
  39. package/build/assets/{manage-backends-modal-sH7l5NgI.js → manage-backends-modal-CTA-2x4F.js} +1 -1
  40. package/build/assets/manifest-510dd26f.js +1 -0
  41. package/build/assets/{markdown-renderer-CZq_UdmE.js → markdown-renderer-oOUs3tw5.js} +1 -1
  42. package/build/assets/{mcp-DdQ72_AO.js → mcp-CiokQDek.js} +2 -2
  43. package/build/assets/messages-BFJXB6MW.js +36 -0
  44. package/build/assets/model-selector-z_QOzaRV.js +1 -0
  45. package/build/assets/{onboarding-DCL9stdH.js → onboarding-CGUaLHfQ.js} +1 -1
  46. package/build/assets/{path-utils-CNd_jqv_.js → path-utils-0KWEiRs9.js} +1 -1
  47. package/build/assets/{planner-tab-QBnZgIXd.js → planner-tab-CNmJiZ22.js} +1 -1
  48. package/build/assets/{recommended-automations-launcher-B01jchhe.js → recommended-automations-launcher-C1_CKGHa.js} +8 -10
  49. package/build/assets/{root-BBV8Ew9E.js → root-DXsSPxni.js} +2 -2
  50. package/build/assets/root-layout-N4s3RLlj.js +2 -0
  51. package/build/assets/{sdk-section-page-BQKe3asw.js → sdk-section-page-DTyvCc52.js} +1 -1
  52. package/build/assets/{sdk-settings-schema-DoRnefvb.js → sdk-settings-schema-B0KrqqPX.js} +1 -1
  53. package/build/assets/{secrets-settings-D2EfzdpC.js → secrets-settings-BQNSDLKS.js} +1 -1
  54. package/build/assets/{settings-B7jVceyu.js → settings-BUlJrO_h.js} +1 -1
  55. package/build/assets/{settings-dropdown-input-BD7ziSoR.js → settings-dropdown-input-BUk4m23x.js} +1 -1
  56. package/build/assets/{settings-index-Xj0v9Oas.js → settings-index-DE91Eahc.js} +1 -1
  57. package/build/assets/{settings-modal-CDBy1S9S.js → settings-modal-CCaPYVqW.js} +1 -1
  58. package/build/assets/{settings-service.api-CTQ-LpAA.js → settings-service.api-4u2RKC8k.js} +1 -1
  59. package/build/assets/{settings-switch-CSHSqH99.js → settings-switch-BQiAS9ga.js} +1 -1
  60. package/build/assets/{settings-utils-BCbzc6-u.js → settings-utils-chxTa1vn.js} +1 -1
  61. package/build/assets/{shared-conversation-BHEbOdHj.js → shared-conversation-sBPLAawM.js} +1 -1
  62. package/build/assets/{sidebar-mobile-menu-toggle-YYPXGikp.js → sidebar-mobile-menu-toggle-BDXWzhyB.js} +1 -1
  63. package/build/assets/{sidebar-nav-link-CiXbBMQx.js → sidebar-nav-link-Bhlzlhp8.js} +1 -1
  64. package/build/assets/{skill-card-pill-row-BXILn-GK.js → skill-card-pill-row-Bg5joQf6.js} +1 -1
  65. package/build/assets/{skills-plugins-Bs5HiF1O.js → skills-plugins-fihjo1KZ.js} +1 -1
  66. package/build/assets/{skills-settings-CQYxMmWf.js → skills-settings-NQnuMwZP.js} +1 -1
  67. package/build/assets/{styled-tooltip-DEr7oa0m.js → styled-tooltip-GXy1qxsO.js} +1 -1
  68. package/build/assets/{task-list-tab-R9N3Wd-U.js → task-list-tab-Hl9BuVfq.js} +1 -1
  69. package/build/assets/telemetry-BoedM0mF.js +2 -0
  70. package/build/assets/{terminal-BTM3UFcQ.js → terminal-DRwe8--D.js} +1 -1
  71. package/build/assets/{use-active-conversation-BY5F6A1G.js → use-active-conversation-DJGoI9Mc.js} +1 -1
  72. package/build/assets/{use-agent-settings-schema-CsuMq16G.js → use-agent-settings-schema-DtusObuC.js} +1 -1
  73. package/build/assets/{use-agent-state-DX5NKEa_.js → use-agent-state-BXgWhFh6.js} +1 -1
  74. package/build/assets/{use-create-conversation-4iJytCT1.js → use-create-conversation-CzvaVA5A.js} +1 -1
  75. package/build/assets/use-event-store-DSpvASbC.js +1 -0
  76. package/build/assets/{use-get-secrets-BMnFFBUx.js → use-get-secrets-DiLgP147.js} +1 -1
  77. package/build/assets/use-handle-plan-click-CUZwmKIk.js +1 -0
  78. package/build/assets/{use-launch-skill-in-chat-BoqKmEHC.js → use-launch-skill-in-chat-ClRJlIx7.js} +1 -1
  79. package/build/assets/use-runtime-is-ready-CWkGQFsb.js +1 -0
  80. package/build/assets/{use-save-settings-hK6LYt0s.js → use-save-settings-CP23emUY.js} +1 -1
  81. package/build/assets/use-settings-0qFqC-r6.js +1 -0
  82. package/build/assets/{use-settings-nav-items-oZ-BlOWX.js → use-settings-nav-items-C6YxUn4h.js} +1 -1
  83. package/build/assets/{use-task-list-DydbuRFM.js → use-task-list-JPudBRv3.js} +1 -1
  84. package/build/assets/{use-tracking-DQU60djN.js → use-tracking-CjLZgh8X.js} +1 -1
  85. package/build/assets/{use-unified-vscode-url-D2Buvmxj.js → use-unified-vscode-url-DSn2tT08.js} +1 -1
  86. package/build/assets/{use-user-conversation-DwOGM1lc.js → use-user-conversation-CQ5IwnZk.js} +1 -1
  87. package/build/assets/{vendor~browser-3J6WDaAB.js → vendor~browser-Dwwc84Zf.js} +1 -1
  88. package/build/assets/{vendor~browser-tab-DYZ-OmbT.js → vendor~browser-tab-Bhohe29F.js} +1 -1
  89. package/build/assets/{vendor~files-tab-Diy4WrQz.js → vendor~files-tab-B447_Zns.js} +1 -1
  90. package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-CWwn0K2j.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-CQQAW8hY.js} +1 -1
  91. package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-dZ3D8RVL.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DFsI4CLy.js} +1 -1
  92. package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BighOCzm.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DcvlNgbn.js} +1 -1
  93. package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-D13hiNGV.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-ojk_J4bB.js} +1 -1
  94. package/build/assets/{vendor~launch-D65Vw0VZ.js → vendor~launch-BdXJCmwc.js} +1 -1
  95. package/build/assets/{vendor~root-layout~conversation-panel~conversation~shared-conversation-BJPgfJoU.js → vendor~root-layout~conversation-panel~conversation~shared-conversation-DToubnIU.js} +1 -1
  96. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~mcp~~jpfhx3ls-BkicN-14.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~mcp~~jpfhx3ls-zdl_Rltz.js} +2 -2
  97. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~settings~settings-index~agen~jxrvuot9-Cwz6a1DC.js → vendor~root-layout~home~conversation-panel~conversation~launch~settings~settings-index~agen~jxrvuot9-BaCzvZac.js} +1 -1
  98. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~shared-conversation~alert-banner~pl~rqjteh0a-C37jLHRk.js → vendor~root-layout~home~conversation-panel~conversation~shared-conversation~alert-banner~pl~rqjteh0a-BwbkftxT.js} +1 -1
  99. package/build/assets/{vendor~root-layout~home~mcp~automations-list-JQ-neDIa.js → vendor~root-layout~home~mcp~automations-list-CtdIEhjQ.js} +1 -1
  100. package/build/assets/{vendor~root-layout~home~mcp~automations-list-BTTZ58Mb.js → vendor~root-layout~home~mcp~automations-list-DGOI7kQz.js} +1 -1
  101. package/build/assets/{vendor~root-layout~home~mcp~llm-settings~agent-settings~condenser-settings~verification-set~o7tv66sg-UYEKKX0Y.js → vendor~root-layout~home~mcp~llm-settings~agent-settings~condenser-settings~verification-set~o7tv66sg-iPAfRWNQ.js} +2 -2
  102. package/build/assets/{verification-settings-Rabe5TpK.js → verification-settings-Cm02KmeI.js} +1 -1
  103. package/build/assets/{vscode-tab-zLD5Z-PP.js → vscode-tab-AF70Yke0.js} +1 -1
  104. package/build/index.html +4 -4
  105. package/build/locales/ar/openhands.json +1 -1
  106. package/build/locales/ca/openhands.json +1 -1
  107. package/build/locales/de/openhands.json +1 -1
  108. package/build/locales/en/openhands.json +1 -1
  109. package/build/locales/es/openhands.json +1 -1
  110. package/build/locales/fr/openhands.json +1 -1
  111. package/build/locales/it/openhands.json +1 -1
  112. package/build/locales/ja/openhands.json +1 -1
  113. package/build/locales/ko-KR/openhands.json +1 -1
  114. package/build/locales/no/openhands.json +1 -1
  115. package/build/locales/pt/openhands.json +1 -1
  116. package/build/locales/tr/openhands.json +1 -1
  117. package/build/locales/uk/openhands.json +1 -1
  118. package/build/locales/zh-CN/openhands.json +1 -1
  119. package/build/locales/zh-TW/openhands.json +1 -1
  120. package/config/defaults.json +2 -6
  121. package/dist/api/agent-server-adapter.cjs +3 -3
  122. package/dist/api/agent-server-adapter.cjs.map +1 -1
  123. package/dist/api/agent-server-adapter.js +90 -85
  124. package/dist/api/agent-server-adapter.js.map +1 -1
  125. package/dist/api/app-preferences-store.cjs.map +1 -1
  126. package/dist/api/app-preferences-store.d.ts +6 -2
  127. package/dist/api/app-preferences-store.js.map +1 -1
  128. package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
  129. package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
  130. package/dist/api/mcp-service/mcp-service.api.js +19 -14
  131. package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
  132. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.cjs +1 -1
  133. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.cjs.map +1 -1
  134. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.js +9 -9
  135. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.js.map +1 -1
  136. package/dist/components/conversation-events/chat/event-message.cjs +1 -1
  137. package/dist/components/conversation-events/chat/event-message.cjs.map +1 -1
  138. package/dist/components/conversation-events/chat/event-message.js +80 -71
  139. package/dist/components/conversation-events/chat/event-message.js.map +1 -1
  140. package/dist/components/features/automations/recommended-automations-launcher.d.ts +7 -1
  141. package/dist/components/features/home/workspace-selection-form.d.ts +1 -0
  142. package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
  143. package/dist/components/features/mcp-page/custom-server-editor.cjs.map +1 -1
  144. package/dist/components/features/mcp-page/custom-server-editor.js +63 -62
  145. package/dist/components/features/mcp-page/custom-server-editor.js.map +1 -1
  146. package/dist/components/features/onboarding/steps/setup-llm-step.d.ts +8 -0
  147. package/dist/components/features/sidebar/sidebar.cjs +1 -1
  148. package/dist/components/features/sidebar/sidebar.js +6 -6
  149. package/dist/components/features/skills/extensions-navigation.cjs +1 -1
  150. package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
  151. package/dist/components/features/skills/extensions-navigation.d.ts +1 -1
  152. package/dist/components/features/skills/extensions-navigation.js +27 -29
  153. package/dist/components/features/skills/extensions-navigation.js.map +1 -1
  154. package/dist/i18n/translation.cjs +1 -1
  155. package/dist/i18n/translation.cjs.map +1 -1
  156. package/dist/i18n/translation.js +15 -15
  157. package/dist/i18n/translation.js.map +1 -1
  158. package/dist/locales/ar/openhands.json +1 -1
  159. package/dist/locales/ca/openhands.json +1 -1
  160. package/dist/locales/de/openhands.json +1 -1
  161. package/dist/locales/en/openhands.json +1 -1
  162. package/dist/locales/es/openhands.json +1 -1
  163. package/dist/locales/fr/openhands.json +1 -1
  164. package/dist/locales/it/openhands.json +1 -1
  165. package/dist/locales/ja/openhands.json +1 -1
  166. package/dist/locales/ko-KR/openhands.json +1 -1
  167. package/dist/locales/no/openhands.json +1 -1
  168. package/dist/locales/pt/openhands.json +1 -1
  169. package/dist/locales/tr/openhands.json +1 -1
  170. package/dist/locales/uk/openhands.json +1 -1
  171. package/dist/locales/zh-CN/openhands.json +1 -1
  172. package/dist/locales/zh-TW/openhands.json +1 -1
  173. package/dist/node_modules/@openhands/typescript-client/dist/models/acp.cjs +1 -1
  174. package/dist/node_modules/@openhands/typescript-client/dist/models/acp.cjs.map +1 -1
  175. package/dist/node_modules/@openhands/typescript-client/dist/models/acp.js +10 -1
  176. package/dist/node_modules/@openhands/typescript-client/dist/models/acp.js.map +1 -1
  177. package/dist/package.cjs +1 -1
  178. package/dist/package.cjs.map +1 -1
  179. package/dist/package.js +5 -3
  180. package/dist/package.js.map +1 -1
  181. package/dist/routes/llm-settings.cjs +1 -1
  182. package/dist/routes/llm-settings.cjs.map +1 -1
  183. package/dist/routes/llm-settings.js +21 -21
  184. package/dist/routes/llm-settings.js.map +1 -1
  185. package/dist/types/agent-server/core/events/index.d.ts +1 -0
  186. package/dist/types/agent-server/core/events/streaming-delta-event.d.ts +7 -0
  187. package/dist/types/agent-server/core/openhands-event.d.ts +2 -2
  188. package/dist/types/agent-server/type-guards.cjs +1 -1
  189. package/dist/types/agent-server/type-guards.cjs.map +1 -1
  190. package/dist/types/agent-server/type-guards.d.ts +2 -0
  191. package/dist/types/agent-server/type-guards.js +3 -3
  192. package/dist/types/agent-server/type-guards.js.map +1 -1
  193. package/dist/utils/handle-event-for-ui.cjs +1 -1
  194. package/dist/utils/handle-event-for-ui.cjs.map +1 -1
  195. package/dist/utils/handle-event-for-ui.js +69 -13
  196. package/dist/utils/handle-event-for-ui.js.map +1 -1
  197. package/dist/utils/mcp-config.cjs +1 -1
  198. package/dist/utils/mcp-config.cjs.map +1 -1
  199. package/dist/utils/mcp-config.js +27 -19
  200. package/dist/utils/mcp-config.js.map +1 -1
  201. package/dist/utils/mcp-marketplace-utils.cjs +1 -1
  202. package/dist/utils/mcp-marketplace-utils.cjs.map +1 -1
  203. package/dist/utils/mcp-marketplace-utils.js +38 -18
  204. package/dist/utils/mcp-marketplace-utils.js.map +1 -1
  205. package/dist/utils/normalize-display-model.cjs +1 -1
  206. package/dist/utils/normalize-display-model.cjs.map +1 -1
  207. package/dist/utils/normalize-display-model.js +8 -7
  208. package/dist/utils/normalize-display-model.js.map +1 -1
  209. package/dist/utils/openhands-llm.cjs +1 -1
  210. package/dist/utils/openhands-llm.cjs.map +1 -1
  211. package/dist/utils/openhands-llm.d.ts +13 -0
  212. package/dist/utils/openhands-llm.js +9 -3
  213. package/dist/utils/openhands-llm.js.map +1 -1
  214. package/package.json +5 -3
  215. package/scripts/check-sdk-version-sync.mjs +6 -6
  216. package/scripts/dev-safe.mjs +83 -124
  217. package/scripts/dev-with-automation.mjs +83 -5
  218. package/scripts/logger.mjs +77 -0
  219. package/scripts/runtime-services-info.mjs +199 -0
  220. package/scripts/static-server.mjs +42 -4
  221. package/build/assets/acp-providers-DZEi8wDz.js +0 -1
  222. package/build/assets/agent-server-conversation-service.api-B82pNNTm.js +0 -5
  223. package/build/assets/browser-DTei6kki.js +0 -5
  224. package/build/assets/chat-send-button-06dIuWXm.js +0 -1
  225. package/build/assets/conversation-CBlJiDaV.js +0 -19
  226. package/build/assets/conversation-Dss8XCN_.js +0 -1
  227. package/build/assets/conversation-panel-B5sVpsz5.js +0 -1
  228. package/build/assets/conversation-service.api-B4s-xIOK.js +0 -1
  229. package/build/assets/conversation-store-kHcewy1E.js +0 -1
  230. package/build/assets/conversation-websocket-context-C2yKCqvj.js +0 -3
  231. package/build/assets/extensions-navigation-oOk5yl8X.js +0 -1
  232. package/build/assets/home-ChuA06Hv.js +0 -1
  233. package/build/assets/install-server-modal--lZ1HSHB.js +0 -1
  234. package/build/assets/llm-settings-D477P0Lg.js +0 -1
  235. package/build/assets/llm-settings-DtlQ7i4C.js +0 -1
  236. package/build/assets/manifest-17af0b17.js +0 -1
  237. package/build/assets/messages-luW9zf1w.js +0 -36
  238. package/build/assets/middleware-B5rcobhi.js +0 -6
  239. package/build/assets/model-selector-DzQRgNGZ.js +0 -1
  240. package/build/assets/root-layout-pQASEqtQ.js +0 -2
  241. package/build/assets/sidebar-store-B76R2gP8.js +0 -1
  242. package/build/assets/telemetry-DCrd7gnV.js +0 -2
  243. package/build/assets/use-event-store-Rw1YbvLm.js +0 -1
  244. package/build/assets/use-handle-plan-click-DYd5a6zN.js +0 -1
  245. package/build/assets/use-runtime-is-ready-DP-KKHO6.js +0 -1
  246. package/build/assets/use-settings-Clf0Y_P3.js +0 -1
  247. /package/build/assets/{automation-LZB0MjdV.js → automation-BzmydDjr.js} +0 -0
  248. /package/build/assets/{browser-store-BjhV_9wS.js → browser-store-C5uQbbIi.js} +0 -0
  249. /package/build/assets/{checkmark-BB7QCG5T.js → checkmark-SEZPnU2I.js} +0 -0
  250. /package/build/assets/{chevron-left-small-CuuwpRi9.js → chevron-left-small-x9_-ucHG.js} +0 -0
  251. /package/build/assets/{close-Cz0OAgTy.js → close-CbOsKMRg.js} +0 -0
  252. /package/build/assets/{code-tag-Cz9AIz-X.js → code-tag-C0vR_IQH.js} +0 -0
  253. /package/build/assets/{command-store-DAd3K0d_.js → command-store-BUWgE-vZ.js} +0 -0
  254. /package/build/assets/{confirmation-modal-C_lds1Tb.js → confirmation-modal-BPgWqWRI.js} +0 -0
  255. /package/build/assets/{context-menu-list-item-DhG1Ln5m.js → context-menu-list-item-CHWCx1Mc.js} +0 -0
  256. /package/build/assets/{conversation-state-store-BUU90dVq.js → conversation-state-store-DpgQaK_O.js} +0 -0
  257. /package/build/assets/{conversation-tab-empty-state-5bW9CQke.js → conversation-tab-empty-state-Ba5hbJhn.js} +0 -0
  258. /package/build/assets/{copy-CA1Dblua.js → copy-CAxUvM-U.js} +0 -0
  259. /package/build/assets/{dist-CBUfAk0Z.js → dist-CeJSjcAI.js} +0 -0
  260. /package/build/assets/{ellipsis-button-DRRmCrWi.js → ellipsis-button-CiLx8dqc.js} +0 -0
  261. /package/build/assets/{environment-switch-overlay-BrHKX6_Z.js → environment-switch-overlay-Cow6h62p.js} +0 -0
  262. /package/build/assets/{file-DM0ihEsO.js → file-BJCSojij.js} +0 -0
  263. /package/build/assets/{files-tab-store-QlUCuW8b.js → files-tab-store-CZAEwv3x.js} +0 -0
  264. /package/build/assets/{folder-UGYUKpqb.js → folder-wShAU0y7.js} +0 -0
  265. /package/build/assets/{git-status-mapper-N4-7eaeC.js → git-status-mapper-C3rfzUex.js} +0 -0
  266. /package/build/assets/{globe-2otpEmVh.js → globe-CQ_5xwpo.js} +0 -0
  267. /package/build/assets/{handle-capture-consent-OitMkDHc.js → handle-capture-consent-DDnXMC9Y.js} +0 -0
  268. /package/build/assets/{iconBase-B_5IRYeZ.js → iconBase-1A_WRQ4E.js} +0 -0
  269. /package/build/assets/{lesson-plan-5O2tVbD1.js → lesson-plan-B607buca.js} +0 -0
  270. /package/build/assets/{link-external-kU6aFXU6.js → link-external-DCsHkAj4.js} +0 -0
  271. /package/build/assets/{map-provider-BHow6ugd.js → map-provider-XSFHmdDs.js} +0 -0
  272. /package/build/assets/{modal-close-button-BCvw9IUN.js → modal-close-button-DY-rVmld.js} +0 -0
  273. /package/build/assets/{plan-components-BRiIX8Wn.js → plan-components-DsiDjcDi.js} +0 -0
  274. /package/build/assets/{sdk-settings-field-metadata-CtO73dY6.js → sdk-settings-field-metadata-CETNItbo.js} +0 -0
  275. /package/build/assets/{search-Cbh-hHBu.js → search-BqXT2Ied.js} +0 -0
  276. /package/build/assets/{secrets-service-DEIB-Cfk.js → secrets-service-rJqZtDmI.js} +0 -0
  277. /package/build/assets/{settings-KgLvVrSm.js → settings-BgL2HUsU.js} +0 -0
  278. /package/build/assets/{settings-gear-xGs_SPgZ.js → settings-gear-DFmoMp-6.js} +0 -0
  279. /package/build/assets/{settings-input-CPr7vX81.js → settings-input-DsoZj8Dm.js} +0 -0
  280. /package/build/assets/{settings-like-page-layout-classes-GknosJgv.js → settings-like-page-layout-classes-DENKlZpD.js} +0 -0
  281. /package/build/assets/{settings-list-classes-CYDn4jUg.js → settings-list-classes-D8VAVZmi.js} +0 -0
  282. /package/build/assets/{settings-section-header-context-aD2iq1gD.js → settings-section-header-context-D61smD-W.js} +0 -0
  283. /package/build/assets/{skills-CCaEu1KQ.js → skills-BDOWVle-.js} +0 -0
  284. /package/build/assets/{switch-skeleton-C87Tx3Tc.js → switch-skeleton-QpdcdxRP.js} +0 -0
  285. /package/build/assets/{terminal-DQJ6IJUd.js → terminal-BUww3Ssl.js} +0 -0
  286. /package/build/assets/{toggle-switch-C-7juZ1u.js → toggle-switch-DDr-DnEc.js} +0 -0
  287. /package/build/assets/{typography-U1gkzkXo.js → typography-Cx7uw7z3.js} +0 -0
  288. /package/build/assets/{u-check-circle-lbkXL2z4.js → u-check-circle-CftRwky1.js} +0 -0
  289. /package/build/assets/{u-check-circle-half-CirnoxXG.js → u-check-circle-half-sGVk0BtL.js} +0 -0
  290. /package/build/assets/{u-circuit-Danff2ks.js → u-circuit-Cg9tH5qb.js} +0 -0
  291. /package/build/assets/{u-edit-CH5nNya1.js → u-edit-foF02hwH.js} +0 -0
  292. /package/build/assets/{use-breakpoint-2sN462wJ.js → use-breakpoint-Dt2knceC.js} +0 -0
  293. /package/build/assets/{use-click-outside-element-_vianyPb.js → use-click-outside-element-Bu2A3s59.js} +0 -0
  294. /package/build/assets/{use-is-authed-DrocXcet.js → use-is-authed-fNsj-Adj.js} +0 -0
  295. /package/build/assets/{use-llm-profiles-BhZRf-NX.js → use-llm-profiles-CyNVoVqm.js} +0 -0
  296. /package/build/assets/{use-skills-v8pQ02ze.js → use-skills-BWHATXK-.js} +0 -0
  297. /package/build/assets/{v4-BMWDcIWQ.js → v4-BygpdDmc.js} +0 -0
  298. /package/build/assets/{vendor~browser-C3GKF4mj.js → vendor~browser-BYEwwJqV.js} +0 -0
  299. /package/build/assets/{vendor~conversation-panel~conversation~alert-banner-DMcFTqbt.js → vendor~conversation-panel~conversation~alert-banner-BnHToS5O.js} +0 -0
  300. /package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-Cntsv2EN.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-B4oeCCli.js} +0 -0
  301. /package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DTosGXG7.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-D8cqyq4k.js} +0 -0
  302. /package/build/assets/{vendor~terminal-CnKZILnC.js → vendor~terminal-aeP3PnKf.js} +0 -0
  303. /package/build/assets/{vscode-url-helper-CwQPl6QN.js → vscode-url-helper-DOCkV_-G.js} +0 -0
  304. /package/build/assets/{waiting-for-runtime-message-B1Dzhtj5.js → waiting-for-runtime-message-Bg27u9JB.js} +0 -0
  305. /package/build/assets/{x-mark-CmcVOTk2.js → x-mark-Cn-YJVbN.js} +0 -0
@@ -1,114 +1,123 @@
1
1
  import { AgentState as e } from "../../../types/agent-state.js";
2
2
  import { useConversationStore as t } from "../../../stores/conversation-store.js";
3
- import { isACPToolCallEvent as n, isActionEvent as r, isAgentErrorEvent as i, isHookExecutionEvent as a, isObservationEvent as o, isPlanningFileEditorObservationEvent as s, isUserMessageEvent as c } from "../../../types/agent-server/type-guards.js";
4
- import { useAgentState as l } from "../../../hooks/use-agent-state.js";
5
- import { useConfig as u } from "../../../hooks/query/use-config.js";
6
- import { PlanPreview as d } from "../../features/chat/plan-preview.js";
7
- import { ErrorEventMessage as f } from "./event-message-components/error-event-message.js";
8
- import { UserAssistantEventMessage as p } from "./event-message-components/user-assistant-event-message.js";
9
- import { createSkillReadyEvent as m } from "./event-content-helpers/create-skill-ready-event.js";
10
- import { FinishEventMessage as h } from "./event-message-components/finish-event-message.js";
11
- import { GenericEventMessageWrapper as g } from "./event-message-components/generic-event-message-wrapper.js";
12
- import { ThoughtEventMessage as _ } from "./event-message-components/thought-event-message.js";
13
- import { CollapsibleThinking as v } from "./event-message-components/collapsible-thinking.js";
14
- import { HookExecutionEventMessage as y } from "../../shared/hook-execution-event-message.js";
3
+ import { isACPToolCallEvent as n, isActionEvent as r, isAgentErrorEvent as i, isHookExecutionEvent as a, isObservationEvent as o, isPlanningFileEditorObservationEvent as s, isStreamingDeltaEvent as c, isUserMessageEvent as l } from "../../../types/agent-server/type-guards.js";
4
+ import { useAgentState as u } from "../../../hooks/use-agent-state.js";
5
+ import { useConfig as d } from "../../../hooks/query/use-config.js";
6
+ import { ChatMessage as f } from "../../features/chat/chat-message.js";
7
+ import { PlanPreview as p } from "../../features/chat/plan-preview.js";
8
+ import { ErrorEventMessage as m } from "./event-message-components/error-event-message.js";
9
+ import { UserAssistantEventMessage as h } from "./event-message-components/user-assistant-event-message.js";
10
+ import { createSkillReadyEvent as g } from "./event-content-helpers/create-skill-ready-event.js";
11
+ import { FinishEventMessage as _ } from "./event-message-components/finish-event-message.js";
12
+ import { GenericEventMessageWrapper as v } from "./event-message-components/generic-event-message-wrapper.js";
13
+ import { ThoughtEventMessage as y } from "./event-message-components/thought-event-message.js";
14
+ import { CollapsibleThinking as b } from "./event-message-components/collapsible-thinking.js";
15
+ import { HookExecutionEventMessage as x } from "../../shared/hook-execution-event-message.js";
15
16
  import "./event-message-components/hook-execution-event-message.js";
16
- import { shouldShowPlanPreview as b } from "./hooks/use-plan-preview-events.js";
17
- import { getReasoningContent as x } from "./event-thought-helpers.js";
17
+ import { shouldShowPlanPreview as S } from "./hooks/use-plan-preview-events.js";
18
+ import { getReasoningContent as C } from "./event-thought-helpers.js";
18
19
  import "react";
19
- import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
20
+ import { Fragment as w, jsx as T, jsxs as E } from "react/jsx-runtime";
20
21
  //#region src/components/conversation-events/chat/event-message.tsx
21
- var T = (e) => e.activated_skills || e.activated_microagents || [], E = (e) => !e || e.length === 0 ? !1 : e.some((e) => e.type === "text" && e.text.trim().length > 0), D = (e) => {
22
- let t = T(e).length > 0, n = E(e.extended_content);
22
+ var D = (e) => e.activated_skills || e.activated_microagents || [], O = (e) => !e || e.length === 0 ? !1 : e.some((e) => e.type === "text" && e.text.trim().length > 0), k = (e) => {
23
+ let t = D(e).length > 0, n = O(e.extended_content);
23
24
  return t && n;
24
- }, O = (e, t, n) => {
25
+ }, A = (e, t, n) => {
25
26
  try {
26
- let r = m(e);
27
- return /* @__PURE__ */ w(S, { children: [/* @__PURE__ */ C(p, {
27
+ let r = g(e);
28
+ return /* @__PURE__ */ E(w, { children: [/* @__PURE__ */ T(h, {
28
29
  event: e,
29
30
  isLastMessage: !1,
30
31
  isFromPlanningAgent: t.isFromPlanningAgent
31
- }), /* @__PURE__ */ C(g, {
32
+ }), /* @__PURE__ */ T(v, {
32
33
  event: r,
33
34
  isLastMessage: n
34
35
  })] });
35
36
  } catch {
36
- return /* @__PURE__ */ C(p, {
37
+ return /* @__PURE__ */ T(h, {
37
38
  event: e,
38
39
  isLastMessage: n,
39
40
  isFromPlanningAgent: t.isFromPlanningAgent
40
41
  });
41
42
  }
42
43
  };
43
- function k({ event: m, messages: T, isLastMessage: E, isInLast10Actions: k, planPreviewEventIds: A, suppressThought: j = !1 }) {
44
- let { data: M } = u(), { planContent: N } = t(), { curAgentState: P } = l(), F = P === e.RUNNING || P === e.LOADING, I = m.isFromPlanningAgent || !1, L = {
45
- isLastMessage: E,
46
- isInLast10Actions: k,
47
- config: M,
48
- isFromPlanningAgent: I
44
+ function j({ event: g, messages: D, isLastMessage: O, isInLast10Actions: j, planPreviewEventIds: M, suppressThought: N = !1 }) {
45
+ let { data: P } = d(), { planContent: F } = t(), { curAgentState: I } = u(), L = I === e.RUNNING || I === e.LOADING, R = g.isFromPlanningAgent || !1, z = {
46
+ isLastMessage: O,
47
+ isInLast10Actions: j,
48
+ config: P,
49
+ isFromPlanningAgent: R
49
50
  };
50
- if (i(m)) return /* @__PURE__ */ C(f, {
51
- event: m,
52
- ...L
51
+ if (i(g)) return /* @__PURE__ */ T(m, {
52
+ event: g,
53
+ ...z
53
54
  });
54
- if (a(m)) return /* @__PURE__ */ C(y, { event: m });
55
- if (n(m)) return /* @__PURE__ */ C(g, {
56
- event: m,
57
- isLastMessage: E
55
+ if (a(g)) return /* @__PURE__ */ T(x, { event: g });
56
+ if (n(g)) return /* @__PURE__ */ T(v, {
57
+ event: g,
58
+ isLastMessage: O
58
59
  });
59
- if (r(m) && m.action.kind === "FinishAction") return /* @__PURE__ */ C(h, {
60
- event: m,
61
- ...L
60
+ if (c(g)) {
61
+ let e = g.content ?? "", t = g.reasoning_content ?? "";
62
+ return /* @__PURE__ */ E(w, { children: [t && /* @__PURE__ */ T(b, { content: t }), e && /* @__PURE__ */ T(f, {
63
+ type: "agent",
64
+ message: e,
65
+ isFromPlanningAgent: R
66
+ })] });
67
+ }
68
+ if (r(g) && g.action.kind === "FinishAction") return /* @__PURE__ */ T(_, {
69
+ event: g,
70
+ ...z
62
71
  });
63
- if (r(m) && m.action.kind === "ThinkAction") return /* @__PURE__ */ C(v, { content: m.action.thought });
64
- if (r(m)) {
65
- let e = x(m);
66
- return /* @__PURE__ */ w(S, { children: [
67
- e && /* @__PURE__ */ C(v, { content: e }),
68
- !j && /* @__PURE__ */ C(_, {
69
- event: m,
70
- isFromPlanningAgent: I
72
+ if (r(g) && g.action.kind === "ThinkAction") return /* @__PURE__ */ T(b, { content: g.action.thought });
73
+ if (r(g)) {
74
+ let e = C(g);
75
+ return /* @__PURE__ */ E(w, { children: [
76
+ e && /* @__PURE__ */ T(b, { content: e }),
77
+ !N && /* @__PURE__ */ T(y, {
78
+ event: g,
79
+ isFromPlanningAgent: R
71
80
  }),
72
- /* @__PURE__ */ C(g, {
73
- event: m,
74
- isLastMessage: E
81
+ /* @__PURE__ */ T(v, {
82
+ event: g,
83
+ isLastMessage: O
75
84
  })
76
85
  ] });
77
86
  }
78
- if (o(m)) {
79
- if (s(m)) return A && b(m.id, A) ? /* @__PURE__ */ C(d, {
80
- planContent: N,
81
- isStreaming: E && P === e.RUNNING,
82
- isBuildDisabled: F
87
+ if (o(g)) {
88
+ if (s(g)) return M && S(g.id, M) ? /* @__PURE__ */ T(p, {
89
+ planContent: F,
90
+ isStreaming: O && I === e.RUNNING,
91
+ isBuildDisabled: L
83
92
  }) : null;
84
- let t = T.find((e) => r(e) && e.id === m.action_id), n = !j && t && r(t) && t.action.kind !== "ThinkAction", i = t && r(t) ? x(t) : "";
85
- return /* @__PURE__ */ w(S, { children: [
86
- i && /* @__PURE__ */ C(v, { content: i }),
87
- n && /* @__PURE__ */ C(_, {
93
+ let t = D.find((e) => r(e) && e.id === g.action_id), n = !N && t && r(t) && t.action.kind !== "ThinkAction", i = t && r(t) ? C(t) : "";
94
+ return /* @__PURE__ */ E(w, { children: [
95
+ i && /* @__PURE__ */ T(b, { content: i }),
96
+ n && /* @__PURE__ */ T(y, {
88
97
  event: t,
89
- isFromPlanningAgent: I
98
+ isFromPlanningAgent: R
90
99
  }),
91
- /* @__PURE__ */ C(g, {
92
- event: m,
93
- isLastMessage: E,
100
+ /* @__PURE__ */ T(v, {
101
+ event: g,
102
+ isLastMessage: O,
94
103
  correspondingAction: t && r(t) ? t : void 0
95
104
  })
96
105
  ] });
97
106
  }
98
- if (!r(m) && !o(m)) {
99
- let e = m;
100
- return c(m) && D(e) ? O(e, L, E) : /* @__PURE__ */ C(p, {
107
+ if (!r(g) && !o(g)) {
108
+ let e = g;
109
+ return l(g) && k(e) ? A(e, z, O) : /* @__PURE__ */ T(h, {
101
110
  event: e,
102
- ...L,
103
- isLastMessage: E
111
+ ...z,
112
+ isLastMessage: O
104
113
  });
105
114
  }
106
- return /* @__PURE__ */ C(g, {
107
- event: m,
108
- isLastMessage: E
115
+ return /* @__PURE__ */ T(v, {
116
+ event: g,
117
+ isLastMessage: O
109
118
  });
110
119
  }
111
120
  //#endregion
112
- export { k as EventMessage };
121
+ export { j as EventMessage };
113
122
 
114
123
  //# sourceMappingURL=event-message.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"event-message.js","names":[],"sources":["../../../../src/components/conversation-events/chat/event-message.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n OpenHandsEvent,\n MessageEvent,\n ActionEvent,\n} from \"#/types/agent-server/core\";\nimport {\n FinishAction,\n ThinkAction,\n} from \"#/types/agent-server/core/base/action\";\nimport {\n isActionEvent,\n isObservationEvent,\n isAgentErrorEvent,\n isUserMessageEvent,\n isPlanningFileEditorObservationEvent,\n isHookExecutionEvent,\n isACPToolCallEvent,\n} from \"#/types/agent-server/type-guards\";\nimport { useConfig } from \"#/hooks/query/use-config\";\nimport { useConversationStore } from \"#/stores/conversation-store\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { AgentState } from \"#/types/agent-state\";\nimport { PlanPreview } from \"../../features/chat/plan-preview\";\nimport { ErrorEventMessage } from \"./event-message-components/error-event-message\";\nimport { UserAssistantEventMessage } from \"./event-message-components/user-assistant-event-message\";\nimport { FinishEventMessage } from \"./event-message-components/finish-event-message\";\nimport { GenericEventMessageWrapper } from \"./event-message-components/generic-event-message-wrapper\";\nimport { ThoughtEventMessage } from \"./event-message-components/thought-event-message\";\nimport { CollapsibleThinking } from \"./event-message-components/collapsible-thinking\";\nimport { HookExecutionEventMessage } from \"./event-message-components/hook-execution-event-message\";\nimport { createSkillReadyEvent } from \"./event-content-helpers/create-skill-ready-event\";\nimport { shouldShowPlanPreview } from \"./hooks/use-plan-preview-events\";\nimport { getReasoningContent } from \"./event-thought-helpers\";\n\ninterface EventMessageProps {\n event: OpenHandsEvent & { isFromPlanningAgent?: boolean };\n messages: OpenHandsEvent[];\n isLastMessage: boolean;\n isInLast10Actions: boolean;\n /** Set of event IDs that should render PlanPreview (one per user message phase) */\n planPreviewEventIds?: Set<string>;\n /**\n * When true, do not render the inline `ThoughtEventMessage` for action /\n * observation events. The caller is expected to render the thought\n * separately (e.g. via a hoisted \"thought\" rendered item) so the message\n * pane and the in-group rendering don't double up on the same content.\n * Has no effect on `ThinkAction`, whose thought IS its action body.\n */\n suppressThought?: boolean;\n}\n\n/**\n * Extracts activated skills from a MessageEvent, supporting both\n * activated_skills and activated_microagents field names.\n */\nconst getActivatedSkills = (event: MessageEvent): string[] =>\n (event as unknown as { activated_skills?: string[] }).activated_skills ||\n event.activated_microagents ||\n [];\n\n/**\n * Checks if extended content contains valid text content.\n */\nconst hasValidExtendedContent = (\n extendedContent: MessageEvent[\"extended_content\"],\n): boolean => {\n if (!extendedContent || extendedContent.length === 0) {\n return false;\n }\n\n return extendedContent.some(\n (content) => content.type === \"text\" && content.text.trim().length > 0,\n );\n};\n\n/**\n * Determines if a Skill Ready event should be displayed for the given message event.\n */\nconst shouldShowSkillReadyEvent = (messageEvent: MessageEvent): boolean => {\n const activatedSkills = getActivatedSkills(messageEvent);\n const hasActivatedSkills = activatedSkills.length > 0;\n const hasExtendedContent = hasValidExtendedContent(\n messageEvent.extended_content,\n );\n\n return hasActivatedSkills && hasExtendedContent;\n};\n\ninterface CommonProps {\n isLastMessage: boolean;\n isInLast10Actions: boolean;\n config: unknown;\n isFromPlanningAgent: boolean;\n}\n\n/**\n * Renders a user message with its corresponding Skill Ready event.\n */\nconst renderUserMessageWithSkillReady = (\n messageEvent: MessageEvent,\n commonProps: CommonProps,\n isLastMessage: boolean,\n): React.ReactElement => {\n try {\n const skillReadyEvent = createSkillReadyEvent(messageEvent);\n return (\n <>\n <UserAssistantEventMessage\n event={messageEvent}\n isLastMessage={false}\n isFromPlanningAgent={commonProps.isFromPlanningAgent}\n />\n <GenericEventMessageWrapper\n event={skillReadyEvent}\n isLastMessage={isLastMessage}\n />\n </>\n );\n } catch (error) {\n // If skill ready event creation fails, just render the user message\n return (\n <UserAssistantEventMessage\n event={messageEvent}\n isLastMessage={isLastMessage}\n isFromPlanningAgent={commonProps.isFromPlanningAgent}\n />\n );\n }\n};\n\nexport function EventMessage({\n event,\n messages,\n isLastMessage,\n isInLast10Actions,\n planPreviewEventIds,\n suppressThought = false,\n}: EventMessageProps) {\n const { data: config } = useConfig();\n const { planContent } = useConversationStore();\n const { curAgentState } = useAgentState();\n\n // Disable Build button while agent is running (streaming)\n const isAgentRunning =\n curAgentState === AgentState.RUNNING ||\n curAgentState === AgentState.LOADING;\n\n // Read isFromPlanningAgent directly from the event object\n const isFromPlanningAgent = event.isFromPlanningAgent || false;\n\n // Common props for components that need them\n const commonProps = {\n isLastMessage,\n isInLast10Actions,\n config,\n isFromPlanningAgent,\n };\n\n // Agent error events\n if (isAgentErrorEvent(event)) {\n return <ErrorEventMessage event={event} {...commonProps} />;\n }\n\n // Hook execution events\n if (isHookExecutionEvent(event)) {\n return <HookExecutionEventMessage event={event} />;\n }\n\n // ACP sub-agent tool call events (Claude Code, Codex, Gemini CLI, …)\n // render through the same generic wrapper used for observation events so\n // the card shape, success indicator and markdown rendering all match.\n if (isACPToolCallEvent(event)) {\n return (\n <GenericEventMessageWrapper event={event} isLastMessage={isLastMessage} />\n );\n }\n\n // Finish actions\n if (isActionEvent(event) && event.action.kind === \"FinishAction\") {\n return (\n <FinishEventMessage\n event={event as ActionEvent<FinishAction>}\n {...commonProps}\n />\n );\n }\n\n // ThinkAction - render the thought inside a collapsible section so it\n // doesn't dominate the chat, especially when the thinking language\n // (usually English) differs from the conversation language.\n if (isActionEvent(event) && event.action.kind === \"ThinkAction\") {\n const thinkAction = event as ActionEvent<ThinkAction>;\n return <CollapsibleThinking content={thinkAction.action.thought} />;\n }\n\n // Action events - render thought + action (will be replaced by thought + observation)\n if (isActionEvent(event)) {\n const reasoningContent = getReasoningContent(event);\n return (\n <>\n {reasoningContent && <CollapsibleThinking content={reasoningContent} />}\n {!suppressThought && (\n <ThoughtEventMessage\n event={event}\n isFromPlanningAgent={isFromPlanningAgent}\n />\n )}\n <GenericEventMessageWrapper\n event={event}\n isLastMessage={isLastMessage}\n />\n </>\n );\n }\n\n // Observation events - find the corresponding action and render thought + observation\n if (isObservationEvent(event)) {\n // Handle PlanningFileEditorObservation specially\n if (isPlanningFileEditorObservationEvent(event)) {\n // Only show PlanPreview if this event is marked as the one to display\n // (last PlanningFileEditorObservation in its phase)\n if (\n planPreviewEventIds &&\n shouldShowPlanPreview(event.id, planPreviewEventIds)\n ) {\n // Show shine effect only if this is the last message AND agent is running\n const isStreaming =\n isLastMessage && curAgentState === AgentState.RUNNING;\n return (\n <PlanPreview\n planContent={planContent}\n isStreaming={isStreaming}\n isBuildDisabled={isAgentRunning}\n />\n );\n }\n // Not the designated preview event for this phase - render nothing\n // This prevents duplicate previews within the same phase\n return null;\n }\n\n // Find the action that this observation is responding to\n const correspondingAction = messages.find(\n (msg) => isActionEvent(msg) && msg.id === event.action_id,\n );\n\n // Skip ThoughtEventMessage for ThinkAction (thought IS the action)\n const shouldShowThought =\n !suppressThought &&\n correspondingAction &&\n isActionEvent(correspondingAction) &&\n correspondingAction.action.kind !== \"ThinkAction\";\n\n const reasoningContent =\n correspondingAction && isActionEvent(correspondingAction)\n ? getReasoningContent(correspondingAction)\n : \"\";\n\n return (\n <>\n {reasoningContent && <CollapsibleThinking content={reasoningContent} />}\n {shouldShowThought && (\n <ThoughtEventMessage\n event={correspondingAction}\n isFromPlanningAgent={isFromPlanningAgent}\n />\n )}\n <GenericEventMessageWrapper\n event={event}\n isLastMessage={isLastMessage}\n correspondingAction={\n correspondingAction && isActionEvent(correspondingAction)\n ? correspondingAction\n : undefined\n }\n />\n </>\n );\n }\n\n // Message events (user and assistant messages)\n if (!isActionEvent(event) && !isObservationEvent(event)) {\n const messageEvent = event as MessageEvent;\n\n // Check if this is a user message that should display a Skill Ready event\n if (isUserMessageEvent(event) && shouldShowSkillReadyEvent(messageEvent)) {\n return renderUserMessageWithSkillReady(\n messageEvent,\n commonProps,\n isLastMessage,\n );\n }\n\n // Render normal message event (user or assistant)\n return (\n <UserAssistantEventMessage\n event={messageEvent}\n {...commonProps}\n isLastMessage={isLastMessage}\n />\n );\n }\n\n // Generic fallback for all other events\n return (\n <GenericEventMessageWrapper event={event} isLastMessage={isLastMessage} />\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"event-message.js","names":[],"sources":["../../../../src/components/conversation-events/chat/event-message.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n OpenHandsEvent,\n MessageEvent,\n ActionEvent,\n} from \"#/types/agent-server/core\";\nimport {\n FinishAction,\n ThinkAction,\n} from \"#/types/agent-server/core/base/action\";\nimport {\n isActionEvent,\n isObservationEvent,\n isAgentErrorEvent,\n isUserMessageEvent,\n isPlanningFileEditorObservationEvent,\n isHookExecutionEvent,\n isACPToolCallEvent,\n isStreamingDeltaEvent,\n} from \"#/types/agent-server/type-guards\";\nimport { useConfig } from \"#/hooks/query/use-config\";\nimport { useConversationStore } from \"#/stores/conversation-store\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { AgentState } from \"#/types/agent-state\";\nimport { ChatMessage } from \"#/components/features/chat/chat-message\";\nimport { PlanPreview } from \"../../features/chat/plan-preview\";\nimport { ErrorEventMessage } from \"./event-message-components/error-event-message\";\nimport { UserAssistantEventMessage } from \"./event-message-components/user-assistant-event-message\";\nimport { FinishEventMessage } from \"./event-message-components/finish-event-message\";\nimport { GenericEventMessageWrapper } from \"./event-message-components/generic-event-message-wrapper\";\nimport { ThoughtEventMessage } from \"./event-message-components/thought-event-message\";\nimport { CollapsibleThinking } from \"./event-message-components/collapsible-thinking\";\nimport { HookExecutionEventMessage } from \"./event-message-components/hook-execution-event-message\";\nimport { createSkillReadyEvent } from \"./event-content-helpers/create-skill-ready-event\";\nimport { shouldShowPlanPreview } from \"./hooks/use-plan-preview-events\";\nimport { getReasoningContent } from \"./event-thought-helpers\";\n\ninterface EventMessageProps {\n event: OpenHandsEvent & { isFromPlanningAgent?: boolean };\n messages: OpenHandsEvent[];\n isLastMessage: boolean;\n isInLast10Actions: boolean;\n /** Set of event IDs that should render PlanPreview (one per user message phase) */\n planPreviewEventIds?: Set<string>;\n /**\n * When true, do not render the inline `ThoughtEventMessage` for action /\n * observation events. The caller is expected to render the thought\n * separately (e.g. via a hoisted \"thought\" rendered item) so the message\n * pane and the in-group rendering don't double up on the same content.\n * Has no effect on `ThinkAction`, whose thought IS its action body.\n */\n suppressThought?: boolean;\n}\n\n/**\n * Extracts activated skills from a MessageEvent, supporting both\n * activated_skills and activated_microagents field names.\n */\nconst getActivatedSkills = (event: MessageEvent): string[] =>\n (event as unknown as { activated_skills?: string[] }).activated_skills ||\n event.activated_microagents ||\n [];\n\n/**\n * Checks if extended content contains valid text content.\n */\nconst hasValidExtendedContent = (\n extendedContent: MessageEvent[\"extended_content\"],\n): boolean => {\n if (!extendedContent || extendedContent.length === 0) {\n return false;\n }\n\n return extendedContent.some(\n (content) => content.type === \"text\" && content.text.trim().length > 0,\n );\n};\n\n/**\n * Determines if a Skill Ready event should be displayed for the given message event.\n */\nconst shouldShowSkillReadyEvent = (messageEvent: MessageEvent): boolean => {\n const activatedSkills = getActivatedSkills(messageEvent);\n const hasActivatedSkills = activatedSkills.length > 0;\n const hasExtendedContent = hasValidExtendedContent(\n messageEvent.extended_content,\n );\n\n return hasActivatedSkills && hasExtendedContent;\n};\n\ninterface CommonProps {\n isLastMessage: boolean;\n isInLast10Actions: boolean;\n config: unknown;\n isFromPlanningAgent: boolean;\n}\n\n/**\n * Renders a user message with its corresponding Skill Ready event.\n */\nconst renderUserMessageWithSkillReady = (\n messageEvent: MessageEvent,\n commonProps: CommonProps,\n isLastMessage: boolean,\n): React.ReactElement => {\n try {\n const skillReadyEvent = createSkillReadyEvent(messageEvent);\n return (\n <>\n <UserAssistantEventMessage\n event={messageEvent}\n isLastMessage={false}\n isFromPlanningAgent={commonProps.isFromPlanningAgent}\n />\n <GenericEventMessageWrapper\n event={skillReadyEvent}\n isLastMessage={isLastMessage}\n />\n </>\n );\n } catch (error) {\n // If skill ready event creation fails, just render the user message\n return (\n <UserAssistantEventMessage\n event={messageEvent}\n isLastMessage={isLastMessage}\n isFromPlanningAgent={commonProps.isFromPlanningAgent}\n />\n );\n }\n};\n\nexport function EventMessage({\n event,\n messages,\n isLastMessage,\n isInLast10Actions,\n planPreviewEventIds,\n suppressThought = false,\n}: EventMessageProps) {\n const { data: config } = useConfig();\n const { planContent } = useConversationStore();\n const { curAgentState } = useAgentState();\n\n // Disable Build button while agent is running (streaming)\n const isAgentRunning =\n curAgentState === AgentState.RUNNING ||\n curAgentState === AgentState.LOADING;\n\n // Read isFromPlanningAgent directly from the event object\n const isFromPlanningAgent = event.isFromPlanningAgent || false;\n\n // Common props for components that need them\n const commonProps = {\n isLastMessage,\n isInLast10Actions,\n config,\n isFromPlanningAgent,\n };\n\n // Agent error events\n if (isAgentErrorEvent(event)) {\n return <ErrorEventMessage event={event} {...commonProps} />;\n }\n\n // Hook execution events\n if (isHookExecutionEvent(event)) {\n return <HookExecutionEventMessage event={event} />;\n }\n\n // ACP sub-agent tool call events (Claude Code, Codex, Gemini CLI, …)\n // render through the same generic wrapper used for observation events so\n // the card shape, success indicator and markdown rendering all match.\n if (isACPToolCallEvent(event)) {\n return (\n <GenericEventMessageWrapper event={event} isLastMessage={isLastMessage} />\n );\n }\n\n if (isStreamingDeltaEvent(event)) {\n const content = event.content ?? \"\";\n const reasoningContent = event.reasoning_content ?? \"\";\n return (\n <>\n {reasoningContent && <CollapsibleThinking content={reasoningContent} />}\n {content && (\n <ChatMessage\n type=\"agent\"\n message={content}\n isFromPlanningAgent={isFromPlanningAgent}\n />\n )}\n </>\n );\n }\n\n // Finish actions\n if (isActionEvent(event) && event.action.kind === \"FinishAction\") {\n return (\n <FinishEventMessage\n event={event as ActionEvent<FinishAction>}\n {...commonProps}\n />\n );\n }\n\n // ThinkAction - render the thought inside a collapsible section so it\n // doesn't dominate the chat, especially when the thinking language\n // (usually English) differs from the conversation language.\n if (isActionEvent(event) && event.action.kind === \"ThinkAction\") {\n const thinkAction = event as ActionEvent<ThinkAction>;\n return <CollapsibleThinking content={thinkAction.action.thought} />;\n }\n\n // Action events - render thought + action (will be replaced by thought + observation)\n if (isActionEvent(event)) {\n const reasoningContent = getReasoningContent(event);\n return (\n <>\n {reasoningContent && <CollapsibleThinking content={reasoningContent} />}\n {!suppressThought && (\n <ThoughtEventMessage\n event={event}\n isFromPlanningAgent={isFromPlanningAgent}\n />\n )}\n <GenericEventMessageWrapper\n event={event}\n isLastMessage={isLastMessage}\n />\n </>\n );\n }\n\n // Observation events - find the corresponding action and render thought + observation\n if (isObservationEvent(event)) {\n // Handle PlanningFileEditorObservation specially\n if (isPlanningFileEditorObservationEvent(event)) {\n // Only show PlanPreview if this event is marked as the one to display\n // (last PlanningFileEditorObservation in its phase)\n if (\n planPreviewEventIds &&\n shouldShowPlanPreview(event.id, planPreviewEventIds)\n ) {\n // Show shine effect only if this is the last message AND agent is running\n const isStreaming =\n isLastMessage && curAgentState === AgentState.RUNNING;\n return (\n <PlanPreview\n planContent={planContent}\n isStreaming={isStreaming}\n isBuildDisabled={isAgentRunning}\n />\n );\n }\n // Not the designated preview event for this phase - render nothing\n // This prevents duplicate previews within the same phase\n return null;\n }\n\n // Find the action that this observation is responding to\n const correspondingAction = messages.find(\n (msg) => isActionEvent(msg) && msg.id === event.action_id,\n );\n\n // Skip ThoughtEventMessage for ThinkAction (thought IS the action)\n const shouldShowThought =\n !suppressThought &&\n correspondingAction &&\n isActionEvent(correspondingAction) &&\n correspondingAction.action.kind !== \"ThinkAction\";\n\n const reasoningContent =\n correspondingAction && isActionEvent(correspondingAction)\n ? getReasoningContent(correspondingAction)\n : \"\";\n\n return (\n <>\n {reasoningContent && <CollapsibleThinking content={reasoningContent} />}\n {shouldShowThought && (\n <ThoughtEventMessage\n event={correspondingAction}\n isFromPlanningAgent={isFromPlanningAgent}\n />\n )}\n <GenericEventMessageWrapper\n event={event}\n isLastMessage={isLastMessage}\n correspondingAction={\n correspondingAction && isActionEvent(correspondingAction)\n ? correspondingAction\n : undefined\n }\n />\n </>\n );\n }\n\n // Message events (user and assistant messages)\n if (!isActionEvent(event) && !isObservationEvent(event)) {\n const messageEvent = event as MessageEvent;\n\n // Check if this is a user message that should display a Skill Ready event\n if (isUserMessageEvent(event) && shouldShowSkillReadyEvent(messageEvent)) {\n return renderUserMessageWithSkillReady(\n messageEvent,\n commonProps,\n isLastMessage,\n );\n }\n\n // Render normal message event (user or assistant)\n return (\n <UserAssistantEventMessage\n event={messageEvent}\n {...commonProps}\n isLastMessage={isLastMessage}\n />\n );\n }\n\n // Generic fallback for all other events\n return (\n <GenericEventMessageWrapper event={event} isLastMessage={isLastMessage} />\n );\n}\n"],"mappings":"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"}
@@ -4,6 +4,12 @@ interface RecommendedAutomationsLauncherProps {
4
4
  /** When true, only the automation card grid scrolls inside its section. */
5
5
  scrollableGrid?: boolean;
6
6
  }
7
- export declare function buildAutomationPrompt(basePrompt: string, backendKind: "local" | "cloud", backendHost?: string): string;
7
+ /**
8
+ * The catalog prompt (or slash command) is passed through as-is.
9
+ * API routing (host, auth) is discovered by the agent at runtime from
10
+ * `<RUNTIME_SERVICES>` in the system prompt — the skills themselves
11
+ * contain the instructions for reading that block.
12
+ */
13
+ export declare function buildAutomationPrompt(basePrompt: string): string;
8
14
  export declare function RecommendedAutomationsLauncher({ query, onLaunched, scrollableGrid, }: RecommendedAutomationsLauncherProps): import("react/jsx-runtime").JSX.Element | null;
9
15
  export {};
@@ -10,5 +10,6 @@ interface WorkspaceSelectionFormProps {
10
10
  */
11
11
  onConfirm?: (workspace: LocalWorkspace) => void;
12
12
  }
13
+ export declare const HOME_SELECTED_WORKSPACE_PATH_KEY = "oh:home-selected-workspace-path";
13
14
  export declare function WorkspaceSelectionForm({ isLoadingSettings, onConfirm, }: WorkspaceSelectionFormProps): import("react/jsx-runtime").JSX.Element;
14
15
  export {};
@@ -1,2 +1,2 @@
1
- const e=require(`../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),n=require(`../../../i18n/declaration.cjs`),r=require(`../../../utils/utils.cjs`),i=require(`../../../utils/custom-toast-handlers.cjs`),a=require(`../../shared/modals/modal-backdrop.cjs`),o=require(`../../../utils/modal-classes.cjs`),s=require(`../../shared/modals/modal-close-button.cjs`),c=require(`../../../utils/retrieve-axios-error-message.cjs`),l=require(`../../shared/modals/confirmation-modal.cjs`),u=require(`../../../hooks/mutation/use-delete-mcp-server.cjs`),d=require(`../../../hooks/mutation/use-add-mcp-server.cjs`),f=require(`../../../hooks/mutation/use-test-mcp-server.cjs`),p=require(`../settings/mcp-settings/mcp-server-form.cjs`),m=require(`../../../hooks/mutation/use-update-mcp-server.cjs`);let h=require(`react`);h=e.__toESM(h,1);let g=require(`react/jsx-runtime`);function _({server:e,existingServers:_,onClose:v}){let{t:y}=t.useTranslation(`openhands`),{mutate:b,isPending:x}=d.useAddMcpServer(),{mutate:S,isPending:C}=m.useUpdateMcpServer(),{mutate:w,isPending:T}=u.useDeleteMcpServer(),{mutate:E,isPending:D,data:O,reset:k}=f.useTestMcpServer(),[A,j]=h.default.useState(!1),M=!!e.id,N=x||C||T,P=N||D||A,F=e=>{switch(e.error_kind){case`timeout`:return y(n.I18nKey.MCP$TEST_ERROR_TIMEOUT);case`connection`:return y(n.I18nKey.MCP$TEST_ERROR_CONNECTION);default:return y(n.I18nKey.MCP$TEST_ERROR_UNKNOWN,{error:e.error})}},I=h.default.useMemo(()=>O?O.ok?{ok:!0,text:y(n.I18nKey.MCP$TEST_SUCCESS,{count:O.tools.length})}:{ok:!1,text:F(O)}:null,[O,y]),L=e=>{i.displayErrorToast(c.retrieveAxiosErrorMessage(e)||y(n.I18nKey.ERROR$GENERIC))};return(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(a.ModalBackdrop,{onClose:P?void 0:v,closeOnEscape:!P,"aria-label":y(M?n.I18nKey.MCP$EDIT_CUSTOM_TITLE:n.I18nKey.MCP$ADD_CUSTOM_TITLE),children:(0,g.jsxs)(`div`,{"data-testid":`mcp-custom-editor`,className:`relative bg-base-secondary p-6 rounded-xl border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[90vh] overflow-y-auto custom-scrollbar`,children:[(0,g.jsx)(s.ModalCloseButton,{onClose:v,testId:`mcp-custom-editor-close`,disabled:P}),(0,g.jsx)(`h2`,{className:r.cn(`mb-4 pr-6`,o.modalTitleLgClassName),children:y(M?n.I18nKey.MCP$EDIT_CUSTOM_TITLE:n.I18nKey.MCP$ADD_CUSTOM_TITLE)}),(0,g.jsx)(p.MCPServerForm,{mode:M?`edit`:`add`,server:M?e:void 0,existingServers:_,onSubmit:t=>{k(),E(t,{onSuccess:n=>{n.ok&&(M?S({serverId:e.id,server:t},{onSuccess:v,onError:L}):b(t,{onSuccess:v,onError:L}))},onError:L})},onCancel:v,onDelete:M?()=>j(!0):void 0,isActionDisabled:N,onTest:e=>{E(e)},isTestPending:D,testMessage:I})]})}),A?(0,g.jsx)(l.ConfirmationModal,{text:y(n.I18nKey.SETTINGS$MCP_CONFIRM_DELETE),onCancel:()=>j(!1),onConfirm:()=>{w(e,{onSuccess:()=>{i.displaySuccessToast(y(n.I18nKey.MCP$REMOVE_SUCCESS)),j(!1),v()},onError:e=>{L(e),j(!1)}})},isConfirming:T}):null]})}exports.CustomServerEditor=_;
1
+ const e=require(`../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),n=require(`../../../i18n/declaration.cjs`),r=require(`../../../utils/utils.cjs`),i=require(`../../../contexts/active-backend-context.cjs`),a=require(`../../../utils/custom-toast-handlers.cjs`),o=require(`../../shared/modals/modal-backdrop.cjs`),s=require(`../../../utils/modal-classes.cjs`),c=require(`../../shared/modals/modal-close-button.cjs`),l=require(`../../../utils/retrieve-axios-error-message.cjs`),u=require(`../../shared/modals/confirmation-modal.cjs`),d=require(`../../../hooks/mutation/use-delete-mcp-server.cjs`),f=require(`../../../hooks/mutation/use-add-mcp-server.cjs`),p=require(`../../../hooks/mutation/use-test-mcp-server.cjs`),m=require(`../settings/mcp-settings/mcp-server-form.cjs`),h=require(`../../../hooks/mutation/use-update-mcp-server.cjs`);let g=require(`react`);g=e.__toESM(g,1);let _=require(`react/jsx-runtime`);function v({server:e,existingServers:v,onClose:y}){let{t:b}=t.useTranslation(`openhands`),{mutate:x,isPending:S}=f.useAddMcpServer(),{mutate:C,isPending:w}=h.useUpdateMcpServer(),{mutate:T,isPending:E}=d.useDeleteMcpServer(),{mutate:D,isPending:O,data:k,reset:A}=p.useTestMcpServer(),[j,M]=g.default.useState(!1),{backend:N}=i.useActiveBackend(),P=N.kind===`cloud`,F=!!e.id,I=S||w||E,L=I||O||j,R=e=>{switch(e.error_kind){case`timeout`:return b(n.I18nKey.MCP$TEST_ERROR_TIMEOUT);case`connection`:return b(n.I18nKey.MCP$TEST_ERROR_CONNECTION);default:return b(n.I18nKey.MCP$TEST_ERROR_UNKNOWN,{error:e.error})}},z=g.default.useMemo(()=>k?k.ok?{ok:!0,text:b(n.I18nKey.MCP$TEST_SUCCESS,{count:k.tools.length})}:{ok:!1,text:R(k)}:null,[k,b]),B=e=>{a.displayErrorToast(l.retrieveAxiosErrorMessage(e)||b(n.I18nKey.ERROR$GENERIC))};return(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(o.ModalBackdrop,{onClose:L?void 0:y,closeOnEscape:!L,"aria-label":b(F?n.I18nKey.MCP$EDIT_CUSTOM_TITLE:n.I18nKey.MCP$ADD_CUSTOM_TITLE),children:(0,_.jsxs)(`div`,{"data-testid":`mcp-custom-editor`,className:`relative bg-base-secondary p-6 rounded-xl border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[90vh] overflow-y-auto custom-scrollbar`,children:[(0,_.jsx)(c.ModalCloseButton,{onClose:y,testId:`mcp-custom-editor-close`,disabled:L}),(0,_.jsx)(`h2`,{className:r.cn(`mb-4 pr-6`,s.modalTitleLgClassName),children:b(F?n.I18nKey.MCP$EDIT_CUSTOM_TITLE:n.I18nKey.MCP$ADD_CUSTOM_TITLE)}),(0,_.jsx)(m.MCPServerForm,{mode:F?`edit`:`add`,server:F?e:void 0,existingServers:v,onSubmit:t=>{A(),D(t,{onSuccess:n=>{n.ok&&(F?C({serverId:e.id,server:t},{onSuccess:y,onError:B}):x(t,{onSuccess:y,onError:B}))},onError:B})},onCancel:y,onDelete:F?()=>M(!0):void 0,isActionDisabled:I,onTest:P?void 0:e=>{D(e)},isTestPending:O,testMessage:P?null:z})]})}),j?(0,_.jsx)(u.ConfirmationModal,{text:b(n.I18nKey.SETTINGS$MCP_CONFIRM_DELETE),onCancel:()=>M(!1),onConfirm:()=>{T(e,{onSuccess:()=>{a.displaySuccessToast(b(n.I18nKey.MCP$REMOVE_SUCCESS)),M(!1),y()},onError:e=>{B(e),M(!1)}})},isConfirming:E}):null]})}exports.CustomServerEditor=v;
2
2
  //# sourceMappingURL=custom-server-editor.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-server-editor.cjs","names":[],"sources":["../../../../src/components/features/mcp-page/custom-server-editor.tsx"],"sourcesContent":["import React from \"react\";\nimport { AxiosError } from \"axios\";\nimport { useTranslation } from \"react-i18next\";\nimport type { MCPTestFailure } from \"@openhands/typescript-client\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalCloseButton } from \"#/components/shared/modals/modal-close-button\";\nimport { ConfirmationModal } from \"#/components/shared/modals/confirmation-modal\";\nimport {\n MCPServerForm,\n type TestMessage,\n} from \"#/components/features/settings/mcp-settings/mcp-server-form\";\nimport { useAddMcpServer } from \"#/hooks/mutation/use-add-mcp-server\";\nimport { useUpdateMcpServer } from \"#/hooks/mutation/use-update-mcp-server\";\nimport { useDeleteMcpServer } from \"#/hooks/mutation/use-delete-mcp-server\";\nimport { useTestMcpServer } from \"#/hooks/mutation/use-test-mcp-server\";\nimport { MCPServerConfig } from \"#/types/mcp-server\";\nimport {\n displayErrorToast,\n displaySuccessToast,\n} from \"#/utils/custom-toast-handlers\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\nimport { cn } from \"#/utils/utils\";\nimport { modalTitleLgClassName } from \"#/utils/modal-classes\";\n\ninterface CustomServerEditorProps {\n server: MCPServerConfig;\n existingServers: MCPServerConfig[];\n onClose: () => void;\n}\n\n/**\n * Modal wrapper around `MCPServerForm` so users can hand-author\n * arbitrary stdio / SSE / SHTTP entries without reaching for raw JSON.\n * An empty `server.id` means \"Add new\".\n */\nexport function CustomServerEditor({\n server,\n existingServers,\n onClose,\n}: CustomServerEditorProps) {\n const { t } = useTranslation(\"openhands\");\n const { mutate: addMcpServer, isPending: isAdding } = useAddMcpServer();\n const { mutate: updateMcpServer, isPending: isUpdating } =\n useUpdateMcpServer();\n const { mutate: deleteMcpServer, isPending: isDeleting } =\n useDeleteMcpServer();\n const {\n mutate: testServer,\n isPending: isTesting,\n data: testResult,\n reset: resetTest,\n } = useTestMcpServer();\n const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);\n\n const isEditing = !!server.id;\n const isPending = isAdding || isUpdating || isDeleting;\n const isDismissBlocked = isPending || isTesting || showDeleteConfirm;\n\n const makeTestErrorMessage = (failure: MCPTestFailure): string => {\n switch (failure.error_kind) {\n case \"timeout\":\n return t(I18nKey.MCP$TEST_ERROR_TIMEOUT);\n case \"connection\":\n return t(I18nKey.MCP$TEST_ERROR_CONNECTION);\n default:\n return t(I18nKey.MCP$TEST_ERROR_UNKNOWN, { error: failure.error });\n }\n };\n\n const testMessage: TestMessage | null = React.useMemo(() => {\n if (!testResult) return null;\n if (testResult.ok) {\n return {\n ok: true,\n text: t(I18nKey.MCP$TEST_SUCCESS, { count: testResult.tools.length }),\n };\n }\n return { ok: false, text: makeTestErrorMessage(testResult) };\n }, [testResult, t]);\n\n // Shared error handler so both add and update surface backend errors\n // as a toast instead of failing silently — previously these calls\n // had no `onError` and the modal closed even on a 4xx/5xx, leaving\n // the user to discover the failure on the next page load.\n const handleError = (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n displayErrorToast(message || t(I18nKey.ERROR$GENERIC));\n };\n\n const handleSubmit = (payload: MCPServerConfig) => {\n resetTest();\n testServer(payload, {\n onSuccess: (result) => {\n if (!result.ok) {\n // Test failed — modal stays open, error shown via testMessage.\n return;\n }\n if (isEditing) {\n updateMcpServer(\n { serverId: server.id, server: payload },\n { onSuccess: onClose, onError: handleError },\n );\n } else {\n addMcpServer(payload, { onSuccess: onClose, onError: handleError });\n }\n },\n onError: handleError,\n });\n };\n\n const handleTestClick = (payload: MCPServerConfig) => {\n testServer(payload);\n };\n\n const handleConfirmDelete = () => {\n deleteMcpServer(server, {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.MCP$REMOVE_SUCCESS));\n setShowDeleteConfirm(false);\n onClose();\n },\n onError: (err) => {\n handleError(err);\n setShowDeleteConfirm(false);\n },\n });\n };\n\n return (\n <>\n <ModalBackdrop\n // Block backdrop-click / Escape from dismissing the modal while\n // a mutation is in flight — closing mid-request would orphan\n // the request and leave the user with no error feedback.\n onClose={isDismissBlocked ? undefined : onClose}\n closeOnEscape={!isDismissBlocked}\n aria-label={\n isEditing\n ? t(I18nKey.MCP$EDIT_CUSTOM_TITLE)\n : t(I18nKey.MCP$ADD_CUSTOM_TITLE)\n }\n >\n <div\n data-testid=\"mcp-custom-editor\"\n className=\"relative bg-base-secondary p-6 rounded-xl border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[90vh] overflow-y-auto custom-scrollbar\"\n >\n <ModalCloseButton\n onClose={onClose}\n testId=\"mcp-custom-editor-close\"\n disabled={isDismissBlocked}\n />\n <h2 className={cn(\"mb-4 pr-6\", modalTitleLgClassName)}>\n {isEditing\n ? t(I18nKey.MCP$EDIT_CUSTOM_TITLE)\n : t(I18nKey.MCP$ADD_CUSTOM_TITLE)}\n </h2>\n <MCPServerForm\n mode={isEditing ? \"edit\" : \"add\"}\n server={isEditing ? server : undefined}\n existingServers={existingServers}\n onSubmit={handleSubmit}\n onCancel={onClose}\n onDelete={isEditing ? () => setShowDeleteConfirm(true) : undefined}\n isActionDisabled={isPending}\n onTest={handleTestClick}\n isTestPending={isTesting}\n testMessage={testMessage}\n />\n </div>\n </ModalBackdrop>\n\n {showDeleteConfirm ? (\n <ConfirmationModal\n text={t(I18nKey.SETTINGS$MCP_CONFIRM_DELETE)}\n onCancel={() => setShowDeleteConfirm(false)}\n onConfirm={handleConfirmDelete}\n isConfirming={isDeleting}\n />\n ) : null}\n </>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"custom-server-editor.cjs","names":[],"sources":["../../../../src/components/features/mcp-page/custom-server-editor.tsx"],"sourcesContent":["import React from \"react\";\nimport { AxiosError } from \"axios\";\nimport { useTranslation } from \"react-i18next\";\nimport type { MCPTestFailure } from \"@openhands/typescript-client\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalCloseButton } from \"#/components/shared/modals/modal-close-button\";\nimport { ConfirmationModal } from \"#/components/shared/modals/confirmation-modal\";\nimport {\n MCPServerForm,\n type TestMessage,\n} from \"#/components/features/settings/mcp-settings/mcp-server-form\";\nimport { useAddMcpServer } from \"#/hooks/mutation/use-add-mcp-server\";\nimport { useUpdateMcpServer } from \"#/hooks/mutation/use-update-mcp-server\";\nimport { useDeleteMcpServer } from \"#/hooks/mutation/use-delete-mcp-server\";\nimport { useTestMcpServer } from \"#/hooks/mutation/use-test-mcp-server\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { MCPServerConfig } from \"#/types/mcp-server\";\nimport {\n displayErrorToast,\n displaySuccessToast,\n} from \"#/utils/custom-toast-handlers\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\nimport { cn } from \"#/utils/utils\";\nimport { modalTitleLgClassName } from \"#/utils/modal-classes\";\n\ninterface CustomServerEditorProps {\n server: MCPServerConfig;\n existingServers: MCPServerConfig[];\n onClose: () => void;\n}\n\n/**\n * Modal wrapper around `MCPServerForm` so users can hand-author\n * arbitrary stdio / SSE / SHTTP entries without reaching for raw JSON.\n * An empty `server.id` means \"Add new\".\n */\nexport function CustomServerEditor({\n server,\n existingServers,\n onClose,\n}: CustomServerEditorProps) {\n const { t } = useTranslation(\"openhands\");\n const { mutate: addMcpServer, isPending: isAdding } = useAddMcpServer();\n const { mutate: updateMcpServer, isPending: isUpdating } =\n useUpdateMcpServer();\n const { mutate: deleteMcpServer, isPending: isDeleting } =\n useDeleteMcpServer();\n const {\n mutate: testServer,\n isPending: isTesting,\n data: testResult,\n reset: resetTest,\n } = useTestMcpServer();\n const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);\n\n // The MCP connectivity-test endpoint only exists on the local agent-server.\n // For cloud backends `McpService.testServer` short-circuits with a synthetic\n // success so the save still completes; we hide the manual \"Test connection\"\n // button here so cloud users aren't shown a misleading \"0 tools\" result.\n const { backend } = useActiveBackend();\n const isCloudBackend = backend.kind === \"cloud\";\n\n const isEditing = !!server.id;\n const isPending = isAdding || isUpdating || isDeleting;\n const isDismissBlocked = isPending || isTesting || showDeleteConfirm;\n\n const makeTestErrorMessage = (failure: MCPTestFailure): string => {\n switch (failure.error_kind) {\n case \"timeout\":\n return t(I18nKey.MCP$TEST_ERROR_TIMEOUT);\n case \"connection\":\n return t(I18nKey.MCP$TEST_ERROR_CONNECTION);\n default:\n return t(I18nKey.MCP$TEST_ERROR_UNKNOWN, { error: failure.error });\n }\n };\n\n const testMessage: TestMessage | null = React.useMemo(() => {\n if (!testResult) return null;\n if (testResult.ok) {\n return {\n ok: true,\n text: t(I18nKey.MCP$TEST_SUCCESS, { count: testResult.tools.length }),\n };\n }\n return { ok: false, text: makeTestErrorMessage(testResult) };\n }, [testResult, t]);\n\n // Shared error handler so both add and update surface backend errors\n // as a toast instead of failing silently — previously these calls\n // had no `onError` and the modal closed even on a 4xx/5xx, leaving\n // the user to discover the failure on the next page load.\n const handleError = (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n displayErrorToast(message || t(I18nKey.ERROR$GENERIC));\n };\n\n const handleSubmit = (payload: MCPServerConfig) => {\n resetTest();\n testServer(payload, {\n onSuccess: (result) => {\n if (!result.ok) {\n // Test failed — modal stays open, error shown via testMessage.\n return;\n }\n if (isEditing) {\n updateMcpServer(\n { serverId: server.id, server: payload },\n { onSuccess: onClose, onError: handleError },\n );\n } else {\n addMcpServer(payload, { onSuccess: onClose, onError: handleError });\n }\n },\n onError: handleError,\n });\n };\n\n const handleTestClick = (payload: MCPServerConfig) => {\n testServer(payload);\n };\n\n const handleConfirmDelete = () => {\n deleteMcpServer(server, {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.MCP$REMOVE_SUCCESS));\n setShowDeleteConfirm(false);\n onClose();\n },\n onError: (err) => {\n handleError(err);\n setShowDeleteConfirm(false);\n },\n });\n };\n\n return (\n <>\n <ModalBackdrop\n // Block backdrop-click / Escape from dismissing the modal while\n // a mutation is in flight — closing mid-request would orphan\n // the request and leave the user with no error feedback.\n onClose={isDismissBlocked ? undefined : onClose}\n closeOnEscape={!isDismissBlocked}\n aria-label={\n isEditing\n ? t(I18nKey.MCP$EDIT_CUSTOM_TITLE)\n : t(I18nKey.MCP$ADD_CUSTOM_TITLE)\n }\n >\n <div\n data-testid=\"mcp-custom-editor\"\n className=\"relative bg-base-secondary p-6 rounded-xl border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[90vh] overflow-y-auto custom-scrollbar\"\n >\n <ModalCloseButton\n onClose={onClose}\n testId=\"mcp-custom-editor-close\"\n disabled={isDismissBlocked}\n />\n <h2 className={cn(\"mb-4 pr-6\", modalTitleLgClassName)}>\n {isEditing\n ? t(I18nKey.MCP$EDIT_CUSTOM_TITLE)\n : t(I18nKey.MCP$ADD_CUSTOM_TITLE)}\n </h2>\n <MCPServerForm\n mode={isEditing ? \"edit\" : \"add\"}\n server={isEditing ? server : undefined}\n existingServers={existingServers}\n onSubmit={handleSubmit}\n onCancel={onClose}\n onDelete={isEditing ? () => setShowDeleteConfirm(true) : undefined}\n isActionDisabled={isPending}\n onTest={isCloudBackend ? undefined : handleTestClick}\n isTestPending={isTesting}\n testMessage={isCloudBackend ? null : testMessage}\n />\n </div>\n </ModalBackdrop>\n\n {showDeleteConfirm ? (\n <ConfirmationModal\n text={t(I18nKey.SETTINGS$MCP_CONFIRM_DELETE)}\n onCancel={() => setShowDeleteConfirm(false)}\n onConfirm={handleConfirmDelete}\n isConfirming={isDeleting}\n />\n ) : null}\n </>\n );\n}\n"],"mappings":"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"}
@@ -1,102 +1,103 @@
1
1
  import { useTranslation as e } from "../../../node_modules/react-i18next/dist/es/useTranslation.js";
2
2
  import { I18nKey as t } from "../../../i18n/declaration.js";
3
3
  import { cn as n } from "../../../utils/utils.js";
4
- import { displayErrorToast as r, displaySuccessToast as i } from "../../../utils/custom-toast-handlers.js";
5
- import { ModalBackdrop as a } from "../../shared/modals/modal-backdrop.js";
6
- import { modalTitleLgClassName as o } from "../../../utils/modal-classes.js";
7
- import { ModalCloseButton as s } from "../../shared/modals/modal-close-button.js";
8
- import { retrieveAxiosErrorMessage as c } from "../../../utils/retrieve-axios-error-message.js";
9
- import { ConfirmationModal as l } from "../../shared/modals/confirmation-modal.js";
10
- import { useDeleteMcpServer as u } from "../../../hooks/mutation/use-delete-mcp-server.js";
11
- import { useAddMcpServer as d } from "../../../hooks/mutation/use-add-mcp-server.js";
12
- import { useTestMcpServer as f } from "../../../hooks/mutation/use-test-mcp-server.js";
13
- import { MCPServerForm as p } from "../settings/mcp-settings/mcp-server-form.js";
14
- import { useUpdateMcpServer as m } from "../../../hooks/mutation/use-update-mcp-server.js";
15
- import h from "react";
16
- import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
4
+ import { useActiveBackend as r } from "../../../contexts/active-backend-context.js";
5
+ import { displayErrorToast as i, displaySuccessToast as a } from "../../../utils/custom-toast-handlers.js";
6
+ import { ModalBackdrop as o } from "../../shared/modals/modal-backdrop.js";
7
+ import { modalTitleLgClassName as s } from "../../../utils/modal-classes.js";
8
+ import { ModalCloseButton as c } from "../../shared/modals/modal-close-button.js";
9
+ import { retrieveAxiosErrorMessage as l } from "../../../utils/retrieve-axios-error-message.js";
10
+ import { ConfirmationModal as u } from "../../shared/modals/confirmation-modal.js";
11
+ import { useDeleteMcpServer as d } from "../../../hooks/mutation/use-delete-mcp-server.js";
12
+ import { useAddMcpServer as f } from "../../../hooks/mutation/use-add-mcp-server.js";
13
+ import { useTestMcpServer as p } from "../../../hooks/mutation/use-test-mcp-server.js";
14
+ import { MCPServerForm as m } from "../settings/mcp-settings/mcp-server-form.js";
15
+ import { useUpdateMcpServer as h } from "../../../hooks/mutation/use-update-mcp-server.js";
16
+ import g from "react";
17
+ import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
17
18
  //#region src/components/features/mcp-page/custom-server-editor.tsx
18
- function y({ server: y, existingServers: b, onClose: x }) {
19
- let { t: S } = e("openhands"), { mutate: C, isPending: w } = d(), { mutate: T, isPending: E } = m(), { mutate: D, isPending: O } = u(), { mutate: k, isPending: A, data: j, reset: M } = f(), [N, P] = h.useState(!1), F = !!y.id, I = w || E || O, L = I || A || N, R = (e) => {
19
+ function b({ server: b, existingServers: x, onClose: S }) {
20
+ let { t: C } = e("openhands"), { mutate: w, isPending: T } = f(), { mutate: E, isPending: D } = h(), { mutate: O, isPending: k } = d(), { mutate: A, isPending: j, data: M, reset: N } = p(), [P, F] = g.useState(!1), { backend: I } = r(), L = I.kind === "cloud", R = !!b.id, z = T || D || k, B = z || j || P, V = (e) => {
20
21
  switch (e.error_kind) {
21
- case "timeout": return S(t.MCP$TEST_ERROR_TIMEOUT);
22
- case "connection": return S(t.MCP$TEST_ERROR_CONNECTION);
23
- default: return S(t.MCP$TEST_ERROR_UNKNOWN, { error: e.error });
22
+ case "timeout": return C(t.MCP$TEST_ERROR_TIMEOUT);
23
+ case "connection": return C(t.MCP$TEST_ERROR_CONNECTION);
24
+ default: return C(t.MCP$TEST_ERROR_UNKNOWN, { error: e.error });
24
25
  }
25
- }, z = h.useMemo(() => j ? j.ok ? {
26
+ }, H = g.useMemo(() => M ? M.ok ? {
26
27
  ok: !0,
27
- text: S(t.MCP$TEST_SUCCESS, { count: j.tools.length })
28
+ text: C(t.MCP$TEST_SUCCESS, { count: M.tools.length })
28
29
  } : {
29
30
  ok: !1,
30
- text: R(j)
31
- } : null, [j, S]), B = (e) => {
32
- r(c(e) || S(t.ERROR$GENERIC));
31
+ text: V(M)
32
+ } : null, [M, C]), U = (e) => {
33
+ i(l(e) || C(t.ERROR$GENERIC));
33
34
  };
34
- return /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _(a, {
35
- onClose: L ? void 0 : x,
36
- closeOnEscape: !L,
37
- "aria-label": S(F ? t.MCP$EDIT_CUSTOM_TITLE : t.MCP$ADD_CUSTOM_TITLE),
38
- children: /* @__PURE__ */ v("div", {
35
+ return /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(o, {
36
+ onClose: B ? void 0 : S,
37
+ closeOnEscape: !B,
38
+ "aria-label": C(R ? t.MCP$EDIT_CUSTOM_TITLE : t.MCP$ADD_CUSTOM_TITLE),
39
+ children: /* @__PURE__ */ y("div", {
39
40
  "data-testid": "mcp-custom-editor",
40
41
  className: "relative bg-base-secondary p-6 rounded-xl border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[90vh] overflow-y-auto custom-scrollbar",
41
42
  children: [
42
- /* @__PURE__ */ _(s, {
43
- onClose: x,
43
+ /* @__PURE__ */ v(c, {
44
+ onClose: S,
44
45
  testId: "mcp-custom-editor-close",
45
- disabled: L
46
+ disabled: B
46
47
  }),
47
- /* @__PURE__ */ _("h2", {
48
- className: n("mb-4 pr-6", o),
49
- children: S(F ? t.MCP$EDIT_CUSTOM_TITLE : t.MCP$ADD_CUSTOM_TITLE)
48
+ /* @__PURE__ */ v("h2", {
49
+ className: n("mb-4 pr-6", s),
50
+ children: C(R ? t.MCP$EDIT_CUSTOM_TITLE : t.MCP$ADD_CUSTOM_TITLE)
50
51
  }),
51
- /* @__PURE__ */ _(p, {
52
- mode: F ? "edit" : "add",
53
- server: F ? y : void 0,
54
- existingServers: b,
52
+ /* @__PURE__ */ v(m, {
53
+ mode: R ? "edit" : "add",
54
+ server: R ? b : void 0,
55
+ existingServers: x,
55
56
  onSubmit: (e) => {
56
- M(), k(e, {
57
+ N(), A(e, {
57
58
  onSuccess: (t) => {
58
- t.ok && (F ? T({
59
- serverId: y.id,
59
+ t.ok && (R ? E({
60
+ serverId: b.id,
60
61
  server: e
61
62
  }, {
62
- onSuccess: x,
63
- onError: B
64
- }) : C(e, {
65
- onSuccess: x,
66
- onError: B
63
+ onSuccess: S,
64
+ onError: U
65
+ }) : w(e, {
66
+ onSuccess: S,
67
+ onError: U
67
68
  }));
68
69
  },
69
- onError: B
70
+ onError: U
70
71
  });
71
72
  },
72
- onCancel: x,
73
- onDelete: F ? () => P(!0) : void 0,
74
- isActionDisabled: I,
75
- onTest: (e) => {
76
- k(e);
73
+ onCancel: S,
74
+ onDelete: R ? () => F(!0) : void 0,
75
+ isActionDisabled: z,
76
+ onTest: L ? void 0 : (e) => {
77
+ A(e);
77
78
  },
78
- isTestPending: A,
79
- testMessage: z
79
+ isTestPending: j,
80
+ testMessage: L ? null : H
80
81
  })
81
82
  ]
82
83
  })
83
- }), N ? /* @__PURE__ */ _(l, {
84
- text: S(t.SETTINGS$MCP_CONFIRM_DELETE),
85
- onCancel: () => P(!1),
84
+ }), P ? /* @__PURE__ */ v(u, {
85
+ text: C(t.SETTINGS$MCP_CONFIRM_DELETE),
86
+ onCancel: () => F(!1),
86
87
  onConfirm: () => {
87
- D(y, {
88
+ O(b, {
88
89
  onSuccess: () => {
89
- i(S(t.MCP$REMOVE_SUCCESS)), P(!1), x();
90
+ a(C(t.MCP$REMOVE_SUCCESS)), F(!1), S();
90
91
  },
91
92
  onError: (e) => {
92
- B(e), P(!1);
93
+ U(e), F(!1);
93
94
  }
94
95
  });
95
96
  },
96
- isConfirming: O
97
+ isConfirming: k
97
98
  }) : null] });
98
99
  }
99
100
  //#endregion
100
- export { y as CustomServerEditor };
101
+ export { b as CustomServerEditor };
101
102
 
102
103
  //# sourceMappingURL=custom-server-editor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-server-editor.js","names":[],"sources":["../../../../src/components/features/mcp-page/custom-server-editor.tsx"],"sourcesContent":["import React from \"react\";\nimport { AxiosError } from \"axios\";\nimport { useTranslation } from \"react-i18next\";\nimport type { MCPTestFailure } from \"@openhands/typescript-client\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalCloseButton } from \"#/components/shared/modals/modal-close-button\";\nimport { ConfirmationModal } from \"#/components/shared/modals/confirmation-modal\";\nimport {\n MCPServerForm,\n type TestMessage,\n} from \"#/components/features/settings/mcp-settings/mcp-server-form\";\nimport { useAddMcpServer } from \"#/hooks/mutation/use-add-mcp-server\";\nimport { useUpdateMcpServer } from \"#/hooks/mutation/use-update-mcp-server\";\nimport { useDeleteMcpServer } from \"#/hooks/mutation/use-delete-mcp-server\";\nimport { useTestMcpServer } from \"#/hooks/mutation/use-test-mcp-server\";\nimport { MCPServerConfig } from \"#/types/mcp-server\";\nimport {\n displayErrorToast,\n displaySuccessToast,\n} from \"#/utils/custom-toast-handlers\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\nimport { cn } from \"#/utils/utils\";\nimport { modalTitleLgClassName } from \"#/utils/modal-classes\";\n\ninterface CustomServerEditorProps {\n server: MCPServerConfig;\n existingServers: MCPServerConfig[];\n onClose: () => void;\n}\n\n/**\n * Modal wrapper around `MCPServerForm` so users can hand-author\n * arbitrary stdio / SSE / SHTTP entries without reaching for raw JSON.\n * An empty `server.id` means \"Add new\".\n */\nexport function CustomServerEditor({\n server,\n existingServers,\n onClose,\n}: CustomServerEditorProps) {\n const { t } = useTranslation(\"openhands\");\n const { mutate: addMcpServer, isPending: isAdding } = useAddMcpServer();\n const { mutate: updateMcpServer, isPending: isUpdating } =\n useUpdateMcpServer();\n const { mutate: deleteMcpServer, isPending: isDeleting } =\n useDeleteMcpServer();\n const {\n mutate: testServer,\n isPending: isTesting,\n data: testResult,\n reset: resetTest,\n } = useTestMcpServer();\n const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);\n\n const isEditing = !!server.id;\n const isPending = isAdding || isUpdating || isDeleting;\n const isDismissBlocked = isPending || isTesting || showDeleteConfirm;\n\n const makeTestErrorMessage = (failure: MCPTestFailure): string => {\n switch (failure.error_kind) {\n case \"timeout\":\n return t(I18nKey.MCP$TEST_ERROR_TIMEOUT);\n case \"connection\":\n return t(I18nKey.MCP$TEST_ERROR_CONNECTION);\n default:\n return t(I18nKey.MCP$TEST_ERROR_UNKNOWN, { error: failure.error });\n }\n };\n\n const testMessage: TestMessage | null = React.useMemo(() => {\n if (!testResult) return null;\n if (testResult.ok) {\n return {\n ok: true,\n text: t(I18nKey.MCP$TEST_SUCCESS, { count: testResult.tools.length }),\n };\n }\n return { ok: false, text: makeTestErrorMessage(testResult) };\n }, [testResult, t]);\n\n // Shared error handler so both add and update surface backend errors\n // as a toast instead of failing silently — previously these calls\n // had no `onError` and the modal closed even on a 4xx/5xx, leaving\n // the user to discover the failure on the next page load.\n const handleError = (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n displayErrorToast(message || t(I18nKey.ERROR$GENERIC));\n };\n\n const handleSubmit = (payload: MCPServerConfig) => {\n resetTest();\n testServer(payload, {\n onSuccess: (result) => {\n if (!result.ok) {\n // Test failed — modal stays open, error shown via testMessage.\n return;\n }\n if (isEditing) {\n updateMcpServer(\n { serverId: server.id, server: payload },\n { onSuccess: onClose, onError: handleError },\n );\n } else {\n addMcpServer(payload, { onSuccess: onClose, onError: handleError });\n }\n },\n onError: handleError,\n });\n };\n\n const handleTestClick = (payload: MCPServerConfig) => {\n testServer(payload);\n };\n\n const handleConfirmDelete = () => {\n deleteMcpServer(server, {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.MCP$REMOVE_SUCCESS));\n setShowDeleteConfirm(false);\n onClose();\n },\n onError: (err) => {\n handleError(err);\n setShowDeleteConfirm(false);\n },\n });\n };\n\n return (\n <>\n <ModalBackdrop\n // Block backdrop-click / Escape from dismissing the modal while\n // a mutation is in flight — closing mid-request would orphan\n // the request and leave the user with no error feedback.\n onClose={isDismissBlocked ? undefined : onClose}\n closeOnEscape={!isDismissBlocked}\n aria-label={\n isEditing\n ? t(I18nKey.MCP$EDIT_CUSTOM_TITLE)\n : t(I18nKey.MCP$ADD_CUSTOM_TITLE)\n }\n >\n <div\n data-testid=\"mcp-custom-editor\"\n className=\"relative bg-base-secondary p-6 rounded-xl border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[90vh] overflow-y-auto custom-scrollbar\"\n >\n <ModalCloseButton\n onClose={onClose}\n testId=\"mcp-custom-editor-close\"\n disabled={isDismissBlocked}\n />\n <h2 className={cn(\"mb-4 pr-6\", modalTitleLgClassName)}>\n {isEditing\n ? t(I18nKey.MCP$EDIT_CUSTOM_TITLE)\n : t(I18nKey.MCP$ADD_CUSTOM_TITLE)}\n </h2>\n <MCPServerForm\n mode={isEditing ? \"edit\" : \"add\"}\n server={isEditing ? server : undefined}\n existingServers={existingServers}\n onSubmit={handleSubmit}\n onCancel={onClose}\n onDelete={isEditing ? () => setShowDeleteConfirm(true) : undefined}\n isActionDisabled={isPending}\n onTest={handleTestClick}\n isTestPending={isTesting}\n testMessage={testMessage}\n />\n </div>\n </ModalBackdrop>\n\n {showDeleteConfirm ? (\n <ConfirmationModal\n text={t(I18nKey.SETTINGS$MCP_CONFIRM_DELETE)}\n onCancel={() => setShowDeleteConfirm(false)}\n onConfirm={handleConfirmDelete}\n isConfirming={isDeleting}\n />\n ) : null}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoCA,SAAgB,EAAmB,EACjC,WACA,oBACA,cAC0B;CAC1B,IAAM,EAAE,SAAM,EAAe,YAAY,EACnC,EAAE,QAAQ,GAAc,WAAW,MAAa,GAAiB,EACjE,EAAE,QAAQ,GAAiB,WAAW,MAC1C,GAAoB,EAChB,EAAE,QAAQ,GAAiB,WAAW,MAC1C,GAAoB,EAChB,EACJ,QAAQ,GACR,WAAW,GACX,MAAM,GACN,OAAO,MACL,GAAkB,EAChB,CAAC,GAAmB,KAAwB,EAAM,SAAS,GAAM,EAEjE,IAAY,CAAC,CAAC,EAAO,IACrB,IAAY,KAAY,KAAc,GACtC,IAAmB,KAAa,KAAa,GAE7C,KAAwB,MAAoC;AAChE,UAAQ,EAAQ,YAAhB;GACE,KAAK,UACH,QAAO,EAAE,EAAQ,uBAAuB;GAC1C,KAAK,aACH,QAAO,EAAE,EAAQ,0BAA0B;GAC7C,QACE,QAAO,EAAE,EAAQ,wBAAwB,EAAE,OAAO,EAAQ,OAAO,CAAC;;IAIlE,IAAkC,EAAM,cACvC,IACD,EAAW,KACN;EACL,IAAI;EACJ,MAAM,EAAE,EAAQ,kBAAkB,EAAE,OAAO,EAAW,MAAM,QAAQ,CAAC;EACtE,GAEI;EAAE,IAAI;EAAO,MAAM,EAAqB,EAAW;EAAE,GAPpC,MAQvB,CAAC,GAAY,EAAE,CAAC,EAMb,KAAe,MAAiB;AAEpC,IADgB,EAA0B,EACxB,IAAW,EAAE,EAAQ,cAAc,CAAC;;AA0CxD,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EAIE,SAAS,IAAmB,KAAA,IAAY;EACxC,eAAe,CAAC;EAChB,cAEM,EADJ,IACM,EAAQ,wBACR,EAAQ,qBAAqB;YAGrC,kBAAC,OAAD;GACE,eAAY;GACZ,WAAU;aAFZ;IAIE,kBAAC,GAAD;KACW;KACT,QAAO;KACP,UAAU;KACV,CAAA;IACF,kBAAC,MAAD;KAAI,WAAW,EAAG,aAAa,EAAsB;eAE/C,EADH,IACK,EAAQ,wBACR,EAAQ,qBAAqB;KAChC,CAAA;IACL,kBAAC,GAAD;KACE,MAAM,IAAY,SAAS;KAC3B,QAAQ,IAAY,IAAS,KAAA;KACZ;KACjB,WAvEY,MAA6B;AAEjD,MADA,GAAW,EACX,EAAW,GAAS;OAClB,YAAY,MAAW;AAChB,UAAO,OAIR,IACF,EACE;SAAE,UAAU,EAAO;SAAI,QAAQ;SAAS,EACxC;SAAE,WAAW;SAAS,SAAS;SAAa,CAC7C,GAED,EAAa,GAAS;SAAE,WAAW;SAAS,SAAS;SAAa,CAAC;;OAGvE,SAAS;OACV,CAAC;;KAsDM,UAAU;KACV,UAAU,UAAkB,EAAqB,GAAK,GAAG,KAAA;KACzD,kBAAkB;KAClB,SAtDe,MAA6B;AACpD,QAAW,EAAQ;;KAsDX,eAAe;KACF;KACb,CAAA;IACE;;EACQ,CAAA,EAEf,IACC,kBAAC,GAAD;EACE,MAAM,EAAE,EAAQ,4BAA4B;EAC5C,gBAAgB,EAAqB,GAAM;EAC3C,iBA7D0B;AAChC,KAAgB,GAAQ;IACtB,iBAAiB;AAGf,KAFA,EAAoB,EAAE,EAAQ,mBAAmB,CAAC,EAClD,EAAqB,GAAM,EAC3B,GAAS;;IAEX,UAAU,MAAQ;AAEhB,KADA,EAAY,EAAI,EAChB,EAAqB,GAAM;;IAE9B,CAAC;;EAmDI,cAAc;EACd,CAAA,GACA,KACH,EAAA,CAAA"}
1
+ {"version":3,"file":"custom-server-editor.js","names":[],"sources":["../../../../src/components/features/mcp-page/custom-server-editor.tsx"],"sourcesContent":["import React from \"react\";\nimport { AxiosError } from \"axios\";\nimport { useTranslation } from \"react-i18next\";\nimport type { MCPTestFailure } from \"@openhands/typescript-client\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalCloseButton } from \"#/components/shared/modals/modal-close-button\";\nimport { ConfirmationModal } from \"#/components/shared/modals/confirmation-modal\";\nimport {\n MCPServerForm,\n type TestMessage,\n} from \"#/components/features/settings/mcp-settings/mcp-server-form\";\nimport { useAddMcpServer } from \"#/hooks/mutation/use-add-mcp-server\";\nimport { useUpdateMcpServer } from \"#/hooks/mutation/use-update-mcp-server\";\nimport { useDeleteMcpServer } from \"#/hooks/mutation/use-delete-mcp-server\";\nimport { useTestMcpServer } from \"#/hooks/mutation/use-test-mcp-server\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { MCPServerConfig } from \"#/types/mcp-server\";\nimport {\n displayErrorToast,\n displaySuccessToast,\n} from \"#/utils/custom-toast-handlers\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\nimport { cn } from \"#/utils/utils\";\nimport { modalTitleLgClassName } from \"#/utils/modal-classes\";\n\ninterface CustomServerEditorProps {\n server: MCPServerConfig;\n existingServers: MCPServerConfig[];\n onClose: () => void;\n}\n\n/**\n * Modal wrapper around `MCPServerForm` so users can hand-author\n * arbitrary stdio / SSE / SHTTP entries without reaching for raw JSON.\n * An empty `server.id` means \"Add new\".\n */\nexport function CustomServerEditor({\n server,\n existingServers,\n onClose,\n}: CustomServerEditorProps) {\n const { t } = useTranslation(\"openhands\");\n const { mutate: addMcpServer, isPending: isAdding } = useAddMcpServer();\n const { mutate: updateMcpServer, isPending: isUpdating } =\n useUpdateMcpServer();\n const { mutate: deleteMcpServer, isPending: isDeleting } =\n useDeleteMcpServer();\n const {\n mutate: testServer,\n isPending: isTesting,\n data: testResult,\n reset: resetTest,\n } = useTestMcpServer();\n const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);\n\n // The MCP connectivity-test endpoint only exists on the local agent-server.\n // For cloud backends `McpService.testServer` short-circuits with a synthetic\n // success so the save still completes; we hide the manual \"Test connection\"\n // button here so cloud users aren't shown a misleading \"0 tools\" result.\n const { backend } = useActiveBackend();\n const isCloudBackend = backend.kind === \"cloud\";\n\n const isEditing = !!server.id;\n const isPending = isAdding || isUpdating || isDeleting;\n const isDismissBlocked = isPending || isTesting || showDeleteConfirm;\n\n const makeTestErrorMessage = (failure: MCPTestFailure): string => {\n switch (failure.error_kind) {\n case \"timeout\":\n return t(I18nKey.MCP$TEST_ERROR_TIMEOUT);\n case \"connection\":\n return t(I18nKey.MCP$TEST_ERROR_CONNECTION);\n default:\n return t(I18nKey.MCP$TEST_ERROR_UNKNOWN, { error: failure.error });\n }\n };\n\n const testMessage: TestMessage | null = React.useMemo(() => {\n if (!testResult) return null;\n if (testResult.ok) {\n return {\n ok: true,\n text: t(I18nKey.MCP$TEST_SUCCESS, { count: testResult.tools.length }),\n };\n }\n return { ok: false, text: makeTestErrorMessage(testResult) };\n }, [testResult, t]);\n\n // Shared error handler so both add and update surface backend errors\n // as a toast instead of failing silently — previously these calls\n // had no `onError` and the modal closed even on a 4xx/5xx, leaving\n // the user to discover the failure on the next page load.\n const handleError = (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n displayErrorToast(message || t(I18nKey.ERROR$GENERIC));\n };\n\n const handleSubmit = (payload: MCPServerConfig) => {\n resetTest();\n testServer(payload, {\n onSuccess: (result) => {\n if (!result.ok) {\n // Test failed — modal stays open, error shown via testMessage.\n return;\n }\n if (isEditing) {\n updateMcpServer(\n { serverId: server.id, server: payload },\n { onSuccess: onClose, onError: handleError },\n );\n } else {\n addMcpServer(payload, { onSuccess: onClose, onError: handleError });\n }\n },\n onError: handleError,\n });\n };\n\n const handleTestClick = (payload: MCPServerConfig) => {\n testServer(payload);\n };\n\n const handleConfirmDelete = () => {\n deleteMcpServer(server, {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.MCP$REMOVE_SUCCESS));\n setShowDeleteConfirm(false);\n onClose();\n },\n onError: (err) => {\n handleError(err);\n setShowDeleteConfirm(false);\n },\n });\n };\n\n return (\n <>\n <ModalBackdrop\n // Block backdrop-click / Escape from dismissing the modal while\n // a mutation is in flight — closing mid-request would orphan\n // the request and leave the user with no error feedback.\n onClose={isDismissBlocked ? undefined : onClose}\n closeOnEscape={!isDismissBlocked}\n aria-label={\n isEditing\n ? t(I18nKey.MCP$EDIT_CUSTOM_TITLE)\n : t(I18nKey.MCP$ADD_CUSTOM_TITLE)\n }\n >\n <div\n data-testid=\"mcp-custom-editor\"\n className=\"relative bg-base-secondary p-6 rounded-xl border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[90vh] overflow-y-auto custom-scrollbar\"\n >\n <ModalCloseButton\n onClose={onClose}\n testId=\"mcp-custom-editor-close\"\n disabled={isDismissBlocked}\n />\n <h2 className={cn(\"mb-4 pr-6\", modalTitleLgClassName)}>\n {isEditing\n ? t(I18nKey.MCP$EDIT_CUSTOM_TITLE)\n : t(I18nKey.MCP$ADD_CUSTOM_TITLE)}\n </h2>\n <MCPServerForm\n mode={isEditing ? \"edit\" : \"add\"}\n server={isEditing ? server : undefined}\n existingServers={existingServers}\n onSubmit={handleSubmit}\n onCancel={onClose}\n onDelete={isEditing ? () => setShowDeleteConfirm(true) : undefined}\n isActionDisabled={isPending}\n onTest={isCloudBackend ? undefined : handleTestClick}\n isTestPending={isTesting}\n testMessage={isCloudBackend ? null : testMessage}\n />\n </div>\n </ModalBackdrop>\n\n {showDeleteConfirm ? (\n <ConfirmationModal\n text={t(I18nKey.SETTINGS$MCP_CONFIRM_DELETE)}\n onCancel={() => setShowDeleteConfirm(false)}\n onConfirm={handleConfirmDelete}\n isConfirming={isDeleting}\n />\n ) : null}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqCA,SAAgB,EAAmB,EACjC,WACA,oBACA,cAC0B;CAC1B,IAAM,EAAE,SAAM,EAAe,YAAY,EACnC,EAAE,QAAQ,GAAc,WAAW,MAAa,GAAiB,EACjE,EAAE,QAAQ,GAAiB,WAAW,MAC1C,GAAoB,EAChB,EAAE,QAAQ,GAAiB,WAAW,MAC1C,GAAoB,EAChB,EACJ,QAAQ,GACR,WAAW,GACX,MAAM,GACN,OAAO,MACL,GAAkB,EAChB,CAAC,GAAmB,KAAwB,EAAM,SAAS,GAAM,EAMjE,EAAE,eAAY,GAAkB,EAChC,IAAiB,EAAQ,SAAS,SAElC,IAAY,CAAC,CAAC,EAAO,IACrB,IAAY,KAAY,KAAc,GACtC,IAAmB,KAAa,KAAa,GAE7C,KAAwB,MAAoC;AAChE,UAAQ,EAAQ,YAAhB;GACE,KAAK,UACH,QAAO,EAAE,EAAQ,uBAAuB;GAC1C,KAAK,aACH,QAAO,EAAE,EAAQ,0BAA0B;GAC7C,QACE,QAAO,EAAE,EAAQ,wBAAwB,EAAE,OAAO,EAAQ,OAAO,CAAC;;IAIlE,IAAkC,EAAM,cACvC,IACD,EAAW,KACN;EACL,IAAI;EACJ,MAAM,EAAE,EAAQ,kBAAkB,EAAE,OAAO,EAAW,MAAM,QAAQ,CAAC;EACtE,GAEI;EAAE,IAAI;EAAO,MAAM,EAAqB,EAAW;EAAE,GAPpC,MAQvB,CAAC,GAAY,EAAE,CAAC,EAMb,KAAe,MAAiB;AAEpC,IADgB,EAA0B,EACxB,IAAW,EAAE,EAAQ,cAAc,CAAC;;AA0CxD,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EAIE,SAAS,IAAmB,KAAA,IAAY;EACxC,eAAe,CAAC;EAChB,cAEM,EADJ,IACM,EAAQ,wBACR,EAAQ,qBAAqB;YAGrC,kBAAC,OAAD;GACE,eAAY;GACZ,WAAU;aAFZ;IAIE,kBAAC,GAAD;KACW;KACT,QAAO;KACP,UAAU;KACV,CAAA;IACF,kBAAC,MAAD;KAAI,WAAW,EAAG,aAAa,EAAsB;eAE/C,EADH,IACK,EAAQ,wBACR,EAAQ,qBAAqB;KAChC,CAAA;IACL,kBAAC,GAAD;KACE,MAAM,IAAY,SAAS;KAC3B,QAAQ,IAAY,IAAS,KAAA;KACZ;KACjB,WAvEY,MAA6B;AAEjD,MADA,GAAW,EACX,EAAW,GAAS;OAClB,YAAY,MAAW;AAChB,UAAO,OAIR,IACF,EACE;SAAE,UAAU,EAAO;SAAI,QAAQ;SAAS,EACxC;SAAE,WAAW;SAAS,SAAS;SAAa,CAC7C,GAED,EAAa,GAAS;SAAE,WAAW;SAAS,SAAS;SAAa,CAAC;;OAGvE,SAAS;OACV,CAAC;;KAsDM,UAAU;KACV,UAAU,UAAkB,EAAqB,GAAK,GAAG,KAAA;KACzD,kBAAkB;KAClB,QAAQ,IAAiB,KAAA,KAtDV,MAA6B;AACpD,QAAW,EAAQ;;KAsDX,eAAe;KACf,aAAa,IAAiB,OAAO;KACrC,CAAA;IACE;;EACQ,CAAA,EAEf,IACC,kBAAC,GAAD;EACE,MAAM,EAAE,EAAQ,4BAA4B;EAC5C,gBAAgB,EAAqB,GAAM;EAC3C,iBA7D0B;AAChC,KAAgB,GAAQ;IACtB,iBAAiB;AAGf,KAFA,EAAoB,EAAE,EAAQ,mBAAmB,CAAC,EAClD,EAAqB,GAAM,EAC3B,GAAS;;IAEX,UAAU,MAAQ;AAEhB,KADA,EAAY,EAAI,EAChB,EAAqB,GAAM;;IAE9B,CAAC;;EAmDI,cAAc;EACd,CAAA,GACA,KACH,EAAA,CAAA"}
@@ -2,6 +2,14 @@ interface SetupLlmStepProps {
2
2
  onBack: () => void;
3
3
  onNext: () => void;
4
4
  }
5
+ /**
6
+ * Pre-fills the LLM form with the OpenAI GPT-5.5 model. The SDK's
7
+ * bare default model is `gpt-5.5`; Canvas stores provider-qualified
8
+ * LiteLLM model ids, so the onboarding override uses this OpenAI-prefixed
9
+ * model id. Keeping this as an explicit override marks the model dirty so
10
+ * the Next button persists the suggested default immediately.
11
+ */
12
+ export declare const ONBOARDING_DEFAULT_LLM_MODEL = "openai/gpt-5.5";
5
13
  /**
6
14
  * Step 2: embed the LLM settings form. The screen runs in `embedded`
7
15
  * mode (so it doesn't render its own sticky Save bar) and with