@openhands/agent-canvas 1.10.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.windows.md +2 -2
- package/build/assets/{acp-providers-DLe_gVDY.js → acp-providers-BkL3HWa3.js} +1 -1
- package/build/assets/{active-backend-context-B0wI7OzM.js → active-backend-context-B_bg5h9O.js} +1 -1
- package/build/assets/{agent-context-settings-CaQtdNA-.js → agent-context-settings-CzWS1DgR.js} +1 -1
- package/build/assets/{agent-profiles-settings-CvuErjp6.js → agent-profiles-settings-hd2cAIZM.js} +1 -1
- package/build/assets/agent-server-conversation-service.api-BheU4HX3.js +86 -0
- package/build/assets/{agent-settings-UE-U4Xii.js → agent-settings-D2J1dKVd.js} +1 -1
- package/build/assets/agent-settings-D_SVrWhI.js +1 -0
- package/build/assets/{alert-banner-BMaOtTCG.js → alert-banner-lrK-2_0Y.js} +1 -1
- package/build/assets/{api-key-entry-screen-Cy66vT4D.js → api-key-entry-screen-D70oJj2c.js} +1 -1
- package/build/assets/app-settings-D0OKHB3M.js +1 -0
- package/build/assets/{automation-detail-fuITm6i3.js → automation-detail-C0SxWTnQ.js} +3 -3
- package/build/assets/{automation-export-CRq40mux.js → automation-export-BjQa_fT6.js} +1 -1
- package/build/assets/{automation-setup-route-EXDazOHW.js → automation-setup-route-BzCNpljP.js} +1 -1
- package/build/assets/{automation-templates-BArZsaxP.js → automation-templates-D9gs6ihu.js} +1 -1
- package/build/assets/{automations-list-CG4HKOTn.js → automations-list-dZg8zOCl.js} +1 -1
- package/build/assets/{back-nav-button-BZB6H7xz.js → back-nav-button-B3pYwmUJ.js} +1 -1
- package/build/assets/{backend-form-modal-B_lXjOGa.js → backend-form-modal-HwclKrUS.js} +1 -1
- package/build/assets/{backend-synced-settings-badge-B_NXJ3u1.js → backend-synced-settings-badge-YI3k09Wr.js} +1 -1
- package/build/assets/{badge-C64c-7PO.js → badge-Dpn3-LTV.js} +1 -1
- package/build/assets/{base-modal-C0RQPug5.js → base-modal-3NmIOKDm.js} +1 -1
- package/build/assets/{brand-button-DJmFCyMK.js → brand-button-CJcwjnfb.js} +1 -1
- package/build/assets/{browser-D3gd2n83.js → browser--eoQOo4M.js} +1 -1
- package/build/assets/{browser-tab-BicAWuJ1.js → browser-tab-4CPdj3J3.js} +1 -1
- package/build/assets/{chat-send-button-CCrH1E8u.js → chat-send-button-B8n6-DQA.js} +1 -1
- package/build/assets/{circle-plus-check-toggle-CB_sNERY.js → circle-plus-check-toggle-BVzv5EkZ.js} +1 -1
- package/build/assets/{cloud-funnel-analytics-XynamQGU.js → cloud-funnel-analytics-CcSez21r.js} +1 -1
- package/build/assets/{combobox-caret-Bwiifgjs.js → combobox-caret-BlmRwiM8.js} +1 -1
- package/build/assets/command-menu-BKOLj-TC.js +1 -0
- package/build/assets/{condenser-settings-cNGy75gq.js → condenser-settings-DLQogFnB.js} +1 -1
- package/build/assets/{confirmation-modal-BATFmFyP.js → confirmation-modal-DAH0XtOp.js} +1 -1
- package/build/assets/{context-menu-list-item-DhJCcBA0.js → context-menu-list-item-BQhmFVEK.js} +1 -1
- package/build/assets/{conversation-Csdxh9Xt.js → conversation-Cmyw9bFh.js} +4 -4
- package/build/assets/conversation-CvoGZ5vC.js +1 -0
- package/build/assets/conversation-panel-CvoGZ5vC.js +1 -0
- package/build/assets/{conversation-state-store-C2QzhPaK.js → conversation-state-store-CtgILxWF.js} +1 -1
- package/build/assets/{conversation-tab-empty-state-D3fb5xIA.js → conversation-tab-empty-state-C9sfDOlt.js} +1 -1
- package/build/assets/{copy-to-clipboard-button-c4MQwKGj.js → copy-to-clipboard-button-DatoElj8.js} +1 -1
- package/build/assets/{device-verify-oFpQoLgm.js → device-verify-BIjXeW9N.js} +1 -1
- package/build/assets/{dropdown-classes-f91ARMV1.js → dropdown-classes-zFW7qPSK.js} +1 -1
- package/build/assets/{entry.client-BCzY2Bf3.js → entry.client-EBn3ZtNP.js} +2 -2
- package/build/assets/{enum-filter-dropdown-HG3q3rkV.js → enum-filter-dropdown-CctILg5t.js} +1 -1
- package/build/assets/{environment-switch-overlay-CquZXolz.js → environment-switch-overlay-Cvmo6clk.js} +1 -1
- package/build/assets/{extensions-hub-BeweE0PW.js → extensions-hub-BZ3HYztk.js} +1 -1
- package/build/assets/{extensions-navigation-Dd58NlUF.js → extensions-navigation-Bnx32WAb.js} +1 -1
- package/build/assets/{files-tab-CLLG55-q.js → files-tab-D5zuU5TY.js} +1 -1
- package/build/assets/{form-control-classes-pHtZUI6K.js → form-control-classes-DLN3Qgub.js} +1 -1
- package/build/assets/format-model-name-BN_rx1Y3.js +1 -0
- package/build/assets/{format-relative-time-6-3uvOXe.js → format-relative-time-BerVamGl.js} +1 -1
- package/build/assets/{git-provider-icon-wg7ShB98.js → git-provider-icon-zuKz2cwo.js} +1 -1
- package/build/assets/{git-repo-dropdown-CWnaUyxL.js → git-repo-dropdown-B5VnMftu.js} +1 -1
- package/build/assets/git-repo-dropdown-Bo7ciSNX.js +1 -0
- package/build/assets/{highlighted-source-view-DBtI3por.js → highlighted-source-view-CgJfD5VT.js} +1 -1
- package/build/assets/home-DqyeeFA_.js +1 -0
- package/build/assets/{home-BpZQkDWM.js → home-Y0aDou-a.js} +1 -1
- package/build/assets/{home-store-DM4qw1lF.js → home-store-Cubdq0uP.js} +1 -1
- package/build/assets/index-home-DqyeeFA_.js +1 -0
- package/build/assets/install-server-modal-DW6dSyGr.js +1 -0
- package/build/assets/{kebab-menu-item-content-By16Tm_0.js → kebab-menu-item-content-CKydZrbH.js} +1 -1
- package/build/assets/{launch-C9uijypN.js → launch-c4GEP8oo.js} +1 -1
- package/build/assets/llm-not-configured-banner-DCE_0B4I.js +27 -0
- package/build/assets/llm-settings-8eWBF3Ij.js +1 -0
- package/build/assets/llm-settings-D9ko42Pi.js +1 -0
- package/build/assets/{llm-subscription-service-DwjJ8-_X.js → llm-subscription-service-B3K-97lP.js} +1 -1
- package/build/assets/{loading-spinner-6Yj-YyoS.js → loading-spinner-CN3riY7k.js} +1 -1
- package/build/assets/{manage-backends-modal-DrwErS0N.js → manage-backends-modal-DTCME_Pu.js} +1 -1
- package/build/assets/manifest-e1c3bc3b.js +1 -0
- package/build/assets/{manifest-subpage-layout-CtqVwIvJ.js → manifest-subpage-layout-Ds7G5GZ8.js} +1 -1
- package/build/assets/map-provider-7Bp2aih5.js +1 -0
- package/build/assets/markdown-renderer-DzvgdZey.js +8 -0
- package/build/assets/mcp-Da7wFU7A.js +9 -0
- package/build/assets/{mcp-marketplace-utils-BMnYz0Gc.js → mcp-marketplace-utils-DSLou4n7.js} +1 -1
- package/build/assets/messages-B2l0qLVk.js +40 -0
- package/build/assets/{modal-body-BHGCSAtj.js → modal-body-duRaxj_K.js} +1 -1
- package/build/assets/{modal-classes-DSTLuxkA.js → modal-classes-CLEXO6dj.js} +1 -1
- package/build/assets/{modal-close-button-dheWZ2ys.js → modal-close-button-D0aT02hs.js} +1 -1
- package/build/assets/npm-Cswluf6-.js +1 -0
- package/build/assets/{onboarding-5CZvRBbh.js → onboarding-BKbTYlW1.js} +1 -1
- package/build/assets/{onboarding-modal-CD2ehuxt.js → onboarding-modal-DrrGlEQq.js} +1 -1
- package/build/assets/{organization-service.api-Dsuoep0g.js → organization-service.api-DK8csGvK.js} +1 -1
- package/build/assets/{planner-tab-DeO7Thb0.js → planner-tab-D-mZ1I7n.js} +1 -1
- package/build/assets/{plugins-management-service-C9f75R6X.js → plugins-management-service-CywqyfLK.js} +1 -1
- package/build/assets/{profiles-service.api-Dl20_2IM.js → profiles-service.api-vcE_jJCe.js} +1 -1
- package/build/assets/{providers-CeuhK46N.js → providers-CdrPPm0z.js} +1 -1
- package/build/assets/{proxy-CIGI9zQC.js → proxy-b4aqL4SX.js} +1 -1
- package/build/assets/recommended-automations-launcher-DIYgUdMm.js +1 -0
- package/build/assets/{root-BQPNqNvD.js → root-CBBi6IAe.js} +2 -2
- package/build/assets/root-CRK9fOFd.css +1 -0
- package/build/assets/root-layout-BFN2rCOy.js +2 -0
- package/build/assets/{schema-field-z2vSLuLo.js → schema-field-Z-rMg9ti.js} +1 -1
- package/build/assets/{sdk-section-page-BnCXAytf.js → sdk-section-page-m_cjygxR.js} +1 -1
- package/build/assets/{secrets-service-DGUNlwQd.js → secrets-service-BHF4fxML.js} +1 -1
- package/build/assets/{secrets-settings-DUmML_dK.js → secrets-settings-aBGXtQhX.js} +1 -1
- package/build/assets/{segmented-toggle-eSofF7gn.js → segmented-toggle-SmvsR3jW.js} +1 -1
- package/build/assets/settings-CZPGNens.js +1 -0
- package/build/assets/{settings-dropdown-input-Cx4g7Xfl.js → settings-dropdown-input-TWIeiG02.js} +1 -1
- package/build/assets/{settings-index-BECdgecg.js → settings-index-Dtlegd6s.js} +1 -1
- package/build/assets/{settings-input-BQY115xH.js → settings-input-D61Vzp9e.js} +1 -1
- package/build/assets/{settings-list-classes-C9cLrrcc.js → settings-list-classes-sE0ASr1s.js} +1 -1
- package/build/assets/{settings-modal-ChBJNTdd.js → settings-modal-CalzJP2l.js} +1 -1
- package/build/assets/{settings-service.api-Dz9cZyvx.js → settings-service.api-DfPYaxZJ.js} +1 -1
- package/build/assets/{settings-switch-BIodMVz9.js → settings-switch-Drt-rF5s.js} +1 -1
- package/build/assets/{settings-utils-BL_Z9uIe.js → settings-utils-gw2ppAvw.js} +1 -1
- package/build/assets/{shared-conversation-CSF0aTuE.js → shared-conversation-BIAcuORk.js} +1 -1
- package/build/assets/{wrench-DRitTfwe.js → shield-check-D2cpEpv3.js} +1 -1
- package/build/assets/{sidebar-layout-DEycoFd_.js → sidebar-layout-Dxg6zc2K.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-DeRvTupV.js → sidebar-mobile-menu-toggle-C6HpQ55l.js} +1 -1
- package/build/assets/{sidebar-nav-link-BjpQ-NVc.js → sidebar-nav-link-CxLoG-dG.js} +1 -1
- package/build/assets/sidebar-store-BJeYY-E9.js +1 -0
- package/build/assets/{skill-card-pill-row-BH6fPGba.js → skill-card-pill-row-B_BYBONu.js} +1 -1
- package/build/assets/{skill-icon-badge-D4uznfjU.js → skill-icon-badge-CN41Hy9l.js} +1 -1
- package/build/assets/{skill-scope-DH_AUUUP.js → skill-scope-Dt1V5X2p.js} +1 -1
- package/build/assets/{skills-plugins-vfvOk34h.js → skills-plugins-B-H0cCOP.js} +1 -1
- package/build/assets/skills-settings-DthdIDUb.js +2 -0
- package/build/assets/{styled-tooltip-CQ9JEFiO.js → styled-tooltip-C5C07RQC.js} +1 -1
- package/build/assets/{task-list-tab-DeF_uXdw.js → task-list-tab-BTde81Iu.js} +1 -1
- package/build/assets/{terminal-DRc4rup7.js → terminal-DRrJo-cR.js} +1 -1
- package/build/assets/{toggle-switch--8n8NeV_.js → toggle-switch-CIioisto.js} +1 -1
- package/build/assets/{typography-BSbUhJPn.js → typography-D9tiHct7.js} +1 -1
- package/build/assets/{use-acp-credential-form-BGKFi1VL.js → use-acp-credential-form-DGyo0QvL.js} +1 -1
- package/build/assets/{use-activate-agent-profile-2nvALjC-.js → use-activate-agent-profile-DrPzIKJF.js} +1 -1
- package/build/assets/{use-agent-profiles-BlQA67MW.js → use-agent-profiles-B37XWDLq.js} +1 -1
- package/build/assets/{use-can-manage-org-profiles-Clw5Dh1s.js → use-can-manage-org-profiles-BzE28H3x.js} +1 -1
- package/build/assets/{use-cloud-current-user-id-B8AQSQFM.js → use-cloud-current-user-id-U6HPjy50.js} +1 -1
- package/build/assets/{use-config-C3zGuUQI.js → use-config-DapX3pjC.js} +1 -1
- package/build/assets/{use-create-conversation-FaP0kUpg.js → use-create-conversation-CRf1dCm5.js} +1 -1
- package/build/assets/{use-create-secret-CgQ3pXd6.js → use-create-secret-DcpT3RPw.js} +1 -1
- package/build/assets/{use-llm-profiles-C-tDO6UB.js → use-llm-profiles-CHxqoHiN.js} +1 -1
- package/build/assets/{use-manifest-capabilities-DLP5wCxp.js → use-manifest-capabilities-zihHDbMW.js} +1 -1
- package/build/assets/{use-onboarding-completion-BiCdXvlU.js → use-onboarding-completion-6kWOW3ul.js} +1 -1
- package/build/assets/{use-plugins-marketplace-DRFNLBlr.js → use-plugins-marketplace-CqkR8kLE.js} +1 -1
- package/build/assets/{use-save-agent-profile-CaGVAudI.js → use-save-agent-profile-CH9_EXQG.js} +1 -1
- package/build/assets/{use-save-settings-C9B8Y-h3.js → use-save-settings-DIEurJ3D.js} +1 -1
- package/build/assets/{use-settings-3RcgdUuZ.js → use-settings-BmLzQjnC.js} +1 -1
- package/build/assets/use-settings-nav-items-DV9qgeu7.js +16 -0
- package/build/assets/{use-tracking-CTtkLAmx.js → use-tracking-salbPJxT.js} +1 -1
- package/build/assets/{use-user-conversation-Bei82QsZ.js → use-user-conversation-Dt-W6uNw.js} +1 -1
- package/build/assets/utils-DPQfkd-7.js +1 -0
- package/build/assets/{verification-settings-nD61Ijph.js → verification-settings-oi54wEc1.js} +1 -1
- package/build/assets/wrench-B1_H-tL1.js +1 -0
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +39 -2
- package/build/locales/ca/openhands.json +39 -2
- package/build/locales/de/openhands.json +39 -2
- package/build/locales/en/openhands.json +39 -2
- package/build/locales/es/openhands.json +39 -2
- package/build/locales/fr/openhands.json +39 -2
- package/build/locales/it/openhands.json +39 -2
- package/build/locales/ja/openhands.json +39 -2
- package/build/locales/ko-KR/openhands.json +39 -2
- package/build/locales/no/openhands.json +39 -2
- package/build/locales/pt/openhands.json +39 -2
- package/build/locales/tr/openhands.json +39 -2
- package/build/locales/uk/openhands.json +39 -2
- package/build/locales/zh-CN/openhands.json +39 -2
- package/build/locales/zh-TW/openhands.json +39 -2
- package/config/defaults.json +1 -1
- 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.d.ts +32 -5
- package/dist/api/agent-server-adapter.js +120 -91
- package/dist/api/agent-server-adapter.js.map +1 -1
- package/dist/api/cloud/conversation-service.api.cjs +1 -1
- package/dist/api/cloud/conversation-service.api.cjs.map +1 -1
- package/dist/api/cloud/conversation-service.api.d.ts +19 -2
- package/dist/api/cloud/conversation-service.api.js +51 -47
- package/dist/api/cloud/conversation-service.api.js.map +1 -1
- package/dist/api/conversation-file-upload.api.cjs +1 -1
- package/dist/api/conversation-file-upload.api.js +10 -10
- package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.js +55 -61
- package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
- package/dist/api/event-service/event-service.api.cjs +1 -1
- package/dist/api/event-service/event-service.api.js +12 -12
- package/dist/api/launch-child-conversation-client-tool.cjs +47 -0
- package/dist/api/launch-child-conversation-client-tool.cjs.map +1 -0
- package/dist/api/launch-child-conversation-client-tool.d.ts +3 -0
- package/dist/api/launch-child-conversation-client-tool.js +93 -0
- package/dist/api/launch-child-conversation-client-tool.js.map +1 -0
- package/dist/api/open-hands.types.d.ts +1 -1
- package/dist/api/workspace-upload-path.cjs +1 -1
- package/dist/api/workspace-upload-path.js +8 -8
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js +24 -18
- package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js +5 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.cjs +2 -2
- 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 +11 -7
- package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.js.map +1 -1
- package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs +1 -1
- package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs.map +1 -1
- package/dist/components/features/chat/components/chat-input-llm-profile-picker.js +61 -60
- package/dist/components/features/chat/components/chat-input-llm-profile-picker.js.map +1 -1
- package/dist/components/features/chat/model-messages.cjs +1 -1
- package/dist/components/features/chat/model-messages.cjs.map +1 -1
- package/dist/components/features/chat/model-messages.js +26 -25
- package/dist/components/features/chat/model-messages.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs +1 -2
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.d.ts +2 -8
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js +50 -53
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.cjs +2 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.cjs.map +1 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.d.ts +12 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.js +6 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.js.map +1 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.d.ts +16 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js +95 -78
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.js +40 -38
- package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs +2 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs.map +1 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.d.ts +14 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js +167 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js.map +1 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs +2 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs.map +1 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.d.ts +63 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js +66 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js.map +1 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.cjs +2 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.cjs.map +1 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.d.ts +15 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.js +117 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.js.map +1 -0
- package/dist/components/features/conversation-panel/conversation-card/no-repository.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-card/no-repository.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/no-repository.js +30 -19
- package/dist/components/features/conversation-panel/conversation-card/no-repository.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-panel-filter-menu.d.ts +7 -2
- package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js +146 -104
- package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-panel-list-helpers.d.ts +20 -0
- package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js +53 -27
- package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-panel.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-panel.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-panel.js +226 -213
- package/dist/components/features/conversation-panel/conversation-panel.js.map +1 -1
- package/dist/components/features/settings/agent-canvas-update-card.cjs +1 -1
- package/dist/components/features/settings/agent-canvas-update-card.cjs.map +1 -1
- package/dist/components/features/settings/agent-canvas-update-card.d.ts +10 -5
- package/dist/components/features/settings/agent-canvas-update-card.js +223 -149
- package/dist/components/features/settings/agent-canvas-update-card.js.map +1 -1
- package/dist/components/features/settings/agent-canvas-version-modal.cjs +2 -0
- package/dist/components/features/settings/agent-canvas-version-modal.cjs.map +1 -0
- package/dist/components/features/settings/agent-canvas-version-modal.d.ts +11 -0
- package/dist/components/features/settings/agent-canvas-version-modal.js +166 -0
- package/dist/components/features/settings/agent-canvas-version-modal.js.map +1 -0
- package/dist/components/features/settings/agent-canvas-version-tile.cjs +2 -0
- package/dist/components/features/settings/agent-canvas-version-tile.cjs.map +1 -0
- package/dist/components/features/settings/agent-canvas-version-tile.d.ts +13 -0
- package/dist/components/features/settings/agent-canvas-version-tile.js +60 -0
- package/dist/components/features/settings/agent-canvas-version-tile.js.map +1 -0
- package/dist/components/features/settings/llm-profiles/profile-row.cjs +1 -1
- package/dist/components/features/settings/llm-profiles/profile-row.js +1 -0
- package/dist/components/features/settings/settings-desktop-sidebar.cjs +1 -1
- package/dist/components/features/settings/settings-desktop-sidebar.cjs.map +1 -1
- package/dist/components/features/settings/settings-desktop-sidebar.js +1 -1
- package/dist/components/features/settings/settings-desktop-sidebar.js.map +1 -1
- package/dist/components/features/settings/settings-mobile-drawer.cjs +1 -1
- package/dist/components/features/settings/settings-mobile-drawer.cjs.map +1 -1
- package/dist/components/features/settings/settings-mobile-drawer.js +1 -1
- package/dist/components/features/settings/settings-mobile-drawer.js.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.js +109 -108
- package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
- 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.js +9 -9
- package/dist/components/features/skills/extensions-navigation.js.map +1 -1
- package/dist/components/shared/modals/settings/model-selector.cjs +1 -1
- package/dist/components/shared/modals/settings/model-selector.cjs.map +1 -1
- package/dist/components/shared/modals/settings/model-selector.js +154 -98
- package/dist/components/shared/modals/settings/model-selector.js.map +1 -1
- package/dist/config/defaults.cjs +1 -1
- package/dist/config/defaults.cjs.map +1 -1
- package/dist/config/defaults.js +1 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/constants/child-conversation.cjs +2 -0
- package/dist/constants/child-conversation.cjs.map +1 -0
- package/dist/constants/child-conversation.d.ts +29 -0
- package/dist/constants/child-conversation.js +6 -0
- package/dist/constants/child-conversation.js.map +1 -0
- package/dist/contexts/conversation-websocket-context.cjs +3 -3
- package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
- package/dist/contexts/conversation-websocket-context.js +189 -188
- package/dist/contexts/conversation-websocket-context.js.map +1 -1
- package/dist/hooks/chat/use-model-interceptor.cjs +1 -1
- package/dist/hooks/chat/use-model-interceptor.js +6 -6
- package/dist/hooks/chat/use-slash-command.cjs +1 -1
- package/dist/hooks/chat/use-slash-command.cjs.map +1 -1
- package/dist/hooks/chat/use-slash-command.js +61 -60
- package/dist/hooks/chat/use-slash-command.js.map +1 -1
- package/dist/hooks/mutation/use-create-conversation.cjs +1 -1
- package/dist/hooks/mutation/use-create-conversation.js +6 -6
- package/dist/i18n/declaration.cjs +1 -1
- package/dist/i18n/declaration.cjs.map +1 -1
- package/dist/i18n/declaration.d.ts +38 -1
- package/dist/i18n/declaration.js +1 -1
- package/dist/i18n/declaration.js.map +1 -1
- package/dist/i18n/translation.cjs +2 -2
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +644 -15
- package/dist/i18n/translation.js.map +1 -1
- package/dist/icons/docker.cjs +2 -0
- package/dist/icons/docker.cjs.map +1 -0
- package/dist/icons/docker.js +19 -0
- package/dist/icons/docker.js.map +1 -0
- package/dist/icons/npm.cjs +2 -0
- package/dist/icons/npm.cjs.map +1 -0
- package/dist/icons/npm.js +19 -0
- package/dist/icons/npm.js.map +1 -0
- package/dist/locales/ar/openhands.json +39 -2
- package/dist/locales/ca/openhands.json +39 -2
- package/dist/locales/de/openhands.json +39 -2
- package/dist/locales/en/openhands.json +39 -2
- package/dist/locales/es/openhands.json +39 -2
- package/dist/locales/fr/openhands.json +39 -2
- package/dist/locales/it/openhands.json +39 -2
- package/dist/locales/ja/openhands.json +39 -2
- package/dist/locales/ko-KR/openhands.json +39 -2
- package/dist/locales/no/openhands.json +39 -2
- package/dist/locales/pt/openhands.json +39 -2
- package/dist/locales/tr/openhands.json +39 -2
- package/dist/locales/uk/openhands.json +39 -2
- package/dist/locales/zh-CN/openhands.json +39 -2
- package/dist/locales/zh-TW/openhands.json +39 -2
- package/dist/node_modules/@openhands/typescript-client/dist/index.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/index.js +1 -1
- package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.js +16 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/building-2.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/building-2.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/building-2.js +27 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/building-2.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.js +21 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.js +23 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.js +43 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/earth.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/earth.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/earth.js +25 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/earth.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/flag.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/flag.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/flag.js +9 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/flag.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.js +27 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.js +25 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.js +30 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/hash.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/hash.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/hash.js +35 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/hash.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/house.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/house.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/house.js +12 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/house.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/id-card.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/id-card.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/id-card.js +33 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/id-card.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/key-round.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/key-round.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/key-round.js +15 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/key-round.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/layers.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/layers.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/layers.js +19 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/layers.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/link-2.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/link-2.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/link-2.js +22 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/link-2.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/mails.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/mails.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/mails.js +23 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/mails.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.js +12 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/plug.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/plug.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/plug.js +23 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/plug.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.js +27 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/ticket.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/ticket.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/ticket.js +23 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/ticket.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/users-round.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/users-round.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/users-round.js +21 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/users-round.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.js +43 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/webhook.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/webhook.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/webhook.js +19 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/webhook.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/workflow.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/workflow.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/workflow.js +27 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/workflow.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/wrench.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/wrench.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/wrench.js +9 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/wrench.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/zap.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/zap.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/zap.js +9 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/zap.js.map +1 -0
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +6 -3
- package/dist/package.js.map +1 -1
- package/dist/routes/app-settings.cjs +1 -1
- package/dist/routes/app-settings.cjs.map +1 -1
- package/dist/routes/app-settings.js +94 -93
- package/dist/routes/app-settings.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 +131 -119
- package/dist/routes/llm-settings.js.map +1 -1
- package/dist/services/child-conversation-launch.cjs +2 -0
- package/dist/services/child-conversation-launch.cjs.map +1 -0
- package/dist/services/child-conversation-launch.d.ts +41 -0
- package/dist/services/child-conversation-launch.js +182 -0
- package/dist/services/child-conversation-launch.js.map +1 -0
- package/dist/stores/conversation-panel-preferences-store.cjs +1 -1
- package/dist/stores/conversation-panel-preferences-store.cjs.map +1 -1
- package/dist/stores/conversation-panel-preferences-store.d.ts +5 -1
- package/dist/stores/conversation-panel-preferences-store.js +8 -2
- package/dist/stores/conversation-panel-preferences-store.js.map +1 -1
- package/dist/types/agent-server/core/base/action.d.ts +17 -1
- package/dist/types/agent-server/core/base/base.d.ts +2 -1
- 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 +8 -1
- package/dist/types/agent-server/type-guards.js +4 -3
- package/dist/types/agent-server/type-guards.js.map +1 -1
- package/dist/types/automation.d.ts +14 -0
- package/dist/utils/custom-toast-handlers.cjs +1 -1
- package/dist/utils/custom-toast-handlers.cjs.map +1 -1
- package/dist/utils/custom-toast-handlers.js +18 -1
- package/dist/utils/custom-toast-handlers.js.map +1 -1
- package/dist/utils/format-model-name.cjs +1 -1
- package/dist/utils/format-model-name.cjs.map +1 -1
- package/dist/utils/format-model-name.d.ts +11 -0
- package/dist/utils/format-model-name.js +11 -3
- package/dist/utils/format-model-name.js.map +1 -1
- package/package.json +6 -3
- package/scripts/brand-dev-electron.mjs +244 -0
- package/scripts/check-translation-completeness.cjs +4 -0
- package/scripts/generate-icons.mjs +109 -0
- package/build/assets/agent-server-conversation-service.api-km_8sOVf.js +0 -41
- package/build/assets/agent-settings-nmO-KSXr.js +0 -1
- package/build/assets/app-settings-9ok42bV6.js +0 -1
- package/build/assets/command-menu-CA3IjGNc.js +0 -1
- package/build/assets/conversation-B6t6EiVp.js +0 -1
- package/build/assets/conversation-panel-B6t6EiVp.js +0 -1
- package/build/assets/copy-DaHuDtG4.js +0 -1
- package/build/assets/git-repo-dropdown-TzOuG5Ef.js +0 -1
- package/build/assets/home-OEx0XtfP.js +0 -1
- package/build/assets/index-home-OEx0XtfP.js +0 -1
- package/build/assets/install-server-modal-DnjZrJUy.js +0 -1
- package/build/assets/list-filter-C86CBRDE.js +0 -1
- package/build/assets/llm-not-configured-banner-DrBrhfN0.js +0 -27
- package/build/assets/llm-settings-CRsLqxgu.js +0 -1
- package/build/assets/llm-settings-RBm_3kNm.js +0 -1
- package/build/assets/manifest-c352d453.js +0 -1
- package/build/assets/map-provider-CXU6issd.js +0 -1
- package/build/assets/markdown-renderer-lsvsp7jn.js +0 -8
- package/build/assets/mcp-DD4hPTRE.js +0 -9
- package/build/assets/messages-Dt77e0qi.js +0 -40
- package/build/assets/recommended-automations-launcher-6xmbf7lh.js +0 -1
- package/build/assets/root-BeuHFY2s.css +0 -1
- package/build/assets/root-layout-Dl_2CDoq.js +0 -3
- package/build/assets/settings-Co-M5bK9.js +0 -1
- package/build/assets/sidebar-store-B04sX8aP.js +0 -1
- package/build/assets/skills-settings-DnbIu2eO.js +0 -2
- package/build/assets/use-settings-nav-items-y-Oyc93G.js +0 -16
- package/build/assets/utils-BX9XJ0IE.js +0 -1
- package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs +0 -2
- package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs.map +0 -1
- package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.js +0 -9
- package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-guards.js","names":[],"sources":["../../../src/types/agent-server/type-guards.ts"],"sourcesContent":["import {\n CANVAS_UI_CLIENT_TOOL_NAME,\n LEGACY_CANVAS_UI_TOOL_NAME,\n} from \"#/constants/canvas-ui\";\n\nimport {\n OpenHandsEvent,\n ObservationEvent,\n BaseEvent,\n ExecuteBashAction,\n TerminalAction,\n ExecuteBashObservation,\n PlanningFileEditorObservation,\n TerminalObservation,\n BrowserObservation,\n BrowserNavigateAction,\n SwitchLLMObservation,\n CanvasUIAction,\n} from \"./core\";\nimport { AgentErrorEvent } from \"./core/events/observation-event\";\nimport { MessageEvent } from \"./core/events/message-event\";\nimport { ActionEvent } from \"./core/events/action-event\";\nimport {\n ConversationStateUpdateEvent,\n ConversationStateUpdateEventAgentStatus,\n ConversationStateUpdateEventFullState,\n ConversationStateUpdateEventStats,\n ConversationStateUpdateEventGoal,\n ConversationErrorEvent,\n ServerErrorEvent,\n} from \"./core/events/conversation-state-event\";\nimport { HookExecutionEvent } from \"./core/events/hook-execution-event\";\nimport { ACPToolCallEvent } from \"./core/events/acp-tool-call-event\";\nimport { StreamingDeltaEvent } from \"./core/events/streaming-delta-event\";\nimport { SystemPromptEvent } from \"./core/events/system-event\";\n\n/**\n * Type guard to check if an unknown value is a valid BaseEvent\n * @param value - The value to check\n * @returns true if the value is a valid BaseEvent\n */\nexport function isBaseEvent(value: unknown): value is BaseEvent {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"id\" in value &&\n \"timestamp\" in value &&\n \"source\" in value &&\n typeof value.id === \"string\" &&\n value.id.length > 0 &&\n typeof value.timestamp === \"string\" &&\n value.timestamp.length > 0 &&\n typeof value.source === \"string\" &&\n (value.source === \"agent\" ||\n value.source === \"user\" ||\n value.source === \"environment\" ||\n value.source === \"hook\")\n );\n}\n\n/**\n * Type guard function to check if an event is an observation event\n */\nexport const isObservationEvent = (\n event: OpenHandsEvent,\n): event is ObservationEvent =>\n event.source === \"environment\" &&\n \"action_id\" in event &&\n \"observation\" in event &&\n event.observation !== null &&\n typeof event.observation === \"object\" &&\n \"kind\" in event.observation;\n\n/**\n * Type guard function to check if an event is an agent error event\n */\nexport const isAgentErrorEvent = (\n event: OpenHandsEvent,\n): event is AgentErrorEvent =>\n event.source === \"agent\" &&\n \"tool_name\" in event &&\n \"tool_call_id\" in event &&\n \"error\" in event &&\n typeof event.tool_name === \"string\" &&\n typeof event.tool_call_id === \"string\" &&\n typeof event.error === \"string\";\n\n/**\n * Type guard function to check if an event is a message event (user or assistant)\n */\nexport const isMessageEvent = (event: OpenHandsEvent): event is MessageEvent =>\n \"llm_message\" in event &&\n typeof event.llm_message === \"object\" &&\n event.llm_message !== null &&\n \"role\" in event.llm_message &&\n \"content\" in event.llm_message;\n\n/**\n * Type guard function to check if an event is a user message event\n */\nexport const isUserMessageEvent = (\n event: OpenHandsEvent,\n): event is MessageEvent =>\n isMessageEvent(event) && event.llm_message.role === \"user\";\n\n/**\n * Type guard function to check if an event is an action event\n */\nexport const isActionEvent = (event: OpenHandsEvent): event is ActionEvent =>\n event.source === \"agent\" &&\n \"action\" in event &&\n event.action !== null &&\n typeof event.action === \"object\" &&\n \"kind\" in event.action &&\n \"tool_name\" in event &&\n \"tool_call_id\" in event &&\n typeof event.tool_name === \"string\" &&\n typeof event.tool_call_id === \"string\";\n\n/**\n * Type guard function to check if an action event is an ExecuteBashAction\n */\nexport const isExecuteBashActionEvent = (\n event: OpenHandsEvent,\n): event is ActionEvent<ExecuteBashAction | TerminalAction> =>\n isActionEvent(event) &&\n (event.action.kind === \"ExecuteBashAction\" ||\n event.action.kind === \"TerminalAction\");\n\n/**\n * Type guard function to check if an observation event contains terminal output\n */\nexport const isExecuteBashObservationEvent = (\n event: OpenHandsEvent,\n): event is ObservationEvent<ExecuteBashObservation | TerminalObservation> =>\n isObservationEvent(event) &&\n (event.observation.kind === \"ExecuteBashObservation\" ||\n event.observation.kind === \"TerminalObservation\");\n\n/**\n * Type guard function to check if an observation event is a PlanningFileEditorObservation\n */\nexport const isPlanningFileEditorObservationEvent = (\n event: OpenHandsEvent,\n): event is ObservationEvent<PlanningFileEditorObservation> =>\n isObservationEvent(event) &&\n event.observation.kind === \"PlanningFileEditorObservation\";\n\n/**\n * Type guard function to check if an observation event is a BrowserObservation\n */\nexport const isBrowserObservationEvent = (\n event: OpenHandsEvent,\n): event is ObservationEvent<BrowserObservation> =>\n isObservationEvent(event) && event.observation.kind === \"BrowserObservation\";\n\n/**\n * Type guard function to check if an observation event is a SwitchLLMObservation\n */\nexport const isSwitchLLMObservationEvent = (\n event: OpenHandsEvent,\n): event is ObservationEvent<SwitchLLMObservation> =>\n isObservationEvent(event) &&\n event.observation.kind === \"SwitchLLMObservation\";\n\n/**\n * Type guard function to check if an action event is a BrowserNavigateAction\n */\nexport const isBrowserNavigateActionEvent = (\n event: OpenHandsEvent,\n): event is ActionEvent<BrowserNavigateAction> =>\n isActionEvent(event) && event.action.kind === \"BrowserNavigateAction\";\n\n/**\n * Type guard for Canvas UI tool ActionEvents.\n *\n * Discriminating on tool_name supports legacy CanvasUIAction events and the\n * SDK-generated action kind without leaking that generated name here.\n */\nexport const isCanvasUIActionEvent = (\n event: OpenHandsEvent,\n): event is ActionEvent<CanvasUIAction> =>\n isActionEvent(event) &&\n (event.tool_name === LEGACY_CANVAS_UI_TOOL_NAME ||\n event.tool_name === CANVAS_UI_CLIENT_TOOL_NAME);\n\n/**\n * Type guard function to check if an event is a system prompt event\n */\nexport const isSystemPromptEvent = (\n event: OpenHandsEvent,\n): event is SystemPromptEvent =>\n event.source === \"agent\" &&\n \"system_prompt\" in event &&\n \"tools\" in event &&\n typeof event.system_prompt === \"object\" &&\n Array.isArray(event.tools);\n\n/**\n * Type guard function to check if an event is a conversation state update event\n */\nexport const isConversationStateUpdateEvent = (\n event: OpenHandsEvent,\n): event is ConversationStateUpdateEvent =>\n \"kind\" in event && event.kind === \"ConversationStateUpdateEvent\";\n\nexport const isFullStateConversationStateUpdateEvent = (\n event: ConversationStateUpdateEvent,\n): event is ConversationStateUpdateEventFullState => event.key === \"full_state\";\n\nexport const isAgentStatusConversationStateUpdateEvent = (\n event: ConversationStateUpdateEvent,\n): event is ConversationStateUpdateEventAgentStatus =>\n event.key === \"execution_status\";\n\nexport const isStatsConversationStateUpdateEvent = (\n event: ConversationStateUpdateEvent,\n): event is ConversationStateUpdateEventStats => event.key === \"stats\";\n\nexport const isGoalConversationStateUpdateEvent = (\n event: ConversationStateUpdateEvent,\n): event is ConversationStateUpdateEventGoal => event.key === \"goal\";\n\n/**\n * Type guard function to check if an event is a conversation error event\n */\nexport const isConversationErrorEvent = (\n event: OpenHandsEvent,\n): event is ConversationErrorEvent =>\n \"kind\" in event && event.kind === \"ConversationErrorEvent\";\n\n/**\n * Type guard function to check if an event is a server error event\n */\nexport const isServerErrorEvent = (\n event: OpenHandsEvent,\n): event is ServerErrorEvent =>\n \"kind\" in event && event.kind === \"ServerErrorEvent\";\n\n/**\n * Type guard function to check if an event is a displayable error event\n * (ConversationErrorEvent or ServerErrorEvent) - both should show as error banners\n */\nexport const isDisplayableErrorEvent = (event: OpenHandsEvent): boolean =>\n isConversationErrorEvent(event) || isServerErrorEvent(event);\n\n/**\n * Type guard function to check if an event is a hook execution event\n */\nexport const isHookExecutionEvent = (\n event: OpenHandsEvent,\n): event is HookExecutionEvent =>\n \"kind\" in event && event.kind === \"HookExecutionEvent\";\n\n/**\n * Type guard function to check if an event is an ACP tool call event\n */\nexport const isACPToolCallEvent = (\n event: OpenHandsEvent,\n): event is ACPToolCallEvent =>\n \"kind\" in event && event.kind === \"ACPToolCallEvent\";\n\nexport const isStreamingDeltaEvent = (\n event: OpenHandsEvent,\n): event is StreamingDeltaEvent =>\n \"kind\" in event && event.kind === \"StreamingDeltaEvent\";\n\n// =============================================================================\n// COMPATIBILITY TYPE GUARDS\n// =============================================================================\n\n/**\n * Type guard to check if an event is an agent-server OpenHandsEvent.\n * Uses isBaseEvent to validate the complete event structure.\n */\nexport function isAgentServerEvent(event: unknown): event is OpenHandsEvent {\n return isBaseEvent(event);\n}\n"],"mappings":";;AAyCA,SAAgB,EAAY,GAAoC;CAC9D,OAEE,OAAO,KAAU,cADjB,KAEA,QAAQ,KACR,eAAe,KACf,YAAY,KACZ,OAAO,EAAM,MAAO,YACpB,EAAM,GAAG,SAAS,KAClB,OAAO,EAAM,aAAc,YAC3B,EAAM,UAAU,SAAS,KACzB,OAAO,EAAM,UAAW,aACvB,EAAM,WAAW,WAChB,EAAM,WAAW,UACjB,EAAM,WAAW,iBACjB,EAAM,WAAW;AAEvB;AAKA,IAAa,KACX,MAEA,EAAM,WAAW,iBACjB,eAAe,KACf,iBAAiB,KACjB,EAAM,gBAAgB,QACtB,OAAO,EAAM,eAAgB,YAC7B,UAAU,EAAM,aAKL,KACX,MAEA,EAAM,WAAW,WACjB,eAAe,KACf,kBAAkB,KAClB,WAAW,KACX,OAAO,EAAM,aAAc,YAC3B,OAAO,EAAM,gBAAiB,YAC9B,OAAO,EAAM,SAAU,UAKZ,KAAkB,MAC7B,iBAAiB,KACjB,OAAO,EAAM,eAAgB,YAC7B,EAAM,gBAAgB,QACtB,UAAU,EAAM,eAChB,aAAa,EAAM,aAKR,KACX,MAEA,EAAe,CAAK,KAAK,EAAM,YAAY,SAAS,QAKzC,KAAiB,MAC5B,EAAM,WAAW,WACjB,YAAY,KACZ,EAAM,WAAW,QACjB,OAAO,EAAM,UAAW,YACxB,UAAU,EAAM,UAChB,eAAe,KACf,kBAAkB,KAClB,OAAO,EAAM,aAAc,YAC3B,OAAO,EAAM,gBAAiB,UAKnB,KACX,MAEA,EAAc,CAAK,MAClB,EAAM,OAAO,SAAS,uBACrB,EAAM,OAAO,SAAS,mBAKb,KACX,MAEA,EAAmB,CAAK,MACvB,EAAM,YAAY,SAAS,4BAC1B,EAAM,YAAY,SAAS,wBAKlB,KACX,MAEA,EAAmB,CAAK,KACxB,EAAM,YAAY,SAAS,iCAKhB,KACX,MAEA,EAAmB,CAAK,KAAK,EAAM,YAAY,SAAS,sBAK7C,KACX,MAEA,EAAmB,CAAK,KACxB,EAAM,YAAY,SAAS,wBAKhB,KACX,MAEA,EAAc,CAAK,KAAK,EAAM,OAAO,SAAS,yBAQnC,KACX,MAEA,EAAc,CAAK,MAClB,EAAM,cAAA,eACL,EAAM,cAAA,sBAKG,KACX,MAEA,EAAM,WAAW,WACjB,mBAAmB,KACnB,WAAW,KACX,OAAO,EAAM,iBAAkB,YAC/B,MAAM,QAAQ,EAAM,KAAK,GAKd,KACX,MAEA,UAAU,KAAS,EAAM,SAAS,gCAEvB,KACX,MACmD,EAAM,QAAQ,cAEtD,KACX,MAEA,EAAM,QAAQ,oBAEH,KACX,MAC+C,EAAM,QAAQ,SAElD,KACX,MAC8C,EAAM,QAAQ,QAKjD,KACX,MAEA,UAAU,KAAS,EAAM,SAAS,0BAKvB,KACX,MAEA,UAAU,KAAS,EAAM,SAAS,oBAMvB,KAA2B,MACtC,EAAyB,CAAK,KAAK,EAAmB,CAAK,GAKhD,KACX,MAEA,UAAU,KAAS,EAAM,SAAS,sBAKvB,KACX,MAEA,UAAU,KAAS,EAAM,SAAS,oBAEvB,KACX,MAEA,UAAU,KAAS,EAAM,SAAS;AAUpC,SAAgB,EAAmB,GAAyC;CAC1E,OAAO,EAAY,CAAK;AAC1B"}
|
|
1
|
+
{"version":3,"file":"type-guards.js","names":[],"sources":["../../../src/types/agent-server/type-guards.ts"],"sourcesContent":["import {\n CANVAS_UI_CLIENT_TOOL_NAME,\n LEGACY_CANVAS_UI_TOOL_NAME,\n} from \"#/constants/canvas-ui\";\nimport { LAUNCH_CHILD_CONVERSATION_TOOL_NAME } from \"#/constants/child-conversation\";\n\nimport {\n OpenHandsEvent,\n ObservationEvent,\n BaseEvent,\n ExecuteBashAction,\n TerminalAction,\n ExecuteBashObservation,\n PlanningFileEditorObservation,\n TerminalObservation,\n BrowserObservation,\n BrowserNavigateAction,\n SwitchLLMObservation,\n CanvasUIAction,\n LaunchChildConversationAction,\n} from \"./core\";\nimport { AgentErrorEvent } from \"./core/events/observation-event\";\nimport { MessageEvent } from \"./core/events/message-event\";\nimport { ActionEvent } from \"./core/events/action-event\";\nimport {\n ConversationStateUpdateEvent,\n ConversationStateUpdateEventAgentStatus,\n ConversationStateUpdateEventFullState,\n ConversationStateUpdateEventStats,\n ConversationStateUpdateEventGoal,\n ConversationErrorEvent,\n ServerErrorEvent,\n} from \"./core/events/conversation-state-event\";\nimport { HookExecutionEvent } from \"./core/events/hook-execution-event\";\nimport { ACPToolCallEvent } from \"./core/events/acp-tool-call-event\";\nimport { StreamingDeltaEvent } from \"./core/events/streaming-delta-event\";\nimport { SystemPromptEvent } from \"./core/events/system-event\";\n\n/**\n * Type guard to check if an unknown value is a valid BaseEvent\n * @param value - The value to check\n * @returns true if the value is a valid BaseEvent\n */\nexport function isBaseEvent(value: unknown): value is BaseEvent {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"id\" in value &&\n \"timestamp\" in value &&\n \"source\" in value &&\n typeof value.id === \"string\" &&\n value.id.length > 0 &&\n typeof value.timestamp === \"string\" &&\n value.timestamp.length > 0 &&\n typeof value.source === \"string\" &&\n (value.source === \"agent\" ||\n value.source === \"user\" ||\n value.source === \"environment\" ||\n value.source === \"hook\")\n );\n}\n\n/**\n * Type guard function to check if an event is an observation event\n */\nexport const isObservationEvent = (\n event: OpenHandsEvent,\n): event is ObservationEvent =>\n event.source === \"environment\" &&\n \"action_id\" in event &&\n \"observation\" in event &&\n event.observation !== null &&\n typeof event.observation === \"object\" &&\n \"kind\" in event.observation;\n\n/**\n * Type guard function to check if an event is an agent error event\n */\nexport const isAgentErrorEvent = (\n event: OpenHandsEvent,\n): event is AgentErrorEvent =>\n event.source === \"agent\" &&\n \"tool_name\" in event &&\n \"tool_call_id\" in event &&\n \"error\" in event &&\n typeof event.tool_name === \"string\" &&\n typeof event.tool_call_id === \"string\" &&\n typeof event.error === \"string\";\n\n/**\n * Type guard function to check if an event is a message event (user or assistant)\n */\nexport const isMessageEvent = (event: OpenHandsEvent): event is MessageEvent =>\n \"llm_message\" in event &&\n typeof event.llm_message === \"object\" &&\n event.llm_message !== null &&\n \"role\" in event.llm_message &&\n \"content\" in event.llm_message;\n\n/**\n * Type guard function to check if an event is a user message event\n */\nexport const isUserMessageEvent = (\n event: OpenHandsEvent,\n): event is MessageEvent =>\n isMessageEvent(event) && event.llm_message.role === \"user\";\n\n/**\n * Type guard function to check if an event is an action event\n */\nexport const isActionEvent = (event: OpenHandsEvent): event is ActionEvent =>\n event.source === \"agent\" &&\n \"action\" in event &&\n event.action !== null &&\n typeof event.action === \"object\" &&\n \"kind\" in event.action &&\n \"tool_name\" in event &&\n \"tool_call_id\" in event &&\n typeof event.tool_name === \"string\" &&\n typeof event.tool_call_id === \"string\";\n\n/**\n * Type guard function to check if an action event is an ExecuteBashAction\n */\nexport const isExecuteBashActionEvent = (\n event: OpenHandsEvent,\n): event is ActionEvent<ExecuteBashAction | TerminalAction> =>\n isActionEvent(event) &&\n (event.action.kind === \"ExecuteBashAction\" ||\n event.action.kind === \"TerminalAction\");\n\n/**\n * Type guard function to check if an observation event contains terminal output\n */\nexport const isExecuteBashObservationEvent = (\n event: OpenHandsEvent,\n): event is ObservationEvent<ExecuteBashObservation | TerminalObservation> =>\n isObservationEvent(event) &&\n (event.observation.kind === \"ExecuteBashObservation\" ||\n event.observation.kind === \"TerminalObservation\");\n\n/**\n * Type guard function to check if an observation event is a PlanningFileEditorObservation\n */\nexport const isPlanningFileEditorObservationEvent = (\n event: OpenHandsEvent,\n): event is ObservationEvent<PlanningFileEditorObservation> =>\n isObservationEvent(event) &&\n event.observation.kind === \"PlanningFileEditorObservation\";\n\n/**\n * Type guard function to check if an observation event is a BrowserObservation\n */\nexport const isBrowserObservationEvent = (\n event: OpenHandsEvent,\n): event is ObservationEvent<BrowserObservation> =>\n isObservationEvent(event) && event.observation.kind === \"BrowserObservation\";\n\n/**\n * Type guard function to check if an observation event is a SwitchLLMObservation\n */\nexport const isSwitchLLMObservationEvent = (\n event: OpenHandsEvent,\n): event is ObservationEvent<SwitchLLMObservation> =>\n isObservationEvent(event) &&\n event.observation.kind === \"SwitchLLMObservation\";\n\n/**\n * Type guard function to check if an action event is a BrowserNavigateAction\n */\nexport const isBrowserNavigateActionEvent = (\n event: OpenHandsEvent,\n): event is ActionEvent<BrowserNavigateAction> =>\n isActionEvent(event) && event.action.kind === \"BrowserNavigateAction\";\n\n/**\n * Type guard for Canvas UI tool ActionEvents.\n *\n * Discriminating on tool_name supports legacy CanvasUIAction events and the\n * SDK-generated action kind without leaking that generated name here.\n */\nexport const isCanvasUIActionEvent = (\n event: OpenHandsEvent,\n): event is ActionEvent<CanvasUIAction> =>\n isActionEvent(event) &&\n (event.tool_name === LEGACY_CANVAS_UI_TOOL_NAME ||\n event.tool_name === CANVAS_UI_CLIENT_TOOL_NAME);\n\n/**\n * Type guard for launch-child-conversation tool ActionEvents.\n *\n * Discriminates on tool_name, like `isCanvasUIActionEvent`, so the\n * SDK-generated action kind stays contained in the constants module.\n */\nexport const isLaunchChildConversationActionEvent = (\n event: OpenHandsEvent,\n): event is ActionEvent<LaunchChildConversationAction> =>\n isActionEvent(event) &&\n event.tool_name === LAUNCH_CHILD_CONVERSATION_TOOL_NAME;\n\n/**\n * Type guard function to check if an event is a system prompt event\n */\nexport const isSystemPromptEvent = (\n event: OpenHandsEvent,\n): event is SystemPromptEvent =>\n event.source === \"agent\" &&\n \"system_prompt\" in event &&\n \"tools\" in event &&\n typeof event.system_prompt === \"object\" &&\n Array.isArray(event.tools);\n\n/**\n * Type guard function to check if an event is a conversation state update event\n */\nexport const isConversationStateUpdateEvent = (\n event: OpenHandsEvent,\n): event is ConversationStateUpdateEvent =>\n \"kind\" in event && event.kind === \"ConversationStateUpdateEvent\";\n\nexport const isFullStateConversationStateUpdateEvent = (\n event: ConversationStateUpdateEvent,\n): event is ConversationStateUpdateEventFullState => event.key === \"full_state\";\n\nexport const isAgentStatusConversationStateUpdateEvent = (\n event: ConversationStateUpdateEvent,\n): event is ConversationStateUpdateEventAgentStatus =>\n event.key === \"execution_status\";\n\nexport const isStatsConversationStateUpdateEvent = (\n event: ConversationStateUpdateEvent,\n): event is ConversationStateUpdateEventStats => event.key === \"stats\";\n\nexport const isGoalConversationStateUpdateEvent = (\n event: ConversationStateUpdateEvent,\n): event is ConversationStateUpdateEventGoal => event.key === \"goal\";\n\n/**\n * Type guard function to check if an event is a conversation error event\n */\nexport const isConversationErrorEvent = (\n event: OpenHandsEvent,\n): event is ConversationErrorEvent =>\n \"kind\" in event && event.kind === \"ConversationErrorEvent\";\n\n/**\n * Type guard function to check if an event is a server error event\n */\nexport const isServerErrorEvent = (\n event: OpenHandsEvent,\n): event is ServerErrorEvent =>\n \"kind\" in event && event.kind === \"ServerErrorEvent\";\n\n/**\n * Type guard function to check if an event is a displayable error event\n * (ConversationErrorEvent or ServerErrorEvent) - both should show as error banners\n */\nexport const isDisplayableErrorEvent = (event: OpenHandsEvent): boolean =>\n isConversationErrorEvent(event) || isServerErrorEvent(event);\n\n/**\n * Type guard function to check if an event is a hook execution event\n */\nexport const isHookExecutionEvent = (\n event: OpenHandsEvent,\n): event is HookExecutionEvent =>\n \"kind\" in event && event.kind === \"HookExecutionEvent\";\n\n/**\n * Type guard function to check if an event is an ACP tool call event\n */\nexport const isACPToolCallEvent = (\n event: OpenHandsEvent,\n): event is ACPToolCallEvent =>\n \"kind\" in event && event.kind === \"ACPToolCallEvent\";\n\nexport const isStreamingDeltaEvent = (\n event: OpenHandsEvent,\n): event is StreamingDeltaEvent =>\n \"kind\" in event && event.kind === \"StreamingDeltaEvent\";\n\n// =============================================================================\n// COMPATIBILITY TYPE GUARDS\n// =============================================================================\n\n/**\n * Type guard to check if an event is an agent-server OpenHandsEvent.\n * Uses isBaseEvent to validate the complete event structure.\n */\nexport function isAgentServerEvent(event: unknown): event is OpenHandsEvent {\n return isBaseEvent(event);\n}\n"],"mappings":";;;AA2CA,SAAgB,EAAY,GAAoC;CAC9D,OAEE,OAAO,KAAU,cADjB,KAEA,QAAQ,KACR,eAAe,KACf,YAAY,KACZ,OAAO,EAAM,MAAO,YACpB,EAAM,GAAG,SAAS,KAClB,OAAO,EAAM,aAAc,YAC3B,EAAM,UAAU,SAAS,KACzB,OAAO,EAAM,UAAW,aACvB,EAAM,WAAW,WAChB,EAAM,WAAW,UACjB,EAAM,WAAW,iBACjB,EAAM,WAAW;AAEvB;AAKA,IAAa,KACX,MAEA,EAAM,WAAW,iBACjB,eAAe,KACf,iBAAiB,KACjB,EAAM,gBAAgB,QACtB,OAAO,EAAM,eAAgB,YAC7B,UAAU,EAAM,aAKL,KACX,MAEA,EAAM,WAAW,WACjB,eAAe,KACf,kBAAkB,KAClB,WAAW,KACX,OAAO,EAAM,aAAc,YAC3B,OAAO,EAAM,gBAAiB,YAC9B,OAAO,EAAM,SAAU,UAKZ,KAAkB,MAC7B,iBAAiB,KACjB,OAAO,EAAM,eAAgB,YAC7B,EAAM,gBAAgB,QACtB,UAAU,EAAM,eAChB,aAAa,EAAM,aAKR,KACX,MAEA,EAAe,CAAK,KAAK,EAAM,YAAY,SAAS,QAKzC,KAAiB,MAC5B,EAAM,WAAW,WACjB,YAAY,KACZ,EAAM,WAAW,QACjB,OAAO,EAAM,UAAW,YACxB,UAAU,EAAM,UAChB,eAAe,KACf,kBAAkB,KAClB,OAAO,EAAM,aAAc,YAC3B,OAAO,EAAM,gBAAiB,UAKnB,KACX,MAEA,EAAc,CAAK,MAClB,EAAM,OAAO,SAAS,uBACrB,EAAM,OAAO,SAAS,mBAKb,KACX,MAEA,EAAmB,CAAK,MACvB,EAAM,YAAY,SAAS,4BAC1B,EAAM,YAAY,SAAS,wBAKlB,KACX,MAEA,EAAmB,CAAK,KACxB,EAAM,YAAY,SAAS,iCAKhB,KACX,MAEA,EAAmB,CAAK,KAAK,EAAM,YAAY,SAAS,sBAK7C,KACX,MAEA,EAAmB,CAAK,KACxB,EAAM,YAAY,SAAS,wBAKhB,KACX,MAEA,EAAc,CAAK,KAAK,EAAM,OAAO,SAAS,yBAQnC,KACX,MAEA,EAAc,CAAK,MAClB,EAAM,cAAA,eACL,EAAM,cAAA,sBAQG,KACX,MAEA,EAAc,CAAK,KACnB,EAAM,cAAA,6BAKK,KACX,MAEA,EAAM,WAAW,WACjB,mBAAmB,KACnB,WAAW,KACX,OAAO,EAAM,iBAAkB,YAC/B,MAAM,QAAQ,EAAM,KAAK,GAKd,KACX,MAEA,UAAU,KAAS,EAAM,SAAS,gCAEvB,KACX,MACmD,EAAM,QAAQ,cAEtD,KACX,MAEA,EAAM,QAAQ,oBAEH,KACX,MAC+C,EAAM,QAAQ,SAElD,KACX,MAC8C,EAAM,QAAQ,QAKjD,KACX,MAEA,UAAU,KAAS,EAAM,SAAS,0BAKvB,KACX,MAEA,UAAU,KAAS,EAAM,SAAS,oBAMvB,KAA2B,MACtC,EAAyB,CAAK,KAAK,EAAmB,CAAK,GAKhD,KACX,MAEA,UAAU,KAAS,EAAM,SAAS,sBAKvB,KACX,MAEA,UAAU,KAAS,EAAM,SAAS,oBAEvB,KACX,MAEA,UAAU,KAAS,EAAM,SAAS;AAUpC,SAAgB,EAAmB,GAAyC;CAC1E,OAAO,EAAY,CAAK;AAC1B"}
|
|
@@ -75,6 +75,14 @@ export interface AutomationRun {
|
|
|
75
75
|
*/
|
|
76
76
|
bash_command_id: string | null;
|
|
77
77
|
error_detail: string | null;
|
|
78
|
+
/**
|
|
79
|
+
* Accumulated LLM cost of the run in USD, reported by the SDK in the
|
|
80
|
+
* completion callback. `null` means unknown — the run predates cost
|
|
81
|
+
* tracking, or ended without a callback (cancelled, watchdog timeout).
|
|
82
|
+
* Absent entirely when the automation service is older than the release
|
|
83
|
+
* that added the field, hence optional.
|
|
84
|
+
*/
|
|
85
|
+
cost?: number | null;
|
|
78
86
|
started_at: string;
|
|
79
87
|
completed_at: string | null;
|
|
80
88
|
}
|
|
@@ -96,4 +104,10 @@ export interface AutomationRunExportRow {
|
|
|
96
104
|
conversation_id: string | null;
|
|
97
105
|
conversation_url: string | null;
|
|
98
106
|
error: string | null;
|
|
107
|
+
/**
|
|
108
|
+
* Accumulated LLM cost in USD, or null when unknown. Unlike
|
|
109
|
+
* `AutomationRun["cost"]` this is always present: the row normalizes a
|
|
110
|
+
* missing field to null so every exported record has the same shape.
|
|
111
|
+
*/
|
|
112
|
+
cost: number | null;
|
|
99
113
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../i18n/declaration.cjs"),n=require("../node_modules/lucide-react/dist/esm/icons/circle-x.cjs"),r=require("../constants/status-colors.cjs"),i=require("./utils.cjs"),a=require("./user-facing-error.cjs"),o=require("../i18n/index.cjs"),s=require("../node_modules/react-hot-toast/dist/index.cjs"),c=require("./toast-duration.cjs");let l=require("react");l=e.__toESM(l,1);let u=require("react/jsx-runtime");var d={background:`var(--oh-color-tertiary)`,border:`1px solid var(--oh-border-input)`,color:`#fff`,borderRadius:`var(--oh-radius)`,maxWidth:`400px`,wordBreak:`break-word`,overflowWrap:`anywhere`,whiteSpace:`pre-wrap`},f={position:`top-right`,style:d},p={...d,color:`var(--oh-muted)`};function m({message:e}){let t=l.default.useRef(null),[a,o]=l.default.useState(!1);return l.default.useLayoutEffect(()=>{let e=t.current;if(!e)return;let n=()=>{let t=Number.parseFloat(getComputedStyle(e).lineHeight);if(!Number.isFinite(t)||t<=0){o(!1);return}o(e.getBoundingClientRect().height>t*1.5)};n();let r=new ResizeObserver(n);return r.observe(e),()=>r.disconnect()},[e]),(0,u.jsxs)(`div`,{className:i.cn(`flex min-w-0 gap-2`,a?`items-start`:`items-center`),children:[(0,u.jsx)(n.CircleX,{"aria-hidden":!0,className:`h-4 w-4 shrink-0`,strokeWidth:2,style:{color:r.OH_STATUS_ERROR_COLOR}}),(0,u.jsx)(`span`,{ref:t,className:`min-w-0 flex-1 text-sm leading-5 [word-break:break-word] [overflow-wrap:anywhere]`,children:e})]})}var h={...f,icon:null,style:p},g=e=>{let n=e||o.default.t(t.I18nKey.STATUS$ERROR);a.isCorsOrNetworkErrorMessage(n)?n=o.default.t(t.I18nKey.ERROR$CORS_OR_NETWORK):a.isBackendRequestTimeoutMessage(n)&&(n=o.default.t(t.I18nKey.ERROR$BACKEND_REQUEST_TIMEOUT));let r=c.calculateToastDuration(n,4e3);s.zt((0,u.jsx)(m,{message:n}),{...h,duration:r})},_=e=>{let t=c.calculateToastDuration(e,5e3);s.zt.success((0,u.jsx)(`span`,{className:`[word-break:break-word] [overflow-wrap:anywhere]`,children:e}),{...f,duration:t})};exports.TOAST_OPTIONS=f,exports.displayErrorToast=g,exports.displaySuccessToast=_;
|
|
1
|
+
const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../i18n/declaration.cjs"),n=require("../node_modules/lucide-react/dist/esm/icons/circle-x.cjs"),r=require("../constants/status-colors.cjs"),i=require("./utils.cjs"),a=require("./user-facing-error.cjs"),o=require("../i18n/index.cjs"),s=require("../node_modules/react-hot-toast/dist/index.cjs"),c=require("./toast-duration.cjs");let l=require("react");l=e.__toESM(l,1);let u=require("react/jsx-runtime");var d={background:`var(--oh-color-tertiary)`,border:`1px solid var(--oh-border-input)`,color:`#fff`,borderRadius:`var(--oh-radius)`,maxWidth:`400px`,wordBreak:`break-word`,overflowWrap:`anywhere`,whiteSpace:`pre-wrap`},f={position:`top-right`,style:d},p={...d,color:`var(--oh-muted)`};function m({message:e}){let t=l.default.useRef(null),[a,o]=l.default.useState(!1);return l.default.useLayoutEffect(()=>{let e=t.current;if(!e)return;let n=()=>{let t=Number.parseFloat(getComputedStyle(e).lineHeight);if(!Number.isFinite(t)||t<=0){o(!1);return}o(e.getBoundingClientRect().height>t*1.5)};n();let r=new ResizeObserver(n);return r.observe(e),()=>r.disconnect()},[e]),(0,u.jsxs)(`div`,{className:i.cn(`flex min-w-0 gap-2`,a?`items-start`:`items-center`),children:[(0,u.jsx)(n.CircleX,{"aria-hidden":!0,className:`h-4 w-4 shrink-0`,strokeWidth:2,style:{color:r.OH_STATUS_ERROR_COLOR}}),(0,u.jsx)(`span`,{ref:t,className:`min-w-0 flex-1 text-sm leading-5 [word-break:break-word] [overflow-wrap:anywhere]`,children:e})]})}var h={...f,icon:null,style:p},g=e=>{let n=e||o.default.t(t.I18nKey.STATUS$ERROR);a.isCorsOrNetworkErrorMessage(n)?n=o.default.t(t.I18nKey.ERROR$CORS_OR_NETWORK):a.isBackendRequestTimeoutMessage(n)&&(n=o.default.t(t.I18nKey.ERROR$BACKEND_REQUEST_TIMEOUT));let r=c.calculateToastDuration(n,4e3);s.zt((0,u.jsx)(m,{message:n}),{...h,duration:r})},_=e=>{let t=c.calculateToastDuration(e,5e3);s.zt.success((0,u.jsx)(`span`,{className:`[word-break:break-word] [overflow-wrap:anywhere]`,children:e}),{...f,duration:t})},v=(e,t,n)=>{let r=c.calculateToastDuration(`${e} ${t}`,5e3);s.zt.success((0,u.jsxs)(`span`,{className:`[word-break:break-word] [overflow-wrap:anywhere]`,children:[e,` `,(0,u.jsx)(`a`,{className:`underline hover:no-underline`,href:n,children:t})]}),{...f,duration:r})};exports.TOAST_OPTIONS=f,exports.displayErrorToast=g,exports.displaySuccessToast=_,exports.displaySuccessToastWithLink=v;
|
|
2
2
|
//# sourceMappingURL=custom-toast-handlers.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-toast-handlers.cjs","names":[],"sources":["../../src/utils/custom-toast-handlers.tsx"],"sourcesContent":["import React, { CSSProperties, ReactNode } from \"react\";\nimport { CircleX } from \"lucide-react\";\nimport toast, { ToastOptions } from \"react-hot-toast\";\nimport { OH_STATUS_ERROR_COLOR } from \"#/constants/status-colors\";\nimport { calculateToastDuration } from \"./toast-duration\";\nimport { cn } from \"#/utils/utils\";\nimport i18n from \"#/i18n\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport {\n isBackendRequestTimeoutMessage,\n isCorsOrNetworkErrorMessage,\n} from \"./user-facing-error\";\n\n// react-hot-toast accepts only CSSProperties via the style option — cannot use className\nconst TOAST_STYLE: CSSProperties = {\n background: \"var(--oh-color-tertiary)\",\n border: \"1px solid var(--oh-border-input)\",\n color: \"#fff\",\n borderRadius: \"var(--oh-radius)\",\n maxWidth: \"400px\",\n wordBreak: \"break-word\",\n overflowWrap: \"anywhere\",\n whiteSpace: \"pre-wrap\",\n};\n\nexport const TOAST_OPTIONS: ToastOptions = {\n position: \"top-right\",\n style: TOAST_STYLE,\n};\n\nconst ERROR_TOAST_STYLE: CSSProperties = {\n ...TOAST_STYLE,\n color: \"var(--oh-muted)\",\n};\n\n/** Icon + message row; center icon for single-line text, top-align when wrapped. */\nexport function ErrorToastContent({ message }: { message: ReactNode }) {\n const contentRef = React.useRef<HTMLSpanElement>(null);\n const [isMultiLine, setIsMultiLine] = React.useState(false);\n\n React.useLayoutEffect(() => {\n const content = contentRef.current;\n if (!content) {\n return undefined;\n }\n\n const updateIsMultiLine = () => {\n const lineHeight = Number.parseFloat(\n getComputedStyle(content).lineHeight,\n );\n if (!Number.isFinite(lineHeight) || lineHeight <= 0) {\n setIsMultiLine(false);\n return;\n }\n\n setIsMultiLine(content.getBoundingClientRect().height > lineHeight * 1.5);\n };\n\n updateIsMultiLine();\n\n const observer = new ResizeObserver(updateIsMultiLine);\n observer.observe(content);\n\n return () => observer.disconnect();\n }, [message]);\n\n return (\n <div\n className={cn(\n \"flex min-w-0 gap-2\",\n isMultiLine ? \"items-start\" : \"items-center\",\n )}\n >\n <CircleX\n aria-hidden\n className=\"h-4 w-4 shrink-0\"\n strokeWidth={2}\n style={{ color: OH_STATUS_ERROR_COLOR }}\n />\n <span\n ref={contentRef}\n className=\"min-w-0 flex-1 text-sm leading-5 [word-break:break-word] [overflow-wrap:anywhere]\"\n >\n {message}\n </span>\n </div>\n );\n}\n\nexport const ERROR_TOAST_OPTIONS: ToastOptions = {\n ...TOAST_OPTIONS,\n icon: null,\n style: ERROR_TOAST_STYLE,\n};\n\nexport const displayErrorToast = (error: string | null | undefined) => {\n let errorMessage = error || i18n.t(I18nKey.STATUS$ERROR);\n if (isCorsOrNetworkErrorMessage(errorMessage)) {\n errorMessage = i18n.t(I18nKey.ERROR$CORS_OR_NETWORK);\n } else if (isBackendRequestTimeoutMessage(errorMessage)) {\n errorMessage = i18n.t(I18nKey.ERROR$BACKEND_REQUEST_TIMEOUT);\n }\n const duration = calculateToastDuration(errorMessage, 4000);\n toast(<ErrorToastContent message={errorMessage} />, {\n ...ERROR_TOAST_OPTIONS,\n duration,\n });\n};\n\nexport const displaySuccessToast = (message: string) => {\n const duration = calculateToastDuration(message, 5000);\n toast.success(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}\n </span>,\n { ...TOAST_OPTIONS, duration },\n );\n};\n\nexport const displaySuccessToastWithLink = (\n message: string,\n linkLabel: string,\n href: string,\n) => {\n const duration = calculateToastDuration(`${message} ${linkLabel}`, 5000);\n toast.success(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}{\" \"}\n <a className=\"underline hover:no-underline\" href={href}>\n {linkLabel}\n </a>\n </span>,\n { ...TOAST_OPTIONS, duration },\n );\n};\n\n/**\n * Neutral, non-success notice — used when an action completed but the outcome\n * is qualified (e.g. a secret was saved but the active backend can't consume it\n * yet). Renders without the success checkmark so it doesn't read as \"all good\".\n */\nexport const displayWarningToast = (message: string) => {\n const duration = calculateToastDuration(message, 6000);\n toast(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}\n </span>,\n { ...TOAST_OPTIONS, icon: \"⚠️\", duration },\n );\n};\n"],"mappings":"kdAcA,IAAM,EAA6B,CACjC,WAAY,2BACZ,OAAQ,mCACR,MAAO,OACP,aAAc,mBACd,SAAU,QACV,UAAW,aACX,aAAc,WACd,WAAY,UACd,EAEa,EAA8B,CACzC,SAAU,YACV,MAAO,CACT,EAEM,EAAmC,CACvC,GAAG,EACH,MAAO,iBACT,EAGA,SAAgB,EAAkB,CAAE,WAAmC,CACrE,IAAM,EAAa,EAAA,QAAM,OAAwB,IAAI,EAC/C,CAAC,EAAa,GAAkB,EAAA,QAAM,SAAS,EAAK,EA4B1D,OA1BA,EAAA,QAAM,oBAAsB,CAC1B,IAAM,EAAU,EAAW,QAC3B,GAAI,CAAC,EACH,OAGF,IAAM,MAA0B,CAC9B,IAAM,EAAa,OAAO,WACxB,iBAAiB,CAAO,EAAE,UAC5B,EACA,GAAI,CAAC,OAAO,SAAS,CAAU,GAAK,GAAc,EAAG,CACnD,EAAe,EAAK,EACpB,MACF,CAEA,EAAe,EAAQ,sBAAsB,EAAE,OAAS,EAAa,GAAG,CAC1E,EAEA,EAAkB,EAElB,IAAM,EAAW,IAAI,eAAe,CAAiB,EAGrD,OAFA,EAAS,QAAQ,CAAO,MAEX,EAAS,WAAW,CACnC,EAAG,CAAC,CAAO,CAAC,GAGV,EAAA,EAAA,MAAC,MAAD,CACE,UAAW,EAAA,GACT,qBACA,EAAc,cAAgB,cAChC,WAJF,EAME,EAAA,EAAA,KAAC,EAAA,QAAD,CACE,cAAA,GACA,UAAU,mBACV,YAAa,EACb,MAAO,CAAE,MAAO,EAAA,qBAAsB,CACvC,CAAA,GACD,EAAA,EAAA,KAAC,OAAD,CACE,IAAK,EACL,UAAU,6FAET,CACG,CAAA,CACH,GAET,CAEA,IAAa,EAAoC,CAC/C,GAAG,EACH,KAAM,KACN,MAAO,CACT,EAEa,EAAqB,GAAqC,CACrE,IAAI,EAAe,GAAS,EAAA,QAAK,EAAE,EAAA,QAAQ,YAAY,EACnD,EAAA,4BAA4B,CAAY,EAC1C,EAAe,EAAA,QAAK,EAAE,EAAA,QAAQ,qBAAqB,EAC1C,EAAA,+BAA+B,CAAY,IACpD,EAAe,EAAA,QAAK,EAAE,EAAA,QAAQ,6BAA6B,GAE7D,IAAM,EAAW,EAAA,uBAAuB,EAAc,GAAI,EAC1D,EAAA,IAAM,EAAA,EAAA,KAAC,EAAD,CAAmB,QAAS,CAAe,CAAA,EAAG,CAClD,GAAG,EACH,UACF,CAAC,CACH,EAEa,EAAuB,GAAoB,CACtD,IAAM,EAAW,EAAA,uBAAuB,EAAS,GAAI,EACrD,EAAA,GAAM,SACJ,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,4DACb,CACG,CAAA,EACN,CAAE,GAAG,EAAe,UAAS,CAC/B,CACF"}
|
|
1
|
+
{"version":3,"file":"custom-toast-handlers.cjs","names":[],"sources":["../../src/utils/custom-toast-handlers.tsx"],"sourcesContent":["import React, { CSSProperties, ReactNode } from \"react\";\nimport { CircleX } from \"lucide-react\";\nimport toast, { ToastOptions } from \"react-hot-toast\";\nimport { OH_STATUS_ERROR_COLOR } from \"#/constants/status-colors\";\nimport { calculateToastDuration } from \"./toast-duration\";\nimport { cn } from \"#/utils/utils\";\nimport i18n from \"#/i18n\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport {\n isBackendRequestTimeoutMessage,\n isCorsOrNetworkErrorMessage,\n} from \"./user-facing-error\";\n\n// react-hot-toast accepts only CSSProperties via the style option — cannot use className\nconst TOAST_STYLE: CSSProperties = {\n background: \"var(--oh-color-tertiary)\",\n border: \"1px solid var(--oh-border-input)\",\n color: \"#fff\",\n borderRadius: \"var(--oh-radius)\",\n maxWidth: \"400px\",\n wordBreak: \"break-word\",\n overflowWrap: \"anywhere\",\n whiteSpace: \"pre-wrap\",\n};\n\nexport const TOAST_OPTIONS: ToastOptions = {\n position: \"top-right\",\n style: TOAST_STYLE,\n};\n\nconst ERROR_TOAST_STYLE: CSSProperties = {\n ...TOAST_STYLE,\n color: \"var(--oh-muted)\",\n};\n\n/** Icon + message row; center icon for single-line text, top-align when wrapped. */\nexport function ErrorToastContent({ message }: { message: ReactNode }) {\n const contentRef = React.useRef<HTMLSpanElement>(null);\n const [isMultiLine, setIsMultiLine] = React.useState(false);\n\n React.useLayoutEffect(() => {\n const content = contentRef.current;\n if (!content) {\n return undefined;\n }\n\n const updateIsMultiLine = () => {\n const lineHeight = Number.parseFloat(\n getComputedStyle(content).lineHeight,\n );\n if (!Number.isFinite(lineHeight) || lineHeight <= 0) {\n setIsMultiLine(false);\n return;\n }\n\n setIsMultiLine(content.getBoundingClientRect().height > lineHeight * 1.5);\n };\n\n updateIsMultiLine();\n\n const observer = new ResizeObserver(updateIsMultiLine);\n observer.observe(content);\n\n return () => observer.disconnect();\n }, [message]);\n\n return (\n <div\n className={cn(\n \"flex min-w-0 gap-2\",\n isMultiLine ? \"items-start\" : \"items-center\",\n )}\n >\n <CircleX\n aria-hidden\n className=\"h-4 w-4 shrink-0\"\n strokeWidth={2}\n style={{ color: OH_STATUS_ERROR_COLOR }}\n />\n <span\n ref={contentRef}\n className=\"min-w-0 flex-1 text-sm leading-5 [word-break:break-word] [overflow-wrap:anywhere]\"\n >\n {message}\n </span>\n </div>\n );\n}\n\nexport const ERROR_TOAST_OPTIONS: ToastOptions = {\n ...TOAST_OPTIONS,\n icon: null,\n style: ERROR_TOAST_STYLE,\n};\n\nexport const displayErrorToast = (error: string | null | undefined) => {\n let errorMessage = error || i18n.t(I18nKey.STATUS$ERROR);\n if (isCorsOrNetworkErrorMessage(errorMessage)) {\n errorMessage = i18n.t(I18nKey.ERROR$CORS_OR_NETWORK);\n } else if (isBackendRequestTimeoutMessage(errorMessage)) {\n errorMessage = i18n.t(I18nKey.ERROR$BACKEND_REQUEST_TIMEOUT);\n }\n const duration = calculateToastDuration(errorMessage, 4000);\n toast(<ErrorToastContent message={errorMessage} />, {\n ...ERROR_TOAST_OPTIONS,\n duration,\n });\n};\n\nexport const displaySuccessToast = (message: string) => {\n const duration = calculateToastDuration(message, 5000);\n toast.success(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}\n </span>,\n { ...TOAST_OPTIONS, duration },\n );\n};\n\nexport const displaySuccessToastWithLink = (\n message: string,\n linkLabel: string,\n href: string,\n) => {\n const duration = calculateToastDuration(`${message} ${linkLabel}`, 5000);\n toast.success(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}{\" \"}\n <a className=\"underline hover:no-underline\" href={href}>\n {linkLabel}\n </a>\n </span>,\n { ...TOAST_OPTIONS, duration },\n );\n};\n\n/**\n * Neutral, non-success notice — used when an action completed but the outcome\n * is qualified (e.g. a secret was saved but the active backend can't consume it\n * yet). Renders without the success checkmark so it doesn't read as \"all good\".\n */\nexport const displayWarningToast = (message: string) => {\n const duration = calculateToastDuration(message, 6000);\n toast(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}\n </span>,\n { ...TOAST_OPTIONS, icon: \"⚠️\", duration },\n );\n};\n"],"mappings":"kdAcA,IAAM,EAA6B,CACjC,WAAY,2BACZ,OAAQ,mCACR,MAAO,OACP,aAAc,mBACd,SAAU,QACV,UAAW,aACX,aAAc,WACd,WAAY,UACd,EAEa,EAA8B,CACzC,SAAU,YACV,MAAO,CACT,EAEM,EAAmC,CACvC,GAAG,EACH,MAAO,iBACT,EAGA,SAAgB,EAAkB,CAAE,WAAmC,CACrE,IAAM,EAAa,EAAA,QAAM,OAAwB,IAAI,EAC/C,CAAC,EAAa,GAAkB,EAAA,QAAM,SAAS,EAAK,EA4B1D,OA1BA,EAAA,QAAM,oBAAsB,CAC1B,IAAM,EAAU,EAAW,QAC3B,GAAI,CAAC,EACH,OAGF,IAAM,MAA0B,CAC9B,IAAM,EAAa,OAAO,WACxB,iBAAiB,CAAO,EAAE,UAC5B,EACA,GAAI,CAAC,OAAO,SAAS,CAAU,GAAK,GAAc,EAAG,CACnD,EAAe,EAAK,EACpB,MACF,CAEA,EAAe,EAAQ,sBAAsB,EAAE,OAAS,EAAa,GAAG,CAC1E,EAEA,EAAkB,EAElB,IAAM,EAAW,IAAI,eAAe,CAAiB,EAGrD,OAFA,EAAS,QAAQ,CAAO,MAEX,EAAS,WAAW,CACnC,EAAG,CAAC,CAAO,CAAC,GAGV,EAAA,EAAA,MAAC,MAAD,CACE,UAAW,EAAA,GACT,qBACA,EAAc,cAAgB,cAChC,WAJF,EAME,EAAA,EAAA,KAAC,EAAA,QAAD,CACE,cAAA,GACA,UAAU,mBACV,YAAa,EACb,MAAO,CAAE,MAAO,EAAA,qBAAsB,CACvC,CAAA,GACD,EAAA,EAAA,KAAC,OAAD,CACE,IAAK,EACL,UAAU,6FAET,CACG,CAAA,CACH,GAET,CAEA,IAAa,EAAoC,CAC/C,GAAG,EACH,KAAM,KACN,MAAO,CACT,EAEa,EAAqB,GAAqC,CACrE,IAAI,EAAe,GAAS,EAAA,QAAK,EAAE,EAAA,QAAQ,YAAY,EACnD,EAAA,4BAA4B,CAAY,EAC1C,EAAe,EAAA,QAAK,EAAE,EAAA,QAAQ,qBAAqB,EAC1C,EAAA,+BAA+B,CAAY,IACpD,EAAe,EAAA,QAAK,EAAE,EAAA,QAAQ,6BAA6B,GAE7D,IAAM,EAAW,EAAA,uBAAuB,EAAc,GAAI,EAC1D,EAAA,IAAM,EAAA,EAAA,KAAC,EAAD,CAAmB,QAAS,CAAe,CAAA,EAAG,CAClD,GAAG,EACH,UACF,CAAC,CACH,EAEa,EAAuB,GAAoB,CACtD,IAAM,EAAW,EAAA,uBAAuB,EAAS,GAAI,EACrD,EAAA,GAAM,SACJ,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,4DACb,CACG,CAAA,EACN,CAAE,GAAG,EAAe,UAAS,CAC/B,CACF,EAEa,GACX,EACA,EACA,IACG,CACH,IAAM,EAAW,EAAA,uBAAuB,GAAG,EAAQ,GAAG,IAAa,GAAI,EACvE,EAAA,GAAM,SACJ,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,4DAAhB,CACG,EAAS,KACV,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,+BAAqC,gBAC/C,CACA,CAAA,CACC,IACN,CAAE,GAAG,EAAe,UAAS,CAC/B,CACF"}
|
|
@@ -76,8 +76,25 @@ var g = {
|
|
|
76
76
|
...p,
|
|
77
77
|
duration: t
|
|
78
78
|
});
|
|
79
|
+
}, y = (e, t, n) => {
|
|
80
|
+
let r = c(`${e} ${t}`, 5e3);
|
|
81
|
+
s.success(/* @__PURE__ */ d("span", {
|
|
82
|
+
className: "[word-break:break-word] [overflow-wrap:anywhere]",
|
|
83
|
+
children: [
|
|
84
|
+
e,
|
|
85
|
+
" ",
|
|
86
|
+
/* @__PURE__ */ u("a", {
|
|
87
|
+
className: "underline hover:no-underline",
|
|
88
|
+
href: n,
|
|
89
|
+
children: t
|
|
90
|
+
})
|
|
91
|
+
]
|
|
92
|
+
}), {
|
|
93
|
+
...p,
|
|
94
|
+
duration: r
|
|
95
|
+
});
|
|
79
96
|
};
|
|
80
97
|
//#endregion
|
|
81
|
-
export { p as TOAST_OPTIONS, _ as displayErrorToast, v as displaySuccessToast };
|
|
98
|
+
export { p as TOAST_OPTIONS, _ as displayErrorToast, v as displaySuccessToast, y as displaySuccessToastWithLink };
|
|
82
99
|
|
|
83
100
|
//# sourceMappingURL=custom-toast-handlers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-toast-handlers.js","names":[],"sources":["../../src/utils/custom-toast-handlers.tsx"],"sourcesContent":["import React, { CSSProperties, ReactNode } from \"react\";\nimport { CircleX } from \"lucide-react\";\nimport toast, { ToastOptions } from \"react-hot-toast\";\nimport { OH_STATUS_ERROR_COLOR } from \"#/constants/status-colors\";\nimport { calculateToastDuration } from \"./toast-duration\";\nimport { cn } from \"#/utils/utils\";\nimport i18n from \"#/i18n\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport {\n isBackendRequestTimeoutMessage,\n isCorsOrNetworkErrorMessage,\n} from \"./user-facing-error\";\n\n// react-hot-toast accepts only CSSProperties via the style option — cannot use className\nconst TOAST_STYLE: CSSProperties = {\n background: \"var(--oh-color-tertiary)\",\n border: \"1px solid var(--oh-border-input)\",\n color: \"#fff\",\n borderRadius: \"var(--oh-radius)\",\n maxWidth: \"400px\",\n wordBreak: \"break-word\",\n overflowWrap: \"anywhere\",\n whiteSpace: \"pre-wrap\",\n};\n\nexport const TOAST_OPTIONS: ToastOptions = {\n position: \"top-right\",\n style: TOAST_STYLE,\n};\n\nconst ERROR_TOAST_STYLE: CSSProperties = {\n ...TOAST_STYLE,\n color: \"var(--oh-muted)\",\n};\n\n/** Icon + message row; center icon for single-line text, top-align when wrapped. */\nexport function ErrorToastContent({ message }: { message: ReactNode }) {\n const contentRef = React.useRef<HTMLSpanElement>(null);\n const [isMultiLine, setIsMultiLine] = React.useState(false);\n\n React.useLayoutEffect(() => {\n const content = contentRef.current;\n if (!content) {\n return undefined;\n }\n\n const updateIsMultiLine = () => {\n const lineHeight = Number.parseFloat(\n getComputedStyle(content).lineHeight,\n );\n if (!Number.isFinite(lineHeight) || lineHeight <= 0) {\n setIsMultiLine(false);\n return;\n }\n\n setIsMultiLine(content.getBoundingClientRect().height > lineHeight * 1.5);\n };\n\n updateIsMultiLine();\n\n const observer = new ResizeObserver(updateIsMultiLine);\n observer.observe(content);\n\n return () => observer.disconnect();\n }, [message]);\n\n return (\n <div\n className={cn(\n \"flex min-w-0 gap-2\",\n isMultiLine ? \"items-start\" : \"items-center\",\n )}\n >\n <CircleX\n aria-hidden\n className=\"h-4 w-4 shrink-0\"\n strokeWidth={2}\n style={{ color: OH_STATUS_ERROR_COLOR }}\n />\n <span\n ref={contentRef}\n className=\"min-w-0 flex-1 text-sm leading-5 [word-break:break-word] [overflow-wrap:anywhere]\"\n >\n {message}\n </span>\n </div>\n );\n}\n\nexport const ERROR_TOAST_OPTIONS: ToastOptions = {\n ...TOAST_OPTIONS,\n icon: null,\n style: ERROR_TOAST_STYLE,\n};\n\nexport const displayErrorToast = (error: string | null | undefined) => {\n let errorMessage = error || i18n.t(I18nKey.STATUS$ERROR);\n if (isCorsOrNetworkErrorMessage(errorMessage)) {\n errorMessage = i18n.t(I18nKey.ERROR$CORS_OR_NETWORK);\n } else if (isBackendRequestTimeoutMessage(errorMessage)) {\n errorMessage = i18n.t(I18nKey.ERROR$BACKEND_REQUEST_TIMEOUT);\n }\n const duration = calculateToastDuration(errorMessage, 4000);\n toast(<ErrorToastContent message={errorMessage} />, {\n ...ERROR_TOAST_OPTIONS,\n duration,\n });\n};\n\nexport const displaySuccessToast = (message: string) => {\n const duration = calculateToastDuration(message, 5000);\n toast.success(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}\n </span>,\n { ...TOAST_OPTIONS, duration },\n );\n};\n\nexport const displaySuccessToastWithLink = (\n message: string,\n linkLabel: string,\n href: string,\n) => {\n const duration = calculateToastDuration(`${message} ${linkLabel}`, 5000);\n toast.success(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}{\" \"}\n <a className=\"underline hover:no-underline\" href={href}>\n {linkLabel}\n </a>\n </span>,\n { ...TOAST_OPTIONS, duration },\n );\n};\n\n/**\n * Neutral, non-success notice — used when an action completed but the outcome\n * is qualified (e.g. a secret was saved but the active backend can't consume it\n * yet). Renders without the success checkmark so it doesn't read as \"all good\".\n */\nexport const displayWarningToast = (message: string) => {\n const duration = calculateToastDuration(message, 6000);\n toast(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}\n </span>,\n { ...TOAST_OPTIONS, icon: \"⚠️\", duration },\n );\n};\n"],"mappings":";;;;;;;;;;;AAcA,IAAM,IAA6B;CACjC,YAAY;CACZ,QAAQ;CACR,OAAO;CACP,cAAc;CACd,UAAU;CACV,WAAW;CACX,cAAc;CACd,YAAY;AACd,GAEa,IAA8B;CACzC,UAAU;CACV,OAAO;AACT,GAEM,IAAmC;CACvC,GAAG;CACH,OAAO;AACT;AAGA,SAAgB,EAAkB,EAAE,cAAmC;CACrE,IAAM,IAAa,EAAM,OAAwB,IAAI,GAC/C,CAAC,GAAa,KAAkB,EAAM,SAAS,EAAK;CA4B1D,OA1BA,EAAM,sBAAsB;EAC1B,IAAM,IAAU,EAAW;EAC3B,IAAI,CAAC,GACH;EAGF,IAAM,UAA0B;GAC9B,IAAM,IAAa,OAAO,WACxB,iBAAiB,CAAO,EAAE,UAC5B;GACA,IAAI,CAAC,OAAO,SAAS,CAAU,KAAK,KAAc,GAAG;IACnD,EAAe,EAAK;IACpB;GACF;GAEA,EAAe,EAAQ,sBAAsB,EAAE,SAAS,IAAa,GAAG;EAC1E;EAEA,EAAkB;EAElB,IAAM,IAAW,IAAI,eAAe,CAAiB;EAGrD,OAFA,EAAS,QAAQ,CAAO,SAEX,EAAS,WAAW;CACnC,GAAG,CAAC,CAAO,CAAC,GAGV,kBAAC,OAAD;EACE,WAAW,EACT,sBACA,IAAc,gBAAgB,cAChC;YAJF,CAME,kBAAC,GAAD;GACE,eAAA;GACA,WAAU;GACV,aAAa;GACb,OAAO,EAAE,OAAO,EAAsB;EACvC,CAAA,GACD,kBAAC,QAAD;GACE,KAAK;GACL,WAAU;aAET;EACG,CAAA,CACH;;AAET;AAEA,IAAa,IAAoC;CAC/C,GAAG;CACH,MAAM;CACN,OAAO;AACT,GAEa,KAAqB,MAAqC;CACrE,IAAI,IAAe,KAAS,EAAK,EAAE,EAAQ,YAAY;CACvD,AAAI,EAA4B,CAAY,IAC1C,IAAe,EAAK,EAAE,EAAQ,qBAAqB,IAC1C,EAA+B,CAAY,MACpD,IAAe,EAAK,EAAE,EAAQ,6BAA6B;CAE7D,IAAM,IAAW,EAAuB,GAAc,GAAI;CAC1D,EAAM,kBAAC,GAAD,EAAmB,SAAS,EAAe,CAAA,GAAG;EAClD,GAAG;EACH;CACF,CAAC;AACH,GAEa,KAAuB,MAAoB;CACtD,IAAM,IAAW,EAAuB,GAAS,GAAI;CACrD,EAAM,QACJ,kBAAC,QAAD;EAAM,WAAU;YACb;CACG,CAAA,GACN;EAAE,GAAG;EAAe;CAAS,CAC/B;AACF"}
|
|
1
|
+
{"version":3,"file":"custom-toast-handlers.js","names":[],"sources":["../../src/utils/custom-toast-handlers.tsx"],"sourcesContent":["import React, { CSSProperties, ReactNode } from \"react\";\nimport { CircleX } from \"lucide-react\";\nimport toast, { ToastOptions } from \"react-hot-toast\";\nimport { OH_STATUS_ERROR_COLOR } from \"#/constants/status-colors\";\nimport { calculateToastDuration } from \"./toast-duration\";\nimport { cn } from \"#/utils/utils\";\nimport i18n from \"#/i18n\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport {\n isBackendRequestTimeoutMessage,\n isCorsOrNetworkErrorMessage,\n} from \"./user-facing-error\";\n\n// react-hot-toast accepts only CSSProperties via the style option — cannot use className\nconst TOAST_STYLE: CSSProperties = {\n background: \"var(--oh-color-tertiary)\",\n border: \"1px solid var(--oh-border-input)\",\n color: \"#fff\",\n borderRadius: \"var(--oh-radius)\",\n maxWidth: \"400px\",\n wordBreak: \"break-word\",\n overflowWrap: \"anywhere\",\n whiteSpace: \"pre-wrap\",\n};\n\nexport const TOAST_OPTIONS: ToastOptions = {\n position: \"top-right\",\n style: TOAST_STYLE,\n};\n\nconst ERROR_TOAST_STYLE: CSSProperties = {\n ...TOAST_STYLE,\n color: \"var(--oh-muted)\",\n};\n\n/** Icon + message row; center icon for single-line text, top-align when wrapped. */\nexport function ErrorToastContent({ message }: { message: ReactNode }) {\n const contentRef = React.useRef<HTMLSpanElement>(null);\n const [isMultiLine, setIsMultiLine] = React.useState(false);\n\n React.useLayoutEffect(() => {\n const content = contentRef.current;\n if (!content) {\n return undefined;\n }\n\n const updateIsMultiLine = () => {\n const lineHeight = Number.parseFloat(\n getComputedStyle(content).lineHeight,\n );\n if (!Number.isFinite(lineHeight) || lineHeight <= 0) {\n setIsMultiLine(false);\n return;\n }\n\n setIsMultiLine(content.getBoundingClientRect().height > lineHeight * 1.5);\n };\n\n updateIsMultiLine();\n\n const observer = new ResizeObserver(updateIsMultiLine);\n observer.observe(content);\n\n return () => observer.disconnect();\n }, [message]);\n\n return (\n <div\n className={cn(\n \"flex min-w-0 gap-2\",\n isMultiLine ? \"items-start\" : \"items-center\",\n )}\n >\n <CircleX\n aria-hidden\n className=\"h-4 w-4 shrink-0\"\n strokeWidth={2}\n style={{ color: OH_STATUS_ERROR_COLOR }}\n />\n <span\n ref={contentRef}\n className=\"min-w-0 flex-1 text-sm leading-5 [word-break:break-word] [overflow-wrap:anywhere]\"\n >\n {message}\n </span>\n </div>\n );\n}\n\nexport const ERROR_TOAST_OPTIONS: ToastOptions = {\n ...TOAST_OPTIONS,\n icon: null,\n style: ERROR_TOAST_STYLE,\n};\n\nexport const displayErrorToast = (error: string | null | undefined) => {\n let errorMessage = error || i18n.t(I18nKey.STATUS$ERROR);\n if (isCorsOrNetworkErrorMessage(errorMessage)) {\n errorMessage = i18n.t(I18nKey.ERROR$CORS_OR_NETWORK);\n } else if (isBackendRequestTimeoutMessage(errorMessage)) {\n errorMessage = i18n.t(I18nKey.ERROR$BACKEND_REQUEST_TIMEOUT);\n }\n const duration = calculateToastDuration(errorMessage, 4000);\n toast(<ErrorToastContent message={errorMessage} />, {\n ...ERROR_TOAST_OPTIONS,\n duration,\n });\n};\n\nexport const displaySuccessToast = (message: string) => {\n const duration = calculateToastDuration(message, 5000);\n toast.success(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}\n </span>,\n { ...TOAST_OPTIONS, duration },\n );\n};\n\nexport const displaySuccessToastWithLink = (\n message: string,\n linkLabel: string,\n href: string,\n) => {\n const duration = calculateToastDuration(`${message} ${linkLabel}`, 5000);\n toast.success(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}{\" \"}\n <a className=\"underline hover:no-underline\" href={href}>\n {linkLabel}\n </a>\n </span>,\n { ...TOAST_OPTIONS, duration },\n );\n};\n\n/**\n * Neutral, non-success notice — used when an action completed but the outcome\n * is qualified (e.g. a secret was saved but the active backend can't consume it\n * yet). Renders without the success checkmark so it doesn't read as \"all good\".\n */\nexport const displayWarningToast = (message: string) => {\n const duration = calculateToastDuration(message, 6000);\n toast(\n <span className=\"[word-break:break-word] [overflow-wrap:anywhere]\">\n {message}\n </span>,\n { ...TOAST_OPTIONS, icon: \"⚠️\", duration },\n );\n};\n"],"mappings":";;;;;;;;;;;AAcA,IAAM,IAA6B;CACjC,YAAY;CACZ,QAAQ;CACR,OAAO;CACP,cAAc;CACd,UAAU;CACV,WAAW;CACX,cAAc;CACd,YAAY;AACd,GAEa,IAA8B;CACzC,UAAU;CACV,OAAO;AACT,GAEM,IAAmC;CACvC,GAAG;CACH,OAAO;AACT;AAGA,SAAgB,EAAkB,EAAE,cAAmC;CACrE,IAAM,IAAa,EAAM,OAAwB,IAAI,GAC/C,CAAC,GAAa,KAAkB,EAAM,SAAS,EAAK;CA4B1D,OA1BA,EAAM,sBAAsB;EAC1B,IAAM,IAAU,EAAW;EAC3B,IAAI,CAAC,GACH;EAGF,IAAM,UAA0B;GAC9B,IAAM,IAAa,OAAO,WACxB,iBAAiB,CAAO,EAAE,UAC5B;GACA,IAAI,CAAC,OAAO,SAAS,CAAU,KAAK,KAAc,GAAG;IACnD,EAAe,EAAK;IACpB;GACF;GAEA,EAAe,EAAQ,sBAAsB,EAAE,SAAS,IAAa,GAAG;EAC1E;EAEA,EAAkB;EAElB,IAAM,IAAW,IAAI,eAAe,CAAiB;EAGrD,OAFA,EAAS,QAAQ,CAAO,SAEX,EAAS,WAAW;CACnC,GAAG,CAAC,CAAO,CAAC,GAGV,kBAAC,OAAD;EACE,WAAW,EACT,sBACA,IAAc,gBAAgB,cAChC;YAJF,CAME,kBAAC,GAAD;GACE,eAAA;GACA,WAAU;GACV,aAAa;GACb,OAAO,EAAE,OAAO,EAAsB;EACvC,CAAA,GACD,kBAAC,QAAD;GACE,KAAK;GACL,WAAU;aAET;EACG,CAAA,CACH;;AAET;AAEA,IAAa,IAAoC;CAC/C,GAAG;CACH,MAAM;CACN,OAAO;AACT,GAEa,KAAqB,MAAqC;CACrE,IAAI,IAAe,KAAS,EAAK,EAAE,EAAQ,YAAY;CACvD,AAAI,EAA4B,CAAY,IAC1C,IAAe,EAAK,EAAE,EAAQ,qBAAqB,IAC1C,EAA+B,CAAY,MACpD,IAAe,EAAK,EAAE,EAAQ,6BAA6B;CAE7D,IAAM,IAAW,EAAuB,GAAc,GAAI;CAC1D,EAAM,kBAAC,GAAD,EAAmB,SAAS,EAAe,CAAA,GAAG;EAClD,GAAG;EACH;CACF,CAAC;AACH,GAEa,KAAuB,MAAoB;CACtD,IAAM,IAAW,EAAuB,GAAS,GAAI;CACrD,EAAM,QACJ,kBAAC,QAAD;EAAM,WAAU;YACb;CACG,CAAA,GACN;EAAE,GAAG;EAAe;CAAS,CAC/B;AACF,GAEa,KACX,GACA,GACA,MACG;CACH,IAAM,IAAW,EAAuB,GAAG,EAAQ,GAAG,KAAa,GAAI;CACvE,EAAM,QACJ,kBAAC,QAAD;EAAM,WAAU;YAAhB;GACG;GAAS;GACV,kBAAC,KAAD;IAAG,WAAU;IAAqC;cAC/C;GACA,CAAA;EACC;KACN;EAAE,GAAG;EAAe;CAAS,CAC/B;AACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require("../_virtual/_rolldown/runtime.cjs");function e(e){return e?e.split(`/`).pop()||e:null}exports.formatNativeModelName=
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");var e=`Free`,t={"openhands/glm-5.2":`OpenHands GLM-5.2 (free)`,"openhands/deepseek-v4-flash":`OpenHands DeepSeek V4 Flash (free)`,"openhands/minimax-m2.7":`OpenHands MiniMax M2.7 (free)`},n=`Free OpenHands models: ${Object.keys(t).join(`, `)}. Other provider endpoints with similar model names may require separate billing.`,r=e=>!!(e&&e in t);function i(e){return e?r(e)?t[e]:e:null}function a(e){return e?r(e)?t[e]:e.split(`/`).pop()||e:null}exports.FREE_MODEL_BADGE_LABEL=e,exports.FREE_OPENHANDS_MODEL_NOTE=n,exports.formatModelNameForDisplay=i,exports.formatNativeModelName=a,exports.isFreeOpenHandsModel=r;
|
|
2
2
|
//# sourceMappingURL=format-model-name.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-model-name.cjs","names":[],"sources":["../../src/utils/format-model-name.ts"],"sourcesContent":["/**\n * Format a native (OpenHands-kind) routing model string for display, stripping\n * the provider route prefix (e.g. ``\"anthropic/claude-sonnet-4-5-20250929\"`` →\n * ``\"claude-sonnet-4-5-20250929\"``, ``\"litellm_proxy/openai/gpt-4o\"`` →\n * ``\"gpt-4o\"``) so a conversation chip shows a meaningful model name rather than\n * the full routing path.\n *\n * Returns ``null`` for an empty/nullish input, and falls back to the original\n * string when stripping the prefix would leave nothing (e.g. a trailing slash)\n * — never an empty string, which would collapse the chip text.\n *\n * Display-only: unlike {@link deriveProfileNameFromModel} this does not sanitize\n * to an identifier, so it keeps the real model id intact for the chip.\n */\nexport function formatNativeModelName(\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n const lastSegment = model.split(\"/\").pop();\n return lastSegment || model;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"format-model-name.cjs","names":[],"sources":["../../src/utils/format-model-name.ts"],"sourcesContent":["export const FREE_MODEL_BADGE_LABEL = \"Free\";\n\nexport const FREE_OPENHANDS_MODELS = {\n \"openhands/glm-5.2\": \"OpenHands GLM-5.2 (free)\",\n \"openhands/deepseek-v4-flash\": \"OpenHands DeepSeek V4 Flash (free)\",\n \"openhands/minimax-m2.7\": \"OpenHands MiniMax M2.7 (free)\",\n} as const;\n\nexport const FREE_OPENHANDS_MODEL_IDS = Object.keys(FREE_OPENHANDS_MODELS);\nexport const FREE_OPENHANDS_MODEL_NOTE = `Free OpenHands models: ${FREE_OPENHANDS_MODEL_IDS.join(\n \", \",\n)}. Other provider endpoints with similar model names may require separate billing.`;\n\nexport const isFreeOpenHandsModel = (\n model: string | null | undefined,\n): model is keyof typeof FREE_OPENHANDS_MODELS =>\n Boolean(model && model in FREE_OPENHANDS_MODELS);\n\nexport function formatModelNameForDisplay(\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n return isFreeOpenHandsModel(model) ? FREE_OPENHANDS_MODELS[model] : model;\n}\n\nexport function formatProviderModelNameForDisplay(\n provider: string | null | undefined,\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n const fullModel = provider ? `${provider}/${model}` : model;\n return isFreeOpenHandsModel(fullModel)\n ? FREE_OPENHANDS_MODELS[fullModel]\n : model;\n}\n\n/**\n * Format a native (OpenHands-kind) routing model string for display, stripping\n * the provider route prefix (e.g. ``\"anthropic/claude-sonnet-4-5-20250929\"`` →\n * ``\"claude-sonnet-4-5-20250929\"``, ``\"litellm_proxy/openai/gpt-4o\"`` →\n * ``\"gpt-4o\"``) so a conversation chip shows a meaningful model name rather than\n * the full routing path.\n *\n * Returns ``null`` for an empty/nullish input, and falls back to the original\n * string when stripping the prefix would leave nothing (e.g. a trailing slash)\n * — never an empty string, which would collapse the chip text.\n *\n * Display-only: unlike {@link deriveProfileNameFromModel} this does not sanitize\n * to an identifier, so it keeps the real model id intact for the chip.\n */\nexport function formatNativeModelName(\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n if (isFreeOpenHandsModel(model)) return FREE_OPENHANDS_MODELS[model];\n const lastSegment = model.split(\"/\").pop();\n return lastSegment || model;\n}\n"],"mappings":"6CAAA,IAAa,EAAyB,OAEzB,EAAwB,CACnC,oBAAqB,2BACrB,8BAA+B,qCAC/B,yBAA0B,+BAC5B,EAGa,EAA4B,0BADD,OAAO,KAAK,CACe,EAAyB,KAC1F,IACF,EAAE,mFAEW,EACX,GAEA,GAAQ,GAAS,KAAS,GAE5B,SAAgB,EACd,EACe,CAEf,OADK,EACE,EAAqB,CAAK,EAAI,EAAsB,GAAS,EADjD,IAErB,CA2BA,SAAgB,EACd,EACe,CAIf,OAHK,EACD,EAAqB,CAAK,EAAU,EAAsB,GAC1C,EAAM,MAAM,GAAG,EAAE,IAC9B,GAAe,EAHH,IAIrB"}
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
export declare const FREE_MODEL_BADGE_LABEL = "Free";
|
|
2
|
+
export declare const FREE_OPENHANDS_MODELS: {
|
|
3
|
+
readonly "openhands/glm-5.2": "OpenHands GLM-5.2 (free)";
|
|
4
|
+
readonly "openhands/deepseek-v4-flash": "OpenHands DeepSeek V4 Flash (free)";
|
|
5
|
+
readonly "openhands/minimax-m2.7": "OpenHands MiniMax M2.7 (free)";
|
|
6
|
+
};
|
|
7
|
+
export declare const FREE_OPENHANDS_MODEL_IDS: string[];
|
|
8
|
+
export declare const FREE_OPENHANDS_MODEL_NOTE: string;
|
|
9
|
+
export declare const isFreeOpenHandsModel: (model: string | null | undefined) => model is keyof typeof FREE_OPENHANDS_MODELS;
|
|
10
|
+
export declare function formatModelNameForDisplay(model: string | null | undefined): string | null;
|
|
11
|
+
export declare function formatProviderModelNameForDisplay(provider: string | null | undefined, model: string | null | undefined): string | null;
|
|
1
12
|
/**
|
|
2
13
|
* Format a native (OpenHands-kind) routing model string for display, stripping
|
|
3
14
|
* the provider route prefix (e.g. ``"anthropic/claude-sonnet-4-5-20250929"`` →
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
//#region src/utils/format-model-name.ts
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
var e = "Free", t = {
|
|
3
|
+
"openhands/glm-5.2": "OpenHands GLM-5.2 (free)",
|
|
4
|
+
"openhands/deepseek-v4-flash": "OpenHands DeepSeek V4 Flash (free)",
|
|
5
|
+
"openhands/minimax-m2.7": "OpenHands MiniMax M2.7 (free)"
|
|
6
|
+
}, n = `Free OpenHands models: ${Object.keys(t).join(", ")}. Other provider endpoints with similar model names may require separate billing.`, r = (e) => !!(e && e in t);
|
|
7
|
+
function i(e) {
|
|
8
|
+
return e ? r(e) ? t[e] : e : null;
|
|
9
|
+
}
|
|
10
|
+
function a(e) {
|
|
11
|
+
return e ? r(e) ? t[e] : e.split("/").pop() || e : null;
|
|
4
12
|
}
|
|
5
13
|
//#endregion
|
|
6
|
-
export { e as formatNativeModelName };
|
|
14
|
+
export { e as FREE_MODEL_BADGE_LABEL, n as FREE_OPENHANDS_MODEL_NOTE, i as formatModelNameForDisplay, a as formatNativeModelName, r as isFreeOpenHandsModel };
|
|
7
15
|
|
|
8
16
|
//# sourceMappingURL=format-model-name.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-model-name.js","names":[],"sources":["../../src/utils/format-model-name.ts"],"sourcesContent":["/**\n * Format a native (OpenHands-kind) routing model string for display, stripping\n * the provider route prefix (e.g. ``\"anthropic/claude-sonnet-4-5-20250929\"`` →\n * ``\"claude-sonnet-4-5-20250929\"``, ``\"litellm_proxy/openai/gpt-4o\"`` →\n * ``\"gpt-4o\"``) so a conversation chip shows a meaningful model name rather than\n * the full routing path.\n *\n * Returns ``null`` for an empty/nullish input, and falls back to the original\n * string when stripping the prefix would leave nothing (e.g. a trailing slash)\n * — never an empty string, which would collapse the chip text.\n *\n * Display-only: unlike {@link deriveProfileNameFromModel} this does not sanitize\n * to an identifier, so it keeps the real model id intact for the chip.\n */\nexport function formatNativeModelName(\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n const lastSegment = model.split(\"/\").pop();\n return lastSegment || model;\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"format-model-name.js","names":[],"sources":["../../src/utils/format-model-name.ts"],"sourcesContent":["export const FREE_MODEL_BADGE_LABEL = \"Free\";\n\nexport const FREE_OPENHANDS_MODELS = {\n \"openhands/glm-5.2\": \"OpenHands GLM-5.2 (free)\",\n \"openhands/deepseek-v4-flash\": \"OpenHands DeepSeek V4 Flash (free)\",\n \"openhands/minimax-m2.7\": \"OpenHands MiniMax M2.7 (free)\",\n} as const;\n\nexport const FREE_OPENHANDS_MODEL_IDS = Object.keys(FREE_OPENHANDS_MODELS);\nexport const FREE_OPENHANDS_MODEL_NOTE = `Free OpenHands models: ${FREE_OPENHANDS_MODEL_IDS.join(\n \", \",\n)}. Other provider endpoints with similar model names may require separate billing.`;\n\nexport const isFreeOpenHandsModel = (\n model: string | null | undefined,\n): model is keyof typeof FREE_OPENHANDS_MODELS =>\n Boolean(model && model in FREE_OPENHANDS_MODELS);\n\nexport function formatModelNameForDisplay(\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n return isFreeOpenHandsModel(model) ? FREE_OPENHANDS_MODELS[model] : model;\n}\n\nexport function formatProviderModelNameForDisplay(\n provider: string | null | undefined,\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n const fullModel = provider ? `${provider}/${model}` : model;\n return isFreeOpenHandsModel(fullModel)\n ? FREE_OPENHANDS_MODELS[fullModel]\n : model;\n}\n\n/**\n * Format a native (OpenHands-kind) routing model string for display, stripping\n * the provider route prefix (e.g. ``\"anthropic/claude-sonnet-4-5-20250929\"`` →\n * ``\"claude-sonnet-4-5-20250929\"``, ``\"litellm_proxy/openai/gpt-4o\"`` →\n * ``\"gpt-4o\"``) so a conversation chip shows a meaningful model name rather than\n * the full routing path.\n *\n * Returns ``null`` for an empty/nullish input, and falls back to the original\n * string when stripping the prefix would leave nothing (e.g. a trailing slash)\n * — never an empty string, which would collapse the chip text.\n *\n * Display-only: unlike {@link deriveProfileNameFromModel} this does not sanitize\n * to an identifier, so it keeps the real model id intact for the chip.\n */\nexport function formatNativeModelName(\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n if (isFreeOpenHandsModel(model)) return FREE_OPENHANDS_MODELS[model];\n const lastSegment = model.split(\"/\").pop();\n return lastSegment || model;\n}\n"],"mappings":";AAAA,IAAa,IAAyB,QAEzB,IAAwB;CACnC,qBAAqB;CACrB,+BAA+B;CAC/B,0BAA0B;AAC5B,GAGa,IAA4B,0BADD,OAAO,KAAK,CACe,EAAyB,KAC1F,IACF,EAAE,oFAEW,KACX,MAEA,GAAQ,KAAS,KAAS;AAE5B,SAAgB,EACd,GACe;CAEf,OADK,IACE,EAAqB,CAAK,IAAI,EAAsB,KAAS,IADjD;AAErB;AA2BA,SAAgB,EACd,GACe;CAIf,OAHK,IACD,EAAqB,CAAK,IAAU,EAAsB,KAC1C,EAAM,MAAM,GAAG,EAAE,IAC9B,KAAe,IAHH;AAIrB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openhands/agent-canvas",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "Agent Canvas UI for OpenHands - run AI coding agents with a visual interface",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -104,11 +104,13 @@
|
|
|
104
104
|
"build:lib": "npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true vite build && tsc -p tsconfig.lib.json",
|
|
105
105
|
"build:docker": "node scripts/docker-build.mjs",
|
|
106
106
|
"example:acp-docker:env": "node scripts/gen-acp-docker-env.mjs",
|
|
107
|
-
"
|
|
107
|
+
"predesktop": "node scripts/brand-dev-electron.mjs",
|
|
108
|
+
"desktop": "npm run build:app && electron electron",
|
|
108
109
|
"build:desktop": "npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && electron-builder --config electron-builder.config.mjs --publish never",
|
|
109
110
|
"build:desktop:universal": "npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && cross-env ELECTRON_ARCH=universal electron-builder --config electron-builder.config.mjs --publish never",
|
|
110
111
|
"download-uv": "node scripts/download-uv.mjs",
|
|
111
|
-
"download-node": "node scripts/download-node.mjs"
|
|
112
|
+
"download-node": "node scripts/download-node.mjs",
|
|
113
|
+
"generate-icons": "node scripts/generate-icons.mjs"
|
|
112
114
|
},
|
|
113
115
|
"lint-staged": {
|
|
114
116
|
"src/**/*.{ts,tsx,js}": [
|
|
@@ -163,6 +165,7 @@
|
|
|
163
165
|
"jsdom": "30.0.0",
|
|
164
166
|
"lint-staged": "16.4.0",
|
|
165
167
|
"msw": "2.15.0",
|
|
168
|
+
"png2icons": "2.0.1",
|
|
166
169
|
"postcss-prefix-selector": "2.1.1",
|
|
167
170
|
"prettier": "3.8.3",
|
|
168
171
|
"tailwindcss": "4.3.3",
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Brand the dev Electron app bundle with the product name (macOS only).
|
|
4
|
+
*
|
|
5
|
+
* Run automatically as the `predesktop` npm hook.
|
|
6
|
+
*
|
|
7
|
+
* WHY THIS EXISTS
|
|
8
|
+
*
|
|
9
|
+
* `npm run desktop` runs the app inside Electron's own prebuilt bundle,
|
|
10
|
+
* node_modules/electron/dist/Electron.app. macOS derives the name it shows
|
|
11
|
+
* in the Dock tooltip, the ⌘-Tab switcher and Finder from that bundle, at
|
|
12
|
+
* launch, before any JavaScript runs. No runtime API can change it —
|
|
13
|
+
* `app.setName()`, `app.name` and package.json `productName` only drive
|
|
14
|
+
* Electron's own notion of the name (menu bar, About panel, and
|
|
15
|
+
* app.getPath("userData")).
|
|
16
|
+
*
|
|
17
|
+
* The packaged app has never had this problem: electron-builder emits a
|
|
18
|
+
* bundle literally named "<productName>.app" with matching plist keys. This
|
|
19
|
+
* script puts the dev bundle in that same state.
|
|
20
|
+
*
|
|
21
|
+
* THE BUNDLE FILENAME IS THE PART THAT ACTUALLY SHOWS
|
|
22
|
+
*
|
|
23
|
+
* Patching the plist alone is NOT enough — verified the hard way. macOS
|
|
24
|
+
* prefers the bundle's filesystem name over CFBundleName/CFBundleDisplayName
|
|
25
|
+
* for the Dock tooltip. Two installed apps prove each half of this:
|
|
26
|
+
*
|
|
27
|
+
* DBeaver.app CFBundleName "DBeaver Community" → displays "DBeaver"
|
|
28
|
+
* (the filename wins over the plist)
|
|
29
|
+
* Antigravity.app CFBundleExecutable "Electron" → displays "Antigravity"
|
|
30
|
+
* (an Electron app whose executable name is irrelevant)
|
|
31
|
+
*
|
|
32
|
+
* So the fix aligns every source of the name at once: the .app directory
|
|
33
|
+
* name, CFBundleName and CFBundleDisplayName. That is exactly the shape of a
|
|
34
|
+
* packaged build, which is known to display correctly.
|
|
35
|
+
*
|
|
36
|
+
* Renaming the bundle means node_modules/electron/path.txt has to move with
|
|
37
|
+
* it: getElectronPath() in node_modules/electron/index.js joins path.txt onto
|
|
38
|
+
* dist/ and silently re-downloads Electron (~100 MB) if the result does not
|
|
39
|
+
* exist. The two are updated together, and the rename is rolled back if
|
|
40
|
+
* path.txt cannot be written.
|
|
41
|
+
*
|
|
42
|
+
* WHY THIS IS SAFE
|
|
43
|
+
*
|
|
44
|
+
* - Electron's prebuilt dist is ad-hoc *linker-signed*: `codesign -dv`
|
|
45
|
+
* reports `flags=0x20002(adhoc,linker-signed)`, `Info.plist=not bound`,
|
|
46
|
+
* `Sealed Resources=none`. The signature covers only the Mach-O, so
|
|
47
|
+
* editing Info.plist does not invalidate it and no re-signing is needed.
|
|
48
|
+
* - `npm run build:desktop` is unaffected: electron-builder packages from
|
|
49
|
+
* its own download cache (~/Library/Caches/electron/electron-v*.zip),
|
|
50
|
+
* never from node_modules/electron/dist.
|
|
51
|
+
*
|
|
52
|
+
* WHAT IT DELIBERATELY DOES NOT TOUCH
|
|
53
|
+
*
|
|
54
|
+
* CFBundleExecutable — left as "Electron". Antigravity above shows it has
|
|
55
|
+
* no bearing on the displayed name; it only feeds ps / Activity Monitor.
|
|
56
|
+
* Leaving it alone keeps path.txt's trailing segments valid.
|
|
57
|
+
* CFBundleIdentifier — kept at com.github.Electron. Changing it would split
|
|
58
|
+
* LaunchServices / TCC state per checkout for no visible gain.
|
|
59
|
+
*
|
|
60
|
+
* The changes live in node_modules, which `npm ci` wipes. That is fine: the
|
|
61
|
+
* `predesktop` hook re-applies them on every `npm run desktop`.
|
|
62
|
+
*
|
|
63
|
+
* This script must never block the desktop run — every failure path warns
|
|
64
|
+
* and exits 0.
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
import { execFileSync } from "node:child_process";
|
|
68
|
+
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
69
|
+
import { createRequire } from "node:module";
|
|
70
|
+
import { dirname, join } from "node:path";
|
|
71
|
+
import { fileURLToPath } from "node:url";
|
|
72
|
+
|
|
73
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
74
|
+
const projectRoot = join(__dirname, "..");
|
|
75
|
+
|
|
76
|
+
// Both keys are set. CFBundleDisplayName is the one LaunchServices reports;
|
|
77
|
+
// CFBundleName is the fallback and shows up in other bundle-name surfaces.
|
|
78
|
+
const NAME_KEYS = ["CFBundleDisplayName", "CFBundleName"];
|
|
79
|
+
|
|
80
|
+
function warn(message) {
|
|
81
|
+
console.warn(`[brand-dev-electron] ${message}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Root of the installed `electron` package, or null if it isn't resolvable. */
|
|
85
|
+
function resolveElectronPackage() {
|
|
86
|
+
const require = createRequire(import.meta.url);
|
|
87
|
+
return dirname(require.resolve("electron/package.json"));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Current value of `key`, or null when the key is absent. */
|
|
91
|
+
function readPlistString(plistPath, key) {
|
|
92
|
+
try {
|
|
93
|
+
return execFileSync(
|
|
94
|
+
"plutil",
|
|
95
|
+
["-extract", key, "raw", "-o", "-", plistPath],
|
|
96
|
+
{ encoding: "utf8" },
|
|
97
|
+
).trim();
|
|
98
|
+
} catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function writePlistString(plistPath, key, value) {
|
|
104
|
+
execFileSync("plutil", ["-replace", key, "-string", value, plistPath], {
|
|
105
|
+
stdio: "pipe",
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Rename dist/<current>.app to dist/<productName>.app and repoint path.txt.
|
|
111
|
+
* Returns { appDir, renamed }, or null if the bundle can't be determined.
|
|
112
|
+
*/
|
|
113
|
+
function ensureBundleName(pkgDir, productName) {
|
|
114
|
+
const distDir = join(pkgDir, "dist");
|
|
115
|
+
const pathFile = join(pkgDir, "path.txt");
|
|
116
|
+
if (!existsSync(pathFile)) {
|
|
117
|
+
warn(`No ${pathFile} — leaving the dev bundle alone.`);
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// e.g. "Electron.app/Contents/MacOS/Electron" — only the first segment
|
|
122
|
+
// (the bundle directory) is ours to rename.
|
|
123
|
+
const relative = readFileSync(pathFile, "utf8").trim();
|
|
124
|
+
const segments = relative.split("/");
|
|
125
|
+
const currentName = segments[0];
|
|
126
|
+
const desiredName = `${productName}.app`;
|
|
127
|
+
if (!currentName.endsWith(".app")) {
|
|
128
|
+
warn(`Unexpected path.txt entry "${relative}" — leaving the bundle alone.`);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const desiredDir = join(distDir, desiredName);
|
|
133
|
+
if (currentName === desiredName && existsSync(desiredDir)) {
|
|
134
|
+
return { appDir: desiredDir, renamed: false };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const currentDir = join(distDir, currentName);
|
|
138
|
+
let renamed = false;
|
|
139
|
+
if (existsSync(currentDir) && currentDir !== desiredDir) {
|
|
140
|
+
if (existsSync(desiredDir)) {
|
|
141
|
+
// Both present: a previous run renamed the bundle and something
|
|
142
|
+
// restored the original. Prefer the correctly named one and just fix
|
|
143
|
+
// path.txt rather than clobbering either bundle.
|
|
144
|
+
warn(`Both ${currentName} and ${desiredName} exist — using the latter.`);
|
|
145
|
+
} else {
|
|
146
|
+
renameSync(currentDir, desiredDir);
|
|
147
|
+
renamed = true;
|
|
148
|
+
}
|
|
149
|
+
} else if (!existsSync(desiredDir)) {
|
|
150
|
+
warn(`No Electron bundle under ${distDir} — leaving the dev bundle alone.`);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// path.txt MUST agree with the directory on disk; a stale entry makes
|
|
155
|
+
// getElectronPath() re-download Electron on the next run.
|
|
156
|
+
segments[0] = desiredName;
|
|
157
|
+
try {
|
|
158
|
+
writeFileSync(pathFile, segments.join("/"));
|
|
159
|
+
} catch (err) {
|
|
160
|
+
// Undo the rename so the checkout is left in a working state.
|
|
161
|
+
if (existsSync(desiredDir) && !existsSync(currentDir)) {
|
|
162
|
+
try {
|
|
163
|
+
renameSync(desiredDir, currentDir);
|
|
164
|
+
} catch {
|
|
165
|
+
warn(`Could not roll back the bundle rename in ${distDir}.`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
warn(`Could not update ${pathFile}: ${err.message}`);
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return { appDir: desiredDir, renamed };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function main() {
|
|
176
|
+
// The Dock/⌘-Tab name is a macOS bundle concept. On Windows the dev
|
|
177
|
+
// taskbar name comes from electron.exe's version resource and on Linux
|
|
178
|
+
// from the .desktop file / WM_CLASS — neither exists until the app is
|
|
179
|
+
// packaged, so there is nothing to patch.
|
|
180
|
+
if (process.platform !== "darwin") return;
|
|
181
|
+
|
|
182
|
+
const manifestPath = join(projectRoot, "electron", "package.json");
|
|
183
|
+
let productName;
|
|
184
|
+
try {
|
|
185
|
+
productName = JSON.parse(readFileSync(manifestPath, "utf8")).productName;
|
|
186
|
+
} catch (err) {
|
|
187
|
+
warn(`Could not read ${manifestPath}: ${err.message}`);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (!productName) {
|
|
191
|
+
warn(`No productName in ${manifestPath} — leaving the dev bundle alone.`);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
// The name becomes a directory entry; a "/" would silently retarget it.
|
|
195
|
+
if (productName.includes("/")) {
|
|
196
|
+
warn(`productName "${productName}" cannot be used as a bundle name.`);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
let pkgDir;
|
|
201
|
+
try {
|
|
202
|
+
pkgDir = resolveElectronPackage();
|
|
203
|
+
} catch (err) {
|
|
204
|
+
warn(`Could not resolve the electron package: ${err.message}`);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
let bundle;
|
|
209
|
+
try {
|
|
210
|
+
bundle = ensureBundleName(pkgDir, productName);
|
|
211
|
+
} catch (err) {
|
|
212
|
+
warn(`Could not rename the dev bundle: ${err.message}`);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (!bundle) return;
|
|
216
|
+
|
|
217
|
+
const plistPath = join(bundle.appDir, "Contents", "Info.plist");
|
|
218
|
+
if (!existsSync(plistPath)) {
|
|
219
|
+
warn(`No Info.plist at ${plistPath} — leaving the plist alone.`);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const stale = NAME_KEYS.filter(
|
|
224
|
+
(key) => readPlistString(plistPath, key) !== productName,
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
for (const key of stale) writePlistString(plistPath, key, productName);
|
|
229
|
+
} catch (err) {
|
|
230
|
+
// Read-only node_modules (CI caches, sandboxes) lands here. The app still
|
|
231
|
+
// runs; only the displayed name keeps saying "Electron".
|
|
232
|
+
warn(`Could not patch ${plistPath}: ${err.message}`);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Stay quiet when there was nothing to do, so repeat runs don't add noise.
|
|
237
|
+
if (bundle.renamed || stale.length > 0) {
|
|
238
|
+
console.log(
|
|
239
|
+
`[brand-dev-electron] Dev Electron bundle now identifies as "${productName}".`,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
main();
|
|
@@ -23,6 +23,7 @@ const IDENTICAL_VALUE_ALLOWLIST = new Set([
|
|
|
23
23
|
'COMMAND_MENU$SHORTCUT',
|
|
24
24
|
'CONVERSATION$ACP_AGENT_GENERIC',
|
|
25
25
|
'CONVERSATION$BUDGET_USAGE_FORMAT',
|
|
26
|
+
'CONVERSATION_PANEL$PREVIEW_GIT',
|
|
26
27
|
'FILES$VSCODE',
|
|
27
28
|
'GITHUB$AUTH_SCOPE',
|
|
28
29
|
'LAUNCH$PLUGIN_PATH',
|
|
@@ -37,6 +38,9 @@ const IDENTICAL_VALUE_ALLOWLIST = new Set([
|
|
|
37
38
|
'SETTINGS$APP_UPDATE_CARD_TITLE',
|
|
38
39
|
'SETTINGS$AZURE_DEVOPS',
|
|
39
40
|
'SETTINGS$CLOUD_SETTINGS_LINK',
|
|
41
|
+
'SETTINGS$VERSION_DOCKER',
|
|
42
|
+
'SETTINGS$VERSION_NPM_RECOMMENDED',
|
|
43
|
+
'SETTINGS$VERSION_PRODUCT_NAME',
|
|
40
44
|
'SETTINGS$GITHUB',
|
|
41
45
|
'SETTINGS$GITLAB',
|
|
42
46
|
'SETTINGS$MCP_AUTH_MODE_OAUTH',
|