@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,19 +1,20 @@
1
1
  import { BUILT_IN_COMMANDS as e, MODEL_COMMAND as t } from "../../utils/constants.js";
2
2
  import { useActiveBackend as n } from "../../contexts/active-backend-context.js";
3
- import { useConversationSkills as r } from "../query/use-conversation-skills.js";
4
- import { useLlmProfiles as i } from "../query/use-llm-profiles.js";
5
- import { useCallback as a, useEffect as o, useMemo as s, useRef as c, useState as l } from "react";
3
+ import { formatModelNameForDisplay as r } from "../../utils/format-model-name.js";
4
+ import { useConversationSkills as i } from "../query/use-conversation-skills.js";
5
+ import { useLlmProfiles as a } from "../query/use-llm-profiles.js";
6
+ import { useCallback as o, useEffect as s, useMemo as c, useRef as l, useState as u } from "react";
6
7
  //#region src/hooks/chat/use-slash-command.ts
7
- function u(e) {
8
+ function d(e) {
8
9
  let t = window.getSelection();
9
10
  if (!t || t.rangeCount === 0) return -1;
10
11
  let n = t.getRangeAt(0), r = n.cloneRange();
11
12
  return r.selectNodeContents(e), r.setEnd(n.startContainer, n.startOffset), r.toString().length;
12
13
  }
13
- var d = (d) => {
14
- let { data: f, isLoading: p } = r(), m = n().backend.kind === "cloud", { data: h, isLoading: g } = i(), [_, v] = l(!1), [y, b] = l(""), [x, S] = l("command"), [C, w] = l(0), T = s(() => {
15
- let t = e.filter((e) => e.command === "/new" ? m : !0);
16
- return p || !f || f.forEach((e) => {
14
+ var f = (f) => {
15
+ let { data: p, isLoading: m } = i(), h = n().backend.kind === "cloud", { data: g, isLoading: _ } = a(), [v, y] = u(!1), [b, x] = u(""), [S, C] = u("command"), [w, T] = u(0), E = c(() => {
16
+ let t = e.filter((e) => e.command === "/new" ? h : !0);
17
+ return m || !p || p.forEach((e) => {
17
18
  let n = (e.triggers || []).filter((e) => e.startsWith("/"));
18
19
  n.length > 0 ? n.forEach((n) => {
19
20
  t.push({
@@ -26,42 +27,42 @@ var d = (d) => {
26
27
  });
27
28
  }), t;
28
29
  }, [
29
- f,
30
30
  p,
31
- m
32
- ]), E = s(() => (h?.profiles ?? []).map((e) => {
31
+ m,
32
+ h
33
+ ]), D = c(() => (g?.profiles ?? []).map((e) => {
33
34
  let n = `${t} ${e.name}`;
34
35
  return {
35
36
  command: n,
36
37
  skill: {
37
38
  name: e.name,
38
39
  type: "agentskills",
39
- content: e.model ? `Switch to ${e.model}` : "Switch to this LLM profile",
40
+ content: e.model ? `Switch to ${r(e.model)}` : "Switch to this LLM profile",
40
41
  triggers: [n]
41
42
  }
42
43
  };
43
- }), [h?.profiles]), D = s(() => {
44
- let e = x === "model-profile" ? E : T;
45
- if (!y) return e;
46
- let t = y.toLowerCase();
44
+ }), [g?.profiles]), O = c(() => {
45
+ let e = S === "model-profile" ? D : E;
46
+ if (!b) return e;
47
+ let t = b.toLowerCase();
47
48
  return e.filter((e) => e.command.toLowerCase().includes(t) || e.skill.name.toLowerCase().includes(t) || e.skill.content?.toLowerCase().includes(t));
48
49
  }, [
49
- x,
50
+ S,
51
+ D,
50
52
  E,
51
- T,
52
- y
53
- ]), O = c(_);
54
- O.current = _;
55
- let k = c(D);
56
- k.current = D;
57
- let A = c(C);
58
- A.current = C, o(() => {
59
- w(0);
60
- }, [y]);
61
- let j = c(null), M = a(() => {
62
- let e = d.current;
53
+ b
54
+ ]), k = l(v);
55
+ k.current = v;
56
+ let A = l(O);
57
+ A.current = O;
58
+ let j = l(w);
59
+ j.current = w, s(() => {
60
+ T(0);
61
+ }, [b]);
62
+ let M = l(null), N = o(() => {
63
+ let e = f.current;
63
64
  if (!e) return null;
64
- let t = (e.innerText || "").replace(/[\n\r]+$/, ""), n = u(e);
65
+ let t = (e.innerText || "").replace(/[\n\r]+$/, ""), n = d(e);
65
66
  if (n < 0) return null;
66
67
  let r = t.slice(0, n), i = r.match(/(^|\s)(\/model(?:\s+\S*)?)$/);
67
68
  if (i) {
@@ -82,21 +83,21 @@ var d = (d) => {
82
83
  start: s,
83
84
  end: l
84
85
  };
85
- }, [d]), N = a(() => {
86
- let e = M(), t = e?.kind === "model-profile" ? E.length > 0 || g : T.length > 0;
87
- e !== null && t ? (S(e.kind), b(e.text), j.current = {
86
+ }, [f]), P = o(() => {
87
+ let e = N(), t = e?.kind === "model-profile" ? D.length > 0 || _ : E.length > 0;
88
+ e !== null && t ? (C(e.kind), x(e.text), M.current = {
88
89
  start: e.start,
89
90
  end: e.end
90
- }, v(!0)) : (v(!1), b(""), S("command"), j.current = null);
91
+ }, y(!0)) : (y(!1), x(""), C("command"), M.current = null);
91
92
  }, [
92
- M,
93
- g,
94
- E.length,
95
- T.length
96
- ]), P = a((e) => {
97
- let t = d.current;
93
+ N,
94
+ _,
95
+ D.length,
96
+ E.length
97
+ ]), F = o((e) => {
98
+ let t = f.current;
98
99
  if (!t) return;
99
- let n = j.current, r = (t.innerText || "").replace(/[\n\r]+$/, ""), i = `${e.command} `;
100
+ let n = M.current, r = (t.innerText || "").replace(/[\n\r]+$/, ""), i = `${e.command} `;
100
101
  if (n) {
101
102
  t.textContent = r.slice(0, n.start) + i + r.slice(n.end);
102
103
  let e = n.start + i.length, a = t.firstChild;
@@ -109,37 +110,37 @@ var d = (d) => {
109
110
  let e = document.createRange(), n = window.getSelection();
110
111
  e.selectNodeContents(t), e.collapse(!1), n?.removeAllRanges(), n?.addRange(e);
111
112
  }
112
- v(!1), b(""), S("command"), w(0), j.current = null, t.dispatchEvent(new InputEvent("input", { bubbles: !0 })), t.focus();
113
- }, [d]);
113
+ y(!1), x(""), C("command"), T(0), M.current = null, t.dispatchEvent(new InputEvent("input", { bubbles: !0 })), t.focus();
114
+ }, [f]);
114
115
  return {
115
- isMenuOpen: _,
116
- filteredItems: D,
117
- selectedIndex: C,
118
- updateSlashMenu: N,
119
- selectItem: P,
120
- handleSlashKeyDown: a((e) => {
121
- let t = k.current;
122
- if (!O.current || t.length === 0) return !1;
116
+ isMenuOpen: v,
117
+ filteredItems: O,
118
+ selectedIndex: w,
119
+ updateSlashMenu: P,
120
+ selectItem: F,
121
+ handleSlashKeyDown: o((e) => {
122
+ let t = A.current;
123
+ if (!k.current || t.length === 0) return !1;
123
124
  switch (e.key) {
124
- case "ArrowDown": return e.preventDefault(), w((e) => e < t.length - 1 ? e + 1 : 0), !0;
125
- case "ArrowUp": return e.preventDefault(), w((e) => e > 0 ? e - 1 : t.length - 1), !0;
125
+ case "ArrowDown": return e.preventDefault(), T((e) => e < t.length - 1 ? e + 1 : 0), !0;
126
+ case "ArrowUp": return e.preventDefault(), T((e) => e > 0 ? e - 1 : t.length - 1), !0;
126
127
  case "Enter":
127
128
  case "Tab": {
128
- let n = t[A.current];
129
- return n ? (e.preventDefault(), P(n), !0) : !1;
129
+ let n = t[j.current];
130
+ return n ? (e.preventDefault(), F(n), !0) : !1;
130
131
  }
131
- case "Escape": return e.preventDefault(), v(!1), !0;
132
+ case "Escape": return e.preventDefault(), y(!1), !0;
132
133
  case "ArrowLeft":
133
134
  case "ArrowRight":
134
135
  case "Home":
135
- case "End": return v(!1), !1;
136
+ case "End": return y(!1), !1;
136
137
  default: return !1;
137
138
  }
138
- }, [P]),
139
- closeMenu: a(() => v(!1), [])
139
+ }, [F]),
140
+ closeMenu: o(() => y(!1), [])
140
141
  };
141
142
  };
142
143
  //#endregion
143
- export { d as useSlashCommand };
144
+ export { f as useSlashCommand };
144
145
 
145
146
  //# sourceMappingURL=use-slash-command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-slash-command.js","names":[],"sources":["../../../src/hooks/chat/use-slash-command.ts"],"sourcesContent":["import { useState, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useConversationSkills } from \"#/hooks/query/use-conversation-skills\";\nimport { SkillInfo } from \"#/types/settings\";\nimport { Microagent } from \"#/api/open-hands.types\";\nimport { BUILT_IN_COMMANDS, MODEL_COMMAND } from \"#/utils/constants\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useLlmProfiles } from \"#/hooks/query/use-llm-profiles\";\n\nexport type SlashCommandSkill = SkillInfo | Microagent;\n\nexport interface SlashCommandItem {\n skill: SlashCommandSkill;\n /** The slash command string, e.g. \"/random-number\" */\n command: string;\n}\n\ntype SlashCompletionKind = \"command\" | \"model-profile\";\n\n/** Get the cursor's character offset within a contentEditable element. */\nfunction getCursorOffset(element: HTMLElement): number {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return -1;\n const range = selection.getRangeAt(0);\n const preRange = range.cloneRange();\n preRange.selectNodeContents(element);\n preRange.setEnd(range.startContainer, range.startOffset);\n return preRange.toString().length;\n}\n\n/**\n * Hook for managing slash command autocomplete in the chat input.\n * Detects when user types \"/\" and provides filtered skill suggestions.\n * Only skills with explicit \"/\" triggers (TaskTrigger) appear in the menu.\n */\nexport const useSlashCommand = (\n chatInputRef: React.RefObject<HTMLDivElement | null>,\n) => {\n // Scope the skill catalog to this conversation's attached workspace so the\n // slash menu lists the same project skills that were loaded into it.\n const { data: skills, isLoading: isSkillsLoading } = useConversationSkills();\n const isCloud = useActiveBackend().backend.kind === \"cloud\";\n const { data: profilesData, isLoading: isProfilesLoading } = useLlmProfiles();\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n const [filterText, setFilterText] = useState(\"\");\n const [completionKind, setCompletionKind] =\n useState<SlashCompletionKind>(\"command\");\n const [selectedIndex, setSelectedIndex] = useState(0);\n\n // Build slash command items from built-in commands + skills:\n // - Built-in commands (like /new) are included for V1 conversations\n // - /new is cloud-only — local backends don't surface it\n // - /model lists/switches LLM profiles; both local and cloud support them\n // - Skills with explicit \"/\" triggers use those triggers\n // - AgentSkills without \"/\" triggers get a derived \"/<name>\" command\n const slashItems = useMemo(() => {\n const items: SlashCommandItem[] = BUILT_IN_COMMANDS.filter((cmd) => {\n if (cmd.command === \"/new\") return isCloud;\n return true;\n });\n\n // Wait for skills to finish initial load so all commands appear together\n if (isSkillsLoading) return items;\n\n if (!skills) return items;\n skills.forEach((skill) => {\n const triggers = skill.triggers || [];\n const slashTriggers = triggers.filter((t) => t.startsWith(\"/\"));\n\n if (slashTriggers.length > 0) {\n // Skill has explicit slash triggers\n slashTriggers.forEach((trigger) => {\n items.push({ skill, command: trigger });\n });\n } else if (skill.type === \"agentskills\") {\n // AgentSkills without slash triggers get a derived command\n items.push({ skill, command: `/${skill.name}` });\n }\n });\n return items;\n }, [skills, isSkillsLoading, isCloud]);\n\n const modelProfileItems = useMemo<SlashCommandItem[]>(() => {\n return (profilesData?.profiles ?? []).map((profile) => {\n const command = `${MODEL_COMMAND} ${profile.name}`;\n return {\n command,\n skill: {\n name: profile.name,\n type: \"agentskills\",\n content: profile.model\n ? `Switch to ${profile.model}`\n : \"Switch to this LLM profile\",\n triggers: [command],\n },\n };\n });\n }, [profilesData?.profiles]);\n\n // Filter items based on user input after \"/\"\n const filteredItems = useMemo(() => {\n const sourceItems =\n completionKind === \"model-profile\" ? modelProfileItems : slashItems;\n if (!filterText) return sourceItems;\n const lower = filterText.toLowerCase();\n return sourceItems.filter(\n (item) =>\n item.command.toLowerCase().includes(lower) ||\n item.skill.name.toLowerCase().includes(lower) ||\n item.skill.content?.toLowerCase().includes(lower),\n );\n }, [completionKind, modelProfileItems, slashItems, filterText]);\n\n // Keep refs in sync so handleSlashKeyDown always reads the latest values,\n // avoiding stale closures from React's batched state updates.\n const isMenuOpenRef = useRef(isMenuOpen);\n isMenuOpenRef.current = isMenuOpen;\n const filteredItemsRef = useRef(filteredItems);\n filteredItemsRef.current = filteredItems;\n const selectedIndexRef = useRef(selectedIndex);\n selectedIndexRef.current = selectedIndex;\n\n // Reset selected index when the filter text changes\n useEffect(() => {\n setSelectedIndex(0);\n }, [filterText]);\n\n // Track the character range of the current slash word so selectItem can\n // replace only that portion instead of wiping the entire input.\n const slashRangeRef = useRef<{ start: number; end: number } | null>(null);\n\n // Detect a slash word at the cursor position.\n // Returns the filter text (characters after \"/\") and the range of the\n // slash word within the full input text, or null if no slash word found.\n const getSlashText = useCallback((): {\n kind: SlashCompletionKind;\n text: string;\n start: number;\n end: number;\n } | null => {\n const element = chatInputRef.current;\n if (!element) return null;\n\n // Strip trailing newlines that contentEditable can produce, but preserve\n // spaces so \"/command \" (after selection) won't re-trigger the menu.\n const text = (element.innerText || \"\").replace(/[\\n\\r]+$/, \"\");\n const cursor = getCursorOffset(element);\n if (cursor < 0) return null;\n\n const textBeforeCursor = text.slice(0, cursor);\n\n const modelMatch = textBeforeCursor.match(/(^|\\s)(\\/model(?:\\s+\\S*)?)$/);\n if (modelMatch) {\n const modelCommand = modelMatch[2];\n const start = textBeforeCursor.length - modelCommand.length;\n const afterCursor = text.slice(cursor);\n const trailing = afterCursor.match(/^\\S*/);\n const end = cursor + (trailing ? trailing[0].length : 0);\n\n return {\n kind: \"model-profile\",\n text: modelCommand.replace(/^\\/model(?:\\s+)?/, \"\"),\n start,\n end,\n };\n }\n\n // Match a \"/\" preceded by whitespace or at position 0, followed by\n // non-whitespace characters, ending right at the cursor.\n const match = textBeforeCursor.match(/(^|\\s)(\\/\\S*)$/);\n if (!match) return null;\n\n const slashWord = match[2]; // e.g. \"/hel\"\n const start = textBeforeCursor.length - slashWord.length;\n // The end of the slash word extends past the cursor to include any\n // contiguous non-whitespace characters (covers the case where the\n // cursor sits in the middle of a word).\n const afterCursor = text.slice(cursor);\n const trailing = afterCursor.match(/^\\S*/);\n const end = cursor + (trailing ? trailing[0].length : 0);\n\n return { kind: \"command\", text: slashWord.slice(1), start, end }; // strip leading \"/\"\n }, [chatInputRef]);\n\n // Update the menu state based on current input\n const updateSlashMenu = useCallback(() => {\n const result = getSlashText();\n const hasItems =\n result?.kind === \"model-profile\"\n ? modelProfileItems.length > 0 || isProfilesLoading\n : slashItems.length > 0;\n\n if (result !== null && hasItems) {\n setCompletionKind(result.kind);\n setFilterText(result.text);\n slashRangeRef.current = { start: result.start, end: result.end };\n setIsMenuOpen(true);\n } else {\n setIsMenuOpen(false);\n setFilterText(\"\");\n setCompletionKind(\"command\");\n slashRangeRef.current = null;\n }\n }, [\n getSlashText,\n isProfilesLoading,\n modelProfileItems.length,\n slashItems.length,\n ]);\n\n // Select an item and replace only the slash word with the command\n const selectItem = useCallback(\n (item: SlashCommandItem) => {\n const element = chatInputRef.current;\n if (!element) return;\n\n const slashRange = slashRangeRef.current;\n const currentText = (element.innerText || \"\").replace(/[\\n\\r]+$/, \"\");\n const replacement = `${item.command} `;\n\n if (slashRange) {\n // Splice the command into the text, replacing only the slash word\n element.textContent =\n currentText.slice(0, slashRange.start) +\n replacement +\n currentText.slice(slashRange.end);\n\n // Position cursor right after the inserted command + space\n const cursorPos = slashRange.start + replacement.length;\n const textNode = element.firstChild;\n if (textNode) {\n const range = document.createRange();\n const sel = window.getSelection();\n const offset = Math.min(cursorPos, textNode.textContent!.length);\n range.setStart(textNode, offset);\n range.collapse(true);\n sel?.removeAllRanges();\n sel?.addRange(range);\n }\n } else {\n // Fallback: replace everything (e.g. if range tracking failed)\n element.textContent = replacement;\n const range = document.createRange();\n const sel = window.getSelection();\n range.selectNodeContents(element);\n range.collapse(false);\n sel?.removeAllRanges();\n sel?.addRange(range);\n }\n\n setIsMenuOpen(false);\n setFilterText(\"\");\n setCompletionKind(\"command\");\n setSelectedIndex(0);\n slashRangeRef.current = null;\n\n // Trigger a native InputEvent so React's onInput fires (for smartResize etc.)\n element.dispatchEvent(new InputEvent(\"input\", { bubbles: true }));\n\n // Restore focus so keyboard events (Enter to submit) work after selection\n element.focus();\n },\n [chatInputRef],\n );\n\n // Handle keyboard navigation in the menu.\n // Uses refs to always read the latest state, avoiding stale closures.\n const handleSlashKeyDown = useCallback(\n (e: React.KeyboardEvent): boolean => {\n const items = filteredItemsRef.current;\n if (!isMenuOpenRef.current || items.length === 0) return false;\n\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n setSelectedIndex((prev) => (prev < items.length - 1 ? prev + 1 : 0));\n return true;\n case \"ArrowUp\":\n e.preventDefault();\n setSelectedIndex((prev) => (prev > 0 ? prev - 1 : items.length - 1));\n return true;\n case \"Enter\":\n case \"Tab\": {\n const item = items[selectedIndexRef.current];\n if (!item) return false;\n e.preventDefault();\n selectItem(item);\n return true;\n }\n case \"Escape\":\n e.preventDefault();\n setIsMenuOpen(false);\n return true;\n // Cursor-movement keys: close the menu to avoid acting on a stale\n // slash-word range, but don't consume the event so the cursor moves.\n case \"ArrowLeft\":\n case \"ArrowRight\":\n case \"Home\":\n case \"End\":\n setIsMenuOpen(false);\n return false;\n default:\n return false;\n }\n },\n [selectItem],\n );\n\n const closeMenu = useCallback(() => setIsMenuOpen(false), []);\n\n return {\n isMenuOpen,\n filteredItems,\n selectedIndex,\n updateSlashMenu,\n selectItem,\n handleSlashKeyDown,\n closeMenu,\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-slash-command.js","names":[],"sources":["../../../src/hooks/chat/use-slash-command.ts"],"sourcesContent":["import { useState, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useConversationSkills } from \"#/hooks/query/use-conversation-skills\";\nimport { SkillInfo } from \"#/types/settings\";\nimport { Microagent } from \"#/api/open-hands.types\";\nimport { BUILT_IN_COMMANDS, MODEL_COMMAND } from \"#/utils/constants\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useLlmProfiles } from \"#/hooks/query/use-llm-profiles\";\nimport { formatModelNameForDisplay } from \"#/utils/format-model-name\";\n\nexport type SlashCommandSkill = SkillInfo | Microagent;\n\nexport interface SlashCommandItem {\n skill: SlashCommandSkill;\n /** The slash command string, e.g. \"/random-number\" */\n command: string;\n}\n\ntype SlashCompletionKind = \"command\" | \"model-profile\";\n\n/** Get the cursor's character offset within a contentEditable element. */\nfunction getCursorOffset(element: HTMLElement): number {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return -1;\n const range = selection.getRangeAt(0);\n const preRange = range.cloneRange();\n preRange.selectNodeContents(element);\n preRange.setEnd(range.startContainer, range.startOffset);\n return preRange.toString().length;\n}\n\n/**\n * Hook for managing slash command autocomplete in the chat input.\n * Detects when user types \"/\" and provides filtered skill suggestions.\n * Only skills with explicit \"/\" triggers (TaskTrigger) appear in the menu.\n */\nexport const useSlashCommand = (\n chatInputRef: React.RefObject<HTMLDivElement | null>,\n) => {\n // Scope the skill catalog to this conversation's attached workspace so the\n // slash menu lists the same project skills that were loaded into it.\n const { data: skills, isLoading: isSkillsLoading } = useConversationSkills();\n const isCloud = useActiveBackend().backend.kind === \"cloud\";\n const { data: profilesData, isLoading: isProfilesLoading } = useLlmProfiles();\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n const [filterText, setFilterText] = useState(\"\");\n const [completionKind, setCompletionKind] =\n useState<SlashCompletionKind>(\"command\");\n const [selectedIndex, setSelectedIndex] = useState(0);\n\n // Build slash command items from built-in commands + skills:\n // - Built-in commands (like /new) are included for V1 conversations\n // - /new is cloud-only — local backends don't surface it\n // - /model lists/switches LLM profiles; both local and cloud support them\n // - Skills with explicit \"/\" triggers use those triggers\n // - AgentSkills without \"/\" triggers get a derived \"/<name>\" command\n const slashItems = useMemo(() => {\n const items: SlashCommandItem[] = BUILT_IN_COMMANDS.filter((cmd) => {\n if (cmd.command === \"/new\") return isCloud;\n return true;\n });\n\n // Wait for skills to finish initial load so all commands appear together\n if (isSkillsLoading) return items;\n\n if (!skills) return items;\n skills.forEach((skill) => {\n const triggers = skill.triggers || [];\n const slashTriggers = triggers.filter((t) => t.startsWith(\"/\"));\n\n if (slashTriggers.length > 0) {\n // Skill has explicit slash triggers\n slashTriggers.forEach((trigger) => {\n items.push({ skill, command: trigger });\n });\n } else if (skill.type === \"agentskills\") {\n // AgentSkills without slash triggers get a derived command\n items.push({ skill, command: `/${skill.name}` });\n }\n });\n return items;\n }, [skills, isSkillsLoading, isCloud]);\n\n const modelProfileItems = useMemo<SlashCommandItem[]>(() => {\n return (profilesData?.profiles ?? []).map((profile) => {\n const command = `${MODEL_COMMAND} ${profile.name}`;\n return {\n command,\n skill: {\n name: profile.name,\n type: \"agentskills\",\n content: profile.model\n ? `Switch to ${formatModelNameForDisplay(profile.model)}`\n : \"Switch to this LLM profile\",\n triggers: [command],\n },\n };\n });\n }, [profilesData?.profiles]);\n\n // Filter items based on user input after \"/\"\n const filteredItems = useMemo(() => {\n const sourceItems =\n completionKind === \"model-profile\" ? modelProfileItems : slashItems;\n if (!filterText) return sourceItems;\n const lower = filterText.toLowerCase();\n return sourceItems.filter(\n (item) =>\n item.command.toLowerCase().includes(lower) ||\n item.skill.name.toLowerCase().includes(lower) ||\n item.skill.content?.toLowerCase().includes(lower),\n );\n }, [completionKind, modelProfileItems, slashItems, filterText]);\n\n // Keep refs in sync so handleSlashKeyDown always reads the latest values,\n // avoiding stale closures from React's batched state updates.\n const isMenuOpenRef = useRef(isMenuOpen);\n isMenuOpenRef.current = isMenuOpen;\n const filteredItemsRef = useRef(filteredItems);\n filteredItemsRef.current = filteredItems;\n const selectedIndexRef = useRef(selectedIndex);\n selectedIndexRef.current = selectedIndex;\n\n // Reset selected index when the filter text changes\n useEffect(() => {\n setSelectedIndex(0);\n }, [filterText]);\n\n // Track the character range of the current slash word so selectItem can\n // replace only that portion instead of wiping the entire input.\n const slashRangeRef = useRef<{ start: number; end: number } | null>(null);\n\n // Detect a slash word at the cursor position.\n // Returns the filter text (characters after \"/\") and the range of the\n // slash word within the full input text, or null if no slash word found.\n const getSlashText = useCallback((): {\n kind: SlashCompletionKind;\n text: string;\n start: number;\n end: number;\n } | null => {\n const element = chatInputRef.current;\n if (!element) return null;\n\n // Strip trailing newlines that contentEditable can produce, but preserve\n // spaces so \"/command \" (after selection) won't re-trigger the menu.\n const text = (element.innerText || \"\").replace(/[\\n\\r]+$/, \"\");\n const cursor = getCursorOffset(element);\n if (cursor < 0) return null;\n\n const textBeforeCursor = text.slice(0, cursor);\n\n const modelMatch = textBeforeCursor.match(/(^|\\s)(\\/model(?:\\s+\\S*)?)$/);\n if (modelMatch) {\n const modelCommand = modelMatch[2];\n const start = textBeforeCursor.length - modelCommand.length;\n const afterCursor = text.slice(cursor);\n const trailing = afterCursor.match(/^\\S*/);\n const end = cursor + (trailing ? trailing[0].length : 0);\n\n return {\n kind: \"model-profile\",\n text: modelCommand.replace(/^\\/model(?:\\s+)?/, \"\"),\n start,\n end,\n };\n }\n\n // Match a \"/\" preceded by whitespace or at position 0, followed by\n // non-whitespace characters, ending right at the cursor.\n const match = textBeforeCursor.match(/(^|\\s)(\\/\\S*)$/);\n if (!match) return null;\n\n const slashWord = match[2]; // e.g. \"/hel\"\n const start = textBeforeCursor.length - slashWord.length;\n // The end of the slash word extends past the cursor to include any\n // contiguous non-whitespace characters (covers the case where the\n // cursor sits in the middle of a word).\n const afterCursor = text.slice(cursor);\n const trailing = afterCursor.match(/^\\S*/);\n const end = cursor + (trailing ? trailing[0].length : 0);\n\n return { kind: \"command\", text: slashWord.slice(1), start, end }; // strip leading \"/\"\n }, [chatInputRef]);\n\n // Update the menu state based on current input\n const updateSlashMenu = useCallback(() => {\n const result = getSlashText();\n const hasItems =\n result?.kind === \"model-profile\"\n ? modelProfileItems.length > 0 || isProfilesLoading\n : slashItems.length > 0;\n\n if (result !== null && hasItems) {\n setCompletionKind(result.kind);\n setFilterText(result.text);\n slashRangeRef.current = { start: result.start, end: result.end };\n setIsMenuOpen(true);\n } else {\n setIsMenuOpen(false);\n setFilterText(\"\");\n setCompletionKind(\"command\");\n slashRangeRef.current = null;\n }\n }, [\n getSlashText,\n isProfilesLoading,\n modelProfileItems.length,\n slashItems.length,\n ]);\n\n // Select an item and replace only the slash word with the command\n const selectItem = useCallback(\n (item: SlashCommandItem) => {\n const element = chatInputRef.current;\n if (!element) return;\n\n const slashRange = slashRangeRef.current;\n const currentText = (element.innerText || \"\").replace(/[\\n\\r]+$/, \"\");\n const replacement = `${item.command} `;\n\n if (slashRange) {\n // Splice the command into the text, replacing only the slash word\n element.textContent =\n currentText.slice(0, slashRange.start) +\n replacement +\n currentText.slice(slashRange.end);\n\n // Position cursor right after the inserted command + space\n const cursorPos = slashRange.start + replacement.length;\n const textNode = element.firstChild;\n if (textNode) {\n const range = document.createRange();\n const sel = window.getSelection();\n const offset = Math.min(cursorPos, textNode.textContent!.length);\n range.setStart(textNode, offset);\n range.collapse(true);\n sel?.removeAllRanges();\n sel?.addRange(range);\n }\n } else {\n // Fallback: replace everything (e.g. if range tracking failed)\n element.textContent = replacement;\n const range = document.createRange();\n const sel = window.getSelection();\n range.selectNodeContents(element);\n range.collapse(false);\n sel?.removeAllRanges();\n sel?.addRange(range);\n }\n\n setIsMenuOpen(false);\n setFilterText(\"\");\n setCompletionKind(\"command\");\n setSelectedIndex(0);\n slashRangeRef.current = null;\n\n // Trigger a native InputEvent so React's onInput fires (for smartResize etc.)\n element.dispatchEvent(new InputEvent(\"input\", { bubbles: true }));\n\n // Restore focus so keyboard events (Enter to submit) work after selection\n element.focus();\n },\n [chatInputRef],\n );\n\n // Handle keyboard navigation in the menu.\n // Uses refs to always read the latest state, avoiding stale closures.\n const handleSlashKeyDown = useCallback(\n (e: React.KeyboardEvent): boolean => {\n const items = filteredItemsRef.current;\n if (!isMenuOpenRef.current || items.length === 0) return false;\n\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n setSelectedIndex((prev) => (prev < items.length - 1 ? prev + 1 : 0));\n return true;\n case \"ArrowUp\":\n e.preventDefault();\n setSelectedIndex((prev) => (prev > 0 ? prev - 1 : items.length - 1));\n return true;\n case \"Enter\":\n case \"Tab\": {\n const item = items[selectedIndexRef.current];\n if (!item) return false;\n e.preventDefault();\n selectItem(item);\n return true;\n }\n case \"Escape\":\n e.preventDefault();\n setIsMenuOpen(false);\n return true;\n // Cursor-movement keys: close the menu to avoid acting on a stale\n // slash-word range, but don't consume the event so the cursor moves.\n case \"ArrowLeft\":\n case \"ArrowRight\":\n case \"Home\":\n case \"End\":\n setIsMenuOpen(false);\n return false;\n default:\n return false;\n }\n },\n [selectItem],\n );\n\n const closeMenu = useCallback(() => setIsMenuOpen(false), []);\n\n return {\n isMenuOpen,\n filteredItems,\n selectedIndex,\n updateSlashMenu,\n selectItem,\n handleSlashKeyDown,\n closeMenu,\n };\n};\n"],"mappings":"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"}
package/dist/package.cjs CHANGED
@@ -1,2 +1,2 @@
1
- require("./_virtual/_rolldown/runtime.cjs");var e={name:`@openhands/agent-canvas`,version:`1.11.0`,description:`Agent Canvas UI for OpenHands - run AI coding agents with a visual interface`,license:`MIT`,private:!1,type:`module`,repository:{type:`git`,url:`https://github.com/OpenHands/OpenHands`},homepage:`https://github.com/OpenHands/OpenHands#readme`,bugs:{url:`https://github.com/OpenHands/OpenHands/issues`},bin:{"agent-canvas":`bin/agent-canvas.mjs`},engines:{node:`>=22.12.0`},dependencies:{"@heroui/react":`2.8.10`,"@microlink/react-json-view":`1.31.20`,"@monaco-editor/react":`4.7.0`,"@openhands/extensions":`0.16.0`,"@openhands/typescript-client":`1.36.1`,"@react-router/node":`7.18.2`,"@react-router/serve":`7.18.2`,"@tailwindcss/vite":`4.3.3`,"@tanstack/react-query":`5.101.4`,"@types/shell-quote":`1.7.5`,"@uidotdev/usehooks":`2.4.1`,"@xterm/addon-fit":`0.11.0`,"@xterm/xterm":`6.0.0`,axios:`1.18.0`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,downshift:`9.3.2`,"framer-motion":`12.38.0`,httpxy:`0.5.3`,i18next:`26.3.6`,"i18next-browser-languagedetector":`8.2.1`,"i18next-http-backend":`4.0.0`,isbot:`5.1.39`,"lucide-react":`1.25.0`,"monaco-editor":`0.56.0`,"posthog-js":`1.380.0`,react:`19.2.8`,"react-dom":`19.2.8`,"react-hot-toast":`2.6.0`,"react-i18next":`17.0.11`,"react-icons":`5.6.0`,"react-markdown":`10.1.0`,"react-router":`7.18.2`,"react-syntax-highlighter":`16.1.1`,"rehype-raw":`7.0.0`,"rehype-sanitize":`6.0.0`,"remark-breaks":`4.0.0`,"remark-gfm":`4.0.1`,"shell-quote":`1.9.0`,sirv:`3.0.2`,"sirv-cli":`3.0.1`,"socket.io-client":`4.8.3`,"tailwind-merge":`3.6.0`,"tailwind-scrollbar":`4.0.2`,"unist-util-visit":`5.1.0`,uuid:`14.0.0`,vite:`8.0.16`,winston:`3.19.0`,"winston-daily-rotate-file":`5.0.0`,zustand:`5.0.12`},scripts:{dev:`node --env-file-if-exists=.env scripts/dev-with-automation.mjs`,"dev:static":`node --env-file-if-exists=.env scripts/dev-static.mjs`,"dev:extra-backend":`node --env-file-if-exists=.env scripts/dev-extra-backend.mjs`,"dev:minimal":`node --env-file-if-exists=.env scripts/dev-safe.mjs`,"dev:frontend":`npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev`,"dev:mock":`npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev`,build:`npm run build:app`,"build:mock":`npm run make-i18n && cross-env VITE_MOCK_API=true react-router build`,start:`npx sirv-cli build/ --single`,test:`npm run make-i18n && vitest run`,"test:e2e":`playwright test --pass-with-no-tests`,"test:e2e:live":`node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs`,"test:e2e:mock-llm":`playwright test --config=playwright.mock-llm.config.ts`,"test:e2e:mock-llm:docker":`playwright test --config=playwright.mock-llm-docker.config.ts`,"test:coverage":`npm run make-i18n && vitest run --coverage`,"test:mutation":`npm run make-i18n && stryker run`,"test:mutation:diff":`npm run make-i18n && node scripts/stryker-diff.mjs`,"test:mutation:incremental":`npm run make-i18n && stryker run --incremental`,dev_wsl:`VITE_WATCH_USE_POLLING=true vite`,preview:`vite preview`,"make-i18n":`node scripts/make-i18n-translations.cjs`,prelint:`npm run make-i18n`,lint:`npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}`,"lint:fix":`eslint src --fix && prettier --write src/**/*.{ts,tsx}`,prepare:`husky`,typecheck:`react-router typegen && tsc`,"typecheck:staged":`react-router typegen && npx tsc --noEmit --skipLibCheck`,"check-translation-completeness":`node scripts/check-translation-completeness.cjs`,"build:app":`npm run make-i18n && react-router build`,"build:lib":`npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true vite build && tsc -p tsconfig.lib.json`,"build:docker":`node scripts/docker-build.mjs`,"example:acp-docker:env":`node scripts/gen-acp-docker-env.mjs`,predesktop:`node scripts/brand-dev-electron.mjs`,desktop:`npm run build:app && electron electron`,"build:desktop":`npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && electron-builder --config electron-builder.config.mjs --publish never`,"build:desktop:universal":`npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && cross-env ELECTRON_ARCH=universal electron-builder --config electron-builder.config.mjs --publish never`,"download-uv":`node scripts/download-uv.mjs`,"download-node":`node scripts/download-node.mjs`,"generate-icons":`node scripts/generate-icons.mjs`},"lint-staged":{"src/**/*.{ts,tsx,js}":[`eslint --fix`,`prettier --write`],"src/**/*.{ts,tsx}":[`node scripts/run-staged-typecheck.mjs`],"src/**/*":[`npm run check-translation-completeness`]},devDependencies:{"@eslint/eslintrc":`3.3.1`,"@eslint/js":`9.39.4`,"@mswjs/socket.io-binding":`0.2.0`,"@playwright/test":`1.62.0`,"@react-router/dev":`7.18.2`,"@stryker-mutator/core":`9.6.1`,"@stryker-mutator/vitest-runner":`9.6.1`,"@tailwindcss/typography":`0.5.20`,"@tanstack/eslint-plugin-query":`5.101.4`,"@testing-library/dom":`10.4.1`,"@testing-library/jest-dom":`7.0.0`,"@testing-library/react":`16.3.2`,"@testing-library/user-event":`14.6.1`,"@types/mdast":`4.0.4`,"@types/node":`26.1.2`,"@types/react":`19.2.17`,"@types/react-dom":`19.2.3`,"@types/react-syntax-highlighter":`15.5.13`,"@typescript-eslint/eslint-plugin":`8.59.2`,"@typescript-eslint/parser":`8.59.2`,"@vercel/react-router":`1.3.0`,"@vitest/coverage-v8":`4.1.10`,"cross-env":`10.1.0`,electron:`42.3.3`,"electron-builder":`26.15.3`,eslint:`9.39.4`,"eslint-config-prettier":`10.1.8`,"eslint-import-resolver-typescript":`4.4.5`,"eslint-plugin-i18next":`6.1.5`,"eslint-plugin-import-x":`4.16.2`,"eslint-plugin-jsx-a11y":`6.10.2`,"eslint-plugin-prettier":`5.5.5`,"eslint-plugin-react":`7.37.5`,"eslint-plugin-react-hooks":`7.1.1`,"eslint-plugin-unused-imports":`4.4.1`,globals:`16.5.0`,husky:`9.1.7`,jsdom:`30.0.0`,"lint-staged":`16.4.0`,msw:`2.15.0`,png2icons:`2.0.1`,"postcss-prefix-selector":`2.1.1`,prettier:`3.8.3`,tailwindcss:`4.3.3`,typescript:`6.0.3`,"vite-plugin-svgr":`5.2.0`,vitest:`4.1.10`},packageManager:`npm@10.5.0`,volta:{node:`22.12.0`},msw:{workerDirectory:[`public`]},overrides:{"@vercel/static-config":{ajv:`8.20.0`},dompurify:`3.4.12`,"typed-rest-client":{qs:`6.15.3`}},main:`./dist/index.cjs`,module:`./dist/index.js`,types:`./dist/index.d.ts`,files:[`dist`,`bin`,`build`,`config`,`scripts`,`tools`],exports:{".":{types:`./dist/index.d.ts`,import:`./dist/index.js`,require:`./dist/index.cjs`},"./browser":{types:`./dist/components/browser/index.d.ts`,import:`./dist/components/browser/index.js`,require:`./dist/components/browser/index.cjs`},"./conversation":{types:`./dist/components/conversation/index.d.ts`,import:`./dist/components/conversation/index.js`,require:`./dist/components/conversation/index.cjs`},"./files":{types:`./dist/components/files/index.d.ts`,import:`./dist/components/files/index.js`,require:`./dist/components/files/index.cjs`},"./settings":{types:`./dist/components/settings/index.d.ts`,import:`./dist/components/settings/index.js`,require:`./dist/components/settings/index.cjs`},"./sidebar":{types:`./dist/components/sidebar/index.d.ts`,import:`./dist/components/sidebar/index.js`,require:`./dist/components/sidebar/index.cjs`},"./terminal":{types:`./dist/components/terminal/index.d.ts`,import:`./dist/components/terminal/index.js`,require:`./dist/components/terminal/index.cjs`},"./i18n":{types:`./dist/i18n/index.d.ts`,import:`./dist/i18n/index.js`,require:`./dist/i18n/index.cjs`},"./package.json":`./package.json`},peerDependencies:{react:`19.2.8`,"react-dom":`19.2.8`,"react-router":`7.18.2`}};exports.default=e;
1
+ require("./_virtual/_rolldown/runtime.cjs");var e={name:`@openhands/agent-canvas`,version:`1.12.0`,description:`Agent Canvas UI for OpenHands - run AI coding agents with a visual interface`,license:`MIT`,private:!1,type:`module`,repository:{type:`git`,url:`https://github.com/OpenHands/OpenHands`},homepage:`https://github.com/OpenHands/OpenHands#readme`,bugs:{url:`https://github.com/OpenHands/OpenHands/issues`},bin:{"agent-canvas":`bin/agent-canvas.mjs`},engines:{node:`>=22.12.0`},dependencies:{"@heroui/react":`2.8.10`,"@microlink/react-json-view":`1.31.20`,"@monaco-editor/react":`4.7.0`,"@openhands/extensions":`0.16.0`,"@openhands/typescript-client":`1.36.1`,"@react-router/node":`7.18.2`,"@react-router/serve":`7.18.2`,"@tailwindcss/vite":`4.3.3`,"@tanstack/react-query":`5.101.4`,"@types/shell-quote":`1.7.5`,"@uidotdev/usehooks":`2.4.1`,"@xterm/addon-fit":`0.11.0`,"@xterm/xterm":`6.0.0`,axios:`1.18.0`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,downshift:`9.3.2`,"framer-motion":`12.38.0`,httpxy:`0.5.3`,i18next:`26.3.6`,"i18next-browser-languagedetector":`8.2.1`,"i18next-http-backend":`4.0.0`,isbot:`5.1.39`,"lucide-react":`1.25.0`,"monaco-editor":`0.56.0`,"posthog-js":`1.380.0`,react:`19.2.8`,"react-dom":`19.2.8`,"react-hot-toast":`2.6.0`,"react-i18next":`17.0.11`,"react-icons":`5.6.0`,"react-markdown":`10.1.0`,"react-router":`7.18.2`,"react-syntax-highlighter":`16.1.1`,"rehype-raw":`7.0.0`,"rehype-sanitize":`6.0.0`,"remark-breaks":`4.0.0`,"remark-gfm":`4.0.1`,"shell-quote":`1.9.0`,sirv:`3.0.2`,"sirv-cli":`3.0.1`,"socket.io-client":`4.8.3`,"tailwind-merge":`3.6.0`,"tailwind-scrollbar":`4.0.2`,"unist-util-visit":`5.1.0`,uuid:`14.0.0`,vite:`8.0.16`,winston:`3.19.0`,"winston-daily-rotate-file":`5.0.0`,zustand:`5.0.12`},scripts:{dev:`node --env-file-if-exists=.env scripts/dev-with-automation.mjs`,"dev:static":`node --env-file-if-exists=.env scripts/dev-static.mjs`,"dev:extra-backend":`node --env-file-if-exists=.env scripts/dev-extra-backend.mjs`,"dev:minimal":`node --env-file-if-exists=.env scripts/dev-safe.mjs`,"dev:frontend":`npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev`,"dev:mock":`npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev`,build:`npm run build:app`,"build:mock":`npm run make-i18n && cross-env VITE_MOCK_API=true react-router build`,start:`npx sirv-cli build/ --single`,test:`npm run make-i18n && vitest run`,"test:e2e":`playwright test --pass-with-no-tests`,"test:e2e:live":`node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs`,"test:e2e:mock-llm":`playwright test --config=playwright.mock-llm.config.ts`,"test:e2e:mock-llm:docker":`playwright test --config=playwright.mock-llm-docker.config.ts`,"test:coverage":`npm run make-i18n && vitest run --coverage`,"test:mutation":`npm run make-i18n && stryker run`,"test:mutation:diff":`npm run make-i18n && node scripts/stryker-diff.mjs`,"test:mutation:incremental":`npm run make-i18n && stryker run --incremental`,dev_wsl:`VITE_WATCH_USE_POLLING=true vite`,preview:`vite preview`,"make-i18n":`node scripts/make-i18n-translations.cjs`,prelint:`npm run make-i18n`,lint:`npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}`,"lint:fix":`eslint src --fix && prettier --write src/**/*.{ts,tsx}`,prepare:`husky`,typecheck:`react-router typegen && tsc`,"typecheck:staged":`react-router typegen && npx tsc --noEmit --skipLibCheck`,"check-translation-completeness":`node scripts/check-translation-completeness.cjs`,"build:app":`npm run make-i18n && react-router build`,"build:lib":`npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true vite build && tsc -p tsconfig.lib.json`,"build:docker":`node scripts/docker-build.mjs`,"example:acp-docker:env":`node scripts/gen-acp-docker-env.mjs`,predesktop:`node scripts/brand-dev-electron.mjs`,desktop:`npm run build:app && electron electron`,"build:desktop":`npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && electron-builder --config electron-builder.config.mjs --publish never`,"build:desktop:universal":`npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && cross-env ELECTRON_ARCH=universal electron-builder --config electron-builder.config.mjs --publish never`,"download-uv":`node scripts/download-uv.mjs`,"download-node":`node scripts/download-node.mjs`,"generate-icons":`node scripts/generate-icons.mjs`},"lint-staged":{"src/**/*.{ts,tsx,js}":[`eslint --fix`,`prettier --write`],"src/**/*.{ts,tsx}":[`node scripts/run-staged-typecheck.mjs`],"src/**/*":[`npm run check-translation-completeness`]},devDependencies:{"@eslint/eslintrc":`3.3.1`,"@eslint/js":`9.39.4`,"@mswjs/socket.io-binding":`0.2.0`,"@playwright/test":`1.62.0`,"@react-router/dev":`7.18.2`,"@stryker-mutator/core":`9.6.1`,"@stryker-mutator/vitest-runner":`9.6.1`,"@tailwindcss/typography":`0.5.20`,"@tanstack/eslint-plugin-query":`5.101.4`,"@testing-library/dom":`10.4.1`,"@testing-library/jest-dom":`7.0.0`,"@testing-library/react":`16.3.2`,"@testing-library/user-event":`14.6.1`,"@types/mdast":`4.0.4`,"@types/node":`26.1.2`,"@types/react":`19.2.17`,"@types/react-dom":`19.2.3`,"@types/react-syntax-highlighter":`15.5.13`,"@typescript-eslint/eslint-plugin":`8.59.2`,"@typescript-eslint/parser":`8.59.2`,"@vercel/react-router":`1.3.0`,"@vitest/coverage-v8":`4.1.10`,"cross-env":`10.1.0`,electron:`42.3.3`,"electron-builder":`26.15.3`,eslint:`9.39.4`,"eslint-config-prettier":`10.1.8`,"eslint-import-resolver-typescript":`4.4.5`,"eslint-plugin-i18next":`6.1.5`,"eslint-plugin-import-x":`4.16.2`,"eslint-plugin-jsx-a11y":`6.10.2`,"eslint-plugin-prettier":`5.5.5`,"eslint-plugin-react":`7.37.5`,"eslint-plugin-react-hooks":`7.1.1`,"eslint-plugin-unused-imports":`4.4.1`,globals:`16.5.0`,husky:`9.1.7`,jsdom:`30.0.0`,"lint-staged":`16.4.0`,msw:`2.15.0`,png2icons:`2.0.1`,"postcss-prefix-selector":`2.1.1`,prettier:`3.8.3`,tailwindcss:`4.3.3`,typescript:`6.0.3`,"vite-plugin-svgr":`5.2.0`,vitest:`4.1.10`},packageManager:`npm@10.5.0`,volta:{node:`22.12.0`},msw:{workerDirectory:[`public`]},overrides:{"@vercel/static-config":{ajv:`8.20.0`},dompurify:`3.4.12`,"typed-rest-client":{qs:`6.15.3`}},main:`./dist/index.cjs`,module:`./dist/index.js`,types:`./dist/index.d.ts`,files:[`dist`,`bin`,`build`,`config`,`scripts`,`tools`],exports:{".":{types:`./dist/index.d.ts`,import:`./dist/index.js`,require:`./dist/index.cjs`},"./browser":{types:`./dist/components/browser/index.d.ts`,import:`./dist/components/browser/index.js`,require:`./dist/components/browser/index.cjs`},"./conversation":{types:`./dist/components/conversation/index.d.ts`,import:`./dist/components/conversation/index.js`,require:`./dist/components/conversation/index.cjs`},"./files":{types:`./dist/components/files/index.d.ts`,import:`./dist/components/files/index.js`,require:`./dist/components/files/index.cjs`},"./settings":{types:`./dist/components/settings/index.d.ts`,import:`./dist/components/settings/index.js`,require:`./dist/components/settings/index.cjs`},"./sidebar":{types:`./dist/components/sidebar/index.d.ts`,import:`./dist/components/sidebar/index.js`,require:`./dist/components/sidebar/index.cjs`},"./terminal":{types:`./dist/components/terminal/index.d.ts`,import:`./dist/components/terminal/index.js`,require:`./dist/components/terminal/index.cjs`},"./i18n":{types:`./dist/i18n/index.d.ts`,import:`./dist/i18n/index.js`,require:`./dist/i18n/index.cjs`},"./package.json":`./package.json`},peerDependencies:{react:`19.2.8`,"react-dom":`19.2.8`,"react-router":`7.18.2`}};exports.default=e;
2
2
  //# sourceMappingURL=package.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"package.cjs","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@openhands/agent-canvas\",\n \"version\": \"1.11.0\",\n \"description\": \"Agent Canvas UI for OpenHands - run AI coding agents with a visual interface\",\n \"license\": \"MIT\",\n \"private\": false,\n \"type\": \"module\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/OpenHands/OpenHands\"\n },\n \"homepage\": \"https://github.com/OpenHands/OpenHands#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/OpenHands/OpenHands/issues\"\n },\n \"bin\": {\n \"agent-canvas\": \"bin/agent-canvas.mjs\"\n },\n \"engines\": {\n \"node\": \">=22.12.0\"\n },\n \"dependencies\": {\n \"@heroui/react\": \"2.8.10\",\n \"@microlink/react-json-view\": \"1.31.20\",\n \"@monaco-editor/react\": \"4.7.0\",\n \"@openhands/extensions\": \"0.16.0\",\n \"@openhands/typescript-client\": \"1.36.1\",\n \"@react-router/node\": \"7.18.2\",\n \"@react-router/serve\": \"7.18.2\",\n \"@tailwindcss/vite\": \"4.3.3\",\n \"@tanstack/react-query\": \"5.101.4\",\n \"@types/shell-quote\": \"1.7.5\",\n \"@uidotdev/usehooks\": \"2.4.1\",\n \"@xterm/addon-fit\": \"0.11.0\",\n \"@xterm/xterm\": \"6.0.0\",\n \"axios\": \"1.18.0\",\n \"class-variance-authority\": \"0.7.1\",\n \"clsx\": \"2.1.1\",\n \"downshift\": \"9.3.2\",\n \"framer-motion\": \"12.38.0\",\n \"httpxy\": \"0.5.3\",\n \"i18next\": \"26.3.6\",\n \"i18next-browser-languagedetector\": \"8.2.1\",\n \"i18next-http-backend\": \"4.0.0\",\n \"isbot\": \"5.1.39\",\n \"lucide-react\": \"1.25.0\",\n \"monaco-editor\": \"0.56.0\",\n \"posthog-js\": \"1.380.0\",\n \"react\": \"19.2.8\",\n \"react-dom\": \"19.2.8\",\n \"react-hot-toast\": \"2.6.0\",\n \"react-i18next\": \"17.0.11\",\n \"react-icons\": \"5.6.0\",\n \"react-markdown\": \"10.1.0\",\n \"react-router\": \"7.18.2\",\n \"react-syntax-highlighter\": \"16.1.1\",\n \"rehype-raw\": \"7.0.0\",\n \"rehype-sanitize\": \"6.0.0\",\n \"remark-breaks\": \"4.0.0\",\n \"remark-gfm\": \"4.0.1\",\n \"shell-quote\": \"1.9.0\",\n \"sirv\": \"3.0.2\",\n \"sirv-cli\": \"3.0.1\",\n \"socket.io-client\": \"4.8.3\",\n \"tailwind-merge\": \"3.6.0\",\n \"tailwind-scrollbar\": \"4.0.2\",\n \"unist-util-visit\": \"5.1.0\",\n \"uuid\": \"14.0.0\",\n \"vite\": \"8.0.16\",\n \"winston\": \"3.19.0\",\n \"winston-daily-rotate-file\": \"5.0.0\",\n \"zustand\": \"5.0.12\"\n },\n \"scripts\": {\n \"dev\": \"node --env-file-if-exists=.env scripts/dev-with-automation.mjs\",\n \"dev:static\": \"node --env-file-if-exists=.env scripts/dev-static.mjs\",\n \"dev:extra-backend\": \"node --env-file-if-exists=.env scripts/dev-extra-backend.mjs\",\n \"dev:minimal\": \"node --env-file-if-exists=.env scripts/dev-safe.mjs\",\n \"dev:frontend\": \"npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev\",\n \"dev:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev\",\n \"build\": \"npm run build:app\",\n \"build:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router build\",\n \"start\": \"npx sirv-cli build/ --single\",\n \"test\": \"npm run make-i18n && vitest run\",\n \"test:e2e\": \"playwright test --pass-with-no-tests\",\n \"test:e2e:live\": \"node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs\",\n \"test:e2e:mock-llm\": \"playwright test --config=playwright.mock-llm.config.ts\",\n \"test:e2e:mock-llm:docker\": \"playwright test --config=playwright.mock-llm-docker.config.ts\",\n \"test:coverage\": \"npm run make-i18n && vitest run --coverage\",\n \"test:mutation\": \"npm run make-i18n && stryker run\",\n \"test:mutation:diff\": \"npm run make-i18n && node scripts/stryker-diff.mjs\",\n \"test:mutation:incremental\": \"npm run make-i18n && stryker run --incremental\",\n \"dev_wsl\": \"VITE_WATCH_USE_POLLING=true vite\",\n \"preview\": \"vite preview\",\n \"make-i18n\": \"node scripts/make-i18n-translations.cjs\",\n \"prelint\": \"npm run make-i18n\",\n \"lint\": \"npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}\",\n \"lint:fix\": \"eslint src --fix && prettier --write src/**/*.{ts,tsx}\",\n \"prepare\": \"husky\",\n \"typecheck\": \"react-router typegen && tsc\",\n \"typecheck:staged\": \"react-router typegen && npx tsc --noEmit --skipLibCheck\",\n \"check-translation-completeness\": \"node scripts/check-translation-completeness.cjs\",\n \"build:app\": \"npm run make-i18n && react-router build\",\n \"build:lib\": \"npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true vite build && tsc -p tsconfig.lib.json\",\n \"build:docker\": \"node scripts/docker-build.mjs\",\n \"example:acp-docker:env\": \"node scripts/gen-acp-docker-env.mjs\",\n \"predesktop\": \"node scripts/brand-dev-electron.mjs\",\n \"desktop\": \"npm run build:app && electron electron\",\n \"build:desktop\": \"npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && electron-builder --config electron-builder.config.mjs --publish never\",\n \"build:desktop:universal\": \"npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && cross-env ELECTRON_ARCH=universal electron-builder --config electron-builder.config.mjs --publish never\",\n \"download-uv\": \"node scripts/download-uv.mjs\",\n \"download-node\": \"node scripts/download-node.mjs\",\n \"generate-icons\": \"node scripts/generate-icons.mjs\"\n },\n \"lint-staged\": {\n \"src/**/*.{ts,tsx,js}\": [\n \"eslint --fix\",\n \"prettier --write\"\n ],\n \"src/**/*.{ts,tsx}\": [\n \"node scripts/run-staged-typecheck.mjs\"\n ],\n \"src/**/*\": [\n \"npm run check-translation-completeness\"\n ]\n },\n \"devDependencies\": {\n \"@eslint/eslintrc\": \"3.3.1\",\n \"@eslint/js\": \"9.39.4\",\n \"@mswjs/socket.io-binding\": \"0.2.0\",\n \"@playwright/test\": \"1.62.0\",\n \"@react-router/dev\": \"7.18.2\",\n \"@stryker-mutator/core\": \"9.6.1\",\n \"@stryker-mutator/vitest-runner\": \"9.6.1\",\n \"@tailwindcss/typography\": \"0.5.20\",\n \"@tanstack/eslint-plugin-query\": \"5.101.4\",\n \"@testing-library/dom\": \"10.4.1\",\n \"@testing-library/jest-dom\": \"7.0.0\",\n \"@testing-library/react\": \"16.3.2\",\n \"@testing-library/user-event\": \"14.6.1\",\n \"@types/mdast\": \"4.0.4\",\n \"@types/node\": \"26.1.2\",\n \"@types/react\": \"19.2.17\",\n \"@types/react-dom\": \"19.2.3\",\n \"@types/react-syntax-highlighter\": \"15.5.13\",\n \"@typescript-eslint/eslint-plugin\": \"8.59.2\",\n \"@typescript-eslint/parser\": \"8.59.2\",\n \"@vercel/react-router\": \"1.3.0\",\n \"@vitest/coverage-v8\": \"4.1.10\",\n \"cross-env\": \"10.1.0\",\n \"electron\": \"42.3.3\",\n \"electron-builder\": \"26.15.3\",\n \"eslint\": \"9.39.4\",\n \"eslint-config-prettier\": \"10.1.8\",\n \"eslint-import-resolver-typescript\": \"4.4.5\",\n \"eslint-plugin-i18next\": \"6.1.5\",\n \"eslint-plugin-import-x\": \"4.16.2\",\n \"eslint-plugin-jsx-a11y\": \"6.10.2\",\n \"eslint-plugin-prettier\": \"5.5.5\",\n \"eslint-plugin-react\": \"7.37.5\",\n \"eslint-plugin-react-hooks\": \"7.1.1\",\n \"eslint-plugin-unused-imports\": \"4.4.1\",\n \"globals\": \"16.5.0\",\n \"husky\": \"9.1.7\",\n \"jsdom\": \"30.0.0\",\n \"lint-staged\": \"16.4.0\",\n \"msw\": \"2.15.0\",\n \"png2icons\": \"2.0.1\",\n \"postcss-prefix-selector\": \"2.1.1\",\n \"prettier\": \"3.8.3\",\n \"tailwindcss\": \"4.3.3\",\n \"typescript\": \"6.0.3\",\n \"vite-plugin-svgr\": \"5.2.0\",\n \"vitest\": \"4.1.10\"\n },\n \"packageManager\": \"npm@10.5.0\",\n \"volta\": {\n \"node\": \"22.12.0\"\n },\n \"msw\": {\n \"workerDirectory\": [\n \"public\"\n ]\n },\n \"overrides\": {\n \"@vercel/static-config\": {\n \"ajv\": \"8.20.0\"\n },\n \"dompurify\": \"3.4.12\",\n \"typed-rest-client\": {\n \"qs\": \"6.15.3\"\n }\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"bin\",\n \"build\",\n \"config\",\n \"scripts\",\n \"tools\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./browser\": {\n \"types\": \"./dist/components/browser/index.d.ts\",\n \"import\": \"./dist/components/browser/index.js\",\n \"require\": \"./dist/components/browser/index.cjs\"\n },\n \"./conversation\": {\n \"types\": \"./dist/components/conversation/index.d.ts\",\n \"import\": \"./dist/components/conversation/index.js\",\n \"require\": \"./dist/components/conversation/index.cjs\"\n },\n \"./files\": {\n \"types\": \"./dist/components/files/index.d.ts\",\n \"import\": \"./dist/components/files/index.js\",\n \"require\": \"./dist/components/files/index.cjs\"\n },\n \"./settings\": {\n \"types\": \"./dist/components/settings/index.d.ts\",\n \"import\": \"./dist/components/settings/index.js\",\n \"require\": \"./dist/components/settings/index.cjs\"\n },\n \"./sidebar\": {\n \"types\": \"./dist/components/sidebar/index.d.ts\",\n \"import\": \"./dist/components/sidebar/index.js\",\n \"require\": \"./dist/components/sidebar/index.cjs\"\n },\n \"./terminal\": {\n \"types\": \"./dist/components/terminal/index.d.ts\",\n \"import\": \"./dist/components/terminal/index.js\",\n \"require\": \"./dist/components/terminal/index.cjs\"\n },\n \"./i18n\": {\n \"types\": \"./dist/i18n/index.d.ts\",\n \"import\": \"./dist/i18n/index.js\",\n \"require\": \"./dist/i18n/index.cjs\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"peerDependencies\": {\n \"react\": \"19.2.8\",\n \"react-dom\": \"19.2.8\",\n \"react-router\": \"7.18.2\"\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"package.cjs","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@openhands/agent-canvas\",\n \"version\": \"1.12.0\",\n \"description\": \"Agent Canvas UI for OpenHands - run AI coding agents with a visual interface\",\n \"license\": \"MIT\",\n \"private\": false,\n \"type\": \"module\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/OpenHands/OpenHands\"\n },\n \"homepage\": \"https://github.com/OpenHands/OpenHands#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/OpenHands/OpenHands/issues\"\n },\n \"bin\": {\n \"agent-canvas\": \"bin/agent-canvas.mjs\"\n },\n \"engines\": {\n \"node\": \">=22.12.0\"\n },\n \"dependencies\": {\n \"@heroui/react\": \"2.8.10\",\n \"@microlink/react-json-view\": \"1.31.20\",\n \"@monaco-editor/react\": \"4.7.0\",\n \"@openhands/extensions\": \"0.16.0\",\n \"@openhands/typescript-client\": \"1.36.1\",\n \"@react-router/node\": \"7.18.2\",\n \"@react-router/serve\": \"7.18.2\",\n \"@tailwindcss/vite\": \"4.3.3\",\n \"@tanstack/react-query\": \"5.101.4\",\n \"@types/shell-quote\": \"1.7.5\",\n \"@uidotdev/usehooks\": \"2.4.1\",\n \"@xterm/addon-fit\": \"0.11.0\",\n \"@xterm/xterm\": \"6.0.0\",\n \"axios\": \"1.18.0\",\n \"class-variance-authority\": \"0.7.1\",\n \"clsx\": \"2.1.1\",\n \"downshift\": \"9.3.2\",\n \"framer-motion\": \"12.38.0\",\n \"httpxy\": \"0.5.3\",\n \"i18next\": \"26.3.6\",\n \"i18next-browser-languagedetector\": \"8.2.1\",\n \"i18next-http-backend\": \"4.0.0\",\n \"isbot\": \"5.1.39\",\n \"lucide-react\": \"1.25.0\",\n \"monaco-editor\": \"0.56.0\",\n \"posthog-js\": \"1.380.0\",\n \"react\": \"19.2.8\",\n \"react-dom\": \"19.2.8\",\n \"react-hot-toast\": \"2.6.0\",\n \"react-i18next\": \"17.0.11\",\n \"react-icons\": \"5.6.0\",\n \"react-markdown\": \"10.1.0\",\n \"react-router\": \"7.18.2\",\n \"react-syntax-highlighter\": \"16.1.1\",\n \"rehype-raw\": \"7.0.0\",\n \"rehype-sanitize\": \"6.0.0\",\n \"remark-breaks\": \"4.0.0\",\n \"remark-gfm\": \"4.0.1\",\n \"shell-quote\": \"1.9.0\",\n \"sirv\": \"3.0.2\",\n \"sirv-cli\": \"3.0.1\",\n \"socket.io-client\": \"4.8.3\",\n \"tailwind-merge\": \"3.6.0\",\n \"tailwind-scrollbar\": \"4.0.2\",\n \"unist-util-visit\": \"5.1.0\",\n \"uuid\": \"14.0.0\",\n \"vite\": \"8.0.16\",\n \"winston\": \"3.19.0\",\n \"winston-daily-rotate-file\": \"5.0.0\",\n \"zustand\": \"5.0.12\"\n },\n \"scripts\": {\n \"dev\": \"node --env-file-if-exists=.env scripts/dev-with-automation.mjs\",\n \"dev:static\": \"node --env-file-if-exists=.env scripts/dev-static.mjs\",\n \"dev:extra-backend\": \"node --env-file-if-exists=.env scripts/dev-extra-backend.mjs\",\n \"dev:minimal\": \"node --env-file-if-exists=.env scripts/dev-safe.mjs\",\n \"dev:frontend\": \"npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev\",\n \"dev:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev\",\n \"build\": \"npm run build:app\",\n \"build:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router build\",\n \"start\": \"npx sirv-cli build/ --single\",\n \"test\": \"npm run make-i18n && vitest run\",\n \"test:e2e\": \"playwright test --pass-with-no-tests\",\n \"test:e2e:live\": \"node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs\",\n \"test:e2e:mock-llm\": \"playwright test --config=playwright.mock-llm.config.ts\",\n \"test:e2e:mock-llm:docker\": \"playwright test --config=playwright.mock-llm-docker.config.ts\",\n \"test:coverage\": \"npm run make-i18n && vitest run --coverage\",\n \"test:mutation\": \"npm run make-i18n && stryker run\",\n \"test:mutation:diff\": \"npm run make-i18n && node scripts/stryker-diff.mjs\",\n \"test:mutation:incremental\": \"npm run make-i18n && stryker run --incremental\",\n \"dev_wsl\": \"VITE_WATCH_USE_POLLING=true vite\",\n \"preview\": \"vite preview\",\n \"make-i18n\": \"node scripts/make-i18n-translations.cjs\",\n \"prelint\": \"npm run make-i18n\",\n \"lint\": \"npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}\",\n \"lint:fix\": \"eslint src --fix && prettier --write src/**/*.{ts,tsx}\",\n \"prepare\": \"husky\",\n \"typecheck\": \"react-router typegen && tsc\",\n \"typecheck:staged\": \"react-router typegen && npx tsc --noEmit --skipLibCheck\",\n \"check-translation-completeness\": \"node scripts/check-translation-completeness.cjs\",\n \"build:app\": \"npm run make-i18n && react-router build\",\n \"build:lib\": \"npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true vite build && tsc -p tsconfig.lib.json\",\n \"build:docker\": \"node scripts/docker-build.mjs\",\n \"example:acp-docker:env\": \"node scripts/gen-acp-docker-env.mjs\",\n \"predesktop\": \"node scripts/brand-dev-electron.mjs\",\n \"desktop\": \"npm run build:app && electron electron\",\n \"build:desktop\": \"npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && electron-builder --config electron-builder.config.mjs --publish never\",\n \"build:desktop:universal\": \"npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && cross-env ELECTRON_ARCH=universal electron-builder --config electron-builder.config.mjs --publish never\",\n \"download-uv\": \"node scripts/download-uv.mjs\",\n \"download-node\": \"node scripts/download-node.mjs\",\n \"generate-icons\": \"node scripts/generate-icons.mjs\"\n },\n \"lint-staged\": {\n \"src/**/*.{ts,tsx,js}\": [\n \"eslint --fix\",\n \"prettier --write\"\n ],\n \"src/**/*.{ts,tsx}\": [\n \"node scripts/run-staged-typecheck.mjs\"\n ],\n \"src/**/*\": [\n \"npm run check-translation-completeness\"\n ]\n },\n \"devDependencies\": {\n \"@eslint/eslintrc\": \"3.3.1\",\n \"@eslint/js\": \"9.39.4\",\n \"@mswjs/socket.io-binding\": \"0.2.0\",\n \"@playwright/test\": \"1.62.0\",\n \"@react-router/dev\": \"7.18.2\",\n \"@stryker-mutator/core\": \"9.6.1\",\n \"@stryker-mutator/vitest-runner\": \"9.6.1\",\n \"@tailwindcss/typography\": \"0.5.20\",\n \"@tanstack/eslint-plugin-query\": \"5.101.4\",\n \"@testing-library/dom\": \"10.4.1\",\n \"@testing-library/jest-dom\": \"7.0.0\",\n \"@testing-library/react\": \"16.3.2\",\n \"@testing-library/user-event\": \"14.6.1\",\n \"@types/mdast\": \"4.0.4\",\n \"@types/node\": \"26.1.2\",\n \"@types/react\": \"19.2.17\",\n \"@types/react-dom\": \"19.2.3\",\n \"@types/react-syntax-highlighter\": \"15.5.13\",\n \"@typescript-eslint/eslint-plugin\": \"8.59.2\",\n \"@typescript-eslint/parser\": \"8.59.2\",\n \"@vercel/react-router\": \"1.3.0\",\n \"@vitest/coverage-v8\": \"4.1.10\",\n \"cross-env\": \"10.1.0\",\n \"electron\": \"42.3.3\",\n \"electron-builder\": \"26.15.3\",\n \"eslint\": \"9.39.4\",\n \"eslint-config-prettier\": \"10.1.8\",\n \"eslint-import-resolver-typescript\": \"4.4.5\",\n \"eslint-plugin-i18next\": \"6.1.5\",\n \"eslint-plugin-import-x\": \"4.16.2\",\n \"eslint-plugin-jsx-a11y\": \"6.10.2\",\n \"eslint-plugin-prettier\": \"5.5.5\",\n \"eslint-plugin-react\": \"7.37.5\",\n \"eslint-plugin-react-hooks\": \"7.1.1\",\n \"eslint-plugin-unused-imports\": \"4.4.1\",\n \"globals\": \"16.5.0\",\n \"husky\": \"9.1.7\",\n \"jsdom\": \"30.0.0\",\n \"lint-staged\": \"16.4.0\",\n \"msw\": \"2.15.0\",\n \"png2icons\": \"2.0.1\",\n \"postcss-prefix-selector\": \"2.1.1\",\n \"prettier\": \"3.8.3\",\n \"tailwindcss\": \"4.3.3\",\n \"typescript\": \"6.0.3\",\n \"vite-plugin-svgr\": \"5.2.0\",\n \"vitest\": \"4.1.10\"\n },\n \"packageManager\": \"npm@10.5.0\",\n \"volta\": {\n \"node\": \"22.12.0\"\n },\n \"msw\": {\n \"workerDirectory\": [\n \"public\"\n ]\n },\n \"overrides\": {\n \"@vercel/static-config\": {\n \"ajv\": \"8.20.0\"\n },\n \"dompurify\": \"3.4.12\",\n \"typed-rest-client\": {\n \"qs\": \"6.15.3\"\n }\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"bin\",\n \"build\",\n \"config\",\n \"scripts\",\n \"tools\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./browser\": {\n \"types\": \"./dist/components/browser/index.d.ts\",\n \"import\": \"./dist/components/browser/index.js\",\n \"require\": \"./dist/components/browser/index.cjs\"\n },\n \"./conversation\": {\n \"types\": \"./dist/components/conversation/index.d.ts\",\n \"import\": \"./dist/components/conversation/index.js\",\n \"require\": \"./dist/components/conversation/index.cjs\"\n },\n \"./files\": {\n \"types\": \"./dist/components/files/index.d.ts\",\n \"import\": \"./dist/components/files/index.js\",\n \"require\": \"./dist/components/files/index.cjs\"\n },\n \"./settings\": {\n \"types\": \"./dist/components/settings/index.d.ts\",\n \"import\": \"./dist/components/settings/index.js\",\n \"require\": \"./dist/components/settings/index.cjs\"\n },\n \"./sidebar\": {\n \"types\": \"./dist/components/sidebar/index.d.ts\",\n \"import\": \"./dist/components/sidebar/index.js\",\n \"require\": \"./dist/components/sidebar/index.cjs\"\n },\n \"./terminal\": {\n \"types\": \"./dist/components/terminal/index.d.ts\",\n \"import\": \"./dist/components/terminal/index.js\",\n \"require\": \"./dist/components/terminal/index.cjs\"\n },\n \"./i18n\": {\n \"types\": \"./dist/i18n/index.d.ts\",\n \"import\": \"./dist/i18n/index.js\",\n \"require\": \"./dist/i18n/index.cjs\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"peerDependencies\": {\n \"react\": \"19.2.8\",\n \"react-dom\": \"19.2.8\",\n \"react-router\": \"7.18.2\"\n }\n}\n"],"mappings":""}
package/dist/package.js CHANGED
@@ -1,6 +1,6 @@
1
1
  var e = {
2
2
  name: "@openhands/agent-canvas",
3
- version: "1.11.0",
3
+ version: "1.12.0",
4
4
  description: "Agent Canvas UI for OpenHands - run AI coding agents with a visual interface",
5
5
  license: "MIT",
6
6
  private: !1,
@@ -1 +1 @@
1
- {"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@openhands/agent-canvas\",\n \"version\": \"1.11.0\",\n \"description\": \"Agent Canvas UI for OpenHands - run AI coding agents with a visual interface\",\n \"license\": \"MIT\",\n \"private\": false,\n \"type\": \"module\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/OpenHands/OpenHands\"\n },\n \"homepage\": \"https://github.com/OpenHands/OpenHands#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/OpenHands/OpenHands/issues\"\n },\n \"bin\": {\n \"agent-canvas\": \"bin/agent-canvas.mjs\"\n },\n \"engines\": {\n \"node\": \">=22.12.0\"\n },\n \"dependencies\": {\n \"@heroui/react\": \"2.8.10\",\n \"@microlink/react-json-view\": \"1.31.20\",\n \"@monaco-editor/react\": \"4.7.0\",\n \"@openhands/extensions\": \"0.16.0\",\n \"@openhands/typescript-client\": \"1.36.1\",\n \"@react-router/node\": \"7.18.2\",\n \"@react-router/serve\": \"7.18.2\",\n \"@tailwindcss/vite\": \"4.3.3\",\n \"@tanstack/react-query\": \"5.101.4\",\n \"@types/shell-quote\": \"1.7.5\",\n \"@uidotdev/usehooks\": \"2.4.1\",\n \"@xterm/addon-fit\": \"0.11.0\",\n \"@xterm/xterm\": \"6.0.0\",\n \"axios\": \"1.18.0\",\n \"class-variance-authority\": \"0.7.1\",\n \"clsx\": \"2.1.1\",\n \"downshift\": \"9.3.2\",\n \"framer-motion\": \"12.38.0\",\n \"httpxy\": \"0.5.3\",\n \"i18next\": \"26.3.6\",\n \"i18next-browser-languagedetector\": \"8.2.1\",\n \"i18next-http-backend\": \"4.0.0\",\n \"isbot\": \"5.1.39\",\n \"lucide-react\": \"1.25.0\",\n \"monaco-editor\": \"0.56.0\",\n \"posthog-js\": \"1.380.0\",\n \"react\": \"19.2.8\",\n \"react-dom\": \"19.2.8\",\n \"react-hot-toast\": \"2.6.0\",\n \"react-i18next\": \"17.0.11\",\n \"react-icons\": \"5.6.0\",\n \"react-markdown\": \"10.1.0\",\n \"react-router\": \"7.18.2\",\n \"react-syntax-highlighter\": \"16.1.1\",\n \"rehype-raw\": \"7.0.0\",\n \"rehype-sanitize\": \"6.0.0\",\n \"remark-breaks\": \"4.0.0\",\n \"remark-gfm\": \"4.0.1\",\n \"shell-quote\": \"1.9.0\",\n \"sirv\": \"3.0.2\",\n \"sirv-cli\": \"3.0.1\",\n \"socket.io-client\": \"4.8.3\",\n \"tailwind-merge\": \"3.6.0\",\n \"tailwind-scrollbar\": \"4.0.2\",\n \"unist-util-visit\": \"5.1.0\",\n \"uuid\": \"14.0.0\",\n \"vite\": \"8.0.16\",\n \"winston\": \"3.19.0\",\n \"winston-daily-rotate-file\": \"5.0.0\",\n \"zustand\": \"5.0.12\"\n },\n \"scripts\": {\n \"dev\": \"node --env-file-if-exists=.env scripts/dev-with-automation.mjs\",\n \"dev:static\": \"node --env-file-if-exists=.env scripts/dev-static.mjs\",\n \"dev:extra-backend\": \"node --env-file-if-exists=.env scripts/dev-extra-backend.mjs\",\n \"dev:minimal\": \"node --env-file-if-exists=.env scripts/dev-safe.mjs\",\n \"dev:frontend\": \"npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev\",\n \"dev:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev\",\n \"build\": \"npm run build:app\",\n \"build:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router build\",\n \"start\": \"npx sirv-cli build/ --single\",\n \"test\": \"npm run make-i18n && vitest run\",\n \"test:e2e\": \"playwright test --pass-with-no-tests\",\n \"test:e2e:live\": \"node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs\",\n \"test:e2e:mock-llm\": \"playwright test --config=playwright.mock-llm.config.ts\",\n \"test:e2e:mock-llm:docker\": \"playwright test --config=playwright.mock-llm-docker.config.ts\",\n \"test:coverage\": \"npm run make-i18n && vitest run --coverage\",\n \"test:mutation\": \"npm run make-i18n && stryker run\",\n \"test:mutation:diff\": \"npm run make-i18n && node scripts/stryker-diff.mjs\",\n \"test:mutation:incremental\": \"npm run make-i18n && stryker run --incremental\",\n \"dev_wsl\": \"VITE_WATCH_USE_POLLING=true vite\",\n \"preview\": \"vite preview\",\n \"make-i18n\": \"node scripts/make-i18n-translations.cjs\",\n \"prelint\": \"npm run make-i18n\",\n \"lint\": \"npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}\",\n \"lint:fix\": \"eslint src --fix && prettier --write src/**/*.{ts,tsx}\",\n \"prepare\": \"husky\",\n \"typecheck\": \"react-router typegen && tsc\",\n \"typecheck:staged\": \"react-router typegen && npx tsc --noEmit --skipLibCheck\",\n \"check-translation-completeness\": \"node scripts/check-translation-completeness.cjs\",\n \"build:app\": \"npm run make-i18n && react-router build\",\n \"build:lib\": \"npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true vite build && tsc -p tsconfig.lib.json\",\n \"build:docker\": \"node scripts/docker-build.mjs\",\n \"example:acp-docker:env\": \"node scripts/gen-acp-docker-env.mjs\",\n \"predesktop\": \"node scripts/brand-dev-electron.mjs\",\n \"desktop\": \"npm run build:app && electron electron\",\n \"build:desktop\": \"npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && electron-builder --config electron-builder.config.mjs --publish never\",\n \"build:desktop:universal\": \"npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && cross-env ELECTRON_ARCH=universal electron-builder --config electron-builder.config.mjs --publish never\",\n \"download-uv\": \"node scripts/download-uv.mjs\",\n \"download-node\": \"node scripts/download-node.mjs\",\n \"generate-icons\": \"node scripts/generate-icons.mjs\"\n },\n \"lint-staged\": {\n \"src/**/*.{ts,tsx,js}\": [\n \"eslint --fix\",\n \"prettier --write\"\n ],\n \"src/**/*.{ts,tsx}\": [\n \"node scripts/run-staged-typecheck.mjs\"\n ],\n \"src/**/*\": [\n \"npm run check-translation-completeness\"\n ]\n },\n \"devDependencies\": {\n \"@eslint/eslintrc\": \"3.3.1\",\n \"@eslint/js\": \"9.39.4\",\n \"@mswjs/socket.io-binding\": \"0.2.0\",\n \"@playwright/test\": \"1.62.0\",\n \"@react-router/dev\": \"7.18.2\",\n \"@stryker-mutator/core\": \"9.6.1\",\n \"@stryker-mutator/vitest-runner\": \"9.6.1\",\n \"@tailwindcss/typography\": \"0.5.20\",\n \"@tanstack/eslint-plugin-query\": \"5.101.4\",\n \"@testing-library/dom\": \"10.4.1\",\n \"@testing-library/jest-dom\": \"7.0.0\",\n \"@testing-library/react\": \"16.3.2\",\n \"@testing-library/user-event\": \"14.6.1\",\n \"@types/mdast\": \"4.0.4\",\n \"@types/node\": \"26.1.2\",\n \"@types/react\": \"19.2.17\",\n \"@types/react-dom\": \"19.2.3\",\n \"@types/react-syntax-highlighter\": \"15.5.13\",\n \"@typescript-eslint/eslint-plugin\": \"8.59.2\",\n \"@typescript-eslint/parser\": \"8.59.2\",\n \"@vercel/react-router\": \"1.3.0\",\n \"@vitest/coverage-v8\": \"4.1.10\",\n \"cross-env\": \"10.1.0\",\n \"electron\": \"42.3.3\",\n \"electron-builder\": \"26.15.3\",\n \"eslint\": \"9.39.4\",\n \"eslint-config-prettier\": \"10.1.8\",\n \"eslint-import-resolver-typescript\": \"4.4.5\",\n \"eslint-plugin-i18next\": \"6.1.5\",\n \"eslint-plugin-import-x\": \"4.16.2\",\n \"eslint-plugin-jsx-a11y\": \"6.10.2\",\n \"eslint-plugin-prettier\": \"5.5.5\",\n \"eslint-plugin-react\": \"7.37.5\",\n \"eslint-plugin-react-hooks\": \"7.1.1\",\n \"eslint-plugin-unused-imports\": \"4.4.1\",\n \"globals\": \"16.5.0\",\n \"husky\": \"9.1.7\",\n \"jsdom\": \"30.0.0\",\n \"lint-staged\": \"16.4.0\",\n \"msw\": \"2.15.0\",\n \"png2icons\": \"2.0.1\",\n \"postcss-prefix-selector\": \"2.1.1\",\n \"prettier\": \"3.8.3\",\n \"tailwindcss\": \"4.3.3\",\n \"typescript\": \"6.0.3\",\n \"vite-plugin-svgr\": \"5.2.0\",\n \"vitest\": \"4.1.10\"\n },\n \"packageManager\": \"npm@10.5.0\",\n \"volta\": {\n \"node\": \"22.12.0\"\n },\n \"msw\": {\n \"workerDirectory\": [\n \"public\"\n ]\n },\n \"overrides\": {\n \"@vercel/static-config\": {\n \"ajv\": \"8.20.0\"\n },\n \"dompurify\": \"3.4.12\",\n \"typed-rest-client\": {\n \"qs\": \"6.15.3\"\n }\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"bin\",\n \"build\",\n \"config\",\n \"scripts\",\n \"tools\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./browser\": {\n \"types\": \"./dist/components/browser/index.d.ts\",\n \"import\": \"./dist/components/browser/index.js\",\n \"require\": \"./dist/components/browser/index.cjs\"\n },\n \"./conversation\": {\n \"types\": \"./dist/components/conversation/index.d.ts\",\n \"import\": \"./dist/components/conversation/index.js\",\n \"require\": \"./dist/components/conversation/index.cjs\"\n },\n \"./files\": {\n \"types\": \"./dist/components/files/index.d.ts\",\n \"import\": \"./dist/components/files/index.js\",\n \"require\": \"./dist/components/files/index.cjs\"\n },\n \"./settings\": {\n \"types\": \"./dist/components/settings/index.d.ts\",\n \"import\": \"./dist/components/settings/index.js\",\n \"require\": \"./dist/components/settings/index.cjs\"\n },\n \"./sidebar\": {\n \"types\": \"./dist/components/sidebar/index.d.ts\",\n \"import\": \"./dist/components/sidebar/index.js\",\n \"require\": \"./dist/components/sidebar/index.cjs\"\n },\n \"./terminal\": {\n \"types\": \"./dist/components/terminal/index.d.ts\",\n \"import\": \"./dist/components/terminal/index.js\",\n \"require\": \"./dist/components/terminal/index.cjs\"\n },\n \"./i18n\": {\n \"types\": \"./dist/i18n/index.d.ts\",\n \"import\": \"./dist/i18n/index.js\",\n \"require\": \"./dist/i18n/index.cjs\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"peerDependencies\": {\n \"react\": \"19.2.8\",\n \"react-dom\": \"19.2.8\",\n \"react-router\": \"7.18.2\"\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@openhands/agent-canvas\",\n \"version\": \"1.12.0\",\n \"description\": \"Agent Canvas UI for OpenHands - run AI coding agents with a visual interface\",\n \"license\": \"MIT\",\n \"private\": false,\n \"type\": \"module\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/OpenHands/OpenHands\"\n },\n \"homepage\": \"https://github.com/OpenHands/OpenHands#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/OpenHands/OpenHands/issues\"\n },\n \"bin\": {\n \"agent-canvas\": \"bin/agent-canvas.mjs\"\n },\n \"engines\": {\n \"node\": \">=22.12.0\"\n },\n \"dependencies\": {\n \"@heroui/react\": \"2.8.10\",\n \"@microlink/react-json-view\": \"1.31.20\",\n \"@monaco-editor/react\": \"4.7.0\",\n \"@openhands/extensions\": \"0.16.0\",\n \"@openhands/typescript-client\": \"1.36.1\",\n \"@react-router/node\": \"7.18.2\",\n \"@react-router/serve\": \"7.18.2\",\n \"@tailwindcss/vite\": \"4.3.3\",\n \"@tanstack/react-query\": \"5.101.4\",\n \"@types/shell-quote\": \"1.7.5\",\n \"@uidotdev/usehooks\": \"2.4.1\",\n \"@xterm/addon-fit\": \"0.11.0\",\n \"@xterm/xterm\": \"6.0.0\",\n \"axios\": \"1.18.0\",\n \"class-variance-authority\": \"0.7.1\",\n \"clsx\": \"2.1.1\",\n \"downshift\": \"9.3.2\",\n \"framer-motion\": \"12.38.0\",\n \"httpxy\": \"0.5.3\",\n \"i18next\": \"26.3.6\",\n \"i18next-browser-languagedetector\": \"8.2.1\",\n \"i18next-http-backend\": \"4.0.0\",\n \"isbot\": \"5.1.39\",\n \"lucide-react\": \"1.25.0\",\n \"monaco-editor\": \"0.56.0\",\n \"posthog-js\": \"1.380.0\",\n \"react\": \"19.2.8\",\n \"react-dom\": \"19.2.8\",\n \"react-hot-toast\": \"2.6.0\",\n \"react-i18next\": \"17.0.11\",\n \"react-icons\": \"5.6.0\",\n \"react-markdown\": \"10.1.0\",\n \"react-router\": \"7.18.2\",\n \"react-syntax-highlighter\": \"16.1.1\",\n \"rehype-raw\": \"7.0.0\",\n \"rehype-sanitize\": \"6.0.0\",\n \"remark-breaks\": \"4.0.0\",\n \"remark-gfm\": \"4.0.1\",\n \"shell-quote\": \"1.9.0\",\n \"sirv\": \"3.0.2\",\n \"sirv-cli\": \"3.0.1\",\n \"socket.io-client\": \"4.8.3\",\n \"tailwind-merge\": \"3.6.0\",\n \"tailwind-scrollbar\": \"4.0.2\",\n \"unist-util-visit\": \"5.1.0\",\n \"uuid\": \"14.0.0\",\n \"vite\": \"8.0.16\",\n \"winston\": \"3.19.0\",\n \"winston-daily-rotate-file\": \"5.0.0\",\n \"zustand\": \"5.0.12\"\n },\n \"scripts\": {\n \"dev\": \"node --env-file-if-exists=.env scripts/dev-with-automation.mjs\",\n \"dev:static\": \"node --env-file-if-exists=.env scripts/dev-static.mjs\",\n \"dev:extra-backend\": \"node --env-file-if-exists=.env scripts/dev-extra-backend.mjs\",\n \"dev:minimal\": \"node --env-file-if-exists=.env scripts/dev-safe.mjs\",\n \"dev:frontend\": \"npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev\",\n \"dev:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev\",\n \"build\": \"npm run build:app\",\n \"build:mock\": \"npm run make-i18n && cross-env VITE_MOCK_API=true react-router build\",\n \"start\": \"npx sirv-cli build/ --single\",\n \"test\": \"npm run make-i18n && vitest run\",\n \"test:e2e\": \"playwright test --pass-with-no-tests\",\n \"test:e2e:live\": \"node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs\",\n \"test:e2e:mock-llm\": \"playwright test --config=playwright.mock-llm.config.ts\",\n \"test:e2e:mock-llm:docker\": \"playwright test --config=playwright.mock-llm-docker.config.ts\",\n \"test:coverage\": \"npm run make-i18n && vitest run --coverage\",\n \"test:mutation\": \"npm run make-i18n && stryker run\",\n \"test:mutation:diff\": \"npm run make-i18n && node scripts/stryker-diff.mjs\",\n \"test:mutation:incremental\": \"npm run make-i18n && stryker run --incremental\",\n \"dev_wsl\": \"VITE_WATCH_USE_POLLING=true vite\",\n \"preview\": \"vite preview\",\n \"make-i18n\": \"node scripts/make-i18n-translations.cjs\",\n \"prelint\": \"npm run make-i18n\",\n \"lint\": \"npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}\",\n \"lint:fix\": \"eslint src --fix && prettier --write src/**/*.{ts,tsx}\",\n \"prepare\": \"husky\",\n \"typecheck\": \"react-router typegen && tsc\",\n \"typecheck:staged\": \"react-router typegen && npx tsc --noEmit --skipLibCheck\",\n \"check-translation-completeness\": \"node scripts/check-translation-completeness.cjs\",\n \"build:app\": \"npm run make-i18n && react-router build\",\n \"build:lib\": \"npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true vite build && tsc -p tsconfig.lib.json\",\n \"build:docker\": \"node scripts/docker-build.mjs\",\n \"example:acp-docker:env\": \"node scripts/gen-acp-docker-env.mjs\",\n \"predesktop\": \"node scripts/brand-dev-electron.mjs\",\n \"desktop\": \"npm run build:app && electron electron\",\n \"build:desktop\": \"npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && electron-builder --config electron-builder.config.mjs --publish never\",\n \"build:desktop:universal\": \"npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && cross-env ELECTRON_ARCH=universal electron-builder --config electron-builder.config.mjs --publish never\",\n \"download-uv\": \"node scripts/download-uv.mjs\",\n \"download-node\": \"node scripts/download-node.mjs\",\n \"generate-icons\": \"node scripts/generate-icons.mjs\"\n },\n \"lint-staged\": {\n \"src/**/*.{ts,tsx,js}\": [\n \"eslint --fix\",\n \"prettier --write\"\n ],\n \"src/**/*.{ts,tsx}\": [\n \"node scripts/run-staged-typecheck.mjs\"\n ],\n \"src/**/*\": [\n \"npm run check-translation-completeness\"\n ]\n },\n \"devDependencies\": {\n \"@eslint/eslintrc\": \"3.3.1\",\n \"@eslint/js\": \"9.39.4\",\n \"@mswjs/socket.io-binding\": \"0.2.0\",\n \"@playwright/test\": \"1.62.0\",\n \"@react-router/dev\": \"7.18.2\",\n \"@stryker-mutator/core\": \"9.6.1\",\n \"@stryker-mutator/vitest-runner\": \"9.6.1\",\n \"@tailwindcss/typography\": \"0.5.20\",\n \"@tanstack/eslint-plugin-query\": \"5.101.4\",\n \"@testing-library/dom\": \"10.4.1\",\n \"@testing-library/jest-dom\": \"7.0.0\",\n \"@testing-library/react\": \"16.3.2\",\n \"@testing-library/user-event\": \"14.6.1\",\n \"@types/mdast\": \"4.0.4\",\n \"@types/node\": \"26.1.2\",\n \"@types/react\": \"19.2.17\",\n \"@types/react-dom\": \"19.2.3\",\n \"@types/react-syntax-highlighter\": \"15.5.13\",\n \"@typescript-eslint/eslint-plugin\": \"8.59.2\",\n \"@typescript-eslint/parser\": \"8.59.2\",\n \"@vercel/react-router\": \"1.3.0\",\n \"@vitest/coverage-v8\": \"4.1.10\",\n \"cross-env\": \"10.1.0\",\n \"electron\": \"42.3.3\",\n \"electron-builder\": \"26.15.3\",\n \"eslint\": \"9.39.4\",\n \"eslint-config-prettier\": \"10.1.8\",\n \"eslint-import-resolver-typescript\": \"4.4.5\",\n \"eslint-plugin-i18next\": \"6.1.5\",\n \"eslint-plugin-import-x\": \"4.16.2\",\n \"eslint-plugin-jsx-a11y\": \"6.10.2\",\n \"eslint-plugin-prettier\": \"5.5.5\",\n \"eslint-plugin-react\": \"7.37.5\",\n \"eslint-plugin-react-hooks\": \"7.1.1\",\n \"eslint-plugin-unused-imports\": \"4.4.1\",\n \"globals\": \"16.5.0\",\n \"husky\": \"9.1.7\",\n \"jsdom\": \"30.0.0\",\n \"lint-staged\": \"16.4.0\",\n \"msw\": \"2.15.0\",\n \"png2icons\": \"2.0.1\",\n \"postcss-prefix-selector\": \"2.1.1\",\n \"prettier\": \"3.8.3\",\n \"tailwindcss\": \"4.3.3\",\n \"typescript\": \"6.0.3\",\n \"vite-plugin-svgr\": \"5.2.0\",\n \"vitest\": \"4.1.10\"\n },\n \"packageManager\": \"npm@10.5.0\",\n \"volta\": {\n \"node\": \"22.12.0\"\n },\n \"msw\": {\n \"workerDirectory\": [\n \"public\"\n ]\n },\n \"overrides\": {\n \"@vercel/static-config\": {\n \"ajv\": \"8.20.0\"\n },\n \"dompurify\": \"3.4.12\",\n \"typed-rest-client\": {\n \"qs\": \"6.15.3\"\n }\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"bin\",\n \"build\",\n \"config\",\n \"scripts\",\n \"tools\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./browser\": {\n \"types\": \"./dist/components/browser/index.d.ts\",\n \"import\": \"./dist/components/browser/index.js\",\n \"require\": \"./dist/components/browser/index.cjs\"\n },\n \"./conversation\": {\n \"types\": \"./dist/components/conversation/index.d.ts\",\n \"import\": \"./dist/components/conversation/index.js\",\n \"require\": \"./dist/components/conversation/index.cjs\"\n },\n \"./files\": {\n \"types\": \"./dist/components/files/index.d.ts\",\n \"import\": \"./dist/components/files/index.js\",\n \"require\": \"./dist/components/files/index.cjs\"\n },\n \"./settings\": {\n \"types\": \"./dist/components/settings/index.d.ts\",\n \"import\": \"./dist/components/settings/index.js\",\n \"require\": \"./dist/components/settings/index.cjs\"\n },\n \"./sidebar\": {\n \"types\": \"./dist/components/sidebar/index.d.ts\",\n \"import\": \"./dist/components/sidebar/index.js\",\n \"require\": \"./dist/components/sidebar/index.cjs\"\n },\n \"./terminal\": {\n \"types\": \"./dist/components/terminal/index.d.ts\",\n \"import\": \"./dist/components/terminal/index.js\",\n \"require\": \"./dist/components/terminal/index.cjs\"\n },\n \"./i18n\": {\n \"types\": \"./dist/i18n/index.d.ts\",\n \"import\": \"./dist/i18n/index.js\",\n \"require\": \"./dist/i18n/index.cjs\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"peerDependencies\": {\n \"react\": \"19.2.8\",\n \"react-dom\": \"19.2.8\",\n \"react-router\": \"7.18.2\"\n }\n}\n"],"mappings":""}
@@ -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("../i18n/index.cjs"),i=require("../utils/retrieve-axios-error-message.cjs"),a=require("../utils/custom-toast-handlers.cjs"),o=require("../services/telemetry.cjs"),s=require("../contexts/active-backend-context.cjs"),c=require("../services/settings.cjs"),l=require("../hooks/query/use-llm-profiles.cjs"),u=require("../hooks/query/use-settings.cjs"),d=require("../components/shared/navigation-link.cjs"),f=require("../components/features/settings/brand-button.cjs"),p=require("../hooks/mutation/use-save-settings.cjs"),m=require("../components/features/settings/settings-switch.cjs"),h=require("../components/features/settings/settings-input.cjs"),g=require("../components/features/settings/settings-dropdown-input.cjs"),_=require("../components/features/settings/app-settings/language-input.cjs"),v=require("../components/features/settings/app-settings/theme-input.cjs"),y=require("../components/features/settings/app-settings/app-settings-inputs-skeleton.cjs");let b=require("react");b=e.__toESM(b,1);let x=require("react/jsx-runtime");var S=`__automatic__`;function C(){let{t:e}=t.useTranslation(`openhands`),{mutate:C,isPending:w}=p.useSaveSettings(),{data:T,isLoading:E}=u.useSettings(),D=s.useActiveBackend().backend.kind===`cloud`,{data:O,isLoading:k}=l.useLlmProfiles(),[A,j]=b.default.useState(!1),[M,N]=b.default.useState(!1),[P,F]=b.default.useState(!1),[I,L]=b.default.useState(!1),[R,z]=b.default.useState(!1),[B,V]=b.default.useState(void 0),H=b.default.useMemo(()=>{let e=T?.title_llm_profile??null;return!e||!O||O.profiles.some(t=>t.name===e)?e:null},[O,T?.title_llm_profile]),U=B===void 0?H:B,W=b.default.useMemo(()=>[{key:S,label:e(n.I18nKey.SETTINGS$TITLE_GENERATION_AUTOMATIC)},...O?.profiles.map(t=>({key:t.name,label:t.model?e(n.I18nKey.SETTINGS$TITLE_GENERATION_PROFILE_OPTION,{name:t.name,model:t.model}):t.name}))??[]],[O?.profiles,e]),G=t=>{let s=t.get(`language-input`)?.toString(),l=r.AvailableLanguages.find(({label:e})=>e===s)?.value||c.DEFAULT_SETTINGS.language,u=D?!0:t.get(`enable-analytics-switch`)?.toString()===`on`,d=t.get(`enable-sound-notifications-switch`)?.toString()===`on`,f=t.get(`git-user-name-input`)?.toString()||c.DEFAULT_SETTINGS.git_user_name,p=t.get(`git-user-email-input`)?.toString()||c.DEFAULT_SETTINGS.git_user_email;C({language:l,...!D&&{user_consents_to_analytics:u},enable_sound_notifications:d,git_user_name:f,git_user_email:p,title_llm_profile:U},{onSuccess:()=>{o.setTelemetryConsent(u?`granted`:`denied`),a.displaySuccessToast(e(n.I18nKey.SETTINGS$SAVED))},onError:t=>{a.displayErrorToast(i.retrieveAxiosErrorMessage(t)||e(n.I18nKey.ERROR$GENERIC))},onSettled:()=>{j(!1),N(!1),F(!1),L(!1),z(!1),V(void 0)}})},K=e=>{let t=r.AvailableLanguages.find(({label:t})=>t===e)?.label,n=r.AvailableLanguages.find(({value:e})=>e===T?.language)?.label;j(t!==n)},q=e=>{N(e!==(T?.user_consents_to_analytics??!0))},J=e=>{F(e!==!!T?.enable_sound_notifications)},Y=e=>{let t=T?.git_user_name;L(e!==t)},X=e=>{let t=T?.git_user_email;z(e!==t)},Z=!A&&!M&&!P&&U===H&&!I&&!R,Q=!T||E||k||w;return(0,x.jsxs)(`form`,{"data-testid":`app-settings-screen`,action:G,className:`flex flex-col gap-6`,children:[Q&&(0,x.jsx)(y.AppSettingsInputsSkeleton,{}),!Q&&(0,x.jsxs)(`div`,{className:`flex flex-col gap-6`,children:[(0,x.jsx)(_.LanguageInput,{name:`language-input`,defaultKey:T.language,onChange:K}),(0,x.jsx)(v.ThemeInput,{}),(0,x.jsx)(m.SettingsSwitch,{testId:`enable-analytics-switch`,name:D?void 0:`enable-analytics-switch`,defaultIsToggled:D?!0:T.user_consents_to_analytics??!0,isToggled:D?!0:void 0,isDisabled:D,onToggle:D?void 0:q,children:e(n.I18nKey.ANALYTICS$SEND_ANONYMOUS_DATA)}),(0,x.jsx)(m.SettingsSwitch,{testId:`enable-sound-notifications-switch`,name:`enable-sound-notifications-switch`,defaultIsToggled:!!T.enable_sound_notifications,onToggle:J,children:e(n.I18nKey.SETTINGS$SOUND_NOTIFICATIONS)}),(0,x.jsxs)(`div`,{className:`border-t border-[var(--oh-border)] pt-6 mt-2`,children:[(0,x.jsx)(`h3`,{className:`text-lg font-medium mb-2`,children:e(n.I18nKey.SETTINGS$CONVERSATION_TITLES)}),(0,x.jsx)(`p`,{className:`mb-4 text-sm leading-5 text-tertiary-light`,children:e(n.I18nKey.SETTINGS$TITLE_GENERATION_DESCRIPTION)}),(0,x.jsx)(g.SettingsDropdownInput,{testId:`title-llm-profile-input`,name:`title-llm-profile-input`,label:e(n.I18nKey.SETTINGS$TITLE_GENERATION_MODEL),items:W,selectedKey:U??S,onSelectionChange:e=>{let t=e?.toString();V(!t||t===S?null:t)}}),(0,x.jsx)(d.NavigationLink,{to:`/settings/llm`,className:`mt-3 inline-block text-sm text-primary hover:underline`,children:e(n.I18nKey.SETTINGS$MANAGE_LLM_PROFILES)})]}),(0,x.jsxs)(`div`,{className:`border-t border-[var(--oh-border)] pt-6 mt-2`,children:[(0,x.jsx)(`h3`,{className:`text-lg font-medium mb-2`,children:e(n.I18nKey.SETTINGS$GIT_SETTINGS)}),(0,x.jsx)(`p`,{className:`mb-4 text-sm leading-5 text-tertiary-light`,children:e(n.I18nKey.SETTINGS$GIT_SETTINGS_DESCRIPTION)}),(0,x.jsxs)(`div`,{className:`flex flex-col gap-6`,children:[(0,x.jsx)(h.SettingsInput,{testId:`git-user-name-input`,name:`git-user-name-input`,type:`text`,label:e(n.I18nKey.SETTINGS$GIT_USERNAME),defaultValue:T.git_user_name||``,onChange:Y,placeholder:e(n.I18nKey.SETTINGS$GIT_USERNAME_PLACEHOLDER),className:`w-full min-w-0`}),(0,x.jsx)(h.SettingsInput,{testId:`git-user-email-input`,name:`git-user-email-input`,type:`email`,label:e(n.I18nKey.SETTINGS$GIT_EMAIL),defaultValue:T.git_user_email||``,onChange:X,placeholder:e(n.I18nKey.SETTINGS$GIT_EMAIL_PLACEHOLDER),className:`w-full min-w-0`})]}),(0,x.jsx)(`div`,{className:`flex justify-start pt-4`,children:(0,x.jsxs)(f.BrandButton,{testId:`submit-button`,variant:`primary`,type:`submit`,isDisabled:w||Z,children:[!w&&e(n.I18nKey.SETTINGS$SAVE_CHANGES),w&&e(n.I18nKey.SETTINGS$SAVING)]})})]})]})]})}exports.default=C;
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("../i18n/index.cjs"),i=require("../utils/retrieve-axios-error-message.cjs"),a=require("../utils/custom-toast-handlers.cjs"),o=require("../services/telemetry.cjs"),s=require("../contexts/active-backend-context.cjs"),c=require("../services/settings.cjs"),l=require("../utils/format-model-name.cjs"),u=require("../hooks/query/use-llm-profiles.cjs"),d=require("../hooks/query/use-settings.cjs"),f=require("../components/shared/navigation-link.cjs"),p=require("../components/features/settings/brand-button.cjs"),m=require("../hooks/mutation/use-save-settings.cjs"),h=require("../components/features/settings/settings-switch.cjs"),g=require("../components/features/settings/settings-input.cjs"),_=require("../components/features/settings/settings-dropdown-input.cjs"),v=require("../components/features/settings/app-settings/language-input.cjs"),y=require("../components/features/settings/app-settings/theme-input.cjs"),b=require("../components/features/settings/app-settings/app-settings-inputs-skeleton.cjs");let x=require("react");x=e.__toESM(x,1);let S=require("react/jsx-runtime");var C=`__automatic__`;function w(){let{t:e}=t.useTranslation(`openhands`),{mutate:w,isPending:T}=m.useSaveSettings(),{data:E,isLoading:D}=d.useSettings(),O=s.useActiveBackend().backend.kind===`cloud`,{data:k,isLoading:A}=u.useLlmProfiles(),[j,M]=x.default.useState(!1),[N,P]=x.default.useState(!1),[F,I]=x.default.useState(!1),[L,R]=x.default.useState(!1),[z,B]=x.default.useState(!1),[V,H]=x.default.useState(void 0),U=x.default.useMemo(()=>{let e=E?.title_llm_profile??null;return!e||!k||k.profiles.some(t=>t.name===e)?e:null},[k,E?.title_llm_profile]),W=V===void 0?U:V,G=x.default.useMemo(()=>[{key:C,label:e(n.I18nKey.SETTINGS$TITLE_GENERATION_AUTOMATIC)},...k?.profiles.map(t=>({key:t.name,label:t.model?e(n.I18nKey.SETTINGS$TITLE_GENERATION_PROFILE_OPTION,{name:t.name,model:l.formatModelNameForDisplay(t.model)??t.model}):t.name}))??[]],[k?.profiles,e]),K=t=>{let s=t.get(`language-input`)?.toString(),l=r.AvailableLanguages.find(({label:e})=>e===s)?.value||c.DEFAULT_SETTINGS.language,u=O?!0:t.get(`enable-analytics-switch`)?.toString()===`on`,d=t.get(`enable-sound-notifications-switch`)?.toString()===`on`,f=t.get(`git-user-name-input`)?.toString()||c.DEFAULT_SETTINGS.git_user_name,p=t.get(`git-user-email-input`)?.toString()||c.DEFAULT_SETTINGS.git_user_email;w({language:l,...!O&&{user_consents_to_analytics:u},enable_sound_notifications:d,git_user_name:f,git_user_email:p,title_llm_profile:W},{onSuccess:()=>{o.setTelemetryConsent(u?`granted`:`denied`),a.displaySuccessToast(e(n.I18nKey.SETTINGS$SAVED))},onError:t=>{a.displayErrorToast(i.retrieveAxiosErrorMessage(t)||e(n.I18nKey.ERROR$GENERIC))},onSettled:()=>{M(!1),P(!1),I(!1),R(!1),B(!1),H(void 0)}})},q=e=>{let t=r.AvailableLanguages.find(({label:t})=>t===e)?.label,n=r.AvailableLanguages.find(({value:e})=>e===E?.language)?.label;M(t!==n)},J=e=>{P(e!==(E?.user_consents_to_analytics??!0))},Y=e=>{I(e!==!!E?.enable_sound_notifications)},X=e=>{let t=E?.git_user_name;R(e!==t)},Z=e=>{let t=E?.git_user_email;B(e!==t)},Q=!j&&!N&&!F&&W===U&&!L&&!z,$=!E||D||A||T;return(0,S.jsxs)(`form`,{"data-testid":`app-settings-screen`,action:K,className:`flex flex-col gap-6`,children:[$&&(0,S.jsx)(b.AppSettingsInputsSkeleton,{}),!$&&(0,S.jsxs)(`div`,{className:`flex flex-col gap-6`,children:[(0,S.jsx)(v.LanguageInput,{name:`language-input`,defaultKey:E.language,onChange:q}),(0,S.jsx)(y.ThemeInput,{}),(0,S.jsx)(h.SettingsSwitch,{testId:`enable-analytics-switch`,name:O?void 0:`enable-analytics-switch`,defaultIsToggled:O?!0:E.user_consents_to_analytics??!0,isToggled:O?!0:void 0,isDisabled:O,onToggle:O?void 0:J,children:e(n.I18nKey.ANALYTICS$SEND_ANONYMOUS_DATA)}),(0,S.jsx)(h.SettingsSwitch,{testId:`enable-sound-notifications-switch`,name:`enable-sound-notifications-switch`,defaultIsToggled:!!E.enable_sound_notifications,onToggle:Y,children:e(n.I18nKey.SETTINGS$SOUND_NOTIFICATIONS)}),(0,S.jsxs)(`div`,{className:`border-t border-[var(--oh-border)] pt-6 mt-2`,children:[(0,S.jsx)(`h3`,{className:`text-lg font-medium mb-2`,children:e(n.I18nKey.SETTINGS$CONVERSATION_TITLES)}),(0,S.jsx)(`p`,{className:`mb-4 text-sm leading-5 text-tertiary-light`,children:e(n.I18nKey.SETTINGS$TITLE_GENERATION_DESCRIPTION)}),(0,S.jsx)(_.SettingsDropdownInput,{testId:`title-llm-profile-input`,name:`title-llm-profile-input`,label:e(n.I18nKey.SETTINGS$TITLE_GENERATION_MODEL),items:G,selectedKey:W??C,onSelectionChange:e=>{let t=e?.toString();H(!t||t===C?null:t)}}),(0,S.jsx)(f.NavigationLink,{to:`/settings/llm`,className:`mt-3 inline-block text-sm text-primary hover:underline`,children:e(n.I18nKey.SETTINGS$MANAGE_LLM_PROFILES)})]}),(0,S.jsxs)(`div`,{className:`border-t border-[var(--oh-border)] pt-6 mt-2`,children:[(0,S.jsx)(`h3`,{className:`text-lg font-medium mb-2`,children:e(n.I18nKey.SETTINGS$GIT_SETTINGS)}),(0,S.jsx)(`p`,{className:`mb-4 text-sm leading-5 text-tertiary-light`,children:e(n.I18nKey.SETTINGS$GIT_SETTINGS_DESCRIPTION)}),(0,S.jsxs)(`div`,{className:`flex flex-col gap-6`,children:[(0,S.jsx)(g.SettingsInput,{testId:`git-user-name-input`,name:`git-user-name-input`,type:`text`,label:e(n.I18nKey.SETTINGS$GIT_USERNAME),defaultValue:E.git_user_name||``,onChange:X,placeholder:e(n.I18nKey.SETTINGS$GIT_USERNAME_PLACEHOLDER),className:`w-full min-w-0`}),(0,S.jsx)(g.SettingsInput,{testId:`git-user-email-input`,name:`git-user-email-input`,type:`email`,label:e(n.I18nKey.SETTINGS$GIT_EMAIL),defaultValue:E.git_user_email||``,onChange:Z,placeholder:e(n.I18nKey.SETTINGS$GIT_EMAIL_PLACEHOLDER),className:`w-full min-w-0`})]}),(0,S.jsx)(`div`,{className:`flex justify-start pt-4`,children:(0,S.jsxs)(p.BrandButton,{testId:`submit-button`,variant:`primary`,type:`submit`,isDisabled:T||Q,children:[!T&&e(n.I18nKey.SETTINGS$SAVE_CHANGES),T&&e(n.I18nKey.SETTINGS$SAVING)]})})]})]})]})}exports.default=w;
2
2
  //# sourceMappingURL=app-settings.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-settings.cjs","names":[],"sources":["../../src/routes/app-settings.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useSaveSettings } from \"#/hooks/mutation/use-save-settings\";\nimport { useSettings } from \"#/hooks/query/use-settings\";\nimport { AvailableLanguages } from \"#/i18n\";\nimport { DEFAULT_SETTINGS } from \"#/services/settings\";\nimport { setTelemetryConsent } from \"#/services/telemetry\";\nimport { BrandButton } from \"#/components/features/settings/brand-button\";\nimport { SettingsSwitch } from \"#/components/features/settings/settings-switch\";\nimport { SettingsInput } from \"#/components/features/settings/settings-input\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { LanguageInput } from \"#/components/features/settings/app-settings/language-input\";\nimport { ThemeInput } from \"#/components/features/settings/app-settings/theme-input\";\nimport {\n displayErrorToast,\n displaySuccessToast,\n} from \"#/utils/custom-toast-handlers\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\nimport { AppSettingsInputsSkeleton } from \"#/components/features/settings/app-settings/app-settings-inputs-skeleton\";\nimport { SettingsDropdownInput } from \"#/components/features/settings/settings-dropdown-input\";\nimport { NavigationLink } from \"#/components/shared/navigation-link\";\nimport { useLlmProfiles } from \"#/hooks/query/use-llm-profiles\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\n\nconst AUTOMATIC_TITLE_LLM_PROFILE_KEY = \"__automatic__\";\n\nexport function AppSettingsScreen() {\n const { t } = useTranslation(\"openhands\");\n\n const { mutate: saveSettings, isPending } = useSaveSettings();\n const { data: settings, isLoading } = useSettings();\n const activeBackend = useActiveBackend();\n const isCloudBackend = activeBackend.backend.kind === \"cloud\";\n const { data: llmProfiles, isLoading: areLlmProfilesLoading } =\n useLlmProfiles();\n\n const [languageInputHasChanged, setLanguageInputHasChanged] =\n React.useState(false);\n const [analyticsSwitchHasChanged, setAnalyticsSwitchHasChanged] =\n React.useState(false);\n const [\n soundNotificationsSwitchHasChanged,\n setSoundNotificationsSwitchHasChanged,\n ] = React.useState(false);\n const [gitUserNameHasChanged, setGitUserNameHasChanged] =\n React.useState(false);\n const [gitUserEmailHasChanged, setGitUserEmailHasChanged] =\n React.useState(false);\n const [titleLlmProfileInput, setTitleLlmProfileInput] = React.useState<\n string | null | undefined\n >(undefined);\n\n const storedTitleLlmProfile = React.useMemo(() => {\n const preference = settings?.title_llm_profile ?? null;\n if (!preference || !llmProfiles) return preference;\n return llmProfiles.profiles.some((profile) => profile.name === preference)\n ? preference\n : null;\n }, [llmProfiles, settings?.title_llm_profile]);\n const selectedTitleLlmProfile =\n titleLlmProfileInput === undefined\n ? storedTitleLlmProfile\n : titleLlmProfileInput;\n const titleLlmProfileItems = React.useMemo(\n () => [\n {\n key: AUTOMATIC_TITLE_LLM_PROFILE_KEY,\n label: t(I18nKey.SETTINGS$TITLE_GENERATION_AUTOMATIC),\n },\n ...(llmProfiles?.profiles.map((profile) => ({\n key: profile.name,\n label: profile.model\n ? t(I18nKey.SETTINGS$TITLE_GENERATION_PROFILE_OPTION, {\n name: profile.name,\n model: profile.model,\n })\n : profile.name,\n })) ?? []),\n ],\n [llmProfiles?.profiles, t],\n );\n\n const formAction = (formData: FormData) => {\n const languageLabel = formData.get(\"language-input\")?.toString();\n const languageValue = AvailableLanguages.find(\n ({ label }) => label === languageLabel,\n )?.value;\n const language = languageValue || DEFAULT_SETTINGS.language;\n\n const enableAnalytics = isCloudBackend\n ? true\n : formData.get(\"enable-analytics-switch\")?.toString() === \"on\";\n const enableSoundNotifications =\n formData.get(\"enable-sound-notifications-switch\")?.toString() === \"on\";\n\n const gitUserName =\n formData.get(\"git-user-name-input\")?.toString() ||\n DEFAULT_SETTINGS.git_user_name;\n const gitUserEmail =\n formData.get(\"git-user-email-input\")?.toString() ||\n DEFAULT_SETTINGS.git_user_email;\n\n saveSettings(\n {\n language,\n ...(!isCloudBackend && { user_consents_to_analytics: enableAnalytics }),\n enable_sound_notifications: enableSoundNotifications,\n git_user_name: gitUserName,\n git_user_email: gitUserEmail,\n title_llm_profile: selectedTitleLlmProfile,\n },\n {\n onSuccess: () => {\n void setTelemetryConsent(enableAnalytics ? \"granted\" : \"denied\");\n displaySuccessToast(t(I18nKey.SETTINGS$SAVED));\n },\n onError: (error) => {\n const errorMessage = retrieveAxiosErrorMessage(error);\n displayErrorToast(errorMessage || t(I18nKey.ERROR$GENERIC));\n },\n onSettled: () => {\n setLanguageInputHasChanged(false);\n setAnalyticsSwitchHasChanged(false);\n setSoundNotificationsSwitchHasChanged(false);\n setGitUserNameHasChanged(false);\n setGitUserEmailHasChanged(false);\n setTitleLlmProfileInput(undefined);\n },\n },\n );\n };\n\n const checkIfLanguageInputHasChanged = (value: string) => {\n const selectedLanguage = AvailableLanguages.find(\n ({ label: langValue }) => langValue === value,\n )?.label;\n const currentLanguage = AvailableLanguages.find(\n ({ value: langValue }) => langValue === settings?.language,\n )?.label;\n\n setLanguageInputHasChanged(selectedLanguage !== currentLanguage);\n };\n\n const checkIfAnalyticsSwitchHasChanged = (checked: boolean) => {\n // Treat null as true since analytics is opt-in by default\n const currentAnalytics = settings?.user_consents_to_analytics ?? true;\n setAnalyticsSwitchHasChanged(checked !== currentAnalytics);\n };\n\n const checkIfSoundNotificationsSwitchHasChanged = (checked: boolean) => {\n const currentSoundNotifications = !!settings?.enable_sound_notifications;\n setSoundNotificationsSwitchHasChanged(\n checked !== currentSoundNotifications,\n );\n };\n\n const checkIfGitUserNameHasChanged = (value: string) => {\n const currentValue = settings?.git_user_name;\n setGitUserNameHasChanged(value !== currentValue);\n };\n\n const checkIfGitUserEmailHasChanged = (value: string) => {\n const currentValue = settings?.git_user_email;\n setGitUserEmailHasChanged(value !== currentValue);\n };\n\n const formIsClean =\n !languageInputHasChanged &&\n !analyticsSwitchHasChanged &&\n !soundNotificationsSwitchHasChanged &&\n selectedTitleLlmProfile === storedTitleLlmProfile &&\n !gitUserNameHasChanged &&\n !gitUserEmailHasChanged;\n\n const shouldBeLoading =\n !settings || isLoading || areLlmProfilesLoading || isPending;\n\n return (\n <form\n data-testid=\"app-settings-screen\"\n action={formAction}\n className=\"flex flex-col gap-6\"\n >\n {shouldBeLoading && <AppSettingsInputsSkeleton />}\n {!shouldBeLoading && (\n <div className=\"flex flex-col gap-6\">\n <LanguageInput\n name=\"language-input\"\n defaultKey={settings.language}\n onChange={checkIfLanguageInputHasChanged}\n />\n\n <ThemeInput />\n\n <SettingsSwitch\n testId=\"enable-analytics-switch\"\n name={isCloudBackend ? undefined : \"enable-analytics-switch\"}\n defaultIsToggled={\n isCloudBackend\n ? true\n : (settings.user_consents_to_analytics ?? true)\n }\n isToggled={isCloudBackend ? true : undefined}\n isDisabled={isCloudBackend}\n onToggle={\n isCloudBackend ? undefined : checkIfAnalyticsSwitchHasChanged\n }\n >\n {t(I18nKey.ANALYTICS$SEND_ANONYMOUS_DATA)}\n </SettingsSwitch>\n\n <SettingsSwitch\n testId=\"enable-sound-notifications-switch\"\n name=\"enable-sound-notifications-switch\"\n defaultIsToggled={!!settings.enable_sound_notifications}\n onToggle={checkIfSoundNotificationsSwitchHasChanged}\n >\n {t(I18nKey.SETTINGS$SOUND_NOTIFICATIONS)}\n </SettingsSwitch>\n\n <div className=\"border-t border-[var(--oh-border)] pt-6 mt-2\">\n <h3 className=\"text-lg font-medium mb-2\">\n {t(I18nKey.SETTINGS$CONVERSATION_TITLES)}\n </h3>\n <p className=\"mb-4 text-sm leading-5 text-tertiary-light\">\n {t(I18nKey.SETTINGS$TITLE_GENERATION_DESCRIPTION)}\n </p>\n <SettingsDropdownInput\n testId=\"title-llm-profile-input\"\n name=\"title-llm-profile-input\"\n label={t(I18nKey.SETTINGS$TITLE_GENERATION_MODEL)}\n items={titleLlmProfileItems}\n selectedKey={\n selectedTitleLlmProfile ?? AUTOMATIC_TITLE_LLM_PROFILE_KEY\n }\n onSelectionChange={(key) => {\n const value = key?.toString();\n setTitleLlmProfileInput(\n !value || value === AUTOMATIC_TITLE_LLM_PROFILE_KEY\n ? null\n : value,\n );\n }}\n />\n <NavigationLink\n to=\"/settings/llm\"\n className=\"mt-3 inline-block text-sm text-primary hover:underline\"\n >\n {t(I18nKey.SETTINGS$MANAGE_LLM_PROFILES)}\n </NavigationLink>\n </div>\n\n <div className=\"border-t border-[var(--oh-border)] pt-6 mt-2\">\n <h3 className=\"text-lg font-medium mb-2\">\n {t(I18nKey.SETTINGS$GIT_SETTINGS)}\n </h3>\n <p className=\"mb-4 text-sm leading-5 text-tertiary-light\">\n {t(I18nKey.SETTINGS$GIT_SETTINGS_DESCRIPTION)}\n </p>\n <div className=\"flex flex-col gap-6\">\n <SettingsInput\n testId=\"git-user-name-input\"\n name=\"git-user-name-input\"\n type=\"text\"\n label={t(I18nKey.SETTINGS$GIT_USERNAME)}\n defaultValue={settings.git_user_name || \"\"}\n onChange={checkIfGitUserNameHasChanged}\n placeholder={t(I18nKey.SETTINGS$GIT_USERNAME_PLACEHOLDER)}\n className=\"w-full min-w-0\"\n />\n <SettingsInput\n testId=\"git-user-email-input\"\n name=\"git-user-email-input\"\n type=\"email\"\n label={t(I18nKey.SETTINGS$GIT_EMAIL)}\n defaultValue={settings.git_user_email || \"\"}\n onChange={checkIfGitUserEmailHasChanged}\n placeholder={t(I18nKey.SETTINGS$GIT_EMAIL_PLACEHOLDER)}\n className=\"w-full min-w-0\"\n />\n </div>\n <div className=\"flex justify-start pt-4\">\n <BrandButton\n testId=\"submit-button\"\n variant=\"primary\"\n type=\"submit\"\n isDisabled={isPending || formIsClean}\n >\n {!isPending && t(I18nKey.SETTINGS$SAVE_CHANGES)}\n {isPending && t(I18nKey.SETTINGS$SAVING)}\n </BrandButton>\n </div>\n </div>\n </div>\n )}\n </form>\n );\n}\n\nexport default AppSettingsScreen;\n"],"mappings":"qrCAwBA,IAAM,EAAkC,gBAExC,SAAgB,GAAoB,CAClC,GAAM,CAAE,KAAM,EAAA,eAAe,WAAW,EAElC,CAAE,OAAQ,EAAc,aAAc,EAAA,gBAAgB,EACtD,CAAE,KAAM,EAAU,aAAc,EAAA,YAAY,EAE5C,EADgB,EAAA,iBACC,EAAc,QAAQ,OAAS,QAChD,CAAE,KAAM,EAAa,UAAW,GACpC,EAAA,eAAe,EAEX,CAAC,EAAyB,GAC9B,EAAA,QAAM,SAAS,EAAK,EAChB,CAAC,EAA2B,GAChC,EAAA,QAAM,SAAS,EAAK,EAChB,CACJ,EACA,GACE,EAAA,QAAM,SAAS,EAAK,EAClB,CAAC,EAAuB,GAC5B,EAAA,QAAM,SAAS,EAAK,EAChB,CAAC,EAAwB,GAC7B,EAAA,QAAM,SAAS,EAAK,EAChB,CAAC,EAAsB,GAA2B,EAAA,QAAM,SAE5D,IAAA,EAAS,EAEL,EAAwB,EAAA,QAAM,YAAc,CAChD,IAAM,EAAa,GAAU,mBAAqB,KAElD,MADI,CAAC,GAAc,CAAC,GACb,EAAY,SAAS,KAAM,GAAY,EAAQ,OAAS,CAAU,EADjC,EAGpC,IACN,EAAG,CAAC,EAAa,GAAU,iBAAiB,CAAC,EACvC,EACJ,IAAyB,IAAA,GACrB,EACA,EACA,EAAuB,EAAA,QAAM,YAC3B,CACJ,CACE,IAAK,EACL,MAAO,EAAE,EAAA,QAAQ,mCAAmC,CACtD,EACA,GAAI,GAAa,SAAS,IAAK,IAAa,CAC1C,IAAK,EAAQ,KACb,MAAO,EAAQ,MACX,EAAE,EAAA,QAAQ,yCAA0C,CAClD,KAAM,EAAQ,KACd,MAAO,EAAQ,KACjB,CAAC,EACD,EAAQ,IACd,EAAE,GAAK,CAAC,CACV,EACA,CAAC,GAAa,SAAU,CAAC,CAC3B,EAEM,EAAc,GAAuB,CACzC,IAAM,EAAgB,EAAS,IAAI,gBAAgB,GAAG,SAAS,EAIzD,EAHgB,EAAA,mBAAmB,MACtC,CAAE,WAAY,IAAU,CAC3B,GAAG,OAC+B,EAAA,iBAAiB,SAE7C,EAAkB,EACpB,GACA,EAAS,IAAI,yBAAyB,GAAG,SAAS,IAAM,KACtD,EACJ,EAAS,IAAI,mCAAmC,GAAG,SAAS,IAAM,KAE9D,EACJ,EAAS,IAAI,qBAAqB,GAAG,SAAS,GAC9C,EAAA,iBAAiB,cACb,EACJ,EAAS,IAAI,sBAAsB,GAAG,SAAS,GAC/C,EAAA,iBAAiB,eAEnB,EACE,CACE,WACA,GAAI,CAAC,GAAkB,CAAE,2BAA4B,CAAgB,EACrE,2BAA4B,EAC5B,cAAe,EACf,eAAgB,EAChB,kBAAmB,CACrB,EACA,CACE,cAAiB,CACf,EAAK,oBAAoB,EAAkB,UAAY,QAAQ,EAC/D,EAAA,oBAAoB,EAAE,EAAA,QAAQ,cAAc,CAAC,CAC/C,EACA,QAAU,GAAU,CAElB,EAAA,kBADqB,EAAA,0BAA0B,CAC7B,GAAgB,EAAE,EAAA,QAAQ,aAAa,CAAC,CAC5D,EACA,cAAiB,CACf,EAA2B,EAAK,EAChC,EAA6B,EAAK,EAClC,EAAsC,EAAK,EAC3C,EAAyB,EAAK,EAC9B,EAA0B,EAAK,EAC/B,EAAwB,IAAA,EAAS,CACnC,CACF,CACF,CACF,EAEM,EAAkC,GAAkB,CACxD,IAAM,EAAmB,EAAA,mBAAmB,MACzC,CAAE,MAAO,KAAgB,IAAc,CAC1C,GAAG,MACG,EAAkB,EAAA,mBAAmB,MACxC,CAAE,MAAO,KAAgB,IAAc,GAAU,QACpD,GAAG,MAEH,EAA2B,IAAqB,CAAe,CACjE,EAEM,EAAoC,GAAqB,CAG7D,EAA6B,KADJ,GAAU,4BAA8B,GACR,CAC3D,EAEM,EAA6C,GAAqB,CAEtE,EACE,IAAY,CAFqB,CAAC,GAAU,0BAG9C,CACF,EAEM,EAAgC,GAAkB,CACtD,IAAM,EAAe,GAAU,cAC/B,EAAyB,IAAU,CAAY,CACjD,EAEM,EAAiC,GAAkB,CACvD,IAAM,EAAe,GAAU,eAC/B,EAA0B,IAAU,CAAY,CAClD,EAEM,EACJ,CAAC,GACD,CAAC,GACD,CAAC,GACD,IAA4B,GAC5B,CAAC,GACD,CAAC,EAEG,EACJ,CAAC,GAAY,GAAa,GAAyB,EAErD,OACE,EAAA,EAAA,MAAC,OAAD,CACE,cAAY,sBACZ,OAAQ,EACR,UAAU,+BAHZ,CAKG,IAAmB,EAAA,EAAA,KAAC,EAAA,0BAAD,CAA4B,CAAA,EAC/C,CAAC,IACA,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,+BAAf,EACE,EAAA,EAAA,KAAC,EAAA,cAAD,CACE,KAAK,iBACL,WAAY,EAAS,SACrB,SAAU,CACX,CAAA,GAED,EAAA,EAAA,KAAC,EAAA,WAAD,CAAa,CAAA,GAEb,EAAA,EAAA,KAAC,EAAA,eAAD,CACE,OAAO,0BACP,KAAM,EAAiB,IAAA,GAAY,0BACnC,iBACE,EACI,GACC,EAAS,4BAA8B,GAE9C,UAAW,EAAiB,GAAO,IAAA,GACnC,WAAY,EACZ,SACE,EAAiB,IAAA,GAAY,WAG9B,EAAE,EAAA,QAAQ,6BAA6B,CAC1B,CAAA,GAEhB,EAAA,EAAA,KAAC,EAAA,eAAD,CACE,OAAO,oCACP,KAAK,oCACL,iBAAkB,CAAC,CAAC,EAAS,2BAC7B,SAAU,WAET,EAAE,EAAA,QAAQ,4BAA4B,CACzB,CAAA,GAEhB,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,wDAAf,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,oCACX,EAAE,EAAA,QAAQ,4BAA4B,CACrC,CAAA,GACJ,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,sDACV,EAAE,EAAA,QAAQ,qCAAqC,CAC/C,CAAA,GACH,EAAA,EAAA,KAAC,EAAA,sBAAD,CACE,OAAO,0BACP,KAAK,0BACL,MAAO,EAAE,EAAA,QAAQ,+BAA+B,EAChD,MAAO,EACP,YACE,GAA2B,EAE7B,kBAAoB,GAAQ,CAC1B,IAAM,EAAQ,GAAK,SAAS,EAC5B,EACE,CAAC,GAAS,IAAU,EAChB,KACA,CACN,CACF,CACD,CAAA,GACD,EAAA,EAAA,KAAC,EAAA,eAAD,CACE,GAAG,gBACH,UAAU,kEAET,EAAE,EAAA,QAAQ,4BAA4B,CACzB,CAAA,CACb,KAEL,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,wDAAf,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,oCACX,EAAE,EAAA,QAAQ,qBAAqB,CAC9B,CAAA,GACJ,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,sDACV,EAAE,EAAA,QAAQ,iCAAiC,CAC3C,CAAA,GACH,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,+BAAf,EACE,EAAA,EAAA,KAAC,EAAA,cAAD,CACE,OAAO,sBACP,KAAK,sBACL,KAAK,OACL,MAAO,EAAE,EAAA,QAAQ,qBAAqB,EACtC,aAAc,EAAS,eAAiB,GACxC,SAAU,EACV,YAAa,EAAE,EAAA,QAAQ,iCAAiC,EACxD,UAAU,gBACX,CAAA,GACD,EAAA,EAAA,KAAC,EAAA,cAAD,CACE,OAAO,uBACP,KAAK,uBACL,KAAK,QACL,MAAO,EAAE,EAAA,QAAQ,kBAAkB,EACnC,aAAc,EAAS,gBAAkB,GACzC,SAAU,EACV,YAAa,EAAE,EAAA,QAAQ,8BAA8B,EACrD,UAAU,gBACX,CAAA,CACE,KACL,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,oCACb,EAAA,EAAA,MAAC,EAAA,YAAD,CACE,OAAO,gBACP,QAAQ,UACR,KAAK,SACL,WAAY,GAAa,WAJ3B,CAMG,CAAC,GAAa,EAAE,EAAA,QAAQ,qBAAqB,EAC7C,GAAa,EAAE,EAAA,QAAQ,eAAe,CAC5B,GACV,CAAA,CACF,GACF,GAEH,GAEV"}
1
+ {"version":3,"file":"app-settings.cjs","names":[],"sources":["../../src/routes/app-settings.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useSaveSettings } from \"#/hooks/mutation/use-save-settings\";\nimport { useSettings } from \"#/hooks/query/use-settings\";\nimport { AvailableLanguages } from \"#/i18n\";\nimport { DEFAULT_SETTINGS } from \"#/services/settings\";\nimport { setTelemetryConsent } from \"#/services/telemetry\";\nimport { BrandButton } from \"#/components/features/settings/brand-button\";\nimport { SettingsSwitch } from \"#/components/features/settings/settings-switch\";\nimport { SettingsInput } from \"#/components/features/settings/settings-input\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { LanguageInput } from \"#/components/features/settings/app-settings/language-input\";\nimport { ThemeInput } from \"#/components/features/settings/app-settings/theme-input\";\nimport {\n displayErrorToast,\n displaySuccessToast,\n} from \"#/utils/custom-toast-handlers\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\nimport { AppSettingsInputsSkeleton } from \"#/components/features/settings/app-settings/app-settings-inputs-skeleton\";\nimport { SettingsDropdownInput } from \"#/components/features/settings/settings-dropdown-input\";\nimport { NavigationLink } from \"#/components/shared/navigation-link\";\nimport { useLlmProfiles } from \"#/hooks/query/use-llm-profiles\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { formatModelNameForDisplay } from \"#/utils/format-model-name\";\n\nconst AUTOMATIC_TITLE_LLM_PROFILE_KEY = \"__automatic__\";\n\nexport function AppSettingsScreen() {\n const { t } = useTranslation(\"openhands\");\n\n const { mutate: saveSettings, isPending } = useSaveSettings();\n const { data: settings, isLoading } = useSettings();\n const activeBackend = useActiveBackend();\n const isCloudBackend = activeBackend.backend.kind === \"cloud\";\n const { data: llmProfiles, isLoading: areLlmProfilesLoading } =\n useLlmProfiles();\n\n const [languageInputHasChanged, setLanguageInputHasChanged] =\n React.useState(false);\n const [analyticsSwitchHasChanged, setAnalyticsSwitchHasChanged] =\n React.useState(false);\n const [\n soundNotificationsSwitchHasChanged,\n setSoundNotificationsSwitchHasChanged,\n ] = React.useState(false);\n const [gitUserNameHasChanged, setGitUserNameHasChanged] =\n React.useState(false);\n const [gitUserEmailHasChanged, setGitUserEmailHasChanged] =\n React.useState(false);\n const [titleLlmProfileInput, setTitleLlmProfileInput] = React.useState<\n string | null | undefined\n >(undefined);\n\n const storedTitleLlmProfile = React.useMemo(() => {\n const preference = settings?.title_llm_profile ?? null;\n if (!preference || !llmProfiles) return preference;\n return llmProfiles.profiles.some((profile) => profile.name === preference)\n ? preference\n : null;\n }, [llmProfiles, settings?.title_llm_profile]);\n const selectedTitleLlmProfile =\n titleLlmProfileInput === undefined\n ? storedTitleLlmProfile\n : titleLlmProfileInput;\n const titleLlmProfileItems = React.useMemo(\n () => [\n {\n key: AUTOMATIC_TITLE_LLM_PROFILE_KEY,\n label: t(I18nKey.SETTINGS$TITLE_GENERATION_AUTOMATIC),\n },\n ...(llmProfiles?.profiles.map((profile) => ({\n key: profile.name,\n label: profile.model\n ? t(I18nKey.SETTINGS$TITLE_GENERATION_PROFILE_OPTION, {\n name: profile.name,\n model: formatModelNameForDisplay(profile.model) ?? profile.model,\n })\n : profile.name,\n })) ?? []),\n ],\n [llmProfiles?.profiles, t],\n );\n\n const formAction = (formData: FormData) => {\n const languageLabel = formData.get(\"language-input\")?.toString();\n const languageValue = AvailableLanguages.find(\n ({ label }) => label === languageLabel,\n )?.value;\n const language = languageValue || DEFAULT_SETTINGS.language;\n\n const enableAnalytics = isCloudBackend\n ? true\n : formData.get(\"enable-analytics-switch\")?.toString() === \"on\";\n const enableSoundNotifications =\n formData.get(\"enable-sound-notifications-switch\")?.toString() === \"on\";\n\n const gitUserName =\n formData.get(\"git-user-name-input\")?.toString() ||\n DEFAULT_SETTINGS.git_user_name;\n const gitUserEmail =\n formData.get(\"git-user-email-input\")?.toString() ||\n DEFAULT_SETTINGS.git_user_email;\n\n saveSettings(\n {\n language,\n ...(!isCloudBackend && { user_consents_to_analytics: enableAnalytics }),\n enable_sound_notifications: enableSoundNotifications,\n git_user_name: gitUserName,\n git_user_email: gitUserEmail,\n title_llm_profile: selectedTitleLlmProfile,\n },\n {\n onSuccess: () => {\n void setTelemetryConsent(enableAnalytics ? \"granted\" : \"denied\");\n displaySuccessToast(t(I18nKey.SETTINGS$SAVED));\n },\n onError: (error) => {\n const errorMessage = retrieveAxiosErrorMessage(error);\n displayErrorToast(errorMessage || t(I18nKey.ERROR$GENERIC));\n },\n onSettled: () => {\n setLanguageInputHasChanged(false);\n setAnalyticsSwitchHasChanged(false);\n setSoundNotificationsSwitchHasChanged(false);\n setGitUserNameHasChanged(false);\n setGitUserEmailHasChanged(false);\n setTitleLlmProfileInput(undefined);\n },\n },\n );\n };\n\n const checkIfLanguageInputHasChanged = (value: string) => {\n const selectedLanguage = AvailableLanguages.find(\n ({ label: langValue }) => langValue === value,\n )?.label;\n const currentLanguage = AvailableLanguages.find(\n ({ value: langValue }) => langValue === settings?.language,\n )?.label;\n\n setLanguageInputHasChanged(selectedLanguage !== currentLanguage);\n };\n\n const checkIfAnalyticsSwitchHasChanged = (checked: boolean) => {\n // Treat null as true since analytics is opt-in by default\n const currentAnalytics = settings?.user_consents_to_analytics ?? true;\n setAnalyticsSwitchHasChanged(checked !== currentAnalytics);\n };\n\n const checkIfSoundNotificationsSwitchHasChanged = (checked: boolean) => {\n const currentSoundNotifications = !!settings?.enable_sound_notifications;\n setSoundNotificationsSwitchHasChanged(\n checked !== currentSoundNotifications,\n );\n };\n\n const checkIfGitUserNameHasChanged = (value: string) => {\n const currentValue = settings?.git_user_name;\n setGitUserNameHasChanged(value !== currentValue);\n };\n\n const checkIfGitUserEmailHasChanged = (value: string) => {\n const currentValue = settings?.git_user_email;\n setGitUserEmailHasChanged(value !== currentValue);\n };\n\n const formIsClean =\n !languageInputHasChanged &&\n !analyticsSwitchHasChanged &&\n !soundNotificationsSwitchHasChanged &&\n selectedTitleLlmProfile === storedTitleLlmProfile &&\n !gitUserNameHasChanged &&\n !gitUserEmailHasChanged;\n\n const shouldBeLoading =\n !settings || isLoading || areLlmProfilesLoading || isPending;\n\n return (\n <form\n data-testid=\"app-settings-screen\"\n action={formAction}\n className=\"flex flex-col gap-6\"\n >\n {shouldBeLoading && <AppSettingsInputsSkeleton />}\n {!shouldBeLoading && (\n <div className=\"flex flex-col gap-6\">\n <LanguageInput\n name=\"language-input\"\n defaultKey={settings.language}\n onChange={checkIfLanguageInputHasChanged}\n />\n\n <ThemeInput />\n\n <SettingsSwitch\n testId=\"enable-analytics-switch\"\n name={isCloudBackend ? undefined : \"enable-analytics-switch\"}\n defaultIsToggled={\n isCloudBackend\n ? true\n : (settings.user_consents_to_analytics ?? true)\n }\n isToggled={isCloudBackend ? true : undefined}\n isDisabled={isCloudBackend}\n onToggle={\n isCloudBackend ? undefined : checkIfAnalyticsSwitchHasChanged\n }\n >\n {t(I18nKey.ANALYTICS$SEND_ANONYMOUS_DATA)}\n </SettingsSwitch>\n\n <SettingsSwitch\n testId=\"enable-sound-notifications-switch\"\n name=\"enable-sound-notifications-switch\"\n defaultIsToggled={!!settings.enable_sound_notifications}\n onToggle={checkIfSoundNotificationsSwitchHasChanged}\n >\n {t(I18nKey.SETTINGS$SOUND_NOTIFICATIONS)}\n </SettingsSwitch>\n\n <div className=\"border-t border-[var(--oh-border)] pt-6 mt-2\">\n <h3 className=\"text-lg font-medium mb-2\">\n {t(I18nKey.SETTINGS$CONVERSATION_TITLES)}\n </h3>\n <p className=\"mb-4 text-sm leading-5 text-tertiary-light\">\n {t(I18nKey.SETTINGS$TITLE_GENERATION_DESCRIPTION)}\n </p>\n <SettingsDropdownInput\n testId=\"title-llm-profile-input\"\n name=\"title-llm-profile-input\"\n label={t(I18nKey.SETTINGS$TITLE_GENERATION_MODEL)}\n items={titleLlmProfileItems}\n selectedKey={\n selectedTitleLlmProfile ?? AUTOMATIC_TITLE_LLM_PROFILE_KEY\n }\n onSelectionChange={(key) => {\n const value = key?.toString();\n setTitleLlmProfileInput(\n !value || value === AUTOMATIC_TITLE_LLM_PROFILE_KEY\n ? null\n : value,\n );\n }}\n />\n <NavigationLink\n to=\"/settings/llm\"\n className=\"mt-3 inline-block text-sm text-primary hover:underline\"\n >\n {t(I18nKey.SETTINGS$MANAGE_LLM_PROFILES)}\n </NavigationLink>\n </div>\n\n <div className=\"border-t border-[var(--oh-border)] pt-6 mt-2\">\n <h3 className=\"text-lg font-medium mb-2\">\n {t(I18nKey.SETTINGS$GIT_SETTINGS)}\n </h3>\n <p className=\"mb-4 text-sm leading-5 text-tertiary-light\">\n {t(I18nKey.SETTINGS$GIT_SETTINGS_DESCRIPTION)}\n </p>\n <div className=\"flex flex-col gap-6\">\n <SettingsInput\n testId=\"git-user-name-input\"\n name=\"git-user-name-input\"\n type=\"text\"\n label={t(I18nKey.SETTINGS$GIT_USERNAME)}\n defaultValue={settings.git_user_name || \"\"}\n onChange={checkIfGitUserNameHasChanged}\n placeholder={t(I18nKey.SETTINGS$GIT_USERNAME_PLACEHOLDER)}\n className=\"w-full min-w-0\"\n />\n <SettingsInput\n testId=\"git-user-email-input\"\n name=\"git-user-email-input\"\n type=\"email\"\n label={t(I18nKey.SETTINGS$GIT_EMAIL)}\n defaultValue={settings.git_user_email || \"\"}\n onChange={checkIfGitUserEmailHasChanged}\n placeholder={t(I18nKey.SETTINGS$GIT_EMAIL_PLACEHOLDER)}\n className=\"w-full min-w-0\"\n />\n </div>\n <div className=\"flex justify-start pt-4\">\n <BrandButton\n testId=\"submit-button\"\n variant=\"primary\"\n type=\"submit\"\n isDisabled={isPending || formIsClean}\n >\n {!isPending && t(I18nKey.SETTINGS$SAVE_CHANGES)}\n {isPending && t(I18nKey.SETTINGS$SAVING)}\n </BrandButton>\n </div>\n </div>\n </div>\n )}\n </form>\n );\n}\n\nexport default AppSettingsScreen;\n"],"mappings":"iuCAyBA,IAAM,EAAkC,gBAExC,SAAgB,GAAoB,CAClC,GAAM,CAAE,KAAM,EAAA,eAAe,WAAW,EAElC,CAAE,OAAQ,EAAc,aAAc,EAAA,gBAAgB,EACtD,CAAE,KAAM,EAAU,aAAc,EAAA,YAAY,EAE5C,EADgB,EAAA,iBACC,EAAc,QAAQ,OAAS,QAChD,CAAE,KAAM,EAAa,UAAW,GACpC,EAAA,eAAe,EAEX,CAAC,EAAyB,GAC9B,EAAA,QAAM,SAAS,EAAK,EAChB,CAAC,EAA2B,GAChC,EAAA,QAAM,SAAS,EAAK,EAChB,CACJ,EACA,GACE,EAAA,QAAM,SAAS,EAAK,EAClB,CAAC,EAAuB,GAC5B,EAAA,QAAM,SAAS,EAAK,EAChB,CAAC,EAAwB,GAC7B,EAAA,QAAM,SAAS,EAAK,EAChB,CAAC,EAAsB,GAA2B,EAAA,QAAM,SAE5D,IAAA,EAAS,EAEL,EAAwB,EAAA,QAAM,YAAc,CAChD,IAAM,EAAa,GAAU,mBAAqB,KAElD,MADI,CAAC,GAAc,CAAC,GACb,EAAY,SAAS,KAAM,GAAY,EAAQ,OAAS,CAAU,EADjC,EAGpC,IACN,EAAG,CAAC,EAAa,GAAU,iBAAiB,CAAC,EACvC,EACJ,IAAyB,IAAA,GACrB,EACA,EACA,EAAuB,EAAA,QAAM,YAC3B,CACJ,CACE,IAAK,EACL,MAAO,EAAE,EAAA,QAAQ,mCAAmC,CACtD,EACA,GAAI,GAAa,SAAS,IAAK,IAAa,CAC1C,IAAK,EAAQ,KACb,MAAO,EAAQ,MACX,EAAE,EAAA,QAAQ,yCAA0C,CAClD,KAAM,EAAQ,KACd,MAAO,EAAA,0BAA0B,EAAQ,KAAK,GAAK,EAAQ,KAC7D,CAAC,EACD,EAAQ,IACd,EAAE,GAAK,CAAC,CACV,EACA,CAAC,GAAa,SAAU,CAAC,CAC3B,EAEM,EAAc,GAAuB,CACzC,IAAM,EAAgB,EAAS,IAAI,gBAAgB,GAAG,SAAS,EAIzD,EAHgB,EAAA,mBAAmB,MACtC,CAAE,WAAY,IAAU,CAC3B,GAAG,OAC+B,EAAA,iBAAiB,SAE7C,EAAkB,EACpB,GACA,EAAS,IAAI,yBAAyB,GAAG,SAAS,IAAM,KACtD,EACJ,EAAS,IAAI,mCAAmC,GAAG,SAAS,IAAM,KAE9D,EACJ,EAAS,IAAI,qBAAqB,GAAG,SAAS,GAC9C,EAAA,iBAAiB,cACb,EACJ,EAAS,IAAI,sBAAsB,GAAG,SAAS,GAC/C,EAAA,iBAAiB,eAEnB,EACE,CACE,WACA,GAAI,CAAC,GAAkB,CAAE,2BAA4B,CAAgB,EACrE,2BAA4B,EAC5B,cAAe,EACf,eAAgB,EAChB,kBAAmB,CACrB,EACA,CACE,cAAiB,CACf,EAAK,oBAAoB,EAAkB,UAAY,QAAQ,EAC/D,EAAA,oBAAoB,EAAE,EAAA,QAAQ,cAAc,CAAC,CAC/C,EACA,QAAU,GAAU,CAElB,EAAA,kBADqB,EAAA,0BAA0B,CAC7B,GAAgB,EAAE,EAAA,QAAQ,aAAa,CAAC,CAC5D,EACA,cAAiB,CACf,EAA2B,EAAK,EAChC,EAA6B,EAAK,EAClC,EAAsC,EAAK,EAC3C,EAAyB,EAAK,EAC9B,EAA0B,EAAK,EAC/B,EAAwB,IAAA,EAAS,CACnC,CACF,CACF,CACF,EAEM,EAAkC,GAAkB,CACxD,IAAM,EAAmB,EAAA,mBAAmB,MACzC,CAAE,MAAO,KAAgB,IAAc,CAC1C,GAAG,MACG,EAAkB,EAAA,mBAAmB,MACxC,CAAE,MAAO,KAAgB,IAAc,GAAU,QACpD,GAAG,MAEH,EAA2B,IAAqB,CAAe,CACjE,EAEM,EAAoC,GAAqB,CAG7D,EAA6B,KADJ,GAAU,4BAA8B,GACR,CAC3D,EAEM,EAA6C,GAAqB,CAEtE,EACE,IAAY,CAFqB,CAAC,GAAU,0BAG9C,CACF,EAEM,EAAgC,GAAkB,CACtD,IAAM,EAAe,GAAU,cAC/B,EAAyB,IAAU,CAAY,CACjD,EAEM,EAAiC,GAAkB,CACvD,IAAM,EAAe,GAAU,eAC/B,EAA0B,IAAU,CAAY,CAClD,EAEM,EACJ,CAAC,GACD,CAAC,GACD,CAAC,GACD,IAA4B,GAC5B,CAAC,GACD,CAAC,EAEG,EACJ,CAAC,GAAY,GAAa,GAAyB,EAErD,OACE,EAAA,EAAA,MAAC,OAAD,CACE,cAAY,sBACZ,OAAQ,EACR,UAAU,+BAHZ,CAKG,IAAmB,EAAA,EAAA,KAAC,EAAA,0BAAD,CAA4B,CAAA,EAC/C,CAAC,IACA,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,+BAAf,EACE,EAAA,EAAA,KAAC,EAAA,cAAD,CACE,KAAK,iBACL,WAAY,EAAS,SACrB,SAAU,CACX,CAAA,GAED,EAAA,EAAA,KAAC,EAAA,WAAD,CAAa,CAAA,GAEb,EAAA,EAAA,KAAC,EAAA,eAAD,CACE,OAAO,0BACP,KAAM,EAAiB,IAAA,GAAY,0BACnC,iBACE,EACI,GACC,EAAS,4BAA8B,GAE9C,UAAW,EAAiB,GAAO,IAAA,GACnC,WAAY,EACZ,SACE,EAAiB,IAAA,GAAY,WAG9B,EAAE,EAAA,QAAQ,6BAA6B,CAC1B,CAAA,GAEhB,EAAA,EAAA,KAAC,EAAA,eAAD,CACE,OAAO,oCACP,KAAK,oCACL,iBAAkB,CAAC,CAAC,EAAS,2BAC7B,SAAU,WAET,EAAE,EAAA,QAAQ,4BAA4B,CACzB,CAAA,GAEhB,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,wDAAf,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,oCACX,EAAE,EAAA,QAAQ,4BAA4B,CACrC,CAAA,GACJ,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,sDACV,EAAE,EAAA,QAAQ,qCAAqC,CAC/C,CAAA,GACH,EAAA,EAAA,KAAC,EAAA,sBAAD,CACE,OAAO,0BACP,KAAK,0BACL,MAAO,EAAE,EAAA,QAAQ,+BAA+B,EAChD,MAAO,EACP,YACE,GAA2B,EAE7B,kBAAoB,GAAQ,CAC1B,IAAM,EAAQ,GAAK,SAAS,EAC5B,EACE,CAAC,GAAS,IAAU,EAChB,KACA,CACN,CACF,CACD,CAAA,GACD,EAAA,EAAA,KAAC,EAAA,eAAD,CACE,GAAG,gBACH,UAAU,kEAET,EAAE,EAAA,QAAQ,4BAA4B,CACzB,CAAA,CACb,KAEL,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,wDAAf,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,oCACX,EAAE,EAAA,QAAQ,qBAAqB,CAC9B,CAAA,GACJ,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,sDACV,EAAE,EAAA,QAAQ,iCAAiC,CAC3C,CAAA,GACH,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,+BAAf,EACE,EAAA,EAAA,KAAC,EAAA,cAAD,CACE,OAAO,sBACP,KAAK,sBACL,KAAK,OACL,MAAO,EAAE,EAAA,QAAQ,qBAAqB,EACtC,aAAc,EAAS,eAAiB,GACxC,SAAU,EACV,YAAa,EAAE,EAAA,QAAQ,iCAAiC,EACxD,UAAU,gBACX,CAAA,GACD,EAAA,EAAA,KAAC,EAAA,cAAD,CACE,OAAO,uBACP,KAAK,uBACL,KAAK,QACL,MAAO,EAAE,EAAA,QAAQ,kBAAkB,EACnC,aAAc,EAAS,gBAAkB,GACzC,SAAU,EACV,YAAa,EAAE,EAAA,QAAQ,8BAA8B,EACrD,UAAU,gBACX,CAAA,CACE,KACL,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,oCACb,EAAA,EAAA,MAAC,EAAA,YAAD,CACE,OAAO,gBACP,QAAQ,UACR,KAAK,SACL,WAAY,GAAa,WAJ3B,CAMG,CAAC,GAAa,EAAE,EAAA,QAAQ,qBAAqB,EAC7C,GAAa,EAAE,EAAA,QAAQ,eAAe,CAC5B,GACV,CAAA,CACF,GACF,GAEH,GAEV"}