@openhands/agent-canvas 1.11.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{active-backend-context-BBvP-bI2.js → active-backend-context-B_bg5h9O.js} +1 -1
  4. package/build/assets/{agent-context-settings-Bno1nwPL.js → agent-context-settings-CzWS1DgR.js} +1 -1
  5. package/build/assets/{agent-profiles-settings-DqoS7RL3.js → agent-profiles-settings-hd2cAIZM.js} +1 -1
  6. package/build/assets/{agent-server-conversation-service.api-0RztSdJJ.js → agent-server-conversation-service.api-BheU4HX3.js} +3 -3
  7. package/build/assets/{agent-settings-h8hQz-IU.js → agent-settings-D2J1dKVd.js} +1 -1
  8. package/build/assets/agent-settings-D_SVrWhI.js +1 -0
  9. package/build/assets/{api-key-entry-screen-Qsb83VX1.js → api-key-entry-screen-D70oJj2c.js} +1 -1
  10. package/build/assets/app-settings-D0OKHB3M.js +1 -0
  11. package/build/assets/{automation-detail-7LkL91j9.js → automation-detail-C0SxWTnQ.js} +1 -1
  12. package/build/assets/{automation-export-U2QNyNy6.js → automation-export-BjQa_fT6.js} +1 -1
  13. package/build/assets/{automation-setup-route-Bel9_Lue.js → automation-setup-route-BzCNpljP.js} +1 -1
  14. package/build/assets/{automation-templates-CRLDssaI.js → automation-templates-D9gs6ihu.js} +1 -1
  15. package/build/assets/{automations-list-B2iV3ZKW.js → automations-list-dZg8zOCl.js} +1 -1
  16. package/build/assets/backend-form-modal-HwclKrUS.js +1 -0
  17. package/build/assets/{backend-synced-settings-badge-DB4717Iu.js → backend-synced-settings-badge-YI3k09Wr.js} +1 -1
  18. package/build/assets/{badge-yR53enbU.js → badge-Dpn3-LTV.js} +1 -1
  19. package/build/assets/{browser-tab-A94o33Vn.js → browser-tab-4CPdj3J3.js} +1 -1
  20. package/build/assets/{cloud-funnel-analytics-CBQdPZl_.js → cloud-funnel-analytics-CcSez21r.js} +1 -1
  21. package/build/assets/{command-menu-PsRXVBz2.js → command-menu-BKOLj-TC.js} +1 -1
  22. package/build/assets/{condenser-settings-w7L3EFvm.js → condenser-settings-DLQogFnB.js} +1 -1
  23. package/build/assets/{conversation-BUzBZAc-.js → conversation-Cmyw9bFh.js} +3 -3
  24. package/build/assets/conversation-CvoGZ5vC.js +1 -0
  25. package/build/assets/conversation-panel-CvoGZ5vC.js +1 -0
  26. package/build/assets/{conversation-state-store-Bs8gA263.js → conversation-state-store-CtgILxWF.js} +1 -1
  27. package/build/assets/{entry.client-DzbDyLkV.js → entry.client-EBn3ZtNP.js} +1 -1
  28. package/build/assets/{extensions-hub-DOmHPGTA.js → extensions-hub-BZ3HYztk.js} +1 -1
  29. package/build/assets/{extensions-navigation-6zU5M1pa.js → extensions-navigation-Bnx32WAb.js} +1 -1
  30. package/build/assets/{files-tab-BzofBmF4.js → files-tab-D5zuU5TY.js} +1 -1
  31. package/build/assets/format-model-name-BN_rx1Y3.js +1 -0
  32. package/build/assets/{format-relative-time-DGPQlPx0.js → format-relative-time-BerVamGl.js} +1 -1
  33. package/build/assets/{git-provider-icon-BLMlwy02.js → git-provider-icon-zuKz2cwo.js} +1 -1
  34. package/build/assets/{git-repo-dropdown-B7RvO70z.js → git-repo-dropdown-B5VnMftu.js} +1 -1
  35. package/build/assets/git-repo-dropdown-Bo7ciSNX.js +1 -0
  36. package/build/assets/home-DqyeeFA_.js +1 -0
  37. package/build/assets/{home-DEZaZqYv.js → home-Y0aDou-a.js} +1 -1
  38. package/build/assets/{home-store-D7CjMN_-.js → home-store-Cubdq0uP.js} +1 -1
  39. package/build/assets/index-home-DqyeeFA_.js +1 -0
  40. package/build/assets/info-C9lpK5pw.js +1 -0
  41. package/build/assets/{install-server-modal-BTwK5lbi.js → install-server-modal-DW6dSyGr.js} +1 -1
  42. package/build/assets/{kebab-menu-item-content-C4CkeiJO.js → kebab-menu-item-content-CKydZrbH.js} +1 -1
  43. package/build/assets/{launch-DVlx4v9o.js → launch-c4GEP8oo.js} +1 -1
  44. package/build/assets/llm-not-configured-banner-DCE_0B4I.js +27 -0
  45. package/build/assets/llm-settings-8eWBF3Ij.js +1 -0
  46. package/build/assets/llm-settings-D9ko42Pi.js +1 -0
  47. package/build/assets/{llm-subscription-service-7eVfDIE1.js → llm-subscription-service-B3K-97lP.js} +1 -1
  48. package/build/assets/{manage-backends-modal-HNWKLYhq.js → manage-backends-modal-DTCME_Pu.js} +1 -1
  49. package/build/assets/manifest-e1c3bc3b.js +1 -0
  50. package/build/assets/{manifest-subpage-layout-D-m-h8_t.js → manifest-subpage-layout-Ds7G5GZ8.js} +1 -1
  51. package/build/assets/{markdown-renderer-BiiiIznl.js → markdown-renderer-DzvgdZey.js} +1 -1
  52. package/build/assets/{mcp-gLgPP7AS.js → mcp-Da7wFU7A.js} +1 -1
  53. package/build/assets/{mcp-marketplace-utils-Dr_HG_ol.js → mcp-marketplace-utils-DSLou4n7.js} +1 -1
  54. package/build/assets/messages-B2l0qLVk.js +40 -0
  55. package/build/assets/{npm-DRzJF5Zn.js → npm-Cswluf6-.js} +1 -1
  56. package/build/assets/{onboarding-DSr8hOpk.js → onboarding-BKbTYlW1.js} +1 -1
  57. package/build/assets/{onboarding-modal-C6Euf7N4.js → onboarding-modal-DrrGlEQq.js} +1 -1
  58. package/build/assets/{organization-service.api-C4GYWwj9.js → organization-service.api-DK8csGvK.js} +1 -1
  59. package/build/assets/{planner-tab-CZcguxTK.js → planner-tab-D-mZ1I7n.js} +1 -1
  60. package/build/assets/{plugins-management-service-BmDzOQsd.js → plugins-management-service-CywqyfLK.js} +1 -1
  61. package/build/assets/{profiles-service.api-CoLTwjc1.js → profiles-service.api-vcE_jJCe.js} +1 -1
  62. package/build/assets/{providers-tBzTpz1w.js → providers-CdrPPm0z.js} +1 -1
  63. package/build/assets/{proxy-DCI9S-LA.js → proxy-b4aqL4SX.js} +1 -1
  64. package/build/assets/{recommended-automations-launcher-BbJAJVED.js → recommended-automations-launcher-DIYgUdMm.js} +1 -1
  65. package/build/assets/root-CBBi6IAe.js +2 -0
  66. package/build/assets/root-CRK9fOFd.css +1 -0
  67. package/build/assets/root-layout-BFN2rCOy.js +2 -0
  68. package/build/assets/{schema-field-zhsVDllR.js → schema-field-Z-rMg9ti.js} +1 -1
  69. package/build/assets/{sdk-section-page-CS4GWn0y.js → sdk-section-page-m_cjygxR.js} +1 -1
  70. package/build/assets/{secrets-service-DjgGduXk.js → secrets-service-BHF4fxML.js} +1 -1
  71. package/build/assets/{secrets-settings-f-qahfbi.js → secrets-settings-aBGXtQhX.js} +1 -1
  72. package/build/assets/{settings-DQd0xLEw.js → settings-CZPGNens.js} +1 -1
  73. package/build/assets/{settings-index-BVwy9JEp.js → settings-index-Dtlegd6s.js} +1 -1
  74. package/build/assets/{settings-modal-D6D5ngET.js → settings-modal-CalzJP2l.js} +1 -1
  75. package/build/assets/{settings-service.api-DZp7E7A9.js → settings-service.api-DfPYaxZJ.js} +1 -1
  76. package/build/assets/{shared-conversation-DIxZjElr.js → shared-conversation-BIAcuORk.js} +1 -1
  77. package/build/assets/{sidebar-mobile-menu-toggle-OoZBHxaT.js → sidebar-mobile-menu-toggle-C6HpQ55l.js} +1 -1
  78. package/build/assets/{skill-scope-B1Per5XI.js → skill-scope-Dt1V5X2p.js} +1 -1
  79. package/build/assets/{skills-plugins-B3AO6sMz.js → skills-plugins-B-H0cCOP.js} +1 -1
  80. package/build/assets/{skills-settings-DmmgJ6CT.js → skills-settings-DthdIDUb.js} +1 -1
  81. package/build/assets/{task-list-tab-C19Q_JNf.js → task-list-tab-BTde81Iu.js} +1 -1
  82. package/build/assets/{terminal-CbuMRYal.js → terminal-DRrJo-cR.js} +1 -1
  83. package/build/assets/{use-acp-credential-form-DJmmJKMo.js → use-acp-credential-form-DGyo0QvL.js} +1 -1
  84. package/build/assets/{use-activate-agent-profile-CeFfYwu_.js → use-activate-agent-profile-DrPzIKJF.js} +1 -1
  85. package/build/assets/{use-agent-profiles-BHLkLbRR.js → use-agent-profiles-B37XWDLq.js} +1 -1
  86. package/build/assets/{use-can-manage-org-profiles-Bu4y8gSx.js → use-can-manage-org-profiles-BzE28H3x.js} +1 -1
  87. package/build/assets/{use-cloud-current-user-id-QD9x3ySO.js → use-cloud-current-user-id-U6HPjy50.js} +1 -1
  88. package/build/assets/{use-config-CPwqciXN.js → use-config-DapX3pjC.js} +1 -1
  89. package/build/assets/{use-create-conversation-DWaSVUOB.js → use-create-conversation-CRf1dCm5.js} +1 -1
  90. package/build/assets/{use-create-secret-BsOfOLvg.js → use-create-secret-DcpT3RPw.js} +1 -1
  91. package/build/assets/{use-llm-profiles-CU8ah1pz.js → use-llm-profiles-CHxqoHiN.js} +1 -1
  92. package/build/assets/{use-manifest-capabilities-DBYPjyV6.js → use-manifest-capabilities-zihHDbMW.js} +1 -1
  93. package/build/assets/{use-onboarding-completion-CtNJxkXG.js → use-onboarding-completion-6kWOW3ul.js} +1 -1
  94. package/build/assets/{use-plugins-marketplace-ZEA-gyM9.js → use-plugins-marketplace-CqkR8kLE.js} +1 -1
  95. package/build/assets/{use-save-agent-profile-DgI_Uz9a.js → use-save-agent-profile-CH9_EXQG.js} +1 -1
  96. package/build/assets/{use-save-settings-pSjRhD_m.js → use-save-settings-DIEurJ3D.js} +1 -1
  97. package/build/assets/{use-settings-BHWsOcIG.js → use-settings-BmLzQjnC.js} +1 -1
  98. package/build/assets/{use-settings-nav-items-CQgkxUbV.js → use-settings-nav-items-DV9qgeu7.js} +1 -1
  99. package/build/assets/{use-tracking-CGCsBWhg.js → use-tracking-salbPJxT.js} +1 -1
  100. package/build/assets/{use-user-conversation-DRfEU8x0.js → use-user-conversation-Dt-W6uNw.js} +1 -1
  101. package/build/assets/{verification-settings-BItwt998.js → verification-settings-oi54wEc1.js} +1 -1
  102. package/build/index.html +4 -4
  103. package/config/defaults.json +1 -1
  104. package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs +1 -1
  105. package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs.map +1 -1
  106. package/dist/components/features/chat/components/chat-input-llm-profile-picker.js +61 -60
  107. package/dist/components/features/chat/components/chat-input-llm-profile-picker.js.map +1 -1
  108. package/dist/components/features/chat/model-messages.cjs +1 -1
  109. package/dist/components/features/chat/model-messages.cjs.map +1 -1
  110. package/dist/components/features/chat/model-messages.js +26 -25
  111. package/dist/components/features/chat/model-messages.js.map +1 -1
  112. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs +1 -1
  113. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js +4 -4
  114. package/dist/components/features/settings/llm-profiles/profile-row.cjs +1 -1
  115. package/dist/components/features/settings/llm-profiles/profile-row.js +1 -0
  116. package/dist/components/shared/modals/settings/model-selector.cjs +1 -1
  117. package/dist/components/shared/modals/settings/model-selector.cjs.map +1 -1
  118. package/dist/components/shared/modals/settings/model-selector.js +154 -98
  119. package/dist/components/shared/modals/settings/model-selector.js.map +1 -1
  120. package/dist/config/defaults.cjs +1 -1
  121. package/dist/config/defaults.cjs.map +1 -1
  122. package/dist/config/defaults.js +1 -1
  123. package/dist/config/defaults.js.map +1 -1
  124. package/dist/hooks/chat/use-slash-command.cjs +1 -1
  125. package/dist/hooks/chat/use-slash-command.cjs.map +1 -1
  126. package/dist/hooks/chat/use-slash-command.js +61 -60
  127. package/dist/hooks/chat/use-slash-command.js.map +1 -1
  128. package/dist/package.cjs +1 -1
  129. package/dist/package.cjs.map +1 -1
  130. package/dist/package.js +1 -1
  131. package/dist/package.js.map +1 -1
  132. package/dist/routes/app-settings.cjs +1 -1
  133. package/dist/routes/app-settings.cjs.map +1 -1
  134. package/dist/routes/app-settings.js +94 -93
  135. package/dist/routes/app-settings.js.map +1 -1
  136. package/dist/routes/llm-settings.cjs +1 -1
  137. package/dist/routes/llm-settings.cjs.map +1 -1
  138. package/dist/routes/llm-settings.js +131 -119
  139. package/dist/routes/llm-settings.js.map +1 -1
  140. package/dist/utils/format-model-name.cjs +1 -1
  141. package/dist/utils/format-model-name.cjs.map +1 -1
  142. package/dist/utils/format-model-name.d.ts +11 -0
  143. package/dist/utils/format-model-name.js +11 -3
  144. package/dist/utils/format-model-name.js.map +1 -1
  145. package/package.json +1 -1
  146. package/build/assets/agent-settings-BJHryp65.js +0 -1
  147. package/build/assets/app-settings-r1RUbgGi.js +0 -1
  148. package/build/assets/backend-form-modal-OroTqnAv.js +0 -1
  149. package/build/assets/conversation-panel-pzAKsSDb.js +0 -1
  150. package/build/assets/conversation-pzAKsSDb.js +0 -1
  151. package/build/assets/git-repo-dropdown-B_PTq4ol.js +0 -1
  152. package/build/assets/home-r89Vj2td.js +0 -1
  153. package/build/assets/index-home-r89Vj2td.js +0 -1
  154. package/build/assets/llm-not-configured-banner-CwKu8C6g.js +0 -27
  155. package/build/assets/llm-settings-BJotLQND.js +0 -1
  156. package/build/assets/llm-settings-CDM-5H2A.js +0 -1
  157. package/build/assets/manifest-2a36a8f8.js +0 -1
  158. package/build/assets/messages-D1cbVhRK.js +0 -40
  159. package/build/assets/root-BfM_kC_d.css +0 -1
  160. package/build/assets/root-gstBEjty.js +0 -2
  161. package/build/assets/root-layout-BIAFLP9p.js +0 -2
@@ -1,3 +1,3 @@
1
- import{a as e}from"./rolldown-runtime-Cyuzqnbw.js";import{St as t}from"./vendor-styling-Ck5D_A2Q.js";import{j as n}from"./vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~kv3pap4j-oGvLV0dO.js";import{O as r,Q as i,T as a,W as o,a as s,b as c,ct as l,d as u,dt as ee,f as te,h as d,lt as ne,n as re,p as ie,w as ae}from"./active-backend-context-BBvP-bI2.js";import{t as f}from"./proxy-DCI9S-LA.js";import{t as oe}from"./vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~ht43enc2-C0JXQb_q.js";import{n as se,t as p}from"./vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~9pstowjp-BOVIFA_g.js";var m=e(t(),1),ce=new Map(oe.map(e=>[e.name,e]));function le(e){return Object.keys(e.requires.integrations)}function ue(e){return Object.entries(e.requires.integrations).filter(([,e])=>e.required!==!1).map(([e])=>e)}function h(e){return ce.get(e.skill??e.id)?.triggers[0]??null}function de(e){return h(e)??`Set up the ${e.name} automation`}var fe=[`form`,`automation`],pe=[`list`,`templates`],me=[`layout-dashboard`,`sparkles`,`bot`,`circle-alert`,`activity`,`timer`],he=[`automations`,`needs-attention`,`total-runs`,`average-duration`],ge={automations:[`active`],"needs-attention":[],"total-runs":[],"average-duration":[]},g={status:[`all`,`active`,`failing`,`disabled`],trigger:[`all`,`schedule`,`event`]},_e=Object.keys(g),ve=[`last-run`,`runs`,`name`],ye=/<[A-Za-z/!]/,be=/^[a-z0-9]+(-[a-z0-9]+)*$/,_=`https://docs.openhands.dev/`,xe=/^[a-z][a-z-]*$/,Se=/^\.[a-z][a-z.]*json$/,Ce=/^[a-z0-9][a-z0-9.-]*$/,we=/^\/[A-Za-z0-9/{}_-]*$/,Te=/^[^{}]*\{id\}[^{}]*$/,Ee=[`github`,`gitlab`,`bitbucket`],v={name:{type:`text`,required:!0},prompt:{type:`textarea`,required:!1},model:{type:`llm-profile`,required:!1},timeout:{type:`number`,required:!1},schedule:{type:`schedule`,required:!1}},De=Object.keys(v),y=[`list`,`health`,`capabilities`,`validate`,`createPrompt`,`createPlugin`],b=[`detail`,`dispatch`,`runs`,`tarball`];function x(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function S(e,t){return typeof e==`string`&&t.includes(e)}var Oe=class{errors=[];fail(e,t){return this.errors.push(`${e}: ${t}`),!1}copy(e,t){return typeof e!=`string`||e.length===0?this.fail(t,`must be a non-empty string`):ye.test(e)?this.fail(t,`must not contain markup`):!0}closed(e,t,n){Object.keys(e).filter(e=>!t.includes(e)).forEach(e=>this.fail(`${n}.${e}`,`is not allowed`))}record(e,t){return x(e)?!0:(this.fail(t,`must be an object`),!1)}};function ke(e,t,n){e.record(t,`routes`)&&(e.closed(t,[`list`,`setup`,`detail`,`templates`],`routes`),[`list`,`setup`,`detail`].forEach(r=>{t[r]!==n[r]&&e.fail(`routes.${r}`,`must be "${n[r]}"`)}),t.templates!==void 0&&t.templates!==n.templates&&e.fail(`routes.templates`,n.templates===void 0?`is not a route this host mounts`:`must be "${n.templates}"`))}function Ae(e,t){if(!Array.isArray(t)||t.length===0){e.fail(`navigation.subPages`,`must be a non-empty array`);return}let n=new Set;t.forEach((t,r)=>{let i=`navigation.subPages[${r}]`;if(!e.record(t,i))return;e.closed(t,[`page`,`label`,`icon`],i);let{page:a,label:o,icon:s}=t;S(a,pe)?n.has(a)?e.fail(`${i}.page`,`repeats a page`):n.add(a):e.fail(`${i}.page`,`is not a sub-page this host serves`),e.copy(o,`${i}.label`),je(e,s,`${i}.icon`)})}function je(e,t,n){S(t,me)||e.fail(n,`is not an icon this host ships`)}function Me(e,t){if(e.record(t,`navigation`)){if(e.closed(t,[`sidebar`,`commandMenu`,`subPages`],`navigation`),e.record(t.sidebar,`navigation.sidebar`)&&(e.closed(t.sidebar,[`label`],`navigation.sidebar`),e.copy(t.sidebar.label,`navigation.sidebar.label`)),e.record(t.commandMenu,`navigation.commandMenu`)){let n=t.commandMenu;e.closed(n,[`title`,`description`,`keywords`],`navigation.commandMenu`),e.copy(n.title,`navigation.commandMenu.title`),e.copy(n.description,`navigation.commandMenu.description`),e.copy(n.keywords,`navigation.commandMenu.keywords`)}t.subPages!==void 0&&Ae(e,t.subPages)}}function Ne(e,t){e.record(t,`pages`)&&(e.closed(t,[`list`,`detail`,`edit`,`templates`],`pages`),e.record(t.list,`pages.list`)&&(e.closed(t.list,[`title`,`subtitle`,`overview`,`filters`,`sort`,`insights`],`pages.list`),e.copy(t.list.title,`pages.list.title`),e.copy(t.list.subtitle,`pages.list.subtitle`),t.list.overview!==void 0&&Pe(e,t.list.overview),t.list.filters!==void 0&&Le(e,t.list.filters),t.list.sort!==void 0&&Be(e,t.list.sort),t.list.insights!==void 0&&Ve(e,t.list.insights)),e.record(t.detail,`pages.detail`)&&(e.closed(t.detail,[`backLabel`],`pages.detail`),e.copy(t.detail.backLabel,`pages.detail.backLabel`)),e.record(t.edit,`pages.edit`)&&(e.closed(t.edit,[`title`],`pages.edit`),e.copy(t.edit.title,`pages.edit.title`)),t.templates!==void 0&&He(e,t.templates))}function Pe(e,t){let n=`pages.list.overview`;if(!e.record(t,n))return;e.closed(t,[`label`,`tiles`],n),e.copy(t.label,`${n}.label`);let{tiles:r}=t;if(!Array.isArray(r)||r.length===0){e.fail(`${n}.tiles`,`must be a non-empty array`);return}let i=new Set;r.forEach((t,r)=>{Fe(e,t,i,`${n}.tiles[${r}]`)})}function Fe(e,t,n,r){if(!e.record(t,r))return;e.closed(t,[`metric`,`label`,`detail`,`zeroDetail`,`icon`],r);let{metric:i,label:a,detail:o,zeroDetail:s,icon:c}=t;if(e.copy(a,`${r}.label`),je(e,c,`${r}.icon`),!S(i,he)){e.fail(`${r}.metric`,`is not a metric this host computes`),e.copy(o,`${r}.detail`),s!==void 0&&e.copy(s,`${r}.zeroDetail`);return}n.has(i)?e.fail(`${r}.metric`,`repeats a metric`):n.add(i),Ie(e,o,i,`${r}.detail`),s!==void 0&&Ie(e,s,i,`${r}.zeroDetail`)}function Ie(e,t,n,r){if(!e.copy(t,r))return;let i=ge[n];(i.length===0?/\{\{/:RegExp(`\\{\\{(?!(?:${i.join(`|`)})\\}\\})`)).test(t)&&e.fail(r,`uses a placeholder this metric does not expose`)}function Le(e,t){let n=`pages.list.filters`;if(!Array.isArray(t)||t.length===0){e.fail(n,`must be a non-empty array`);return}let r=new Set;t.forEach((t,i)=>{Re(e,t,r,`${n}[${i}]`)})}function Re(e,t,n,r){if(!e.record(t,r))return;e.closed(t,[`id`,`label`,`options`],r);let{id:i,label:a,options:o}=t;if(e.copy(a,`${r}.label`),!S(i,_e)){e.fail(`${r}.id`,`is not a filter this host implements`);return}n.has(i)?e.fail(`${r}.id`,`repeats a filter`):n.add(i),ze(e,o,g[i],`${r}.options`)}function ze(e,t,n,r){if(!Array.isArray(t)||t.length<2){e.fail(r,`must offer at least two options`);return}let i=new Set;t.forEach((t,a)=>{let o=`${r}[${a}]`;if(!e.record(t,o))return;e.closed(t,[`value`,`label`],o);let{value:s,label:c}=t;S(s,n)?i.has(s)?e.fail(`${o}.value`,`repeats a value`):i.add(s):e.fail(`${o}.value`,`is not a value this host implements`),e.copy(c,`${o}.label`)}),i.has(`all`)||e.fail(r,`must offer the "all" option`)}function Be(e,t){let n=`pages.list.sort`;if(!e.record(t,n))return;e.closed(t,[`label`,`options`,`default`],n);let{label:r,options:i,default:a}=t;e.copy(r,`${n}.label`);let o=new Set;!Array.isArray(i)||i.length===0?e.fail(`${n}.options`,`must be a non-empty array`):i.forEach((t,r)=>{let i=`${n}.options[${r}]`;e.record(t,i)&&(e.closed(t,[`value`,`label`],i),S(t.value,ve)?o.has(t.value)?e.fail(`${i}.value`,`repeats a value`):o.add(t.value):e.fail(`${i}.value`,`is not a sort this host implements`),e.copy(t.label,`${i}.label`))}),(typeof a!=`string`||!o.has(a))&&e.fail(`${n}.default`,`must be one of the declared option values`)}var C={health:[`healthy`,`failing`,`running`,`disabled`,`neverRun`,`checking`],lastRun:[`label`,`never`,`justNow`],stats:[`runs`,`recentSuccess`,`averageDuration`]};function Ve(e,t){let n=`pages.list.insights`;e.record(t,n)&&(e.closed(t,Object.keys(C),n),Object.keys(C).forEach(r=>{let i=`${n}.${r}`,a=t[r];if(!e.record(a,i))return;let o=C[r];e.closed(a,o,i),o.forEach(t=>{e.copy(a[t],`${i}.${t}`)})}))}function He(e,t){let n=`pages.templates`;e.record(t,n)&&(e.closed(t,[`title`,`description`],n),e.copy(t.title,`${n}.title`),e.copy(t.description,`${n}.description`))}function Ue(e,t){let n=x(t.routes)?t.routes:{},r=x(t.navigation)?t.navigation:{},i=x(t.pages)?t.pages:{},a=x(i.list)?i.list:{},o=[[`routes.templates`,n.templates],[`navigation.subPages`,r.subPages],[`pages.templates`,i.templates],[`pages.list.overview`,a.overview],[`pages.list.filters`,a.filters],[`pages.list.sort`,a.sort],[`pages.list.insights`,a.insights]],s=o.filter(([,e])=>e===void 0).map(([e])=>e);s.length===0||s.length===o.length||e.fail(`interface`,`the sub-page surface must be declared whole; missing ${s.join(`, `)}`)}function We(e,t,n,r){if(!e.record(n,r))return;e.closed(n,[`type`,`label`,`help`,`required`,`constraints`],r);let{type:i,label:a,help:o,required:s,constraints:c}=n;if(i!==t.type&&e.fail(`${r}.type`,`must be "${t.type}", the control this host renders`),e.copy(a,`${r}.label`),o!==void 0&&e.copy(o,`${r}.help`),s!==t.required&&e.fail(`${r}.required`,`must be ${t.required}, what this host enforces`),c!==void 0){if(t.type!==`number`)e.fail(`${r}.constraints`,`is only allowed on a number attribute`);else if(e.record(c,`${r}.constraints`)){e.closed(c,[`min`,`max`],`${r}.constraints`);let{min:t,max:n}=c;t!==void 0&&t!==1&&e.fail(`${r}.constraints.min`,`must be the 1 this host enforces`),n!==void 0&&(!Number.isInteger(n)||n<1)&&e.fail(`${r}.constraints.max`,`must be a positive integer`)}}}function Ge(e,t){if(!e.record(t,`attributes`))return;let n=Object.keys(t);n.length===0&&e.fail(`attributes`,`must declare at least one attribute`),n.forEach(n=>{if(!De.includes(n)){e.fail(`attributes.${n}`,`is not a settable attribute`);return}We(e,v[n],t[n],`attributes.${n}`)})}function Ke(e,t){if(!e.record(t,`importExport`))return;e.closed(t,[`fileKind`,`fileVersion`,`filenameSuffix`,`importDefaults`],`importExport`);let{fileKind:n,fileVersion:r,filenameSuffix:i,importDefaults:a}=t;(typeof n!=`string`||!xe.test(n))&&e.fail(`importExport.fileKind`,`must be a lowercase slug`),r!==1&&e.fail(`importExport.fileVersion`,`must be 1`),(typeof i!=`string`||!Se.test(i))&&e.fail(`importExport.filenameSuffix`,`must be a .json suffix`),e.record(a,`importExport.importDefaults`)&&(e.closed(a,[`repoProvider`,`placeholderEventSource`],`importExport.importDefaults`),(typeof a.repoProvider!=`string`||!Ee.includes(a.repoProvider))&&e.fail(`importExport.importDefaults.repoProvider`,`is not a supported provider`),(typeof a.placeholderEventSource!=`string`||!Ce.test(a.placeholderEventSource))&&e.fail(`importExport.importDefaults.placeholderEventSource`,`must be a lowercase event source`))}function qe(e,t){if(!e.record(t,`endpoints`))return;let n=[...y,...b];e.closed(t,n,`endpoints`);let r=n=>{let r=t[n];return typeof r!=`string`||!we.test(r)||r.includes(`//`)?(e.fail(`endpoints.${n}`,`must be a rooted service-relative path`),null):r};y.forEach(t=>{let n=r(t);n!==null&&/[{}]/.test(n)&&e.fail(`endpoints.${t}`,`must not carry a substitution`)}),b.forEach(t=>{let n=r(t);n!==null&&!Te.test(n)&&e.fail(`endpoints.${t}`,`must carry exactly one {id}`)})}function w(e,t,n){if(!Array.isArray(t)||t.length===0)return e.fail(n,`must be a non-empty array`),[];let r=t.filter(t=>typeof t==`string`&&be.test(t)?!0:(e.fail(n,`must contain only lowercase slugs`),!1));return new Set(r).size!==r.length&&e.fail(n,`must not repeat an id`),r}var Je=[`version`,`routes`,`navigation`,`pages`,`docsUrl`,`attributes`,`importExport`,`endpoints`,`featuredAutomationIds`,`responderIntegrationIds`];function Ye(e,t){if(!x(e))return{valid:!1,errors:[`interface: must be an object`]};if(e.version!==`1.0`)return{valid:!1,errors:[`interface.version: must be "1.0"`]};let n=new Oe;return n.closed(e,Je,`interface`),ke(n,e.routes,t.mountedRoutes),Me(n,e.navigation),Ne(n,e.pages),(typeof e.docsUrl!=`string`||!e.docsUrl.startsWith(_))&&n.fail(`docsUrl`,`must start with ${_}`),Ge(n,e.attributes),Ke(n,e.importExport),qe(n,e.endpoints),w(n,e.featuredAutomationIds,`featuredAutomationIds`).forEach(e=>{t.catalogIds.has(e)||n.fail(`featuredAutomationIds`,`${e} is not a catalog entry`)}),w(n,e.responderIntegrationIds,`responderIntegrationIds`),Ue(n,e),{valid:n.errors.length===0,errors:n.errors}}var T=/^[a-z0-9]+(-[a-z0-9]+)*$/,Xe=/^[a-z][A-Za-z0-9]*$/,Ze=/<[A-Za-z/!]/,Qe=RegExp(`\\{\\{(?!(?:${fe.join(`|`)})\\.[A-Za-z0-9_.]+\\}\\})`),$e=[`direct`,`assisted`],et=[`text`,`textarea`,`select`,`cron`,`timezone`,`repo-picker`],tt=[`github`,`gitlab`,`bitbucket`],nt=[`cron`,`event`],rt=[`safeExpressionLiteral`],E=2e3;function D(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function O(e,t){return typeof e==`string`&&t.includes(e)}function it(e,t){return typeof e==`number`&&Number.isInteger(e)&&e>=t}var at=class{errors=[];fail(e,t){return this.errors.push(`${e}: ${t}`),!1}copy(e,t){return typeof e!=`string`||e.length===0?this.fail(t,`must be a non-empty string`):Ze.test(e)?this.fail(t,`must not contain markup`):!0}placeholders(e,t){return Qe.test(e)?this.fail(t,`uses an unknown placeholder namespace`):!0}templateCopy(e,t){return this.copy(e,t)&&this.placeholders(e,t)}templateValue(e,t){return typeof e!=`string`||e.length===0?this.fail(t,`must be a non-empty string`):this.placeholders(e,t)}absent(e,t,n,r){return t in e?this.fail(`${n}.${t}`,r):!0}};function ot(e,t){if(!D(t)){e.fail(`requires`,`must be an object`);return}let{integrations:n,features:r}=t;!D(n)||Object.keys(n).length===0?e.fail(`requires.integrations`,`must be a non-empty object`):Object.entries(n).forEach(([t,n])=>{let r=`requires.integrations.${t}`;if(!D(n)){e.fail(r,`must be an object`);return}e.copy(n.message,`${r}.message`),`required`in n&&n.required!==!1&&e.fail(`${r}.required`,`may only be false`);let i=[`message`,`required`];Object.keys(n).filter(e=>!i.includes(e)).forEach(t=>e.fail(`${r}.${t}`,`is not allowed`))}),r!==void 0&&(!Array.isArray(r)||r.length===0?e.fail(`requires.features`,`must be a non-empty array`):r.forEach((t,n)=>{(typeof t!=`string`||t.length===0)&&e.fail(`requires.features[${n}]`,`must be a non-empty string`)}))}function st(e,t,n){if(!D(t)||Object.keys(t).length===0){e.fail(n,`must be a non-empty object`);return}let{minLength:r,maxLength:i,format:a}=t;r!==void 0&&!it(r,0)&&e.fail(`${n}.minLength`,`must be a non-negative integer`),i!==void 0&&!it(i,1)&&e.fail(`${n}.maxLength`,`must be a positive integer`),a!==void 0&&!O(a,rt)&&e.fail(`${n}.format`,`is not a supported format`)}function ct(e,t,n){if(!D(t)){e.fail(n,`must be an object`);return}let{type:r,label:i,help:a,placeholder:o,required:s,provider:c,options:l}=t;O(r,et)||e.fail(`${n}.type`,`is not a supported field type`),e.copy(i,`${n}.label`),e.copy(a,`${n}.help`),o!==void 0&&e.copy(o,`${n}.placeholder`),t.default!==void 0&&typeof t.default!=`string`&&e.fail(`${n}.default`,`must be a string`),typeof s!=`boolean`&&e.fail(`${n}.required`,`must be a boolean`),c!==void 0&&!O(c,tt)&&e.fail(`${n}.provider`,`is not a supported provider`),r===`repo-picker`&&c===void 0&&e.fail(`${n}.provider`,`is required for a repository field`),l!==void 0&&(r===`select`?!Array.isArray(l)||l.length===0?e.fail(`${n}.options`,`must be a non-empty array`):l.forEach((t,r)=>{let i=`${n}.options[${r}]`;if(!D(t)){e.fail(i,`must be an object`);return}(typeof t.value!=`string`||t.value.length===0)&&e.fail(`${i}.value`,`must be a non-empty string`),e.copy(t.label,`${i}.label`)}):e.fail(`${n}.options`,`is only allowed on a select field`)),t.constraints!==void 0&&st(e,t.constraints,`${n}.constraints`)}function lt(e,t,n){return!D(t)||Object.keys(t).length===0?(e.fail(n,`must be a non-empty object`),[]):Object.entries(t).map(([t,r])=>(Xe.test(t)||e.fail(`${n}.${t}`,`is not a valid field name`),ct(e,r,`${n}.${t}`),t))}function ut(e,t){if(!D(t))return e.fail(`setup.form`,`must be an object`),[];t.note!==void 0&&e.copy(t.note,`setup.form.note`);let n=lt(e,t.args,`setup.form.args`),r=[];t.triggers!==void 0&&(!D(t.triggers)||Object.keys(t.triggers).length===0?e.fail(`setup.form.triggers`,`must be a non-empty object`):Object.entries(t.triggers).forEach(([t,i])=>{if(!O(t,nt)){e.fail(`setup.form.triggers.${t}`,`is not a trigger kind`);return}r.push(t),n.push(...lt(e,i,`setup.form.triggers.${t}`))}));let i=n.filter((e,t)=>n.indexOf(e)!==t);return Array.from(new Set(i)).forEach(t=>e.fail(`setup.form.${t}`,`is declared more than once`)),r}function dt(e){return D(e)?[e.args,...Object.values(D(e.triggers)?e.triggers:{})].some(e=>D(e)&&Object.values(e).some(e=>D(e)&&e.type===`repo-picker`)):!1}function ft(e,t){e.templateCopy(t,`setup.message`)&&t.length>E&&e.fail(`setup.message`,`must be at most ${E} characters`)}function pt(e,t,n){if(!O(t.mode,$e)){e.fail(`setup.mode`,`is not a supported mode`);return}if(t.mode===`direct`){e.templateValue(t.prompt,`setup.prompt`),t.message!==void 0&&ft(e,t.message),n.length!==1&&e.fail(`setup.form.triggers`,`must declare exactly one trigger kind`),n.includes(`event`)&&!dt(t.form)&&e.fail(`setup.form`,`must declare a repository field for an event trigger`),t.filter!==void 0&&(n.includes(`event`)?e.templateValue(t.filter,`setup.filter`):e.fail(`setup.filter`,`is only allowed for an event trigger`));return}ft(e,t.message),e.absent(t,`prompt`,`setup`,`is only allowed for direct setup`),e.absent(t,`filter`,`setup`,`is only allowed for direct setup`)}function mt(e){return D(e)&&e.setup!==void 0}function ht(e){let t=new at;if(!D(e))return{valid:!1,errors:[`manifest: must be an object`]};let{setup:n}=e;return D(n)?n.version===`1.0`?((typeof e.id!=`string`||!T.test(e.id))&&t.fail(`id`,`must be a lowercase slug`),t.copy(e.name,`name`),t.copy(e.description,`description`),e.skill!==void 0&&(typeof e.skill!=`string`||!T.test(e.skill))&&t.fail(`skill`,`must be a lowercase slug`),ot(t,e.requires),pt(t,n,ut(t,n.form)),{valid:t.errors.length===0,errors:t.errors}):{valid:!1,errors:[`setup.version: must be "1.0"`]}:{valid:!1,errors:[`setup: must be an object`]}}function gt(e){let t=[],n=new Map;return e.forEach(e=>{if(!mt(e))return;let{valid:r,errors:i}=ht(e);if(!r){console.warn(`Rejected a setup manifest:`,i.join(`; `));return}let a=e;if(n.has(a.id)){console.warn(`Rejected a setup manifest: id "${a.id}" is already registered`);return}t.push(a),n.set(a.id,a)}),{entries:t,findById:e=>n.get(e)??null}}var _t=gt(p),vt=se,yt=`AUTOMATION_INTERFACE`in vt?vt.AUTOMATION_INTERFACE:void 0,k={list:`/automations`,setup:`/automations/new/:automationId`,detail:`/automations/:automationId`,templates:`/automations/templates`},bt={list:`/v1`,detail:`/v1/{id}`,dispatch:`/v1/{id}/dispatch`,runs:`/v1/{id}/runs`,tarball:`/v1/{id}/tarball`,health:`/health`,capabilities:`/v1/capabilities`,validate:`/v1/validate`,createPrompt:`/v1/preset/prompt`,createPlugin:`/v1/preset/plugin`},xt={fileKind:`automation`,fileVersion:1,filenameSuffix:`.automation.json`,importDefaults:{repoProvider:`github`,placeholderEventSource:`agent-canvas-import`}},St=`https://docs.openhands.dev/openhands/usage/automations/overview`,Ct=[`github-pr-reviewer`,`github-repo-monitor`,`slack-channel-monitor`],wt=[`github`,`slack`],Tt={present:!1,label:null,help:null,required:!1,min:null,max:null},Et={name:{present:!0,label:null,help:null,required:!0,min:null,max:null},prompt:{present:!0,label:null,help:null,required:!1,min:null,max:null},model:{present:!0,label:null,help:null,required:!1,min:null,max:null},timeout:{present:!0,label:null,help:null,required:!1,min:1,max:null},schedule:{present:!0,label:null,help:null,required:!1,min:null,max:null}};function Dt(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Ot(){return new Set(p.flatMap(e=>Dt(e)&&typeof e.id==`string`?[e.id]:[]))}function kt(e){if(e===void 0)return null;let t=Ye(e,{catalogIds:Ot(),mountedRoutes:k});return t.valid?e:(console.warn(`Rejected the automation interface manifest:`,t.errors.join(`; `)),null)}var A=kt(yt);function At(e,t){return e.replace(`:automationId`,encodeURIComponent(t))}function j(){return(A?.routes??k).list}function jt(e){return At((A?.routes??k).setup,e)}function Mt(e){return At((A?.routes??k).detail,e)}function Nt(){return A?.routes.templates??k.templates}function M(e){return(A?.endpoints??bt)[e]}function N(e,t){return M(e).replace(`{id}`,encodeURIComponent(t))}var Pt={sidebarLabel:null,commandMenuTitle:null,commandMenuDescription:null,commandMenuKeywords:null,listTitle:null,listSubtitle:null,detailBackLabel:null,editTitle:null};function Ft(){return A?{sidebarLabel:A.navigation.sidebar.label,commandMenuTitle:A.navigation.commandMenu.title,commandMenuDescription:A.navigation.commandMenu.description,commandMenuKeywords:A.navigation.commandMenu.keywords,listTitle:A.pages.list.title,listSubtitle:A.pages.list.subtitle,detailBackLabel:A.pages.detail.backLabel,editTitle:A.pages.edit.title}:Pt}function It(e){if(!A)return Et[e];let t=A.attributes[e];return t?{present:!0,label:t.label,help:t.help??null,required:t.required,min:t.constraints?.min??null,max:t.constraints?.max??null}:Tt}function P(){return A?.importExport??xt}function Lt(){return A?.docsUrl??St}function Rt(){return A?.featuredAutomationIds??Ct}function zt(){return A?.responderIntegrationIds??wt}function Bt(){let e=A?.navigation.subPages;return e?e.map(e=>({page:e.page,to:e.page===`templates`?Nt():j(),label:e.label,icon:e.icon})):null}function Vt(){let e=A?.pages.list;return!e?.overview||!e.filters||!e.sort||!e.insights?null:{overview:e.overview,filters:e.filters,sort:e.sort,insights:e.insights}}function Ht(){return A?.pages.templates??null}var Ut=/["'\\]/;function F(e){let t=Object.values(e.form.triggers??{});return Object.assign({},...t,e.form.args)}function Wt(e,t){let n=t?.triggers?.cron?.timezones;if(!n?.length)return{};let r=n.map(e=>({value:e,label:e}));return Object.fromEntries(Object.entries(F(e)).filter(([,e])=>e.type===`timezone`).map(([e])=>[e,{options:r}]))}function I(e,t,n={}){return n[e]?.options??t.options??[]}function Gt(e){return Object.fromEntries(Object.entries(F(e)).map(([e,t])=>[e,t.default??``]))}function Kt(e,t,n,r){let i=(n??``).trim();if(!i)return t.required?{code:`required`}:null;let{minLength:a,maxLength:o,format:s}=t.constraints??{};if(a!==void 0&&i.length<a)return{code:`minLength`,length:a};if(o!==void 0&&i.length>o)return{code:`maxLength`,length:o};if(s===`safeExpressionLiteral`&&Ut.test(i))return{code:`unsafeExpressionLiteral`};let c=I(e,t,r);return c.length>0&&!c.some(e=>e.value===i)?{code:`invalidOption`}:null}function qt(e,t,n={}){return Object.entries(F(e)).reduce((e,[r,i])=>{let a=Kt(r,i,t[r],n);return a?{...e,[r]:a}:e},{})}var L=/\{\{([A-Za-z0-9_]+(?:\.[A-Za-z0-9_]+)*)\}\}/g;function Jt(e,t){return t.split(`.`).reduce((e,t)=>{if(!(typeof e!=`object`||!e))return e[t]},e)}function R(e){return typeof e==`string`?e:typeof e==`number`||typeof e==`boolean`?String(e):``}function z(e,t){return e.replace(L,(e,n)=>R(Jt(t,n)))}function Yt(e,t){return e.replace(L,(e,n)=>R(t[n]))}var B=M(`createPrompt`),Xt={cron:[`schedule`,`timezone`],event:[`on`]},Zt=[`ref`],Qt=/\{\{form\.([A-Za-z0-9_.]+)\}\}/g;function $t(e){let t=Object.entries(F(e)).find(([,e])=>e.type===`repo-picker`);return t?{name:t[0],field:t[1]}:null}function en(e){let t=Object.entries(e.form.triggers??{});if(t.length===0)return null;let[n,r]=t[0];return{kind:n,fields:r??{}}}function V(e,t){let{setup:n}=e;if(n.mode!==`direct`||!n.prompt)return null;let r={form:t,automation:e},i=$t(n),a=i?t[i.name]:void 0,o={name:a?`${e.name} - ${a}`:e.name,prompt:z(n.prompt,r)};if(a&&i?.field.provider){let e=Zt.filter(e=>e in t);o.repos=[{url:a,...Object.fromEntries(e.map(e=>[e,t[e]])),provider:i.field.provider}]}let s=en(n);if(s){let e=Xt[s.kind],a=Object.keys(s.fields).filter(t=>e.includes(t));o.trigger={type:s.kind,...Object.fromEntries(a.map(e=>[e,t[e]??``])),...s.kind===`event`&&{source:i?.field.provider??``,...n.filter&&{filter:z(n.filter,r)}}}}return o}function tn(e,t){let n=V(e,t);return n?{automationId:e.id,endpoint:B,draft:n}:null}function nn(e,t){return[h(e),e.setup.message?z(e.setup.message,{form:t,automation:e}):``].filter(Boolean).join(`
1
+ import{a as e}from"./rolldown-runtime-Cyuzqnbw.js";import{St as t}from"./vendor-styling-Ck5D_A2Q.js";import{j as n}from"./vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~kv3pap4j-oGvLV0dO.js";import{O as r,Q as i,T as a,W as o,a as s,b as c,ct as l,d as u,dt as ee,f as te,h as d,lt as ne,n as re,p as ie,w as ae}from"./active-backend-context-B_bg5h9O.js";import{t as f}from"./proxy-b4aqL4SX.js";import{t as oe}from"./vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~ht43enc2-C0JXQb_q.js";import{n as se,t as p}from"./vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~9pstowjp-BOVIFA_g.js";var m=e(t(),1),ce=new Map(oe.map(e=>[e.name,e]));function le(e){return Object.keys(e.requires.integrations)}function ue(e){return Object.entries(e.requires.integrations).filter(([,e])=>e.required!==!1).map(([e])=>e)}function h(e){return ce.get(e.skill??e.id)?.triggers[0]??null}function de(e){return h(e)??`Set up the ${e.name} automation`}var fe=[`form`,`automation`],pe=[`list`,`templates`],me=[`layout-dashboard`,`sparkles`,`bot`,`circle-alert`,`activity`,`timer`],he=[`automations`,`needs-attention`,`total-runs`,`average-duration`],ge={automations:[`active`],"needs-attention":[],"total-runs":[],"average-duration":[]},g={status:[`all`,`active`,`failing`,`disabled`],trigger:[`all`,`schedule`,`event`]},_e=Object.keys(g),ve=[`last-run`,`runs`,`name`],ye=/<[A-Za-z/!]/,be=/^[a-z0-9]+(-[a-z0-9]+)*$/,_=`https://docs.openhands.dev/`,xe=/^[a-z][a-z-]*$/,Se=/^\.[a-z][a-z.]*json$/,Ce=/^[a-z0-9][a-z0-9.-]*$/,we=/^\/[A-Za-z0-9/{}_-]*$/,Te=/^[^{}]*\{id\}[^{}]*$/,Ee=[`github`,`gitlab`,`bitbucket`],v={name:{type:`text`,required:!0},prompt:{type:`textarea`,required:!1},model:{type:`llm-profile`,required:!1},timeout:{type:`number`,required:!1},schedule:{type:`schedule`,required:!1}},De=Object.keys(v),y=[`list`,`health`,`capabilities`,`validate`,`createPrompt`,`createPlugin`],b=[`detail`,`dispatch`,`runs`,`tarball`];function x(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function S(e,t){return typeof e==`string`&&t.includes(e)}var Oe=class{errors=[];fail(e,t){return this.errors.push(`${e}: ${t}`),!1}copy(e,t){return typeof e!=`string`||e.length===0?this.fail(t,`must be a non-empty string`):ye.test(e)?this.fail(t,`must not contain markup`):!0}closed(e,t,n){Object.keys(e).filter(e=>!t.includes(e)).forEach(e=>this.fail(`${n}.${e}`,`is not allowed`))}record(e,t){return x(e)?!0:(this.fail(t,`must be an object`),!1)}};function ke(e,t,n){e.record(t,`routes`)&&(e.closed(t,[`list`,`setup`,`detail`,`templates`],`routes`),[`list`,`setup`,`detail`].forEach(r=>{t[r]!==n[r]&&e.fail(`routes.${r}`,`must be "${n[r]}"`)}),t.templates!==void 0&&t.templates!==n.templates&&e.fail(`routes.templates`,n.templates===void 0?`is not a route this host mounts`:`must be "${n.templates}"`))}function Ae(e,t){if(!Array.isArray(t)||t.length===0){e.fail(`navigation.subPages`,`must be a non-empty array`);return}let n=new Set;t.forEach((t,r)=>{let i=`navigation.subPages[${r}]`;if(!e.record(t,i))return;e.closed(t,[`page`,`label`,`icon`],i);let{page:a,label:o,icon:s}=t;S(a,pe)?n.has(a)?e.fail(`${i}.page`,`repeats a page`):n.add(a):e.fail(`${i}.page`,`is not a sub-page this host serves`),e.copy(o,`${i}.label`),je(e,s,`${i}.icon`)})}function je(e,t,n){S(t,me)||e.fail(n,`is not an icon this host ships`)}function Me(e,t){if(e.record(t,`navigation`)){if(e.closed(t,[`sidebar`,`commandMenu`,`subPages`],`navigation`),e.record(t.sidebar,`navigation.sidebar`)&&(e.closed(t.sidebar,[`label`],`navigation.sidebar`),e.copy(t.sidebar.label,`navigation.sidebar.label`)),e.record(t.commandMenu,`navigation.commandMenu`)){let n=t.commandMenu;e.closed(n,[`title`,`description`,`keywords`],`navigation.commandMenu`),e.copy(n.title,`navigation.commandMenu.title`),e.copy(n.description,`navigation.commandMenu.description`),e.copy(n.keywords,`navigation.commandMenu.keywords`)}t.subPages!==void 0&&Ae(e,t.subPages)}}function Ne(e,t){e.record(t,`pages`)&&(e.closed(t,[`list`,`detail`,`edit`,`templates`],`pages`),e.record(t.list,`pages.list`)&&(e.closed(t.list,[`title`,`subtitle`,`overview`,`filters`,`sort`,`insights`],`pages.list`),e.copy(t.list.title,`pages.list.title`),e.copy(t.list.subtitle,`pages.list.subtitle`),t.list.overview!==void 0&&Pe(e,t.list.overview),t.list.filters!==void 0&&Le(e,t.list.filters),t.list.sort!==void 0&&Be(e,t.list.sort),t.list.insights!==void 0&&Ve(e,t.list.insights)),e.record(t.detail,`pages.detail`)&&(e.closed(t.detail,[`backLabel`],`pages.detail`),e.copy(t.detail.backLabel,`pages.detail.backLabel`)),e.record(t.edit,`pages.edit`)&&(e.closed(t.edit,[`title`],`pages.edit`),e.copy(t.edit.title,`pages.edit.title`)),t.templates!==void 0&&He(e,t.templates))}function Pe(e,t){let n=`pages.list.overview`;if(!e.record(t,n))return;e.closed(t,[`label`,`tiles`],n),e.copy(t.label,`${n}.label`);let{tiles:r}=t;if(!Array.isArray(r)||r.length===0){e.fail(`${n}.tiles`,`must be a non-empty array`);return}let i=new Set;r.forEach((t,r)=>{Fe(e,t,i,`${n}.tiles[${r}]`)})}function Fe(e,t,n,r){if(!e.record(t,r))return;e.closed(t,[`metric`,`label`,`detail`,`zeroDetail`,`icon`],r);let{metric:i,label:a,detail:o,zeroDetail:s,icon:c}=t;if(e.copy(a,`${r}.label`),je(e,c,`${r}.icon`),!S(i,he)){e.fail(`${r}.metric`,`is not a metric this host computes`),e.copy(o,`${r}.detail`),s!==void 0&&e.copy(s,`${r}.zeroDetail`);return}n.has(i)?e.fail(`${r}.metric`,`repeats a metric`):n.add(i),Ie(e,o,i,`${r}.detail`),s!==void 0&&Ie(e,s,i,`${r}.zeroDetail`)}function Ie(e,t,n,r){if(!e.copy(t,r))return;let i=ge[n];(i.length===0?/\{\{/:RegExp(`\\{\\{(?!(?:${i.join(`|`)})\\}\\})`)).test(t)&&e.fail(r,`uses a placeholder this metric does not expose`)}function Le(e,t){let n=`pages.list.filters`;if(!Array.isArray(t)||t.length===0){e.fail(n,`must be a non-empty array`);return}let r=new Set;t.forEach((t,i)=>{Re(e,t,r,`${n}[${i}]`)})}function Re(e,t,n,r){if(!e.record(t,r))return;e.closed(t,[`id`,`label`,`options`],r);let{id:i,label:a,options:o}=t;if(e.copy(a,`${r}.label`),!S(i,_e)){e.fail(`${r}.id`,`is not a filter this host implements`);return}n.has(i)?e.fail(`${r}.id`,`repeats a filter`):n.add(i),ze(e,o,g[i],`${r}.options`)}function ze(e,t,n,r){if(!Array.isArray(t)||t.length<2){e.fail(r,`must offer at least two options`);return}let i=new Set;t.forEach((t,a)=>{let o=`${r}[${a}]`;if(!e.record(t,o))return;e.closed(t,[`value`,`label`],o);let{value:s,label:c}=t;S(s,n)?i.has(s)?e.fail(`${o}.value`,`repeats a value`):i.add(s):e.fail(`${o}.value`,`is not a value this host implements`),e.copy(c,`${o}.label`)}),i.has(`all`)||e.fail(r,`must offer the "all" option`)}function Be(e,t){let n=`pages.list.sort`;if(!e.record(t,n))return;e.closed(t,[`label`,`options`,`default`],n);let{label:r,options:i,default:a}=t;e.copy(r,`${n}.label`);let o=new Set;!Array.isArray(i)||i.length===0?e.fail(`${n}.options`,`must be a non-empty array`):i.forEach((t,r)=>{let i=`${n}.options[${r}]`;e.record(t,i)&&(e.closed(t,[`value`,`label`],i),S(t.value,ve)?o.has(t.value)?e.fail(`${i}.value`,`repeats a value`):o.add(t.value):e.fail(`${i}.value`,`is not a sort this host implements`),e.copy(t.label,`${i}.label`))}),(typeof a!=`string`||!o.has(a))&&e.fail(`${n}.default`,`must be one of the declared option values`)}var C={health:[`healthy`,`failing`,`running`,`disabled`,`neverRun`,`checking`],lastRun:[`label`,`never`,`justNow`],stats:[`runs`,`recentSuccess`,`averageDuration`]};function Ve(e,t){let n=`pages.list.insights`;e.record(t,n)&&(e.closed(t,Object.keys(C),n),Object.keys(C).forEach(r=>{let i=`${n}.${r}`,a=t[r];if(!e.record(a,i))return;let o=C[r];e.closed(a,o,i),o.forEach(t=>{e.copy(a[t],`${i}.${t}`)})}))}function He(e,t){let n=`pages.templates`;e.record(t,n)&&(e.closed(t,[`title`,`description`],n),e.copy(t.title,`${n}.title`),e.copy(t.description,`${n}.description`))}function Ue(e,t){let n=x(t.routes)?t.routes:{},r=x(t.navigation)?t.navigation:{},i=x(t.pages)?t.pages:{},a=x(i.list)?i.list:{},o=[[`routes.templates`,n.templates],[`navigation.subPages`,r.subPages],[`pages.templates`,i.templates],[`pages.list.overview`,a.overview],[`pages.list.filters`,a.filters],[`pages.list.sort`,a.sort],[`pages.list.insights`,a.insights]],s=o.filter(([,e])=>e===void 0).map(([e])=>e);s.length===0||s.length===o.length||e.fail(`interface`,`the sub-page surface must be declared whole; missing ${s.join(`, `)}`)}function We(e,t,n,r){if(!e.record(n,r))return;e.closed(n,[`type`,`label`,`help`,`required`,`constraints`],r);let{type:i,label:a,help:o,required:s,constraints:c}=n;if(i!==t.type&&e.fail(`${r}.type`,`must be "${t.type}", the control this host renders`),e.copy(a,`${r}.label`),o!==void 0&&e.copy(o,`${r}.help`),s!==t.required&&e.fail(`${r}.required`,`must be ${t.required}, what this host enforces`),c!==void 0){if(t.type!==`number`)e.fail(`${r}.constraints`,`is only allowed on a number attribute`);else if(e.record(c,`${r}.constraints`)){e.closed(c,[`min`,`max`],`${r}.constraints`);let{min:t,max:n}=c;t!==void 0&&t!==1&&e.fail(`${r}.constraints.min`,`must be the 1 this host enforces`),n!==void 0&&(!Number.isInteger(n)||n<1)&&e.fail(`${r}.constraints.max`,`must be a positive integer`)}}}function Ge(e,t){if(!e.record(t,`attributes`))return;let n=Object.keys(t);n.length===0&&e.fail(`attributes`,`must declare at least one attribute`),n.forEach(n=>{if(!De.includes(n)){e.fail(`attributes.${n}`,`is not a settable attribute`);return}We(e,v[n],t[n],`attributes.${n}`)})}function Ke(e,t){if(!e.record(t,`importExport`))return;e.closed(t,[`fileKind`,`fileVersion`,`filenameSuffix`,`importDefaults`],`importExport`);let{fileKind:n,fileVersion:r,filenameSuffix:i,importDefaults:a}=t;(typeof n!=`string`||!xe.test(n))&&e.fail(`importExport.fileKind`,`must be a lowercase slug`),r!==1&&e.fail(`importExport.fileVersion`,`must be 1`),(typeof i!=`string`||!Se.test(i))&&e.fail(`importExport.filenameSuffix`,`must be a .json suffix`),e.record(a,`importExport.importDefaults`)&&(e.closed(a,[`repoProvider`,`placeholderEventSource`],`importExport.importDefaults`),(typeof a.repoProvider!=`string`||!Ee.includes(a.repoProvider))&&e.fail(`importExport.importDefaults.repoProvider`,`is not a supported provider`),(typeof a.placeholderEventSource!=`string`||!Ce.test(a.placeholderEventSource))&&e.fail(`importExport.importDefaults.placeholderEventSource`,`must be a lowercase event source`))}function qe(e,t){if(!e.record(t,`endpoints`))return;let n=[...y,...b];e.closed(t,n,`endpoints`);let r=n=>{let r=t[n];return typeof r!=`string`||!we.test(r)||r.includes(`//`)?(e.fail(`endpoints.${n}`,`must be a rooted service-relative path`),null):r};y.forEach(t=>{let n=r(t);n!==null&&/[{}]/.test(n)&&e.fail(`endpoints.${t}`,`must not carry a substitution`)}),b.forEach(t=>{let n=r(t);n!==null&&!Te.test(n)&&e.fail(`endpoints.${t}`,`must carry exactly one {id}`)})}function w(e,t,n){if(!Array.isArray(t)||t.length===0)return e.fail(n,`must be a non-empty array`),[];let r=t.filter(t=>typeof t==`string`&&be.test(t)?!0:(e.fail(n,`must contain only lowercase slugs`),!1));return new Set(r).size!==r.length&&e.fail(n,`must not repeat an id`),r}var Je=[`version`,`routes`,`navigation`,`pages`,`docsUrl`,`attributes`,`importExport`,`endpoints`,`featuredAutomationIds`,`responderIntegrationIds`];function Ye(e,t){if(!x(e))return{valid:!1,errors:[`interface: must be an object`]};if(e.version!==`1.0`)return{valid:!1,errors:[`interface.version: must be "1.0"`]};let n=new Oe;return n.closed(e,Je,`interface`),ke(n,e.routes,t.mountedRoutes),Me(n,e.navigation),Ne(n,e.pages),(typeof e.docsUrl!=`string`||!e.docsUrl.startsWith(_))&&n.fail(`docsUrl`,`must start with ${_}`),Ge(n,e.attributes),Ke(n,e.importExport),qe(n,e.endpoints),w(n,e.featuredAutomationIds,`featuredAutomationIds`).forEach(e=>{t.catalogIds.has(e)||n.fail(`featuredAutomationIds`,`${e} is not a catalog entry`)}),w(n,e.responderIntegrationIds,`responderIntegrationIds`),Ue(n,e),{valid:n.errors.length===0,errors:n.errors}}var T=/^[a-z0-9]+(-[a-z0-9]+)*$/,Xe=/^[a-z][A-Za-z0-9]*$/,Ze=/<[A-Za-z/!]/,Qe=RegExp(`\\{\\{(?!(?:${fe.join(`|`)})\\.[A-Za-z0-9_.]+\\}\\})`),$e=[`direct`,`assisted`],et=[`text`,`textarea`,`select`,`cron`,`timezone`,`repo-picker`],tt=[`github`,`gitlab`,`bitbucket`],nt=[`cron`,`event`],rt=[`safeExpressionLiteral`],E=2e3;function D(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function O(e,t){return typeof e==`string`&&t.includes(e)}function it(e,t){return typeof e==`number`&&Number.isInteger(e)&&e>=t}var at=class{errors=[];fail(e,t){return this.errors.push(`${e}: ${t}`),!1}copy(e,t){return typeof e!=`string`||e.length===0?this.fail(t,`must be a non-empty string`):Ze.test(e)?this.fail(t,`must not contain markup`):!0}placeholders(e,t){return Qe.test(e)?this.fail(t,`uses an unknown placeholder namespace`):!0}templateCopy(e,t){return this.copy(e,t)&&this.placeholders(e,t)}templateValue(e,t){return typeof e!=`string`||e.length===0?this.fail(t,`must be a non-empty string`):this.placeholders(e,t)}absent(e,t,n,r){return t in e?this.fail(`${n}.${t}`,r):!0}};function ot(e,t){if(!D(t)){e.fail(`requires`,`must be an object`);return}let{integrations:n,features:r}=t;!D(n)||Object.keys(n).length===0?e.fail(`requires.integrations`,`must be a non-empty object`):Object.entries(n).forEach(([t,n])=>{let r=`requires.integrations.${t}`;if(!D(n)){e.fail(r,`must be an object`);return}e.copy(n.message,`${r}.message`),`required`in n&&n.required!==!1&&e.fail(`${r}.required`,`may only be false`);let i=[`message`,`required`];Object.keys(n).filter(e=>!i.includes(e)).forEach(t=>e.fail(`${r}.${t}`,`is not allowed`))}),r!==void 0&&(!Array.isArray(r)||r.length===0?e.fail(`requires.features`,`must be a non-empty array`):r.forEach((t,n)=>{(typeof t!=`string`||t.length===0)&&e.fail(`requires.features[${n}]`,`must be a non-empty string`)}))}function st(e,t,n){if(!D(t)||Object.keys(t).length===0){e.fail(n,`must be a non-empty object`);return}let{minLength:r,maxLength:i,format:a}=t;r!==void 0&&!it(r,0)&&e.fail(`${n}.minLength`,`must be a non-negative integer`),i!==void 0&&!it(i,1)&&e.fail(`${n}.maxLength`,`must be a positive integer`),a!==void 0&&!O(a,rt)&&e.fail(`${n}.format`,`is not a supported format`)}function ct(e,t,n){if(!D(t)){e.fail(n,`must be an object`);return}let{type:r,label:i,help:a,placeholder:o,required:s,provider:c,options:l}=t;O(r,et)||e.fail(`${n}.type`,`is not a supported field type`),e.copy(i,`${n}.label`),e.copy(a,`${n}.help`),o!==void 0&&e.copy(o,`${n}.placeholder`),t.default!==void 0&&typeof t.default!=`string`&&e.fail(`${n}.default`,`must be a string`),typeof s!=`boolean`&&e.fail(`${n}.required`,`must be a boolean`),c!==void 0&&!O(c,tt)&&e.fail(`${n}.provider`,`is not a supported provider`),r===`repo-picker`&&c===void 0&&e.fail(`${n}.provider`,`is required for a repository field`),l!==void 0&&(r===`select`?!Array.isArray(l)||l.length===0?e.fail(`${n}.options`,`must be a non-empty array`):l.forEach((t,r)=>{let i=`${n}.options[${r}]`;if(!D(t)){e.fail(i,`must be an object`);return}(typeof t.value!=`string`||t.value.length===0)&&e.fail(`${i}.value`,`must be a non-empty string`),e.copy(t.label,`${i}.label`)}):e.fail(`${n}.options`,`is only allowed on a select field`)),t.constraints!==void 0&&st(e,t.constraints,`${n}.constraints`)}function lt(e,t,n){return!D(t)||Object.keys(t).length===0?(e.fail(n,`must be a non-empty object`),[]):Object.entries(t).map(([t,r])=>(Xe.test(t)||e.fail(`${n}.${t}`,`is not a valid field name`),ct(e,r,`${n}.${t}`),t))}function ut(e,t){if(!D(t))return e.fail(`setup.form`,`must be an object`),[];t.note!==void 0&&e.copy(t.note,`setup.form.note`);let n=lt(e,t.args,`setup.form.args`),r=[];t.triggers!==void 0&&(!D(t.triggers)||Object.keys(t.triggers).length===0?e.fail(`setup.form.triggers`,`must be a non-empty object`):Object.entries(t.triggers).forEach(([t,i])=>{if(!O(t,nt)){e.fail(`setup.form.triggers.${t}`,`is not a trigger kind`);return}r.push(t),n.push(...lt(e,i,`setup.form.triggers.${t}`))}));let i=n.filter((e,t)=>n.indexOf(e)!==t);return Array.from(new Set(i)).forEach(t=>e.fail(`setup.form.${t}`,`is declared more than once`)),r}function dt(e){return D(e)?[e.args,...Object.values(D(e.triggers)?e.triggers:{})].some(e=>D(e)&&Object.values(e).some(e=>D(e)&&e.type===`repo-picker`)):!1}function ft(e,t){e.templateCopy(t,`setup.message`)&&t.length>E&&e.fail(`setup.message`,`must be at most ${E} characters`)}function pt(e,t,n){if(!O(t.mode,$e)){e.fail(`setup.mode`,`is not a supported mode`);return}if(t.mode===`direct`){e.templateValue(t.prompt,`setup.prompt`),t.message!==void 0&&ft(e,t.message),n.length!==1&&e.fail(`setup.form.triggers`,`must declare exactly one trigger kind`),n.includes(`event`)&&!dt(t.form)&&e.fail(`setup.form`,`must declare a repository field for an event trigger`),t.filter!==void 0&&(n.includes(`event`)?e.templateValue(t.filter,`setup.filter`):e.fail(`setup.filter`,`is only allowed for an event trigger`));return}ft(e,t.message),e.absent(t,`prompt`,`setup`,`is only allowed for direct setup`),e.absent(t,`filter`,`setup`,`is only allowed for direct setup`)}function mt(e){return D(e)&&e.setup!==void 0}function ht(e){let t=new at;if(!D(e))return{valid:!1,errors:[`manifest: must be an object`]};let{setup:n}=e;return D(n)?n.version===`1.0`?((typeof e.id!=`string`||!T.test(e.id))&&t.fail(`id`,`must be a lowercase slug`),t.copy(e.name,`name`),t.copy(e.description,`description`),e.skill!==void 0&&(typeof e.skill!=`string`||!T.test(e.skill))&&t.fail(`skill`,`must be a lowercase slug`),ot(t,e.requires),pt(t,n,ut(t,n.form)),{valid:t.errors.length===0,errors:t.errors}):{valid:!1,errors:[`setup.version: must be "1.0"`]}:{valid:!1,errors:[`setup: must be an object`]}}function gt(e){let t=[],n=new Map;return e.forEach(e=>{if(!mt(e))return;let{valid:r,errors:i}=ht(e);if(!r){console.warn(`Rejected a setup manifest:`,i.join(`; `));return}let a=e;if(n.has(a.id)){console.warn(`Rejected a setup manifest: id "${a.id}" is already registered`);return}t.push(a),n.set(a.id,a)}),{entries:t,findById:e=>n.get(e)??null}}var _t=gt(p),vt=se,yt=`AUTOMATION_INTERFACE`in vt?vt.AUTOMATION_INTERFACE:void 0,k={list:`/automations`,setup:`/automations/new/:automationId`,detail:`/automations/:automationId`,templates:`/automations/templates`},bt={list:`/v1`,detail:`/v1/{id}`,dispatch:`/v1/{id}/dispatch`,runs:`/v1/{id}/runs`,tarball:`/v1/{id}/tarball`,health:`/health`,capabilities:`/v1/capabilities`,validate:`/v1/validate`,createPrompt:`/v1/preset/prompt`,createPlugin:`/v1/preset/plugin`},xt={fileKind:`automation`,fileVersion:1,filenameSuffix:`.automation.json`,importDefaults:{repoProvider:`github`,placeholderEventSource:`agent-canvas-import`}},St=`https://docs.openhands.dev/openhands/usage/automations/overview`,Ct=[`github-pr-reviewer`,`github-repo-monitor`,`slack-channel-monitor`],wt=[`github`,`slack`],Tt={present:!1,label:null,help:null,required:!1,min:null,max:null},Et={name:{present:!0,label:null,help:null,required:!0,min:null,max:null},prompt:{present:!0,label:null,help:null,required:!1,min:null,max:null},model:{present:!0,label:null,help:null,required:!1,min:null,max:null},timeout:{present:!0,label:null,help:null,required:!1,min:1,max:null},schedule:{present:!0,label:null,help:null,required:!1,min:null,max:null}};function Dt(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Ot(){return new Set(p.flatMap(e=>Dt(e)&&typeof e.id==`string`?[e.id]:[]))}function kt(e){if(e===void 0)return null;let t=Ye(e,{catalogIds:Ot(),mountedRoutes:k});return t.valid?e:(console.warn(`Rejected the automation interface manifest:`,t.errors.join(`; `)),null)}var A=kt(yt);function At(e,t){return e.replace(`:automationId`,encodeURIComponent(t))}function j(){return(A?.routes??k).list}function jt(e){return At((A?.routes??k).setup,e)}function Mt(e){return At((A?.routes??k).detail,e)}function Nt(){return A?.routes.templates??k.templates}function M(e){return(A?.endpoints??bt)[e]}function N(e,t){return M(e).replace(`{id}`,encodeURIComponent(t))}var Pt={sidebarLabel:null,commandMenuTitle:null,commandMenuDescription:null,commandMenuKeywords:null,listTitle:null,listSubtitle:null,detailBackLabel:null,editTitle:null};function Ft(){return A?{sidebarLabel:A.navigation.sidebar.label,commandMenuTitle:A.navigation.commandMenu.title,commandMenuDescription:A.navigation.commandMenu.description,commandMenuKeywords:A.navigation.commandMenu.keywords,listTitle:A.pages.list.title,listSubtitle:A.pages.list.subtitle,detailBackLabel:A.pages.detail.backLabel,editTitle:A.pages.edit.title}:Pt}function It(e){if(!A)return Et[e];let t=A.attributes[e];return t?{present:!0,label:t.label,help:t.help??null,required:t.required,min:t.constraints?.min??null,max:t.constraints?.max??null}:Tt}function P(){return A?.importExport??xt}function Lt(){return A?.docsUrl??St}function Rt(){return A?.featuredAutomationIds??Ct}function zt(){return A?.responderIntegrationIds??wt}function Bt(){let e=A?.navigation.subPages;return e?e.map(e=>({page:e.page,to:e.page===`templates`?Nt():j(),label:e.label,icon:e.icon})):null}function Vt(){let e=A?.pages.list;return!e?.overview||!e.filters||!e.sort||!e.insights?null:{overview:e.overview,filters:e.filters,sort:e.sort,insights:e.insights}}function Ht(){return A?.pages.templates??null}var Ut=/["'\\]/;function F(e){let t=Object.values(e.form.triggers??{});return Object.assign({},...t,e.form.args)}function Wt(e,t){let n=t?.triggers?.cron?.timezones;if(!n?.length)return{};let r=n.map(e=>({value:e,label:e}));return Object.fromEntries(Object.entries(F(e)).filter(([,e])=>e.type===`timezone`).map(([e])=>[e,{options:r}]))}function I(e,t,n={}){return n[e]?.options??t.options??[]}function Gt(e){return Object.fromEntries(Object.entries(F(e)).map(([e,t])=>[e,t.default??``]))}function Kt(e,t,n,r){let i=(n??``).trim();if(!i)return t.required?{code:`required`}:null;let{minLength:a,maxLength:o,format:s}=t.constraints??{};if(a!==void 0&&i.length<a)return{code:`minLength`,length:a};if(o!==void 0&&i.length>o)return{code:`maxLength`,length:o};if(s===`safeExpressionLiteral`&&Ut.test(i))return{code:`unsafeExpressionLiteral`};let c=I(e,t,r);return c.length>0&&!c.some(e=>e.value===i)?{code:`invalidOption`}:null}function qt(e,t,n={}){return Object.entries(F(e)).reduce((e,[r,i])=>{let a=Kt(r,i,t[r],n);return a?{...e,[r]:a}:e},{})}var L=/\{\{([A-Za-z0-9_]+(?:\.[A-Za-z0-9_]+)*)\}\}/g;function Jt(e,t){return t.split(`.`).reduce((e,t)=>{if(!(typeof e!=`object`||!e))return e[t]},e)}function R(e){return typeof e==`string`?e:typeof e==`number`||typeof e==`boolean`?String(e):``}function z(e,t){return e.replace(L,(e,n)=>R(Jt(t,n)))}function Yt(e,t){return e.replace(L,(e,n)=>R(t[n]))}var B=M(`createPrompt`),Xt={cron:[`schedule`,`timezone`],event:[`on`]},Zt=[`ref`],Qt=/\{\{form\.([A-Za-z0-9_.]+)\}\}/g;function $t(e){let t=Object.entries(F(e)).find(([,e])=>e.type===`repo-picker`);return t?{name:t[0],field:t[1]}:null}function en(e){let t=Object.entries(e.form.triggers??{});if(t.length===0)return null;let[n,r]=t[0];return{kind:n,fields:r??{}}}function V(e,t){let{setup:n}=e;if(n.mode!==`direct`||!n.prompt)return null;let r={form:t,automation:e},i=$t(n),a=i?t[i.name]:void 0,o={name:a?`${e.name} - ${a}`:e.name,prompt:z(n.prompt,r)};if(a&&i?.field.provider){let e=Zt.filter(e=>e in t);o.repos=[{url:a,...Object.fromEntries(e.map(e=>[e,t[e]])),provider:i.field.provider}]}let s=en(n);if(s){let e=Xt[s.kind],a=Object.keys(s.fields).filter(t=>e.includes(t));o.trigger={type:s.kind,...Object.fromEntries(a.map(e=>[e,t[e]??``])),...s.kind===`event`&&{source:i?.field.provider??``,...n.filter&&{filter:z(n.filter,r)}}}}return o}function tn(e,t){let n=V(e,t);return n?{automationId:e.id,endpoint:B,draft:n}:null}function nn(e,t){return[h(e),e.setup.message?z(e.setup.message,{form:t,automation:e}):``].filter(Boolean).join(`
2
2
 
3
3
  `)}function rn(e){let t=Array.from(e.matchAll(Qt),e=>e[1]);return Array.from(new Set(t))}function an(e){let t={},n=V(e,Object.fromEntries(Object.keys(F(e.setup)).map(e=>[e,`{{form.${e}}}`])));if(!n)return t;let r=(e,n)=>{if(Array.isArray(e)){e.forEach((e,t)=>r(e,`${n}[${t}]`));return}if(typeof e==`object`&&e){Object.entries(e).forEach(([e,t])=>r(t,n?`${n}.${e}`:e));return}if(typeof e==`string`){let r=rn(e);r.length>0&&(t[n]=r)}};return r(n,``),t}var H=`/api/automation`,U=n.create();async function W(e={}){let t=await te();return{...a,...t?{[r]:t}:{},...e}}U.interceptors.request.use(async e=>{let t=await W();if(Object.entries(t).forEach(([t,n])=>{e.headers.set(t,n)}),e.baseURL)return e;let n=ne();if(!n)throw new i;e.baseURL=n.host;let r=n.apiKey?.trim();return r&&e.headers.set(`X-Session-API-Key`,r),e});function G(e){return typeof e==`string`&&e.trim()||null}function on(e){return typeof e==`string`?G(e):G(e.sdk_version)??G(e.version)}function K(e,t){let n=new URLSearchParams;return n.set(`limit`,String(e)),n.set(`offset`,String(t)),n.toString()}function sn(e){return e.trigger.type===`event`?{type:`event`,source:e.trigger.source,on:e.trigger.on,...e.trigger.filter&&{filter:e.trigger.filter}}:{type:`cron`,schedule:e.trigger.schedule,timezone:e.timezone??e.trigger.timezone??`UTC`}}function cn(){return typeof crypto<`u`&&typeof crypto.randomUUID==`function`?`pending.${crypto.randomUUID()}`:`pending.${Date.now()}.${Math.random().toString(36).slice(2,10)}`}function ln(e){if(!e.prompt)throw Error(`An automation prompt is required for import.`);let{importDefaults:t}=P(),n=e.repository?[{url:e.repository,...e.branch&&{ref:e.branch},...!e.repository.includes(`://`)&&!e.repository.startsWith(`git@`)&&{provider:t.repoProvider}}]:void 0;return{path:`${H}${M(e.plugins?.length?`createPlugin`:`createPrompt`)}`,body:{name:e.name,prompt:e.prompt,trigger:{type:`event`,source:t.placeholderEventSource,on:cn()},...e.model&&{model:e.model},...n&&{repos:n},...e.plugins?.length&&{plugins:e.plugins.map(e=>({source:e}))},...e.timeout!=null&&{timeout:e.timeout}}}}async function q(e){let t=e.apiKey.trim();return{baseURL:e.host,headers:await W(t?{"X-Session-API-Key":t}:{})}}async function J(e){return W(e.orgId?{"X-Org-Id":e.orgId}:{})}var Y=class e{static async syncTelemetryConsent(e=u()){if(l().backend.kind!==`local`)return;let t=await ie();await U.post(`${H}/v1/telemetry/consent`,{consent_granted:e===`granted`,frontend_distinct_id:t},{timeout:5e3}),e!==`granted`&&t&&s(t)}static async getSdkVersion(){let e=l(),t=`${H}/sdk-version`;try{let n;if(e.backend.kind===`cloud`)n=await f({backend:e.backend,method:`GET`,path:t,headers:await J(e),timeoutSeconds:5});else{let{data:e}=await U.get(t,{timeout:5e3});n=e}return on(n)}catch{return null}}static async listAutomations(e={}){let{limit:t=50,offset:n=0}=e,r=l().backend;if(r.kind===`cloud`)return f({backend:r,method:`GET`,path:`${H}${M(`list`)}?${K(t,n)}`,headers:await W()});let{data:i}=await U.get(`${H}${M(`list`)}`,{params:{limit:t,offset:n}});return i}static async getAutomations(t=50,n=0){return e.listAutomations({limit:t,offset:n})}static async getAutomation(e){let t=l().backend,n=`${H}${N(`detail`,e)}`;if(t.kind===`cloud`)return f({backend:t,method:`GET`,path:n,headers:await W()});let{data:r}=await U.get(n);return r}static async createAutomation(e){let t=l(),{path:n,body:r}=ln(e),i;if(t.backend.kind===`cloud`)i=await f({backend:t.backend,method:`POST`,path:n,body:r,headers:await J(t)});else{let{data:e}=await U.post(n,r,await q(t.backend));i=e}let a=`${H}${N(`detail`,i.id)}`,o={trigger:sn(e),enabled:!1};try{if(t.backend.kind===`cloud`)return await f({backend:t.backend,method:`PATCH`,path:a,body:o,headers:await J(t)});let{data:e}=await U.patch(a,o,await q(t.backend));return e}catch(e){try{t.backend.kind===`cloud`?await f({backend:t.backend,method:`DELETE`,path:a,headers:await J(t)}):await U.delete(a,await q(t.backend))}catch(t){throw AggregateError([e,t],`Failed to disable the imported automation and clean it up.`)}throw e}}static async updateAutomation(e,t){let n=l().backend,r=`${H}${N(`detail`,e)}`;if(n.kind===`cloud`)return f({backend:n,method:`PATCH`,path:r,body:t,headers:await W()});let{data:i}=await U.patch(r,t);return i}static async deleteAutomation(e){let t=l().backend,n=`${H}${N(`detail`,e)}`;if(t.kind===`cloud`){await f({backend:t,method:`DELETE`,path:n,headers:await W()});return}await U.delete(n)}static async dispatchAutomation(e){let t=l().backend,n=`${H}${N(`dispatch`,e)}`;if(t.kind===`cloud`)return f({backend:t,method:`POST`,path:n,headers:await W()});let{data:r}=await U.post(n);return r}static async cancelAutomationRun(e){let t=l().backend,n=`${H}/v1/runs/${encodeURIComponent(e)}/cancel`;if(t.kind===`cloud`)return f({backend:t,method:`POST`,path:n,headers:await W()});let{data:r}=await U.post(n);return r}static async listAutomationRuns(e,t={}){let{limit:n=50,offset:r=0}=t,i=l().backend,a=`${H}${N(`runs`,e)}`;if(i.kind===`cloud`)return f({backend:i,method:`GET`,path:`${a}?${K(n,r)}`,headers:await W()});let{data:o}=await U.get(a,{params:{limit:n,offset:r}});return o}static async getAutomationRuns(t,n=50,r=0){return e.listAutomationRuns(t,{limit:n,offset:r})}static async toggleAutomation(t,n){return e.updateAutomation(t,{enabled:n})}static async downloadTarball(e,t){let n=l().backend,r=`${H}${N(`tarball`,e)}`,i;if(n.kind===`cloud`)i=await f({backend:n,method:`GET`,path:r,responseType:`blob`,headers:await W()});else{let{data:e}=await U.get(r,{responseType:`blob`});i=e}let a=URL.createObjectURL(i),o=document.createElement(`a`);o.href=a,o.download=`${t}.tar`,o.click(),URL.revokeObjectURL(a)}static async getCapabilities(){let e=l().backend,t=`${H}${M(`capabilities`)}`;if(e.kind===`cloud`)return f({backend:e,method:`GET`,path:t,headers:await W()});let{data:n}=await U.get(t);return n}static async validateDraft(e){let t=l().backend,n=`${H}${M(`validate`)}`;if(t.kind===`cloud`)return f({backend:t,method:`POST`,path:n,body:e,headers:await W()});let{data:r}=await U.post(n,e);return r}static async createAutomationDraft(e){let t=l().backend,n=`${H}${B}`;if(t.kind===`cloud`)return f({backend:t,method:`POST`,path:n,body:e,headers:await W()});let{data:r}=await U.post(n,e);return r}static async checkHealth(){let e=l().backend,t=`${H}${M(`health`)}`;try{if(e.kind===`cloud`)return await f({backend:e,method:`GET`,path:t,timeoutSeconds:5,headers:await W()});let{data:n}=await U.get(t,{timeout:5e3});return n}catch{return{status:`error`}}}},un=`automation-sdk-version`,dn=3600*1e3,fn=`\0`,X=new Map,Z=new Map;function Q(e){let t=X.get(e);if(t){if(t.expiresAt<=Date.now()){X.delete(e);return}return t.version}}function $(e,t){X.set(e,{expiresAt:Date.now()+dn,version:t})}function pn(e){let t=Q(e);if(t!==void 0)return Promise.resolve(t);let n=Z.get(e);if(n)return n;if(typeof Y.getSdkVersion!=`function`)return $(e,null),Promise.resolve(null);let r=Y.getSdkVersion().then(t=>($(e,t),t)).catch(()=>($(e,null),null)).finally(()=>{Z.delete(e)});return Z.set(e,r),r}function mn(){let e=re(),{backend:t}=e,n=[un,t.id,t.kind,t.host,e.orgId??``].join(fn),[r,i]=m.useState(()=>Q(n)??null);return m.useEffect(()=>{if(ee(t)){i(null);return}let e=Q(n);if(e!==void 0){i(e);return}let r=!0;return i(null),pn(n).then(e=>{r&&i(e)}),()=>{r=!1}},[t,n]),r}var hn=()=>{let{backend:e}=re(),t=mn(),n=m.useCallback(()=>({backendKind:e.kind,agentServerVersion:e.kind===`local`?o(e.host):null,automationSdkVersion:t??null}),[t,e.host,e.kind]);m.useEffect(()=>{d(n())},[n]);let r={current_url:window.location.href},i=(e,t={})=>{d(n()),c(e,{...r,...t})};return{trackLoginButtonClick:({provider:e})=>{i(`login_button_clicked`,{provider:e})},trackConversationCreated:({conversationId:e,taskId:t,hasRepository:n,gitProvider:r,hasWorkspace:a,workspaceMode:o,hasInitialQuery:s,agentType:c,hasParentConversation:l,entryPoint:u})=>{i(`conversation_start_requested`,{conversation_id:e,task_id:t,is_start_task:e.startsWith(`task-`),has_repository:n,git_provider:r,has_workspace:a,workspace_mode:o,has_initial_query:s,agent_type:c,has_parent_conversation:l,entry_point:u})},trackPushButtonClick:()=>{i(`push_button_clicked`)},trackPullButtonClick:()=>{i(`pull_button_clicked`)},trackCreatePrButtonClick:()=>{i(`create_pr_button_clicked`)},trackUserSignupCompleted:()=>{i(`user_signup_completed`,{signup_timestamp:new Date().toISOString()})},trackPrebuiltAutomationEnabled:({automationId:e,automationName:t,automationCategory:n})=>{i(`prebuilt_automation_enabled`,{automation_id:e,automation_name:t,automation_category:n})},trackAutomationSetupOpened:({automationId:e})=>{i(`automation_setup_opened`,{automation_id:e})},trackAutomationSetupValidated:({automationId:e})=>{i(`automation_setup_validated`,{automation_id:e})},trackAutomationSetupCreated:({automationId:e,setupMode:t})=>{i(`automation_setup_created`,{automation_id:e,setup_mode:t})},trackAutomationSetupFailed:({automationId:e,setupMode:t})=>{i(`automation_setup_failed`,{automation_id:e,setup_mode:t})},trackInitialQuerySubmitted:({entryPoint:e,queryCharacterLength:t,replayJsonSize:n})=>{i(`initial_query_submitted`,{entry_point:e,query_character_length:t,replay_json_size:n})},trackUserMessageSent:({sessionMessageCount:e,currentMessageLength:t})=>{i(`user_message_sent`,{session_message_count:e,current_message_length:t})},trackDownloadVsCodeButtonClicked:()=>{i(`download_via_vscode_button_clicked`)},trackSettingsSaved:({llmModel:e,llmApiKeySet:t,searchApiKeySet:n,remoteRuntimeResourceFactor:r})=>{i(`settings_saved`,{LLM_MODEL:e,LLM_API_KEY_SET:t,SEARCH_API_KEY_SET:n,REMOTE_RUNTIME_RESOURCE_FACTOR:r})},trackMcpConfigUpdated:({sseServersCount:e,stdioServersCount:t})=>{i(`mcp_config_updated`,{has_mcp_config:!0,sse_servers_count:e,stdio_servers_count:t})},trackDownloadTrajectoryButtonClicked:()=>{i(`download_trajectory_button_clicked`)},trackConversationExported:e=>{i(`conversation_exported`,{format:e})},trackAutomationCreatedButton:({backendKind:e})=>{i(`automation_created_button`,{backend_kind:e})},trackAutomationExecuted:({backendKind:e})=>{i(`automation_executed`,{backend_kind:e})},trackAutomationDeleted:({backendKind:e})=>{i(`automation_deleted`,{backend_kind:e})},trackAutomationDisableButton:({backendKind:e})=>{i(`automation_disable_button`,{backend_kind:e})},trackAutomationEdited:({backendKind:e})=>{i(`automation_edited`,{backend_kind:e})},trackAutomationExported:({backendKind:e})=>{i(`automation_exported`,{backend_kind:e})},trackAutomationActivityLogExported:({backendKind:e,format:t})=>{i(`automation_activity_log_exported`,{backend_kind:e,format:t})},trackAutomationImported:({backendKind:e})=>{i(`automation_imported`,{backend_kind:e})},trackBackendAdded:({backendKind:e,connectionMethod:t,hasApiKey:n,source:r,agentServerVersion:a,backendVersion:o})=>{i(`backend_added`,{...ae({backendKind:e,agentServerVersion:a,backendVersion:o,connectionMethod:t}),has_api_key:n,source:r})},trackOnboardingStarted:()=>{i(`onboarding_started`)},trackOnboardingStepViewed:({step:e,stepIndex:t,totalSteps:n,agent:r})=>{i(`onboarding_step_viewed`,{step:e,step_index:t,total_steps:n,agent:r})},trackOnboardingCompleted:({agent:e})=>{i(`onboarding_completed`,{agent:e})},trackOnboardingSkipped:({step:e,stepIndex:t,totalSteps:n,agent:r})=>{i(`onboarding_skipped`,{step:e,step_index:t,total_steps:n,agent:r})}}};export{Bt as C,de as D,h as E,le as O,zt as S,_t as T,Lt as _,tn as a,P as b,F as c,Wt as d,qt as f,It as g,jt as h,V as i,ue as k,I as l,j as m,Y as n,an as o,Mt as p,nn as r,Yt as s,hn as t,Gt as u,Vt as v,Ht as w,Ft as x,Rt as y};
@@ -1 +1 @@
1
- import{a as e}from"./rolldown-runtime-Cyuzqnbw.js";import{St as t}from"./vendor-styling-Ck5D_A2Q.js";import{t as n}from"./useQuery-BCnzy4LX.js";import{n as r}from"./active-backend-context-BBvP-bI2.js";import{t as i}from"./agent-server-conversation-service.api-0RztSdJJ.js";var a=e(t(),1),o=1e3*60*5,s=1e3*60*15,c=(e,t)=>{let c=r(),l=(0,a.useRef)({cid:e,backendId:c.backend.id});l.current.cid!==e&&(l.current={cid:e,backendId:c.backend.id});let u=l.current.backendId!==c.backend.id;return n({queryKey:[`user`,`conversation`,e,c.backend.id,c.orgId],queryFn:async()=>e?(await i.batchGetAppConversations([e]))[0]??null:null,enabled:!!e&&!e.startsWith(`task-`)&&!u,retry:!1,refetchInterval:t,staleTime:o,gcTime:s})};export{c as t};
1
+ import{a as e}from"./rolldown-runtime-Cyuzqnbw.js";import{St as t}from"./vendor-styling-Ck5D_A2Q.js";import{t as n}from"./useQuery-BCnzy4LX.js";import{n as r}from"./active-backend-context-B_bg5h9O.js";import{t as i}from"./agent-server-conversation-service.api-BheU4HX3.js";var a=e(t(),1),o=1e3*60*5,s=1e3*60*15,c=(e,t)=>{let c=r(),l=(0,a.useRef)({cid:e,backendId:c.backend.id});l.current.cid!==e&&(l.current={cid:e,backendId:c.backend.id});let u=l.current.backendId!==c.backend.id;return n({queryKey:[`user`,`conversation`,e,c.backend.id,c.orgId],queryFn:async()=>e?(await i.batchGetAppConversations([e]))[0]??null:null,enabled:!!e&&!e.startsWith(`task-`)&&!u,retry:!1,refetchInterval:t,staleTime:o,gcTime:s})};export{c as t};
@@ -1 +1 @@
1
- import{yt as e}from"./vendor-styling-Ck5D_A2Q.js";import{U as t}from"./vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~lq5hicxx-cHFhpUBq.js";import{t as n}from"./sdk-section-page-CS4GWn0y.js";var r=e(),i=new Set([`verification.confirmation_mode`,`verification.security_analyzer`]);function a({scope:e=`personal`,renderTopContent:t,testId:a=`verification-settings-screen`}){return(0,r.jsx)(n,{scope:e,settingsSources:[{settingsSource:`conversation_settings`,sectionKeys:[`verification`]},{settingsSource:`agent_settings`,sectionKeys:[`verification`],excludeKeys:i}],header:t?()=>t():void 0,testId:a})}var o=t(a);export{o as default};
1
+ import{yt as e}from"./vendor-styling-Ck5D_A2Q.js";import{U as t}from"./vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~lq5hicxx-cHFhpUBq.js";import{t as n}from"./sdk-section-page-m_cjygxR.js";var r=e(),i=new Set([`verification.confirmation_mode`,`verification.security_analyzer`]);function a({scope:e=`personal`,renderTopContent:t,testId:a=`verification-settings-screen`}){return(0,r.jsx)(n,{scope:e,settingsSources:[{settingsSource:`conversation_settings`,sectionKeys:[`verification`]},{settingsSource:`agent_settings`,sectionKeys:[`verification`],excludeKeys:i}],header:t?()=>t():void 0,testId:a})}var o=t(a);export{o as default};
package/build/index.html CHANGED
@@ -1,13 +1,13 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>OpenHands</title><meta name="description" content="Let&#x27;s Start Building!"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/><link rel="modulepreload" href="/assets/manifest-2a36a8f8.js"/><link rel="modulepreload" href="/assets/entry.client-DzbDyLkV.js"/><link rel="modulepreload" href="/assets/rolldown-runtime-Cyuzqnbw.js"/><link rel="modulepreload" href="/assets/vendor-styling-Ck5D_A2Q.js"/><link rel="modulepreload" href="/assets/active-backend-context-BBvP-bI2.js"/><link rel="modulepreload" href="/assets/vendor~entry.client-zSIea5EO.js"/><link rel="modulepreload" href="/assets/providers-tBzTpz1w.js"/><link rel="modulepreload" href="/assets/vendor~entry.client-CgNUwtQL.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~kv3pap4j-oGvLV0dO.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~lq5hicxx-cHFhpUBq.js"/><link rel="modulepreload" href="/assets/utils-DPQfkd-7.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~cy4jtuc2-rfV8mQ9m.js"/><link rel="modulepreload" href="/assets/agent-server-ui-style-scope-DdG0ZAHu.js"/><link rel="modulepreload" href="/assets/root-gstBEjty.js"/><link rel="modulepreload" href="/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~gxu4j2ea-Cwhh3zLe.js"/><link rel="modulepreload" href="/assets/useQuery-BCnzy4LX.js"/><link rel="modulepreload" href="/assets/use-config-CPwqciXN.js"/><link rel="modulepreload" href="/assets/use-onboarding-completion-CtNJxkXG.js"/><link rel="modulepreload" href="/assets/brand-button-CJcwjnfb.js"/><link rel="modulepreload" href="/assets/base-modal-3NmIOKDm.js"/><link rel="modulepreload" href="/assets/loading-spinner-CN3riY7k.js"/><link rel="modulepreload" href="/assets/modal-backdrop-BSzNhM4r.js"/><link rel="modulepreload" href="/assets/modal-body-duRaxj_K.js"/><link rel="modulepreload" href="/assets/navigation-context-CQZwH_tC.js"/><link rel="modulepreload" href="/assets/use-save-settings-pSjRhD_m.js"/><link rel="modulepreload" href="/assets/use-settings-BHWsOcIG.js"/><link rel="modulepreload" href="/assets/color-themes-DTj5Ylbr.js"/><link rel="modulepreload" href="/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~hjcjabwg-CuQhkiS7.js"/><link rel="modulepreload" href="/assets/useQueries-Cjv3E8_1.js"/><link rel="modulepreload" href="/assets/organization-service.api-C4GYWwj9.js"/><link rel="modulepreload" href="/assets/proxy-DCI9S-LA.js"/><link rel="modulepreload" href="/assets/form-control-classes-DLN3Qgub.js"/><link rel="modulepreload" href="/assets/modal-classes-CLEXO6dj.js"/><link rel="modulepreload" href="/assets/useMutation-ChpkYxI5.js"/><link rel="modulepreload" href="/assets/use-tracking-CGCsBWhg.js"/><link rel="modulepreload" href="/assets/settings-service.api-DZp7E7A9.js"/><link rel="modulepreload" href="/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~9pstowjp-BOVIFA_g.js"/><link rel="modulepreload" href="/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~ht43enc2-C0JXQb_q.js"/><link rel="modulepreload" href="/assets/settings-CWFxymAf.js"/><link rel="stylesheet" href="/assets/root-BfM_kC_d.css"/></head><body data-agent-server-ui="" class="m-0"><div data-agent-server-ui="" style="--oh-color-logo:#cfb755;--oh-color-base:var(--cool-grey-950);--oh-color-base-secondary:var(--cool-grey-925);--oh-color-danger:#e76a5e;--oh-color-success:#a5e75e;--oh-color-basic:var(--cool-grey-400);--oh-color-tertiary:var(--cool-grey-800);--oh-color-tertiary-light:var(--cool-grey-300);--oh-color-content:var(--cool-grey-100);--oh-color-content-2:var(--cool-grey-50);--oh-background:var(--cool-grey-950);--oh-foreground:var(--cool-grey-100);--oh-surface:var(--cool-grey-925);--oh-surface-foreground:var(--cool-grey-100);--oh-surface-raised:var(--cool-grey-900);--oh-surface-deep:var(--cool-grey-975);--oh-overlay:var(--cool-grey-925);--oh-overlay-foreground:var(--cool-grey-100);--oh-muted:var(--cool-grey-400);--oh-text-secondary:var(--cool-grey-300);--oh-text-tertiary:var(--cool-grey-200);--oh-text-dim:var(--cool-grey-500);--oh-text-subtle:var(--cool-grey-600);--oh-interactive-hover:var(--cool-grey-700);--oh-interactive-hover-low:var(--cool-grey-900);--oh-interactive-active:var(--cool-grey-800);--oh-interactive-selected:var(--cool-grey-600);--oh-scrollbar:color-mix(in srgb, var(--cool-grey-400) 30%, transparent);--oh-scrollbar-hover:color-mix(in srgb, var(--cool-grey-400) 50%, transparent);--oh-default:var(--cool-grey-800);--oh-default-foreground:var(--cool-grey-100);--oh-accent-foreground:var(--cool-grey-950);--oh-success:#a5e75e;--oh-success-foreground:var(--cool-grey-950);--oh-warning-foreground:var(--cool-grey-950);--oh-danger:#e76a5e;--oh-danger-foreground:var(--cool-grey-50);--oh-segment:var(--cool-grey-925);--oh-segment-foreground:var(--cool-grey-100);--oh-border-width:1px;--oh-field-border-width:1px;--oh-border:var(--cool-grey-700);--oh-border-input:var(--cool-grey-600);--oh-border-subtle:var(--cool-grey-800);--oh-separator:rgba(113, 120, 136, 0.5);--oh-focus:#ffffff;--oh-status-success:#1FBD53;--oh-status-error:#FF684E;--oh-link:var(--cool-grey-100);--oh-radius:8px;--oh-field-radius:8px;--oh-surface-shadow:none;--oh-overlay-shadow:none;--oh-field-shadow:none;--oh-bg-dark:var(--cool-grey-950);--oh-bg-light:var(--cool-grey-900);--oh-bg-input:var(--cool-grey-800);--oh-bg-workspace:var(--cool-grey-925);--oh-text-editor-base:var(--cool-grey-400);--oh-text-editor-active:var(--cool-grey-300);--oh-bg-editor-sidebar:var(--cool-grey-925);--oh-bg-editor-active:var(--cool-grey-900);--oh-border-editor-sidebar:var(--cool-grey-800);--oh-bg-neutral-muted:color-mix(in srgb, var(--cool-grey-300) 20%, transparent)"><div class="dark min-h-screen text-foreground" data-theme="dark"><script>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>OpenHands</title><meta name="description" content="Let&#x27;s Start Building!"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/><link rel="modulepreload" href="/assets/manifest-e1c3bc3b.js"/><link rel="modulepreload" href="/assets/entry.client-EBn3ZtNP.js"/><link rel="modulepreload" href="/assets/rolldown-runtime-Cyuzqnbw.js"/><link rel="modulepreload" href="/assets/vendor-styling-Ck5D_A2Q.js"/><link rel="modulepreload" href="/assets/active-backend-context-B_bg5h9O.js"/><link rel="modulepreload" href="/assets/vendor~entry.client-zSIea5EO.js"/><link rel="modulepreload" href="/assets/providers-CdrPPm0z.js"/><link rel="modulepreload" href="/assets/vendor~entry.client-CgNUwtQL.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~kv3pap4j-oGvLV0dO.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~lq5hicxx-cHFhpUBq.js"/><link rel="modulepreload" href="/assets/utils-DPQfkd-7.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~cy4jtuc2-rfV8mQ9m.js"/><link rel="modulepreload" href="/assets/agent-server-ui-style-scope-DdG0ZAHu.js"/><link rel="modulepreload" href="/assets/root-CBBi6IAe.js"/><link rel="modulepreload" href="/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~gxu4j2ea-Cwhh3zLe.js"/><link rel="modulepreload" href="/assets/useQuery-BCnzy4LX.js"/><link rel="modulepreload" href="/assets/use-config-DapX3pjC.js"/><link rel="modulepreload" href="/assets/use-onboarding-completion-6kWOW3ul.js"/><link rel="modulepreload" href="/assets/brand-button-CJcwjnfb.js"/><link rel="modulepreload" href="/assets/base-modal-3NmIOKDm.js"/><link rel="modulepreload" href="/assets/loading-spinner-CN3riY7k.js"/><link rel="modulepreload" href="/assets/modal-backdrop-BSzNhM4r.js"/><link rel="modulepreload" href="/assets/modal-body-duRaxj_K.js"/><link rel="modulepreload" href="/assets/navigation-context-CQZwH_tC.js"/><link rel="modulepreload" href="/assets/use-save-settings-DIEurJ3D.js"/><link rel="modulepreload" href="/assets/use-settings-BmLzQjnC.js"/><link rel="modulepreload" href="/assets/color-themes-DTj5Ylbr.js"/><link rel="modulepreload" href="/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~hjcjabwg-CuQhkiS7.js"/><link rel="modulepreload" href="/assets/useQueries-Cjv3E8_1.js"/><link rel="modulepreload" href="/assets/organization-service.api-DK8csGvK.js"/><link rel="modulepreload" href="/assets/proxy-b4aqL4SX.js"/><link rel="modulepreload" href="/assets/form-control-classes-DLN3Qgub.js"/><link rel="modulepreload" href="/assets/modal-classes-CLEXO6dj.js"/><link rel="modulepreload" href="/assets/useMutation-ChpkYxI5.js"/><link rel="modulepreload" href="/assets/use-tracking-salbPJxT.js"/><link rel="modulepreload" href="/assets/settings-service.api-DfPYaxZJ.js"/><link rel="modulepreload" href="/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~9pstowjp-BOVIFA_g.js"/><link rel="modulepreload" href="/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~ht43enc2-C0JXQb_q.js"/><link rel="modulepreload" href="/assets/settings-CWFxymAf.js"/><link rel="stylesheet" href="/assets/root-CRK9fOFd.css"/></head><body data-agent-server-ui="" class="m-0"><div data-agent-server-ui="" style="--oh-color-logo:#cfb755;--oh-color-base:var(--cool-grey-950);--oh-color-base-secondary:var(--cool-grey-925);--oh-color-danger:#e76a5e;--oh-color-success:#a5e75e;--oh-color-basic:var(--cool-grey-400);--oh-color-tertiary:var(--cool-grey-800);--oh-color-tertiary-light:var(--cool-grey-300);--oh-color-content:var(--cool-grey-100);--oh-color-content-2:var(--cool-grey-50);--oh-background:var(--cool-grey-950);--oh-foreground:var(--cool-grey-100);--oh-surface:var(--cool-grey-925);--oh-surface-foreground:var(--cool-grey-100);--oh-surface-raised:var(--cool-grey-900);--oh-surface-deep:var(--cool-grey-975);--oh-overlay:var(--cool-grey-925);--oh-overlay-foreground:var(--cool-grey-100);--oh-muted:var(--cool-grey-400);--oh-text-secondary:var(--cool-grey-300);--oh-text-tertiary:var(--cool-grey-200);--oh-text-dim:var(--cool-grey-500);--oh-text-subtle:var(--cool-grey-600);--oh-interactive-hover:var(--cool-grey-700);--oh-interactive-hover-low:var(--cool-grey-900);--oh-interactive-active:var(--cool-grey-800);--oh-interactive-selected:var(--cool-grey-600);--oh-scrollbar:color-mix(in srgb, var(--cool-grey-400) 30%, transparent);--oh-scrollbar-hover:color-mix(in srgb, var(--cool-grey-400) 50%, transparent);--oh-default:var(--cool-grey-800);--oh-default-foreground:var(--cool-grey-100);--oh-accent-foreground:var(--cool-grey-950);--oh-success:#a5e75e;--oh-success-foreground:var(--cool-grey-950);--oh-warning-foreground:var(--cool-grey-950);--oh-danger:#e76a5e;--oh-danger-foreground:var(--cool-grey-50);--oh-segment:var(--cool-grey-925);--oh-segment-foreground:var(--cool-grey-100);--oh-border-width:1px;--oh-field-border-width:1px;--oh-border:var(--cool-grey-700);--oh-border-input:var(--cool-grey-600);--oh-border-subtle:var(--cool-grey-800);--oh-separator:rgba(113, 120, 136, 0.5);--oh-focus:#ffffff;--oh-status-success:#1FBD53;--oh-status-error:#FF684E;--oh-link:var(--cool-grey-100);--oh-radius:8px;--oh-field-radius:8px;--oh-surface-shadow:none;--oh-overlay-shadow:none;--oh-field-shadow:none;--oh-bg-dark:var(--cool-grey-950);--oh-bg-light:var(--cool-grey-900);--oh-bg-input:var(--cool-grey-800);--oh-bg-workspace:var(--cool-grey-925);--oh-text-editor-base:var(--cool-grey-400);--oh-text-editor-active:var(--cool-grey-300);--oh-bg-editor-sidebar:var(--cool-grey-925);--oh-bg-editor-active:var(--cool-grey-900);--oh-border-editor-sidebar:var(--cool-grey-800);--oh-bg-neutral-muted:color-mix(in srgb, var(--cool-grey-300) 20%, transparent)"><div class="dark min-h-screen text-foreground" data-theme="dark"><script>
2
2
  console.log(
3
3
  "💿 Hey developer 👋. You can provide a way better UX than this " +
4
4
  "when your app is loading JS modules and/or running `clientLoader` " +
5
5
  "functions. Check out https://reactrouter.com/start/framework/route-module#hydratefallback " +
6
6
  "for more information."
7
7
  );
8
- </script><div data-rht-toaster="" style="position:fixed;z-index:9999;top:16px;left:16px;right:16px;bottom:16px;pointer-events:none"></div><div id="modal-portal-exit"></div></div></div><script>window.__reactRouterContext = {"basename":"/","future":{"unstable_optimizeDeps":false,"v8_passThroughRequests":false,"v8_trailingSlashAwareDataRequests":false,"unstable_previewServerPrerendering":false,"v8_middleware":false,"v8_splitRouteModules":false,"v8_viteEnvironmentApi":false},"routeDiscovery":{"mode":"initial"},"ssr":false,"isSpaMode":true};window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());</script><script type="module" async="">import "/assets/manifest-2a36a8f8.js";
9
- import * as route0 from "/assets/root-gstBEjty.js";
8
+ </script><div data-rht-toaster="" style="position:fixed;z-index:9999;top:16px;left:16px;right:16px;bottom:16px;pointer-events:none"></div><div id="modal-portal-exit"></div></div></div><script>window.__reactRouterContext = {"basename":"/","future":{"unstable_optimizeDeps":false,"v8_passThroughRequests":false,"v8_trailingSlashAwareDataRequests":false,"unstable_previewServerPrerendering":false,"v8_middleware":false,"v8_splitRouteModules":false,"v8_viteEnvironmentApi":false},"routeDiscovery":{"mode":"initial"},"ssr":false,"isSpaMode":true};window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());</script><script type="module" async="">import "/assets/manifest-e1c3bc3b.js";
9
+ import * as route0 from "/assets/root-CBBi6IAe.js";
10
10
 
11
11
  window.__reactRouterRouteModules = {"root":route0};
12
12
 
13
- import("/assets/entry.client-DzbDyLkV.js");</script><!--$--><script>window.__reactRouterContext.streamController.enqueue("[{\"_1\":2,\"_3\":-5,\"_4\":-5},\"loaderData\",{},\"actionData\",\"errors\"]\n");</script><!--$--><script>window.__reactRouterContext.streamController.close();</script><!--/$--><!--/$--></body></html>
13
+ import("/assets/entry.client-EBn3ZtNP.js");</script><!--$--><script>window.__reactRouterContext.streamController.enqueue("[{\"_1\":2,\"_3\":-5,\"_4\":-5},\"loaderData\",{},\"actionData\",\"errors\"]\n");</script><!--$--><script>window.__reactRouterContext.streamController.close();</script><!--/$--><!--/$--></body></html>
@@ -2,7 +2,7 @@
2
2
  "_comment": "Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.",
3
3
  "versions": {
4
4
  "agentServer": "1.40.1",
5
- "agentCanvas": "1.11.0",
5
+ "agentCanvas": "1.12.0",
6
6
  "automation": "1.6.0"
7
7
  },
8
8
  "compatibility": {
@@ -1,2 +1,2 @@
1
- const e=require("../../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),n=require("../../../../i18n/declaration.cjs"),r=require("../../../../utils/utils.cjs"),i=require("../../../../icons/checkmark.cjs"),a=require("../../../../utils/form-control-classes.cjs"),o=require("../../../../ui/typography.cjs"),s=require("../../../../ui/combobox-caret.cjs"),c=require("../../../../ui/context-menu.cjs"),l=require("../../context-menu/context-menu-list-item.cjs"),u=require("../../../../hooks/use-click-outside-element.cjs"),d=require("../../../../icons/settings-gear.cjs"),f=require("../../../shared/navigation-link.cjs"),p=require("../../../../ui/divider.cjs"),m=require("../../../../hooks/use-chat-input-llm-profile-state.cjs");let h=require("react");h=e.__toESM(h,1);let g=require("react/jsx-runtime");var _=18;function v(e){return e.length<=_?e:`${e.slice(0,_)}…`}function y({onClose:e,dividerInset:a,settingsLinkClassName:s,settingsIconClassName:c}){let{t:u}=t.useTranslation(`openhands`),{profiles:h,currentProfileName:_,currentProfileModel:v,canSwitchProfile:y,selectProfile:b}=m.useChatInputLlmProfileState(),x=y&&h.length>0,S=y?null:_,C=t=>{b(t),e()};return(0,g.jsxs)(g.Fragment,{children:[x&&(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`li`,{role:`presentation`,className:`px-2 pt-1 pb-0.5`,children:(0,g.jsx)(o.Typography.Text,{className:`text-[11px] font-medium text-[var(--oh-text-dim)] uppercase tracking-wide leading-4`,children:u(n.I18nKey.SETTINGS$AVAILABLE_PROFILES)})}),h.map(t=>{let n=t.name===_;return(0,g.jsxs)(l.ContextMenuListItem,{testId:`chat-input-llm-profile-option-${t.name}`,onClick:r=>{if(r.preventDefault(),r.stopPropagation(),n){e();return}C(t.name)},className:r.cn(`flex flex-col items-stretch gap-0.5`,n&&`bg-[var(--oh-interactive-hover)]`),children:[(0,g.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,g.jsx)(`span`,{className:`flex-1 truncate text-sm leading-5`,title:t.model??t.name,children:t.name}),n&&(0,g.jsx)(i.default,{width:14,height:14,className:`shrink-0`,"aria-hidden":!0})]}),t.model&&(0,g.jsx)(`span`,{className:`block truncate text-xs leading-4 text-[var(--oh-muted)]`,children:t.model})]},t.name)})]}),S&&(0,g.jsx)(`li`,{className:`text-sm`,"data-testid":`chat-input-llm-profile-current`,children:(0,g.jsxs)(`div`,{className:`flex flex-col gap-0.5 p-2 leading-5 text-[var(--oh-foreground)]`,children:[(0,g.jsx)(`span`,{className:`truncate`,title:S,children:S}),v&&(0,g.jsx)(`span`,{className:`truncate text-xs leading-4 text-[var(--oh-muted)]`,children:v})]})}),(x||S)&&(0,g.jsx)(p.Divider,{inset:a}),(0,g.jsx)(`li`,{className:`text-sm`,children:(0,g.jsxs)(f.NavigationLink,{to:`/settings/llm`,onClick:e,className:r.cn(`flex h-[30px] items-center gap-2 rounded p-2 leading-5 text-[var(--oh-foreground)] hover:bg-[var(--oh-interactive-hover)] transition-colors`,s),children:[(0,g.jsx)(d.default,{width:16,height:16,className:r.cn(`shrink-0`,c),"aria-hidden":!0}),(0,g.jsx)(`span`,{children:u(n.I18nKey.SETTINGS$LLM_PROFILES)})]})})]})}function b(){let{t:e}=t.useTranslation(`openhands`),{profiles:i,currentProfileName:o,isLoading:l,isSwitching:d}=m.useChatInputLlmProfileState(),[f,p]=h.default.useState(!1),_=h.default.useRef(null),b=u.useClickOutsideElement(()=>p(!1),_);if(l||i.length===0)return null;let x=o??e(n.I18nKey.LLM$SELECT_MODEL_PLACEHOLDER);return(0,g.jsxs)(`div`,{className:`relative min-w-0`,children:[(0,g.jsxs)(`button`,{ref:_,type:`button`,className:r.cn(a.chatInputPillButtonClassName,`max-w-[200px]`),title:o??void 0,"data-testid":`chat-input-llm-profile`,"aria-expanded":f,"aria-haspopup":`dialog`,disabled:d,"aria-busy":d,onClick:e=>{e.preventDefault(),e.stopPropagation(),p(e=>!e)},children:[(0,g.jsx)(`span`,{className:`truncate`,children:v(x)}),(0,g.jsx)(s.ComboboxCaretInline,{isOpen:f})]}),f&&(0,g.jsx)(c.ContextMenu,{ref:b,testId:`chat-input-llm-profile-popover`,position:`top`,alignment:`left`,spacing:`none`,className:`z-[60] mb-2 min-w-[200px] max-w-[320px] max-h-[60vh] overflow-y-auto`,children:(0,g.jsx)(y,{onClose:()=>p(!1)})})]})}exports.ChatInputLlmProfileMenuContent=y,exports.ChatInputLlmProfilePicker=b;
1
+ const e=require("../../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),n=require("../../../../i18n/declaration.cjs"),r=require("../../../../utils/utils.cjs"),i=require("../../../../icons/checkmark.cjs"),a=require("../../../../utils/form-control-classes.cjs"),o=require("../../../../utils/format-model-name.cjs"),s=require("../../../../ui/typography.cjs"),c=require("../../../../ui/combobox-caret.cjs"),l=require("../../../../ui/context-menu.cjs"),u=require("../../context-menu/context-menu-list-item.cjs"),d=require("../../../../hooks/use-click-outside-element.cjs"),f=require("../../../../icons/settings-gear.cjs"),p=require("../../../shared/navigation-link.cjs"),m=require("../../../../ui/divider.cjs"),h=require("../../../../hooks/use-chat-input-llm-profile-state.cjs");let g=require("react");g=e.__toESM(g,1);let _=require("react/jsx-runtime");var v=18;function y(e){return e.length<=v?e:`${e.slice(0,v)}…`}function b({onClose:e,dividerInset:a,settingsLinkClassName:c,settingsIconClassName:l}){let{t:d}=t.useTranslation(`openhands`),{profiles:g,currentProfileName:v,currentProfileModel:y,canSwitchProfile:b,selectProfile:x}=h.useChatInputLlmProfileState(),S=b&&g.length>0,C=b?null:v,w=t=>{x(t),e()};return(0,_.jsxs)(_.Fragment,{children:[S&&(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(`li`,{role:`presentation`,className:`px-2 pt-1 pb-0.5`,children:(0,_.jsx)(s.Typography.Text,{className:`text-[11px] font-medium text-[var(--oh-text-dim)] uppercase tracking-wide leading-4`,children:d(n.I18nKey.SETTINGS$AVAILABLE_PROFILES)})}),g.map(t=>{let n=t.name===v,a=o.formatModelNameForDisplay(t.model);return(0,_.jsxs)(u.ContextMenuListItem,{testId:`chat-input-llm-profile-option-${t.name}`,onClick:r=>{if(r.preventDefault(),r.stopPropagation(),n){e();return}w(t.name)},className:r.cn(`flex flex-col items-stretch gap-0.5`,n&&`bg-[var(--oh-interactive-hover)]`),children:[(0,_.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,_.jsx)(`span`,{className:`flex-1 truncate text-sm leading-5`,title:t.model??t.name,children:t.name}),n&&(0,_.jsx)(i.default,{width:14,height:14,className:`shrink-0`,"aria-hidden":!0})]}),a&&(0,_.jsx)(`span`,{className:`block truncate text-xs leading-4 text-[var(--oh-muted)]`,children:a})]},t.name)})]}),C&&(0,_.jsx)(`li`,{className:`text-sm`,"data-testid":`chat-input-llm-profile-current`,children:(0,_.jsxs)(`div`,{className:`flex flex-col gap-0.5 p-2 leading-5 text-[var(--oh-foreground)]`,children:[(0,_.jsx)(`span`,{className:`truncate`,title:C,children:C}),y&&(0,_.jsx)(`span`,{className:`truncate text-xs leading-4 text-[var(--oh-muted)]`,children:o.formatModelNameForDisplay(y)})]})}),(S||C)&&(0,_.jsx)(m.Divider,{inset:a}),(0,_.jsx)(`li`,{className:`text-sm`,children:(0,_.jsxs)(p.NavigationLink,{to:`/settings/llm`,onClick:e,className:r.cn(`flex h-[30px] items-center gap-2 rounded p-2 leading-5 text-[var(--oh-foreground)] hover:bg-[var(--oh-interactive-hover)] transition-colors`,c),children:[(0,_.jsx)(f.default,{width:16,height:16,className:r.cn(`shrink-0`,l),"aria-hidden":!0}),(0,_.jsx)(`span`,{children:d(n.I18nKey.SETTINGS$LLM_PROFILES)})]})})]})}function x(){let{t:e}=t.useTranslation(`openhands`),{profiles:i,currentProfileName:o,isLoading:s,isSwitching:u}=h.useChatInputLlmProfileState(),[f,p]=g.default.useState(!1),m=g.default.useRef(null),v=d.useClickOutsideElement(()=>p(!1),m);if(s||i.length===0)return null;let x=o??e(n.I18nKey.LLM$SELECT_MODEL_PLACEHOLDER);return(0,_.jsxs)(`div`,{className:`relative min-w-0`,children:[(0,_.jsxs)(`button`,{ref:m,type:`button`,className:r.cn(a.chatInputPillButtonClassName,`max-w-[200px]`),title:o??void 0,"data-testid":`chat-input-llm-profile`,"aria-expanded":f,"aria-haspopup":`dialog`,disabled:u,"aria-busy":u,onClick:e=>{e.preventDefault(),e.stopPropagation(),p(e=>!e)},children:[(0,_.jsx)(`span`,{className:`truncate`,children:y(x)}),(0,_.jsx)(c.ComboboxCaretInline,{isOpen:f})]}),f&&(0,_.jsx)(l.ContextMenu,{ref:v,testId:`chat-input-llm-profile-popover`,position:`top`,alignment:`left`,spacing:`none`,className:`z-[60] mb-2 min-w-[200px] max-w-[320px] max-h-[60vh] overflow-y-auto`,children:(0,_.jsx)(b,{onClose:()=>p(!1)})})]})}exports.ChatInputLlmProfileMenuContent=b,exports.ChatInputLlmProfilePicker=x;
2
2
  //# sourceMappingURL=chat-input-llm-profile-picker.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-input-llm-profile-picker.cjs","names":[],"sources":["../../../../../src/components/features/chat/components/chat-input-llm-profile-picker.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useChatInputLlmProfileState } from \"#/hooks/use-chat-input-llm-profile-state\";\nimport { ComboboxCaretInline } from \"#/ui/combobox-caret\";\nimport SettingsGearIcon from \"#/icons/settings-gear.svg?react\";\nimport CheckIcon from \"#/icons/checkmark.svg?react\";\nimport { useClickOutsideElement } from \"#/hooks/use-click-outside-element\";\nimport { NavigationLink } from \"#/components/shared/navigation-link\";\nimport { ContextMenu } from \"#/ui/context-menu\";\nimport { ContextMenuListItem } from \"#/components/features/context-menu/context-menu-list-item\";\nimport { Divider } from \"#/ui/divider\";\nimport { Typography } from \"#/ui/typography\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { cn } from \"#/utils/utils\";\nimport { chatInputPillButtonClassName } from \"#/utils/form-control-classes\";\n\nconst PROFILE_LABEL_MAX_CHARS = 18;\n\nfunction truncateLabel(label: string): string {\n return label.length <= PROFILE_LABEL_MAX_CHARS\n ? label\n : `${label.slice(0, PROFILE_LABEL_MAX_CHARS)}…`;\n}\n\ninterface ChatInputLlmProfileMenuContentProps {\n onClose: () => void;\n dividerInset?: \"menu\";\n settingsLinkClassName?: string;\n settingsIconClassName?: string;\n}\n\n/**\n * The in-conversation OpenHands LLM-profile switcher list. Selecting a profile\n * live-swaps the running conversation's LLM via `/switch_profile` (the ACP\n * analog is {@link ChatInputModelMenuContent}). Shared by the inline pill and\n * the chat-input overflow submenu.\n */\nexport function ChatInputLlmProfileMenuContent({\n onClose,\n dividerInset,\n settingsLinkClassName,\n settingsIconClassName,\n}: ChatInputLlmProfileMenuContentProps) {\n const { t } = useTranslation(\"openhands\");\n const {\n profiles,\n currentProfileName,\n currentProfileModel,\n canSwitchProfile,\n selectProfile,\n } = useChatInputLlmProfileState();\n // Read-only surfaces (a cloud member on the home page, or a start-task route)\n // still name the active profile — the same shape ChatInputModelMenuContent\n // uses when the ACP picker is gated off.\n const showProfileList = canSwitchProfile && profiles.length > 0;\n const readOnlyProfileName = canSwitchProfile ? null : currentProfileName;\n\n const handleSelect = (profileName: string) => {\n selectProfile(profileName);\n onClose();\n };\n\n return (\n <>\n {showProfileList && (\n <>\n {/* role=\"presentation\" keeps this a valid <li> child of the\n ContextMenu <ul> without exposing the label as a menu item. */}\n <li role=\"presentation\" className=\"px-2 pt-1 pb-0.5\">\n <Typography.Text className=\"text-[11px] font-medium text-[var(--oh-text-dim)] uppercase tracking-wide leading-4\">\n {t(I18nKey.SETTINGS$AVAILABLE_PROFILES)}\n </Typography.Text>\n </li>\n {profiles.map((profile) => {\n const isCurrent = profile.name === currentProfileName;\n return (\n <ContextMenuListItem\n key={profile.name}\n testId={`chat-input-llm-profile-option-${profile.name}`}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n if (isCurrent) {\n onClose();\n return;\n }\n handleSelect(profile.name);\n }}\n className={cn(\n \"flex flex-col items-stretch gap-0.5\",\n isCurrent && \"bg-[var(--oh-interactive-hover)]\",\n )}\n >\n <span className=\"flex items-center gap-2\">\n <span\n className=\"flex-1 truncate text-sm leading-5\"\n title={profile.model ?? profile.name}\n >\n {profile.name}\n </span>\n {isCurrent && (\n <CheckIcon\n width={14}\n height={14}\n className=\"shrink-0\"\n aria-hidden\n />\n )}\n </span>\n {profile.model && (\n <span className=\"block truncate text-xs leading-4 text-[var(--oh-muted)]\">\n {profile.model}\n </span>\n )}\n </ContextMenuListItem>\n );\n })}\n </>\n )}\n {readOnlyProfileName && (\n <li className=\"text-sm\" data-testid=\"chat-input-llm-profile-current\">\n <div className=\"flex flex-col gap-0.5 p-2 leading-5 text-[var(--oh-foreground)]\">\n <span className=\"truncate\" title={readOnlyProfileName}>\n {readOnlyProfileName}\n </span>\n {currentProfileModel && (\n <span className=\"truncate text-xs leading-4 text-[var(--oh-muted)]\">\n {currentProfileModel}\n </span>\n )}\n </div>\n </li>\n )}\n {(showProfileList || readOnlyProfileName) && (\n <Divider inset={dividerInset} />\n )}\n <li className=\"text-sm\">\n <NavigationLink\n to=\"/settings/llm\"\n onClick={onClose}\n className={cn(\n \"flex h-[30px] items-center gap-2 rounded p-2 leading-5 text-[var(--oh-foreground)] hover:bg-[var(--oh-interactive-hover)] transition-colors\",\n settingsLinkClassName,\n )}\n >\n <SettingsGearIcon\n width={16}\n height={16}\n className={cn(\"shrink-0\", settingsIconClassName)}\n aria-hidden\n />\n <span>{t(I18nKey.SETTINGS$LLM_PROFILES)}</span>\n </NavigationLink>\n </li>\n </>\n );\n}\n\nexport function ChatInputLlmProfilePicker() {\n const { t } = useTranslation(\"openhands\");\n const { profiles, currentProfileName, isLoading, isSwitching } =\n useChatInputLlmProfileState();\n const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const popoverRef = useClickOutsideElement<HTMLUListElement>(\n () => setIsPopoverOpen(false),\n triggerRef,\n );\n\n // No LLM profiles yet (or the agent-server lacks the surface): stay out of\n // the way, exactly like the ACP/AgentProfile pickers.\n if (isLoading || profiles.length === 0) {\n return null;\n }\n\n const label = currentProfileName ?? t(I18nKey.LLM$SELECT_MODEL_PLACEHOLDER);\n\n return (\n <div className=\"relative min-w-0\">\n <button\n ref={triggerRef}\n type=\"button\"\n className={cn(chatInputPillButtonClassName, \"max-w-[200px]\")}\n title={currentProfileName ?? undefined}\n data-testid=\"chat-input-llm-profile\"\n aria-expanded={isPopoverOpen}\n aria-haspopup=\"dialog\"\n // Disabled mid-switch so re-opening can't fire a second /switch_profile.\n disabled={isSwitching}\n aria-busy={isSwitching}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n setIsPopoverOpen((open) => !open);\n }}\n >\n <span className=\"truncate\">{truncateLabel(label)}</span>\n <ComboboxCaretInline isOpen={isPopoverOpen} />\n </button>\n\n {isPopoverOpen && (\n <ContextMenu\n ref={popoverRef}\n testId=\"chat-input-llm-profile-popover\"\n position=\"top\"\n alignment=\"left\"\n spacing=\"none\"\n className=\"z-[60] mb-2 min-w-[200px] max-w-[320px] max-h-[60vh] overflow-y-auto\"\n >\n <ChatInputLlmProfileMenuContent\n onClose={() => setIsPopoverOpen(false)}\n />\n </ContextMenu>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"chat-input-llm-profile-picker.cjs","names":[],"sources":["../../../../../src/components/features/chat/components/chat-input-llm-profile-picker.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useChatInputLlmProfileState } from \"#/hooks/use-chat-input-llm-profile-state\";\nimport { ComboboxCaretInline } from \"#/ui/combobox-caret\";\nimport SettingsGearIcon from \"#/icons/settings-gear.svg?react\";\nimport CheckIcon from \"#/icons/checkmark.svg?react\";\nimport { useClickOutsideElement } from \"#/hooks/use-click-outside-element\";\nimport { NavigationLink } from \"#/components/shared/navigation-link\";\nimport { ContextMenu } from \"#/ui/context-menu\";\nimport { ContextMenuListItem } from \"#/components/features/context-menu/context-menu-list-item\";\nimport { Divider } from \"#/ui/divider\";\nimport { Typography } from \"#/ui/typography\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { cn } from \"#/utils/utils\";\nimport { chatInputPillButtonClassName } from \"#/utils/form-control-classes\";\nimport { formatModelNameForDisplay } from \"#/utils/format-model-name\";\n\nconst PROFILE_LABEL_MAX_CHARS = 18;\n\nfunction truncateLabel(label: string): string {\n return label.length <= PROFILE_LABEL_MAX_CHARS\n ? label\n : `${label.slice(0, PROFILE_LABEL_MAX_CHARS)}…`;\n}\n\ninterface ChatInputLlmProfileMenuContentProps {\n onClose: () => void;\n dividerInset?: \"menu\";\n settingsLinkClassName?: string;\n settingsIconClassName?: string;\n}\n\n/**\n * The in-conversation OpenHands LLM-profile switcher list. Selecting a profile\n * live-swaps the running conversation's LLM via `/switch_profile` (the ACP\n * analog is {@link ChatInputModelMenuContent}). Shared by the inline pill and\n * the chat-input overflow submenu.\n */\nexport function ChatInputLlmProfileMenuContent({\n onClose,\n dividerInset,\n settingsLinkClassName,\n settingsIconClassName,\n}: ChatInputLlmProfileMenuContentProps) {\n const { t } = useTranslation(\"openhands\");\n const {\n profiles,\n currentProfileName,\n currentProfileModel,\n canSwitchProfile,\n selectProfile,\n } = useChatInputLlmProfileState();\n // Read-only surfaces (a cloud member on the home page, or a start-task route)\n // still name the active profile — the same shape ChatInputModelMenuContent\n // uses when the ACP picker is gated off.\n const showProfileList = canSwitchProfile && profiles.length > 0;\n const readOnlyProfileName = canSwitchProfile ? null : currentProfileName;\n\n const handleSelect = (profileName: string) => {\n selectProfile(profileName);\n onClose();\n };\n\n return (\n <>\n {showProfileList && (\n <>\n {/* role=\"presentation\" keeps this a valid <li> child of the\n ContextMenu <ul> without exposing the label as a menu item. */}\n <li role=\"presentation\" className=\"px-2 pt-1 pb-0.5\">\n <Typography.Text className=\"text-[11px] font-medium text-[var(--oh-text-dim)] uppercase tracking-wide leading-4\">\n {t(I18nKey.SETTINGS$AVAILABLE_PROFILES)}\n </Typography.Text>\n </li>\n {profiles.map((profile) => {\n const isCurrent = profile.name === currentProfileName;\n const displayModel = formatModelNameForDisplay(profile.model);\n return (\n <ContextMenuListItem\n key={profile.name}\n testId={`chat-input-llm-profile-option-${profile.name}`}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n if (isCurrent) {\n onClose();\n return;\n }\n handleSelect(profile.name);\n }}\n className={cn(\n \"flex flex-col items-stretch gap-0.5\",\n isCurrent && \"bg-[var(--oh-interactive-hover)]\",\n )}\n >\n <span className=\"flex items-center gap-2\">\n <span\n className=\"flex-1 truncate text-sm leading-5\"\n title={profile.model ?? profile.name}\n >\n {profile.name}\n </span>\n {isCurrent && (\n <CheckIcon\n width={14}\n height={14}\n className=\"shrink-0\"\n aria-hidden\n />\n )}\n </span>\n {displayModel && (\n <span className=\"block truncate text-xs leading-4 text-[var(--oh-muted)]\">\n {displayModel}\n </span>\n )}\n </ContextMenuListItem>\n );\n })}\n </>\n )}\n {readOnlyProfileName && (\n <li className=\"text-sm\" data-testid=\"chat-input-llm-profile-current\">\n <div className=\"flex flex-col gap-0.5 p-2 leading-5 text-[var(--oh-foreground)]\">\n <span className=\"truncate\" title={readOnlyProfileName}>\n {readOnlyProfileName}\n </span>\n {currentProfileModel && (\n <span className=\"truncate text-xs leading-4 text-[var(--oh-muted)]\">\n {formatModelNameForDisplay(currentProfileModel)}\n </span>\n )}\n </div>\n </li>\n )}\n {(showProfileList || readOnlyProfileName) && (\n <Divider inset={dividerInset} />\n )}\n <li className=\"text-sm\">\n <NavigationLink\n to=\"/settings/llm\"\n onClick={onClose}\n className={cn(\n \"flex h-[30px] items-center gap-2 rounded p-2 leading-5 text-[var(--oh-foreground)] hover:bg-[var(--oh-interactive-hover)] transition-colors\",\n settingsLinkClassName,\n )}\n >\n <SettingsGearIcon\n width={16}\n height={16}\n className={cn(\"shrink-0\", settingsIconClassName)}\n aria-hidden\n />\n <span>{t(I18nKey.SETTINGS$LLM_PROFILES)}</span>\n </NavigationLink>\n </li>\n </>\n );\n}\n\nexport function ChatInputLlmProfilePicker() {\n const { t } = useTranslation(\"openhands\");\n const { profiles, currentProfileName, isLoading, isSwitching } =\n useChatInputLlmProfileState();\n const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const popoverRef = useClickOutsideElement<HTMLUListElement>(\n () => setIsPopoverOpen(false),\n triggerRef,\n );\n\n // No LLM profiles yet (or the agent-server lacks the surface): stay out of\n // the way, exactly like the ACP/AgentProfile pickers.\n if (isLoading || profiles.length === 0) {\n return null;\n }\n\n const label = currentProfileName ?? t(I18nKey.LLM$SELECT_MODEL_PLACEHOLDER);\n\n return (\n <div className=\"relative min-w-0\">\n <button\n ref={triggerRef}\n type=\"button\"\n className={cn(chatInputPillButtonClassName, \"max-w-[200px]\")}\n title={currentProfileName ?? undefined}\n data-testid=\"chat-input-llm-profile\"\n aria-expanded={isPopoverOpen}\n aria-haspopup=\"dialog\"\n // Disabled mid-switch so re-opening can't fire a second /switch_profile.\n disabled={isSwitching}\n aria-busy={isSwitching}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n setIsPopoverOpen((open) => !open);\n }}\n >\n <span className=\"truncate\">{truncateLabel(label)}</span>\n <ComboboxCaretInline isOpen={isPopoverOpen} />\n </button>\n\n {isPopoverOpen && (\n <ContextMenu\n ref={popoverRef}\n testId=\"chat-input-llm-profile-popover\"\n position=\"top\"\n alignment=\"left\"\n spacing=\"none\"\n className=\"z-[60] mb-2 min-w-[200px] max-w-[320px] max-h-[60vh] overflow-y-auto\"\n >\n <ChatInputLlmProfileMenuContent\n onClose={() => setIsPopoverOpen(false)}\n />\n </ContextMenu>\n )}\n </div>\n );\n}\n"],"mappings":"s5BAiBA,IAAM,EAA0B,GAEhC,SAAS,EAAc,EAAuB,CAC5C,OAAO,EAAM,QAAU,EACnB,EACA,GAAG,EAAM,MAAM,EAAG,CAAuB,EAAE,EACjD,CAeA,SAAgB,EAA+B,CAC7C,UACA,eACA,wBACA,yBACsC,CACtC,GAAM,CAAE,KAAM,EAAA,eAAe,WAAW,EAClC,CACJ,WACA,qBACA,sBACA,mBACA,iBACE,EAAA,4BAA4B,EAI1B,EAAkB,GAAoB,EAAS,OAAS,EACxD,EAAsB,EAAmB,KAAO,EAEhD,EAAgB,GAAwB,CAC5C,EAAc,CAAW,EACzB,EAAQ,CACV,EAEA,OACE,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,CACG,IACC,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,EAGE,EAAA,EAAA,KAAC,KAAD,CAAI,KAAK,eAAe,UAAU,6BAChC,EAAA,EAAA,KAAC,EAAA,WAAW,KAAZ,CAAiB,UAAU,+FACxB,EAAE,EAAA,QAAQ,2BAA2B,CACvB,CAAA,CACf,CAAA,EACH,EAAS,IAAK,GAAY,CACzB,IAAM,EAAY,EAAQ,OAAS,EAC7B,EAAe,EAAA,0BAA0B,EAAQ,KAAK,EAC5D,OACE,EAAA,EAAA,MAAC,EAAA,oBAAD,CAEE,OAAQ,iCAAiC,EAAQ,OACjD,QAAU,GAAU,CAGlB,GAFA,EAAM,eAAe,EACrB,EAAM,gBAAgB,EAClB,EAAW,CACb,EAAQ,EACR,MACF,CACA,EAAa,EAAQ,IAAI,CAC3B,EACA,UAAW,EAAA,GACT,sCACA,GAAa,kCACf,WAfF,EAiBE,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,mCAAhB,EACE,EAAA,EAAA,KAAC,OAAD,CACE,UAAU,oCACV,MAAO,EAAQ,OAAS,EAAQ,cAE/B,EAAQ,IACL,CAAA,EACL,IACC,EAAA,EAAA,KAAC,EAAA,QAAD,CACE,MAAO,GACP,OAAQ,GACR,UAAU,WACV,cAAA,EACD,CAAA,CAEC,IACL,IACC,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,mEACb,CACG,CAAA,CAEW,GArCd,EAAQ,IAqCM,CAEzB,CAAC,CACD,CAAA,CAAA,EAEH,IACC,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,UAAU,cAAY,2CAClC,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,2EAAf,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,WAAW,MAAO,WAC/B,CACG,CAAA,EACL,IACC,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,6DACb,EAAA,0BAA0B,CAAmB,CAC1C,CAAA,CAEL,GACH,CAAA,GAEJ,GAAmB,KACnB,EAAA,EAAA,KAAC,EAAA,QAAD,CAAS,MAAO,CAAe,CAAA,GAEjC,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,oBACZ,EAAA,EAAA,MAAC,EAAA,eAAD,CACE,GAAG,gBACH,QAAS,EACT,UAAW,EAAA,GACT,8IACA,CACF,WANF,EAQE,EAAA,EAAA,KAAC,EAAA,QAAD,CACE,MAAO,GACP,OAAQ,GACR,UAAW,EAAA,GAAG,WAAY,CAAqB,EAC/C,cAAA,EACD,CAAA,GACD,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAE,EAAA,QAAQ,qBAAqB,CAAQ,CAAA,CAChC,GACd,CAAA,CACJ,CAAA,CAAA,CAEN,CAEA,SAAgB,GAA4B,CAC1C,GAAM,CAAE,KAAM,EAAA,eAAe,WAAW,EAClC,CAAE,WAAU,qBAAoB,YAAW,eAC/C,EAAA,4BAA4B,EACxB,CAAC,EAAe,GAAoB,EAAA,QAAM,SAAS,EAAK,EACxD,EAAa,EAAA,QAAM,OAA0B,IAAI,EACjD,EAAa,EAAA,2BACX,EAAiB,EAAK,EAC5B,CACF,EAIA,GAAI,GAAa,EAAS,SAAW,EACnC,OAAO,KAGT,IAAM,EAAQ,GAAsB,EAAE,EAAA,QAAQ,4BAA4B,EAE1E,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,4BAAf,EACE,EAAA,EAAA,MAAC,SAAD,CACE,IAAK,EACL,KAAK,SACL,UAAW,EAAA,GAAG,EAAA,6BAA8B,eAAe,EAC3D,MAAO,GAAsB,IAAA,GAC7B,cAAY,yBACZ,gBAAe,EACf,gBAAc,SAEd,SAAU,EACV,YAAW,EACX,QAAU,GAAU,CAClB,EAAM,eAAe,EACrB,EAAM,gBAAgB,EACtB,EAAkB,GAAS,CAAC,CAAI,CAClC,WAfF,EAiBE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,oBAAY,EAAc,CAAK,CAAQ,CAAA,GACvD,EAAA,EAAA,KAAC,EAAA,oBAAD,CAAqB,OAAQ,CAAgB,CAAA,CACvC,IAEP,IACC,EAAA,EAAA,KAAC,EAAA,YAAD,CACE,IAAK,EACL,OAAO,iCACP,SAAS,MACT,UAAU,OACV,QAAQ,OACR,UAAU,iFAEV,EAAA,EAAA,KAAC,EAAD,CACE,YAAe,EAAiB,EAAK,CACtC,CAAA,CACU,CAAA,CAEZ,GAET"}
@@ -3,131 +3,132 @@ import { I18nKey as t } from "../../../../i18n/declaration.js";
3
3
  import { cn as n } from "../../../../utils/utils.js";
4
4
  import r from "../../../../icons/checkmark.js";
5
5
  import { chatInputPillButtonClassName as i } from "../../../../utils/form-control-classes.js";
6
- import { Typography as a } from "../../../../ui/typography.js";
7
- import { ComboboxCaretInline as o } from "../../../../ui/combobox-caret.js";
8
- import { ContextMenu as s } from "../../../../ui/context-menu.js";
9
- import { ContextMenuListItem as c } from "../../context-menu/context-menu-list-item.js";
10
- import { useClickOutsideElement as l } from "../../../../hooks/use-click-outside-element.js";
11
- import u from "../../../../icons/settings-gear.js";
12
- import { NavigationLink as d } from "../../../shared/navigation-link.js";
13
- import { Divider as f } from "../../../../ui/divider.js";
14
- import { useChatInputLlmProfileState as p } from "../../../../hooks/use-chat-input-llm-profile-state.js";
15
- import m from "react";
16
- import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
6
+ import { formatModelNameForDisplay as a } from "../../../../utils/format-model-name.js";
7
+ import { Typography as o } from "../../../../ui/typography.js";
8
+ import { ComboboxCaretInline as s } from "../../../../ui/combobox-caret.js";
9
+ import { ContextMenu as c } from "../../../../ui/context-menu.js";
10
+ import { ContextMenuListItem as l } from "../../context-menu/context-menu-list-item.js";
11
+ import { useClickOutsideElement as u } from "../../../../hooks/use-click-outside-element.js";
12
+ import d from "../../../../icons/settings-gear.js";
13
+ import { NavigationLink as f } from "../../../shared/navigation-link.js";
14
+ import { Divider as p } from "../../../../ui/divider.js";
15
+ import { useChatInputLlmProfileState as m } from "../../../../hooks/use-chat-input-llm-profile-state.js";
16
+ import h from "react";
17
+ import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
17
18
  //#region src/components/features/chat/components/chat-input-llm-profile-picker.tsx
18
- var v = 18;
19
- function y(e) {
20
- return e.length <= v ? e : `${e.slice(0, v)}…`;
19
+ var y = 18;
20
+ function b(e) {
21
+ return e.length <= y ? e : `${e.slice(0, y)}…`;
21
22
  }
22
- function b({ onClose: i, dividerInset: o, settingsLinkClassName: s, settingsIconClassName: l }) {
23
- let { t: m } = e("openhands"), { profiles: v, currentProfileName: y, currentProfileModel: b, canSwitchProfile: x, selectProfile: S } = p(), C = x && v.length > 0, w = x ? null : y, T = (e) => {
24
- S(e), i();
23
+ function x({ onClose: i, dividerInset: s, settingsLinkClassName: c, settingsIconClassName: u }) {
24
+ let { t: h } = e("openhands"), { profiles: y, currentProfileName: b, currentProfileModel: x, canSwitchProfile: S, selectProfile: C } = m(), w = S && y.length > 0, T = S ? null : b, E = (e) => {
25
+ C(e), i();
25
26
  };
26
- return /* @__PURE__ */ _(h, { children: [
27
- C && /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g("li", {
27
+ return /* @__PURE__ */ v(g, { children: [
28
+ w && /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _("li", {
28
29
  role: "presentation",
29
30
  className: "px-2 pt-1 pb-0.5",
30
- children: /* @__PURE__ */ g(a.Text, {
31
+ children: /* @__PURE__ */ _(o.Text, {
31
32
  className: "text-[11px] font-medium text-[var(--oh-text-dim)] uppercase tracking-wide leading-4",
32
- children: m(t.SETTINGS$AVAILABLE_PROFILES)
33
+ children: h(t.SETTINGS$AVAILABLE_PROFILES)
33
34
  })
34
- }), v.map((e) => {
35
- let t = e.name === y;
36
- return /* @__PURE__ */ _(c, {
35
+ }), y.map((e) => {
36
+ let t = e.name === b, o = a(e.model);
37
+ return /* @__PURE__ */ v(l, {
37
38
  testId: `chat-input-llm-profile-option-${e.name}`,
38
39
  onClick: (n) => {
39
40
  if (n.preventDefault(), n.stopPropagation(), t) {
40
41
  i();
41
42
  return;
42
43
  }
43
- T(e.name);
44
+ E(e.name);
44
45
  },
45
46
  className: n("flex flex-col items-stretch gap-0.5", t && "bg-[var(--oh-interactive-hover)]"),
46
- children: [/* @__PURE__ */ _("span", {
47
+ children: [/* @__PURE__ */ v("span", {
47
48
  className: "flex items-center gap-2",
48
- children: [/* @__PURE__ */ g("span", {
49
+ children: [/* @__PURE__ */ _("span", {
49
50
  className: "flex-1 truncate text-sm leading-5",
50
51
  title: e.model ?? e.name,
51
52
  children: e.name
52
- }), t && /* @__PURE__ */ g(r, {
53
+ }), t && /* @__PURE__ */ _(r, {
53
54
  width: 14,
54
55
  height: 14,
55
56
  className: "shrink-0",
56
57
  "aria-hidden": !0
57
58
  })]
58
- }), e.model && /* @__PURE__ */ g("span", {
59
+ }), o && /* @__PURE__ */ _("span", {
59
60
  className: "block truncate text-xs leading-4 text-[var(--oh-muted)]",
60
- children: e.model
61
+ children: o
61
62
  })]
62
63
  }, e.name);
63
64
  })] }),
64
- w && /* @__PURE__ */ g("li", {
65
+ T && /* @__PURE__ */ _("li", {
65
66
  className: "text-sm",
66
67
  "data-testid": "chat-input-llm-profile-current",
67
- children: /* @__PURE__ */ _("div", {
68
+ children: /* @__PURE__ */ v("div", {
68
69
  className: "flex flex-col gap-0.5 p-2 leading-5 text-[var(--oh-foreground)]",
69
- children: [/* @__PURE__ */ g("span", {
70
+ children: [/* @__PURE__ */ _("span", {
70
71
  className: "truncate",
71
- title: w,
72
- children: w
73
- }), b && /* @__PURE__ */ g("span", {
72
+ title: T,
73
+ children: T
74
+ }), x && /* @__PURE__ */ _("span", {
74
75
  className: "truncate text-xs leading-4 text-[var(--oh-muted)]",
75
- children: b
76
+ children: a(x)
76
77
  })]
77
78
  })
78
79
  }),
79
- (C || w) && /* @__PURE__ */ g(f, { inset: o }),
80
- /* @__PURE__ */ g("li", {
80
+ (w || T) && /* @__PURE__ */ _(p, { inset: s }),
81
+ /* @__PURE__ */ _("li", {
81
82
  className: "text-sm",
82
- children: /* @__PURE__ */ _(d, {
83
+ children: /* @__PURE__ */ v(f, {
83
84
  to: "/settings/llm",
84
85
  onClick: i,
85
- className: n("flex h-[30px] items-center gap-2 rounded p-2 leading-5 text-[var(--oh-foreground)] hover:bg-[var(--oh-interactive-hover)] transition-colors", s),
86
- children: [/* @__PURE__ */ g(u, {
86
+ className: n("flex h-[30px] items-center gap-2 rounded p-2 leading-5 text-[var(--oh-foreground)] hover:bg-[var(--oh-interactive-hover)] transition-colors", c),
87
+ children: [/* @__PURE__ */ _(d, {
87
88
  width: 16,
88
89
  height: 16,
89
- className: n("shrink-0", l),
90
+ className: n("shrink-0", u),
90
91
  "aria-hidden": !0
91
- }), /* @__PURE__ */ g("span", { children: m(t.SETTINGS$LLM_PROFILES) })]
92
+ }), /* @__PURE__ */ _("span", { children: h(t.SETTINGS$LLM_PROFILES) })]
92
93
  })
93
94
  })
94
95
  ] });
95
96
  }
96
- function x() {
97
- let { t: r } = e("openhands"), { profiles: a, currentProfileName: c, isLoading: u, isSwitching: d } = p(), [f, h] = m.useState(!1), v = m.useRef(null), x = l(() => h(!1), v);
98
- if (u || a.length === 0) return null;
99
- let S = c ?? r(t.LLM$SELECT_MODEL_PLACEHOLDER);
100
- return /* @__PURE__ */ _("div", {
97
+ function S() {
98
+ let { t: r } = e("openhands"), { profiles: a, currentProfileName: o, isLoading: l, isSwitching: d } = m(), [f, p] = h.useState(!1), g = h.useRef(null), y = u(() => p(!1), g);
99
+ if (l || a.length === 0) return null;
100
+ let S = o ?? r(t.LLM$SELECT_MODEL_PLACEHOLDER);
101
+ return /* @__PURE__ */ v("div", {
101
102
  className: "relative min-w-0",
102
- children: [/* @__PURE__ */ _("button", {
103
- ref: v,
103
+ children: [/* @__PURE__ */ v("button", {
104
+ ref: g,
104
105
  type: "button",
105
106
  className: n(i, "max-w-[200px]"),
106
- title: c ?? void 0,
107
+ title: o ?? void 0,
107
108
  "data-testid": "chat-input-llm-profile",
108
109
  "aria-expanded": f,
109
110
  "aria-haspopup": "dialog",
110
111
  disabled: d,
111
112
  "aria-busy": d,
112
113
  onClick: (e) => {
113
- e.preventDefault(), e.stopPropagation(), h((e) => !e);
114
+ e.preventDefault(), e.stopPropagation(), p((e) => !e);
114
115
  },
115
- children: [/* @__PURE__ */ g("span", {
116
+ children: [/* @__PURE__ */ _("span", {
116
117
  className: "truncate",
117
- children: y(S)
118
- }), /* @__PURE__ */ g(o, { isOpen: f })]
119
- }), f && /* @__PURE__ */ g(s, {
120
- ref: x,
118
+ children: b(S)
119
+ }), /* @__PURE__ */ _(s, { isOpen: f })]
120
+ }), f && /* @__PURE__ */ _(c, {
121
+ ref: y,
121
122
  testId: "chat-input-llm-profile-popover",
122
123
  position: "top",
123
124
  alignment: "left",
124
125
  spacing: "none",
125
126
  className: "z-[60] mb-2 min-w-[200px] max-w-[320px] max-h-[60vh] overflow-y-auto",
126
- children: /* @__PURE__ */ g(b, { onClose: () => h(!1) })
127
+ children: /* @__PURE__ */ _(x, { onClose: () => p(!1) })
127
128
  })]
128
129
  });
129
130
  }
130
131
  //#endregion
131
- export { b as ChatInputLlmProfileMenuContent, x as ChatInputLlmProfilePicker };
132
+ export { x as ChatInputLlmProfileMenuContent, S as ChatInputLlmProfilePicker };
132
133
 
133
134
  //# sourceMappingURL=chat-input-llm-profile-picker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-input-llm-profile-picker.js","names":[],"sources":["../../../../../src/components/features/chat/components/chat-input-llm-profile-picker.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useChatInputLlmProfileState } from \"#/hooks/use-chat-input-llm-profile-state\";\nimport { ComboboxCaretInline } from \"#/ui/combobox-caret\";\nimport SettingsGearIcon from \"#/icons/settings-gear.svg?react\";\nimport CheckIcon from \"#/icons/checkmark.svg?react\";\nimport { useClickOutsideElement } from \"#/hooks/use-click-outside-element\";\nimport { NavigationLink } from \"#/components/shared/navigation-link\";\nimport { ContextMenu } from \"#/ui/context-menu\";\nimport { ContextMenuListItem } from \"#/components/features/context-menu/context-menu-list-item\";\nimport { Divider } from \"#/ui/divider\";\nimport { Typography } from \"#/ui/typography\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { cn } from \"#/utils/utils\";\nimport { chatInputPillButtonClassName } from \"#/utils/form-control-classes\";\n\nconst PROFILE_LABEL_MAX_CHARS = 18;\n\nfunction truncateLabel(label: string): string {\n return label.length <= PROFILE_LABEL_MAX_CHARS\n ? label\n : `${label.slice(0, PROFILE_LABEL_MAX_CHARS)}…`;\n}\n\ninterface ChatInputLlmProfileMenuContentProps {\n onClose: () => void;\n dividerInset?: \"menu\";\n settingsLinkClassName?: string;\n settingsIconClassName?: string;\n}\n\n/**\n * The in-conversation OpenHands LLM-profile switcher list. Selecting a profile\n * live-swaps the running conversation's LLM via `/switch_profile` (the ACP\n * analog is {@link ChatInputModelMenuContent}). Shared by the inline pill and\n * the chat-input overflow submenu.\n */\nexport function ChatInputLlmProfileMenuContent({\n onClose,\n dividerInset,\n settingsLinkClassName,\n settingsIconClassName,\n}: ChatInputLlmProfileMenuContentProps) {\n const { t } = useTranslation(\"openhands\");\n const {\n profiles,\n currentProfileName,\n currentProfileModel,\n canSwitchProfile,\n selectProfile,\n } = useChatInputLlmProfileState();\n // Read-only surfaces (a cloud member on the home page, or a start-task route)\n // still name the active profile — the same shape ChatInputModelMenuContent\n // uses when the ACP picker is gated off.\n const showProfileList = canSwitchProfile && profiles.length > 0;\n const readOnlyProfileName = canSwitchProfile ? null : currentProfileName;\n\n const handleSelect = (profileName: string) => {\n selectProfile(profileName);\n onClose();\n };\n\n return (\n <>\n {showProfileList && (\n <>\n {/* role=\"presentation\" keeps this a valid <li> child of the\n ContextMenu <ul> without exposing the label as a menu item. */}\n <li role=\"presentation\" className=\"px-2 pt-1 pb-0.5\">\n <Typography.Text className=\"text-[11px] font-medium text-[var(--oh-text-dim)] uppercase tracking-wide leading-4\">\n {t(I18nKey.SETTINGS$AVAILABLE_PROFILES)}\n </Typography.Text>\n </li>\n {profiles.map((profile) => {\n const isCurrent = profile.name === currentProfileName;\n return (\n <ContextMenuListItem\n key={profile.name}\n testId={`chat-input-llm-profile-option-${profile.name}`}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n if (isCurrent) {\n onClose();\n return;\n }\n handleSelect(profile.name);\n }}\n className={cn(\n \"flex flex-col items-stretch gap-0.5\",\n isCurrent && \"bg-[var(--oh-interactive-hover)]\",\n )}\n >\n <span className=\"flex items-center gap-2\">\n <span\n className=\"flex-1 truncate text-sm leading-5\"\n title={profile.model ?? profile.name}\n >\n {profile.name}\n </span>\n {isCurrent && (\n <CheckIcon\n width={14}\n height={14}\n className=\"shrink-0\"\n aria-hidden\n />\n )}\n </span>\n {profile.model && (\n <span className=\"block truncate text-xs leading-4 text-[var(--oh-muted)]\">\n {profile.model}\n </span>\n )}\n </ContextMenuListItem>\n );\n })}\n </>\n )}\n {readOnlyProfileName && (\n <li className=\"text-sm\" data-testid=\"chat-input-llm-profile-current\">\n <div className=\"flex flex-col gap-0.5 p-2 leading-5 text-[var(--oh-foreground)]\">\n <span className=\"truncate\" title={readOnlyProfileName}>\n {readOnlyProfileName}\n </span>\n {currentProfileModel && (\n <span className=\"truncate text-xs leading-4 text-[var(--oh-muted)]\">\n {currentProfileModel}\n </span>\n )}\n </div>\n </li>\n )}\n {(showProfileList || readOnlyProfileName) && (\n <Divider inset={dividerInset} />\n )}\n <li className=\"text-sm\">\n <NavigationLink\n to=\"/settings/llm\"\n onClick={onClose}\n className={cn(\n \"flex h-[30px] items-center gap-2 rounded p-2 leading-5 text-[var(--oh-foreground)] hover:bg-[var(--oh-interactive-hover)] transition-colors\",\n settingsLinkClassName,\n )}\n >\n <SettingsGearIcon\n width={16}\n height={16}\n className={cn(\"shrink-0\", settingsIconClassName)}\n aria-hidden\n />\n <span>{t(I18nKey.SETTINGS$LLM_PROFILES)}</span>\n </NavigationLink>\n </li>\n </>\n );\n}\n\nexport function ChatInputLlmProfilePicker() {\n const { t } = useTranslation(\"openhands\");\n const { profiles, currentProfileName, isLoading, isSwitching } =\n useChatInputLlmProfileState();\n const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const popoverRef = useClickOutsideElement<HTMLUListElement>(\n () => setIsPopoverOpen(false),\n triggerRef,\n );\n\n // No LLM profiles yet (or the agent-server lacks the surface): stay out of\n // the way, exactly like the ACP/AgentProfile pickers.\n if (isLoading || profiles.length === 0) {\n return null;\n }\n\n const label = currentProfileName ?? t(I18nKey.LLM$SELECT_MODEL_PLACEHOLDER);\n\n return (\n <div className=\"relative min-w-0\">\n <button\n ref={triggerRef}\n type=\"button\"\n className={cn(chatInputPillButtonClassName, \"max-w-[200px]\")}\n title={currentProfileName ?? undefined}\n data-testid=\"chat-input-llm-profile\"\n aria-expanded={isPopoverOpen}\n aria-haspopup=\"dialog\"\n // Disabled mid-switch so re-opening can't fire a second /switch_profile.\n disabled={isSwitching}\n aria-busy={isSwitching}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n setIsPopoverOpen((open) => !open);\n }}\n >\n <span className=\"truncate\">{truncateLabel(label)}</span>\n <ComboboxCaretInline isOpen={isPopoverOpen} />\n </button>\n\n {isPopoverOpen && (\n <ContextMenu\n ref={popoverRef}\n testId=\"chat-input-llm-profile-popover\"\n position=\"top\"\n alignment=\"left\"\n spacing=\"none\"\n className=\"z-[60] mb-2 min-w-[200px] max-w-[320px] max-h-[60vh] overflow-y-auto\"\n >\n <ChatInputLlmProfileMenuContent\n onClose={() => setIsPopoverOpen(false)}\n />\n </ContextMenu>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"chat-input-llm-profile-picker.js","names":[],"sources":["../../../../../src/components/features/chat/components/chat-input-llm-profile-picker.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useChatInputLlmProfileState } from \"#/hooks/use-chat-input-llm-profile-state\";\nimport { ComboboxCaretInline } from \"#/ui/combobox-caret\";\nimport SettingsGearIcon from \"#/icons/settings-gear.svg?react\";\nimport CheckIcon from \"#/icons/checkmark.svg?react\";\nimport { useClickOutsideElement } from \"#/hooks/use-click-outside-element\";\nimport { NavigationLink } from \"#/components/shared/navigation-link\";\nimport { ContextMenu } from \"#/ui/context-menu\";\nimport { ContextMenuListItem } from \"#/components/features/context-menu/context-menu-list-item\";\nimport { Divider } from \"#/ui/divider\";\nimport { Typography } from \"#/ui/typography\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { cn } from \"#/utils/utils\";\nimport { chatInputPillButtonClassName } from \"#/utils/form-control-classes\";\nimport { formatModelNameForDisplay } from \"#/utils/format-model-name\";\n\nconst PROFILE_LABEL_MAX_CHARS = 18;\n\nfunction truncateLabel(label: string): string {\n return label.length <= PROFILE_LABEL_MAX_CHARS\n ? label\n : `${label.slice(0, PROFILE_LABEL_MAX_CHARS)}…`;\n}\n\ninterface ChatInputLlmProfileMenuContentProps {\n onClose: () => void;\n dividerInset?: \"menu\";\n settingsLinkClassName?: string;\n settingsIconClassName?: string;\n}\n\n/**\n * The in-conversation OpenHands LLM-profile switcher list. Selecting a profile\n * live-swaps the running conversation's LLM via `/switch_profile` (the ACP\n * analog is {@link ChatInputModelMenuContent}). Shared by the inline pill and\n * the chat-input overflow submenu.\n */\nexport function ChatInputLlmProfileMenuContent({\n onClose,\n dividerInset,\n settingsLinkClassName,\n settingsIconClassName,\n}: ChatInputLlmProfileMenuContentProps) {\n const { t } = useTranslation(\"openhands\");\n const {\n profiles,\n currentProfileName,\n currentProfileModel,\n canSwitchProfile,\n selectProfile,\n } = useChatInputLlmProfileState();\n // Read-only surfaces (a cloud member on the home page, or a start-task route)\n // still name the active profile — the same shape ChatInputModelMenuContent\n // uses when the ACP picker is gated off.\n const showProfileList = canSwitchProfile && profiles.length > 0;\n const readOnlyProfileName = canSwitchProfile ? null : currentProfileName;\n\n const handleSelect = (profileName: string) => {\n selectProfile(profileName);\n onClose();\n };\n\n return (\n <>\n {showProfileList && (\n <>\n {/* role=\"presentation\" keeps this a valid <li> child of the\n ContextMenu <ul> without exposing the label as a menu item. */}\n <li role=\"presentation\" className=\"px-2 pt-1 pb-0.5\">\n <Typography.Text className=\"text-[11px] font-medium text-[var(--oh-text-dim)] uppercase tracking-wide leading-4\">\n {t(I18nKey.SETTINGS$AVAILABLE_PROFILES)}\n </Typography.Text>\n </li>\n {profiles.map((profile) => {\n const isCurrent = profile.name === currentProfileName;\n const displayModel = formatModelNameForDisplay(profile.model);\n return (\n <ContextMenuListItem\n key={profile.name}\n testId={`chat-input-llm-profile-option-${profile.name}`}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n if (isCurrent) {\n onClose();\n return;\n }\n handleSelect(profile.name);\n }}\n className={cn(\n \"flex flex-col items-stretch gap-0.5\",\n isCurrent && \"bg-[var(--oh-interactive-hover)]\",\n )}\n >\n <span className=\"flex items-center gap-2\">\n <span\n className=\"flex-1 truncate text-sm leading-5\"\n title={profile.model ?? profile.name}\n >\n {profile.name}\n </span>\n {isCurrent && (\n <CheckIcon\n width={14}\n height={14}\n className=\"shrink-0\"\n aria-hidden\n />\n )}\n </span>\n {displayModel && (\n <span className=\"block truncate text-xs leading-4 text-[var(--oh-muted)]\">\n {displayModel}\n </span>\n )}\n </ContextMenuListItem>\n );\n })}\n </>\n )}\n {readOnlyProfileName && (\n <li className=\"text-sm\" data-testid=\"chat-input-llm-profile-current\">\n <div className=\"flex flex-col gap-0.5 p-2 leading-5 text-[var(--oh-foreground)]\">\n <span className=\"truncate\" title={readOnlyProfileName}>\n {readOnlyProfileName}\n </span>\n {currentProfileModel && (\n <span className=\"truncate text-xs leading-4 text-[var(--oh-muted)]\">\n {formatModelNameForDisplay(currentProfileModel)}\n </span>\n )}\n </div>\n </li>\n )}\n {(showProfileList || readOnlyProfileName) && (\n <Divider inset={dividerInset} />\n )}\n <li className=\"text-sm\">\n <NavigationLink\n to=\"/settings/llm\"\n onClick={onClose}\n className={cn(\n \"flex h-[30px] items-center gap-2 rounded p-2 leading-5 text-[var(--oh-foreground)] hover:bg-[var(--oh-interactive-hover)] transition-colors\",\n settingsLinkClassName,\n )}\n >\n <SettingsGearIcon\n width={16}\n height={16}\n className={cn(\"shrink-0\", settingsIconClassName)}\n aria-hidden\n />\n <span>{t(I18nKey.SETTINGS$LLM_PROFILES)}</span>\n </NavigationLink>\n </li>\n </>\n );\n}\n\nexport function ChatInputLlmProfilePicker() {\n const { t } = useTranslation(\"openhands\");\n const { profiles, currentProfileName, isLoading, isSwitching } =\n useChatInputLlmProfileState();\n const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const popoverRef = useClickOutsideElement<HTMLUListElement>(\n () => setIsPopoverOpen(false),\n triggerRef,\n );\n\n // No LLM profiles yet (or the agent-server lacks the surface): stay out of\n // the way, exactly like the ACP/AgentProfile pickers.\n if (isLoading || profiles.length === 0) {\n return null;\n }\n\n const label = currentProfileName ?? t(I18nKey.LLM$SELECT_MODEL_PLACEHOLDER);\n\n return (\n <div className=\"relative min-w-0\">\n <button\n ref={triggerRef}\n type=\"button\"\n className={cn(chatInputPillButtonClassName, \"max-w-[200px]\")}\n title={currentProfileName ?? undefined}\n data-testid=\"chat-input-llm-profile\"\n aria-expanded={isPopoverOpen}\n aria-haspopup=\"dialog\"\n // Disabled mid-switch so re-opening can't fire a second /switch_profile.\n disabled={isSwitching}\n aria-busy={isSwitching}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n setIsPopoverOpen((open) => !open);\n }}\n >\n <span className=\"truncate\">{truncateLabel(label)}</span>\n <ComboboxCaretInline isOpen={isPopoverOpen} />\n </button>\n\n {isPopoverOpen && (\n <ContextMenu\n ref={popoverRef}\n testId=\"chat-input-llm-profile-popover\"\n position=\"top\"\n alignment=\"left\"\n spacing=\"none\"\n className=\"z-[60] mb-2 min-w-[200px] max-w-[320px] max-h-[60vh] overflow-y-auto\"\n >\n <ChatInputLlmProfileMenuContent\n onClose={() => setIsPopoverOpen(false)}\n />\n </ContextMenu>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../node_modules/react-i18next/dist/es/Trans.cjs"),n=require("../../../i18n/declaration.cjs"),r=require("../../../node_modules/lucide-react/dist/esm/icons/chevron-down.cjs"),i=require("../../../node_modules/lucide-react/dist/esm/icons/chevron-right.cjs"),a=require("../../../stores/model-store.cjs"),o=require("./generic-event-message.cjs"),s=require("../../../icons/info-circle.cjs");let c=require("react");c=e.__toESM(c,1);let l=require("react/jsx-runtime");function u({profile:e}){let[t,n]=c.default.useState(!1);return(0,l.jsxs)(`div`,{className:`border border-neutral-700 rounded-md overflow-hidden`,children:[(0,l.jsxs)(`button`,{type:`button`,onClick:()=>n(e=>!e),"aria-expanded":t,"aria-label":`Toggle details for ${e.name}`,className:`w-full py-1.5 px-2 text-left flex items-center gap-2 hover:bg-neutral-700 transition-colors cursor-pointer`,children:[(0,l.jsx)(`span`,{className:`text-neutral-300`,children:t?(0,l.jsx)(r.ChevronDown,{size:14}):(0,l.jsx)(i.ChevronRight,{size:14})}),(0,l.jsx)(`span`,{className:`font-normal text-neutral-200 text-sm`,children:e.name})]}),t&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`hr`,{className:`border-neutral-700`}),(0,l.jsx)(`div`,{className:`px-3 py-2 text-xs text-neutral-300 font-mono whitespace-pre-wrap`,children:`model: ${e.model??`—`}\nbase_url: ${e.base_url??`—`}\napi_key: ${e.api_key_set?`set`:`not set`}`})]})]})}function d({conversationId:e,anchorEventId:r}){let i=a.useModelStore(e=>e.entriesByConversation),c=(e?i[e]??[]:[]).filter(e=>e.anchorEventId===r);return!e||c.length===0?null:(0,l.jsx)(`div`,{"data-testid":`model-messages`,className:`flex flex-col w-full`,children:c.map(e=>{if(e.switchedTo)return(0,l.jsx)(o.GenericEventMessage,{title:(0,l.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,l.jsx)(s.default,{width:14,height:14,className:`shrink-0 text-neutral-400`,"aria-hidden":!0}),(0,l.jsx)(t.Trans,{i18nKey:n.I18nKey.MODEL$SWITCHED_TO_PROFILE,values:{name:e.switchedTo},components:{cmd:(0,l.jsx)(`span`,{className:`font-mono text-neutral-200 bg-neutral-800 px-1 rounded`})}})]}),details:``},e.id);let r=e.profiles.length===0;return(0,l.jsx)(o.GenericEventMessage,{title:(0,l.jsx)(`span`,{children:r?(0,l.jsx)(t.Trans,{i18nKey:n.I18nKey.MODEL$NO_SAVED_PROFILES}):(0,l.jsx)(t.Trans,{i18nKey:n.I18nKey.MODEL$AVAILABLE_PROFILES,values:{count:e.profiles.length}})}),details:r?(0,l.jsx)(`span`,{className:`text-neutral-300 text-sm px-2 py-1 block`,children:(0,l.jsx)(t.Trans,{i18nKey:n.I18nKey.MODEL$NO_PROFILES_HINT})}):(0,l.jsx)(`div`,{className:`flex flex-col gap-1 mt-1`,children:e.profiles.map(e=>(0,l.jsx)(u,{profile:e},e.name))}),initiallyExpanded:r},e.id)})})}exports.ModelMessages=d;
1
+ const e=require("../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../node_modules/react-i18next/dist/es/Trans.cjs"),n=require("../../../i18n/declaration.cjs"),r=require("../../../node_modules/lucide-react/dist/esm/icons/chevron-down.cjs"),i=require("../../../node_modules/lucide-react/dist/esm/icons/chevron-right.cjs"),a=require("../../../stores/model-store.cjs"),o=require("./generic-event-message.cjs"),s=require("../../../icons/info-circle.cjs"),c=require("../../../utils/format-model-name.cjs");let l=require("react");l=e.__toESM(l,1);let u=require("react/jsx-runtime");function d({profile:e}){let[t,n]=l.default.useState(!1),a=c.formatModelNameForDisplay(e.model);return(0,u.jsxs)(`div`,{className:`border border-neutral-700 rounded-md overflow-hidden`,children:[(0,u.jsxs)(`button`,{type:`button`,onClick:()=>n(e=>!e),"aria-expanded":t,"aria-label":`Toggle details for ${e.name}`,className:`w-full py-1.5 px-2 text-left flex items-center gap-2 hover:bg-neutral-700 transition-colors cursor-pointer`,children:[(0,u.jsx)(`span`,{className:`text-neutral-300`,children:t?(0,u.jsx)(r.ChevronDown,{size:14}):(0,u.jsx)(i.ChevronRight,{size:14})}),(0,u.jsx)(`span`,{className:`font-normal text-neutral-200 text-sm`,children:e.name})]}),t&&(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(`hr`,{className:`border-neutral-700`}),(0,u.jsx)(`div`,{className:`px-3 py-2 text-xs text-neutral-300 font-mono whitespace-pre-wrap`,children:`model: ${a??`—`}\nbase_url: ${e.base_url??`—`}\napi_key: ${e.api_key_set?`set`:`not set`}`})]})]})}function f({conversationId:e,anchorEventId:r}){let i=a.useModelStore(e=>e.entriesByConversation),c=(e?i[e]??[]:[]).filter(e=>e.anchorEventId===r);return!e||c.length===0?null:(0,u.jsx)(`div`,{"data-testid":`model-messages`,className:`flex flex-col w-full`,children:c.map(e=>{if(e.switchedTo)return(0,u.jsx)(o.GenericEventMessage,{title:(0,u.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,u.jsx)(s.default,{width:14,height:14,className:`shrink-0 text-neutral-400`,"aria-hidden":!0}),(0,u.jsx)(t.Trans,{i18nKey:n.I18nKey.MODEL$SWITCHED_TO_PROFILE,values:{name:e.switchedTo},components:{cmd:(0,u.jsx)(`span`,{className:`font-mono text-neutral-200 bg-neutral-800 px-1 rounded`})}})]}),details:``},e.id);let r=e.profiles.length===0;return(0,u.jsx)(o.GenericEventMessage,{title:(0,u.jsx)(`span`,{children:r?(0,u.jsx)(t.Trans,{i18nKey:n.I18nKey.MODEL$NO_SAVED_PROFILES}):(0,u.jsx)(t.Trans,{i18nKey:n.I18nKey.MODEL$AVAILABLE_PROFILES,values:{count:e.profiles.length}})}),details:r?(0,u.jsx)(`span`,{className:`text-neutral-300 text-sm px-2 py-1 block`,children:(0,u.jsx)(t.Trans,{i18nKey:n.I18nKey.MODEL$NO_PROFILES_HINT})}):(0,u.jsx)(`div`,{className:`flex flex-col gap-1 mt-1`,children:e.profiles.map(e=>(0,u.jsx)(d,{profile:e},e.name))}),initiallyExpanded:r},e.id)})})}exports.ModelMessages=f;
2
2
  //# sourceMappingURL=model-messages.cjs.map