@openhands/agent-canvas 1.3.0 → 1.5.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 +11 -12
- package/README.windows.md +4 -2
- package/build/assets/{Trans-DY6toRDu.js → Trans-DqF_OEZB.js} +1 -1
- package/build/assets/{acp-providers-Djl6vNn-.js → acp-providers-BQwoUBpe.js} +1 -1
- package/build/assets/active-backend-context-BCXRv5pm.js +1 -0
- package/build/assets/{add-backend-modal-DljoP9lc.js → add-backend-modal-BKHzq5no.js} +1 -1
- package/build/assets/{agent-profiles-settings-BJMmTZgv.js → agent-profiles-settings-CEp5CIz8.js} +1 -1
- package/build/assets/agent-server-compatibility-D6DSanlx.js +1 -0
- package/build/assets/agent-server-conversation-service.api-cylugfDz.js +41 -0
- package/build/assets/{agent-settings-lUknCeaF.js → agent-settings-C-tann3x.js} +2 -2
- package/build/assets/agent-settings-DGUKNSnU.js +1 -0
- package/build/assets/{alert-banner-Bpf2NQJq.js → alert-banner-Dd4woGbm.js} +1 -1
- package/build/assets/api-key-entry-screen-Bll_CkuQ.js +1 -0
- package/build/assets/app-settings-BpViWwpC.js +1 -0
- package/build/assets/automation-detail-Z9dN2f5l.js +2 -0
- package/build/assets/automation-export-D5uL0Tf8.js +2 -0
- package/build/assets/automations-list-BMOWcqzZ.js +1 -0
- package/build/assets/{back-nav-button-CUS2mi-U.js → back-nav-button-ZUDTMOTB.js} +1 -1
- package/build/assets/backend-form-modal-DhBT8P4g.js +1 -0
- package/build/assets/{backend-synced-settings-badge-CanzmG12.js → backend-synced-settings-badge-Db_REKVw.js} +1 -1
- package/build/assets/{base-modal-BuF2f0YL.js → base-modal-Cb0C6m0Q.js} +1 -1
- package/build/assets/{bot-D7eUAuSB.js → bot-C-EA6685.js} +1 -1
- package/build/assets/{brand-button-vMVuyDXu.js → brand-button-2Tp3aXk1.js} +1 -1
- package/build/assets/{browser-BifzWIBd.js → browser-QYLVr1kS.js} +2 -2
- package/build/assets/browser-store-BGXOGo-R.js +1 -0
- package/build/assets/{browser-tab-CkkqJnqw.js → browser-tab-BTTP1OE2.js} +1 -1
- package/build/assets/canvas-ui-BhxjoA1f.js +1 -0
- package/build/assets/{chat-send-button-B_jc5z5C.js → chat-send-button-BZHG2hAW.js} +1 -1
- package/build/assets/check-TbOEtHKj.js +1 -0
- package/build/assets/{chevron-down-CI8A6tet.js → chevron-down-D7IvFMBM.js} +1 -1
- package/build/assets/{circle-plus-check-toggle-C5YxjxvI.js → circle-plus-check-toggle-QQJKUnF6.js} +1 -1
- package/build/assets/client-source-Biqarhgr.js +1 -0
- package/build/assets/cloud-funnel-analytics-D-27T5Ao.js +1 -0
- package/build/assets/{combobox-caret-DoObzqf4.js → combobox-caret-A5jMVHgE.js} +1 -1
- package/build/assets/{command-menu-D-JV3Wqm.js → command-menu-BMVEme4H.js} +1 -1
- package/build/assets/{command-store-D8J5LMW1.js → command-store-jrWX_CcW.js} +1 -1
- package/build/assets/condenser-settings-CIa6eyB4.js +1 -0
- package/build/assets/{confirmation-modal-BGLu6XJN.js → confirmation-modal-4n_944zq.js} +1 -1
- package/build/assets/{context-menu-list-item-BD5_EaKN.js → context-menu-list-item-DvfFic5I.js} +1 -1
- package/build/assets/conversation-CHnEXGRM.js +1 -0
- package/build/assets/conversation-D4o4dG2t.js +89 -0
- package/build/assets/conversation-panel-11FjLCId.js +1 -0
- package/build/assets/conversation-service.api-0JG_fF9d.js +1 -0
- package/build/assets/conversation-state-store-JiUQp02U.js +1 -0
- package/build/assets/{conversation-store-LptbOvKa.js → conversation-store-BCSpLuEf.js} +1 -1
- package/build/assets/{conversation-tab-empty-state-B2dDYEwf.js → conversation-tab-empty-state-BUhKVwoi.js} +1 -1
- package/build/assets/{copy-3JCw_XFB.js → copy-D1YGjP-C.js} +1 -1
- package/build/assets/{copy-to-clipboard-button-CaR52OnA.js → copy-to-clipboard-button-Dp4Q_hXi.js} +1 -1
- package/build/assets/declaration-BGsHjPEW.js +1 -0
- package/build/assets/{device-verify-BsznkV-a.js → device-verify-CM086oKs.js} +1 -1
- package/build/assets/{dropdown-classes-DJSXeLqc.js → dropdown-classes-DZq0BQjb.js} +1 -1
- package/build/assets/{ellipsis-button-C5Z-tPFp.js → ellipsis-button-TPJdyxnK.js} +1 -1
- package/build/assets/{entry.client-JixNvFrr.js → entry.client-DypYHsYm.js} +2 -2
- package/build/assets/{enum-filter-dropdown-DXbVwiNZ.js → enum-filter-dropdown-CW_mBg0e.js} +1 -1
- package/build/assets/{environment-switch-overlay-DZQfRGTx.js → environment-switch-overlay-6laJch-9.js} +1 -1
- package/build/assets/{extensions-hub-DfvgqzTc.js → extensions-hub-BJFbFfKS.js} +1 -1
- package/build/assets/{extensions-navigation-D9i0DL62.js → extensions-navigation-DqSl7CJw.js} +1 -1
- package/build/assets/{external-link-D2zJjE9G.js → external-link-lhdITPqq.js} +1 -1
- package/build/assets/files-tab-c316dKAq.js +1 -0
- package/build/assets/{files-tab-store-DJsPxYdg.js → files-tab-store-tfCav6bB.js} +1 -1
- package/build/assets/{form-control-classes-ChpNBe9n.js → form-control-classes-CvUaw8_L.js} +1 -1
- package/build/assets/format-time-delta-DhDbkD7V.js +1 -0
- package/build/assets/git-provider-icon-DUb2pEos.js +1 -0
- package/build/assets/home-BQ-DC06B.js +1 -0
- package/build/assets/home-D7ds4Jyw.js +1 -0
- package/build/assets/index-home-BRFDWs_4.js +1 -0
- package/build/assets/install-server-modal-CvHvzZj3.js +1 -0
- package/build/assets/{launch-BgIlZLSX.js → launch-A47TK2Me.js} +1 -1
- package/build/assets/lesson-plan-DSf95kQ2.js +4 -0
- package/build/assets/{list-todo-BfH6yYUK.js → list-todo-CAtvkzcy.js} +1 -1
- package/build/assets/llm-not-configured-banner-B7DR8SPs.js +27 -0
- package/build/assets/llm-settings-Ch4ZbW3c.js +1 -0
- package/build/assets/llm-settings-Cvi7q4ox.js +1 -0
- package/build/assets/llm-subscription-service-Cz1yBBvE.js +1 -0
- package/build/assets/loader-circle-CsAsfLIs.js +1 -0
- package/build/assets/{loading-spinner-BLdswi6q.js → loading-spinner-Txxx1I1p.js} +1 -1
- package/build/assets/manage-backends-modal-DAVhNUCe.js +1 -0
- package/build/assets/manifest-958c741a.js +1 -0
- package/build/assets/{markdown-renderer-DMT7Zkpd.js → markdown-renderer-B6cJJ_MN.js} +1 -1
- package/build/assets/{mcp-CHkklDMv.js → mcp-BwssgMpg.js} +2 -2
- package/build/assets/{messages-B3RugH7P.js → messages-D8MeG2ZQ.js} +26 -26
- package/build/assets/{modal-body-DouOE5KH.js → modal-body-CDZdZ-eT.js} +1 -1
- package/build/assets/{modal-classes-Cf-4tbHz.js → modal-classes-B4oit_4c.js} +1 -1
- package/build/assets/{modal-close-button-B6CfxxJj.js → modal-close-button-DQElFMPo.js} +1 -1
- package/build/assets/model-selector-BxTbbKub.js +1 -0
- package/build/assets/{navigation-link-D8hfwvxI.js → navigation-link-imH6S7h2.js} +1 -1
- package/build/assets/onboarding-CyicadGt.js +1 -0
- package/build/assets/onboarding-modal-DQwihcTz.js +1 -0
- package/build/assets/option-service.api-DAkg_F7p.js +1 -0
- package/build/assets/organization-service.api-QknzKDh3.js +1 -0
- package/build/assets/package-Dk_VtWJ4.js +1 -0
- package/build/assets/path-utils-BECGet7G.js +1 -0
- package/build/assets/{pencil-Dj2XjKmI.js → pencil-CWhApFIT.js} +1 -1
- package/build/assets/{plan-components-CcCBmCzW.js → plan-components-CgPHWz3E.js} +1 -1
- package/build/assets/{planner-tab-CCqdXxkL.js → planner-tab-DPKHmMAX.js} +1 -1
- package/build/assets/plugins-management-service-DuTTxquo.js +1 -0
- package/build/assets/profiles-service.api-D6jvZOWu.js +1 -0
- package/build/assets/providers-B8pxQK8x.js +1 -0
- package/build/assets/proxy-CuhhyjdX.js +1 -0
- package/build/assets/{recommended-automations-launcher-CVEF_1pc.js → recommended-automations-launcher-DA6DWS7V.js} +1 -1
- package/build/assets/{refresh-cw-DM82EIyx.js → refresh-cw-B9B7-vsy.js} +1 -1
- package/build/assets/root-BhP6bTBB.js +2 -0
- package/build/assets/root-CYWeTrWE.css +1 -0
- package/build/assets/root-layout-oBaHHW4s.js +2 -0
- package/build/assets/{runtime-waiting-state-BsXLElvN.js → runtime-waiting-state-DeD9G7yJ.js} +1 -1
- package/build/assets/schema-field-BOLdL_U7.js +1 -0
- package/build/assets/sdk-section-page-ZIltERxf.js +1 -0
- package/build/assets/{sdk-settings-schema-Cv7M9eSe.js → sdk-settings-schema-Ba_Pa9uf.js} +1 -1
- package/build/assets/search-dIQ09UY2.js +1 -0
- package/build/assets/secrets-service-50DElFny.js +1 -0
- package/build/assets/{secrets-settings-DxTx9HgU.js → secrets-settings-Digl7JLe.js} +1 -1
- package/build/assets/{segmented-toggle-DyQqPhoD.js → segmented-toggle-C1-ZVyr5.js} +1 -1
- package/build/assets/settings-BfgLHsgd.js +1 -0
- package/build/assets/{settings-dropdown-input-BjunGXJb.js → settings-dropdown-input-BD5C9fBn.js} +1 -1
- package/build/assets/{settings-index-BjeuYFFa.js → settings-index-CODBijya.js} +1 -1
- package/build/assets/{settings-input-bD6npsDm.js → settings-input-CzNOq-Pj.js} +1 -1
- package/build/assets/{settings-list-classes-Dp_OgzN0.js → settings-list-classes-CuxH9ZoR.js} +1 -1
- package/build/assets/settings-modal-BcSWpKI0.js +1 -0
- package/build/assets/settings-service.api-Bsu1PvYO.js +1 -0
- package/build/assets/{settings-switch-5cuxl8Dc.js → settings-switch-DqmHAfWJ.js} +1 -1
- package/build/assets/{settings-utils-BMdG65By.js → settings-utils-B1lBErvV.js} +1 -1
- package/build/assets/shared-conversation-CDskdmrb.js +1 -0
- package/build/assets/{sidebar-layout-DuzJMMw-.js → sidebar-layout-Cn6eQaEI.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-CMmAYkh8.js → sidebar-mobile-menu-toggle-DmCmZgq1.js} +1 -1
- package/build/assets/{sidebar-nav-link-5AlTT5-j.js → sidebar-nav-link-DMc8AIe7.js} +1 -1
- package/build/assets/{sidebar-store-CZuE8AH5.js → sidebar-store-DXWSCFpa.js} +1 -1
- package/build/assets/{skill-card-pill-row-eTIkE4nz.js → skill-card-pill-row-DOIWjiMF.js} +1 -1
- package/build/assets/skills-plugins-DLgINYuY.js +1 -0
- package/build/assets/{skills-settings-BYn4-AQQ.js → skills-settings-DPiCWalR.js} +2 -2
- package/build/assets/{square-chevron-right-Czw3FFWc.js → square-chevron-right-DE-JN-2Z.js} +1 -1
- package/build/assets/{styled-tooltip-CgX2oRaK.js → styled-tooltip-CvsjHuIf.js} +1 -1
- package/build/assets/{suspense-X5dBsJzn.js → suspense-DmZ3MSSh.js} +1 -1
- package/build/assets/{task-list-tab-0k9PhuqO.js → task-list-tab-CuhcDycu.js} +1 -1
- package/build/assets/telemetry-DHiTRl5_.js +2 -0
- package/build/assets/{terminal-BsGcSpRS.js → terminal-CVqF-tCD.js} +1 -1
- package/build/assets/{toggle-switch-2j5wwR85.js → toggle-switch-CS0ClOy2.js} +1 -1
- package/build/assets/{trash-2-Be_7y3Mn.js → trash-2-BU6BlW4i.js} +1 -1
- package/build/assets/{typography-D8mHDeNG.js → typography-CQn9wyEX.js} +1 -1
- package/build/assets/use-acp-credential-form-LlfZO_DD.js +1 -0
- package/build/assets/{use-activate-agent-profile-WaAZYz4E.js → use-activate-agent-profile-DpQjsXM0.js} +1 -1
- package/build/assets/{use-active-agent-profile-CYY3vGar.js → use-active-agent-profile-Gw_uJujV.js} +1 -1
- package/build/assets/{use-active-conversation-D-r929nx.js → use-active-conversation-B0sttISF.js} +1 -1
- package/build/assets/use-agent-profiles-LHZEK0Gg.js +1 -0
- package/build/assets/{use-agent-state-DijdVAQ0.js → use-agent-state-C5uA0bRj.js} +1 -1
- package/build/assets/use-backends-health-DKt1SmiU.js +1 -0
- package/build/assets/{use-can-manage-org-profiles-BEo0peGn.js → use-can-manage-org-profiles-BAtqsbCi.js} +1 -1
- package/build/assets/use-cloud-current-user-id-C8m1oBy4.js +1 -0
- package/build/assets/use-config-CXy4vD0H.js +1 -0
- package/build/assets/use-create-conversation-CWQGNQ9J.js +1 -0
- package/build/assets/{use-create-secret-D5O5qdWC.js → use-create-secret-BIrsX3OB.js} +1 -1
- package/build/assets/{use-event-store-DjgU4wfO.js → use-event-store-CsD17BKu.js} +1 -1
- package/build/assets/{use-handle-plan-click-Mn_SNTCh.js → use-handle-plan-click-DEuO7Byo.js} +1 -1
- package/build/assets/use-is-authed-Dvbpiu3B.js +1 -0
- package/build/assets/{use-launch-skill-in-chat-BnoDgvAy.js → use-launch-skill-in-chat-CdHOoQGM.js} +1 -1
- package/build/assets/use-llm-profiles-DQpQxVOD.js +1 -0
- package/build/assets/use-plugins-marketplace-Bkk07W_M.js +1 -0
- package/build/assets/use-runtime-is-ready-D4pkGT6E.js +1 -0
- package/build/assets/use-save-agent-profile-BxEsjnW0.js +1 -0
- package/build/assets/{use-save-settings-D1HoCDbn.js → use-save-settings-ioSUMqbE.js} +1 -1
- package/build/assets/use-settings-DNJC4gqu.js +1 -0
- package/build/assets/use-settings-nav-items-BUsrDbVR.js +16 -0
- package/build/assets/use-skills-BsmKm23M.js +1 -0
- package/build/assets/{use-task-list-AVBLbbcR.js → use-task-list-rs7Xbzl8.js} +1 -1
- package/build/assets/{use-tracking-2ZwQwpg_.js → use-tracking-poxQHMwR.js} +1 -1
- package/build/assets/{use-user-conversation-OAfenBRG.js → use-user-conversation-B337kUKB.js} +1 -1
- package/build/assets/{useMutation-DCE9RcgK.js → useMutation-u8UgRgDK.js} +1 -1
- package/build/assets/{useMutationState-BUab8Kxr.js → useMutationState-OnAsCLA_.js} +1 -1
- package/build/assets/{useQueries-CRzaAqzH.js → useQueries-BpIlT8Mt.js} +1 -1
- package/build/assets/{useQuery-CpjHYtZc.js → useQuery-D5pEZbY0.js} +1 -1
- package/build/assets/{useTranslation-CDRCKC9-.js → useTranslation-Cbf5AGg_.js} +1 -1
- package/build/assets/{utils-D3U3rlqr.js → utils-DB9LsAzA.js} +1 -1
- package/build/assets/{vendor~browser-Cvg7jXCP.js → vendor~browser-5Njjw1Cl.js} +1 -1
- package/build/assets/{vendor~browser-tab-Di0kh5Zw.js → vendor~browser-tab-Xn94EtUo.js} +1 -1
- package/build/assets/{vendor~entry.client-9tWQ_Ugw.js → vendor~entry.client-DDuH4--y.js} +1 -1
- package/build/assets/{vendor~entry.client-D6BtSOtn.js → vendor~entry.client-DQGrNspu.js} +1 -1
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~dhilvkxv-BIieS_OD.js +2 -0
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~iztiaf2o-rqo6vRFz.js +185 -0
- package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~nn5zty47-Zl0G1QCy.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ljq5gbus-B2XD4bi2.js} +1 -1
- package/build/assets/{vendor~files-tab-B02k3xvx.js → vendor~files-tab-CiC3-lGh.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation-CYMF9JYB.js → vendor~index-home~home~conversation-panel~conversation-ChmYLVgz.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-9UMeuPV6.js → vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-B8XNNEQZ.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-d8aETPbZ.js → vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-CnJRLn5s.js} +1 -1
- package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DWteoTyr.js +2 -0
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-D7EUmQ8Y.js → vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-Dc5nKwLO.js} +1 -1
- package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BD0GaRGa.js → vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-tlf6AnDe.js} +1 -1
- package/build/assets/{vendor~launch-CHXA9cJu.js → vendor~launch-28DK5Rsl.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation-CpiTHpHl.js → vendor~root-layout~conversation-panel~conversation-8tIsyrPj.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation~shared-conversation-_TdZcNMD.js → vendor~root-layout~conversation-panel~conversation~shared-conversation-lYNG9C1U.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation-Cn2jwSga.js → vendor~root-layout~index-home~home~conversation-panel~conversation-Zhq6xAxR.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~shared-conversation~alert-banner~pl~rqjteh0a-CZM4hwUT.js → vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation~aler~gfu7qdtz-B81b08bw.js} +1 -1
- package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~settings~settings-index~agen~enjl5xdm-mMKDm94D.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~ftka0fnu-jpyLM1Nn.js} +2 -2
- package/build/assets/{verification-settings-DnXS6VWv.js → verification-settings-HRgEM-_3.js} +1 -1
- package/build/assets/x-ZE4iplpF.js +1 -0
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +9 -0
- package/build/locales/ca/openhands.json +9 -0
- package/build/locales/de/openhands.json +9 -0
- package/build/locales/en/openhands.json +10 -1
- package/build/locales/es/openhands.json +9 -0
- package/build/locales/fr/openhands.json +9 -0
- package/build/locales/it/openhands.json +9 -0
- package/build/locales/ja/openhands.json +9 -0
- package/build/locales/ko-KR/openhands.json +9 -0
- package/build/locales/no/openhands.json +9 -0
- package/build/locales/pt/openhands.json +9 -0
- package/build/locales/tr/openhands.json +9 -0
- package/build/locales/uk/openhands.json +9 -0
- package/build/locales/zh-CN/openhands.json +9 -0
- package/build/locales/zh-TW/openhands.json +9 -0
- package/config/defaults.json +5 -4
- 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 +9 -1
- package/dist/api/agent-server-adapter.js +105 -102
- package/dist/api/agent-server-adapter.js.map +1 -1
- package/dist/api/agent-server-config.cjs +1 -1
- package/dist/api/agent-server-config.cjs.map +1 -1
- package/dist/api/agent-server-config.d.ts +3 -0
- package/dist/api/agent-server-config.js +45 -23
- package/dist/api/agent-server-config.js.map +1 -1
- package/dist/api/backend-registry/auth.cjs +1 -1
- package/dist/api/backend-registry/auth.cjs.map +1 -1
- package/dist/api/backend-registry/auth.js +1 -1
- package/dist/api/backend-registry/auth.js.map +1 -1
- package/dist/api/backend-registry/default-backend.cjs +1 -1
- package/dist/api/backend-registry/default-backend.cjs.map +1 -1
- package/dist/api/backend-registry/default-backend.d.ts +3 -0
- package/dist/api/backend-registry/default-backend.js +22 -10
- package/dist/api/backend-registry/default-backend.js.map +1 -1
- package/dist/api/backend-registry/storage.cjs +1 -1
- package/dist/api/backend-registry/storage.cjs.map +1 -1
- package/dist/api/backend-registry/storage.js +38 -33
- package/dist/api/backend-registry/storage.js.map +1 -1
- package/dist/api/backend-registry/types.d.ts +2 -0
- package/dist/api/canvas-ui-client-tool.cjs +38 -0
- package/dist/api/canvas-ui-client-tool.cjs.map +1 -0
- package/dist/api/canvas-ui-client-tool.d.ts +14 -0
- package/dist/api/canvas-ui-client-tool.js +47 -0
- package/dist/api/canvas-ui-client-tool.js.map +1 -0
- package/dist/api/client-source.cjs +2 -0
- package/dist/api/client-source.cjs.map +1 -0
- package/dist/api/client-source.d.ts +9 -0
- package/dist/api/client-source.js +10 -0
- package/dist/api/client-source.js.map +1 -0
- package/dist/api/cloud/client.cjs +2 -0
- package/dist/api/cloud/client.cjs.map +1 -0
- package/dist/api/cloud/client.d.ts +4 -0
- package/dist/api/cloud/client.js +38 -0
- package/dist/api/cloud/client.js.map +1 -0
- 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.js +33 -31
- package/dist/api/cloud/conversation-service.api.js.map +1 -1
- package/dist/api/cloud/organization-service.api.cjs +1 -1
- package/dist/api/cloud/organization-service.api.cjs.map +1 -1
- package/dist/api/cloud/organization-service.api.js +11 -10
- package/dist/api/cloud/organization-service.api.js.map +1 -1
- package/dist/api/cloud/proxy.cjs +1 -1
- package/dist/api/cloud/proxy.cjs.map +1 -1
- package/dist/api/cloud/proxy.d.ts +2 -40
- package/dist/api/cloud/proxy.js +14 -39
- package/dist/api/cloud/proxy.js.map +1 -1
- package/dist/api/conversation-metadata-store.cjs +1 -1
- package/dist/api/conversation-metadata-store.cjs.map +1 -1
- package/dist/api/conversation-metadata-store.d.ts +2 -9
- package/dist/api/conversation-metadata-store.js +13 -9
- package/dist/api/conversation-metadata-store.js.map +1 -1
- 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.d.ts +2 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.js +98 -88
- package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.types.d.ts +5 -0
- package/dist/api/device-flow-client.cjs +1 -1
- package/dist/api/device-flow-client.cjs.map +1 -1
- package/dist/api/device-flow-client.d.ts +4 -58
- package/dist/api/device-flow-client.js +8 -98
- package/dist/api/device-flow-client.js.map +1 -1
- package/dist/api/git-service/agent-server-git-service.api.cjs +1 -1
- package/dist/api/git-service/agent-server-git-service.api.cjs.map +1 -1
- package/dist/api/git-service/agent-server-git-service.api.d.ts +10 -2
- package/dist/api/git-service/agent-server-git-service.api.js +107 -40
- package/dist/api/git-service/agent-server-git-service.api.js.map +1 -1
- package/dist/api/open-hands.types.d.ts +11 -0
- package/dist/api/secrets-service.cjs +1 -1
- package/dist/api/secrets-service.cjs.map +1 -1
- package/dist/api/secrets-service.js +15 -14
- package/dist/api/secrets-service.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 +73 -64
- 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/get-observation-content.cjs +2 -2
- package/dist/components/conversation-events/chat/event-content-helpers/get-observation-content.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-observation-content.js +2 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-observation-content.js.map +1 -1
- package/dist/components/features/backends/backend-form-modal.cjs +1 -1
- package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
- package/dist/components/features/backends/backend-form-modal.d.ts +7 -3
- package/dist/components/features/backends/backend-form-modal.js +216 -201
- package/dist/components/features/backends/backend-form-modal.js.map +1 -1
- package/dist/components/features/backends/backend-row.cjs +1 -1
- package/dist/components/features/backends/backend-row.cjs.map +1 -1
- package/dist/components/features/backends/backend-row.js +2 -1
- package/dist/components/features/backends/backend-row.js.map +1 -1
- package/dist/components/features/backends/backend-selector.cjs +1 -1
- package/dist/components/features/backends/backend-selector.cjs.map +1 -1
- package/dist/components/features/backends/backend-selector.js +51 -51
- package/dist/components/features/backends/backend-selector.js.map +1 -1
- package/dist/components/features/backends/device-flow-auth.cjs +1 -1
- package/dist/components/features/backends/device-flow-auth.cjs.map +1 -1
- package/dist/components/features/backends/device-flow-auth.d.ts +4 -1
- package/dist/components/features/backends/device-flow-auth.js +38 -38
- package/dist/components/features/backends/device-flow-auth.js.map +1 -1
- package/dist/components/features/chat/chat-interface.cjs +2 -2
- package/dist/components/features/chat/chat-interface.cjs.map +1 -1
- package/dist/components/features/chat/chat-interface.js +173 -165
- package/dist/components/features/chat/chat-interface.js.map +1 -1
- package/dist/components/features/chat/components/chat-input-actions.cjs +1 -1
- package/dist/components/features/chat/components/chat-input-actions.cjs.map +1 -1
- package/dist/components/features/chat/components/chat-input-actions.d.ts +2 -1
- package/dist/components/features/chat/components/chat-input-actions.js +44 -43
- package/dist/components/features/chat/components/chat-input-actions.js.map +1 -1
- package/dist/components/features/chat/components/chat-input-container.cjs +1 -1
- package/dist/components/features/chat/components/chat-input-container.cjs.map +1 -1
- package/dist/components/features/chat/components/chat-input-container.d.ts +2 -1
- package/dist/components/features/chat/components/chat-input-container.js +20 -19
- package/dist/components/features/chat/components/chat-input-container.js.map +1 -1
- package/dist/components/features/chat/components/chat-input-profile-picker.cjs +1 -1
- package/dist/components/features/chat/components/chat-input-profile-picker.cjs.map +1 -1
- package/dist/components/features/chat/components/chat-input-profile-picker.js +44 -32
- package/dist/components/features/chat/components/chat-input-profile-picker.js.map +1 -1
- package/dist/components/features/chat/components/resolve-picker-kind.cjs +1 -1
- package/dist/components/features/chat/components/resolve-picker-kind.cjs.map +1 -1
- package/dist/components/features/chat/components/resolve-picker-kind.d.ts +10 -22
- package/dist/components/features/chat/components/resolve-picker-kind.js +6 -3
- package/dist/components/features/chat/components/resolve-picker-kind.js.map +1 -1
- package/dist/components/features/chat/custom-chat-input.cjs +1 -1
- package/dist/components/features/chat/custom-chat-input.cjs.map +1 -1
- package/dist/components/features/chat/custom-chat-input.d.ts +2 -1
- package/dist/components/features/chat/custom-chat-input.js +52 -51
- package/dist/components/features/chat/custom-chat-input.js.map +1 -1
- package/dist/components/features/chat/interactive-chat-box.cjs +1 -1
- package/dist/components/features/chat/interactive-chat-box.cjs.map +1 -1
- package/dist/components/features/chat/interactive-chat-box.d.ts +2 -1
- package/dist/components/features/chat/interactive-chat-box.js +9 -8
- package/dist/components/features/chat/interactive-chat-box.js.map +1 -1
- package/dist/components/features/diff-viewer/commit-list.cjs +2 -0
- package/dist/components/features/diff-viewer/commit-list.cjs.map +1 -0
- package/dist/components/features/diff-viewer/commit-list.d.ts +13 -0
- package/dist/components/features/diff-viewer/commit-list.js +27 -0
- package/dist/components/features/diff-viewer/commit-list.js.map +1 -0
- package/dist/components/features/diff-viewer/commit-row.cjs +2 -0
- package/dist/components/features/diff-viewer/commit-row.cjs.map +1 -0
- package/dist/components/features/diff-viewer/commit-row.d.ts +14 -0
- package/dist/components/features/diff-viewer/commit-row.js +59 -0
- package/dist/components/features/diff-viewer/commit-row.js.map +1 -0
- package/dist/components/features/diff-viewer/file-diff-viewer.cjs +1 -1
- package/dist/components/features/diff-viewer/file-diff-viewer.cjs.map +1 -1
- package/dist/components/features/diff-viewer/file-diff-viewer.d.ts +7 -1
- package/dist/components/features/diff-viewer/file-diff-viewer.js +40 -39
- package/dist/components/features/diff-viewer/file-diff-viewer.js.map +1 -1
- package/dist/components/features/plugins/plugin-detail-modal.d.ts +2 -1
- package/dist/components/shared/modals/settings/settings-modal.cjs +1 -1
- package/dist/components/shared/modals/settings/settings-modal.cjs.map +1 -1
- package/dist/components/shared/modals/settings/settings-modal.js +23 -22
- package/dist/components/shared/modals/settings/settings-modal.js.map +1 -1
- package/dist/config/defaults.cjs +1 -1
- package/dist/config/defaults.cjs.map +1 -1
- package/dist/config/defaults.js +5 -4
- package/dist/config/defaults.js.map +1 -1
- package/dist/constants/acp-providers.cjs.map +1 -1
- package/dist/constants/acp-providers.d.ts +1 -1
- package/dist/constants/acp-providers.js.map +1 -1
- package/dist/constants/canvas-ui.cjs +2 -0
- package/dist/constants/canvas-ui.cjs.map +1 -0
- package/dist/constants/canvas-ui.d.ts +8 -0
- package/dist/constants/canvas-ui.js +6 -0
- package/dist/constants/canvas-ui.js.map +1 -0
- package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
- package/dist/contexts/conversation-websocket-context.js.map +1 -1
- package/dist/hooks/mutation/use-create-conversation.cjs +1 -1
- package/dist/hooks/mutation/use-create-conversation.cjs.map +1 -1
- package/dist/hooks/mutation/use-create-conversation.d.ts +2 -1
- package/dist/hooks/mutation/use-create-conversation.js +52 -52
- package/dist/hooks/mutation/use-create-conversation.js.map +1 -1
- package/dist/hooks/query/query-keys.cjs +1 -1
- package/dist/hooks/query/query-keys.cjs.map +1 -1
- package/dist/hooks/query/query-keys.d.ts +2 -0
- package/dist/hooks/query/query-keys.js +4 -1
- package/dist/hooks/query/query-keys.js.map +1 -1
- package/dist/hooks/query/use-backends-health.cjs +1 -1
- package/dist/hooks/query/use-backends-health.cjs.map +1 -1
- package/dist/hooks/query/use-backends-health.js +50 -48
- package/dist/hooks/query/use-backends-health.js.map +1 -1
- package/dist/hooks/query/use-cloud-organizations.cjs +1 -1
- package/dist/hooks/query/use-cloud-organizations.cjs.map +1 -1
- package/dist/hooks/query/use-cloud-organizations.d.ts +1 -0
- package/dist/hooks/query/use-cloud-organizations.js +5 -2
- package/dist/hooks/query/use-cloud-organizations.js.map +1 -1
- package/dist/hooks/query/use-commit-changes.cjs +2 -0
- package/dist/hooks/query/use-commit-changes.cjs.map +1 -0
- package/dist/hooks/query/use-commit-changes.d.ts +5 -0
- package/dist/hooks/query/use-commit-changes.js +34 -0
- package/dist/hooks/query/use-commit-changes.js.map +1 -0
- package/dist/hooks/query/use-task-polling.cjs +1 -1
- package/dist/hooks/query/use-task-polling.cjs.map +1 -1
- package/dist/hooks/query/use-task-polling.d.ts +3 -2
- package/dist/hooks/query/use-task-polling.js +53 -40
- package/dist/hooks/query/use-task-polling.js.map +1 -1
- package/dist/hooks/query/use-unified-git-commits.cjs +2 -0
- package/dist/hooks/query/use-unified-git-commits.cjs.map +1 -0
- package/dist/hooks/query/use-unified-git-commits.d.ts +10 -0
- package/dist/hooks/query/use-unified-git-commits.js +41 -0
- package/dist/hooks/query/use-unified-git-commits.js.map +1 -0
- package/dist/hooks/query/use-unified-git-diff.cjs +1 -1
- package/dist/hooks/query/use-unified-git-diff.cjs.map +1 -1
- package/dist/hooks/query/use-unified-git-diff.d.ts +5 -0
- package/dist/hooks/query/use-unified-git-diff.js +11 -4
- package/dist/hooks/query/use-unified-git-diff.js.map +1 -1
- package/dist/hooks/use-acp-model-context.cjs +1 -1
- package/dist/hooks/use-acp-model-context.cjs.map +1 -1
- package/dist/hooks/use-acp-model-context.d.ts +4 -1
- package/dist/hooks/use-acp-model-context.js +9 -8
- package/dist/hooks/use-acp-model-context.js.map +1 -1
- package/dist/hooks/use-auto-refresh-files-on-edit.cjs +1 -1
- package/dist/hooks/use-auto-refresh-files-on-edit.cjs.map +1 -1
- package/dist/hooks/use-auto-refresh-files-on-edit.js +1 -1
- package/dist/hooks/use-auto-refresh-files-on-edit.js.map +1 -1
- package/dist/hooks/use-chat-input-model-state.cjs.map +1 -1
- package/dist/hooks/use-chat-input-model-state.d.ts +2 -1
- package/dist/hooks/use-chat-input-model-state.js.map +1 -1
- package/dist/hooks/use-chat-input-profile-state.cjs +1 -1
- package/dist/hooks/use-chat-input-profile-state.cjs.map +1 -1
- package/dist/hooks/use-chat-input-profile-state.d.ts +1 -10
- package/dist/hooks/use-chat-input-profile-state.js +42 -15
- package/dist/hooks/use-chat-input-profile-state.js.map +1 -1
- package/dist/hooks/use-device-flow.cjs +1 -1
- package/dist/hooks/use-device-flow.cjs.map +1 -1
- package/dist/hooks/use-device-flow.d.ts +4 -1
- package/dist/hooks/use-device-flow.js +42 -40
- package/dist/hooks/use-device-flow.js.map +1 -1
- package/dist/hooks/use-tracking.cjs.map +1 -1
- package/dist/hooks/use-tracking.d.ts +2 -1
- package/dist/hooks/use-tracking.js.map +1 -1
- package/dist/i18n/declaration.cjs +1 -1
- package/dist/i18n/declaration.cjs.map +1 -1
- package/dist/i18n/declaration.d.ts +9 -0
- package/dist/i18n/declaration.js +1 -1
- package/dist/i18n/declaration.js.map +1 -1
- package/dist/i18n/index.cjs +1 -1
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.js +19 -18
- package/dist/i18n/index.js.map +1 -1
- package/dist/i18n/translation.cjs +3 -3
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +154 -1
- package/dist/i18n/translation.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +32 -32
- package/dist/lib/index.cjs +1 -1
- package/dist/lib/index.js +1 -1
- package/dist/locales/ar/openhands.json +9 -0
- package/dist/locales/ca/openhands.json +9 -0
- package/dist/locales/de/openhands.json +9 -0
- package/dist/locales/en/openhands.json +10 -1
- package/dist/locales/es/openhands.json +9 -0
- package/dist/locales/fr/openhands.json +9 -0
- package/dist/locales/it/openhands.json +9 -0
- package/dist/locales/ja/openhands.json +9 -0
- package/dist/locales/ko-KR/openhands.json +9 -0
- package/dist/locales/no/openhands.json +9 -0
- package/dist/locales/pt/openhands.json +9 -0
- package/dist/locales/tr/openhands.json +9 -0
- package/dist/locales/uk/openhands.json +9 -0
- package/dist/locales/zh-CN/openhands.json +9 -0
- package/dist/locales/zh-TW/openhands.json +9 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/cloud-client.cjs +2 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/cloud-client.cjs.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/cloud-client.js +351 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/cloud-client.js.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/device-flow-client.cjs +2 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/device-flow-client.cjs.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/device-flow-client.js +106 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/device-flow-client.js.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.cjs +2 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.cjs.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.js +69 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.js.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/clients.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/clients.js +3 -0
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js +18 -2
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp.js.map +1 -1
- package/dist/node_modules/axios/index.cjs +1 -1
- package/dist/node_modules/axios/index.js +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +2 -2
- 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 +67 -66
- package/dist/routes/app-settings.js.map +1 -1
- package/dist/routes/commits-tab.cjs +2 -0
- package/dist/routes/commits-tab.cjs.map +1 -0
- package/dist/routes/commits-tab.d.ts +8 -0
- package/dist/routes/commits-tab.js +45 -0
- package/dist/routes/commits-tab.js.map +1 -0
- package/dist/routes/files-tab.cjs +1 -1
- package/dist/routes/files-tab.cjs.map +1 -1
- package/dist/routes/files-tab.js +148 -127
- package/dist/routes/files-tab.js.map +1 -1
- package/dist/services/cloud-funnel-analytics.cjs +2 -0
- package/dist/services/cloud-funnel-analytics.cjs.map +1 -0
- package/dist/services/cloud-funnel-analytics.d.ts +12 -0
- package/dist/services/cloud-funnel-analytics.js +53 -0
- package/dist/services/cloud-funnel-analytics.js.map +1 -0
- package/dist/services/telemetry.cjs +1 -1
- package/dist/services/telemetry.cjs.map +1 -1
- package/dist/services/telemetry.js +49 -47
- package/dist/services/telemetry.js.map +1 -1
- package/dist/types/agent-server/core/base/action.d.ts +5 -4
- package/dist/types/agent-server/core/base/base.d.ts +3 -2
- package/dist/types/agent-server/core/base/observation.d.ts +1 -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 +3 -5
- package/dist/types/agent-server/type-guards.js +2 -1
- package/dist/types/agent-server/type-guards.js.map +1 -1
- package/dist/types/automation.d.ts +5 -0
- package/dist/utils/api-error-message.d.ts +11 -0
- package/dist/utils/automation-timeout.d.ts +19 -0
- package/dist/utils/base-path.cjs +2 -0
- package/dist/utils/base-path.cjs.map +1 -0
- package/dist/utils/base-path.d.ts +2 -0
- package/dist/utils/base-path.js +23 -0
- package/dist/utils/base-path.js.map +1 -0
- package/package.json +2 -2
- package/scripts/check-sdk-version-sync.mjs +6 -6
- package/scripts/dev-safe.mjs +7 -8
- package/scripts/dev-static.mjs +3 -0
- package/scripts/dev-with-automation.mjs +3 -0
- package/scripts/docker-build.mjs +4 -0
- package/scripts/static-server.mjs +93 -7
- package/tools/canvas_ui_tool.py +14 -8
- package/build/assets/active-backend-context-B3umL5R-.js +0 -1
- package/build/assets/agent-server-client-options-DVLRd9sw.js +0 -1
- package/build/assets/agent-server-conversation-service.api-D_ZvtJjG.js +0 -5
- package/build/assets/agent-settings-BVVFzBWS.js +0 -1
- package/build/assets/api-key-entry-screen-CWEHcPJA.js +0 -1
- package/build/assets/app-settings-Dj90qosy.js +0 -1
- package/build/assets/automation-detail-CXJU0_gF.js +0 -2
- package/build/assets/automation-export-FWY9LPsG.js +0 -2
- package/build/assets/automations-list-DDGBkWLC.js +0 -1
- package/build/assets/backend-form-modal-DSbrafX2.js +0 -1
- package/build/assets/browser-store-BI6uklCG.js +0 -1
- package/build/assets/check-Bvi71siz.js +0 -1
- package/build/assets/condenser-settings-30cX9SK6.js +0 -1
- package/build/assets/conversation-BltULtFA.js +0 -89
- package/build/assets/conversation-e0a0_X4S.js +0 -1
- package/build/assets/conversation-panel-Cr9_ZGI-.js +0 -1
- package/build/assets/conversation-service.api-DQaKzIRj.js +0 -1
- package/build/assets/conversation-state-store-B2Bp32XI.js +0 -1
- package/build/assets/declaration-gq8V5eTU.js +0 -1
- package/build/assets/files-tab-DDtEJcGE.js +0 -1
- package/build/assets/git-provider-icon-BjkecAuV.js +0 -1
- package/build/assets/home-BCKWpKpf.js +0 -1
- package/build/assets/index-redirect-CUUJiNki.js +0 -1
- package/build/assets/install-server-modal-BIugLhVB.js +0 -1
- package/build/assets/lesson-plan-DgpP80mJ.js +0 -4
- package/build/assets/llm-not-configured-banner-BlX8NifC.js +0 -27
- package/build/assets/llm-settings-DJmbryaE.js +0 -1
- package/build/assets/llm-settings-kU5v0H1Z.js +0 -1
- package/build/assets/llm-subscription-service-CKyaV24y.js +0 -1
- package/build/assets/loader-circle-BEykUKYG.js +0 -1
- package/build/assets/manage-backends-modal-C8FJQIZR.js +0 -1
- package/build/assets/manifest-56d40d7c.js +0 -1
- package/build/assets/model-selector-BOj1wBlq.js +0 -1
- package/build/assets/mouse-pointer-click-PdEQPL6v.js +0 -1
- package/build/assets/onboarding-DYhDxmI9.js +0 -1
- package/build/assets/onboarding-modal-CP_WxDC9.js +0 -1
- package/build/assets/option-service.api-C0tYT4-r.js +0 -1
- package/build/assets/organization-service.api-CnynNoT-.js +0 -1
- package/build/assets/path-utils-DWcgCGen.js +0 -1
- package/build/assets/plugins-management-service-BAp70KN7.js +0 -1
- package/build/assets/profiles-service.api-CeYEmSM3.js +0 -1
- package/build/assets/providers-BxCuC9bZ.js +0 -1
- package/build/assets/proxy-CHmFkV16.js +0 -1
- package/build/assets/root-V8fkplMy.css +0 -1
- package/build/assets/root-layout-CttG_lQi.js +0 -2
- package/build/assets/root-uJ2t9rCQ.js +0 -2
- package/build/assets/schema-field-xUr6rDd6.js +0 -1
- package/build/assets/sdk-section-page-CbLrVUa3.js +0 -1
- package/build/assets/search-4DHskuhE.js +0 -1
- package/build/assets/secrets-service-CZYjNxFw.js +0 -1
- package/build/assets/settings-DnlfS09K.js +0 -1
- package/build/assets/settings-modal-DfTcL-mV.js +0 -1
- package/build/assets/settings-service.api-K4ncGlBv.js +0 -1
- package/build/assets/shared-conversation-DWtBkJv7.js +0 -1
- package/build/assets/skills-plugins-BJ040luO.js +0 -1
- package/build/assets/use-acp-credential-form-EtnbtYt0.js +0 -1
- package/build/assets/use-agent-profiles-DEAMFp-W.js +0 -1
- package/build/assets/use-backends-health-DkC7tKkC.js +0 -1
- package/build/assets/use-cloud-current-user-id-Dm99wXp2.js +0 -1
- package/build/assets/use-config-CHzNIHpv.js +0 -1
- package/build/assets/use-create-conversation-CTsvZ96U.js +0 -1
- package/build/assets/use-is-authed-_dhQ2Xuj.js +0 -1
- package/build/assets/use-llm-profiles-BMhPDlwQ.js +0 -1
- package/build/assets/use-plugins-marketplace-BGb-KgfD.js +0 -1
- package/build/assets/use-runtime-is-ready-CC-KrLKe.js +0 -1
- package/build/assets/use-save-agent-profile-CLMmbx_X.js +0 -1
- package/build/assets/use-settings-BReAMxCG.js +0 -1
- package/build/assets/use-settings-nav-items-xe1YgLnE.js +0 -16
- package/build/assets/use-skills-Dqo-pDDx.js +0 -1
- package/build/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~d1e18dtv-5Q6lQJdE.js +0 -177
- package/build/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~ncdxw0bh-ClHnt5lR.js +0 -10
- package/build/assets/vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-CqXiHwjU.js +0 -2
- package/build/assets/x-Cb0WAtak.js +0 -1
- /package/build/assets/{__vite-browser-external-4xJsU2-u.js → __vite-browser-external-DU-Cb_sT.js} +0 -0
- /package/build/assets/{automation-BU8zu-FP.js → automation-BVEmGghX.js} +0 -0
- /package/build/assets/{checkmark-h7udgXMM.js → checkmark-DhcMGwtO.js} +0 -0
- /package/build/assets/{close-p3Op5lxI.js → close-DO5Rq_CS.js} +0 -0
- /package/build/assets/{code-tag-DYlAhEQY.js → code-tag-BvjtzUsr.js} +0 -0
- /package/build/assets/{color-themes-DPBzNtVg.js → color-themes-bVMmJJG6.js} +0 -0
- /package/build/assets/{common-Dh7OqABE.js → common-CxbUL3nR.js} +0 -0
- /package/build/assets/{conversation-local-storage-F6zVMM--.js → conversation-local-storage-B31voBg7.js} +0 -0
- /package/build/assets/{copy-BLmGeJcd.js → copy-DLUw2us-.js} +0 -0
- /package/build/assets/{createLucideIcon-CVAsW2Yo.js → createLucideIcon-D4Tak8A1.js} +0 -0
- /package/build/assets/{dist-CodhvuAP.js → dist-Dj01FXbZ.js} +0 -0
- /package/build/assets/{environment-switch-store-DkjlKWzN.js → environment-switch-store-D9hB9PvY.js} +0 -0
- /package/build/assets/{extension-module-card-classes-9V3J9J_b.js → extension-module-card-classes-BlO4w702.js} +0 -0
- /package/build/assets/{folder-mMWFvaw0.js → folder-ynxP2EIL.js} +0 -0
- /package/build/assets/{get-language-from-path-CPNnuVhI.js → get-language-from-path-rWEQrOGU.js} +0 -0
- /package/build/assets/{git-status-mapper-BI8FyUVp.js → git-status-mapper-C3rfzUex.js} +0 -0
- /package/build/assets/{handle-capture-consent-CPMXU29K.js → handle-capture-consent-DDnXMC9Y.js} +0 -0
- /package/build/assets/{iconBase-DaTRRUjy.js → iconBase-CuvxAQZ5.js} +0 -0
- /package/build/assets/{link-external-DfKQroKX.js → link-external-BVDiJfZt.js} +0 -0
- /package/build/assets/{llm-subscription-DtsX5Lhg.js → llm-subscription-BkdHwtQe.js} +0 -0
- /package/build/assets/{map-provider-BM2SJarp.js → map-provider-XSFHmdDs.js} +0 -0
- /package/build/assets/{middleware-DYHYNAnP.js → middleware-CWYDMVuG.js} +0 -0
- /package/build/assets/{modal-backdrop-zVwfOJZr.js → modal-backdrop-Dsmzgr5s.js} +0 -0
- /package/build/assets/{navigation-context-DPs2G0X8.js → navigation-context-SjzfpygH.js} +0 -0
- /package/build/assets/{objectWithoutPropertiesLoose-BgYIAs2y.js → objectWithoutPropertiesLoose-CQwg6tC0.js} +0 -0
- /package/build/assets/{openhands-logo-bcNw5bkY.js → openhands-logo-C-gDp1wr.js} +0 -0
- /package/build/assets/{react-DPDgL6du.js → react-ao3tWj6K.js} +0 -0
- /package/build/assets/{search-BsjCEFNf.js → search-pb4UKTfK.js} +0 -0
- /package/build/assets/{settings-mQUckT0g.js → settings-DksoDv5z.js} +0 -0
- /package/build/assets/{settings-gear-MXCyZW0x.js → settings-gear-D_HVvE5L.js} +0 -0
- /package/build/assets/{settings-like-page-layout-classes-DENKlZpD.js → settings-like-page-layout-classes-DLrsPCaI.js} +0 -0
- /package/build/assets/{settings-section-header-context-COMOIaxV.js → settings-section-header-context-C2MUIG88.js} +0 -0
- /package/build/assets/{skills-9cDZONKh.js → skills-CH4xgIh-.js} +0 -0
- /package/build/assets/{switch-skeleton-DqQwalyu.js → switch-skeleton-BpSOvZ-n.js} +0 -0
- /package/build/assets/{terminal-BuLtIrb9.js → terminal-Dokfkxn0.js} +0 -0
- /package/build/assets/{u-check-circle-BqoIxNz_.js → u-check-circle-DPWVO-9N.js} +0 -0
- /package/build/assets/{u-check-circle-half-LiwZkuFe.js → u-check-circle-half-BGNAAjOW.js} +0 -0
- /package/build/assets/{u-edit-DJ90xc8Z.js → u-edit-BIskOoEG.js} +0 -0
- /package/build/assets/{use-breakpoint-B-O0lQ84.js → use-breakpoint-OjLm94cF.js} +0 -0
- /package/build/assets/{use-click-outside-element-Bf4Omzot.js → use-click-outside-element-Jpt2WWd7.js} +0 -0
- /package/build/assets/{use-onboarding-completion-C_Swglzp.js → use-onboarding-completion-DkRpDTsD.js} +0 -0
- /package/build/assets/{v4-DbCkTSoU.js → v4-DPgam_jW.js} +0 -0
- /package/build/assets/{vendor~browser-Dqd33JyP.js → vendor~browser-BvEKaLBz.js} +0 -0
- /package/build/assets/{vendor~conversation-panel~conversation~alert-banner-DHDkknt5.js → vendor~conversation-panel~conversation~alert-banner-CznX01nZ.js} +0 -0
- /package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~i3v2mlbw-BrJQ3XZH.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~e0djk9ee-Cw6LUe8p.js} +0 -0
- /package/build/assets/{vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~k6tszsdc-Bb-xMtbv.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~g9hift2g-DmmpG9SI.js} +0 -0
- /package/build/assets/{vendor~entry.client~root~root-layout~index-redirect~home~conversation-panel~conversation~la~byh8a1g4-XNPdpuO8.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~jkpzbynd-CkpBIhVe.js} +0 -0
- /package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DTzw2x50.js → vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BuL5kjfS.js} +0 -0
- /package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~launch~skills-settings~automations-~ki5qnp0d-rV6d1Iv_.js → vendor~root-layout~index-home~home~conversation-panel~conversation~launch~skills-settings~a~j2jlu22h-DUYl8gbZ.js} +0 -0
- /package/build/assets/{vendor~root-layout~home~mcp~automations-list~onboarding-modal-CXyYYvYh.js → vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-pIgQDxTc.js} +0 -0
- /package/build/assets/{vendor~terminal-aeP3PnKf.js → vendor~terminal-jAaNQWS9.js} +0 -0
- /package/build/assets/{x-mark-Batp6gXa.js → x-mark-C5przfXl.js} +0 -0
package/dist/routes/files-tab.js
CHANGED
|
@@ -9,143 +9,164 @@ import { SegmentedToggle as s } from "../components/features/files-tab/segmented
|
|
|
9
9
|
import { NoFileSelectedMessage as c } from "../components/features/files-tab/no-file-selected-message.js";
|
|
10
10
|
import { useUnifiedGetGitChanges as l } from "../hooks/query/use-unified-get-git-changes.js";
|
|
11
11
|
import { useWorkspaceFiles as u } from "../hooks/query/use-workspace-files.js";
|
|
12
|
-
import { useWorkspaceMutationCounter as
|
|
13
|
-
import { useWorkspaceFileContent as
|
|
14
|
-
import { useHasAttachedSource as
|
|
15
|
-
import { useHasGitCommits as
|
|
16
|
-
import { useAutoRefreshFilesOnEdit as
|
|
17
|
-
import { sortFilesByPriority as
|
|
18
|
-
import { FileQuickRow as
|
|
19
|
-
import { FileTreeView as
|
|
20
|
-
import { FileContentViewer as
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import
|
|
12
|
+
import { useWorkspaceMutationCounter as ee, withWorkspaceCacheBuster as te } from "../stores/use-workspace-mutation-counter.js";
|
|
13
|
+
import { useWorkspaceFileContent as ne } from "../hooks/query/use-workspace-file-content.js";
|
|
14
|
+
import { useHasAttachedSource as re } from "../hooks/use-has-attached-source.js";
|
|
15
|
+
import { useHasGitCommits as d } from "../hooks/query/use-has-git-commits.js";
|
|
16
|
+
import { useAutoRefreshFilesOnEdit as f } from "../hooks/use-auto-refresh-files-on-edit.js";
|
|
17
|
+
import { sortFilesByPriority as ie } from "../utils/file-priority.js";
|
|
18
|
+
import { FileQuickRow as p } from "../components/features/files-tab/file-quick-row.js";
|
|
19
|
+
import { FileTreeView as m } from "../components/features/files-tab/file-tree-view.js";
|
|
20
|
+
import { FileContentViewer as h } from "../components/features/files-tab/file-content-viewer.js";
|
|
21
|
+
import g from "../icons/u-refresh.js";
|
|
22
|
+
import { useUnifiedGitCommits as _ } from "../hooks/query/use-unified-git-commits.js";
|
|
23
|
+
import v from "./changes-tab.js";
|
|
24
|
+
import y from "./commits-tab.js";
|
|
25
|
+
import { useCallback as b, useEffect as x, useMemo as ae, useState as S } from "react";
|
|
26
|
+
import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
25
27
|
//#region src/routes/files-tab.tsx
|
|
26
|
-
function
|
|
27
|
-
let { t:
|
|
28
|
-
|
|
29
|
-
let { hasAttachedSource:
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
function E() {
|
|
29
|
+
let { t: E } = e("openhands");
|
|
30
|
+
f();
|
|
31
|
+
let { hasAttachedSource: D, isLoading: O } = re(), { hasCommits: k } = d({ enabled: D }), { conversationId: A } = n(), { state: j, setFilesTabDiffView: M, setFilesTabContentViewMode: N } = r(A ?? ""), P = (D || O) && k !== !1, F = j.filesTabDiffView ?? P, I = j.filesTabContentViewMode, { isSuccess: oe, isUnsupported: L } = _(), R = oe && !L, [z, B] = S(!1), V = F ? "on" : "off";
|
|
32
|
+
z && R && (V = "commits");
|
|
33
|
+
let [H, U] = S(!1), W = u(), G = ae(() => W.data ?? [], [W.data]), K = a((e) => e.selectedPath), q = a((e) => e.selectedConversationId), J = a((e) => e.setSelectedPath), Y = q === A ? K : null, X = b((e) => J(e, A), [A, J]), se = ne(Y), ce = ee((e) => e.count), Z = te(se.data?.staticUrl ?? null, ce);
|
|
34
|
+
x(() => {
|
|
35
|
+
q !== A && J(null, A);
|
|
32
36
|
}, [
|
|
33
|
-
G,
|
|
34
|
-
N,
|
|
35
|
-
K
|
|
36
|
-
]), C(() => {
|
|
37
|
-
if (q || U.length === 0) return;
|
|
38
|
-
let [e] = _(U);
|
|
39
|
-
e && K(e, N);
|
|
40
|
-
}, [
|
|
41
|
-
U,
|
|
42
37
|
q,
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
A,
|
|
39
|
+
J
|
|
40
|
+
]), x(() => {
|
|
41
|
+
if (Y || G.length === 0) return;
|
|
42
|
+
let [e] = ie(G);
|
|
43
|
+
e && J(e, A);
|
|
44
|
+
}, [
|
|
45
|
+
G,
|
|
46
|
+
Y,
|
|
47
|
+
A,
|
|
48
|
+
J
|
|
45
49
|
]);
|
|
46
|
-
let Q = i(), { refetch:
|
|
47
|
-
|
|
50
|
+
let Q = i(), { refetch: le, isFetching: $ } = l(), ue = () => {
|
|
51
|
+
le(), Q.invalidateQueries({ queryKey: ["workspace-files"] }), Q.invalidateQueries({ queryKey: ["workspace-file-content"] }), Q.invalidateQueries({ queryKey: ["git_commits"] });
|
|
52
|
+
};
|
|
53
|
+
return /* @__PURE__ */ T("main", {
|
|
48
54
|
className: "h-full w-full flex flex-col items-stretch",
|
|
49
55
|
"data-testid": "files-tab",
|
|
50
|
-
children: [
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
56
|
+
children: [
|
|
57
|
+
/* @__PURE__ */ T("div", {
|
|
58
|
+
className: "flex items-center gap-3 px-3 py-1.5 border-b border-[var(--oh-border)]",
|
|
59
|
+
children: [
|
|
60
|
+
/* @__PURE__ */ w(s, {
|
|
61
|
+
ariaLabel: E(t.FILES$DIFF_VIEW),
|
|
62
|
+
testId: "files-tab-diff-toggle",
|
|
63
|
+
value: V,
|
|
64
|
+
options: [
|
|
65
|
+
{
|
|
66
|
+
value: "on",
|
|
67
|
+
label: E(t.FILES$DIFF_VIEW)
|
|
68
|
+
},
|
|
69
|
+
...R ? [{
|
|
70
|
+
value: "commits",
|
|
71
|
+
label: E(t.DIFF_VIEWER$COMMITS)
|
|
72
|
+
}] : [],
|
|
73
|
+
{
|
|
74
|
+
value: "off",
|
|
75
|
+
label: E(t.COMMON$FILES)
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
onChange: (e) => {
|
|
79
|
+
e === "commits" ? B(!0) : (B(!1), M(e === "on"));
|
|
80
|
+
}
|
|
81
|
+
}),
|
|
82
|
+
V === "off" && /* @__PURE__ */ w(s, {
|
|
83
|
+
ariaLabel: E(t.FILES$RICH),
|
|
84
|
+
testId: "files-tab-content-mode-toggle",
|
|
85
|
+
value: I,
|
|
86
|
+
options: [{
|
|
87
|
+
value: "rich",
|
|
88
|
+
label: E(t.FILES$RICH)
|
|
89
|
+
}, {
|
|
90
|
+
value: "plain",
|
|
91
|
+
label: E(t.FILES$PLAIN)
|
|
92
|
+
}],
|
|
93
|
+
onChange: N
|
|
94
|
+
}),
|
|
95
|
+
/* @__PURE__ */ T("div", {
|
|
96
|
+
className: "ml-auto flex items-center gap-1",
|
|
97
|
+
children: [V === "off" && Z && /* @__PURE__ */ w("a", {
|
|
98
|
+
href: Z,
|
|
99
|
+
target: "_blank",
|
|
100
|
+
rel: "noopener noreferrer",
|
|
101
|
+
"aria-label": E(t.FILES$OPEN_IN_NEW_WINDOW),
|
|
102
|
+
title: E(t.FILES$OPEN_IN_NEW_WINDOW),
|
|
103
|
+
"data-testid": "files-tab-open-in-new-window",
|
|
104
|
+
className: "flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:bg-[var(--oh-interactive-hover)] cursor-pointer text-white",
|
|
105
|
+
children: /* @__PURE__ */ w(o, {
|
|
106
|
+
width: 14,
|
|
107
|
+
height: 14
|
|
108
|
+
})
|
|
109
|
+
}), /* @__PURE__ */ w("button", {
|
|
110
|
+
type: "button",
|
|
111
|
+
onClick: ue,
|
|
112
|
+
disabled: $,
|
|
113
|
+
"aria-label": E(t.FILES$REFRESH),
|
|
114
|
+
title: E(t.FILES$REFRESH),
|
|
115
|
+
"data-testid": "files-tab-refresh",
|
|
116
|
+
className: "flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:enabled:bg-[var(--oh-interactive-hover)] cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",
|
|
117
|
+
children: /* @__PURE__ */ w(g, {
|
|
118
|
+
width: 12.75,
|
|
119
|
+
height: 15,
|
|
120
|
+
color: "#ffffff",
|
|
121
|
+
className: $ ? "animate-spin" : ""
|
|
122
|
+
})
|
|
123
|
+
})]
|
|
124
|
+
})
|
|
125
|
+
]
|
|
126
|
+
}),
|
|
127
|
+
V === "on" && /* @__PURE__ */ w("div", {
|
|
128
|
+
className: "flex-1 min-h-0",
|
|
129
|
+
children: /* @__PURE__ */ w(v, {})
|
|
130
|
+
}),
|
|
131
|
+
V === "commits" && /* @__PURE__ */ w("div", {
|
|
132
|
+
className: "flex-1 min-h-0",
|
|
133
|
+
children: /* @__PURE__ */ w(y, {})
|
|
134
|
+
}),
|
|
135
|
+
V === "off" && /* @__PURE__ */ w("div", {
|
|
136
|
+
className: "flex flex-1 flex-col min-h-0",
|
|
137
|
+
children: W.isLoading ? /* @__PURE__ */ w("div", {
|
|
138
|
+
className: "flex flex-1 items-center justify-center text-sm text-[var(--oh-muted)]",
|
|
139
|
+
children: E(t.FILES$LOADING_FILES)
|
|
140
|
+
}) : /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(p, {
|
|
141
|
+
paths: G,
|
|
142
|
+
selectedPath: Y,
|
|
143
|
+
onSelectFile: X,
|
|
144
|
+
isTreeVisible: H,
|
|
145
|
+
onToggleTree: () => U((e) => !e)
|
|
146
|
+
}), /* @__PURE__ */ T("div", {
|
|
147
|
+
className: "flex h-full min-h-0 flex-1",
|
|
148
|
+
children: [H && /* @__PURE__ */ w("aside", {
|
|
149
|
+
className: "w-56 shrink-0 border-r border-[var(--oh-border)] overflow-y-auto custom-scrollbar-always",
|
|
150
|
+
"data-testid": "files-tab-tree",
|
|
151
|
+
children: /* @__PURE__ */ w(m, {
|
|
152
|
+
paths: G,
|
|
153
|
+
selectedPath: Y,
|
|
154
|
+
onSelectFile: X
|
|
108
155
|
})
|
|
156
|
+
}), /* @__PURE__ */ w("section", {
|
|
157
|
+
className: "flex h-full min-h-0 min-w-0 flex-1 flex-col",
|
|
158
|
+
"data-testid": "files-tab-content",
|
|
159
|
+
children: Y ? /* @__PURE__ */ w(h, {
|
|
160
|
+
path: Y,
|
|
161
|
+
viewMode: I
|
|
162
|
+
}) : /* @__PURE__ */ w(c, {})
|
|
109
163
|
})]
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
className: "flex-1 min-h-0",
|
|
114
|
-
children: /* @__PURE__ */ D(S, {})
|
|
115
|
-
}) : /* @__PURE__ */ D("div", {
|
|
116
|
-
className: "flex flex-1 flex-col min-h-0",
|
|
117
|
-
children: H.isLoading ? /* @__PURE__ */ D("div", {
|
|
118
|
-
className: "flex flex-1 items-center justify-center text-sm text-[var(--oh-muted)]",
|
|
119
|
-
children: k(t.FILES$LOADING_FILES)
|
|
120
|
-
}) : /* @__PURE__ */ O(E, { children: [/* @__PURE__ */ D(v, {
|
|
121
|
-
paths: U,
|
|
122
|
-
selectedPath: q,
|
|
123
|
-
onSelectFile: J,
|
|
124
|
-
isTreeVisible: B,
|
|
125
|
-
onToggleTree: () => V((e) => !e)
|
|
126
|
-
}), /* @__PURE__ */ O("div", {
|
|
127
|
-
className: "flex h-full min-h-0 flex-1",
|
|
128
|
-
children: [B && /* @__PURE__ */ D("aside", {
|
|
129
|
-
className: "w-56 shrink-0 border-r border-[var(--oh-border)] overflow-y-auto custom-scrollbar-always",
|
|
130
|
-
"data-testid": "files-tab-tree",
|
|
131
|
-
children: /* @__PURE__ */ D(y, {
|
|
132
|
-
paths: U,
|
|
133
|
-
selectedPath: q,
|
|
134
|
-
onSelectFile: J
|
|
135
|
-
})
|
|
136
|
-
}), /* @__PURE__ */ D("section", {
|
|
137
|
-
className: "flex h-full min-h-0 min-w-0 flex-1 flex-col",
|
|
138
|
-
"data-testid": "files-tab-content",
|
|
139
|
-
children: q ? /* @__PURE__ */ D(b, {
|
|
140
|
-
path: q,
|
|
141
|
-
viewMode: z
|
|
142
|
-
}) : /* @__PURE__ */ D(c, {})
|
|
143
|
-
})]
|
|
144
|
-
})] })
|
|
145
|
-
})]
|
|
164
|
+
})] })
|
|
165
|
+
})
|
|
166
|
+
]
|
|
146
167
|
});
|
|
147
168
|
}
|
|
148
169
|
//#endregion
|
|
149
|
-
export {
|
|
170
|
+
export { E as default };
|
|
150
171
|
|
|
151
172
|
//# sourceMappingURL=files-tab.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files-tab.js","names":[],"sources":["../../src/routes/files-tab.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\nimport { NoFileSelectedMessage } from \"#/components/features/files-tab/no-file-selected-message\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useFilesTabStore } from \"#/stores/files-tab-store\";\nimport { useWorkspaceFiles } from \"#/hooks/query/use-workspace-files\";\nimport { useWorkspaceFileContent } from \"#/hooks/query/use-workspace-file-content\";\nimport { useHasAttachedSource } from \"#/hooks/use-has-attached-source\";\nimport { useHasGitCommits } from \"#/hooks/query/use-has-git-commits\";\nimport { useAutoRefreshFilesOnEdit } from \"#/hooks/use-auto-refresh-files-on-edit\";\nimport { useUnifiedGetGitChanges } from \"#/hooks/query/use-unified-get-git-changes\";\nimport { useOptionalConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport {\n useWorkspaceMutationCounter,\n withWorkspaceCacheBuster,\n} from \"#/stores/use-workspace-mutation-counter\";\nimport { sortFilesByPriority } from \"#/utils/file-priority\";\nimport { FileQuickRow } from \"#/components/features/files-tab/file-quick-row\";\nimport { FileTreeView } from \"#/components/features/files-tab/file-tree-view\";\nimport { FileContentViewer } from \"#/components/features/files-tab/file-content-viewer\";\nimport { SegmentedToggle } from \"#/components/features/files-tab/segmented-toggle\";\nimport type { ViewMode } from \"#/components/features/files-tab/view-mode\";\nimport RefreshIcon from \"#/icons/u-refresh.svg?react\";\nimport LinkExternalIcon from \"#/icons/link-external.svg?react\";\nimport GitChanges from \"./changes-tab\";\n\nfunction FilesTab() {\n const { t } = useTranslation(\"openhands\");\n\n // Keep the list / content / diff caches fresh as the agent writes files.\n useAutoRefreshFilesOnEdit();\n\n const { hasAttachedSource, isLoading: isAttachedSourceLoading } =\n useHasAttachedSource();\n // A workspace with zero commits has no diff base to compare against, so\n // the diff view would just be empty / misleading. Only probe when we\n // already believe the user attached a source — saves a workspace round\n // trip on every plain (no-attachment) conversation.\n const { hasCommits } = useHasGitCommits({ enabled: hasAttachedSource });\n\n // Diff view defaults to ON when the user attached a source (repo or\n // local workspace) *and* there's at least one commit, OFF otherwise\n // (no attachment, or attachment with no commits yet).\n //\n // While the attachment / commit probes are still resolving we stay\n // optimistic — most attached conversations live in a real repo, so\n // defaulting to diff during the brief loading window avoids a\n // \"files → diff\" flash on initial load. We only flip to files-view\n // once `hasAttachedSource` *or* `hasCommits` definitively resolves\n // false. The user's persisted choice always wins.\n const { conversationId } = useOptionalConversationId();\n const {\n state: persistedState,\n setFilesTabDiffView,\n setFilesTabContentViewMode,\n } = useConversationLocalStorageState(conversationId ?? \"\");\n\n const diffViewDefault =\n (hasAttachedSource || isAttachedSourceLoading) && hasCommits !== false;\n const diffViewEnabled = persistedState.filesTabDiffView ?? diffViewDefault;\n const contentViewMode = persistedState.filesTabContentViewMode;\n\n // Collapsed by default — the quick-access pill row at the top is usually\n // enough; the user can expand the tree on demand.\n const [isTreeVisible, setIsTreeVisible] = useState(false);\n\n const filesQuery = useWorkspaceFiles();\n const paths = useMemo(() => filesQuery.data ?? [], [filesQuery.data]);\n\n const storedSelectedPath = useFilesTabStore((s) => s.selectedPath);\n const selectedConversationId = useFilesTabStore(\n (s) => s.selectedConversationId,\n );\n const setSelectedPath = useFilesTabStore((s) => s.setSelectedPath);\n\n // A selection is scoped to the conversation it was made in. Ignore a path\n // that belongs to a different conversation so we never try to open a file\n // that only exists in the previous conversation's workspace (issue #1350).\n // The auto-select effect below then picks this conversation's top file.\n const selectedPath =\n selectedConversationId === conversationId ? storedSelectedPath : null;\n\n // Tag every selection with the active conversation so it can't leak into\n // the next one. FileQuickRow / FileTreeView call this with just the path.\n const handleSelectFile = useCallback(\n (path: string) => setSelectedPath(path, conversationId),\n [conversationId, setSelectedPath],\n );\n\n // Pre-fetch the selected file's content here too so the toolbar's\n // \"open in new window\" link can reach for its `staticUrl`. react-query\n // dedupes against `FileContentViewer`'s identical call, so this costs\n // nothing extra.\n const selectedFileContent = useWorkspaceFileContent(selectedPath);\n const mutationCounter = useWorkspaceMutationCounter((state) => state.count);\n const selectedFileStaticUrl = withWorkspaceCacheBuster(\n selectedFileContent.data?.staticUrl ?? null,\n mutationCounter,\n );\n\n useEffect(() => {\n if (selectedConversationId === conversationId) return;\n setSelectedPath(null, conversationId);\n }, [selectedConversationId, conversationId, setSelectedPath]);\n\n // Auto-select the highest-priority file the first time we load the list,\n // so users see something useful immediately.\n useEffect(() => {\n if (selectedPath || paths.length === 0) return;\n const [first] = sortFilesByPriority(paths);\n if (first) setSelectedPath(first, conversationId);\n }, [paths, selectedPath, conversationId, setSelectedPath]);\n\n // Refresh button: covers the diff view (git changes) and the file viewer\n // (workspace listing + cached file contents). Lives in this toolbar — not\n // in the outer ConversationTabs bar — so it sits with the other\n // files-tab-local controls.\n const queryClient = useQueryClient();\n const { refetch: refetchGitChanges, isFetching: isFetchingGitChanges } =\n useUnifiedGetGitChanges();\n const refreshFiles = () => {\n refetchGitChanges();\n queryClient.invalidateQueries({ queryKey: [\"workspace-files\"] });\n queryClient.invalidateQueries({ queryKey: [\"workspace-file-content\"] });\n };\n\n return (\n <main\n className=\"h-full w-full flex flex-col items-stretch\"\n data-testid=\"files-tab\"\n >\n {/* Top toolbar: diff/files + rich/plain toggles (left-aligned) plus\n the refresh button on the right. */}\n <div className=\"flex items-center gap-3 px-3 py-1.5 border-b border-[var(--oh-border)]\">\n <SegmentedToggle<\"on\" | \"off\">\n ariaLabel={t(I18nKey.FILES$DIFF_VIEW)}\n testId=\"files-tab-diff-toggle\"\n value={diffViewEnabled ? \"on\" : \"off\"}\n options={[\n { value: \"on\", label: t(I18nKey.FILES$DIFF_VIEW) },\n { value: \"off\", label: t(I18nKey.COMMON$FILES) },\n ]}\n onChange={(value) => setFilesTabDiffView(value === \"on\")}\n />\n\n {!diffViewEnabled && (\n <SegmentedToggle<ViewMode>\n ariaLabel={t(I18nKey.FILES$RICH)}\n testId=\"files-tab-content-mode-toggle\"\n value={contentViewMode}\n options={[\n { value: \"rich\", label: t(I18nKey.FILES$RICH) },\n { value: \"plain\", label: t(I18nKey.FILES$PLAIN) },\n ]}\n onChange={setFilesTabContentViewMode}\n />\n )}\n\n <div className=\"ml-auto flex items-center gap-1\">\n {/* Open the currently-selected file in a new browser tab. Only\n meaningful while we're showing a file (not the diff view) and\n we've resolved its staticUrl from the workspace fileserver. */}\n {!diffViewEnabled && selectedFileStaticUrl && (\n <a\n href={selectedFileStaticUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n title={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n data-testid=\"files-tab-open-in-new-window\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:bg-[var(--oh-interactive-hover)] cursor-pointer text-white\"\n >\n <LinkExternalIcon width={14} height={14} />\n </a>\n )}\n <button\n type=\"button\"\n onClick={refreshFiles}\n disabled={isFetchingGitChanges}\n aria-label={t(I18nKey.FILES$REFRESH)}\n title={t(I18nKey.FILES$REFRESH)}\n data-testid=\"files-tab-refresh\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:enabled:bg-[var(--oh-interactive-hover)] cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <RefreshIcon\n width={12.75}\n height={15}\n color=\"#ffffff\"\n className={isFetchingGitChanges ? \"animate-spin\" : \"\"}\n />\n </button>\n </div>\n </div>\n\n {diffViewEnabled ? (\n <div className=\"flex-1 min-h-0\">\n <GitChanges />\n </div>\n ) : (\n <div className=\"flex flex-1 flex-col min-h-0\">\n {filesQuery.isLoading ? (\n <div className=\"flex flex-1 items-center justify-center text-sm text-[var(--oh-muted)]\">\n {t(I18nKey.FILES$LOADING_FILES)}\n </div>\n ) : (\n <>\n <FileQuickRow\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n isTreeVisible={isTreeVisible}\n onToggleTree={() => setIsTreeVisible((prev) => !prev)}\n />\n <div className=\"flex h-full min-h-0 flex-1\">\n {isTreeVisible && (\n <aside\n className=\"w-56 shrink-0 border-r border-[var(--oh-border)] overflow-y-auto custom-scrollbar-always\"\n data-testid=\"files-tab-tree\"\n >\n <FileTreeView\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n />\n </aside>\n )}\n <section\n className=\"flex h-full min-h-0 min-w-0 flex-1 flex-col\"\n data-testid=\"files-tab-content\"\n >\n {selectedPath ? (\n <FileContentViewer\n path={selectedPath}\n viewMode={contentViewMode}\n />\n ) : (\n <NoFileSelectedMessage />\n )}\n </section>\n </div>\n </>\n )}\n </div>\n )}\n </main>\n );\n}\n\nexport default FilesTab;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"files-tab.js","names":[],"sources":["../../src/routes/files-tab.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\nimport { NoFileSelectedMessage } from \"#/components/features/files-tab/no-file-selected-message\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useFilesTabStore } from \"#/stores/files-tab-store\";\nimport { useWorkspaceFiles } from \"#/hooks/query/use-workspace-files\";\nimport { useWorkspaceFileContent } from \"#/hooks/query/use-workspace-file-content\";\nimport { useHasAttachedSource } from \"#/hooks/use-has-attached-source\";\nimport { useHasGitCommits } from \"#/hooks/query/use-has-git-commits\";\nimport { useAutoRefreshFilesOnEdit } from \"#/hooks/use-auto-refresh-files-on-edit\";\nimport { useUnifiedGetGitChanges } from \"#/hooks/query/use-unified-get-git-changes\";\nimport { useOptionalConversationId } from \"#/hooks/use-conversation-id\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport {\n useWorkspaceMutationCounter,\n withWorkspaceCacheBuster,\n} from \"#/stores/use-workspace-mutation-counter\";\nimport { sortFilesByPriority } from \"#/utils/file-priority\";\nimport { FileQuickRow } from \"#/components/features/files-tab/file-quick-row\";\nimport { FileTreeView } from \"#/components/features/files-tab/file-tree-view\";\nimport { FileContentViewer } from \"#/components/features/files-tab/file-content-viewer\";\nimport { SegmentedToggle } from \"#/components/features/files-tab/segmented-toggle\";\nimport type { ViewMode } from \"#/components/features/files-tab/view-mode\";\nimport RefreshIcon from \"#/icons/u-refresh.svg?react\";\nimport LinkExternalIcon from \"#/icons/link-external.svg?react\";\nimport { useUnifiedGitCommits } from \"#/hooks/query/use-unified-git-commits\";\nimport GitChanges from \"./changes-tab\";\nimport GitCommits from \"./commits-tab\";\n\nfunction FilesTab() {\n const { t } = useTranslation(\"openhands\");\n\n // Keep the list / content / diff caches fresh as the agent writes files.\n useAutoRefreshFilesOnEdit();\n\n const { hasAttachedSource, isLoading: isAttachedSourceLoading } =\n useHasAttachedSource();\n // A workspace with zero commits has no diff base to compare against, so\n // the diff view would just be empty / misleading. Only probe when we\n // already believe the user attached a source — saves a workspace round\n // trip on every plain (no-attachment) conversation.\n const { hasCommits } = useHasGitCommits({ enabled: hasAttachedSource });\n\n // Diff view defaults to ON when the user attached a source (repo or\n // local workspace) *and* there's at least one commit, OFF otherwise\n // (no attachment, or attachment with no commits yet).\n //\n // While the attachment / commit probes are still resolving we stay\n // optimistic — most attached conversations live in a real repo, so\n // defaulting to diff during the brief loading window avoids a\n // \"files → diff\" flash on initial load. We only flip to files-view\n // once `hasAttachedSource` *or* `hasCommits` definitively resolves\n // false. The user's persisted choice always wins.\n const { conversationId } = useOptionalConversationId();\n const {\n state: persistedState,\n setFilesTabDiffView,\n setFilesTabContentViewMode,\n } = useConversationLocalStorageState(conversationId ?? \"\");\n\n const diffViewDefault =\n (hasAttachedSource || isAttachedSourceLoading) && hasCommits !== false;\n const diffViewEnabled = persistedState.filesTabDiffView ?? diffViewDefault;\n const contentViewMode = persistedState.filesTabContentViewMode;\n\n // Commit history gets a third toggle segment, offered only when the\n // agent server supports the commits API (older servers 404 → the toggle\n // stays two-way and the tab looks exactly as it did before). The\n // selection is session-local; the persisted diff/files preference is\n // untouched so falling out of the commits view restores it.\n const { isSuccess: commitsIsSuccess, isUnsupported: commitsUnsupported } =\n useUnifiedGitCommits();\n const showCommitsOption = commitsIsSuccess && !commitsUnsupported;\n const [commitsViewSelected, setCommitsViewSelected] = useState(false);\n let activeView: \"on\" | \"off\" | \"commits\" = diffViewEnabled ? \"on\" : \"off\";\n if (commitsViewSelected && showCommitsOption) activeView = \"commits\";\n\n // Collapsed by default — the quick-access pill row at the top is usually\n // enough; the user can expand the tree on demand.\n const [isTreeVisible, setIsTreeVisible] = useState(false);\n\n const filesQuery = useWorkspaceFiles();\n const paths = useMemo(() => filesQuery.data ?? [], [filesQuery.data]);\n\n const storedSelectedPath = useFilesTabStore((s) => s.selectedPath);\n const selectedConversationId = useFilesTabStore(\n (s) => s.selectedConversationId,\n );\n const setSelectedPath = useFilesTabStore((s) => s.setSelectedPath);\n\n // A selection is scoped to the conversation it was made in. Ignore a path\n // that belongs to a different conversation so we never try to open a file\n // that only exists in the previous conversation's workspace (issue #1350).\n // The auto-select effect below then picks this conversation's top file.\n const selectedPath =\n selectedConversationId === conversationId ? storedSelectedPath : null;\n\n // Tag every selection with the active conversation so it can't leak into\n // the next one. FileQuickRow / FileTreeView call this with just the path.\n const handleSelectFile = useCallback(\n (path: string) => setSelectedPath(path, conversationId),\n [conversationId, setSelectedPath],\n );\n\n // Pre-fetch the selected file's content here too so the toolbar's\n // \"open in new window\" link can reach for its `staticUrl`. react-query\n // dedupes against `FileContentViewer`'s identical call, so this costs\n // nothing extra.\n const selectedFileContent = useWorkspaceFileContent(selectedPath);\n const mutationCounter = useWorkspaceMutationCounter((state) => state.count);\n const selectedFileStaticUrl = withWorkspaceCacheBuster(\n selectedFileContent.data?.staticUrl ?? null,\n mutationCounter,\n );\n\n useEffect(() => {\n if (selectedConversationId === conversationId) return;\n setSelectedPath(null, conversationId);\n }, [selectedConversationId, conversationId, setSelectedPath]);\n\n // Auto-select the highest-priority file the first time we load the list,\n // so users see something useful immediately.\n useEffect(() => {\n if (selectedPath || paths.length === 0) return;\n const [first] = sortFilesByPriority(paths);\n if (first) setSelectedPath(first, conversationId);\n }, [paths, selectedPath, conversationId, setSelectedPath]);\n\n // Refresh button: covers the diff view (git changes) and the file viewer\n // (workspace listing + cached file contents). Lives in this toolbar — not\n // in the outer ConversationTabs bar — so it sits with the other\n // files-tab-local controls.\n const queryClient = useQueryClient();\n const { refetch: refetchGitChanges, isFetching: isFetchingGitChanges } =\n useUnifiedGetGitChanges();\n const refreshFiles = () => {\n refetchGitChanges();\n queryClient.invalidateQueries({ queryKey: [\"workspace-files\"] });\n queryClient.invalidateQueries({ queryKey: [\"workspace-file-content\"] });\n queryClient.invalidateQueries({ queryKey: [\"git_commits\"] });\n };\n\n return (\n <main\n className=\"h-full w-full flex flex-col items-stretch\"\n data-testid=\"files-tab\"\n >\n {/* Top toolbar: diff/files + rich/plain toggles (left-aligned) plus\n the refresh button on the right. */}\n <div className=\"flex items-center gap-3 px-3 py-1.5 border-b border-[var(--oh-border)]\">\n <SegmentedToggle<\"on\" | \"off\" | \"commits\">\n ariaLabel={t(I18nKey.FILES$DIFF_VIEW)}\n testId=\"files-tab-diff-toggle\"\n value={activeView}\n options={[\n { value: \"on\", label: t(I18nKey.FILES$DIFF_VIEW) },\n ...(showCommitsOption\n ? [\n {\n value: \"commits\" as const,\n label: t(I18nKey.DIFF_VIEWER$COMMITS),\n },\n ]\n : []),\n { value: \"off\", label: t(I18nKey.COMMON$FILES) },\n ]}\n onChange={(value) => {\n if (value === \"commits\") {\n setCommitsViewSelected(true);\n } else {\n setCommitsViewSelected(false);\n setFilesTabDiffView(value === \"on\");\n }\n }}\n />\n\n {activeView === \"off\" && (\n <SegmentedToggle<ViewMode>\n ariaLabel={t(I18nKey.FILES$RICH)}\n testId=\"files-tab-content-mode-toggle\"\n value={contentViewMode}\n options={[\n { value: \"rich\", label: t(I18nKey.FILES$RICH) },\n { value: \"plain\", label: t(I18nKey.FILES$PLAIN) },\n ]}\n onChange={setFilesTabContentViewMode}\n />\n )}\n\n <div className=\"ml-auto flex items-center gap-1\">\n {/* Open the currently-selected file in a new browser tab. Only\n meaningful while we're showing a file (not the diff view) and\n we've resolved its staticUrl from the workspace fileserver. */}\n {activeView === \"off\" && selectedFileStaticUrl && (\n <a\n href={selectedFileStaticUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n title={t(I18nKey.FILES$OPEN_IN_NEW_WINDOW)}\n data-testid=\"files-tab-open-in-new-window\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:bg-[var(--oh-interactive-hover)] cursor-pointer text-white\"\n >\n <LinkExternalIcon width={14} height={14} />\n </a>\n )}\n <button\n type=\"button\"\n onClick={refreshFiles}\n disabled={isFetchingGitChanges}\n aria-label={t(I18nKey.FILES$REFRESH)}\n title={t(I18nKey.FILES$REFRESH)}\n data-testid=\"files-tab-refresh\"\n className=\"flex items-center justify-center w-[26px] py-1 rounded-[7px] hover:enabled:bg-[var(--oh-interactive-hover)] cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <RefreshIcon\n width={12.75}\n height={15}\n color=\"#ffffff\"\n className={isFetchingGitChanges ? \"animate-spin\" : \"\"}\n />\n </button>\n </div>\n </div>\n\n {activeView === \"on\" && (\n <div className=\"flex-1 min-h-0\">\n <GitChanges />\n </div>\n )}\n {activeView === \"commits\" && (\n <div className=\"flex-1 min-h-0\">\n <GitCommits />\n </div>\n )}\n {activeView === \"off\" && (\n <div className=\"flex flex-1 flex-col min-h-0\">\n {filesQuery.isLoading ? (\n <div className=\"flex flex-1 items-center justify-center text-sm text-[var(--oh-muted)]\">\n {t(I18nKey.FILES$LOADING_FILES)}\n </div>\n ) : (\n <>\n <FileQuickRow\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n isTreeVisible={isTreeVisible}\n onToggleTree={() => setIsTreeVisible((prev) => !prev)}\n />\n <div className=\"flex h-full min-h-0 flex-1\">\n {isTreeVisible && (\n <aside\n className=\"w-56 shrink-0 border-r border-[var(--oh-border)] overflow-y-auto custom-scrollbar-always\"\n data-testid=\"files-tab-tree\"\n >\n <FileTreeView\n paths={paths}\n selectedPath={selectedPath}\n onSelectFile={handleSelectFile}\n />\n </aside>\n )}\n <section\n className=\"flex h-full min-h-0 min-w-0 flex-1 flex-col\"\n data-testid=\"files-tab-content\"\n >\n {selectedPath ? (\n <FileContentViewer\n path={selectedPath}\n viewMode={contentViewMode}\n />\n ) : (\n <NoFileSelectedMessage />\n )}\n </section>\n </div>\n </>\n )}\n </div>\n )}\n </main>\n );\n}\n\nexport default FilesTab;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../node_modules/@openhands/typescript-client/dist/client/device-flow-client.cjs`),t=require(`../api/client-source.cjs`);require(`../api/device-flow-client.cjs`);const n=require(`./telemetry.cjs`);var r={client_source:t.AGENT_CANVAS_CLIENT_SOURCE,client_version:t.AGENT_CANVAS_CLIENT_VERSION};function i(e,t){return n.isTelemetryEnabled()?(n.trackEvent(e,{...t,...r}),!0):!1}function a(t){let n=e.isOpenHandsCloudHost(t);return{is_openhands_cloud:n,is_custom_host:!n}}function o(e,t){return i(`cloud_device_authorization_started`,{...a(e),source:t})}function s(e,t){return i(`cloud_device_authorization_succeeded`,{...a(e),source:t})}function c({backendKind:e,connectionMethod:t,host:n,hasApiKey:r,source:o}){return i(`backend_added`,{backend_kind:e,connection_method:t,...a(n),has_api_key:r,source:o})}function l(e,t){return i(`cloud_conversation_ready`,{task_id:e,conversation_id:t})}exports.trackCanvasBackendAdded=c,exports.trackCloudConversationReady=l,exports.trackCloudDeviceAuthorizationStarted=o,exports.trackCloudDeviceAuthorizationSucceeded=s;
|
|
2
|
+
//# sourceMappingURL=cloud-funnel-analytics.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-funnel-analytics.cjs","names":[],"sources":["../../src/services/cloud-funnel-analytics.ts"],"sourcesContent":["import type { BackendKind } from \"#/api/backend-registry/types\";\nimport {\n AGENT_CANVAS_CLIENT_SOURCE,\n AGENT_CANVAS_CLIENT_VERSION,\n} from \"#/api/client-source\";\nimport { isOpenHandsCloudHost } from \"#/api/device-flow-client\";\nimport { isTelemetryEnabled, trackEvent } from \"#/services/telemetry\";\n\nexport type CloudConnectionSource =\n | \"onboarding\"\n | \"add_backend_modal\"\n | \"manage_backends_modal\";\n\nconst commonProperties = {\n client_source: AGENT_CANVAS_CLIENT_SOURCE,\n client_version: AGENT_CANVAS_CLIENT_VERSION,\n};\n\nfunction trackCloudFunnelEvent(\n event: string,\n properties: Record<string, unknown>,\n): boolean {\n if (!isTelemetryEnabled()) return false;\n void trackEvent(event, { ...properties, ...commonProperties });\n return true;\n}\n\nfunction hostClassification(host: string) {\n const isOpenhandsCloud = isOpenHandsCloudHost(host);\n return {\n is_openhands_cloud: isOpenhandsCloud,\n is_custom_host: !isOpenhandsCloud,\n };\n}\n\nexport function trackCloudDeviceAuthorizationStarted(\n host: string,\n source?: CloudConnectionSource,\n): boolean {\n return trackCloudFunnelEvent(\"cloud_device_authorization_started\", {\n ...hostClassification(host),\n source,\n });\n}\n\nexport function trackCloudDeviceAuthorizationSucceeded(\n host: string,\n source?: CloudConnectionSource,\n): boolean {\n return trackCloudFunnelEvent(\"cloud_device_authorization_succeeded\", {\n ...hostClassification(host),\n source,\n });\n}\n\nexport function trackCanvasBackendAdded({\n backendKind,\n connectionMethod,\n host,\n hasApiKey,\n source,\n}: {\n backendKind: BackendKind;\n connectionMethod: \"manual\" | \"cloud_login\";\n host: string;\n hasApiKey: boolean;\n source?: CloudConnectionSource;\n}): boolean {\n return trackCloudFunnelEvent(\"backend_added\", {\n backend_kind: backendKind,\n connection_method: connectionMethod,\n ...hostClassification(host),\n has_api_key: hasApiKey,\n source,\n });\n}\n\nexport function trackCloudConversationReady(\n taskId: string,\n conversationId: string,\n): boolean {\n return trackCloudFunnelEvent(\"cloud_conversation_ready\", {\n task_id: taskId,\n conversation_id: conversationId,\n });\n}\n"],"mappings":"kQAaA,IAAM,EAAmB,CACvB,cAAe,EAAA,2BACf,eAAgB,EAAA,4BACjB,CAED,SAAS,EACP,EACA,EACS,CAGT,OAFK,EAAA,oBAAoB,EACpB,EAAA,WAAW,EAAO,CAAE,GAAG,EAAY,GAAG,EAAkB,CAAC,CACvD,IAF2B,GAKpC,SAAS,EAAmB,EAAc,CACxC,IAAM,EAAmB,EAAA,qBAAqB,EAAK,CACnD,MAAO,CACL,mBAAoB,EACpB,eAAgB,CAAC,EAClB,CAGH,SAAgB,EACd,EACA,EACS,CACT,OAAO,EAAsB,qCAAsC,CACjE,GAAG,EAAmB,EAAK,CAC3B,SACD,CAAC,CAGJ,SAAgB,EACd,EACA,EACS,CACT,OAAO,EAAsB,uCAAwC,CACnE,GAAG,EAAmB,EAAK,CAC3B,SACD,CAAC,CAGJ,SAAgB,EAAwB,CACtC,cACA,mBACA,OACA,YACA,UAOU,CACV,OAAO,EAAsB,gBAAiB,CAC5C,aAAc,EACd,kBAAmB,EACnB,GAAG,EAAmB,EAAK,CAC3B,YAAa,EACb,SACD,CAAC,CAGJ,SAAgB,EACd,EACA,EACS,CACT,OAAO,EAAsB,2BAA4B,CACvD,QAAS,EACT,gBAAiB,EAClB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BackendKind } from "#/api/backend-registry/types";
|
|
2
|
+
export type CloudConnectionSource = "onboarding" | "add_backend_modal" | "manage_backends_modal";
|
|
3
|
+
export declare function trackCloudDeviceAuthorizationStarted(host: string, source?: CloudConnectionSource): boolean;
|
|
4
|
+
export declare function trackCloudDeviceAuthorizationSucceeded(host: string, source?: CloudConnectionSource): boolean;
|
|
5
|
+
export declare function trackCanvasBackendAdded({ backendKind, connectionMethod, host, hasApiKey, source, }: {
|
|
6
|
+
backendKind: BackendKind;
|
|
7
|
+
connectionMethod: "manual" | "cloud_login";
|
|
8
|
+
host: string;
|
|
9
|
+
hasApiKey: boolean;
|
|
10
|
+
source?: CloudConnectionSource;
|
|
11
|
+
}): boolean;
|
|
12
|
+
export declare function trackCloudConversationReady(taskId: string, conversationId: string): boolean;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { isOpenHandsCloudHost as e } from "../node_modules/@openhands/typescript-client/dist/client/device-flow-client.js";
|
|
2
|
+
import { AGENT_CANVAS_CLIENT_SOURCE as t, AGENT_CANVAS_CLIENT_VERSION as n } from "../api/client-source.js";
|
|
3
|
+
import "../api/device-flow-client.js";
|
|
4
|
+
import { isTelemetryEnabled as r, trackEvent as i } from "./telemetry.js";
|
|
5
|
+
//#region src/services/cloud-funnel-analytics.ts
|
|
6
|
+
var a = {
|
|
7
|
+
client_source: t,
|
|
8
|
+
client_version: n
|
|
9
|
+
};
|
|
10
|
+
function o(e, t) {
|
|
11
|
+
return r() ? (i(e, {
|
|
12
|
+
...t,
|
|
13
|
+
...a
|
|
14
|
+
}), !0) : !1;
|
|
15
|
+
}
|
|
16
|
+
function s(t) {
|
|
17
|
+
let n = e(t);
|
|
18
|
+
return {
|
|
19
|
+
is_openhands_cloud: n,
|
|
20
|
+
is_custom_host: !n
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function c(e, t) {
|
|
24
|
+
return o("cloud_device_authorization_started", {
|
|
25
|
+
...s(e),
|
|
26
|
+
source: t
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function l(e, t) {
|
|
30
|
+
return o("cloud_device_authorization_succeeded", {
|
|
31
|
+
...s(e),
|
|
32
|
+
source: t
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function u({ backendKind: e, connectionMethod: t, host: n, hasApiKey: r, source: i }) {
|
|
36
|
+
return o("backend_added", {
|
|
37
|
+
backend_kind: e,
|
|
38
|
+
connection_method: t,
|
|
39
|
+
...s(n),
|
|
40
|
+
has_api_key: r,
|
|
41
|
+
source: i
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function d(e, t) {
|
|
45
|
+
return o("cloud_conversation_ready", {
|
|
46
|
+
task_id: e,
|
|
47
|
+
conversation_id: t
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { u as trackCanvasBackendAdded, d as trackCloudConversationReady, c as trackCloudDeviceAuthorizationStarted, l as trackCloudDeviceAuthorizationSucceeded };
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=cloud-funnel-analytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-funnel-analytics.js","names":[],"sources":["../../src/services/cloud-funnel-analytics.ts"],"sourcesContent":["import type { BackendKind } from \"#/api/backend-registry/types\";\nimport {\n AGENT_CANVAS_CLIENT_SOURCE,\n AGENT_CANVAS_CLIENT_VERSION,\n} from \"#/api/client-source\";\nimport { isOpenHandsCloudHost } from \"#/api/device-flow-client\";\nimport { isTelemetryEnabled, trackEvent } from \"#/services/telemetry\";\n\nexport type CloudConnectionSource =\n | \"onboarding\"\n | \"add_backend_modal\"\n | \"manage_backends_modal\";\n\nconst commonProperties = {\n client_source: AGENT_CANVAS_CLIENT_SOURCE,\n client_version: AGENT_CANVAS_CLIENT_VERSION,\n};\n\nfunction trackCloudFunnelEvent(\n event: string,\n properties: Record<string, unknown>,\n): boolean {\n if (!isTelemetryEnabled()) return false;\n void trackEvent(event, { ...properties, ...commonProperties });\n return true;\n}\n\nfunction hostClassification(host: string) {\n const isOpenhandsCloud = isOpenHandsCloudHost(host);\n return {\n is_openhands_cloud: isOpenhandsCloud,\n is_custom_host: !isOpenhandsCloud,\n };\n}\n\nexport function trackCloudDeviceAuthorizationStarted(\n host: string,\n source?: CloudConnectionSource,\n): boolean {\n return trackCloudFunnelEvent(\"cloud_device_authorization_started\", {\n ...hostClassification(host),\n source,\n });\n}\n\nexport function trackCloudDeviceAuthorizationSucceeded(\n host: string,\n source?: CloudConnectionSource,\n): boolean {\n return trackCloudFunnelEvent(\"cloud_device_authorization_succeeded\", {\n ...hostClassification(host),\n source,\n });\n}\n\nexport function trackCanvasBackendAdded({\n backendKind,\n connectionMethod,\n host,\n hasApiKey,\n source,\n}: {\n backendKind: BackendKind;\n connectionMethod: \"manual\" | \"cloud_login\";\n host: string;\n hasApiKey: boolean;\n source?: CloudConnectionSource;\n}): boolean {\n return trackCloudFunnelEvent(\"backend_added\", {\n backend_kind: backendKind,\n connection_method: connectionMethod,\n ...hostClassification(host),\n has_api_key: hasApiKey,\n source,\n });\n}\n\nexport function trackCloudConversationReady(\n taskId: string,\n conversationId: string,\n): boolean {\n return trackCloudFunnelEvent(\"cloud_conversation_ready\", {\n task_id: taskId,\n conversation_id: conversationId,\n });\n}\n"],"mappings":";;;;;AAaA,IAAM,IAAmB;CACvB,eAAe;CACf,gBAAgB;CACjB;AAED,SAAS,EACP,GACA,GACS;AAGT,QAFK,GAAoB,IACpB,EAAW,GAAO;EAAE,GAAG;EAAY,GAAG;EAAkB,CAAC,EACvD,MAF2B;;AAKpC,SAAS,EAAmB,GAAc;CACxC,IAAM,IAAmB,EAAqB,EAAK;AACnD,QAAO;EACL,oBAAoB;EACpB,gBAAgB,CAAC;EAClB;;AAGH,SAAgB,EACd,GACA,GACS;AACT,QAAO,EAAsB,sCAAsC;EACjE,GAAG,EAAmB,EAAK;EAC3B;EACD,CAAC;;AAGJ,SAAgB,EACd,GACA,GACS;AACT,QAAO,EAAsB,wCAAwC;EACnE,GAAG,EAAmB,EAAK;EAC3B;EACD,CAAC;;AAGJ,SAAgB,EAAwB,EACtC,gBACA,qBACA,SACA,cACA,aAOU;AACV,QAAO,EAAsB,iBAAiB;EAC5C,cAAc;EACd,mBAAmB;EACnB,GAAG,EAAmB,EAAK;EAC3B,aAAa;EACb;EACD,CAAC;;AAGJ,SAAgB,EACd,GACA,GACS;AACT,QAAO,EAAsB,4BAA4B;EACvD,SAAS;EACT,iBAAiB;EAClB,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../package.cjs`);var t=`openhands-telemetry-consent`,n=`openhands-telemetry-first-use`,r=`openhands-telemetry-session`,i=`
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../package.cjs`);var t=`openhands-telemetry-consent`,n=`openhands-telemetry-first-use`,r=`openhands-telemetry-session`,i=`agent-canvas`,a=`phc_BgzfxKdgsYMLFTmJqt424ZoyVHvKFfrwttLimzdYTKFK`,o=`https://z.openhands.dev`,s=`https://us.posthog.com`,c=!1,l=null;function u(){return typeof window<`u`&&typeof localStorage<`u`}async function d(){if(!u())return null;if(l)return l;try{let{default:e}=await Promise.resolve().then(()=>require(`../node_modules/posthog-js/dist/module.cjs`));return e}catch{return null}}function f(){return typeof process<`u`&&process.env?.DO_NOT_TRACK===`1`||typeof navigator<`u`&&(navigator.doNotTrack===`1`||typeof window<`u`&&window.doNotTrack===`1`)}async function p(t=!1){if(c)return l;let n=await d();return n?(l=n.init(a,{api_host:o,ui_host:s,opt_out_capturing_by_default:!t,capture_pageview:!1,autocapture:!1,persistence:`localStorage`,persistence_name:i,consent_persistence_name:`${i}-consent`,disable_session_recording:!0,loaded:t=>{t.register({package_name:e.default.name,package_version:e.default.version})}},i),c=!0,l):null}function m(){if(!u())return`pending`;if(f())return`denied`;try{let e=localStorage.getItem(t);if(e===`granted`||e===`denied`)return e}catch{}return`pending`}async function h(e){if(u())try{localStorage.setItem(t,e);let n=await p();if(!n)return;e===`granted`?n.opt_in_capturing():n.opt_out_capturing()}catch{}}function g(){return m()===`granted`}function _(){if(!u())return!1;try{return localStorage.getItem(n)===`true`}catch{return!1}}function v(){if(u())try{localStorage.setItem(n,`true`)}catch{}}async function y(){if(f()||_())return;let e=await p(!0);e&&((e.has_opted_out_capturing?.()??!1)&&e.opt_in_capturing(),e.capture(`canvas_install`,{platform:typeof navigator<`u`?navigator.platform:`unknown`,user_agent:typeof navigator<`u`?navigator.userAgent:`unknown`,referrer:typeof document<`u`?document.referrer:``,url_origin:typeof window<`u`?window.location.origin:``,embedded:typeof window<`u`&&window.self!==window.top}),v(),m()!==`granted`&&e.opt_out_capturing())}function b(){if(!u())return!1;try{return sessionStorage.getItem(r)===`true`}catch{return!1}}function x(){if(u())try{sessionStorage.setItem(r,`true`)}catch{}}async function S(){if(!g()||b())return;let e=await p();e&&(e.capture(`canvas_new_session`,{is_first_use:!_()}),x())}async function C(e,t={}){if(!g())return;let n=await p();n&&n.capture(e,t)}async function w(){if(u())try{localStorage.removeItem(t),localStorage.removeItem(n),sessionStorage.removeItem(r),c&&l&&l.reset()}catch{}}async function T(){return c?l:null}exports.clearTelemetryData=w,exports.getPostHogInstance=T,exports.getTelemetryConsent=m,exports.isTelemetryEnabled=g,exports.setTelemetryConsent=h,exports.trackEvent=C,exports.trackInstall=y,exports.trackSessionStart=S;
|
|
2
2
|
//# sourceMappingURL=telemetry.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry.cjs","names":[],"sources":["../../src/services/telemetry.ts"],"sourcesContent":["/**\n * Telemetry service for tracking library usage.\n *\n * This module handles anonymous telemetry for the @openhands/agent-canvas package\n * using the PostHog SDK for reliable event delivery with batching, retry logic,\n * and offline support.\n *\n * TRACKING PHILOSOPHY:\n * - Install event (canvas_install): Sent immediately on first use, regardless of consent.\n * This is anonymous and contains no PII - just basic browser info and a random ID.\n * - Session/custom events: Only sent after user grants consent via the consent modal.\n * - Users can opt out of all future tracking by declining consent.\n *\n * AD BLOCKER BYPASS:\n * By default, telemetry is routed through OpenHands' reverse proxy (z.openhands.dev)\n * to avoid being blocked by ad blockers. Library consumers can override this with:\n * - VITE_POSTHOG_HOST: Custom proxy URL or direct PostHog URL\n * - VITE_POSTHOG_UI_HOST: PostHog UI host (defaults to https://us.posthog.com)\n *\n * IMPORTANT: By default, telemetry is sent to the OpenHands PostHog project.\n * Library consumers can override this by setting VITE_POSTHOG_API_KEY.\n *\n * Users can disable all telemetry (including install tracking) via:\n * - Setting VITE_DO_NOT_TRACK=1 environment variable\n * - Browser's Do Not Track setting\n */\n\nimport type { PostHog } from \"posthog-js\";\nimport packageJson from \"../../package.json\";\n\nconst TELEMETRY_CONSENT_KEY = \"openhands-telemetry-consent\";\nconst TELEMETRY_FIRST_USE_KEY = \"openhands-telemetry-first-use\";\nconst TELEMETRY_SESSION_KEY = \"openhands-telemetry-session\";\n\n// PostHog project keys — one per deployment environment, hardcoded so they\n// are baked into the static bundle at build time and cannot drift at runtime.\n// Replace POSTHOG_STAGING_KEY with a dedicated project key once provisioned.\nconst POSTHOG_PROD_KEY = \"phc_BgzfxKdgsYMLFTmJqt424ZoyVHvKFfrwttLimzdYTKFK\";\nconst POSTHOG_STAGING_KEY = \"phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U\";\n\n// Always use the staging key unless VITE_APP_ENV is explicitly set to\n// \"production\" at bundle time (hardcoded in build:lib and production CI).\n// Library consumers can always override with VITE_POSTHOG_API_KEY.\nconst POSTHOG_API_KEY: string =\n (import.meta.env.VITE_POSTHOG_API_KEY as string | undefined) ||\n (import.meta.env.VITE_APP_ENV === \"production\"\n ? POSTHOG_PROD_KEY\n : POSTHOG_STAGING_KEY);\n\n// Default to OpenHands' reverse proxy to bypass ad blockers.\n// The proxy at z.openhands.dev routes to PostHog's US region.\n// Library consumers can override this with their own proxy or direct PostHog URL.\nconst POSTHOG_HOST =\n import.meta.env.VITE_POSTHOG_HOST || \"https://z.openhands.dev\";\n\n// UI host is needed for PostHog features like toolbar to work correctly\n// when using a reverse proxy. Defaults to US region.\nconst POSTHOG_UI_HOST =\n import.meta.env.VITE_POSTHOG_UI_HOST || \"https://us.posthog.com\";\n\nexport type TelemetryConsent = \"granted\" | \"denied\" | \"pending\";\n\nlet isInitialized = false;\nlet posthogInstance: PostHog | null = null;\n\n/**\n * Check if we're in a browser environment\n */\nfunction isBrowser(): boolean {\n return typeof window !== \"undefined\" && typeof localStorage !== \"undefined\";\n}\n\n/**\n * Lazily load PostHog to avoid SSR/Node.js issues.\n * PostHog is a browser-only library, so we dynamically import it only when needed.\n */\nasync function getPostHog(): Promise<PostHog | null> {\n if (!isBrowser()) {\n return null;\n }\n\n if (posthogInstance) {\n return posthogInstance;\n }\n\n try {\n const { default: posthog } = await import(\"posthog-js\");\n posthogInstance = posthog;\n return posthog;\n } catch {\n // Failed to load PostHog - telemetry will be disabled\n return null;\n }\n}\n\n/**\n * Check if telemetry is disabled via environment variable or browser setting.\n * Works in both Node.js and browser (Vite) environments.\n */\nfunction isDoNotTrackEnabled(): boolean {\n // Check Vite environment variable (browser)\n if (\n typeof import.meta !== \"undefined\" &&\n import.meta.env?.VITE_DO_NOT_TRACK === \"1\"\n ) {\n return true;\n }\n\n // Check Node.js environment variable (SSR/testing)\n if (typeof process !== \"undefined\" && process.env?.DO_NOT_TRACK === \"1\") {\n return true;\n }\n\n // Check browser's navigator.doNotTrack standard\n if (\n typeof navigator !== \"undefined\" &&\n (navigator.doNotTrack === \"1\" ||\n // @ts-expect-error - Some browsers use window.doNotTrack\n (typeof window !== \"undefined\" && window.doNotTrack === \"1\"))\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Initialize PostHog SDK.\n *\n * @param enableCapturing - If true, enable capturing immediately (for install tracking).\n * If false, start with capturing disabled (for consent-gated tracking).\n */\nasync function initializePostHog(\n enableCapturing = false,\n): Promise<PostHog | null> {\n if (isInitialized) {\n return posthogInstance;\n }\n\n const posthog = await getPostHog();\n if (!posthog) {\n return null;\n }\n\n posthog.init(POSTHOG_API_KEY, {\n api_host: POSTHOG_HOST,\n // UI host is required when using a reverse proxy so PostHog features work correctly\n ui_host: POSTHOG_UI_HOST,\n // Start with capturing disabled by default - we enable it explicitly when needed\n opt_out_capturing_by_default: !enableCapturing,\n // Don't auto-capture page views - we control when to track\n capture_pageview: false,\n // Don't auto-capture clicks etc.\n autocapture: false,\n // Use localStorage for persistence\n persistence: \"localStorage\",\n // Disable session recording\n disable_session_recording: true,\n // Set default properties for all events\n loaded: (ph) => {\n ph.register({\n package_name: packageJson.name,\n package_version: packageJson.version,\n });\n },\n });\n\n isInitialized = true;\n return posthog;\n}\n\n/**\n * Get user's telemetry consent preference\n */\nexport function getTelemetryConsent(): TelemetryConsent {\n if (!isBrowser()) {\n return \"pending\";\n }\n\n // Check environment variable for opt-out\n if (isDoNotTrackEnabled()) {\n return \"denied\";\n }\n\n try {\n const consent = localStorage.getItem(TELEMETRY_CONSENT_KEY);\n if (consent === \"granted\" || consent === \"denied\") {\n return consent;\n }\n } catch {\n // Ignore storage errors\n }\n\n return \"pending\";\n}\n\n/**\n * Set user's telemetry consent preference\n */\nexport async function setTelemetryConsent(\n consent: \"granted\" | \"denied\",\n): Promise<void> {\n if (!isBrowser()) {\n return;\n }\n\n try {\n localStorage.setItem(TELEMETRY_CONSENT_KEY, consent);\n\n // Initialize PostHog if not already done\n const posthog = await initializePostHog();\n if (!posthog) {\n return;\n }\n\n if (consent === \"granted\") {\n // Enable capturing\n posthog.opt_in_capturing();\n } else {\n // Disable capturing and clear any queued events\n posthog.opt_out_capturing();\n }\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Check if telemetry is enabled (user has granted consent)\n */\nexport function isTelemetryEnabled(): boolean {\n return getTelemetryConsent() === \"granted\";\n}\n\n/**\n * Check if first use event has already been sent\n */\nfunction hasFirstUseSent(): boolean {\n if (!isBrowser()) {\n return false;\n }\n\n try {\n return localStorage.getItem(TELEMETRY_FIRST_USE_KEY) === \"true\";\n } catch {\n return false;\n }\n}\n\n/**\n * Mark first use event as sent\n */\nfunction markFirstUseSent(): void {\n if (!isBrowser()) {\n return;\n }\n\n try {\n localStorage.setItem(TELEMETRY_FIRST_USE_KEY, \"true\");\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Track the initial install of the library.\n *\n * IMPORTANT: This is sent immediately on first use, regardless of consent status.\n * This allows us to track library adoption even if users haven't made a consent choice yet.\n *\n * The event is:\n * - Completely anonymous (no PII, just a random PostHog distinct_id)\n * - Sent only once per installation (tracked via localStorage, persists across sessions)\n * - Still respects DO_NOT_TRACK environment variable and browser setting\n *\n * Users who want complete privacy can:\n * - Set VITE_DO_NOT_TRACK=1 or browser's Do Not Track\n * - Later deny consent to prevent all future tracking\n */\nexport async function trackInstall(): Promise<void> {\n // Respect hard opt-out via environment variable or browser setting\n if (isDoNotTrackEnabled()) {\n return;\n }\n\n // Already sent install event (persisted in localStorage - survives app relaunches)\n if (hasFirstUseSent()) {\n return;\n }\n\n // Initialize PostHog with capturing enabled (for this one event)\n const posthog = await initializePostHog(true);\n if (!posthog) {\n return;\n }\n\n // Temporarily enable capturing if it was disabled\n const wasOptedOut = posthog.has_opted_out_capturing?.() ?? false;\n if (wasOptedOut) {\n posthog.opt_in_capturing();\n }\n\n // Capture the install event\n posthog.capture(\"canvas_install\", {\n platform: typeof navigator !== \"undefined\" ? navigator.platform : \"unknown\",\n user_agent:\n typeof navigator !== \"undefined\" ? navigator.userAgent : \"unknown\",\n referrer: typeof document !== \"undefined\" ? document.referrer : \"\",\n url_origin: typeof window !== \"undefined\" ? window.location.origin : \"\",\n embedded: typeof window !== \"undefined\" && window.self !== window.top,\n });\n\n // Mark as sent (stored in localStorage - persists across browser sessions)\n markFirstUseSent();\n\n // Restore opt-out state if user hasn't granted consent yet\n // This ensures we only send the install event, not subsequent events\n const currentConsent = getTelemetryConsent();\n if (currentConsent !== \"granted\") {\n posthog.opt_out_capturing();\n }\n}\n\n/**\n * Check if session start event has already been sent (this browser session)\n */\nfunction hasSessionSent(): boolean {\n if (!isBrowser()) {\n return false;\n }\n\n try {\n return sessionStorage.getItem(TELEMETRY_SESSION_KEY) === \"true\";\n } catch {\n return false;\n }\n}\n\n/**\n * Mark session start event as sent (uses sessionStorage so it resets on new tabs/sessions)\n */\nfunction markSessionSent(): void {\n if (!isBrowser()) {\n return;\n }\n\n try {\n sessionStorage.setItem(TELEMETRY_SESSION_KEY, \"true\");\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Track a session start event.\n * Called each time a new browser session starts (respects consent).\n * Uses sessionStorage for deduplication - only sends once per browser session.\n */\nexport async function trackSessionStart(): Promise<void> {\n if (!isTelemetryEnabled()) {\n return;\n }\n\n // Already sent session event this browser session\n if (hasSessionSent()) {\n return;\n }\n\n // Initialize PostHog if needed\n const posthog = await initializePostHog();\n if (!posthog) {\n return;\n }\n\n posthog.capture(\"canvas_new_session\", {\n is_first_use: !hasFirstUseSent(),\n });\n\n // Mark as sent for this session\n markSessionSent();\n}\n\n/**\n * Track a custom event (respects consent).\n */\nexport async function trackEvent(\n eventName: string,\n properties: Record<string, unknown> = {},\n): Promise<void> {\n if (!isTelemetryEnabled()) {\n return;\n }\n\n // Initialize PostHog if needed\n const posthog = await initializePostHog();\n if (!posthog) {\n return;\n }\n\n posthog.capture(eventName, properties);\n}\n\n/**\n * Clear all telemetry data (for privacy/GDPR requests)\n */\nexport async function clearTelemetryData(): Promise<void> {\n if (!isBrowser()) {\n return;\n }\n\n try {\n localStorage.removeItem(TELEMETRY_CONSENT_KEY);\n localStorage.removeItem(TELEMETRY_FIRST_USE_KEY);\n sessionStorage.removeItem(TELEMETRY_SESSION_KEY);\n\n // Reset PostHog if initialized\n if (isInitialized && posthogInstance) {\n posthogInstance.reset();\n }\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Get the PostHog instance for advanced usage (if needed).\n * Returns the instance if initialized, otherwise null.\n * Note: This is async because PostHog is lazily loaded.\n */\nexport async function getPostHogInstance(): Promise<PostHog | null> {\n if (!isInitialized) {\n return null;\n }\n return posthogInstance;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"telemetry.cjs","names":[],"sources":["../../src/services/telemetry.ts"],"sourcesContent":["/**\n * Telemetry service for tracking library usage.\n *\n * This module handles anonymous telemetry for the @openhands/agent-canvas package\n * using the PostHog SDK for reliable event delivery with batching, retry logic,\n * and offline support.\n *\n * TRACKING PHILOSOPHY:\n * - Install event (canvas_install): Sent immediately on first use, regardless of consent.\n * This is anonymous and contains no PII - just basic browser info and a random ID.\n * - Session/custom events: Only sent after user grants consent via the consent modal.\n * - Users can opt out of all future tracking by declining consent.\n *\n * AD BLOCKER BYPASS:\n * By default, telemetry is routed through OpenHands' reverse proxy (z.openhands.dev)\n * to avoid being blocked by ad blockers. Library consumers can override this with:\n * - VITE_POSTHOG_HOST: Custom proxy URL or direct PostHog URL\n * - VITE_POSTHOG_UI_HOST: PostHog UI host (defaults to https://us.posthog.com)\n *\n * IMPORTANT: By default, telemetry is sent to the OpenHands PostHog project.\n * Library consumers can override this by setting VITE_POSTHOG_API_KEY.\n *\n * Users can disable all telemetry (including install tracking) via:\n * - Setting VITE_DO_NOT_TRACK=1 environment variable\n * - Browser's Do Not Track setting\n */\n\nimport type { PostHog } from \"posthog-js\";\nimport packageJson from \"../../package.json\";\n\nconst TELEMETRY_CONSENT_KEY = \"openhands-telemetry-consent\";\nconst TELEMETRY_FIRST_USE_KEY = \"openhands-telemetry-first-use\";\nconst TELEMETRY_SESSION_KEY = \"openhands-telemetry-session\";\nconst POSTHOG_INSTANCE_NAME = \"agent-canvas\";\n\n// PostHog project keys — one per deployment environment, hardcoded so they\n// are baked into the static bundle at build time and cannot drift at runtime.\n// Replace POSTHOG_STAGING_KEY with a dedicated project key once provisioned.\nconst POSTHOG_PROD_KEY = \"phc_BgzfxKdgsYMLFTmJqt424ZoyVHvKFfrwttLimzdYTKFK\";\nconst POSTHOG_STAGING_KEY = \"phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U\";\n\n// Always use the staging key unless VITE_APP_ENV is explicitly set to\n// \"production\" at bundle time (hardcoded in build:lib and production CI).\n// Library consumers can always override with VITE_POSTHOG_API_KEY.\nconst POSTHOG_API_KEY: string =\n (import.meta.env.VITE_POSTHOG_API_KEY as string | undefined) ||\n (import.meta.env.VITE_APP_ENV === \"production\"\n ? POSTHOG_PROD_KEY\n : POSTHOG_STAGING_KEY);\n\n// Default to OpenHands' reverse proxy to bypass ad blockers.\n// The proxy at z.openhands.dev routes to PostHog's US region.\n// Library consumers can override this with their own proxy or direct PostHog URL.\nconst POSTHOG_HOST =\n import.meta.env.VITE_POSTHOG_HOST || \"https://z.openhands.dev\";\n\n// UI host is needed for PostHog features like toolbar to work correctly\n// when using a reverse proxy. Defaults to US region.\nconst POSTHOG_UI_HOST =\n import.meta.env.VITE_POSTHOG_UI_HOST || \"https://us.posthog.com\";\n\nexport type TelemetryConsent = \"granted\" | \"denied\" | \"pending\";\n\nlet isInitialized = false;\nlet posthogInstance: PostHog | null = null;\n\n/**\n * Check if we're in a browser environment\n */\nfunction isBrowser(): boolean {\n return typeof window !== \"undefined\" && typeof localStorage !== \"undefined\";\n}\n\n/**\n * Lazily load PostHog to avoid SSR/Node.js issues.\n * PostHog is a browser-only library, so we dynamically import it only when needed.\n */\nasync function getPostHog(): Promise<PostHog | null> {\n if (!isBrowser()) {\n return null;\n }\n\n if (posthogInstance) {\n return posthogInstance;\n }\n\n try {\n const { default: posthog } = await import(\"posthog-js\");\n return posthog;\n } catch {\n // Failed to load PostHog - telemetry will be disabled\n return null;\n }\n}\n\n/**\n * Check if telemetry is disabled via environment variable or browser setting.\n * Works in both Node.js and browser (Vite) environments.\n */\nfunction isDoNotTrackEnabled(): boolean {\n // Check Vite environment variable (browser)\n if (\n typeof import.meta !== \"undefined\" &&\n import.meta.env?.VITE_DO_NOT_TRACK === \"1\"\n ) {\n return true;\n }\n\n // Check Node.js environment variable (SSR/testing)\n if (typeof process !== \"undefined\" && process.env?.DO_NOT_TRACK === \"1\") {\n return true;\n }\n\n // Check browser's navigator.doNotTrack standard\n if (\n typeof navigator !== \"undefined\" &&\n (navigator.doNotTrack === \"1\" ||\n // @ts-expect-error - Some browsers use window.doNotTrack\n (typeof window !== \"undefined\" && window.doNotTrack === \"1\"))\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Initialize PostHog SDK.\n *\n * @param enableCapturing - If true, enable capturing immediately (for install tracking).\n * If false, start with capturing disabled (for consent-gated tracking).\n */\nasync function initializePostHog(\n enableCapturing = false,\n): Promise<PostHog | null> {\n if (isInitialized) {\n return posthogInstance;\n }\n\n const posthog = await getPostHog();\n if (!posthog) {\n return null;\n }\n\n // Canvas telemetry must not share PostHog's default singleton with host-app\n // analytics. A named instance gives it independent configuration, consent,\n // persistence, and delivery state.\n posthogInstance = posthog.init(\n POSTHOG_API_KEY,\n {\n api_host: POSTHOG_HOST,\n // UI host is required when using a reverse proxy so PostHog features work correctly\n ui_host: POSTHOG_UI_HOST,\n // Start with capturing disabled by default - we enable it explicitly when needed\n opt_out_capturing_by_default: !enableCapturing,\n // Don't auto-capture page views - we control when to track\n capture_pageview: false,\n // Don't auto-capture clicks etc.\n autocapture: false,\n // Use localStorage for persistence\n persistence: \"localStorage\",\n persistence_name: POSTHOG_INSTANCE_NAME,\n consent_persistence_name: `${POSTHOG_INSTANCE_NAME}-consent`,\n // Disable session recording\n disable_session_recording: true,\n // Set default properties for all events\n loaded: (ph) => {\n ph.register({\n package_name: packageJson.name,\n package_version: packageJson.version,\n });\n },\n },\n POSTHOG_INSTANCE_NAME,\n );\n\n isInitialized = true;\n return posthogInstance;\n}\n\n/**\n * Get user's telemetry consent preference\n */\nexport function getTelemetryConsent(): TelemetryConsent {\n if (!isBrowser()) {\n return \"pending\";\n }\n\n // Check environment variable for opt-out\n if (isDoNotTrackEnabled()) {\n return \"denied\";\n }\n\n try {\n const consent = localStorage.getItem(TELEMETRY_CONSENT_KEY);\n if (consent === \"granted\" || consent === \"denied\") {\n return consent;\n }\n } catch {\n // Ignore storage errors\n }\n\n return \"pending\";\n}\n\n/**\n * Set user's telemetry consent preference\n */\nexport async function setTelemetryConsent(\n consent: \"granted\" | \"denied\",\n): Promise<void> {\n if (!isBrowser()) {\n return;\n }\n\n try {\n localStorage.setItem(TELEMETRY_CONSENT_KEY, consent);\n\n // Initialize PostHog if not already done\n const posthog = await initializePostHog();\n if (!posthog) {\n return;\n }\n\n if (consent === \"granted\") {\n // Enable capturing\n posthog.opt_in_capturing();\n } else {\n // Disable capturing and clear any queued events\n posthog.opt_out_capturing();\n }\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Check if telemetry is enabled (user has granted consent)\n */\nexport function isTelemetryEnabled(): boolean {\n return getTelemetryConsent() === \"granted\";\n}\n\n/**\n * Check if first use event has already been sent\n */\nfunction hasFirstUseSent(): boolean {\n if (!isBrowser()) {\n return false;\n }\n\n try {\n return localStorage.getItem(TELEMETRY_FIRST_USE_KEY) === \"true\";\n } catch {\n return false;\n }\n}\n\n/**\n * Mark first use event as sent\n */\nfunction markFirstUseSent(): void {\n if (!isBrowser()) {\n return;\n }\n\n try {\n localStorage.setItem(TELEMETRY_FIRST_USE_KEY, \"true\");\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Track the initial install of the library.\n *\n * IMPORTANT: This is sent immediately on first use, regardless of consent status.\n * This allows us to track library adoption even if users haven't made a consent choice yet.\n *\n * The event is:\n * - Completely anonymous (no PII, just a random PostHog distinct_id)\n * - Sent only once per installation (tracked via localStorage, persists across sessions)\n * - Still respects DO_NOT_TRACK environment variable and browser setting\n *\n * Users who want complete privacy can:\n * - Set VITE_DO_NOT_TRACK=1 or browser's Do Not Track\n * - Later deny consent to prevent all future tracking\n */\nexport async function trackInstall(): Promise<void> {\n // Respect hard opt-out via environment variable or browser setting\n if (isDoNotTrackEnabled()) {\n return;\n }\n\n // Already sent install event (persisted in localStorage - survives app relaunches)\n if (hasFirstUseSent()) {\n return;\n }\n\n // Initialize PostHog with capturing enabled (for this one event)\n const posthog = await initializePostHog(true);\n if (!posthog) {\n return;\n }\n\n // Temporarily enable capturing if it was disabled\n const wasOptedOut = posthog.has_opted_out_capturing?.() ?? false;\n if (wasOptedOut) {\n posthog.opt_in_capturing();\n }\n\n // Capture the install event\n posthog.capture(\"canvas_install\", {\n platform: typeof navigator !== \"undefined\" ? navigator.platform : \"unknown\",\n user_agent:\n typeof navigator !== \"undefined\" ? navigator.userAgent : \"unknown\",\n referrer: typeof document !== \"undefined\" ? document.referrer : \"\",\n url_origin: typeof window !== \"undefined\" ? window.location.origin : \"\",\n embedded: typeof window !== \"undefined\" && window.self !== window.top,\n });\n\n // Mark as sent (stored in localStorage - persists across browser sessions)\n markFirstUseSent();\n\n // Restore opt-out state if user hasn't granted consent yet\n // This ensures we only send the install event, not subsequent events\n const currentConsent = getTelemetryConsent();\n if (currentConsent !== \"granted\") {\n posthog.opt_out_capturing();\n }\n}\n\n/**\n * Check if session start event has already been sent (this browser session)\n */\nfunction hasSessionSent(): boolean {\n if (!isBrowser()) {\n return false;\n }\n\n try {\n return sessionStorage.getItem(TELEMETRY_SESSION_KEY) === \"true\";\n } catch {\n return false;\n }\n}\n\n/**\n * Mark session start event as sent (uses sessionStorage so it resets on new tabs/sessions)\n */\nfunction markSessionSent(): void {\n if (!isBrowser()) {\n return;\n }\n\n try {\n sessionStorage.setItem(TELEMETRY_SESSION_KEY, \"true\");\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Track a session start event.\n * Called each time a new browser session starts (respects consent).\n * Uses sessionStorage for deduplication - only sends once per browser session.\n */\nexport async function trackSessionStart(): Promise<void> {\n if (!isTelemetryEnabled()) {\n return;\n }\n\n // Already sent session event this browser session\n if (hasSessionSent()) {\n return;\n }\n\n // Initialize PostHog if needed\n const posthog = await initializePostHog();\n if (!posthog) {\n return;\n }\n\n posthog.capture(\"canvas_new_session\", {\n is_first_use: !hasFirstUseSent(),\n });\n\n // Mark as sent for this session\n markSessionSent();\n}\n\n/**\n * Track a custom event (respects consent).\n */\nexport async function trackEvent(\n eventName: string,\n properties: Record<string, unknown> = {},\n): Promise<void> {\n if (!isTelemetryEnabled()) {\n return;\n }\n\n // Initialize PostHog if needed\n const posthog = await initializePostHog();\n if (!posthog) {\n return;\n }\n\n posthog.capture(eventName, properties);\n}\n\n/**\n * Clear all telemetry data (for privacy/GDPR requests)\n */\nexport async function clearTelemetryData(): Promise<void> {\n if (!isBrowser()) {\n return;\n }\n\n try {\n localStorage.removeItem(TELEMETRY_CONSENT_KEY);\n localStorage.removeItem(TELEMETRY_FIRST_USE_KEY);\n sessionStorage.removeItem(TELEMETRY_SESSION_KEY);\n\n // Reset PostHog if initialized\n if (isInitialized && posthogInstance) {\n posthogInstance.reset();\n }\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Get the PostHog instance for advanced usage (if needed).\n * Returns the instance if initialized, otherwise null.\n * Note: This is async because PostHog is lazily loaded.\n */\nexport async function getPostHogInstance(): Promise<PostHog | null> {\n if (!isInitialized) {\n return null;\n }\n return posthogInstance;\n}\n"],"mappings":"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"}
|