@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
@@ -21,6 +21,11 @@ import {
21
21
  isProcessRunning,
22
22
  signalProcessTree,
23
23
  } from "./dev-process-utils.mjs";
24
+ // buildRuntimeServicesInfo moved to its own dependency-free module so the
25
+ // Docker entrypoint can run it as a CLI. Re-exported below for back-compat
26
+ // (dev-with-automation.mjs and tests still import it from here).
27
+ import { buildRuntimeServicesInfo } from "./runtime-services-info.mjs";
28
+ import { fileLog, stripAnsi } from "./logger.mjs";
24
29
 
25
30
  // ── Centralized config (single source of truth for versions, ports, etc.) ───
26
31
  const __dev_safe_dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -31,6 +36,32 @@ const SHARED_DEFAULTS = JSON.parse(
31
36
  ),
32
37
  );
33
38
 
39
+ /**
40
+ * Extract the pinned commit SHA for @openhands/extensions from package.json.
41
+ * Returns the 40-char hex SHA when the dependency is a git+https URL with a
42
+ * commit hash fragment (e.g. "git+https://…#62594156…"), null otherwise.
43
+ * @returns {string | null}
44
+ */
45
+ function getExtensionsRef() {
46
+ try {
47
+ const pkg = JSON.parse(
48
+ readFileSync(
49
+ path.join(__dev_safe_dirname, "..", "package.json"),
50
+ "utf-8",
51
+ ),
52
+ );
53
+ const url =
54
+ (pkg.dependencies ?? pkg.devDependencies ?? {})["@openhands/extensions"] ??
55
+ "";
56
+ return url.match(/#([0-9a-f]{40})$/i)?.[1] ?? null;
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ /** Pinned extensions commit SHA derived from package.json, or null if not pinned. */
63
+ export const DEFAULT_EXTENSIONS_REF = getExtensionsRef();
64
+
34
65
  const DEFAULT_BACKEND_PORT = SHARED_DEFAULTS.ports.agentServer;
35
66
  const DEFAULT_VITE_PORT = 3001;
36
67
  const DEFAULT_WAIT_TIMEOUT_MS = 30_000;
@@ -389,7 +420,7 @@ export function validateFrontendDependencies(
389
420
  * edits are picked up without a manual reinstall. The agent-server itself
390
421
  * is rebuilt from local source on each invocation (--reinstall).
391
422
  * - OH_AGENT_SERVER_GIT_REF: Git commit SHA or branch name
392
- * - OH_AGENT_SERVER_VERSION: Specific PyPI version (e.g., "1.24.0")
423
+ * - OH_AGENT_SERVER_VERSION: Specific PyPI version (e.g., "1.26.0")
393
424
  *
394
425
  * If none are set, defaults to the released version specified by
395
426
  * DEFAULT_AGENT_SERVER_VERSION. Set OH_AGENT_SERVER_GIT_REF to use a
@@ -426,14 +457,23 @@ export function buildAgentServerCommand(env = process.env) {
426
457
  );
427
458
  source = `local (${localPath})`;
428
459
  } else if (gitRef) {
429
- // Use git ref with subdirectory syntax for uv workspace monorepo
460
+ // Use git ref with subdirectory syntax for uv workspace monorepo.
430
461
  // The software-agent-sdk repo has packages in subdirectories:
431
- // openhands-agent-server/, openhands-tools/, openhands-workspace/
462
+ // openhands-agent-server/, openhands-sdk/, openhands-tools/, openhands-workspace/
463
+ // All four must come from the same ref so inter-package APIs stay in sync.
464
+ //
465
+ // --reinstall is required because the git branch may carry the same version
466
+ // string as the current PyPI release (e.g. both "1.26.0"). Without it, uv
467
+ // silently reuses the cached PyPI wheels and the git ref is never actually
468
+ // used, even though it was explicitly requested.
432
469
  const baseGitUrl = `git+${AGENT_SERVER_GIT_REPO}@${gitRef}`;
433
470
  uvxArgs.push(
471
+ "--reinstall",
434
472
  "--from",
435
473
  `${baseGitUrl}#subdirectory=openhands-agent-server`,
436
474
  "--with",
475
+ `${baseGitUrl}#subdirectory=openhands-sdk`,
476
+ "--with",
437
477
  `${baseGitUrl}#subdirectory=openhands-tools`,
438
478
  "--with",
439
479
  `${baseGitUrl}#subdirectory=openhands-workspace`,
@@ -697,124 +737,20 @@ export function buildAgentServerEnv(config) {
697
737
  // Make the host tools/ directory importable so the agent-server can
698
738
  // resolve modules listed in tool_module_qualnames (e.g. canvas_ui_tool).
699
739
  OH_EXTRA_PYTHON_PATH: config.canvasToolsDir,
740
+ // Tell the agent-server which extensions commit to use for the public
741
+ // skills catalog. Derived from the @openhands/extensions pin in
742
+ // package.json; the SDK skips network polling when it already has this
743
+ // SHA cached. Only injected when the caller has not already set it.
744
+ ...(DEFAULT_EXTENSIONS_REF && !process.env.EXTENSIONS_REF
745
+ ? { EXTENSIONS_REF: DEFAULT_EXTENSIONS_REF }
746
+ : {}),
700
747
  };
701
748
  }
702
749
 
703
- /**
704
- * Build a structured description of the dev-stack services that are
705
- * reachable from inside the agent's sandbox. The frontend forwards this
706
- * (verbatim, as a JSON string in `VITE_RUNTIME_SERVICES_INFO`) and renders
707
- * it into the system prompt via `AgentContext.system_message_suffix`, so
708
- * the agent sees a `<RUNTIME_SERVICES>` block listing what's available
709
- * without having to probe.
710
- *
711
- * URLs are written from the *agent's* point of view. The agent-server
712
- * runs on the host, so the host alias is "localhost".
713
- *
714
- * @param {object} options
715
- * @param {string} [options.mode] - Human-readable dev mode label (e.g. "dev:safe").
716
- * @param {string} [options.agentHostAlias="localhost"] - Hostname the agent
717
- * uses to reach services running on the host machine.
718
- * @param {number} [options.agentServerPort] - Port the agent-server listens on.
719
- * Required at runtime; the function throws if missing because the resulting
720
- * URL would otherwise bake `undefined` into the agent's system prompt.
721
- * Typed as optional only so TypeScript callers can negative-test the guard.
722
- * @param {number} [options.ingressPort] - Ingress port (omit if no ingress).
723
- * @param {number} [options.frontendPort] - Frontend port (Vite dev server
724
- * or static-file server). Omit if no frontend is exposed.
725
- * @param {number} [options.vitePort] - Deprecated alias for `frontendPort`,
726
- * accepted for backward compat with older launchers. Remove after one release.
727
- * @param {"vite"|"static"} [options.frontendKind="vite"] - Whether the
728
- * frontend port hosts Vite or a static build. Only affects the
729
- * description shown to the agent.
730
- * @param {object} [options.automation] - Automation backend info. Skipped
731
- * entirely if `.port` is missing, so passing `{}` is safe.
732
- * @param {number} [options.automation.port] - Automation backend port.
733
- * @param {string} [options.automation.apiPrefix="/api/automation"] - Path
734
- * prefix all automation routes are mounted under.
735
- * @param {string} [options.automation.authEnvVar="OPENHANDS_AUTOMATION_API_KEY"]
736
- * - Env var holding the API key.
737
- * @returns {object} A JSON-serializable runtime services info object.
738
- */
739
- export function buildRuntimeServicesInfo(options) {
740
- const {
741
- mode,
742
- agentHostAlias = "localhost",
743
- agentServerPort,
744
- ingressPort,
745
- // Accept legacy `vitePort` for one release so external callers keep working.
746
- vitePort,
747
- frontendPort = vitePort,
748
- frontendKind = "vite",
749
- automation,
750
- } = options;
751
-
752
- if (agentServerPort === undefined || agentServerPort === null) {
753
- // Without this the URL becomes `http://localhost:undefined` and ends up
754
- // verbatim in the agent's system prompt, which is worse than failing fast.
755
- throw new Error(
756
- "buildRuntimeServicesInfo: agentServerPort is required " +
757
- "(otherwise the agent_server URL would be `http://localhost:undefined`).",
758
- );
759
- }
760
-
761
- const services = {
762
- agent_server: {
763
- description:
764
- "The OpenHands Agent Server this agent is running inside. " +
765
- "Tool calls (terminal, file_editor, browser, etc.) execute here.",
766
- // From the agent's POV, the agent-server it's *inside* is on
767
- // localhost, regardless of where the host is.
768
- url_from_agent: `http://localhost:${agentServerPort}`,
769
- },
770
- };
771
-
772
- if (ingressPort !== undefined) {
773
- services.ingress = {
774
- description:
775
- "Unified entry point. Routes /api/automation/* to the automation " +
776
- "backend, /api/* and /sockets to the agent-server, and /* to the " +
777
- "frontend.",
778
- url_from_agent: `http://${agentHostAlias}:${ingressPort}`,
779
- };
780
- }
781
-
782
- if (frontendPort !== undefined) {
783
- services.frontend = {
784
- kind: frontendKind,
785
- description:
786
- frontendKind === "static"
787
- ? "Static-file server hosting the agent-canvas production build."
788
- : "Vite dev server hosting the agent-canvas frontend.",
789
- url_from_agent: `http://${agentHostAlias}:${frontendPort}`,
790
- };
791
- }
792
-
793
- // Require an explicit port so we don't bake `:undefined` into the
794
- // automation URL when the caller passes `automation: {}`.
795
- if (automation?.port !== undefined && automation.port !== null) {
796
- const apiPrefix = automation.apiPrefix ?? "/api/automation";
797
- const authEnvVar = automation.authEnvVar ?? "OPENHANDS_AUTOMATION_API_KEY";
798
- const baseUrl = `http://${agentHostAlias}:${automation.port}`;
799
- services.automation = {
800
- description:
801
- "OpenHands Automations service. All routes are mounted under " +
802
- `'${apiPrefix}'. Authenticate with header ` +
803
- `'X-Session-API-Key: $${authEnvVar}'.`,
804
- url_from_agent: baseUrl,
805
- api_prefix: apiPrefix,
806
- docs_url: `${baseUrl}${apiPrefix}/docs`,
807
- openapi_url: `${baseUrl}${apiPrefix}/openapi.json`,
808
- auth_env_var: authEnvVar,
809
- };
810
- }
811
-
812
- return {
813
- mode,
814
- agent_host_alias: agentHostAlias,
815
- services,
816
- };
817
- }
750
+ // Re-export so existing importers (dev-with-automation.mjs, tests) keep
751
+ // resolving `buildRuntimeServicesInfo` from this module. The implementation
752
+ // now lives in ./runtime-services-info.mjs (imported at the top of this file).
753
+ export { buildRuntimeServicesInfo };
818
754
 
819
755
  export function buildNpmScriptCommand(
820
756
  scriptName,
@@ -899,13 +835,16 @@ function spawnProcess(command, args, options = {}) {
899
835
 
900
836
  child.once("error", (error) => {
901
837
  if (isEnoentError(error) && command === "uvx") {
902
- console.error(formatMissingUvxGuidance(options?.cwd));
838
+ const msg = formatMissingUvxGuidance(options?.cwd);
839
+ console.error(msg);
840
+ fileLog("error", stripAnsi(msg));
903
841
  } else if (isEnoentError(error)) {
904
- console.error(
905
- `Failed to start ${command}. Make sure it is installed and on your PATH.`,
906
- );
842
+ const msg = `Failed to start ${command}. Make sure it is installed and on your PATH.`;
843
+ console.error(msg);
844
+ fileLog("error", msg);
907
845
  } else {
908
846
  console.error(`Failed to start ${command}:`, error);
847
+ fileLog("error", `Failed to start ${command}: ${error.message}`);
909
848
  }
910
849
  });
911
850
 
@@ -914,9 +853,12 @@ function spawnProcess(command, args, options = {}) {
914
853
 
915
854
  async function main() {
916
855
  console.log("Starting isolated agent-server + frontend dev stack...");
856
+ fileLog("info", "Starting isolated agent-server + frontend dev stack...");
917
857
  validateFrontendDependencies();
918
858
  console.log("Frontend dependencies found.");
859
+ fileLog("info", "Frontend dependencies found.");
919
860
  console.log("Allocating ports...");
861
+ fileLog("info", "Allocating ports...");
920
862
 
921
863
  // Use async config builder with dynamic port allocation
922
864
  const config = await buildSafeDevConfigAsync();
@@ -955,6 +897,16 @@ async function main() {
955
897
  console.log(`- secret key: ${secretKeySource}`);
956
898
  console.log(`- session API key: ${sessionKeySource}`);
957
899
  console.log("");
900
+ fileLog(
901
+ "info",
902
+ [
903
+ "Agent-server stack config:",
904
+ ` agent-server: ${agentServerCmd.source}`,
905
+ ` backend: ${config.backendBaseUrl}`,
906
+ ` working dir: ${config.workingDir}`,
907
+ ` state dir: ${config.stateDir}`,
908
+ ].join("\n"),
909
+ );
958
910
 
959
911
  const backend = spawnProcess(
960
912
  agentServerCmd.command,
@@ -1055,7 +1007,9 @@ async function main() {
1055
1007
 
1056
1008
  backend.once("exit", (code) => {
1057
1009
  if (!shuttingDown) {
1058
- console.error(`agent-server exited unexpectedly with code ${code ?? 0}`);
1010
+ const msg = `agent-server exited unexpectedly with code ${code ?? 0}`;
1011
+ console.error(msg);
1012
+ fileLog("error", msg);
1059
1013
  shutdown();
1060
1014
  process.exitCode = code ?? 1;
1061
1015
  }
@@ -1142,7 +1096,12 @@ if (
1142
1096
  import.meta.url === pathToFileURL(process.argv[1]).href
1143
1097
  ) {
1144
1098
  main().catch((error) => {
1145
- console.error(error instanceof Error ? error.message : error);
1099
+ const msg = error instanceof Error ? error.message : String(error);
1100
+ console.error(msg);
1101
+ fileLog("error", `Fatal error: ${msg}`);
1102
+ if (error instanceof Error && error.stack) {
1103
+ fileLog("error", error.stack);
1104
+ }
1146
1105
  process.exit(1);
1147
1106
  });
1148
1107
  }
@@ -68,6 +68,7 @@ import {
68
68
  isProcessRunning,
69
69
  signalProcessTree,
70
70
  } from "./dev-process-utils.mjs";
71
+ import { fileLog, stripAnsi } from "./logger.mjs";
71
72
 
72
73
  const __dirname = dirname(fileURLToPath(import.meta.url));
73
74
  const projectRoot = resolve(__dirname, "..");
@@ -105,18 +106,54 @@ const c = {
105
106
  function logService(name, message, color = c.reset) {
106
107
  const ts = new Date().toISOString().split("T")[1].split(".")[0];
107
108
  console.log(`${c.dim}${ts}${c.reset} ${color}[${name}]${c.reset} ${message}`);
109
+ fileLog("info", `[${name}] ${stripAnsi(message)}`);
108
110
  }
109
111
 
110
112
  function logStep(step, message) {
111
113
  console.log(`${c.cyan}[${step}]${c.reset} ${message}`);
114
+ fileLog("info", `[${step}] ${message}`);
112
115
  }
113
116
 
114
117
  function logSuccess(message) {
115
118
  console.log(`${c.green}✓${c.reset} ${message}`);
119
+ fileLog("info", `✓ ${message}`);
116
120
  }
117
121
 
118
122
  function logError(message) {
119
123
  console.error(`${c.red}✗${c.reset} ${message}`);
124
+ fileLog("error", `✗ ${stripAnsi(message)}`);
125
+ }
126
+
127
+ /**
128
+ * Parse one JSON log line produced by the SDK's JsonFormatter and return a
129
+ * single-line human-readable string + an appropriate ANSI color.
130
+ *
131
+ * Returns null for non-JSON lines so callers can fall back to the raw text.
132
+ *
133
+ * @param {string} rawLine
134
+ * @returns {{ text: string; color: string } | null}
135
+ */
136
+ function parseAgentServerLogLine(rawLine) {
137
+ try {
138
+ const obj = JSON.parse(rawLine);
139
+ if (!obj.levelname || obj.message === undefined) return null;
140
+ const level = obj.levelname.padEnd(8);
141
+ const location =
142
+ obj.filename && obj.lineno ? ` ${obj.filename}:${obj.lineno}` : "";
143
+ const text = `${level} ${obj.message}${location}`;
144
+ const lvl = obj.levelname;
145
+ const color =
146
+ lvl === "DEBUG"
147
+ ? c.dim
148
+ : lvl === "WARNING"
149
+ ? c.yellow
150
+ : lvl === "ERROR" || lvl === "CRITICAL"
151
+ ? c.red
152
+ : c.blue;
153
+ return { text, color };
154
+ } catch {
155
+ return null;
156
+ }
120
157
  }
121
158
 
122
159
  // ═══════════════════════════════════════════════════════════════════════════
@@ -440,7 +477,9 @@ function checkPrerequisites({
440
477
 
441
478
  if (checkUvx) {
442
479
  if (!commandExists("uvx")) {
443
- console.error(formatMissingUvxGuidance(projectRoot));
480
+ const uvxGuidance = formatMissingUvxGuidance(projectRoot);
481
+ console.error(uvxGuidance);
482
+ fileLog("error", stripAnsi(uvxGuidance));
444
483
  process.exit(1);
445
484
  }
446
485
  logSuccess("uvx found");
@@ -521,6 +560,7 @@ function spawnService(name, command, args, options = {}) {
521
560
  );
522
561
 
523
562
  const color = options.color || c.reset;
563
+ const parseLogLine = options.parseLogLine;
524
564
 
525
565
  proc.stdout.on("data", (data) => {
526
566
  data
@@ -528,7 +568,8 @@ function spawnService(name, command, args, options = {}) {
528
568
  .split("\n")
529
569
  .filter(Boolean)
530
570
  .forEach((line) => {
531
- logService(name, line.trim(), color);
571
+ const parsed = parseLogLine ? parseLogLine(line.trim()) : null;
572
+ logService(name, parsed ? parsed.text : line.trim(), parsed ? parsed.color : color);
532
573
  });
533
574
  });
534
575
 
@@ -538,7 +579,8 @@ function spawnService(name, command, args, options = {}) {
538
579
  .split("\n")
539
580
  .filter(Boolean)
540
581
  .forEach((line) => {
541
- logService(name, line.trim(), c.yellow);
582
+ const parsed = parseLogLine ? parseLogLine(line.trim()) : null;
583
+ logService(name, parsed ? parsed.text : line.trim(), parsed ? parsed.color : c.yellow);
542
584
  });
543
585
  });
544
586
 
@@ -699,6 +741,11 @@ function startAgentServer(config) {
699
741
  // Ensure the agent-server uses the resolved key from config. This is
700
742
  // LOCAL_BACKEND_API_KEY when set, or the auto-generated persisted key.
701
743
  OH_SESSION_API_KEYS_0: config.sessionApiKey,
744
+ // Emit structured JSON log lines instead of Rich-formatted output.
745
+ // Rich wraps long messages across multiple lines and prepends its own
746
+ // timestamp; LOG_JSON=true produces one JSON object per record which
747
+ // parseAgentServerLogLine re-formats into a clean single-line entry.
748
+ LOG_JSON: "true",
702
749
  };
703
750
 
704
751
  spawnService(
@@ -715,6 +762,7 @@ function startAgentServer(config) {
715
762
  cwd: safeConfig.workspacesPath,
716
763
  env: agentServerEnv,
717
764
  color: c.blue,
765
+ parseLogLine: parseAgentServerLogLine,
718
766
  },
719
767
  );
720
768
  }
@@ -796,8 +844,10 @@ function startAutomationBackend(config) {
796
844
  join(config.stateDir, "workspaces"),
797
845
  // Session API key for self-hosted auth — shared with agent-server via X-Session-API-Key header
798
846
  AUTOMATION_LOCAL_API_KEY: config.sessionApiKey,
799
- // CORS: allow localhost origins for dev
800
- AUTOMATION_CORS_ORIGINS: `http://localhost:${config.ingressPort},http://127.0.0.1:${config.ingressPort},http://localhost:3001,http://127.0.0.1:3001`,
847
+ // CORS: allow localhost origins for dev, unless explicitly overridden.
848
+ AUTOMATION_CORS_ORIGINS:
849
+ process.env.AUTOMATION_CORS_ORIGINS ||
850
+ `http://localhost:${config.ingressPort},http://127.0.0.1:${config.ingressPort},http://localhost:3001,http://127.0.0.1:3001`,
801
851
  FILE_STORE: "local",
802
852
  LOCAL_STORAGE_PATH: join(config.stateDir, "storage"),
803
853
  OPENHANDS_SUPPRESS_BANNER: "1",
@@ -819,6 +869,7 @@ function shutdown() {
819
869
 
820
870
  console.log("");
821
871
  console.log(`${c.yellow}Shutting down...${c.reset}`);
872
+ fileLog("info", "Shutting down...");
822
873
 
823
874
  for (const [name, proc] of processes) {
824
875
  logService(name, "Stopping...", c.dim);
@@ -1090,6 +1141,20 @@ function printBanner(config) {
1090
1141
  console.log(`${c.dim}State directory: ${config.stateDir}${c.reset}`);
1091
1142
  console.log(`${c.dim}Press Ctrl+C to stop${c.reset}`);
1092
1143
  console.log("");
1144
+
1145
+ // Write a compact plain-text summary to the log file.
1146
+ const summary = [
1147
+ `${stackName} — started`,
1148
+ ` Ingress: http://localhost:${config.ingressPort}/`,
1149
+ ...(config.launchFrontend
1150
+ ? [` Main UI: http://localhost:${config.ingressPort}/`]
1151
+ : []),
1152
+ ...(config.launchAutomation
1153
+ ? [` API Docs: http://localhost:${config.ingressPort}/api/automation/docs`]
1154
+ : []),
1155
+ ` State directory: ${config.stateDir}`,
1156
+ ];
1157
+ fileLog("info", summary.join("\n"));
1093
1158
  }
1094
1159
 
1095
1160
  async function main(options = {}) {
@@ -1143,6 +1208,7 @@ async function main(options = {}) {
1143
1208
  console.log("");
1144
1209
  console.log(`${c.cyan}${c.bold}${titleWithMode}${c.reset}`);
1145
1210
  console.log("");
1211
+ fileLog("info", titleWithMode);
1146
1212
 
1147
1213
  // Setup phase
1148
1214
  checkPrerequisites({
@@ -1269,6 +1335,13 @@ function startStaticFrontend(config, staticDir) {
1269
1335
  logService("static", `Starting on port ${config.vitePort}...`, c.magenta);
1270
1336
  logService("static", `Serving from: ${staticDir}`, c.dim);
1271
1337
 
1338
+ // Build the runtime-services info JSON so the pre-built frontend can
1339
+ // populate the agent's <RUNTIME_SERVICES> system-prompt block without
1340
+ // VITE_RUNTIME_SERVICES_INFO baked in at build time.
1341
+ const runtimeServicesInfo = config.launchAgentServer
1342
+ ? JSON.stringify(buildAutomationRuntimeServicesInfo(config))
1343
+ : null;
1344
+
1272
1345
  const staticServerScript = join(projectRoot, "scripts", "static-server.mjs");
1273
1346
  spawnService(
1274
1347
  "static",
@@ -1288,6 +1361,10 @@ function startStaticFrontend(config, staticDir) {
1288
1361
  ...(config.launchAgentServer && config.isPublic
1289
1362
  ? ["--auth-required"]
1290
1363
  : []),
1364
+ // Inject runtime-services info so the agent knows what's reachable.
1365
+ ...(runtimeServicesInfo
1366
+ ? ["--runtime-services-info", runtimeServicesInfo]
1367
+ : []),
1291
1368
  // Proxy routes only to services that this launch mode started.
1292
1369
  ...buildRouteArgs(getLocalServiceRoutes(config)),
1293
1370
  // Reject known API prefixes that have no backend — returns 503
@@ -1343,6 +1420,7 @@ if (isMainModule) {
1343
1420
  logError(`Fatal error: ${err.message}`);
1344
1421
  if (err.stack) {
1345
1422
  console.error(c.dim + err.stack + c.reset);
1423
+ fileLog("error", err.stack);
1346
1424
  }
1347
1425
  process.exit(1);
1348
1426
  });
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Shared file logger for agent-canvas dev scripts.
3
+ *
4
+ * Writes log output to a daily-rotating file under <project-root>/logs/
5
+ * alongside the existing console output (which is unchanged).
6
+ *
7
+ * File naming: logs/agent-canvas.YYYY-MM-DD.log
8
+ * Retention: 7 days (files older than 7 days are automatically deleted)
9
+ */
10
+
11
+ import { mkdirSync } from "node:fs";
12
+ import { homedir } from "node:os";
13
+ import { join } from "node:path";
14
+ import process from "node:process";
15
+ import { createLogger, format } from "winston";
16
+ import DailyRotateFile from "winston-daily-rotate-file";
17
+
18
+ // Mirror the state-directory logic from dev-safe.mjs so log files live
19
+ // alongside all other agent-canvas runtime state (e.g. ~/.openhands/agent-canvas).
20
+ // The same env var (OH_CANVAS_SAFE_STATE_DIR) overrides both.
21
+ const stateDir =
22
+ process.env.OH_CANVAS_SAFE_STATE_DIR ||
23
+ join(homedir(), ".openhands", "agent-canvas");
24
+ const logDir = join(stateDir, "logs");
25
+
26
+ // Ensure the logs directory exists before the transport tries to open a file.
27
+ mkdirSync(logDir, { recursive: true });
28
+
29
+ // Matches any ANSI CSI escape sequence (colors, cursor movement, etc.).
30
+ const ANSI_RE = /\x1b\[[0-9;]*m/g;
31
+
32
+ /**
33
+ * Remove ANSI escape codes so log files contain clean plain text.
34
+ * @param {string} str
35
+ * @returns {string}
36
+ */
37
+ export function stripAnsi(str) {
38
+ return typeof str === "string" ? str.replace(ANSI_RE, "") : String(str);
39
+ }
40
+
41
+ const fileTransport = new DailyRotateFile({
42
+ dirname: logDir,
43
+ filename: "agent-canvas.%DATE%.log",
44
+ datePattern: "YYYY-MM-DD",
45
+ maxFiles: "7d",
46
+ // Audit file tracks which rotated files exist; kept alongside log files.
47
+ auditFile: join(logDir, ".log-audit.json"),
48
+ createSymlink: false,
49
+ });
50
+
51
+ const fileLogger = createLogger({
52
+ level: "debug",
53
+ format: format.combine(
54
+ format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
55
+ format.printf(
56
+ ({ timestamp, level, message }) =>
57
+ `${timestamp} [${level.toUpperCase().padEnd(5)}] ${message}`,
58
+ ),
59
+ ),
60
+ transports: [fileTransport],
61
+ });
62
+
63
+ // Swallow any transport-level errors (e.g. disk full) so a logging failure
64
+ // never crashes the dev server.
65
+ fileLogger.on("error", () => {});
66
+ fileTransport.on("error", () => {});
67
+
68
+ /**
69
+ * Write a message to the rotating log file.
70
+ * ANSI escape codes are stripped automatically; console output is unaffected.
71
+ *
72
+ * @param {'info' | 'warn' | 'error' | 'debug'} level
73
+ * @param {string} message
74
+ */
75
+ export function fileLog(level, message) {
76
+ fileLogger.log(level, stripAnsi(message));
77
+ }