@openhands/agent-canvas 1.18.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.windows.md +2 -2
- package/build/assets/acp-providers-DOKcGeaV.js +1 -0
- package/build/assets/active-backend-context-BETEdaJl.js +2 -0
- package/build/assets/{agent-context-settings-D3peZkjX.js → agent-context-settings-Dir0loAn.js} +1 -1
- package/build/assets/{agent-profiles-service.api-DkeZaqIl.js → agent-profiles-service.api-CiMVQAIT.js} +1 -1
- package/build/assets/{agent-profiles-settings-7yMWYjGF.js → agent-profiles-settings-CT5owzRT.js} +1 -1
- package/build/assets/agent-server-conversation-service.api-BtOlitCD.js +88 -0
- package/build/assets/agent-settings-BnzyTgCb.js +2 -0
- package/build/assets/agent-settings-CeXj3xK-.js +1 -0
- package/build/assets/{alert-banner-eYyqvHL3.js → alert-banner-Ccx1Du6n.js} +1 -1
- package/build/assets/{api-key-entry-screen-CCBvBD8u.js → api-key-entry-screen-DXIuzBjY.js} +1 -1
- package/build/assets/{app-settings-BtYDs-Be.js → app-settings-DkIJVTKL.js} +1 -1
- package/build/assets/automation-detail-CF2SweVs.js +3 -0
- package/build/assets/automation-disabled-reason-QFtMrdOr.js +1 -0
- package/build/assets/{automation-export-BJsfi7n2.js → automation-export-CkvehhPF.js} +1 -1
- package/build/assets/{automation-git-sync-B7o_Nbl-.js → automation-git-sync-di4tBAyZ.js} +1 -1
- package/build/assets/automation-setup-route-FERj7WEe.js +3 -0
- package/build/assets/{automation-templates-Bb98r-kx.js → automation-templates-DlaCRvD-.js} +1 -1
- package/build/assets/automations-list-yK7ETmYP.js +1 -0
- package/build/assets/{back-nav-button-B2yBiVMB.js → back-nav-button-oDvIxpQ5.js} +1 -1
- package/build/assets/backend-form-modal-DzYf_arO.js +1 -0
- package/build/assets/{backend-synced-settings-badge-DLEp6cq7.js → backend-synced-settings-badge-DXDDHWX4.js} +1 -1
- package/build/assets/{badge-ehL-kgeO.js → badge-CDHZEVeN.js} +1 -1
- package/build/assets/{base-modal-C1a0TsSx.js → base-modal-CZq4kB_H.js} +1 -1
- package/build/assets/{brand-button-CUMfjb99.js → brand-button-CGUwj6zK.js} +1 -1
- package/build/assets/{browser-SE24Tk8g.js → browser-kY6jN61T.js} +2 -2
- package/build/assets/{browser-tab-HjJxHA0V.js → browser-tab-DFyZXsnB.js} +1 -1
- package/build/assets/{canvas-extension-page-BsUGBb1T.js → canvas-extension-page-DsGq1DtT.js} +1 -1
- package/build/assets/{canvas-extensions-C9Tm6s_E.js → canvas-extensions-Cb2Z0Hdc.js} +1 -1
- package/build/assets/{canvas-extensions-runtime-B8kxM4rO.js → canvas-extensions-runtime-DS6eT4nK.js} +1 -1
- package/build/assets/{chat-send-button-CGvc2wpE.js → chat-send-button-B6aVaD9V.js} +1 -1
- package/build/assets/{circle-plus-check-toggle-BDX_ctNs.js → circle-plus-check-toggle-ZOXpJ3I2.js} +1 -1
- package/build/assets/{cloud-funnel-analytics-D5uJ_4JE.js → cloud-funnel-analytics-BH_zxjiO.js} +1 -1
- package/build/assets/{cog-CAEugqtV.js → cog-DVZT1f0s.js} +1 -1
- package/build/assets/{command-menu-CQxs4mtX.js → command-menu-ImeHQ6c2.js} +1 -1
- package/build/assets/{commits-tab-D0xgjipP.js → commits-tab-B5SUF66c.js} +1 -1
- package/build/assets/{condenser-settings-D63NJRBT.js → condenser-settings-BlGOXEXM.js} +1 -1
- package/build/assets/{confirmation-modal-78sd9Vny.js → confirmation-modal-oN1EId79.js} +1 -1
- package/build/assets/{context-menu-list-item-Cm7-7Y-7.js → context-menu-list-item-DIm5xQg6.js} +1 -1
- package/build/assets/{conversation-B_nweu5p.js → conversation-9a53tdbO.js} +4 -4
- package/build/assets/conversation-XRsI28ZM.js +1 -0
- package/build/assets/conversation-panel-XRsI28ZM.js +1 -0
- package/build/assets/{conversation-state-store-9D_3P7q4.js → conversation-state-store-Br-eE-gg.js} +1 -1
- package/build/assets/{conversation-tab-empty-state-B3dpJXX0.js → conversation-tab-empty-state-BT1GrnKP.js} +1 -1
- package/build/assets/{copy-to-clipboard-button-B1ljgNxO.js → copy-to-clipboard-button-CvTHqY13.js} +1 -1
- package/build/assets/{device-verify-D5QRIS_x.js → device-verify-DX0xdNjo.js} +1 -1
- package/build/assets/{dropdown-classes-BGvOvW2_.js → dropdown-classes-DyyMaaXl.js} +1 -1
- package/build/assets/edit-automation-modal-bfD-5NIc.js +1 -0
- package/build/assets/empty-state-B5advKVW.js +1 -0
- package/build/assets/{entry.client-BMafTpjO.js → entry.client-D_2gnSyB.js} +2 -2
- package/build/assets/{enum-filter-dropdown-UNaom12H.js → enum-filter-dropdown-VAJp5mqh.js} +1 -1
- package/build/assets/{environment-switch-overlay-COibRUA-.js → environment-switch-overlay-C7x_yhEs.js} +1 -1
- package/build/assets/{error-state-Cf8LRuuY.js → error-state-BgYl7YeB.js} +1 -1
- package/build/assets/{extensions-hub-C_6ahIua.js → extensions-hub-DjhOed1I.js} +1 -1
- package/build/assets/{extensions-navigation-C5GfpzFe.js → extensions-navigation-Di-J2KUR.js} +1 -1
- package/build/assets/{files-tab-D5PPIWI1.js → files-tab-BNDp3e_x.js} +1 -1
- package/build/assets/{form-control-classes-Dbq-7YP_.js → form-control-classes-BVI_szaj.js} +1 -1
- package/build/assets/{get-git-path-jU2zjqIB.js → get-git-path-DOe6PM_a.js} +1 -1
- package/build/assets/git-repo-dropdown-1fZGYtYm.js +1 -0
- package/build/assets/{git-repo-dropdown-uxlFw2gn.js → git-repo-dropdown-DNlinQ7r.js} +1 -1
- package/build/assets/{highlighted-source-view-C7pAXrT0.js → highlighted-source-view-DPerL6tF.js} +1 -1
- package/build/assets/home-4lyLzYjG.js +1 -0
- package/build/assets/home-BGaB0EeK.js +1 -0
- package/build/assets/home-automation-run-tooltip-v5n7zXR0.js +1 -0
- package/build/assets/{home-store-DCbei3DX.js → home-store-roz1x6D5.js} +1 -1
- package/build/assets/{hooks-service-Dnmhqc0Z.js → hooks-service-tzRqtAlm.js} +1 -1
- package/build/assets/index-home-6Y_Y7kOo.js +1 -0
- package/build/assets/{install-server-modal-B81I-5OE.js → install-server-modal-DkMCfj0J.js} +1 -1
- package/build/assets/{key-O84CMFHb.js → key-DpfBWQbk.js} +1 -1
- package/build/assets/{launch-ZLxI4opd.js → launch-TrnYlJe6.js} +1 -1
- package/build/assets/link-external-B4gx3EeM.js +1 -0
- package/build/assets/llm-not-configured-banner-BdjItKQR.js +27 -0
- package/build/assets/{llm-settings-CODhjQzy.js → llm-settings-CUgt39uu.js} +1 -1
- package/build/assets/llm-settings-DEfw-fUJ.js +1 -0
- package/build/assets/{llm-subscription-service-CgIDc38n.js → llm-subscription-service-LGYVzyAc.js} +1 -1
- package/build/assets/{loading-spinner-BeLV0IXf.js → loading-spinner-BJc2J0Dw.js} +1 -1
- package/build/assets/{manage-backends-modal-cMXqCb-B.js → manage-backends-modal-CIjk0B2H.js} +1 -1
- package/build/assets/manifest-23d79467.js +1 -0
- package/build/assets/{manifest-subpage-layout-CVZgVKoY.js → manifest-subpage-layout-DGYRoP_8.js} +1 -1
- package/build/assets/{markdown-renderer-DyFl9-mL.js → markdown-renderer-DRpwRlNm.js} +1 -1
- package/build/assets/mcp-CoUOIGBF.js +1 -0
- package/build/assets/mcp-installed-servers-BW51n6PC.js +1 -0
- package/build/assets/mcp-marketplace-utils-BwEnDYqm.js +1 -0
- package/build/assets/mcp-page-hZ4aJjj_.js +9 -0
- package/build/assets/{messages-Bk1xhbU2.js → messages-WUb9Yh-p.js} +4 -4
- package/build/assets/{modal-body-C24WsdFb.js → modal-body-B_95ci1c.js} +1 -1
- package/build/assets/{modal-classes-B0b9eiL8.js → modal-classes-BPcBCWVj.js} +1 -1
- package/build/assets/{modal-close-button-DfqfB2Nj.js → modal-close-button-Cq3dma5u.js} +1 -1
- package/build/assets/onboarding-Cc4Av7bi.js +1 -0
- package/build/assets/{onboarding-modal-BT3Gx_sZ.js → onboarding-modal-DCFD4Dsa.js} +1 -1
- package/build/assets/{organization-service.api-B5CvmnYQ.js → organization-service.api-zhHpQU0t.js} +1 -1
- package/build/assets/parse-git-remote-url-BG8pcKL8.js +1 -0
- package/build/assets/{planner-tab-CstoOlAB.js → planner-tab-yISBVUKu.js} +1 -1
- package/build/assets/{plugins-management-service-5rqVPEGN.js → plugins-management-service-2oP6_tWr.js} +1 -1
- package/build/assets/{profiles-service.api-D1XKMgr0.js → profiles-service.api-B5thiTI3.js} +1 -1
- package/build/assets/{providers-XmZ9HM4Q.js → providers-Co9PsD0s.js} +1 -1
- package/build/assets/{proxy-XP6U1Dhv.js → proxy-BCCQUna8.js} +1 -1
- package/build/assets/recommended-automations-launcher-D1Do753p.js +1 -0
- package/build/assets/root-D1y82Lhg.js +2 -0
- package/build/assets/{root-layout-DUquNZTU.js → root-layout-cQTYEG2w.js} +2 -2
- package/build/assets/root-sEWn3ha1.css +1 -0
- package/build/assets/{schema-field-Y3F8JvXd.js → schema-field-DSi0d7a8.js} +1 -1
- package/build/assets/{sdk-section-page-CNZTLwH9.js → sdk-section-page-DCoI2dtd.js} +1 -1
- package/build/assets/{secret-form-9-BoGA40.js → secret-form-BDvzojzN.js} +1 -1
- package/build/assets/{secrets-service-BOIsfD9j.js → secrets-service-C3CNNEpY.js} +1 -1
- package/build/assets/{secrets-settings-CBJgFr42.js → secrets-settings-BKqfYQt5.js} +1 -1
- package/build/assets/{settings-D4hdToD4.js → settings-C8ZLONyx.js} +1 -1
- package/build/assets/{settings-dropdown-input-DBvsZ7-Q.js → settings-dropdown-input-Df_HXRk4.js} +1 -1
- package/build/assets/{settings-index-DeQphyBK.js → settings-index-BWvlGHg3.js} +1 -1
- package/build/assets/{settings-input-dVuzapBA.js → settings-input-B3i5U9GL.js} +1 -1
- package/build/assets/{settings-list-classes-DhAPuXm6.js → settings-list-classes-DbqcSiVW.js} +1 -1
- package/build/assets/{settings-modal-tHiJ8iYV.js → settings-modal-DHKJSBPL.js} +1 -1
- package/build/assets/{settings-nav-GAQjW1a-.js → settings-nav-BThjwLWD.js} +1 -1
- package/build/assets/{settings-service.api-C1vZH9Vh.js → settings-service.api-CYBTLGOd.js} +1 -1
- package/build/assets/{settings-switch-DDd1cQ8t.js → settings-switch-CI93Iozg.js} +1 -1
- package/build/assets/{shared-conversation-Cyg7m7ns.js → shared-conversation-C7OILS-U.js} +1 -1
- package/build/assets/{sidebar-layout-DH0E-5KW.js → sidebar-layout-Csb6Geq0.js} +1 -1
- package/build/assets/{sidebar-mobile-menu-toggle-CQ4iky__.js → sidebar-mobile-menu-toggle-B2xwXm4s.js} +1 -1
- package/build/assets/{sidebar-nav-link-oLQiKUBu.js → sidebar-nav-link-Xv7QEMVS.js} +1 -1
- package/build/assets/{sidebar-onboarding-checklist-storage-TfvNNnnr.js → sidebar-onboarding-checklist-storage-_zxMqHS0.js} +1 -1
- package/build/assets/{skill-card-pill-row-DfjIfj0K.js → skill-card-pill-row-CxOFySng.js} +1 -1
- package/build/assets/{skill-enablement-DXeaImBz.js → skill-enablement-BBKya60C.js} +1 -1
- package/build/assets/{skill-filter-DsNLmn76.js → skill-filter-BvtbD--b.js} +1 -1
- package/build/assets/{skill-icon-badge-0MK_68Nc.js → skill-icon-badge-CVxE42yg.js} +1 -1
- package/build/assets/{skill-scope-BE-H9TSZ.js → skill-scope-C0NxJnpT.js} +1 -1
- package/build/assets/{skills-plugins-vzSdxSk_.js → skills-plugins-BGjX4jve.js} +1 -1
- package/build/assets/{skills-settings-BiPOH9H9.js → skills-settings-d3ZwIjSP.js} +1 -1
- package/build/assets/{styled-tooltip-CejG0rqv.js → styled-tooltip-CknPQH4Y.js} +1 -1
- package/build/assets/{task-list-tab-OkZSqnTp.js → task-list-tab-CQisRcPh.js} +1 -1
- package/build/assets/{terminal-Dph60VFZ.js → terminal-Bs50gJPC.js} +1 -1
- package/build/assets/{toggle-switch-B2uXaAUS.js → toggle-switch-D3TBxlsc.js} +1 -1
- package/build/assets/trash-D1QMHInX.js +1 -0
- package/build/assets/{typography-DgcLGdHk.js → typography-BdAApXGl.js} +1 -1
- package/build/assets/{usage-tab-MCmNRAnR.js → usage-tab-ClVHAFJy.js} +1 -1
- package/build/assets/{use-acp-credential-form-ychoGqjC.js → use-acp-credential-form-GfqcTJl5.js} +1 -1
- package/build/assets/{use-activate-agent-profile-8L8Xdghy.js → use-activate-agent-profile-DO6SNPkK.js} +1 -1
- package/build/assets/{use-agent-profiles-Bi8hSkze.js → use-agent-profiles-YsBlt3tT.js} +1 -1
- package/build/assets/{use-automation-health-U99vvHxx.js → use-automation-health-CbQ9n-k7.js} +1 -1
- package/build/assets/{use-automation-permissions-Buus0R6h.js → use-automation-permissions-gFy-2VD0.js} +1 -1
- package/build/assets/{use-automations-Bq5hVuv0.js → use-automations-7_XBXHQK.js} +1 -1
- package/build/assets/{use-can-manage-org-profiles-MzIeEV8F.js → use-can-manage-org-profiles-Dt4YkPO7.js} +1 -1
- package/build/assets/{use-canvas-extensions-Ca9KoVEm.js → use-canvas-extensions-BhYQrtMK.js} +1 -1
- package/build/assets/{use-cloud-current-user-id-B4ZLUZSa.js → use-cloud-current-user-id-Dqw6qQUg.js} +1 -1
- package/build/assets/{use-config-l5tkDHyD.js → use-config-BJ_FJCjV.js} +1 -1
- package/build/assets/use-create-conversation-D15Px574.js +1 -0
- package/build/assets/use-create-secret-D_qPU88t.js +1 -0
- package/build/assets/{use-free-models-gCsJ5BV0.js → use-free-models-FAk2nngq.js} +1 -1
- package/build/assets/{use-get-secrets-CMTuWEp_.js → use-get-secrets-Pbo9jh2A.js} +1 -1
- package/build/assets/{use-llm-configured-Dl4zg8ht.js → use-llm-configured-DF9BYmIe.js} +1 -1
- package/build/assets/{use-llm-profiles-SWsuFmFu.js → use-llm-profiles-U4u1gzuk.js} +1 -1
- package/build/assets/use-manifest-capabilities-D81_YdAF.js +1 -0
- package/build/assets/{use-onboarding-completion-Xl63ZvzQ.js → use-onboarding-completion-C4W-m2Jk.js} +1 -1
- package/build/assets/{use-pinned-home-route-BXDIUaxQ.js → use-pinned-home-route-DByWTojw.js} +1 -1
- package/build/assets/{use-plugins-marketplace-BIIaPiaB.js → use-plugins-marketplace-CTRoukH0.js} +1 -1
- package/build/assets/{use-save-agent-profile-D-ZHHE94.js → use-save-agent-profile-xpHBxMZM.js} +1 -1
- package/build/assets/{use-save-settings-Dapkf4cC.js → use-save-settings-CmX41wlf.js} +1 -1
- package/build/assets/{use-settings-C2KKQKVC.js → use-settings-D69cw06D.js} +1 -1
- package/build/assets/{use-settings-nav-items-TOc0Rsfd.js → use-settings-nav-items-CVz0SnDr.js} +1 -1
- package/build/assets/use-tracking-BAFpgpgq.js +3 -0
- package/build/assets/{use-user-conversation-5UFqMoO4.js → use-user-conversation-BBDXUbOc.js} +1 -1
- package/build/assets/utils-CbjwNcR-.js +1 -0
- package/build/assets/{vendor~browser-hbU4u2Ag.js → vendor~browser-BZ-zIfb6.js} +1 -1
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-DvZtOcoT.js +2 -0
- package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-CxhwKuAd.js → vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-BIjRfQ4u.js} +1 -1
- package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-BBfdJIV9.js +48 -0
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-3eJ4ExtV.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-fgzdgvrL.js} +3579 -165
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~jz4f6vo2-C7HiY4Ae.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~jz4f6vo2-BqdU447s.js} +794 -227
- package/build/assets/{verification-settings-DdBpaVPz.js → verification-settings-BXspn27q.js} +1 -1
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +18 -1
- package/build/locales/ca/openhands.json +18 -1
- package/build/locales/de/openhands.json +18 -1
- package/build/locales/en/openhands.json +18 -1
- package/build/locales/es/openhands.json +18 -1
- package/build/locales/fr/openhands.json +18 -1
- package/build/locales/it/openhands.json +18 -1
- package/build/locales/ja/openhands.json +18 -1
- package/build/locales/ko-KR/openhands.json +18 -1
- package/build/locales/no/openhands.json +18 -1
- package/build/locales/pt/openhands.json +18 -1
- package/build/locales/tr/openhands.json +18 -1
- package/build/locales/uk/openhands.json +18 -1
- package/build/locales/zh-CN/openhands.json +18 -1
- package/build/locales/zh-TW/openhands.json +18 -1
- package/config/defaults.json +3 -3
- package/dist/api/agent-profiles-service/profile-field-support.d.ts +2 -0
- package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.cjs +3 -3
- package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.js +12 -16
- package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.js.map +1 -1
- package/dist/components/features/automations/agent-profile-selector.d.ts +7 -0
- package/dist/components/features/automations/detail/disabled-reason-banner.d.ts +16 -0
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs +1 -1
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs.map +1 -1
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js +38 -29
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js.map +1 -1
- package/dist/components/features/settings/agent-profiles/profile-scope-list.d.ts +20 -0
- package/dist/config/defaults.cjs +1 -1
- package/dist/config/defaults.cjs.map +1 -1
- package/dist/config/defaults.js +3 -3
- package/dist/config/defaults.js.map +1 -1
- package/dist/constants/acp-providers.cjs +1 -1
- package/dist/constants/acp-providers.cjs.map +1 -1
- package/dist/constants/acp-providers.d.ts +0 -5
- package/dist/constants/acp-providers.js +20 -16
- package/dist/constants/acp-providers.js.map +1 -1
- package/dist/constants/profile-scope.d.ts +21 -0
- 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.js +30 -19
- package/dist/hooks/mutation/use-create-conversation.js.map +1 -1
- package/dist/hooks/mutation/use-switch-acp-model.cjs +1 -1
- package/dist/hooks/mutation/use-switch-acp-model.cjs.map +1 -1
- package/dist/hooks/mutation/use-switch-acp-model.js +11 -12
- package/dist/hooks/mutation/use-switch-acp-model.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 +1 -0
- package/dist/hooks/query/query-keys.js +10 -1
- package/dist/hooks/query/query-keys.js.map +1 -1
- package/dist/hooks/query/use-active-acp-profile-detail.cjs +1 -1
- package/dist/hooks/query/use-active-acp-profile-detail.cjs.map +1 -1
- package/dist/hooks/query/use-active-acp-profile-detail.d.ts +0 -9
- package/dist/hooks/query/use-active-acp-profile-detail.js +4 -13
- package/dist/hooks/query/use-active-acp-profile-detail.js.map +1 -1
- package/dist/hooks/query/use-automation-sdk-version.cjs +1 -1
- package/dist/hooks/query/use-automation-sdk-version.cjs.map +1 -1
- package/dist/hooks/query/use-automation-sdk-version.js +3 -1
- package/dist/hooks/query/use-automation-sdk-version.js.map +1 -1
- package/dist/hooks/use-drag-resize.cjs +1 -1
- package/dist/hooks/use-drag-resize.cjs.map +1 -1
- package/dist/hooks/use-drag-resize.js +8 -9
- package/dist/hooks/use-drag-resize.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 +18 -1
- package/dist/i18n/declaration.js +1 -1
- package/dist/i18n/declaration.js.map +1 -1
- package/dist/i18n/translation.cjs +3 -3
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +289 -0
- package/dist/i18n/translation.js.map +1 -1
- package/dist/locales/ar/openhands.json +18 -1
- package/dist/locales/ca/openhands.json +18 -1
- package/dist/locales/de/openhands.json +18 -1
- package/dist/locales/en/openhands.json +18 -1
- package/dist/locales/es/openhands.json +18 -1
- package/dist/locales/fr/openhands.json +18 -1
- package/dist/locales/it/openhands.json +18 -1
- package/dist/locales/ja/openhands.json +18 -1
- package/dist/locales/ko-KR/openhands.json +18 -1
- package/dist/locales/no/openhands.json +18 -1
- package/dist/locales/pt/openhands.json +18 -1
- package/dist/locales/tr/openhands.json +18 -1
- package/dist/locales/uk/openhands.json +18 -1
- package/dist/locales/zh-CN/openhands.json +18 -1
- package/dist/locales/zh-TW/openhands.json +18 -1
- package/dist/manifests/automation-setup.cjs.map +1 -1
- package/dist/manifests/automation-setup.js.map +1 -1
- package/dist/manifests/manifest-local-validation.cjs.map +1 -1
- package/dist/manifests/manifest-local-validation.js.map +1 -1
- package/dist/manifests/manifest-validation.cjs +1 -1
- package/dist/manifests/manifest-validation.cjs.map +1 -1
- package/dist/manifests/manifest-validation.js +2 -2
- package/dist/manifests/manifest-validation.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/bundle-index.cjs +3670 -247
- package/dist/node_modules/@openhands/extensions/automations/bundle-index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/bundle-index.js +26 -3
- package/dist/node_modules/@openhands/extensions/automations/bundle-index.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.js +4 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-delivery-watchdog/manifest.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-delivery-watchdog/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-delivery-watchdog/manifest.js +79 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-delivery-watchdog/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs +1 -11
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js +25 -11
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-triage/manifest.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-triage/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-triage/manifest.js +72 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-triage/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +1 -10
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +24 -11
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/gitlab-issue-to-mr/manifest.cjs +12 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/gitlab-issue-to-mr/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/gitlab-issue-to-mr/manifest.js +115 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/gitlab-issue-to-mr/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +20 -14
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/reportportal.cjs +2 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/reportportal.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/reportportal.js +73 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog/reportportal.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js +9 -7
- package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/skills/index.cjs +794 -227
- package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/skills/index.js +46 -6
- package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.js +15 -8
- package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.js +11 -13
- package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js +6 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.js +9 -12
- package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.js +9 -10
- package/dist/node_modules/@openhands/typescript-client/dist/client/openhands-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.cjs +2 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.cjs.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.js +41 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.js.map +1 -0
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js +2 -2
- package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.js +3 -6
- package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/clients.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/clients.js +1 -2
- package/dist/node_modules/@openhands/typescript-client/dist/conversation/conversation-manager.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/conversation/conversation-manager.js +0 -1
- 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 +199 -61
- package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.cjs +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.cjs.map +1 -1
- package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.js +9 -8
- package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +3 -3
- package/dist/package.js.map +1 -1
- package/dist/routes/agent-settings.d.ts +11 -0
- package/dist/types/automation.cjs.map +1 -1
- package/dist/types/automation.d.ts +26 -2
- package/dist/types/automation.js.map +1 -1
- package/dist/utils/automation-disabled-reason.cjs +2 -0
- package/dist/utils/automation-disabled-reason.cjs.map +1 -0
- package/dist/utils/automation-disabled-reason.d.ts +32 -0
- package/dist/utils/automation-disabled-reason.js +19 -0
- package/dist/utils/automation-disabled-reason.js.map +1 -0
- package/dist/utils/parse-git-remote-url.cjs +1 -1
- package/dist/utils/parse-git-remote-url.cjs.map +1 -1
- package/dist/utils/parse-git-remote-url.d.ts +5 -1
- package/dist/utils/parse-git-remote-url.js +20 -13
- package/dist/utils/parse-git-remote-url.js.map +1 -1
- package/package.json +3 -3
- package/scripts/check-sdk-version-sync.mjs +79 -8
- package/scripts/dev-safe.mjs +14 -1
- package/scripts/docker-build.mjs +3 -0
- package/scripts/static-server.mjs +24 -7
- package/build/assets/acp-providers-DcY_mKYa.js +0 -1
- package/build/assets/active-backend-context-BnH4-L8h.js +0 -2
- package/build/assets/agent-server-conversation-service.api-jiCopc2E.js +0 -88
- package/build/assets/agent-settings-BF8hM6wb.js +0 -2
- package/build/assets/agent-settings-YPutBAeR.js +0 -1
- package/build/assets/automation-detail-BxXhb_m2.js +0 -3
- package/build/assets/automation-setup-route-qaJ6lLCf.js +0 -3
- package/build/assets/automations-list-DEPVNud3.js +0 -1
- package/build/assets/backend-form-modal-DxisQV_6.js +0 -1
- package/build/assets/conversation-edjzrv5w.js +0 -1
- package/build/assets/conversation-panel-edjzrv5w.js +0 -1
- package/build/assets/edit-automation-modal-D_JWSmxT.js +0 -1
- package/build/assets/empty-state-FK_s1B60.js +0 -1
- package/build/assets/git-repo-dropdown-BoDDWXfX.js +0 -1
- package/build/assets/home-BM5_Wz_R.js +0 -1
- package/build/assets/home-Ivfm7KC4.js +0 -1
- package/build/assets/home-automation-run-tooltip-B1N2uO9p.js +0 -1
- package/build/assets/index-home-td9BN2T3.js +0 -1
- package/build/assets/kebab-menu-item-content-SCJBwZnp.js +0 -1
- package/build/assets/link-external-BNZzCM1I.js +0 -1
- package/build/assets/llm-not-configured-banner-Dh_ajcM8.js +0 -27
- package/build/assets/llm-settings-CZaXYgtw.js +0 -1
- package/build/assets/manifest-bfeccb98.js +0 -1
- package/build/assets/mcp-CraxoXQv.js +0 -1
- package/build/assets/mcp-marketplace-utils-C7PYr293.js +0 -1
- package/build/assets/mcp-page-CteH_K0N.js +0 -9
- package/build/assets/onboarding-DXFBRqEy.js +0 -1
- package/build/assets/parse-git-remote-url-DpDM9bK6.js +0 -1
- package/build/assets/recommended-automations-launcher-DEHRKIAg.js +0 -1
- package/build/assets/root-CM6IZHlg.css +0 -1
- package/build/assets/root-DdFkodKW.js +0 -2
- package/build/assets/trash-Ckh7yCaB.js +0 -1
- package/build/assets/use-create-conversation-i_PdFdIs.js +0 -1
- package/build/assets/use-create-secret-CjWq0J4O.js +0 -1
- package/build/assets/use-manifest-capabilities-CdqYfUAC.js +0 -1
- package/build/assets/use-tracking-j4uo9VEW.js +0 -3
- package/build/assets/utils-BgLSZdyy.js +0 -1
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-Z0lly3FE.js +0 -2
- package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-CnsDDzeE.js +0 -48
- package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.cjs +0 -2
- package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.cjs.map +0 -1
- package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.js +0 -21
- package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.js.map +0 -1
|
@@ -1437,6 +1437,10 @@ reviewing it would tell you nothing the first did not.
|
|
|
1437
1437
|
|
|
1438
1438
|
---
|
|
1439
1439
|
|
|
1440
|
+
The script imports shared GitHub transport from
|
|
1441
|
+
\`scripts/github_client.py\`, installed with this skill. Include it beside
|
|
1442
|
+
\`main.py\` when packaging manually, as shown below.
|
|
1443
|
+
|
|
1440
1444
|
## Prerequisites
|
|
1441
1445
|
|
|
1442
1446
|
### Required secret
|
|
@@ -1560,9 +1564,11 @@ substitutions near the top of the file:
|
|
|
1560
1564
|
Use a safe string writer such as \`json.dumps(value)\` when inserting user-provided
|
|
1561
1565
|
repository names or prefixes into Python string literals.
|
|
1562
1566
|
|
|
1563
|
-
|
|
1567
|
+
Run these commands from this skill's directory, write the customized script
|
|
1568
|
+
to a temporary build directory, and validate it:
|
|
1564
1569
|
\`\`\`bash
|
|
1565
1570
|
mkdir -p /tmp/agents-md-build
|
|
1571
|
+
cp -L scripts/github_client.py /tmp/agents-md-build/github_client.py
|
|
1566
1572
|
# write the customized main.py to /tmp/agents-md-build/main.py
|
|
1567
1573
|
python3 -m py_compile /tmp/agents-md-build/main.py && echo "Syntax OK"
|
|
1568
1574
|
\`\`\`
|
|
@@ -1676,7 +1682,14 @@ For each repository:
|
|
|
1676
1682
|
| \`git is not available in the automation runtime\` | The runtime image has no git | Use a runtime image that ships git |
|
|
1677
1683
|
| Pull request says nothing changed | The agent judged AGENTS.md accurate but still committed | Read its summary in the pull request body; tighten the prompt if it keeps making cosmetic edits |
|
|
1678
1684
|
| Every run reports \`no-changes\` | AGENTS.md is accurate, or the agent cannot read the repository | Open the conversation from the run log and check what it saw |
|
|
1679
|
-
| Clones remain under \`agents-md/\` | Their conversations had not stopped yet | They are removed by a later run once the conversation is terminal |`,category:`automations`},{name:`github-issue-to-pr`,description:`Create an automation that implements GitHub issues when a configurable trigger label is applied. Polls one or more repositories deterministically, clones the default branch, starts one OpenHands conversation per label event, then commits, pushes, and opens the pull request itself.`,triggers:[`/issue-to-pr:setup`],content:`# GitHub Issue to PR Automation
|
|
1685
|
+
| Clones remain under \`agents-md/\` | Their conversations had not stopped yet | They are removed by a later run once the conversation is terminal |`,category:`automations`},{name:`github-delivery-watchdog`,description:`Periodically check pull requests and merge only current heads with independent review, tests, and passing CI.`,triggers:[`/github-delivery-watchdog`],content:"# GitHub delivery watchdog\n\nThis is a deterministic scheduled host command. It creates no agent or\nconversation and needs no agent profile. Configure a repository-scoped\nfine-grained PAT with Contents and Issues read/write plus Pull requests, Actions,\nCommit statuses, and Metadata read. Contents write permits merge; Issues write\nretains the review label when the branch is updated. Never put the token value in\nthe automation definition.\n\nPackage `scripts/worker.py` as `worker.py` and the shared\n`scripts/github_client.py` as `github_client.py`.\nThe catalog bundle declares these exact files. Its `config.json` supplies\n`repos`, `branch_prefix`, and the saved secret name. The shared GitHub client\nresolves only that named secret. Automation owns scheduling and cancellation.\n\nSet `branch_prefix` (default `openhands/issue`), `base_branch` (defaults to the repository's default branch),\nand `required_workflow_ids` when particular Actions workflows must run. The\nwatchdog requires `software-factory/tests` and `software-factory/review` success\nstatuses on the exact head, all other statuses and Actions passing, a current\nbase, a non-draft PR, and GitHub reporting it mergeable. Missing, pending, failed,\nor inaccessible evidence does not permit merge. A changed head requires fresh\nreview and tests. When an accepted branch is behind the base, the watchdog asks\nGitHub to update it and retains the review trigger label; it considers the new\nhead only on a later run. The merge request includes the expected head SHA.\n\nActions are optional when `required_workflow_ids` is empty; the two acceptance\nstatuses remain mandatory. Configure workflow IDs when GitHub Actions must also\nsupply evidence. Branch protection remains GitHub's final merge gate.",category:`automations`},{name:`github-issue-to-pr`,description:`Create an automation that implements GitHub issues when a configurable trigger label is applied. Polls one or more repositories deterministically, clones the default branch, starts one OpenHands conversation per label event, then commits, pushes, and opens the pull request itself.`,triggers:[`/issue-to-pr:setup`],content:`# GitHub Issue to PR Automation
|
|
1686
|
+
|
|
1687
|
+
## Agent Canvas catalog
|
|
1688
|
+
|
|
1689
|
+
For new Agent Canvas installations, use the **GitHub issue to PR** catalog
|
|
1690
|
+
entry. Its deterministic \`worker.py\` scanner delegates each eligible issue to a
|
|
1691
|
+
stable conversation using the selected agent profile. The manual upload flow
|
|
1692
|
+
below remains for existing deployments and is deprecated for new installations.
|
|
1680
1693
|
|
|
1681
1694
|
Create a cron automation that watches one or more GitHub repositories for issues
|
|
1682
1695
|
with a trigger label, starts an OpenHands conversation once per label event with
|
|
@@ -1707,6 +1720,11 @@ environment of a command that mentions it, and masks it in the output.
|
|
|
1707
1720
|
|
|
1708
1721
|
---
|
|
1709
1722
|
|
|
1723
|
+
The script imports shared GitHub transport from
|
|
1724
|
+
\`scripts/github_client.py\`, installed with this skill. Include it beside
|
|
1725
|
+
\`main.py\` when packaging manually, as shown below; catalog bundles include it
|
|
1726
|
+
automatically.
|
|
1727
|
+
|
|
1710
1728
|
## Prerequisites
|
|
1711
1729
|
|
|
1712
1730
|
### Required secret
|
|
@@ -1872,9 +1890,11 @@ Use a safe string writer such as \`json.dumps(value)\` when inserting user-provi
|
|
|
1872
1890
|
repository names, labels, or prefixes into Python string literals.
|
|
1873
1891
|
\`json.dumps(list_of_repos)\` produces the whole \`REPOS\` list safely in one step.
|
|
1874
1892
|
|
|
1875
|
-
|
|
1893
|
+
Run these commands from this skill's directory and write the customized script
|
|
1894
|
+
to a temporary build directory:
|
|
1876
1895
|
\`\`\`bash
|
|
1877
1896
|
mkdir -p /tmp/issue-to-pr-build
|
|
1897
|
+
cp -L scripts/github_client.py /tmp/issue-to-pr-build/github_client.py
|
|
1878
1898
|
# write the customized main.py to /tmp/issue-to-pr-build/main.py
|
|
1879
1899
|
\`\`\`
|
|
1880
1900
|
|
|
@@ -2037,7 +2057,33 @@ The completion callback fires once for the whole run.
|
|
|
2037
2057
|
| Same issue not picked up again after new comments | Its label event was already processed | Remove and re-apply the trigger label |
|
|
2038
2058
|
| Agent reports it cannot push or open a PR | By design - it has no credentials | No action; the automation pushes and opens the pull request after the agent stops |
|
|
2039
2059
|
| A backlog of labelled issues starts slowly | \`MAX_NEW_PER_RUN\` caps how many conversations one poll starts | Wait for the next polls, or raise the cap in the script |
|
|
2040
|
-
| Clones remain under \`issue-to-pr/\` | Their conversations had not stopped yet | They are removed by a later poll once the conversation is terminal |`,category:`automations`},{name:`github-
|
|
2060
|
+
| Clones remain under \`issue-to-pr/\` | Their conversations had not stopped yet | They are removed by a later poll once the conversation is terminal |`,category:`automations`},{name:`github-issue-triage`,description:`Prioritize open issues and establish acceptance criteria before marking them ready for development.`,triggers:[`/github-issue-triage`],content:`# GitHub issue triage
|
|
2061
|
+
|
|
2062
|
+
Prioritize open issues and establish acceptance criteria before marking them ready for development.
|
|
2063
|
+
|
|
2064
|
+
Create this automation separately from implementation and review. Use a
|
|
2065
|
+
fine-grained GitHub PAT limited to the selected repositories with Issues: read and
|
|
2066
|
+
write. Never put the token value in the automation definition or prompt.
|
|
2067
|
+
|
|
2068
|
+
Package \`worker.py\` with the shared \`github_client.py\` and
|
|
2069
|
+
\`agent_conversation.py\` helpers. Supply \`config.json\` with \`repos\` and the saved
|
|
2070
|
+
GitHub secret name; the entrypoint is \`python3 worker.py\`. Include that secret in
|
|
2071
|
+
the selected profile so the delegated agent can use GitHub. Naming it in the
|
|
2072
|
+
automation does not grant it to the agent.
|
|
2073
|
+
|
|
2074
|
+
The scanner is an ordinary Automation host command. It submits selected issues
|
|
2075
|
+
through the shared KV-backed conversation dispatcher, which creates or resumes
|
|
2076
|
+
one stable conversation per issue through the Software Agent SDK. Only that
|
|
2077
|
+
agent workspace is local or Docker. Automation owns scheduling, cancellation,
|
|
2078
|
+
and cleanup.
|
|
2079
|
+
|
|
2080
|
+
Honor \`Depends on: #12, #13\` lines. A dependency must be closed as completed.
|
|
2081
|
+
Post readable acceptance criteria and rationale. Add \`ready-for-dev\` only when
|
|
2082
|
+
criteria are actionable; preserve existing issue labels. Unclear issues stay open
|
|
2083
|
+
for clarification. Do not implement code or accept pull requests.
|
|
2084
|
+
|
|
2085
|
+
Each scheduled run submits every changed eligible issue. A failure on one issue is
|
|
2086
|
+
reported and does not prevent the remaining issues from being submitted.`,category:`automations`},{name:`github-pr-review`,description:`Post PR review comments using the GitHub API with inline comments, suggestions, and priority labels.`,triggers:[`/github-pr-review`],content:`# GitHub PR Review
|
|
2041
2087
|
|
|
2042
2088
|
Post structured code review feedback using the GitHub API with inline comments on specific lines.
|
|
2043
2089
|
Windows PowerShell equivalents for JSON file creation, temp paths, line lookup, and fallback \`curl\` are in \`references/windows.md\`.
|
|
@@ -2218,6 +2264,13 @@ curl -X POST \\
|
|
|
2218
2264
|
7. Keep the review body brief (details go in inline comments)
|
|
2219
2265
|
8. If no issues: post a short approval message with no inline comments`,category:`code-hosting`},{name:`github-pr-reviewer`,description:`Create an automation that reviews GitHub pull requests when a configurable trigger label is applied. Polls one or more repositories deterministically, starts one OpenHands review conversation per label event with the pull request's head commit already checked out, and publishes the review to GitHub.`,triggers:[`/pr-reviewer:setup`],content:`# GitHub PR Reviewer Automation
|
|
2220
2266
|
|
|
2267
|
+
## Agent Canvas catalog
|
|
2268
|
+
|
|
2269
|
+
For new Agent Canvas installations, use the **GitHub code review** catalog
|
|
2270
|
+
entry. Its deterministic \`worker.py\` scanner delegates each labeled exact head
|
|
2271
|
+
to a stable conversation using the selected agent profile. The manual upload
|
|
2272
|
+
flow below remains for existing deployments and is deprecated for new installations.
|
|
2273
|
+
|
|
2221
2274
|
Create a cron automation that watches one or more GitHub repositories for pull
|
|
2222
2275
|
requests with a review trigger label, starts an OpenHands review conversation
|
|
2223
2276
|
once per label event, and publishes the AI review to GitHub.
|
|
@@ -2236,6 +2289,11 @@ checkout once the conversation has stopped. Nothing accumulates between runs.
|
|
|
2236
2289
|
|
|
2237
2290
|
---
|
|
2238
2291
|
|
|
2292
|
+
The script imports shared GitHub transport from
|
|
2293
|
+
\`scripts/github_client.py\`, installed with this skill. Include it beside
|
|
2294
|
+
\`main.py\` when packaging manually, as shown below; catalog bundles include it
|
|
2295
|
+
automatically.
|
|
2296
|
+
|
|
2239
2297
|
## Prerequisites
|
|
2240
2298
|
|
|
2241
2299
|
### Required secret
|
|
@@ -2368,9 +2426,11 @@ Use a safe string writer such as \`json.dumps(value)\` when inserting user-provi
|
|
|
2368
2426
|
repository names, labels, or style instructions into Python string literals.
|
|
2369
2427
|
\`json.dumps(list_of_repos)\` produces the whole \`REPOS\` list safely in one step.
|
|
2370
2428
|
|
|
2371
|
-
|
|
2429
|
+
Run these commands from this skill's directory and write the customized script
|
|
2430
|
+
to a temporary build directory:
|
|
2372
2431
|
\`\`\`bash
|
|
2373
2432
|
mkdir -p /tmp/pr-reviewer-build
|
|
2433
|
+
cp -L scripts/github_client.py /tmp/pr-reviewer-build/github_client.py
|
|
2374
2434
|
# write the customized main.py to /tmp/pr-reviewer-build/main.py
|
|
2375
2435
|
\`\`\`
|
|
2376
2436
|
|
|
@@ -2544,6 +2604,10 @@ On every subsequent run:
|
|
|
2544
2604
|
|
|
2545
2605
|
---
|
|
2546
2606
|
|
|
2607
|
+
The script imports shared GitHub transport from
|
|
2608
|
+
\`scripts/github_client.py\`, installed with this skill. Include it beside
|
|
2609
|
+
\`main.py\` when packaging manually, as shown below.
|
|
2610
|
+
|
|
2547
2611
|
## Prerequisites
|
|
2548
2612
|
|
|
2549
2613
|
### Required secret
|
|
@@ -2688,9 +2752,11 @@ constant substitutions near the top of the file:
|
|
|
2688
2752
|
| \`ALLOWED_GITHUB_LOGINS = ["<TOKEN_OWNER>"]\` | \`ALLOWED_GITHUB_LOGINS = {allowed_logins_list}\` |
|
|
2689
2753
|
| \`DEFAULT_OPENHANDS_URL = "http://localhost:8000"\` | \`DEFAULT_OPENHANDS_URL = "{url}"\` (keep default if the user has no preference) |
|
|
2690
2754
|
|
|
2691
|
-
|
|
2755
|
+
Run these commands from this skill's directory and write the customised script
|
|
2756
|
+
to a temporary build directory:
|
|
2692
2757
|
\`\`\`bash
|
|
2693
2758
|
mkdir -p /tmp/github-monitor-build
|
|
2759
|
+
cp -L scripts/github_client.py /tmp/github-monitor-build/github_client.py
|
|
2694
2760
|
# (write the customised main.py to /tmp/github-monitor-build/main.py)
|
|
2695
2761
|
\`\`\`
|
|
2696
2762
|
|
|
@@ -2821,7 +2887,403 @@ Each cron run executes \`main.py\`, which:
|
|
|
2821
2887
|
| Comments posted but no conversation created | Agent server URL wrong | Check \`OPENHANDS_URL\` secret and \`AGENT_SERVER_URL\` env var |
|
|
2822
2888
|
| Same comment processed twice | \`processed_comment_ids\` cleared | State file was deleted; harmless but duplicate comment may appear |
|
|
2823
2889
|
| Summary never posted | Conversation stuck in \`running\` | Open the conversation in the OpenHands UI; agent may need input |
|
|
2824
|
-
| No events detected after first run | \`last_poll\` in the future | Delete the state file to reset; it will be recreated on next run |`,category:`automations`},{name:`gitlab`,description:`Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.`,triggers:[`gitlab`],content:"You have access to an environment variable, `GITLAB_TOKEN`, which allows you to interact with\nthe GitLab API.\n\n<IMPORTANT>\nYou can use `curl` with the `GITLAB_TOKEN` to interact with GitLab's API.\nALWAYS use the GitLab API for operations instead of a web browser.\nALWAYS use the `create_mr` tool to open a merge request\n</IMPORTANT>\n\nIf you encounter authentication issues when pushing to GitLab (such as password prompts or permission errors), the old token may have expired. In such case, update the remote URL to include the current token: `git remote set-url origin https://oauth2:${GITLAB_TOKEN}@gitlab.com/username/repo.git`\n\nHere are some instructions for pushing, but ONLY do this if the user asks you to:\n* NEVER push directly to the `main` or `master` branch\n* Git config (username and email) is pre-set. Do not modify.\n* You may already be on a branch starting with `openhands-workspace`. Create a new branch with a better name before pushing.\n* Use the `create_mr` tool to create a merge request, if you haven't already\n* Once you've created your own branch or a merge request, continue to update it. Do NOT create a new one unless you are explicitly asked to. Update the PR title and description as necessary, but don't change the branch name.\n* Use the main branch as the base branch, unless the user requests otherwise\n* After opening or updating a merge request, send the user a short message with a link to the merge request.\n* Do all of the above in as few steps as possible. E.g. you could push changes with one step by running the following bash commands:\n```bash\ngit remote -v && git branch # to find the current org, repo and branch\ngit checkout -b create-widget && git add . && git commit -m \"Create widget\" && git push -u origin create-widget\n```\n\nOn Windows PowerShell, use `$env:GITLAB_TOKEN` in remote URLs and run the `git` commands as separate commands if `&&` is not supported by the installed shell.",category:`code-hosting`},{name:`
|
|
2890
|
+
| No events detected after first run | \`last_poll\` in the future | Delete the state file to reset; it will be recreated on next run |`,category:`automations`},{name:`gitlab`,description:`Interact with GitLab repositories, merge requests, and APIs using the GITLAB_TOKEN environment variable. Use when working with code hosted on GitLab or managing GitLab resources.`,triggers:[`gitlab`],content:"You have access to an environment variable, `GITLAB_TOKEN`, which allows you to interact with\nthe GitLab API.\n\n<IMPORTANT>\nYou can use `curl` with the `GITLAB_TOKEN` to interact with GitLab's API.\nALWAYS use the GitLab API for operations instead of a web browser.\nALWAYS use the `create_mr` tool to open a merge request\n</IMPORTANT>\n\nIf you encounter authentication issues when pushing to GitLab (such as password prompts or permission errors), the old token may have expired. In such case, update the remote URL to include the current token: `git remote set-url origin https://oauth2:${GITLAB_TOKEN}@gitlab.com/username/repo.git`\n\nHere are some instructions for pushing, but ONLY do this if the user asks you to:\n* NEVER push directly to the `main` or `master` branch\n* Git config (username and email) is pre-set. Do not modify.\n* You may already be on a branch starting with `openhands-workspace`. Create a new branch with a better name before pushing.\n* Use the `create_mr` tool to create a merge request, if you haven't already\n* Once you've created your own branch or a merge request, continue to update it. Do NOT create a new one unless you are explicitly asked to. Update the PR title and description as necessary, but don't change the branch name.\n* Use the main branch as the base branch, unless the user requests otherwise\n* After opening or updating a merge request, send the user a short message with a link to the merge request.\n* Do all of the above in as few steps as possible. E.g. you could push changes with one step by running the following bash commands:\n```bash\ngit remote -v && git branch # to find the current org, repo and branch\ngit checkout -b create-widget && git add . && git commit -m \"Create widget\" && git push -u origin create-widget\n```\n\nOn Windows PowerShell, use `$env:GITLAB_TOKEN` in remote URLs and run the `git` commands as separate commands if `&&` is not supported by the installed shell.",category:`code-hosting`},{name:`gitlab-issue-to-mr`,description:`Create an automation that implements GitLab issues when a configurable trigger label is applied. Polls one or more projects deterministically, clones the default branch, starts one OpenHands conversation per label event, then commits, pushes, and opens the merge request itself.`,triggers:[`/issue-to-mr:setup`],content:`# GitLab Issue to MR Automation
|
|
2891
|
+
|
|
2892
|
+
Create a cron automation that watches one or more GitLab projects for issues
|
|
2893
|
+
with a trigger label, starts an OpenHands conversation once per label event with
|
|
2894
|
+
the project's default branch already checked out, and opens a merge request with
|
|
2895
|
+
whatever the agent produced.
|
|
2896
|
+
|
|
2897
|
+
The automation script is deterministic: issue discovery, label-event tracking,
|
|
2898
|
+
state persistence, the clone, the branch, the commit, the push, the merge
|
|
2899
|
+
request, the issue comments, and the clone's removal are all handled in Python.
|
|
2900
|
+
The LLM is invoked only to write the code.
|
|
2901
|
+
|
|
2902
|
+
The agent is told **which** issue to implement, not what it says. It fetches the
|
|
2903
|
+
description, the discussion, and whatever they link to itself, so nothing in the
|
|
2904
|
+
prompt goes stale between dispatch and the moment the agent reads it.
|
|
2905
|
+
|
|
2906
|
+
That needs read access, so the conversation is handed one secret, \`GITLAB_TOKEN\`.
|
|
2907
|
+
\`AGENT_SECRET_NAMES\` stays an allow-list: the rest of the deployment's secret
|
|
2908
|
+
store is not reachable from a conversation whose instructions came from an issue.
|
|
2909
|
+
|
|
2910
|
+
The deployment's MCP servers are forwarded whole, matching \`github-pr-reviewer\`,
|
|
2911
|
+
so a connected GitLab server gives the agent typed tools rather than curl. What
|
|
2912
|
+
those servers reach is reachable from an issue-authored prompt, so connect only
|
|
2913
|
+
servers that may be driven by untrusted text.
|
|
2914
|
+
|
|
2915
|
+
The agent also finishes the job: it commits, pushes its branch, and opens the
|
|
2916
|
+
merge request, so the merge request appears when the agent stops rather than on
|
|
2917
|
+
the next poll. The script does not trust that it happened - when the conversation
|
|
2918
|
+
ends it asks GitLab whether the merge request exists, and opens it itself when it
|
|
2919
|
+
does not. \`origin\` still carries no credential, so every GitLab command the agent
|
|
2920
|
+
runs has to name \`GITLAB_TOKEN\`; the SDK only puts a secret in the environment of
|
|
2921
|
+
a command that mentions it, and masks it in the output.
|
|
2922
|
+
|
|
2923
|
+
---
|
|
2924
|
+
|
|
2925
|
+
## Prerequisites
|
|
2926
|
+
|
|
2927
|
+
### Required secret
|
|
2928
|
+
|
|
2929
|
+
Verify that the following secret is set in **OpenHands Settings -> Secrets**:
|
|
2930
|
+
|
|
2931
|
+
| Secret name | Token type | Minimum requirements |
|
|
2932
|
+
|---|---|---|
|
|
2933
|
+
| \`GITLAB_TOKEN\` | Personal access token | \`api\` scope, and at least the **Developer** role on every watched project |
|
|
2934
|
+
| \`GITLAB_TOKEN\` | Project or group access token | \`api\` scope, role **Developer** or above |
|
|
2935
|
+
|
|
2936
|
+
The \`api\` scope is what GitLab grants read and write on issues, notes, branches,
|
|
2937
|
+
and merge requests through one scope; \`read_api\` polls happily and then fails at
|
|
2938
|
+
the point of pushing. Developer is the lowest role that can push a branch and
|
|
2939
|
+
open a merge request.
|
|
2940
|
+
|
|
2941
|
+
Two things the role does not cover, and which fail the push rather than the poll:
|
|
2942
|
+
|
|
2943
|
+
- **Protected branches.** The default branch is usually protected, but the
|
|
2944
|
+
automation never pushes to it. Protect the branch prefix as well and the push
|
|
2945
|
+
is rejected; leave \`openhands/issue-*\` unprotected.
|
|
2946
|
+
- **CI/CD files.** An issue asking for a pipeline change makes the agent touch
|
|
2947
|
+
\`.gitlab-ci.yml\`. That needs no extra scope, but a project with a protected
|
|
2948
|
+
CI/CD configuration path rejects the push.
|
|
2949
|
+
|
|
2950
|
+
When several projects are monitored, the token must cover all of them.
|
|
2951
|
+
|
|
2952
|
+
Check with:
|
|
2953
|
+
\`\`\`bash
|
|
2954
|
+
curl -s "https://gitlab.com/api/v4/user" \\
|
|
2955
|
+
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \\
|
|
2956
|
+
| python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('username') or d.get('message'))"
|
|
2957
|
+
\`\`\`
|
|
2958
|
+
|
|
2959
|
+
If the token is missing or invalid, inform the user and stop.
|
|
2960
|
+
|
|
2961
|
+
---
|
|
2962
|
+
|
|
2963
|
+
## Setup Workflow
|
|
2964
|
+
|
|
2965
|
+
Follow these steps in order.
|
|
2966
|
+
|
|
2967
|
+
### Step 1 - Verify \`GITLAB_TOKEN\`
|
|
2968
|
+
|
|
2969
|
+
Run the \`curl\` check above, against the user's instance if it is not
|
|
2970
|
+
\`gitlab.com\`.
|
|
2971
|
+
|
|
2972
|
+
- If absent: *"GITLAB_TOKEN is not set. Please add it in OpenHands Settings ->
|
|
2973
|
+
Secrets."* Stop.
|
|
2974
|
+
- If the API returns \`{"message": "401 Unauthorized"}\`: tell the user the token
|
|
2975
|
+
is invalid and ask them to update it. Stop.
|
|
2976
|
+
|
|
2977
|
+
### Step 2 - Collect the GitLab API URL
|
|
2978
|
+
|
|
2979
|
+
Ask: *"Which GitLab instance? (Press Enter for gitlab.com. For a self-managed
|
|
2980
|
+
instance give its API root, e.g. \`https://gitlab.example.com/api/v4\`.)"*
|
|
2981
|
+
|
|
2982
|
+
Record as \`GITLAB_API_URL\`. Default: \`https://gitlab.com/api/v4\`. Use this URL in
|
|
2983
|
+
every check below.
|
|
2984
|
+
|
|
2985
|
+
### Step 3 - Collect projects
|
|
2986
|
+
|
|
2987
|
+
Ask: *"Which GitLab projects should be watched?
|
|
2988
|
+
(Format: \`group/project\`, e.g. \`myorg/backend\`. Subgroups are fine -
|
|
2989
|
+
\`myorg/team/service\`. List several separated by commas to serve them all from one
|
|
2990
|
+
automation.)"*
|
|
2991
|
+
|
|
2992
|
+
Validate access to **each** project, and confirm the token's role:
|
|
2993
|
+
\`\`\`bash
|
|
2994
|
+
PROJECT_ID=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "{group}/{project}")
|
|
2995
|
+
curl -s "\${GITLAB_API_URL}/projects/\${PROJECT_ID}" \\
|
|
2996
|
+
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \\
|
|
2997
|
+
| python3 -c "
|
|
2998
|
+
import json, sys
|
|
2999
|
+
d = json.load(sys.stdin)
|
|
3000
|
+
if 'message' in d or 'error' in d:
|
|
3001
|
+
print('ERROR:', d.get('message') or d.get('error'))
|
|
3002
|
+
else:
|
|
3003
|
+
perms = d.get('permissions') or {}
|
|
3004
|
+
levels = [(perms.get(k) or {}).get('access_level') for k in ('project_access', 'group_access')]
|
|
3005
|
+
levels = [n for n in levels if isinstance(n, int)]
|
|
3006
|
+
role = max(levels) if levels else 'unknown'
|
|
3007
|
+
print(f\\"Accessible. Default branch: {d.get('default_branch')}. Access level: {role}\\")
|
|
3008
|
+
"
|
|
3009
|
+
\`\`\`
|
|
3010
|
+
|
|
3011
|
+
Record every accepted project into \`PROJECTS = ["{group}/{project}", ...]\`. If
|
|
3012
|
+
one project fails the check, say which and ask whether to continue without it.
|
|
3013
|
+
An access level below \`30\` (Developer) means the automation cannot open merge
|
|
3014
|
+
requests there; ask for a token with a higher role.
|
|
3015
|
+
|
|
3016
|
+
Each project is polled independently and keeps its own state, so issue numbers
|
|
3017
|
+
never collide between them. The trigger label, branch prefix, and schedule are
|
|
3018
|
+
shared; a project needing different settings wants its own automation.
|
|
3019
|
+
|
|
3020
|
+
### Step 4 - Collect trigger label
|
|
3021
|
+
|
|
3022
|
+
Ask: *"Which issue label should trigger an implementation?
|
|
3023
|
+
(Press Enter for the default: \`openhands\`.)"*
|
|
3024
|
+
|
|
3025
|
+
Record the answer as \`TRIGGER_LABEL\`. If the label does not exist yet, tell the
|
|
3026
|
+
user that GitLab will still record the event once the label is created and
|
|
3027
|
+
applied to an issue.
|
|
3028
|
+
|
|
3029
|
+
The automation works an issue when it sees the latest matching label event for
|
|
3030
|
+
that label. To ask for another attempt later, remove and re-apply the label -
|
|
3031
|
+
that opens a second branch and a second merge request rather than overwriting the
|
|
3032
|
+
first.
|
|
3033
|
+
|
|
3034
|
+
### Step 5 - Collect the merge request mode
|
|
3035
|
+
|
|
3036
|
+
Ask: *"Should the merge requests be opened as drafts?
|
|
3037
|
+
1. Draft (default) - title prefixed \`Draft:\`, ready for a human to mark ready
|
|
3038
|
+
2. Ready for review - opened as a normal merge request
|
|
3039
|
+
(Press Enter for Draft)"*
|
|
3040
|
+
|
|
3041
|
+
Map the choice to \`DRAFT_MERGE_REQUEST\` (\`True\` or \`False\`). GitLab has no draft
|
|
3042
|
+
flag on the merge request API; a draft is a title carrying the \`Draft: \` prefix,
|
|
3043
|
+
which the script adds.
|
|
3044
|
+
|
|
3045
|
+
### Step 6 - Collect the branch prefix
|
|
3046
|
+
|
|
3047
|
+
Ask: *"What branch prefix should the automation use?
|
|
3048
|
+
(Press Enter for the default: \`openhands/issue\`, which produces
|
|
3049
|
+
\`openhands/issue-42\`.)"*
|
|
3050
|
+
|
|
3051
|
+
Record as \`BRANCH_PREFIX\`. Keep it free of spaces and of characters git rejects
|
|
3052
|
+
in a ref name, and make sure the prefix is not covered by a protected-branch
|
|
3053
|
+
rule.
|
|
3054
|
+
|
|
3055
|
+
### Step 7 - Collect cron schedule
|
|
3056
|
+
|
|
3057
|
+
Ask: *"How often should the automation poll for labelled issues?
|
|
3058
|
+
(Press Enter for the default: every 5 minutes.
|
|
3059
|
+
Use a cron expression for a different interval, e.g. \`0 * * * *\` = hourly)"*
|
|
3060
|
+
|
|
3061
|
+
Default: \`*/5 * * * *\`.
|
|
3062
|
+
|
|
3063
|
+
Record as \`CRON_SCHEDULE\`.
|
|
3064
|
+
|
|
3065
|
+
### Step 8 - Confirm the secret scope
|
|
3066
|
+
|
|
3067
|
+
The agent is handed \`GITLAB_TOKEN\`, because it reads the issue and its discussion
|
|
3068
|
+
itself. Ask: *"Beyond the GitLab token, does the project's build need a secret of
|
|
3069
|
+
its own - a package registry token, for example? (Press Enter for none.)"*
|
|
3070
|
+
|
|
3071
|
+
Record the answers appended to the default, as
|
|
3072
|
+
\`AGENT_SECRET_NAMES = ["GITLAB_TOKEN", "NAME", ...]\`.
|
|
3073
|
+
|
|
3074
|
+
Keep it an allow-list. Forwarding the whole secret store would put every
|
|
3075
|
+
credential in the deployment behind a prompt written by whoever opened the issue.
|
|
3076
|
+
If the projects are public and you would rather the conversation held no
|
|
3077
|
+
credential at all, set the list to \`[]\` - the agent can still read a public issue
|
|
3078
|
+
unauthenticated, and private projects then stop working.
|
|
3079
|
+
|
|
3080
|
+
The deployment's MCP servers are a separate matter: they are forwarded whole, so
|
|
3081
|
+
the conversation can reach everything they expose. Say so, and check the user is
|
|
3082
|
+
willing to have those servers driven by text written by whoever opened an issue.
|
|
3083
|
+
Removing a server from the deployment's MCP settings is the only way to keep it
|
|
3084
|
+
out of these conversations.
|
|
3085
|
+
|
|
3086
|
+
### Step 9 - Generate the automation script
|
|
3087
|
+
|
|
3088
|
+
Read \`scripts/main.py\` from this skill's directory. Apply exactly six constant
|
|
3089
|
+
substitutions near the top of the file:
|
|
3090
|
+
|
|
3091
|
+
> The script also reads a \`config.json\` shipped beside it, if there is one, over
|
|
3092
|
+
> these constants. That is how the catalog entry
|
|
3093
|
+
> (\`automations/catalog/gitlab-issue-to-mr/\`) configures an unmodified copy,
|
|
3094
|
+
> since a declarative host cannot rewrite Python. This setup path substitutes the
|
|
3095
|
+
> constants and ships no \`config.json\`, so the two never collide.
|
|
3096
|
+
|
|
3097
|
+
| Placeholder | Replace with |
|
|
3098
|
+
|---|---|
|
|
3099
|
+
| \`PROJECTS = ["group/project"]\` | \`PROJECTS = ["{group_project}", ...]\` - one entry per project collected in Step 3 |
|
|
3100
|
+
| \`TRIGGER_LABEL = "openhands"\` | \`TRIGGER_LABEL = "{trigger_label}"\` |
|
|
3101
|
+
| \`BRANCH_PREFIX = "openhands/issue"\` | \`BRANCH_PREFIX = "{branch_prefix}"\` |
|
|
3102
|
+
| \`DRAFT_MERGE_REQUEST = True\` | \`DRAFT_MERGE_REQUEST = {True or False}\` |
|
|
3103
|
+
| \`GITLAB_API_URL = "https://gitlab.com/api/v4"\` | \`GITLAB_API_URL = "{gitlab_api_url}"\` |
|
|
3104
|
+
| \`AGENT_SECRET_NAMES: list[str] = ["GITLAB_TOKEN"]\` | \`AGENT_SECRET_NAMES: list[str] = ["{name}", ...]\` |
|
|
3105
|
+
|
|
3106
|
+
Leave \`MAX_NEW_PER_RUN\` and \`DEFAULT_OPENHANDS_URL\` alone unless the user asks
|
|
3107
|
+
for a different cap or a non-default OpenHands URL.
|
|
3108
|
+
|
|
3109
|
+
A project may be given as \`group/project\`, as a clone URL, or as an SSH remote;
|
|
3110
|
+
the script normalizes each one at startup and names the value it could not read
|
|
3111
|
+
rather than blaming the token. Subgroups are preserved.
|
|
3112
|
+
|
|
3113
|
+
Use a safe string writer such as \`json.dumps(value)\` when inserting user-provided
|
|
3114
|
+
project paths, labels, or prefixes into Python string literals.
|
|
3115
|
+
\`json.dumps(list_of_projects)\` produces the whole \`PROJECTS\` list safely in one
|
|
3116
|
+
step.
|
|
3117
|
+
|
|
3118
|
+
Write the customized script to a temporary build directory:
|
|
3119
|
+
\`\`\`bash
|
|
3120
|
+
mkdir -p /tmp/issue-to-mr-build
|
|
3121
|
+
# write the customized main.py to /tmp/issue-to-mr-build/main.py
|
|
3122
|
+
\`\`\`
|
|
3123
|
+
|
|
3124
|
+
Validate syntax before packaging:
|
|
3125
|
+
\`\`\`bash
|
|
3126
|
+
python3 -m py_compile /tmp/issue-to-mr-build/main.py && echo "Syntax OK"
|
|
3127
|
+
\`\`\`
|
|
3128
|
+
|
|
3129
|
+
Fix any syntax errors before proceeding.
|
|
3130
|
+
|
|
3131
|
+
### Step 10 - Package and upload
|
|
3132
|
+
|
|
3133
|
+
Determine the Automation backend URL and auth from the \`<RUNTIME_SERVICES>\`
|
|
3134
|
+
block in your system context:
|
|
3135
|
+
- **OPENHANDS_HOST**: the Automation backend \`url_from_agent\`
|
|
3136
|
+
- **Auth**: \`X-Session-API-Key: $OPENHANDS_AUTOMATION_API_KEY\`
|
|
3137
|
+
|
|
3138
|
+
\`\`\`bash
|
|
3139
|
+
tar -czf /tmp/issue-to-mr.tar.gz -C /tmp/issue-to-mr-build .
|
|
3140
|
+
|
|
3141
|
+
TARBALL_PATH=$(curl -s -X POST \\
|
|
3142
|
+
"\${OPENHANDS_HOST}/api/automation/v1/uploads?name=gitlab-issue-to-mr" \\
|
|
3143
|
+
-H "X-Session-API-Key: $OPENHANDS_AUTOMATION_API_KEY" \\
|
|
3144
|
+
-H "Content-Type: application/gzip" \\
|
|
3145
|
+
--data-binary @/tmp/issue-to-mr.tar.gz \\
|
|
3146
|
+
| python3 -c "import json,sys; print(json.load(sys.stdin)['tarball_path'])")
|
|
3147
|
+
|
|
3148
|
+
echo "Uploaded: $TARBALL_PATH"
|
|
3149
|
+
\`\`\`
|
|
3150
|
+
|
|
3151
|
+
### Step 11 - Register the automation
|
|
3152
|
+
|
|
3153
|
+
\`\`\`bash
|
|
3154
|
+
curl -s -X POST "\${OPENHANDS_HOST}/api/automation/v1" \\
|
|
3155
|
+
-H "X-Session-API-Key: $OPENHANDS_AUTOMATION_API_KEY" \\
|
|
3156
|
+
-H "Content-Type: application/json" \\
|
|
3157
|
+
-d "{
|
|
3158
|
+
\\"name\\": \\"GitLab Issue to MR: {project_summary} label {trigger_label}\\",
|
|
3159
|
+
\\"trigger\\": {\\"type\\": \\"cron\\", \\"schedule\\": \\"{cron_schedule}\\"},
|
|
3160
|
+
\\"tarball_path\\": \\"$TARBALL_PATH\\",
|
|
3161
|
+
\\"entrypoint\\": \\"python3 main.py\\",
|
|
3162
|
+
\\"timeout\\": 900
|
|
3163
|
+
}" | python3 -m json.tool
|
|
3164
|
+
\`\`\`
|
|
3165
|
+
|
|
3166
|
+
Use the single project as \`{project_summary}\` when there is one, and something
|
|
3167
|
+
like \`3 projects\` when there are several. A poll clones a project per queued
|
|
3168
|
+
issue and pushes finished branches, so the timeout allows for that; a run never
|
|
3169
|
+
waits for an agent to finish, only for it to be started.
|
|
3170
|
+
|
|
3171
|
+
Record the returned \`id\`.
|
|
3172
|
+
|
|
3173
|
+
### Step 12 - Confirm
|
|
3174
|
+
|
|
3175
|
+
Tell the user:
|
|
3176
|
+
|
|
3177
|
+
> ✅ **GitLab Issue to MR** is running!
|
|
3178
|
+
>
|
|
3179
|
+
> - Automation ID: \`{id}\`
|
|
3180
|
+
> - Projects: \`{group}/{project}\`, ... (one line each)
|
|
3181
|
+
> - GitLab API: \`{gitlab_api_url}\`
|
|
3182
|
+
> - Trigger label: \`{trigger_label}\`
|
|
3183
|
+
> - Branch prefix: \`{branch_prefix}\`
|
|
3184
|
+
> - Merge requests: \`{draft or ready for review}\`
|
|
3185
|
+
> - Polling schedule: \`{cron_schedule}\`
|
|
3186
|
+
> - State file per project:
|
|
3187
|
+
> \`~/.openhands/workspaces/automation-state/gitlab_issue_to_mr_{id}_{group}__{project}.json\`
|
|
3188
|
+
>
|
|
3189
|
+
> Apply the \`{trigger_label}\` label to an issue to queue an implementation. Each
|
|
3190
|
+
> label event is processed once. To ask for another attempt, remove and re-apply
|
|
3191
|
+
> the label - that opens a second branch and merge request.
|
|
3192
|
+
>
|
|
3193
|
+
> The agent runs without a checkout credential; the automation pushes the branch
|
|
3194
|
+
> and opens the merge request once the agent has stopped.
|
|
3195
|
+
|
|
3196
|
+
---
|
|
3197
|
+
|
|
3198
|
+
## Runtime Behaviour (per poll)
|
|
3199
|
+
|
|
3200
|
+
Each cron run executes \`main.py\`, which loads \`config.json\` if the catalog
|
|
3201
|
+
shipped one, checks that \`git\` is available, resolves and validates \`GITLAB_TOKEN\`
|
|
3202
|
+
once, then processes every project in \`PROJECTS\` independently. One project
|
|
3203
|
+
failing does not stop the others; the run fails only if every project fails.
|
|
3204
|
+
|
|
3205
|
+
For each project:
|
|
3206
|
+
|
|
3207
|
+
1. Loads that project's state (see \`references/state-schema.md\`) and reads its
|
|
3208
|
+
default branch and clone URL.
|
|
3209
|
+
2. Lists open issues carrying \`TRIGGER_LABEL\`, newest-updated first. GitLab keeps
|
|
3210
|
+
merge requests on their own endpoint, so labelling a merge request never
|
|
3211
|
+
queues an implementation.
|
|
3212
|
+
3. For each labelled issue, up to \`MAX_NEW_PER_RUN\` new ones per run:
|
|
3213
|
+
- Refetches the issue so a label removed since the listing does not start work.
|
|
3214
|
+
- Finds the latest matching resource label event with \`action: "add"\`, and
|
|
3215
|
+
skips it if that event has already been tracked.
|
|
3216
|
+
- Picks the first free branch name, \`{BRANCH_PREFIX}-{iid}\` or a numbered
|
|
3217
|
+
variant of it.
|
|
3218
|
+
- Clones the default branch, shallow and single-branch, into
|
|
3219
|
+
\`{WORKSPACE_BASE}/issue-to-mr/{group}__{project}/issue-{iid}-{event_id}\`,
|
|
3220
|
+
sets the commit identity, and creates the branch. \`origin\` keeps its plain
|
|
3221
|
+
HTTPS URL, so the workspace holds no credential.
|
|
3222
|
+
- Starts an OpenHands conversation **whose working directory is that clone**,
|
|
3223
|
+
told which issue to read, with the secrets named in \`AGENT_SECRET_NAMES\`
|
|
3224
|
+
and the deployment's MCP servers attached.
|
|
3225
|
+
- Comments on the issue with the branch, the label event, and the conversation
|
|
3226
|
+
link.
|
|
3227
|
+
- Records the task with \`status: "active"\`.
|
|
3228
|
+
- If the clone or the conversation cannot be created, the clone is removed and
|
|
3229
|
+
nothing is recorded, so the next poll retries the label event.
|
|
3230
|
+
4. For each active task:
|
|
3231
|
+
- Abandons a conversation that has not reached a terminal status within two
|
|
3232
|
+
hours, comments on the issue, and reclaims its clone.
|
|
3233
|
+
- When the conversation reaches \`idle\`, \`finished\`, \`error\`, or \`stuck\`:
|
|
3234
|
+
- Adopts the merge request the agent opened, if GitLab says one exists for
|
|
3235
|
+
the branch, and comments its link on the issue. Everything below is the
|
|
3236
|
+
path taken when it does not.
|
|
3237
|
+
- Skips the merge request if the issue was closed meanwhile.
|
|
3238
|
+
- Reports the problem on the issue if the conversation ended in \`error\` or
|
|
3239
|
+
\`stuck\`.
|
|
3240
|
+
- Commits whatever the agent left uncommitted, on top of any commits it made
|
|
3241
|
+
itself.
|
|
3242
|
+
- Posts the agent's answer on the issue, and opens no merge request, when
|
|
3243
|
+
there are no commits at all - that is how an agent reports an issue too
|
|
3244
|
+
ambiguous to implement.
|
|
3245
|
+
- Otherwise pushes the branch, opens the merge request (draft by default,
|
|
3246
|
+
titled \`Draft: [#42] <issue title>\`, with the agent's summary and
|
|
3247
|
+
\`Closes #42\` in the description), and comments the link on the issue.
|
|
3248
|
+
- A push or merge request that fails is retried on the next two polls before
|
|
3249
|
+
the task is reported as failed, so a transient GitLab error does not throw
|
|
3250
|
+
the work away.
|
|
3251
|
+
5. Removes the clone of every finished task, but only after confirming the
|
|
3252
|
+
conversation has stopped - deleting it under a running agent would remove its
|
|
3253
|
+
working directory. When that cannot be confirmed the directory is left alone
|
|
3254
|
+
and the next poll tries again.
|
|
3255
|
+
6. Saves that project's state atomically.
|
|
3256
|
+
|
|
3257
|
+
The completion callback fires once for the whole run.
|
|
3258
|
+
|
|
3259
|
+
---
|
|
3260
|
+
|
|
3261
|
+
## Additional Resources
|
|
3262
|
+
|
|
3263
|
+
- **\`references/state-schema.md\`** - State JSON schema, field definitions, and the
|
|
3264
|
+
task lifecycle.
|
|
3265
|
+
- **\`scripts/main.py\`** - The complete automation script. Customize the six
|
|
3266
|
+
constants at the top before packaging.
|
|
3267
|
+
|
|
3268
|
+
---
|
|
3269
|
+
|
|
3270
|
+
## Troubleshooting
|
|
3271
|
+
|
|
3272
|
+
| Symptom | Likely cause | Fix |
|
|
3273
|
+
|---|---|---|
|
|
3274
|
+
| Nothing is ever queued | Trigger label not present, or applied to a merge request rather than an issue | Apply the configured label to an issue |
|
|
3275
|
+
| "401 Unauthorized" in run logs | Token expired | Rotate and update \`GITLAB_TOKEN\` |
|
|
3276
|
+
| "The token's role on ... is below Developer" | The token has Reporter or Guest on that project | Grant Developer or above, or drop the project from \`PROJECTS\` |
|
|
3277
|
+
| Push rejected: "You are not allowed to push code to protected branches" | The branch prefix is covered by a protected-branch rule | Leave \`{BRANCH_PREFIX}-*\` unprotected |
|
|
3278
|
+
| Push rejected on \`.gitlab-ci.yml\` | The project protects its CI/CD configuration path | Allow the token's role to update it, or exclude such issues |
|
|
3279
|
+
| 404 on project access | Project path wrong, or no access | Re-check the entry in \`PROJECTS\` and the token's role. Subgroups must be included in full |
|
|
3280
|
+
| \`git is not available in the automation runtime\` | The runtime image has no git | Use a runtime image that ships git; the script clones, commits, and pushes with it |
|
|
3281
|
+
| Issue commented "did not change any code" | The agent judged the issue too ambiguous, or made no edits | Read its answer in the comment, add the missing detail to the issue, then re-apply the label |
|
|
3282
|
+
| Same issue not picked up again after new comments | Its label event was already processed | Remove and re-apply the trigger label |
|
|
3283
|
+
| Agent reports it cannot push or open an MR | By design - it has no push credentials in \`origin\` | No action; the automation pushes and opens the merge request after the agent stops |
|
|
3284
|
+
| \`Warning: could not fetch MCP config\` in run logs | The settings endpoint was unreachable | Non-fatal; the agent falls back to the REST calls in the prompt |
|
|
3285
|
+
| A backlog of labelled issues starts slowly | \`MAX_NEW_PER_RUN\` caps how many conversations one poll starts | Wait for the next polls, or raise the cap in the script |
|
|
3286
|
+
| Clones remain under \`issue-to-mr/\` | Their conversations had not stopped yet | They are removed by a later poll once the conversation is terminal |`,category:`automations`},{name:`incident-retrospective`,description:`Create an automation that drafts incident retrospectives. Gathers incident-channel messages from Slack, collects linked tickets and follow-ups from Linear, and publishes a retrospective draft to Notion with a timeline, impact summary, root-cause hypotheses, and action items.`,triggers:[`/incident-retro:setup`],content:`# Incident Retrospective Drafter Automation
|
|
2825
3287
|
|
|
2826
3288
|
Set up an automation that drafts incident retrospectives by pulling data from
|
|
2827
3289
|
Slack, Linear, and Notion.
|
|
@@ -4928,7 +5390,7 @@ The agent server typically runs inside a **sandbox** (a Docker or Kubernetes con
|
|
|
4928
5390
|
|---|---|---|
|
|
4929
5391
|
| \`RUNTIME_URL\` | Ambient in cloud environments | Public-facing URL of the **agent server** sandbox. Use this to determine whether external webhook delivery is possible — if unset or local, webhooks cannot be received. The automation service may run at a separate URL (see Determining the API Host). |
|
|
4930
5392
|
| \`AGENT_SERVER_URL\` | Injected into scripts at run time only | Internal URL of the agent server. Available inside script execution context; **not** an ambient environment variable outside of a running script. |
|
|
4931
|
-
| \`OPENHANDS_HOST\` | Shell convention only — set manually | Base URL for the automation service API. **Not a real environment variable.** Set it from
|
|
5393
|
+
| \`OPENHANDS_HOST\` | Shell convention only — set manually | Base URL for the automation service API. **Not a real environment variable.** Set it from an explicit host, a detected local Agent Canvas server, or the cloud default. Used in all \`curl\` examples throughout this skill. |
|
|
4932
5394
|
|
|
4933
5395
|
> **⚠️ CRITICAL — Agent behavior rules:**
|
|
4934
5396
|
>
|
|
@@ -4993,11 +5455,17 @@ Entrypoint must be \`python3 main.py\` (no \`setup.sh\` needed). Wrap your main
|
|
|
4993
5455
|
|
|
4994
5456
|
## Authentication
|
|
4995
5457
|
|
|
4996
|
-
All requests require
|
|
5458
|
+
All requests require authentication:
|
|
4997
5459
|
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5460
|
+
- Cloud (default \`https://app.all-hands.dev\`): Bearer token:
|
|
5461
|
+
|
|
5462
|
+
\`-H "Authorization: Bearer \${OPENHANDS_API_KEY}"\`
|
|
5463
|
+
|
|
5464
|
+
- Local Agent Canvas (\`http://localhost:8001\`): session API key through \`X-Session-API-Key\`:
|
|
5465
|
+
|
|
5466
|
+
\`-H "X-Session-API-Key: \${OPENHANDS_AUTOMATION_API_KEY:-\${SESSION_API_KEY}}"\`
|
|
5467
|
+
|
|
5468
|
+
The curl examples below show cloud Bearer authentication. For local Agent Canvas, replace that header with the \`X-Session-API-Key\` header above.
|
|
5001
5469
|
|
|
5002
5470
|
## API Endpoints
|
|
5003
5471
|
|
|
@@ -5007,14 +5475,18 @@ All requests require Bearer authentication:
|
|
|
5007
5475
|
|
|
5008
5476
|
The automation service may run at a different URL from the agent server. In the examples throughout this skill, \`\${OPENHANDS_HOST}\` is a shell-variable convention for the automation service base URL — it is **not** a real environment variable. Set it from context before running any curl command:
|
|
5009
5477
|
|
|
5010
|
-
- Look for a \`<HOST>\` value in the system prompt. If present, use that URL.
|
|
5478
|
+
- Look for a \`<HOST>\` value in the system prompt or runtime-services block. If present, use that URL.
|
|
5479
|
+
- If running inside a local Agent Canvas stack and no explicit host is provided, use \`http://localhost:8001\` for the local automation/agent-server API.
|
|
5011
5480
|
- Otherwise default to \`https://app.all-hands.dev\`.
|
|
5012
5481
|
|
|
5482
|
+
For a local Agent Canvas server, validate the endpoint before making a mutating request and authenticate with the session key through \`X-Session-API-Key\` when that API requires it. Do not use the cloud default merely because no \`<HOST>\` value is present.
|
|
5483
|
+
|
|
5013
5484
|
\`\`\`bash
|
|
5014
|
-
|
|
5485
|
+
# Choose the host that matches the detected environment:
|
|
5486
|
+
OPENHANDS_HOST="http://localhost:8001" # local Agent Canvas
|
|
5487
|
+
# OPENHANDS_HOST="https://app.all-hands.dev" # OpenHands Cloud
|
|
5015
5488
|
\`\`\`
|
|
5016
5489
|
|
|
5017
|
-
|
|
5018
5490
|
### Automation Endpoints
|
|
5019
5491
|
|
|
5020
5492
|
| Endpoint | Method | Description |
|
|
@@ -5766,233 +6238,328 @@ See \`references/security.md\` — also covers narrowing triggers and sender-lev
|
|
|
5766
6238
|
- **\`references/custom-automation.md\`** — Detailed guide for custom automations: tarball uploads, code structure (SDK and no-LLM), state persistence via the KV store, environment variables, validation rules, and complete examples. Consult this whenever you need to evaluate or recommend the custom path (including for deterministic / cost-sensitive tasks per rule 0). Only *implement* a custom automation after the user agrees to that path.
|
|
5767
6239
|
- **\`references/ab-testing.md\`** — A/B testing for plugin automations: defining variants with weights, experiment configuration, variant selection logic, observability via conversation tags, and complete examples. Consult this when a user wants to compare plugin versions or configurations.
|
|
5768
6240
|
- **\`references/security.md\`** — Trust boundaries: untrusted content vs. verified sender, least-privilege secrets, trigger scoping, sender authorization, pre-deploy verification. Consult whenever an automation handles external input or forwards secrets to a spawned conversation.
|
|
5769
|
-
- **\`references/security.md\`** — Trust boundaries for automations: untrusted event content vs. verified sender, least-privilege secret scoping for spawned conversations, narrowing triggers, sender-level authorization, and verifying a script actually runs before deploying it. Consult this whenever an automation handles external/untrusted input (GitHub issues/PRs, Slack messages, any public-facing webhook) or forwards secrets to a spawned conversation.`,category:`automations`,defaultEnabled:!0},{name:`openhands-
|
|
6241
|
+
- **\`references/security.md\`** — Trust boundaries for automations: untrusted event content vs. verified sender, least-privilege secret scoping for spawned conversations, narrowing triggers, sender-level authorization, and verifying a script actually runs before deploying it. Consult this whenever an automation handles external/untrusted input (GitHub issues/PRs, Slack messages, any public-facing webhook) or forwards secrets to a spawned conversation.`,category:`automations`,defaultEnabled:!0},{name:`openhands-enterprise-troubleshooting`,description:`This skill should be used when a user reports an issue with OpenHands Enterprise (OHE) on a self-hosted (Replicated VM-based) installation. Use for diagnosing sandbox startup failures, auth issues, certificate errors, LLM connectivity problems, Keycloak login issues, Replicated Admin Console access, upgrade failures, or resource exhaustion. Helps triage symptoms, run diagnostic commands, guide through recovery steps, generate and analyze Replicated support bundles offline, and produce escalation handoffs.`,triggers:[`openhands enterprise`,`OHE troubleshooting`,`openhands not working`,`sandbox failed`,`replicated admin console`,`keycloak login`,`certificate error`,`LLM connectivity`,`upgrade failed`,`support bundle`,`openhands install`],content:`# OpenHands Enterprise Troubleshooting
|
|
5770
6242
|
|
|
5771
|
-
|
|
6243
|
+
This skill helps diagnose and resolve common issues on OpenHands Enterprise (OHE) self-hosted installations using Replicated. It covers triage, guided recovery, support bundle generation, and escalation handoffs.
|
|
5772
6244
|
|
|
5773
|
-
|
|
5774
|
-
the "OpenHands Software Agent SDK" section.
|
|
6245
|
+
## Diagnostic Workflow
|
|
5775
6246
|
|
|
5776
|
-
|
|
6247
|
+
When a user reports an OHE issue:
|
|
5777
6248
|
|
|
5778
|
-
|
|
6249
|
+
1. **Collect symptoms** - Ask user to describe what they see, error messages, when it started
|
|
6250
|
+
2. **Identify failure mode** - Match symptoms to one of the common issues below
|
|
6251
|
+
3. **Run targeted diagnostics** - Use commands in \`references/diagnostics.md\`
|
|
6252
|
+
4. **Guide recovery** - Follow resolution steps for the identified issue, one at a time
|
|
6253
|
+
5. **Verify fix** - Confirm the original symptom is gone, not just that the last command succeeded
|
|
6254
|
+
6. **Generate handoff** - If unresolved, produce a clear summary for the OpenHands team
|
|
5779
6255
|
|
|
5780
|
-
|
|
5781
|
-
|
|
6256
|
+
Take recovery one step at a time. Before each step, state what it will change and what you expect to
|
|
6257
|
+
see afterwards; after it, run the check that confirms it before moving on. If the check fails or
|
|
6258
|
+
shows something unexpected, stop and re-diagnose — a step applied on top of a failed one buries the
|
|
6259
|
+
evidence, and several applied blind can leave the install worse than the fault you started with.
|
|
6260
|
+
Destructive steps (restarts, rollbacks, config changes) need the user's agreement first, and are
|
|
6261
|
+
worth recording as you go so the handoff can say exactly what was changed.
|
|
5782
6262
|
|
|
5783
|
-
from
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
6263
|
+
Work from whatever the user has. A described symptom starts at step 1; a support bundle goes to
|
|
6264
|
+
[Analyzing the Support Bundle](#analyzing-the-support-bundle). If they paste raw log output, the
|
|
6265
|
+
triage method in
|
|
6266
|
+
[\`references/support-bundle-analysis.md\`](references/support-bundle-analysis.md#triaging-a-log-file)
|
|
6267
|
+
applies to pasted text as well as to files, and notes what a hand-picked excerpt can hide.
|
|
5787
6268
|
|
|
6269
|
+
## Common Failure Modes
|
|
5788
6270
|
|
|
5789
|
-
|
|
5790
|
-
model=os.getenv("LLM_MODEL", "gpt-5.5"),
|
|
5791
|
-
api_key=os.getenv("LLM_API_KEY"),
|
|
5792
|
-
base_url=os.getenv("LLM_BASE_URL", None),
|
|
5793
|
-
)
|
|
6271
|
+
### 1. Sandbox Fails to Start / Timeout
|
|
5794
6272
|
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
6273
|
+
**Symptoms:**
|
|
6274
|
+
- Conversation hangs then times out
|
|
6275
|
+
- "Sandbox failed to start" error
|
|
6276
|
+
- A timeout in the logs. Read the actual value rather than assuming one: the timeouts in
|
|
6277
|
+
\`runtime-api\` are configurable and differ between the Kubernetes client and the app, so quoting a
|
|
6278
|
+
fixed number back to a customer is how you end up chasing the wrong one.
|
|
6279
|
+
|
|
6280
|
+
**Diagnosis:** Check sandbox service status, the \`sysbox-runc\` RuntimeClass and its containerd
|
|
6281
|
+
runtime, resource availability
|
|
5803
6282
|
|
|
5804
|
-
|
|
5805
|
-
conversation = Conversation(agent=agent, workspace=cwd)
|
|
6283
|
+
**Reference:** See \`references/diagnostics.md\` - Section "Sandbox Startup"
|
|
5806
6284
|
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
6285
|
+
### 2. Git Provider Auth Broken
|
|
6286
|
+
|
|
6287
|
+
**Symptoms:**
|
|
6288
|
+
- "Authentication failed" for the configured provider
|
|
6289
|
+
- Can't clone or push repos
|
|
6290
|
+
- The provider shows as disconnected
|
|
6291
|
+
|
|
6292
|
+
**Diagnosis:** Check the provider's secret in Kubernetes and that the provider is enabled. GitHub,
|
|
6293
|
+
GitLab, Bitbucket Data Center, and Azure DevOps are each configured separately — confirm which one
|
|
6294
|
+
the user is actually on before diagnosing
|
|
6295
|
+
|
|
6296
|
+
**Reference:** See \`references/diagnostics.md\` - Section "Git Provider Auth"
|
|
6297
|
+
|
|
6298
|
+
### 3. Certificate Errors
|
|
6299
|
+
|
|
6300
|
+
**Symptoms:**
|
|
6301
|
+
- "certificate expired" or "self-signed certificate" errors
|
|
6302
|
+
- TLS handshake failures
|
|
6303
|
+
- Browser shows insecure connection warning
|
|
6304
|
+
|
|
6305
|
+
**Diagnosis:** Check cert expiry, certificate chain, ingress configuration
|
|
6306
|
+
|
|
6307
|
+
**Reference:** See \`references/diagnostics.md\` - Section "Certificate Issues"
|
|
6308
|
+
|
|
6309
|
+
### 4. LLM Connectivity Failures
|
|
6310
|
+
|
|
6311
|
+
**Symptoms:**
|
|
6312
|
+
- "LLM endpoint unreachable"
|
|
6313
|
+
- "Authentication failed" for LLM API
|
|
6314
|
+
- Conversations fail to start
|
|
6315
|
+
|
|
6316
|
+
**Diagnosis:** Check LLM endpoint URL, API key secrets, network policies
|
|
6317
|
+
|
|
6318
|
+
**Reference:** See \`references/diagnostics.md\` - Section "LLM Connectivity"
|
|
6319
|
+
|
|
6320
|
+
### 5. Keycloak Login Issues
|
|
6321
|
+
|
|
6322
|
+
**Symptoms:**
|
|
6323
|
+
- Can't access admin console
|
|
6324
|
+
- Login loop or "invalid credentials"
|
|
6325
|
+
- Keycloak pod showing errors
|
|
6326
|
+
|
|
6327
|
+
**Diagnosis:** Check Keycloak pod status, database connectivity, realm configuration
|
|
6328
|
+
|
|
6329
|
+
**Reference:** See \`references/diagnostics.md\` - Section "Keycloak"
|
|
6330
|
+
|
|
6331
|
+
### 6. Replicated Admin Console Unreachable
|
|
6332
|
+
|
|
6333
|
+
**Symptoms:**
|
|
6334
|
+
- Can't access admin console URL
|
|
6335
|
+
- Connection refused or timeout
|
|
6336
|
+
- Browser shows "site cannot be reached"
|
|
6337
|
+
|
|
6338
|
+
**Diagnosis:** Check Replicated operator pod, ingress, service endpoints
|
|
6339
|
+
|
|
6340
|
+
**Reference:** See \`references/diagnostics.md\` - Section "Replicated Admin Console"
|
|
6341
|
+
|
|
6342
|
+
### 7. Upgrade Stuck or Failed
|
|
6343
|
+
|
|
6344
|
+
**Symptoms:**
|
|
6345
|
+
- Replicated shows upgrade as "failed"
|
|
6346
|
+
- Pods in crash loop after upgrade
|
|
6347
|
+
- Migration jobs failing
|
|
6348
|
+
|
|
6349
|
+
**Diagnosis:** Check failed job logs, resource availability, pre-flight failures
|
|
6350
|
+
|
|
6351
|
+
**Reference:** See \`references/diagnostics.md\` - Section "Upgrade Issues"
|
|
6352
|
+
|
|
6353
|
+
### 8. OOM / Resource Exhaustion
|
|
6354
|
+
|
|
6355
|
+
**Symptoms:**
|
|
6356
|
+
- Pods being OOMKilled
|
|
6357
|
+
- "Too many open files" errors
|
|
6358
|
+
- Services becoming unresponsive
|
|
6359
|
+
|
|
6360
|
+
**Diagnosis:** Check node resources (memory, disk, file descriptors)
|
|
6361
|
+
|
|
6362
|
+
**Reference:** See \`references/diagnostics.md\` - Section "Resource Exhaustion"
|
|
6363
|
+
|
|
6364
|
+
## Diagnostic Commands Quick Reference
|
|
6365
|
+
|
|
6366
|
+
Access the VM and run these common commands.
|
|
6367
|
+
|
|
6368
|
+
**An empty result never means "healthy".** \`kubectl get pods -l <selector>\` prints \`No resources
|
|
6369
|
+
found\` and exits 0 both when a component is down and when the selector is wrong, so the two are
|
|
6370
|
+
indistinguishable. When you need to know whether something is running, ask its Deployment or
|
|
6371
|
+
StatefulSet for a READY count instead — that object exists either way, and \`0/1\` means down while a
|
|
6372
|
+
\`NotFound\` error means you had the name wrong.
|
|
6373
|
+
|
|
6374
|
+
\`\`\`bash
|
|
6375
|
+
# Is it up? READY answers this; an empty pod list does not.
|
|
6376
|
+
kubectl get deploy,statefulset -n openhands
|
|
6377
|
+
|
|
6378
|
+
# Check overall pod status
|
|
6379
|
+
kubectl get pods -n openhands
|
|
6380
|
+
|
|
6381
|
+
# View pod logs (replace POD_NAME)
|
|
6382
|
+
kubectl logs -n openhands POD_NAME
|
|
6383
|
+
kubectl logs -n openhands POD_NAME --previous
|
|
6384
|
+
|
|
6385
|
+
# Describe a pod for events
|
|
6386
|
+
kubectl describe pod -n openhands POD_NAME
|
|
6387
|
+
|
|
6388
|
+
# Check resource usage
|
|
6389
|
+
kubectl top nodes
|
|
6390
|
+
kubectl top pods -n openhands
|
|
6391
|
+
|
|
6392
|
+
# Check certificate expiry
|
|
6393
|
+
echo | openssl s_client -connect HOST:443 2>/dev/null | openssl x509 -noout -dates
|
|
6394
|
+
|
|
6395
|
+
# Check the Replicated components. On Embedded Cluster these are the Admin
|
|
6396
|
+
# Console in \`kotsadm\`, the operator in \`embedded-cluster\`, and the Replicated
|
|
6397
|
+
# SDK in \`openhands\` under app.kubernetes.io/name=replicated. A \`replicated\`
|
|
6398
|
+
# namespace belongs to the older kURL topology and is absent here.
|
|
6399
|
+
kubectl get pods -n kotsadm
|
|
6400
|
+
kubectl get pods -n embedded-cluster
|
|
6401
|
+
kubectl get pods -n openhands -l app.kubernetes.io/name=replicated
|
|
5810
6402
|
\`\`\`
|
|
5811
6403
|
|
|
5812
|
-
##
|
|
6404
|
+
## Support Bundle Generation
|
|
6405
|
+
|
|
6406
|
+
When the issue requires deeper investigation — or before escalating — generate a support bundle. It
|
|
6407
|
+
captures both host- and cluster-level state in one archive.
|
|
6408
|
+
|
|
6409
|
+
### Generating the Support Bundle
|
|
6410
|
+
|
|
6411
|
+
SSH to the VM, then from the directory containing the installer binary:
|
|
6412
|
+
|
|
6413
|
+
\`\`\`bash
|
|
6414
|
+
sudo ./openhands support-bundle
|
|
6415
|
+
\`\`\`
|
|
5813
6416
|
|
|
5814
|
-
|
|
6417
|
+
This uses the default Embedded Cluster spec to collect cluster- *and* host-level information, and
|
|
6418
|
+
automatically includes the OpenHands application-specific collectors. Run it on a **controller
|
|
6419
|
+
node** — on a non-controller node it cannot capture cluster-wide information.
|
|
6420
|
+
|
|
6421
|
+
For Embedded Cluster versions earlier than 1.17.0, use the support-bundle plugin from within the
|
|
6422
|
+
cluster shell instead:
|
|
6423
|
+
|
|
6424
|
+
\`\`\`bash
|
|
6425
|
+
sudo ./openhands shell
|
|
6426
|
+
kubectl support-bundle --load-cluster-specs /var/lib/embedded-cluster/support/host-support-bundle.yaml
|
|
6427
|
+
\`\`\`
|
|
6428
|
+
|
|
6429
|
+
The bundle is written to the working directory as \`support-bundle-<UTC timestamp>.tar.gz\`. Share it
|
|
6430
|
+
with the OpenHands team, or analyze it directly with the steps below.
|
|
6431
|
+
|
|
6432
|
+
Support bundles carry potentially sensitive data. Replicated's redactor masks common secret patterns
|
|
6433
|
+
as \`***HIDDEN***\`, but it is not a guarantee — hostnames, user and installation identifiers, and
|
|
6434
|
+
config values routinely survive it. Treat a bundle as confidential, send it only through the channel
|
|
6435
|
+
the OpenHands team gives you, and avoid pasting raw excerpts into public issues or chats.
|
|
6436
|
+
|
|
6437
|
+
### Analyzing the Support Bundle
|
|
6438
|
+
|
|
6439
|
+
**Full guide: [\`references/support-bundle-analysis.md\`](references/support-bundle-analysis.md).**
|
|
6440
|
+
Read it before drawing conclusions — the bundle's layout is not what you would guess from \`kubectl\`,
|
|
6441
|
+
and several of its gaps produce convincing false negatives.
|
|
6442
|
+
|
|
6443
|
+
Fast path — the bundled triage script reconstructs the standard first pass (cluster meta, analyzer
|
|
6444
|
+
results, pod table, OOM and restart scan, \`top\` equivalent, allocatable headroom, events) in one
|
|
6445
|
+
command. It reports; the ranking and the diagnosis are yours to make:
|
|
6446
|
+
|
|
6447
|
+
\`\`\`bash
|
|
6448
|
+
tar -xzf support-bundle-2026-07-28T06_54_18.tar.gz
|
|
6449
|
+
python3 scripts/bundle_triage.py support-bundle-2026-07-28T06_54_18
|
|
6450
|
+
\`\`\`
|
|
6451
|
+
|
|
6452
|
+
You are reading this bundle because something is broken, so treat a clean run as "not here" rather
|
|
6453
|
+
than "nothing wrong" — the script sees pod objects, analyzer verdicts, node conditions and resource
|
|
6454
|
+
totals, and reads no application logs at all. \`references/support-bundle-analysis.md\` has a section
|
|
6455
|
+
on where to look next when the objects come back clean.
|
|
6456
|
+
|
|
6457
|
+
Then the four things that most often answer the question outright:
|
|
6458
|
+
|
|
6459
|
+
| Question | Where to look |
|
|
5815
6460
|
|---|---|
|
|
5816
|
-
|
|
|
5817
|
-
|
|
|
5818
|
-
|
|
|
5819
|
-
|
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
-
|
|
5848
|
-
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
- [
|
|
5887
|
-
- [
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
- [
|
|
5900
|
-
- [
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
- [\`
|
|
5909
|
-
- [\`
|
|
5910
|
-
-
|
|
5911
|
-
- [
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
- [\`20_stuck_detector.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/20_stuck_detector.py)
|
|
5918
|
-
- [\`21_generate_extraneous_conversation_costs.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/21_generate_extraneous_conversation_costs.py)
|
|
5919
|
-
- [\`22_anthropic_thinking.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/22_anthropic_thinking.py)
|
|
5920
|
-
- [\`23_responses_reasoning.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/23_responses_reasoning.py)
|
|
5921
|
-
- [\`24_planning_agent_workflow.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/24_planning_agent_workflow.py)
|
|
5922
|
-
- [\`25_agent_delegation.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/25_agent_delegation.py)
|
|
5923
|
-
- [\`26_custom_visualizer.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/26_custom_visualizer.py)
|
|
5924
|
-
- [\`27_observability_laminar.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/27_observability_laminar.py)
|
|
5925
|
-
- [\`28_ask_agent_example.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/28_ask_agent_example.py)
|
|
5926
|
-
- [\`29_llm_streaming.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/29_llm_streaming.py)
|
|
5927
|
-
- [\`30_tom_agent.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/30_tom_agent.py)
|
|
5928
|
-
- [\`31_iterative_refinement.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/31_iterative_refinement.py)
|
|
5929
|
-
- [\`32_configurable_security_policy.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/32_configurable_security_policy.py)
|
|
5930
|
-
- [\`33_hooks\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/33_hooks)
|
|
5931
|
-
- [\`34_critic_example.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/34_critic_example.py)
|
|
5932
|
-
- [\`35_subscription_login.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/35_subscription_login.py)
|
|
5933
|
-
- [\`36_event_json_to_openai_messages.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/36_event_json_to_openai_messages.py)
|
|
5934
|
-
- [\`37_llm_profile_store\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/37_llm_profile_store)
|
|
5935
|
-
- [\`38_browser_session_recording.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/38_browser_session_recording.py)
|
|
5936
|
-
- [\`39_llm_fallback.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/39_llm_fallback.py)
|
|
5937
|
-
- [\`40_acp_agent_example.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/40_acp_agent_example.py)
|
|
5938
|
-
- [\`41_task_tool_set.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/41_task_tool_set.py)
|
|
5939
|
-
- [\`42_file_based_subagents.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/42_file_based_subagents.py)
|
|
5940
|
-
- [\`44_model_switching_in_convo.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/44_model_switching_in_convo.py)
|
|
5941
|
-
- [\`45_parallel_tool_execution.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/45_parallel_tool_execution.py)
|
|
5942
|
-
- [\`46_agent_settings.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/46_agent_settings.py)
|
|
5943
|
-
- [\`47_defense_in_depth_security.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/47_defense_in_depth_security.py)
|
|
5944
|
-
- [\`48_conversation_fork.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/48_conversation_fork.py)
|
|
5945
|
-
- [\`49_switch_llm_tool.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/49_switch_llm_tool.py)
|
|
5946
|
-
- [\`50_async_cancellation.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/50_async_cancellation.py)
|
|
5947
|
-
- [\`51_agent_hooks\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/51_agent_hooks)
|
|
5948
|
-
- [\`52_dynamic_workflow.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/52_dynamic_workflow.py)
|
|
5949
|
-
- [\`53_client_defined_tools.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/53_client_defined_tools.py)
|
|
5950
|
-
- [\`54_goal_completion_loop.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/54_goal_completion_loop.py)
|
|
5951
|
-
- [\`55_persistent_memory.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/55_persistent_memory.py)
|
|
5952
|
-
- [\`56_structured_output.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/56_structured_output.py)
|
|
5953
|
-
- [\`57_prompt_hooks\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/57_prompt_hooks)
|
|
5954
|
-
- [\`58_ask_oracle_tool\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/58_ask_oracle_tool)
|
|
5955
|
-
|
|
5956
|
-
### [\`02_remote_agent_server/\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server)
|
|
5957
|
-
|
|
5958
|
-
- [\`01_convo_with_local_agent_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/01_convo_with_local_agent_server.py)
|
|
5959
|
-
- [\`02_convo_with_docker_sandboxed_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/02_convo_with_docker_sandboxed_server.py)
|
|
5960
|
-
- [\`03_browser_use_with_docker_sandboxed_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/03_browser_use_with_docker_sandboxed_server.py)
|
|
5961
|
-
- [\`04_convo_with_api_sandboxed_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/04_convo_with_api_sandboxed_server.py)
|
|
5962
|
-
- [\`05_vscode_with_docker_sandboxed_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/05_vscode_with_docker_sandboxed_server.py)
|
|
5963
|
-
- [\`06_custom_tool\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/06_custom_tool)
|
|
5964
|
-
- [\`07_convo_with_cloud_workspace.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/07_convo_with_cloud_workspace.py)
|
|
5965
|
-
- [\`08_convo_with_apptainer_sandboxed_server.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/08_convo_with_apptainer_sandboxed_server.py)
|
|
5966
|
-
- [\`09_acp_agent_with_remote_runtime.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py)
|
|
5967
|
-
- [\`10_cloud_workspace_share_credentials.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/10_cloud_workspace_share_credentials.py)
|
|
5968
|
-
- [\`11_conversation_fork.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/11_conversation_fork.py)
|
|
5969
|
-
- [\`12_settings_and_secrets_api.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/12_settings_and_secrets_api.py)
|
|
5970
|
-
- [\`13_workspace_get_llm.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/13_workspace_get_llm.py)
|
|
5971
|
-
- [\`14_client_defined_tools.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/14_client_defined_tools.py)
|
|
5972
|
-
- [\`15_openai_compatible_gateway.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/15_openai_compatible_gateway.py)
|
|
5973
|
-
- [\`16_deferred_init.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/16_deferred_init.py)
|
|
5974
|
-
- [\`hook_scripts\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/hook_scripts)
|
|
5975
|
-
- [\`scripts\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/scripts)
|
|
5976
|
-
|
|
5977
|
-
### [\`03_github_workflows/\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows)
|
|
5978
|
-
|
|
5979
|
-
- [\`01_basic_action\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/01_basic_action)
|
|
5980
|
-
- [\`02_pr_review\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/02_pr_review)
|
|
5981
|
-
- [\`03_todo_management\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/03_todo_management)
|
|
5982
|
-
- [\`04_datadog_debugging\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/04_datadog_debugging)
|
|
5983
|
-
- [\`05_posthog_debugging\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/05_posthog_debugging)
|
|
5984
|
-
|
|
5985
|
-
### [\`04_llm_specific_tools/\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/04_llm_specific_tools)
|
|
5986
|
-
|
|
5987
|
-
- [\`01_gpt5_apply_patch_preset.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/04_llm_specific_tools/01_gpt5_apply_patch_preset.py)
|
|
5988
|
-
- [\`02_gemini_file_tools.py\`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/04_llm_specific_tools/02_gemini_file_tools.py)
|
|
5989
|
-
|
|
5990
|
-
### [\`05_skills_and_plugins/\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins)
|
|
5991
|
-
|
|
5992
|
-
- [\`01_loading_agentskills\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/01_loading_agentskills)
|
|
5993
|
-
- [\`02_loading_plugins\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/02_loading_plugins)
|
|
5994
|
-
- [\`03_managing_installed_skills\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/03_managing_installed_skills)
|
|
5995
|
-
- [\`04_mixed_marketplace_skills\`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/04_mixed_marketplace_skills)`,category:`agent-authoring`,defaultEnabled:!0},{name:`pdflatex`,description:`Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.`,triggers:[`pdflatex`],content:`PdfLatex is a tool that converts Latex sources into PDF. This is specifically very important for researchers, as they use it to publish their findings. It could be installed very easily using Linux terminal, though this seems an annoying task on Windows. Installation commands are given below.
|
|
6461
|
+
| What did the collector already conclude? | \`analysis.json\` — pre-computed verdicts, highest-value file in the bundle |
|
|
6462
|
+
| What is each pod actually doing? | \`cluster-resources/pods/<namespace>.json\` |
|
|
6463
|
+
| What did a container log? | \`cluster-resources/pods/logs/<ns>/<pod>/<container>.log\` |
|
|
6464
|
+
| What is the install running? | \`kots/admin_console/app-info.json\` — version, channel, sequence |
|
|
6465
|
+
|
|
6466
|
+
Four traps worth knowing before you start:
|
|
6467
|
+
|
|
6468
|
+
- **Never use file mtimes for timing.** They record when you extracted the archive. Take the capture
|
|
6469
|
+
time from the bundle directory name, which is UTC.
|
|
6470
|
+
- **Log filenames are container names, not pod names.** Init-container failures (\`migrate-db\`,
|
|
6471
|
+
\`wait-for-db\`) are invisible to \`kubectl logs <pod>\` and are the easiest real failure to miss.
|
|
6472
|
+
- **\`***HIDDEN***\` means "redacted", not "unset".** The redactor over-redacts, including non-secrets.
|
|
6473
|
+
- **Check a log's format before filtering it.** Most bundle logs are plain text, not JSON, and \`jq\`
|
|
6474
|
+
aborts on the first non-JSON line — so a severity filter can print nothing on a file full of
|
|
6475
|
+
errors. Prefix with \`grep '^{'\`, and read the non-JSON lines separately.
|
|
6476
|
+
|
|
6477
|
+
Once triage points at a failure mode, use \`references/diagnostics.md\` for that mode's specific
|
|
6478
|
+
commands and error patterns.
|
|
6479
|
+
|
|
6480
|
+
### Summarizing the Bundle: Most Likely Root Cause
|
|
6481
|
+
|
|
6482
|
+
The script reports; deciding which of its observations explains the user's symptom is your job. Work
|
|
6483
|
+
through its output in this order, because it is roughly the order in which a finding is likely to be
|
|
6484
|
+
the actual cause rather than a side effect.
|
|
6485
|
+
|
|
6486
|
+
**1. Start from the symptom and the clock, not from the output.** Get the capture time from the
|
|
6487
|
+
bundle directory name (UTC) and establish when the user says it broke. A finding that predates the
|
|
6488
|
+
symptom by weeks is background; one that starts within the window is a candidate. Ages in the pod
|
|
6489
|
+
table are the cheapest way to place an event in time.
|
|
6490
|
+
|
|
6491
|
+
**2. Read \`analysis.json\` first — but not literally.** The collector's own verdicts are the
|
|
6492
|
+
highest-value content in the bundle. Two cautions when reading them through the script: everything
|
|
6493
|
+
non-passing prints under a \`FAIL\` heading, including \`warn\`-severity entries that may be advisory,
|
|
6494
|
+
so check the severity in \`analysis.json\` before calling one a failure; and per-object analyzers are
|
|
6495
|
+
collapsed into families with one example each, so \`[x12]\` means twelve objects affected and the
|
|
6496
|
+
example shown is arbitrary. Open the file directly before quoting an analyzer verdict to a customer.
|
|
6497
|
+
|
|
6498
|
+
**3. Rank what remains by how directly it explains the symptom.** In descending order of
|
|
6499
|
+
usefulness — a container in \`CrashLoopBackOff\` or actively OOM-killed right now; a pod that never
|
|
6500
|
+
started (\`Pending\`, \`CreateContainerConfigError\`, an init container that never completed); a pod
|
|
6501
|
+
that is \`Running\` but not \`Ready\`, which fails a health check and takes traffic out of rotation; a
|
|
6502
|
+
node condition that is genuinely bad; and resource pressure, which is usually a consequence rather
|
|
6503
|
+
than a cause. A recovered termination — visible only as \`lastState\` with an older age — explains a
|
|
6504
|
+
past blip, not a live outage; do not lead with one.
|
|
6505
|
+
|
|
6506
|
+
**4. Prefer the cause nearest the symptom.** A failed \`migrate-db\` init container and an app pod
|
|
6507
|
+
stuck \`Pending\` are one finding, not two, and the init container is the one to report. When several
|
|
6508
|
+
findings share a timestamp, look for the common dependency rather than listing all of them.
|
|
6509
|
+
|
|
6510
|
+
**5. Say what you ruled out.** The script reads pod objects, analyzer verdicts, node conditions and
|
|
6511
|
+
resource totals — and no application logs. If nothing in the objects explains the symptom, that is
|
|
6512
|
+
itself a result: it puts the cause in the application logs, in the network path, or outside the
|
|
6513
|
+
cluster. Name which, rather than reporting that the bundle looked healthy.
|
|
6514
|
+
|
|
6515
|
+
State the conclusion with its evidence and its confidence — the object or analyzer it rests on, and
|
|
6516
|
+
whether it explains the reported symptom or merely coincides with it. A ranked shortlist of two or
|
|
6517
|
+
three candidates is more useful than a single confident guess, and it drops straight into the
|
|
6518
|
+
**Likely Root Cause** field of the handoff template below.
|
|
6519
|
+
|
|
6520
|
+
## Escalation Handoff Template
|
|
6521
|
+
|
|
6522
|
+
When an issue cannot be resolved, produce this summary:
|
|
6523
|
+
|
|
6524
|
+
\`\`\`
|
|
6525
|
+
## Issue Summary
|
|
6526
|
+
**Problem:** [One-line description]
|
|
6527
|
+
**Duration:** [When it started]
|
|
6528
|
+
**Impact:** [Who is affected]
|
|
6529
|
+
|
|
6530
|
+
## Symptoms Observed
|
|
6531
|
+
- [Symptom 1]
|
|
6532
|
+
- [Symptom 2]
|
|
6533
|
+
|
|
6534
|
+
## Diagnostic Steps Taken
|
|
6535
|
+
1. [Step 1]
|
|
6536
|
+
2. [Step 2]
|
|
6537
|
+
|
|
6538
|
+
## Logs / Evidence
|
|
6539
|
+
\`\`\`
|
|
6540
|
+
[Relevant log excerpts]
|
|
6541
|
+
\`\`\`
|
|
6542
|
+
|
|
6543
|
+
## Resolution Attempts
|
|
6544
|
+
- [Attempt 1] - [Result]
|
|
6545
|
+
- [Attempt 2] - [Result]
|
|
6546
|
+
|
|
6547
|
+
## Likely Root Cause
|
|
6548
|
+
[Analysis]
|
|
6549
|
+
\`\`\`
|
|
6550
|
+
|
|
6551
|
+
## Additional Resources
|
|
6552
|
+
|
|
6553
|
+
- **Diagnostic Reference:** [\`references/diagnostics.md\`](references/diagnostics.md) — detailed commands and log interpretation for each failure mode
|
|
6554
|
+
- **Support Bundle Analysis:** [\`references/support-bundle-analysis.md\`](references/support-bundle-analysis.md) — reading a bundle offline: file map, interpretation traps, known gaps
|
|
6555
|
+
- **Triage Script:** \`scripts/bundle_triage.py\` — offline first-pass triage, standard library only
|
|
6556
|
+
- **Replicated Docs:** [Generating support bundles for Embedded Cluster](https://docs.replicated.com/vendor/support-bundle-embedded)
|
|
6557
|
+
|
|
6558
|
+
## Maintenance
|
|
6559
|
+
|
|
6560
|
+
As new failure modes are discovered in the field, add them to this skill. Update
|
|
6561
|
+
\`references/diagnostics.md\` with new patterns and resolution steps, and add the offline equivalent to
|
|
6562
|
+
\`references/support-bundle-analysis.md\` when the failure is diagnosable from a bundle.`,category:`integrations`},{name:`openhands-sdk`,description:`Reference skill for the OpenHands Software Agent SDK - the Python framework for building AI agents that write software. Use when you need to build agents with the SDK, create custom tools, configure LLMs, manage conversations, delegate to sub-agents, or deploy agents locally or remotely.`,triggers:[`openhands-sdk`,`openhands sdk`,`software-agent-sdk`,`agent-sdk`,`/sdk`],content:'# OpenHands Software Agent SDK\n\nAll SDK documentation lives at <https://docs.openhands.dev/sdk>.\n\nFor the full topic index, fetch <https://docs.openhands.dev/llms.txt> and read\nthe "OpenHands Software Agent SDK" section.\n\n## Quick reference\n\nInstall: `pip install openhands-sdk openhands-tools`\n\n```python\nimport os\n\nfrom openhands.sdk import LLM, Agent, Conversation, Tool\nfrom openhands.tools.file_editor import FileEditorTool\nfrom openhands.tools.task_tracker import TaskTrackerTool\nfrom openhands.tools.terminal import TerminalTool\n\n\nllm = LLM(\n model=os.getenv("LLM_MODEL", "gpt-5.5"),\n api_key=os.getenv("LLM_API_KEY"),\n base_url=os.getenv("LLM_BASE_URL", None),\n)\n\nagent = Agent(\n llm=llm,\n tools=[\n Tool(name=TerminalTool.name),\n Tool(name=FileEditorTool.name),\n Tool(name=TaskTrackerTool.name),\n ],\n)\n\ncwd = os.getcwd()\nconversation = Conversation(agent=agent, workspace=cwd)\n\nconversation.send_message("Write 3 facts about the current project into FACTS.txt.")\nconversation.run()\nprint("All done!")\n```\n\n## Core classes (`openhands.sdk`)\n\n| Class | Purpose |\n|---|---|\n| [`Agent`](https://docs.openhands.dev/sdk/arch/agent.md) | Reasoning-action loop |\n| [`Condenser`](https://docs.openhands.dev/sdk/arch/condenser.md) | Conversation history compression system |\n| [`Conversation`](https://docs.openhands.dev/sdk/arch/conversation.md) | Conversation orchestration system |\n| [`Event`](https://docs.openhands.dev/sdk/arch/events.md) | Typed event framework |\n| [`LLM`](https://docs.openhands.dev/sdk/arch/llm.md) | Provider-agnostic language model interface |\n| [`SecurityAnalyzer`](https://docs.openhands.dev/sdk/arch/security.md) | Action security analysis and validation |\n| [`Skill`](https://docs.openhands.dev/sdk/arch/skill.md) | Reusable prompt system |\n| [`Tool / ToolDefinition`](https://docs.openhands.dev/sdk/arch/tool-system.md) | Action-observation tool framework |\n| [`Workspace`](https://docs.openhands.dev/sdk/arch/workspace.md) | Execution environment abstraction |\n\n## API reference\n\n[`openhands.sdk.agent`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.agent.md), [`openhands.sdk.conversation`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.conversation.md), [`openhands.sdk.event`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.event.md), [`openhands.sdk.llm`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.llm.md), [`openhands.sdk.security`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.security.md), [`openhands.sdk.tool`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.tool.md), [`openhands.sdk.utils`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.utils.md), [`openhands.sdk.workspace`](https://docs.openhands.dev/sdk/api-reference/openhands.sdk.workspace.md)\n\n## Guides\n\n- [ACP Agent](https://docs.openhands.dev/sdk/guides/agent-acp.md): Delegate to an ACP-compatible server (Claude Code, Gemini CLI, etc.) instead of calling an LLM directly.\n- [Agent Settings](https://docs.openhands.dev/sdk/guides/agent-settings.md): Configure, serialize, and recreate agents from structured settings.\n- [Agent Skills & Context](https://docs.openhands.dev/sdk/guides/skill.md): Skills add specialized behaviors, domain knowledge, and context-aware triggers to your agent through structured prompts.\n- [API-based Sandbox](https://docs.openhands.dev/sdk/guides/agent-server/api-sandbox.md): Connect to hosted API-based agent server for fully managed infrastructure.\n- [Apptainer Sandbox](https://docs.openhands.dev/sdk/guides/agent-server/apptainer-sandbox.md): Run agent server in rootless Apptainer containers for HPC and shared computing environments.\n- [Ask Agent Questions](https://docs.openhands.dev/sdk/guides/convo-ask-agent.md): Get sidebar replies from the agent during conversation execution without interrupting the main flow.\n- [Assign Reviews](https://docs.openhands.dev/sdk/guides/github-workflows/assign-reviews.md): Automate PR management with intelligent reviewer assignment and workflow notifications using OpenHands Agent\n- [Browser Session Recording](https://docs.openhands.dev/sdk/guides/browser-session-recording.md): Record and replay your agent\'s browser sessions using rrweb.\n- [Browser Use](https://docs.openhands.dev/sdk/guides/agent-browser-use.md): Enable web browsing and interaction capabilities for your agent.\n- [Context Condenser](https://docs.openhands.dev/sdk/guides/context-condenser.md): Manage agent memory by condensing conversation history to save tokens.\n- [Conversation Goals](https://docs.openhands.dev/sdk/guides/agent-server/conversation-goals.md): Add a resumable goal strategy to a normal agent-server conversation.\n- [Conversation with Async](https://docs.openhands.dev/sdk/guides/convo-async.md): Use async/await for concurrent agent operations and non-blocking execution.\n- [Creating Custom Agent](https://docs.openhands.dev/sdk/guides/agent-custom.md): Learn how to design specialized agents with custom tool sets\n- [Critic (Experimental)](https://docs.openhands.dev/sdk/guides/critic.md): Real-time evaluation of agent actions using an LLM-based critic model, with built-in iterative refinement.\n- [Custom Tools](https://docs.openhands.dev/sdk/guides/custom-tools.md): Tools define what agents can do. The SDK includes built-in tools for common operations and supports creating custom tools for specialized needs.\n- [Custom Tools with Remote Agent Server](https://docs.openhands.dev/sdk/guides/agent-server/custom-tools.md): Learn how to use custom tools with a remote agent server by building a custom base image that includes your tool implementations.\n- [Custom Visualizer](https://docs.openhands.dev/sdk/guides/convo-custom-visualizer.md): Customize conversation visualization by creating custom visualizers or configuring the default visualizer.\n- [Deferred Init (Warm-Pool)](https://docs.openhands.dev/sdk/guides/agent-server/deferred-init.md): Pre-warm agent-server pods before a user is matched, then activate them at runtime with POST /api/init.\n- [Docker Sandbox](https://docs.openhands.dev/sdk/guides/agent-server/docker-sandbox.md): Run agent server in isolated Docker containers for security and reproducibility.\n- [Exception Handling](https://docs.openhands.dev/sdk/guides/llm-error-handling.md): Provider‑agnostic exceptions raised by the SDK and recommended patterns for handling them.\n- [FAQ](https://docs.openhands.dev/sdk/faq.md): Frequently asked questions about the OpenHands SDK\n- [File-Based Agents](https://docs.openhands.dev/sdk/guides/agent-file-based.md): Define specialized sub-agents as simple Markdown files with YAML frontmatter — no Python code required.\n- [Fork a Conversation](https://docs.openhands.dev/sdk/guides/convo-fork.md): Branch off an existing conversation for follow-up exploration without contaminating the original.\n- [Getting Started](https://docs.openhands.dev/sdk/getting-started.md): Install the OpenHands SDK and build AI agents that write software.\n- [Goal Completion Loop](https://docs.openhands.dev/sdk/guides/convo-goal.md): Drive a conversation toward a verifiable objective with a judge-driven, self-continuing completion loop.\n- [GPT-5 Preset (ApplyPatchTool)](https://docs.openhands.dev/sdk/guides/llm-gpt5-preset.md): Use the GPT-5 preset to build an agent that swaps the standard FileEditorTool for ApplyPatchTool.\n- [Hello World](https://docs.openhands.dev/sdk/guides/hello-world.md): The simplest possible OpenHands agent - configure an LLM, create an agent, and complete a task.\n- [Hooks](https://docs.openhands.dev/sdk/guides/hooks.md): Use lifecycle hooks to observe, log, and customize agent execution.\n- [Image Input](https://docs.openhands.dev/sdk/guides/llm-image-input.md): Send images to multimodal agents for vision-based tasks and analysis.\n- [Interactive Terminal](https://docs.openhands.dev/sdk/guides/agent-interactive-terminal.md): Enable agents to interact with terminal applications like ipython, python REPL, and other interactive CLI tools.\n- [Iterative Refinement](https://docs.openhands.dev/sdk/guides/iterative-refinement.md): Implement iterative refinement workflows where agents refine their work based on critique feedback until quality thresholds are met.\n- [LLM Fallback Strategy](https://docs.openhands.dev/sdk/guides/llm-fallback.md): Automatically try alternate LLMs when the primary model fails with a transient error.\n- [LLM Profile Store](https://docs.openhands.dev/sdk/guides/llm-profile-store.md): Save, load, and manage reusable LLM configurations so you never repeat setup code again.\n- [LLM Registry](https://docs.openhands.dev/sdk/guides/llm-registry.md): Dynamically select and configure language models using the LLM registry.\n- [LLM Streaming](https://docs.openhands.dev/sdk/guides/llm-streaming.md): Stream LLM responses token-by-token for real-time display and interactive user experiences.\n- [LLM Subscriptions](https://docs.openhands.dev/sdk/guides/llm-subscriptions.md): Use your ChatGPT Plus/Pro subscription to access Codex models without consuming API credits.\n- [Local Agent Server](https://docs.openhands.dev/sdk/guides/agent-server/local-server.md): Install and run an OpenHands Agent Server on your machine, then connect to it from the SDK.\n- [Metrics Tracking](https://docs.openhands.dev/sdk/guides/metrics.md): Track token usage, costs, and latency metrics for your agents.\n- [Model Context Protocol](https://docs.openhands.dev/sdk/guides/mcp.md): Model Context Protocol (MCP) enables dynamic tool integration from external servers. Agents can discover and use MCP-provided tools automatically.\n- [Model Routing](https://docs.openhands.dev/sdk/guides/llm-routing.md): Route agent\'s LLM requests to different models.\n- [Observability & Tracing](https://docs.openhands.dev/sdk/guides/observability.md): Enable OpenTelemetry tracing to monitor and debug your agent\'s execution with tools like Laminar, MLflow, Honeycomb, or any OTLP-compatible backend.\n- [OpenAI-Compatible Endpoint](https://docs.openhands.dev/sdk/guides/agent-server/openai-gateway.md): Call an OpenHands agent-server through the OpenAI Chat Completions protocol.\n- [OpenHands Cloud Workspace](https://docs.openhands.dev/sdk/guides/agent-server/cloud-workspace.md): Connect to OpenHands Cloud for fully managed sandbox environments with optional SaaS credential inheritance.\n- [Overview](https://docs.openhands.dev/sdk/guides/agent-server/overview.md): Run agents on remote servers with isolated workspaces for production deployments.\n- [Parallel Tool Execution](https://docs.openhands.dev/sdk/guides/parallel-tool-execution.md): Execute multiple tools concurrently within a single LLM response to improve throughput for independent operations.\n- [Pause and Resume](https://docs.openhands.dev/sdk/guides/convo-pause-and-resume.md): Pause agent execution, perform operations, and resume without losing state.\n- [Persistence](https://docs.openhands.dev/sdk/guides/convo-persistence.md): Save and restore conversation state for multi-session workflows.\n- [Persistent Memory](https://docs.openhands.dev/sdk/guides/persistent-memory.md): Give agents opt-in, two-tier memory that survives across conversations.\n- [Plugins](https://docs.openhands.dev/sdk/guides/plugins.md): Plugins bundle skills, hooks, MCP servers, agents, and commands into reusable packages that extend agent capabilities.\n- [PR Review](https://docs.openhands.dev/sdk/guides/github-workflows/pr-review.md): Use OpenHands Agent to generate meaningful pull request review\n- [Reasoning](https://docs.openhands.dev/sdk/guides/llm-reasoning.md): Access model reasoning traces from Anthropic extended thinking and OpenAI responses API.\n- [Secret Registry](https://docs.openhands.dev/sdk/guides/secrets.md): Provide environment variables and secrets to agent workspace securely.\n- [Security & Action Confirmation](https://docs.openhands.dev/sdk/guides/security.md): Control agent action execution through confirmation policy and security analyzer.\n- [Send Message While Running](https://docs.openhands.dev/sdk/guides/convo-send-message-while-running.md): Interrupt running agents to provide additional context or corrections.\n- [Software Agent SDK](https://docs.openhands.dev/sdk.md): Build AI agents that write software. A clean, modular SDK with production-ready tools.\n- [Stuck Detector](https://docs.openhands.dev/sdk/guides/agent-stuck-detector.md): Detect and handle stuck agents automatically with timeout mechanisms.\n- [Task Tool Set](https://docs.openhands.dev/sdk/guides/task-tool-set.md): Delegate complex work to specialized sub-agents that run synchronously and return results to the parent agent.\n- [Theory of Mind (TOM) Agent](https://docs.openhands.dev/sdk/guides/agent-tom-agent.md): Enable your agent to understand user intent and preferences through Theory of Mind capabilities, providing personalized guidance based on user modeling.\n- [TODO Management](https://docs.openhands.dev/sdk/guides/github-workflows/todo-management.md): Implement TODOs using OpenHands Agent\n\n## Examples\n\nSource: [`examples/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples)\n\n### [`01_standalone_sdk/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk)\n\n- [`01_hello_world.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/01_hello_world.py)\n- [`02_custom_tools.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/02_custom_tools.py)\n- [`03_activate_skill.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/03_activate_skill.py)\n- [`04_confirmation_mode_example.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/04_confirmation_mode_example.py)\n- [`05_use_llm_registry.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/05_use_llm_registry.py)\n- [`06_interactive_terminal_w_reasoning.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/06_interactive_terminal_w_reasoning.py)\n- [`07_mcp_integration.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/07_mcp_integration.py)\n- [`08_mcp_with_oauth.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/08_mcp_with_oauth.py)\n- [`09_pause_example.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/09_pause_example.py)\n- [`10_persistence.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/10_persistence.py)\n- [`11_async.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/11_async.py)\n- [`12_custom_secrets.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/12_custom_secrets.py)\n- [`13_get_llm_metrics.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/13_get_llm_metrics.py)\n- [`14_context_condenser.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/14_context_condenser.py)\n- [`15_browser_use.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/15_browser_use.py)\n- [`16_llm_security_analyzer.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/16_llm_security_analyzer.py)\n- [`17_image_input.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/17_image_input.py)\n- [`18_send_message_while_processing.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/18_send_message_while_processing.py)\n- [`19_llm_routing.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/19_llm_routing.py)\n- [`20_stuck_detector.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/20_stuck_detector.py)\n- [`21_generate_extraneous_conversation_costs.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/21_generate_extraneous_conversation_costs.py)\n- [`22_anthropic_thinking.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/22_anthropic_thinking.py)\n- [`23_responses_reasoning.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/23_responses_reasoning.py)\n- [`24_planning_agent_workflow.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/24_planning_agent_workflow.py)\n- [`25_agent_delegation.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/25_agent_delegation.py)\n- [`26_custom_visualizer.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/26_custom_visualizer.py)\n- [`27_observability_laminar.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/27_observability_laminar.py)\n- [`28_ask_agent_example.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/28_ask_agent_example.py)\n- [`29_llm_streaming.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/29_llm_streaming.py)\n- [`30_tom_agent.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/30_tom_agent.py)\n- [`31_iterative_refinement.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/31_iterative_refinement.py)\n- [`32_configurable_security_policy.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/32_configurable_security_policy.py)\n- [`33_hooks`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/33_hooks)\n- [`34_critic_example.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/34_critic_example.py)\n- [`35_subscription_login.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/35_subscription_login.py)\n- [`36_event_json_to_openai_messages.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/36_event_json_to_openai_messages.py)\n- [`37_llm_profile_store`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/37_llm_profile_store)\n- [`38_browser_session_recording.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/38_browser_session_recording.py)\n- [`39_llm_fallback.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/39_llm_fallback.py)\n- [`40_acp_agent_example.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/40_acp_agent_example.py)\n- [`41_task_tool_set.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/41_task_tool_set.py)\n- [`42_file_based_subagents.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/42_file_based_subagents.py)\n- [`44_model_switching_in_convo.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/44_model_switching_in_convo.py)\n- [`45_parallel_tool_execution.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/45_parallel_tool_execution.py)\n- [`46_agent_settings.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/46_agent_settings.py)\n- [`47_defense_in_depth_security.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/47_defense_in_depth_security.py)\n- [`48_conversation_fork.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/48_conversation_fork.py)\n- [`49_switch_llm_tool.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/49_switch_llm_tool.py)\n- [`50_async_cancellation.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/50_async_cancellation.py)\n- [`51_agent_hooks`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/51_agent_hooks)\n- [`52_dynamic_workflow.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/52_dynamic_workflow.py)\n- [`53_client_defined_tools.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/53_client_defined_tools.py)\n- [`54_goal_completion_loop.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/54_goal_completion_loop.py)\n- [`55_persistent_memory.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/55_persistent_memory.py)\n- [`56_structured_output.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/56_structured_output.py)\n- [`57_prompt_hooks`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/57_prompt_hooks)\n- [`58_ask_oracle_tool`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/01_standalone_sdk/58_ask_oracle_tool)\n\n### [`02_remote_agent_server/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server)\n\n- [`01_convo_with_local_agent_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/01_convo_with_local_agent_server.py)\n- [`02_convo_with_docker_sandboxed_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/02_convo_with_docker_sandboxed_server.py)\n- [`03_browser_use_with_docker_sandboxed_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/03_browser_use_with_docker_sandboxed_server.py)\n- [`04_convo_with_api_sandboxed_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/04_convo_with_api_sandboxed_server.py)\n- [`05_vscode_with_docker_sandboxed_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/05_vscode_with_docker_sandboxed_server.py)\n- [`06_custom_tool`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/06_custom_tool)\n- [`07_convo_with_cloud_workspace.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/07_convo_with_cloud_workspace.py)\n- [`08_convo_with_apptainer_sandboxed_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/08_convo_with_apptainer_sandboxed_server.py)\n- [`09_acp_agent_with_remote_runtime.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py)\n- [`10_cloud_workspace_share_credentials.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/10_cloud_workspace_share_credentials.py)\n- [`11_conversation_fork.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/11_conversation_fork.py)\n- [`12_settings_and_secrets_api.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/12_settings_and_secrets_api.py)\n- [`13_workspace_get_llm.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/13_workspace_get_llm.py)\n- [`14_client_defined_tools.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/14_client_defined_tools.py)\n- [`15_openai_compatible_gateway.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/15_openai_compatible_gateway.py)\n- [`16_deferred_init.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/16_deferred_init.py)\n- [`17_convo_with_agent_sandbox_server.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/17_convo_with_agent_sandbox_server.py)\n- [`agent_sandbox_deploy`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/agent_sandbox_deploy)\n- [`hook_scripts`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/hook_scripts)\n- [`scripts`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/02_remote_agent_server/scripts)\n\n### [`03_github_workflows/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows)\n\n- [`01_basic_action`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/01_basic_action)\n- [`02_pr_review`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/02_pr_review)\n- [`03_todo_management`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/03_todo_management)\n- [`04_datadog_debugging`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/04_datadog_debugging)\n- [`05_posthog_debugging`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/03_github_workflows/05_posthog_debugging)\n\n### [`04_llm_specific_tools/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/04_llm_specific_tools)\n\n- [`01_gpt5_apply_patch_preset.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/04_llm_specific_tools/01_gpt5_apply_patch_preset.py)\n- [`02_gemini_file_tools.py`](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/04_llm_specific_tools/02_gemini_file_tools.py)\n\n### [`05_skills_and_plugins/`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins)\n\n- [`01_loading_agentskills`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/01_loading_agentskills)\n- [`02_loading_plugins`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/02_loading_plugins)\n- [`03_managing_installed_skills`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/03_managing_installed_skills)\n- [`04_mixed_marketplace_skills`](https://github.com/OpenHands/software-agent-sdk/tree/main/examples/05_skills_and_plugins/04_mixed_marketplace_skills)',category:`agent-authoring`,defaultEnabled:!0},{name:`pdflatex`,description:`Install and use pdflatex to compile LaTeX documents into PDFs on Linux. Use when generating academic papers, research publications, or any documents written in LaTeX.`,triggers:[`pdflatex`],content:`PdfLatex is a tool that converts Latex sources into PDF. This is specifically very important for researchers, as they use it to publish their findings. It could be installed very easily using Linux terminal, though this seems an annoying task on Windows. Installation commands are given below.
|
|
5996
6563
|
|
|
5997
6564
|
* Install the TexLive base
|
|
5998
6565
|
|