@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.
- package/README.md +2 -2
- package/README.windows.md +2 -2
- package/build/assets/acp-providers-C55k29rf.js +1 -0
- package/build/assets/{add-backend-modal-CIfhseZn.js → add-backend-modal-BdYxoUdL.js} +1 -1
- package/build/assets/agent-server-conversation-service.api-js3oYcdU.js +5 -0
- package/build/assets/{agent-settings-B6htMeS2.js → agent-settings-BNrffu3I.js} +1 -1
- package/build/assets/{alert-banner-D41ZKDZT.js → alert-banner-BzU93oDh.js} +1 -1
- package/build/assets/{analytics-consent-form-modal-TINgM_jV.js → analytics-consent-form-modal-DIfCKp6g.js} +1 -1
- package/build/assets/{api-key-entry-screen-Di1vHgIU.js → api-key-entry-screen-CGyS-Cna.js} +1 -1
- package/build/assets/{app-settings-CjCa1MOB.js → app-settings-DmOs4oik.js} +1 -1
- package/build/assets/{automation-detail-DPoxzTdV.js → automation-detail-DLbCVJCw.js} +1 -1
- package/build/assets/{automations-list-DwUEe2Ea.js → automations-list-CoYj4o97.js} +1 -1
- package/build/assets/{backend-form-modal-B6q897ZX.js → backend-form-modal-BUy-PzZN.js} +1 -1
- package/build/assets/{backend-synced-settings-badge-BwTawSCE.js → backend-synced-settings-badge-1A63yxGs.js} +1 -1
- package/build/assets/browser-B8bp1IqT.js +5 -0
- package/build/assets/{browser-tab-DiRTKik8.js → browser-tab-CiBRWB4X.js} +1 -1
- package/build/assets/chat-send-button-qKFZuB9E.js +1 -0
- package/build/assets/{circle-plus-check-toggle-B3_W6-nt.js → circle-plus-check-toggle-CboDp7XB.js} +1 -1
- package/build/assets/{condenser-settings-DczjwkIp.js → condenser-settings-FCBjvqSo.js} +1 -1
- package/build/assets/conversation-CT8AvxEH.js +1 -0
- package/build/assets/conversation-panel-DqDDs4WZ.js +1 -0
- package/build/assets/conversation-service.api-y_eB_43m.js +1 -0
- package/build/assets/conversation-store-CiYGBud3.js +6 -0
- package/build/assets/conversation-vNuLKgz6.js +19 -0
- package/build/assets/conversation-websocket-context-Bb4XBXoc.js +3 -0
- package/build/assets/{device-verify-BVl4GEvt.js → device-verify-BOQz2LJQ.js} +1 -1
- package/build/assets/{edit-automation-modal-kc_FzbzK.js → edit-automation-modal-C-oC5tis.js} +1 -1
- package/build/assets/{entry.client-CWkbusD1.js → entry.client-Db3BpFL_.js} +2 -2
- package/build/assets/{enum-filter-dropdown-DlY0Q3fj.js → enum-filter-dropdown-DFwoVtOw.js} +1 -1
- package/build/assets/{extensions-hub-NbQnt-cn.js → extensions-hub-BxZbAtjP.js} +1 -1
- package/build/assets/extensions-navigation-BIb-vAa2.js +1 -0
- package/build/assets/{files-tab-mK7Mdyuf.js → files-tab-DpulQlIo.js} +1 -1
- package/build/assets/{git-control-bar-branch-button-C1qmab0K.js → git-control-bar-branch-button-D1uam-nI.js} +1 -1
- package/build/assets/home-D77Xasws.js +1 -0
- package/build/assets/install-server-modal-BjmEphcZ.js +1 -0
- package/build/assets/{launch-BADsYeGp.js → launch-DgtB1JTX.js} +1 -1
- package/build/assets/llm-settings-B8kPJ0Of.js +1 -0
- package/build/assets/llm-settings-CjUpPsvA.js +1 -0
- package/build/assets/{manage-backends-modal-sH7l5NgI.js → manage-backends-modal-CTA-2x4F.js} +1 -1
- package/build/assets/manifest-510dd26f.js +1 -0
- package/build/assets/{markdown-renderer-CZq_UdmE.js → markdown-renderer-oOUs3tw5.js} +1 -1
- package/build/assets/{mcp-DdQ72_AO.js → mcp-CiokQDek.js} +2 -2
- package/build/assets/messages-BFJXB6MW.js +36 -0
- package/build/assets/model-selector-z_QOzaRV.js +1 -0
- package/build/assets/{onboarding-DCL9stdH.js → onboarding-CGUaLHfQ.js} +1 -1
- package/build/assets/{path-utils-CNd_jqv_.js → path-utils-0KWEiRs9.js} +1 -1
- package/build/assets/{planner-tab-QBnZgIXd.js → planner-tab-CNmJiZ22.js} +1 -1
- package/build/assets/{recommended-automations-launcher-B01jchhe.js → recommended-automations-launcher-C1_CKGHa.js} +8 -10
- package/build/assets/{root-BBV8Ew9E.js → root-DXsSPxni.js} +2 -2
- package/build/assets/root-layout-N4s3RLlj.js +2 -0
- package/build/assets/{sdk-section-page-BQKe3asw.js → sdk-section-page-DTyvCc52.js} +1 -1
- package/build/assets/{sdk-settings-schema-DoRnefvb.js → sdk-settings-schema-B0KrqqPX.js} +1 -1
- package/build/assets/{secrets-settings-D2EfzdpC.js → secrets-settings-BQNSDLKS.js} +1 -1
- package/build/assets/{settings-B7jVceyu.js → settings-BUlJrO_h.js} +1 -1
- package/build/assets/{settings-dropdown-input-BD7ziSoR.js → settings-dropdown-input-BUk4m23x.js} +1 -1
- package/build/assets/{settings-index-Xj0v9Oas.js → settings-index-DE91Eahc.js} +1 -1
- package/build/assets/{settings-modal-CDBy1S9S.js → settings-modal-CCaPYVqW.js} +1 -1
- package/build/assets/{settings-service.api-CTQ-LpAA.js → settings-service.api-4u2RKC8k.js} +1 -1
- package/build/assets/{settings-switch-CSHSqH99.js → settings-switch-BQiAS9ga.js} +1 -1
- package/build/assets/{settings-utils-BCbzc6-u.js → settings-utils-chxTa1vn.js} +1 -1
- package/build/assets/{shared-conversation-BHEbOdHj.js → shared-conversation-sBPLAawM.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-YYPXGikp.js → sidebar-mobile-menu-toggle-BDXWzhyB.js} +1 -1
- package/build/assets/{sidebar-nav-link-CiXbBMQx.js → sidebar-nav-link-Bhlzlhp8.js} +1 -1
- package/build/assets/{skill-card-pill-row-BXILn-GK.js → skill-card-pill-row-Bg5joQf6.js} +1 -1
- package/build/assets/{skills-plugins-Bs5HiF1O.js → skills-plugins-fihjo1KZ.js} +1 -1
- package/build/assets/{skills-settings-CQYxMmWf.js → skills-settings-NQnuMwZP.js} +1 -1
- package/build/assets/{styled-tooltip-DEr7oa0m.js → styled-tooltip-GXy1qxsO.js} +1 -1
- package/build/assets/{task-list-tab-R9N3Wd-U.js → task-list-tab-Hl9BuVfq.js} +1 -1
- package/build/assets/telemetry-BoedM0mF.js +2 -0
- package/build/assets/{terminal-BTM3UFcQ.js → terminal-DRwe8--D.js} +1 -1
- package/build/assets/{use-active-conversation-BY5F6A1G.js → use-active-conversation-DJGoI9Mc.js} +1 -1
- package/build/assets/{use-agent-settings-schema-CsuMq16G.js → use-agent-settings-schema-DtusObuC.js} +1 -1
- package/build/assets/{use-agent-state-DX5NKEa_.js → use-agent-state-BXgWhFh6.js} +1 -1
- package/build/assets/{use-create-conversation-4iJytCT1.js → use-create-conversation-CzvaVA5A.js} +1 -1
- package/build/assets/use-event-store-DSpvASbC.js +1 -0
- package/build/assets/{use-get-secrets-BMnFFBUx.js → use-get-secrets-DiLgP147.js} +1 -1
- package/build/assets/use-handle-plan-click-CUZwmKIk.js +1 -0
- package/build/assets/{use-launch-skill-in-chat-BoqKmEHC.js → use-launch-skill-in-chat-ClRJlIx7.js} +1 -1
- package/build/assets/use-runtime-is-ready-CWkGQFsb.js +1 -0
- package/build/assets/{use-save-settings-hK6LYt0s.js → use-save-settings-CP23emUY.js} +1 -1
- package/build/assets/use-settings-0qFqC-r6.js +1 -0
- package/build/assets/{use-settings-nav-items-oZ-BlOWX.js → use-settings-nav-items-C6YxUn4h.js} +1 -1
- package/build/assets/{use-task-list-DydbuRFM.js → use-task-list-JPudBRv3.js} +1 -1
- package/build/assets/{use-tracking-DQU60djN.js → use-tracking-CjLZgh8X.js} +1 -1
- package/build/assets/{use-unified-vscode-url-D2Buvmxj.js → use-unified-vscode-url-DSn2tT08.js} +1 -1
- package/build/assets/{use-user-conversation-DwOGM1lc.js → use-user-conversation-CQ5IwnZk.js} +1 -1
- package/build/assets/{vendor~browser-3J6WDaAB.js → vendor~browser-Dwwc84Zf.js} +1 -1
- package/build/assets/{vendor~browser-tab-DYZ-OmbT.js → vendor~browser-tab-Bhohe29F.js} +1 -1
- package/build/assets/{vendor~files-tab-Diy4WrQz.js → vendor~files-tab-B447_Zns.js} +1 -1
- 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
- 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
- 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
- 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
- package/build/assets/{vendor~launch-D65Vw0VZ.js → vendor~launch-BdXJCmwc.js} +1 -1
- 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
- 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
- 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
- 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
- package/build/assets/{vendor~root-layout~home~mcp~automations-list-JQ-neDIa.js → vendor~root-layout~home~mcp~automations-list-CtdIEhjQ.js} +1 -1
- package/build/assets/{vendor~root-layout~home~mcp~automations-list-BTTZ58Mb.js → vendor~root-layout~home~mcp~automations-list-DGOI7kQz.js} +1 -1
- 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
- package/build/assets/{verification-settings-Rabe5TpK.js → verification-settings-Cm02KmeI.js} +1 -1
- package/build/assets/{vscode-tab-zLD5Z-PP.js → vscode-tab-AF70Yke0.js} +1 -1
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +1 -1
- package/build/locales/ca/openhands.json +1 -1
- package/build/locales/de/openhands.json +1 -1
- package/build/locales/en/openhands.json +1 -1
- package/build/locales/es/openhands.json +1 -1
- package/build/locales/fr/openhands.json +1 -1
- package/build/locales/it/openhands.json +1 -1
- package/build/locales/ja/openhands.json +1 -1
- package/build/locales/ko-KR/openhands.json +1 -1
- package/build/locales/no/openhands.json +1 -1
- package/build/locales/pt/openhands.json +1 -1
- package/build/locales/tr/openhands.json +1 -1
- package/build/locales/uk/openhands.json +1 -1
- package/build/locales/zh-CN/openhands.json +1 -1
- package/build/locales/zh-TW/openhands.json +1 -1
- package/config/defaults.json +2 -6
- package/dist/api/agent-server-adapter.cjs +3 -3
- package/dist/api/agent-server-adapter.cjs.map +1 -1
- package/dist/api/agent-server-adapter.js +90 -85
- package/dist/api/agent-server-adapter.js.map +1 -1
- package/dist/api/app-preferences-store.cjs.map +1 -1
- package/dist/api/app-preferences-store.d.ts +6 -2
- package/dist/api/app-preferences-store.js.map +1 -1
- package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
- package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
- package/dist/api/mcp-service/mcp-service.api.js +19 -14
- package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.cjs +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.js +9 -9
- package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.js.map +1 -1
- package/dist/components/conversation-events/chat/event-message.cjs +1 -1
- package/dist/components/conversation-events/chat/event-message.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-message.js +80 -71
- package/dist/components/conversation-events/chat/event-message.js.map +1 -1
- package/dist/components/features/automations/recommended-automations-launcher.d.ts +7 -1
- package/dist/components/features/home/workspace-selection-form.d.ts +1 -0
- package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
- package/dist/components/features/mcp-page/custom-server-editor.cjs.map +1 -1
- package/dist/components/features/mcp-page/custom-server-editor.js +63 -62
- package/dist/components/features/mcp-page/custom-server-editor.js.map +1 -1
- package/dist/components/features/onboarding/steps/setup-llm-step.d.ts +8 -0
- package/dist/components/features/sidebar/sidebar.cjs +1 -1
- package/dist/components/features/sidebar/sidebar.js +6 -6
- package/dist/components/features/skills/extensions-navigation.cjs +1 -1
- package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
- package/dist/components/features/skills/extensions-navigation.d.ts +1 -1
- package/dist/components/features/skills/extensions-navigation.js +27 -29
- package/dist/components/features/skills/extensions-navigation.js.map +1 -1
- package/dist/i18n/translation.cjs +1 -1
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +15 -15
- package/dist/i18n/translation.js.map +1 -1
- package/dist/locales/ar/openhands.json +1 -1
- package/dist/locales/ca/openhands.json +1 -1
- package/dist/locales/de/openhands.json +1 -1
- package/dist/locales/en/openhands.json +1 -1
- package/dist/locales/es/openhands.json +1 -1
- package/dist/locales/fr/openhands.json +1 -1
- package/dist/locales/it/openhands.json +1 -1
- package/dist/locales/ja/openhands.json +1 -1
- package/dist/locales/ko-KR/openhands.json +1 -1
- package/dist/locales/no/openhands.json +1 -1
- package/dist/locales/pt/openhands.json +1 -1
- package/dist/locales/tr/openhands.json +1 -1
- package/dist/locales/uk/openhands.json +1 -1
- package/dist/locales/zh-CN/openhands.json +1 -1
- package/dist/locales/zh-TW/openhands.json +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp.js +10 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +5 -3
- package/dist/package.js.map +1 -1
- package/dist/routes/llm-settings.cjs +1 -1
- package/dist/routes/llm-settings.cjs.map +1 -1
- package/dist/routes/llm-settings.js +21 -21
- package/dist/routes/llm-settings.js.map +1 -1
- package/dist/types/agent-server/core/events/index.d.ts +1 -0
- package/dist/types/agent-server/core/events/streaming-delta-event.d.ts +7 -0
- package/dist/types/agent-server/core/openhands-event.d.ts +2 -2
- package/dist/types/agent-server/type-guards.cjs +1 -1
- package/dist/types/agent-server/type-guards.cjs.map +1 -1
- package/dist/types/agent-server/type-guards.d.ts +2 -0
- package/dist/types/agent-server/type-guards.js +3 -3
- package/dist/types/agent-server/type-guards.js.map +1 -1
- package/dist/utils/handle-event-for-ui.cjs +1 -1
- package/dist/utils/handle-event-for-ui.cjs.map +1 -1
- package/dist/utils/handle-event-for-ui.js +69 -13
- package/dist/utils/handle-event-for-ui.js.map +1 -1
- package/dist/utils/mcp-config.cjs +1 -1
- package/dist/utils/mcp-config.cjs.map +1 -1
- package/dist/utils/mcp-config.js +27 -19
- package/dist/utils/mcp-config.js.map +1 -1
- package/dist/utils/mcp-marketplace-utils.cjs +1 -1
- package/dist/utils/mcp-marketplace-utils.cjs.map +1 -1
- package/dist/utils/mcp-marketplace-utils.js +38 -18
- package/dist/utils/mcp-marketplace-utils.js.map +1 -1
- package/dist/utils/normalize-display-model.cjs +1 -1
- package/dist/utils/normalize-display-model.cjs.map +1 -1
- package/dist/utils/normalize-display-model.js +8 -7
- package/dist/utils/normalize-display-model.js.map +1 -1
- package/dist/utils/openhands-llm.cjs +1 -1
- package/dist/utils/openhands-llm.cjs.map +1 -1
- package/dist/utils/openhands-llm.d.ts +13 -0
- package/dist/utils/openhands-llm.js +9 -3
- package/dist/utils/openhands-llm.js.map +1 -1
- package/package.json +5 -3
- package/scripts/check-sdk-version-sync.mjs +6 -6
- package/scripts/dev-safe.mjs +83 -124
- package/scripts/dev-with-automation.mjs +83 -5
- package/scripts/logger.mjs +77 -0
- package/scripts/runtime-services-info.mjs +199 -0
- package/scripts/static-server.mjs +42 -4
- package/build/assets/acp-providers-DZEi8wDz.js +0 -1
- package/build/assets/agent-server-conversation-service.api-B82pNNTm.js +0 -5
- package/build/assets/browser-DTei6kki.js +0 -5
- package/build/assets/chat-send-button-06dIuWXm.js +0 -1
- package/build/assets/conversation-CBlJiDaV.js +0 -19
- package/build/assets/conversation-Dss8XCN_.js +0 -1
- package/build/assets/conversation-panel-B5sVpsz5.js +0 -1
- package/build/assets/conversation-service.api-B4s-xIOK.js +0 -1
- package/build/assets/conversation-store-kHcewy1E.js +0 -1
- package/build/assets/conversation-websocket-context-C2yKCqvj.js +0 -3
- package/build/assets/extensions-navigation-oOk5yl8X.js +0 -1
- package/build/assets/home-ChuA06Hv.js +0 -1
- package/build/assets/install-server-modal--lZ1HSHB.js +0 -1
- package/build/assets/llm-settings-D477P0Lg.js +0 -1
- package/build/assets/llm-settings-DtlQ7i4C.js +0 -1
- package/build/assets/manifest-17af0b17.js +0 -1
- package/build/assets/messages-luW9zf1w.js +0 -36
- package/build/assets/middleware-B5rcobhi.js +0 -6
- package/build/assets/model-selector-DzQRgNGZ.js +0 -1
- package/build/assets/root-layout-pQASEqtQ.js +0 -2
- package/build/assets/sidebar-store-B76R2gP8.js +0 -1
- package/build/assets/telemetry-DCrd7gnV.js +0 -2
- package/build/assets/use-event-store-Rw1YbvLm.js +0 -1
- package/build/assets/use-handle-plan-click-DYd5a6zN.js +0 -1
- package/build/assets/use-runtime-is-ready-DP-KKHO6.js +0 -1
- package/build/assets/use-settings-Clf0Y_P3.js +0 -1
- /package/build/assets/{automation-LZB0MjdV.js → automation-BzmydDjr.js} +0 -0
- /package/build/assets/{browser-store-BjhV_9wS.js → browser-store-C5uQbbIi.js} +0 -0
- /package/build/assets/{checkmark-BB7QCG5T.js → checkmark-SEZPnU2I.js} +0 -0
- /package/build/assets/{chevron-left-small-CuuwpRi9.js → chevron-left-small-x9_-ucHG.js} +0 -0
- /package/build/assets/{close-Cz0OAgTy.js → close-CbOsKMRg.js} +0 -0
- /package/build/assets/{code-tag-Cz9AIz-X.js → code-tag-C0vR_IQH.js} +0 -0
- /package/build/assets/{command-store-DAd3K0d_.js → command-store-BUWgE-vZ.js} +0 -0
- /package/build/assets/{confirmation-modal-C_lds1Tb.js → confirmation-modal-BPgWqWRI.js} +0 -0
- /package/build/assets/{context-menu-list-item-DhG1Ln5m.js → context-menu-list-item-CHWCx1Mc.js} +0 -0
- /package/build/assets/{conversation-state-store-BUU90dVq.js → conversation-state-store-DpgQaK_O.js} +0 -0
- /package/build/assets/{conversation-tab-empty-state-5bW9CQke.js → conversation-tab-empty-state-Ba5hbJhn.js} +0 -0
- /package/build/assets/{copy-CA1Dblua.js → copy-CAxUvM-U.js} +0 -0
- /package/build/assets/{dist-CBUfAk0Z.js → dist-CeJSjcAI.js} +0 -0
- /package/build/assets/{ellipsis-button-DRRmCrWi.js → ellipsis-button-CiLx8dqc.js} +0 -0
- /package/build/assets/{environment-switch-overlay-BrHKX6_Z.js → environment-switch-overlay-Cow6h62p.js} +0 -0
- /package/build/assets/{file-DM0ihEsO.js → file-BJCSojij.js} +0 -0
- /package/build/assets/{files-tab-store-QlUCuW8b.js → files-tab-store-CZAEwv3x.js} +0 -0
- /package/build/assets/{folder-UGYUKpqb.js → folder-wShAU0y7.js} +0 -0
- /package/build/assets/{git-status-mapper-N4-7eaeC.js → git-status-mapper-C3rfzUex.js} +0 -0
- /package/build/assets/{globe-2otpEmVh.js → globe-CQ_5xwpo.js} +0 -0
- /package/build/assets/{handle-capture-consent-OitMkDHc.js → handle-capture-consent-DDnXMC9Y.js} +0 -0
- /package/build/assets/{iconBase-B_5IRYeZ.js → iconBase-1A_WRQ4E.js} +0 -0
- /package/build/assets/{lesson-plan-5O2tVbD1.js → lesson-plan-B607buca.js} +0 -0
- /package/build/assets/{link-external-kU6aFXU6.js → link-external-DCsHkAj4.js} +0 -0
- /package/build/assets/{map-provider-BHow6ugd.js → map-provider-XSFHmdDs.js} +0 -0
- /package/build/assets/{modal-close-button-BCvw9IUN.js → modal-close-button-DY-rVmld.js} +0 -0
- /package/build/assets/{plan-components-BRiIX8Wn.js → plan-components-DsiDjcDi.js} +0 -0
- /package/build/assets/{sdk-settings-field-metadata-CtO73dY6.js → sdk-settings-field-metadata-CETNItbo.js} +0 -0
- /package/build/assets/{search-Cbh-hHBu.js → search-BqXT2Ied.js} +0 -0
- /package/build/assets/{secrets-service-DEIB-Cfk.js → secrets-service-rJqZtDmI.js} +0 -0
- /package/build/assets/{settings-KgLvVrSm.js → settings-BgL2HUsU.js} +0 -0
- /package/build/assets/{settings-gear-xGs_SPgZ.js → settings-gear-DFmoMp-6.js} +0 -0
- /package/build/assets/{settings-input-CPr7vX81.js → settings-input-DsoZj8Dm.js} +0 -0
- /package/build/assets/{settings-like-page-layout-classes-GknosJgv.js → settings-like-page-layout-classes-DENKlZpD.js} +0 -0
- /package/build/assets/{settings-list-classes-CYDn4jUg.js → settings-list-classes-D8VAVZmi.js} +0 -0
- /package/build/assets/{settings-section-header-context-aD2iq1gD.js → settings-section-header-context-D61smD-W.js} +0 -0
- /package/build/assets/{skills-CCaEu1KQ.js → skills-BDOWVle-.js} +0 -0
- /package/build/assets/{switch-skeleton-C87Tx3Tc.js → switch-skeleton-QpdcdxRP.js} +0 -0
- /package/build/assets/{terminal-DQJ6IJUd.js → terminal-BUww3Ssl.js} +0 -0
- /package/build/assets/{toggle-switch-C-7juZ1u.js → toggle-switch-DDr-DnEc.js} +0 -0
- /package/build/assets/{typography-U1gkzkXo.js → typography-Cx7uw7z3.js} +0 -0
- /package/build/assets/{u-check-circle-lbkXL2z4.js → u-check-circle-CftRwky1.js} +0 -0
- /package/build/assets/{u-check-circle-half-CirnoxXG.js → u-check-circle-half-sGVk0BtL.js} +0 -0
- /package/build/assets/{u-circuit-Danff2ks.js → u-circuit-Cg9tH5qb.js} +0 -0
- /package/build/assets/{u-edit-CH5nNya1.js → u-edit-foF02hwH.js} +0 -0
- /package/build/assets/{use-breakpoint-2sN462wJ.js → use-breakpoint-Dt2knceC.js} +0 -0
- /package/build/assets/{use-click-outside-element-_vianyPb.js → use-click-outside-element-Bu2A3s59.js} +0 -0
- /package/build/assets/{use-is-authed-DrocXcet.js → use-is-authed-fNsj-Adj.js} +0 -0
- /package/build/assets/{use-llm-profiles-BhZRf-NX.js → use-llm-profiles-CyNVoVqm.js} +0 -0
- /package/build/assets/{use-skills-v8pQ02ze.js → use-skills-BWHATXK-.js} +0 -0
- /package/build/assets/{v4-BMWDcIWQ.js → v4-BygpdDmc.js} +0 -0
- /package/build/assets/{vendor~browser-C3GKF4mj.js → vendor~browser-BYEwwJqV.js} +0 -0
- /package/build/assets/{vendor~conversation-panel~conversation~alert-banner-DMcFTqbt.js → vendor~conversation-panel~conversation~alert-banner-BnHToS5O.js} +0 -0
- /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
- /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
- /package/build/assets/{vendor~terminal-CnKZILnC.js → vendor~terminal-aeP3PnKf.js} +0 -0
- /package/build/assets/{vscode-url-helper-CwQPl6QN.js → vscode-url-helper-DOCkV_-G.js} +0 -0
- /package/build/assets/{waiting-for-runtime-message-B1Dzhtj5.js → waiting-for-runtime-message-Bg27u9JB.js} +0 -0
- /package/build/assets/{x-mark-CmcVOTk2.js → x-mark-Cn-YJVbN.js} +0 -0
package/scripts/dev-safe.mjs
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
705
|
-
|
|
706
|
-
|
|
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
|
-
|
|
838
|
+
const msg = formatMissingUvxGuidance(options?.cwd);
|
|
839
|
+
console.error(msg);
|
|
840
|
+
fileLog("error", stripAnsi(msg));
|
|
903
841
|
} else if (isEnoentError(error)) {
|
|
904
|
-
|
|
905
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
+
}
|