@sortedyuan/maybecode 0.3.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/README.md +166 -55
  2. package/README.zh-CN.md +267 -0
  3. package/dist/application.d.ts +40 -34
  4. package/dist/application.d.ts.map +1 -1
  5. package/dist/application.js +290 -170
  6. package/dist/application.js.map +1 -1
  7. package/dist/args.d.ts +2 -2
  8. package/dist/args.d.ts.map +1 -1
  9. package/dist/args.js +50 -27
  10. package/dist/args.js.map +1 -1
  11. package/dist/bin.js +82 -71
  12. package/dist/bin.js.map +4 -4
  13. package/dist/cli/chunk-3IORPKBL.js +3572 -0
  14. package/dist/cli/chunk-3IORPKBL.js.map +7 -0
  15. package/dist/cli/{chunk-LVTRXPDS.js → chunk-4B2Z6KW7.js} +1547 -1536
  16. package/dist/cli/chunk-4B2Z6KW7.js.map +7 -0
  17. package/dist/cli/{chunk-JT6VBKOM.js → chunk-4WG6JIJJ.js} +127 -33
  18. package/dist/cli/{chunk-JT6VBKOM.js.map → chunk-4WG6JIJJ.js.map} +3 -3
  19. package/dist/cli/{chunk-K5JWPNSY.js → chunk-5SLWALZK.js} +3521 -16164
  20. package/dist/cli/chunk-5SLWALZK.js.map +7 -0
  21. package/dist/cli/chunk-MNBYXL5Y.js +132 -0
  22. package/dist/cli/chunk-MNBYXL5Y.js.map +7 -0
  23. package/dist/cli/{chunk-F4XRPLUM.js → chunk-SLWLUEHQ.js} +226 -86
  24. package/dist/cli/chunk-SLWLUEHQ.js.map +7 -0
  25. package/dist/cli/chunk-UQDZ55LQ.js +199 -0
  26. package/dist/cli/chunk-UQDZ55LQ.js.map +7 -0
  27. package/dist/cli/{chunk-7ISOHFS7.js → chunk-WMSG5ZTR.js} +717 -388
  28. package/dist/cli/chunk-WMSG5ZTR.js.map +7 -0
  29. package/dist/cli/chunk-WVIRS76R.js +4057 -0
  30. package/dist/cli/chunk-WVIRS76R.js.map +7 -0
  31. package/dist/cli/{chunk-HOU5ITUK.js → chunk-XTEMRAQW.js} +1 -1
  32. package/dist/cli/chunk-XTEMRAQW.js.map +7 -0
  33. package/dist/cli/chunk-Z3BOPBVU.js +91 -0
  34. package/dist/cli/chunk-Z3BOPBVU.js.map +7 -0
  35. package/dist/cli/{configured-WHY3GGAJ.js → configured-ACNM6TRQ.js} +10 -9
  36. package/dist/cli/{file-type-R2T7TBHI.js → file-type-HLHPV7WC.js} +817 -13
  37. package/dist/cli/file-type-HLHPV7WC.js.map +7 -0
  38. package/dist/cli/mcp-auth-XD5U7WCV.js +74 -0
  39. package/dist/cli/mcp-auth-XD5U7WCV.js.map +7 -0
  40. package/dist/cli/onboarding-WQWCPYEO.js +530 -0
  41. package/dist/cli/onboarding-WQWCPYEO.js.map +7 -0
  42. package/dist/cli/onboarding-check-HRRI5OJ7.js +32 -0
  43. package/dist/cli/onboarding-check-HRRI5OJ7.js.map +7 -0
  44. package/dist/cli/{retained-tui-VJ3VX4R3.js → retained-tui-QF5VMYLC.js} +788 -332
  45. package/dist/cli/retained-tui-QF5VMYLC.js.map +7 -0
  46. package/dist/cli/{sixel-LWTCM76G.js → sixel-ISZ4FZ3U.js} +37 -37
  47. package/dist/cli/{sixel-LWTCM76G.js.map → sixel-ISZ4FZ3U.js.map} +1 -1
  48. package/dist/cli/{team-T7G7PPNN.js → team-O2I5BXHM.js} +7 -6
  49. package/dist/cli/{team-v2-JGBBQ7FR.js → team-v2-YYO2G7DJ.js} +816 -390
  50. package/dist/cli/team-v2-YYO2G7DJ.js.map +7 -0
  51. package/dist/cli/{web-server-FOMNPY7Q.js → web-server-SXMH6FGA.js} +55 -19
  52. package/dist/cli/web-server-SXMH6FGA.js.map +7 -0
  53. package/dist/cli/{web-ui-COB6PKC5.js → web-ui-UWQUFE4W.js} +7 -6
  54. package/dist/config-schema.json +337 -0
  55. package/dist/configured.d.ts +18 -11
  56. package/dist/configured.d.ts.map +1 -1
  57. package/dist/configured.js +213 -390
  58. package/dist/configured.js.map +1 -1
  59. package/dist/controller.d.ts +19 -18
  60. package/dist/controller.d.ts.map +1 -1
  61. package/dist/delegation-commands.d.ts +1 -1
  62. package/dist/delegation-commands.d.ts.map +1 -1
  63. package/dist/delegation-commands.js +8 -8
  64. package/dist/delegation-commands.js.map +1 -1
  65. package/dist/errors.d.ts +2 -1
  66. package/dist/errors.d.ts.map +1 -1
  67. package/dist/errors.js +2 -1
  68. package/dist/errors.js.map +1 -1
  69. package/dist/events.d.ts +8 -6
  70. package/dist/events.d.ts.map +1 -1
  71. package/dist/fork-picker.d.ts.map +1 -1
  72. package/dist/fork-picker.js +19 -5
  73. package/dist/fork-picker.js.map +1 -1
  74. package/dist/git-request.d.ts +6 -6
  75. package/dist/git-request.d.ts.map +1 -1
  76. package/dist/git-request.js +28 -15
  77. package/dist/git-request.js.map +1 -1
  78. package/dist/goal-commands.d.ts +1 -1
  79. package/dist/goal-commands.d.ts.map +1 -1
  80. package/dist/goal-commands.js +12 -5
  81. package/dist/goal-commands.js.map +1 -1
  82. package/dist/index.d.ts +5 -37
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +3 -36
  85. package/dist/index.js.map +1 -1
  86. package/dist/instructions.d.ts +2 -7
  87. package/dist/instructions.d.ts.map +1 -1
  88. package/dist/instructions.js +7 -15
  89. package/dist/instructions.js.map +1 -1
  90. package/dist/keymap.d.ts +2 -2
  91. package/dist/keymap.d.ts.map +1 -1
  92. package/dist/keymap.js +2 -2
  93. package/dist/keymap.js.map +1 -1
  94. package/dist/maybecode-config.schema.json +1765 -0
  95. package/dist/mcp-auth.d.ts +1 -1
  96. package/dist/mcp-auth.d.ts.map +1 -1
  97. package/dist/mcp-auth.js +11 -8
  98. package/dist/mcp-auth.js.map +1 -1
  99. package/dist/mcp-commands.d.ts.map +1 -1
  100. package/dist/mcp-commands.js +18 -4
  101. package/dist/mcp-commands.js.map +1 -1
  102. package/dist/mcp-interaction-ui.d.ts.map +1 -1
  103. package/dist/mcp-interaction-ui.js +11 -4
  104. package/dist/mcp-interaction-ui.js.map +1 -1
  105. package/dist/media-history.d.ts +1 -1
  106. package/dist/media-history.d.ts.map +1 -1
  107. package/dist/media-history.js +8 -2
  108. package/dist/media-history.js.map +1 -1
  109. package/dist/model-picker.d.ts.map +1 -1
  110. package/dist/model-picker.js +10 -11
  111. package/dist/model-picker.js.map +1 -1
  112. package/dist/model-transition.d.ts +11 -0
  113. package/dist/model-transition.d.ts.map +1 -0
  114. package/dist/model-transition.js +48 -0
  115. package/dist/model-transition.js.map +1 -0
  116. package/dist/model.d.ts +2 -2
  117. package/dist/model.d.ts.map +1 -1
  118. package/dist/model.js +8 -4
  119. package/dist/model.js.map +1 -1
  120. package/dist/onboarding-check.d.ts +3 -0
  121. package/dist/onboarding-check.d.ts.map +1 -0
  122. package/dist/onboarding-check.js +22 -0
  123. package/dist/onboarding-check.js.map +1 -0
  124. package/dist/onboarding.d.ts +6 -0
  125. package/dist/onboarding.d.ts.map +1 -0
  126. package/dist/onboarding.js +463 -0
  127. package/dist/onboarding.js.map +1 -0
  128. package/dist/plugins/application.d.ts +6 -4
  129. package/dist/plugins/application.d.ts.map +1 -1
  130. package/dist/plugins/application.js +106 -52
  131. package/dist/plugins/application.js.map +1 -1
  132. package/dist/plugins/instructions.d.ts +1 -1
  133. package/dist/plugins/instructions.d.ts.map +1 -1
  134. package/dist/plugins/instructions.js +24 -11
  135. package/dist/plugins/instructions.js.map +1 -1
  136. package/dist/plugins/resources.d.ts +2 -2
  137. package/dist/plugins/resources.d.ts.map +1 -1
  138. package/dist/plugins/resources.js +22 -12
  139. package/dist/plugins/resources.js.map +1 -1
  140. package/dist/policy.d.ts +1 -1
  141. package/dist/policy.d.ts.map +1 -1
  142. package/dist/policy.js +59 -11
  143. package/dist/policy.js.map +1 -1
  144. package/dist/run.d.ts +2 -0
  145. package/dist/run.d.ts.map +1 -1
  146. package/dist/run.js +38 -33
  147. package/dist/run.js.map +1 -1
  148. package/dist/runtime-instructions.d.ts +1 -1
  149. package/dist/runtime-instructions.d.ts.map +1 -1
  150. package/dist/runtime-instructions.js +15 -7
  151. package/dist/runtime-instructions.js.map +1 -1
  152. package/dist/session-navigation.d.ts +6 -0
  153. package/dist/session-navigation.d.ts.map +1 -0
  154. package/dist/session-navigation.js +64 -0
  155. package/dist/session-navigation.js.map +1 -0
  156. package/dist/session-picker.d.ts +1 -1
  157. package/dist/session-picker.d.ts.map +1 -1
  158. package/dist/session-picker.js +23 -32
  159. package/dist/session-picker.js.map +1 -1
  160. package/dist/settings.d.ts +718 -0
  161. package/dist/settings.d.ts.map +1 -0
  162. package/dist/settings.js +14 -0
  163. package/dist/settings.js.map +1 -0
  164. package/dist/skills.d.ts +1 -1
  165. package/dist/skills.d.ts.map +1 -1
  166. package/dist/skills.js +10 -12
  167. package/dist/skills.js.map +1 -1
  168. package/dist/slash-commands.d.ts +2 -2
  169. package/dist/slash-commands.d.ts.map +1 -1
  170. package/dist/slash-commands.js +149 -67
  171. package/dist/slash-commands.js.map +1 -1
  172. package/dist/team-execution.d.ts +10 -0
  173. package/dist/team-execution.d.ts.map +1 -0
  174. package/dist/team-execution.js +29 -0
  175. package/dist/team-execution.js.map +1 -0
  176. package/dist/team-patches.d.ts.map +1 -1
  177. package/dist/team-patches.js +149 -52
  178. package/dist/team-patches.js.map +1 -1
  179. package/dist/team-plan.d.ts +2 -2
  180. package/dist/team-plan.d.ts.map +1 -1
  181. package/dist/team-plan.js +115 -34
  182. package/dist/team-plan.js.map +1 -1
  183. package/dist/team-recovery.d.ts +1 -1
  184. package/dist/team-recovery.d.ts.map +1 -1
  185. package/dist/team-recovery.js +40 -10
  186. package/dist/team-recovery.js.map +1 -1
  187. package/dist/team-v2.d.ts.map +1 -1
  188. package/dist/team-v2.js +335 -104
  189. package/dist/team-v2.js.map +1 -1
  190. package/dist/team-verification.d.ts +4 -2
  191. package/dist/team-verification.d.ts.map +1 -1
  192. package/dist/team-verification.js +300 -97
  193. package/dist/team-verification.js.map +1 -1
  194. package/dist/team.d.ts +2 -2
  195. package/dist/team.d.ts.map +1 -1
  196. package/dist/team.js +172 -62
  197. package/dist/team.js.map +1 -1
  198. package/dist/terminal-web.d.ts +1 -0
  199. package/dist/terminal-web.d.ts.map +1 -1
  200. package/dist/terminal-web.js +28 -10
  201. package/dist/terminal-web.js.map +1 -1
  202. package/dist/ui/actions.d.ts.map +1 -1
  203. package/dist/ui/actions.js.map +1 -1
  204. package/dist/ui/retained-tui.d.ts.map +1 -1
  205. package/dist/ui/retained-tui.js +231 -173
  206. package/dist/ui/retained-tui.js.map +1 -1
  207. package/dist/ui/{prototype-view.d.ts → terminal-view.d.ts} +7 -7
  208. package/dist/ui/terminal-view.d.ts.map +1 -0
  209. package/dist/ui/{prototype-view.js → terminal-view.js} +185 -98
  210. package/dist/ui/terminal-view.js.map +1 -0
  211. package/dist/web-commands.d.ts.map +1 -1
  212. package/dist/web-commands.js +160 -57
  213. package/dist/web-commands.js.map +1 -1
  214. package/dist/web-extension.d.ts.map +1 -1
  215. package/dist/web-extension.js +14 -4
  216. package/dist/web-extension.js.map +1 -1
  217. package/dist/web-server.d.ts.map +1 -1
  218. package/dist/web-server.js +2 -1
  219. package/dist/web-server.js.map +1 -1
  220. package/dist/web-ui.d.ts.map +1 -1
  221. package/dist/web-ui.js +167 -40
  222. package/dist/web-ui.js.map +1 -1
  223. package/dist/workspace-configuration.d.ts +7 -0
  224. package/dist/workspace-configuration.d.ts.map +1 -0
  225. package/dist/workspace-configuration.js +134 -0
  226. package/dist/workspace-configuration.js.map +1 -0
  227. package/dist/workspace-state.d.ts +20 -0
  228. package/dist/workspace-state.d.ts.map +1 -0
  229. package/dist/workspace-state.js +2 -0
  230. package/dist/workspace-state.js.map +1 -0
  231. package/dist/workspace.d.ts +26 -43
  232. package/dist/workspace.d.ts.map +1 -1
  233. package/dist/workspace.js +261 -323
  234. package/dist/workspace.js.map +1 -1
  235. package/package.json +21 -31
  236. package/dist/cli/chunk-7ISOHFS7.js.map +0 -7
  237. package/dist/cli/chunk-F4XRPLUM.js.map +0 -7
  238. package/dist/cli/chunk-H7SNBFO4.js +0 -5522
  239. package/dist/cli/chunk-H7SNBFO4.js.map +0 -7
  240. package/dist/cli/chunk-HOU5ITUK.js.map +0 -7
  241. package/dist/cli/chunk-K5JWPNSY.js.map +0 -7
  242. package/dist/cli/chunk-LVTRXPDS.js.map +0 -7
  243. package/dist/cli/chunk-VAZMCNBB.js +0 -686
  244. package/dist/cli/chunk-VAZMCNBB.js.map +0 -7
  245. package/dist/cli/chunk-WOFEI42C.js +0 -7820
  246. package/dist/cli/chunk-WOFEI42C.js.map +0 -7
  247. package/dist/cli/file-type-R2T7TBHI.js.map +0 -7
  248. package/dist/cli/mcp-auth-UNRHSIKJ.js +0 -63
  249. package/dist/cli/mcp-auth-UNRHSIKJ.js.map +0 -7
  250. package/dist/cli/retained-tui-VJ3VX4R3.js.map +0 -7
  251. package/dist/cli/team-v2-JGBBQ7FR.js.map +0 -7
  252. package/dist/cli/tui-SA74DKMA.js +0 -1705
  253. package/dist/cli/tui-SA74DKMA.js.map +0 -7
  254. package/dist/cli/web-server-FOMNPY7Q.js.map +0 -7
  255. package/dist/delegation.d.ts +0 -2
  256. package/dist/delegation.d.ts.map +0 -1
  257. package/dist/delegation.js +0 -2
  258. package/dist/delegation.js.map +0 -1
  259. package/dist/history-memory.d.ts +0 -2
  260. package/dist/history-memory.d.ts.map +0 -1
  261. package/dist/history-memory.js +0 -2
  262. package/dist/history-memory.js.map +0 -1
  263. package/dist/subagent-budget.d.ts +0 -2
  264. package/dist/subagent-budget.d.ts.map +0 -1
  265. package/dist/subagent-budget.js +0 -2
  266. package/dist/subagent-budget.js.map +0 -1
  267. package/dist/subagent-files.d.ts +0 -2
  268. package/dist/subagent-files.d.ts.map +0 -1
  269. package/dist/subagent-files.js +0 -2
  270. package/dist/subagent-files.js.map +0 -1
  271. package/dist/subagent-host.d.ts +0 -2
  272. package/dist/subagent-host.d.ts.map +0 -1
  273. package/dist/subagent-host.js +0 -2
  274. package/dist/subagent-host.js.map +0 -1
  275. package/dist/subagent-instructions.d.ts +0 -2
  276. package/dist/subagent-instructions.d.ts.map +0 -1
  277. package/dist/subagent-instructions.js +0 -2
  278. package/dist/subagent-instructions.js.map +0 -1
  279. package/dist/subagents.d.ts +0 -2
  280. package/dist/subagents.d.ts.map +0 -1
  281. package/dist/subagents.js +0 -2
  282. package/dist/subagents.js.map +0 -1
  283. package/dist/summarizer.d.ts +0 -2
  284. package/dist/summarizer.d.ts.map +0 -1
  285. package/dist/summarizer.js +0 -2
  286. package/dist/summarizer.js.map +0 -1
  287. package/dist/tui.d.ts +0 -7
  288. package/dist/tui.d.ts.map +0 -1
  289. package/dist/tui.js +0 -1109
  290. package/dist/tui.js.map +0 -1
  291. package/dist/ui/prototype-view.d.ts.map +0 -1
  292. package/dist/ui/prototype-view.js.map +0 -1
  293. /package/dist/cli/{configured-WHY3GGAJ.js.map → configured-ACNM6TRQ.js.map} +0 -0
  294. /package/dist/cli/{team-T7G7PPNN.js.map → team-O2I5BXHM.js.map} +0 -0
  295. /package/dist/cli/{web-ui-COB6PKC5.js.map → web-ui-UWQUFE4W.js.map} +0 -0
@@ -1,29 +1,17 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
- import {
3
- createMaybeCodeWebHost,
4
- startMaybeCodeWebServer
5
- } from "./chunk-7ISOHFS7.js";
6
2
  import {
7
3
  Keymap,
8
4
  TerminalImageSupport,
9
5
  eastAsianWidth,
10
- formatKeySequence,
11
6
  isFullWidth,
12
7
  isWide,
13
8
  keyStroke,
14
9
  mergeKeyBindings,
15
- parseKeySequence,
16
10
  require_index_min,
17
11
  stringWidth,
18
12
  stripAnsi,
19
13
  terminalImageProtocol
20
- } from "./chunk-JT6VBKOM.js";
21
- import {
22
- diffChars
23
- } from "./chunk-H7SNBFO4.js";
24
- import {
25
- decodeToolChangePreviewPresentation
26
- } from "./chunk-K5JWPNSY.js";
14
+ } from "./chunk-4WG6JIJJ.js";
27
15
  import {
28
16
  __name,
29
17
  __toESM
@@ -102,6 +90,12 @@ function createTerminalClipboard(options = {}) {
102
90
  }
103
91
  __name(createTerminalClipboard, "createTerminalClipboard");
104
92
 
93
+ // packages/ui/tui/dist/images.js
94
+ import { homedir } from "node:os";
95
+ import { join } from "node:path";
96
+ import { omitUndefined } from "@sortedyuan/may/core";
97
+ import { FileMediaStore, imageAttachment, imagePng, readEmbeddedImage } from "@sortedyuan/media";
98
+
105
99
  // packages/ui/tui/dist/text.js
106
100
  import { stripVTControlCharacters as stripVTControlCharacters2 } from "node:util";
107
101
 
@@ -772,25 +766,25 @@ var removeModifierStylesByClose = /* @__PURE__ */ __name((activeStyles, closeCod
772
766
  }
773
767
  }, "removeModifierStylesByClose");
774
768
  var getColorStyle = /* @__PURE__ */ __name((sgrToken) => {
775
- const { code, open: open2, hasArguments } = sgrToken;
769
+ const { code, open, hasArguments } = sgrToken;
776
770
  if (code >= 30 && code <= 37 || code >= 90 && code <= 97 || code === ANSI_SGR_FOREGROUND_EXTENDED && hasArguments) {
777
771
  return {
778
772
  family: "foreground",
779
- open: open2,
773
+ open,
780
774
  close: ANSI_SGR_RESET_FOREGROUND
781
775
  };
782
776
  }
783
777
  if (code >= 40 && code <= 47 || code >= 100 && code <= 107 || code === ANSI_SGR_BACKGROUND_EXTENDED && hasArguments) {
784
778
  return {
785
779
  family: "background",
786
- open: open2,
780
+ open,
787
781
  close: ANSI_SGR_RESET_BACKGROUND
788
782
  };
789
783
  }
790
784
  if (code === ANSI_SGR_UNDERLINE_COLOR_EXTENDED && hasArguments) {
791
785
  return {
792
786
  family: "underlineColor",
793
- open: open2,
787
+ open,
794
788
  close: ANSI_SGR_RESET_UNDERLINE_COLOR
795
789
  };
796
790
  }
@@ -1219,35 +1213,35 @@ var DEFAULT_DARK_THEME = {
1219
1213
  function styleText(value, style2) {
1220
1214
  if (value === "" || style2 === void 0)
1221
1215
  return value;
1222
- const open2 = [];
1216
+ const open = [];
1223
1217
  const close = [];
1224
- appendColor(open2, close, style2.foreground, false);
1225
- appendColor(open2, close, style2.background, true);
1226
- appendEffect(open2, close, style2.bold, 1, 22);
1227
- appendEffect(open2, close, style2.dim, 2, 22);
1228
- appendEffect(open2, close, style2.italic, 3, 23);
1229
- appendEffect(open2, close, style2.underline, 4, 24);
1230
- appendEffect(open2, close, style2.inverse, 7, 27);
1231
- appendEffect(open2, close, style2.strikethrough, 9, 29);
1232
- if (open2.length === 0)
1218
+ appendColor(open, close, style2.foreground, false);
1219
+ appendColor(open, close, style2.background, true);
1220
+ appendEffect(open, close, style2.bold, 1, 22);
1221
+ appendEffect(open, close, style2.dim, 2, 22);
1222
+ appendEffect(open, close, style2.italic, 3, 23);
1223
+ appendEffect(open, close, style2.underline, 4, 24);
1224
+ appendEffect(open, close, style2.inverse, 7, 27);
1225
+ appendEffect(open, close, style2.strikethrough, 9, 29);
1226
+ if (open.length === 0)
1233
1227
  return value;
1234
- return `\x1B[${open2.join(";")}m${value}\x1B[${[...new Set(close.reverse())].join(";")}m`;
1228
+ return `\x1B[${open.join(";")}m${value}\x1B[${[...new Set(close.reverse())].join(";")}m`;
1235
1229
  }
1236
1230
  __name(styleText, "styleText");
1237
- function appendEffect(open2, close, enabled, openCode, closeCode) {
1231
+ function appendEffect(open, close, enabled, openCode, closeCode) {
1238
1232
  if (!enabled)
1239
1233
  return;
1240
- open2.push(openCode);
1234
+ open.push(openCode);
1241
1235
  close.push(closeCode);
1242
1236
  }
1243
1237
  __name(appendEffect, "appendEffect");
1244
- function appendColor(open2, close, color, background) {
1238
+ function appendColor(open, close, color, background) {
1245
1239
  if (color === void 0 || color === "")
1246
1240
  return;
1247
1241
  const prefix = background ? 48 : 38;
1248
1242
  const reset = background ? 49 : 39;
1249
1243
  if (typeof color === "number") {
1250
- open2.push(prefix, 5, clampByte(color));
1244
+ open.push(prefix, 5, clampByte(color));
1251
1245
  close.push(reset);
1252
1246
  return;
1253
1247
  }
@@ -1255,12 +1249,12 @@ function appendColor(open2, close, color, background) {
1255
1249
  const rgb = parseHexColor(color);
1256
1250
  if (rgb === void 0)
1257
1251
  throw new Error(`Invalid terminal color: ${color}`);
1258
- open2.push(prefix, 2, rgb.red, rgb.green, rgb.blue);
1252
+ open.push(prefix, 2, rgb.red, rgb.green, rgb.blue);
1259
1253
  close.push(reset);
1260
1254
  return;
1261
1255
  }
1262
1256
  const code = NAMED_COLORS[color];
1263
- open2.push(code + (background ? 10 : 0));
1257
+ open.push(code + (background ? 10 : 0));
1264
1258
  close.push(reset);
1265
1259
  }
1266
1260
  __name(appendColor, "appendColor");
@@ -1332,9 +1326,6 @@ function sanitizeTerminalText(value) {
1332
1326
  __name(sanitizeTerminalText, "sanitizeTerminalText");
1333
1327
 
1334
1328
  // packages/ui/tui/dist/images.js
1335
- import { homedir } from "node:os";
1336
- import { join } from "node:path";
1337
- import { FileMediaStore, imageAttachment, imagePng, readEmbeddedImage } from "@sortedyuan/media";
1338
1329
  var TerminalImages = class {
1339
1330
  static {
1340
1331
  __name(this, "TerminalImages");
@@ -1363,7 +1354,7 @@ var TerminalImages = class {
1363
1354
  const image = await this.store.save(part.source);
1364
1355
  const png = this.protocol === "none" ? Buffer.alloc(0) : await imagePng(image);
1365
1356
  if (this.protocol === "sixel")
1366
- this.sixel ??= await import("./sixel-LWTCM76G.js");
1357
+ this.sixel ??= await import("./sixel-ISZ4FZ3U.js");
1367
1358
  const raster = this.protocol === "sixel" ? await this.sixel.Jimp.read(png) : void 0;
1368
1359
  if (raster && (raster.width > 1280 || raster.height > 768))
1369
1360
  raster.scaleToFit({ w: 1280, h: 768 });
@@ -1378,7 +1369,7 @@ var TerminalImages = class {
1378
1369
  const attachment = imageAttachment(source), image = this.values.get(attachment.id);
1379
1370
  const caption = image ? `\u56FE\u7247 ${image.width}\xD7${image.height} \xB7 ${image.mediaType} \xB7 ${image.data.byteLength} bytes
1380
1371
  ${image.path}` : attachment.url ? `\u56FE\u7247\u94FE\u63A5\uFF1A${attachment.url}` : `\u56FE\u7247 ${attachment.id}\uFF08\u5A92\u4F53\u8BFB\u53D6\u63A5\u53E3\u672A\u63D0\u4F9B\u6B64\u8D44\u6E90\uFF09`;
1381
- const label = new Text(sanitizeTerminalText(caption), sourceId === void 0 ? {} : { sourceId }).render(size);
1372
+ const label = new Text(sanitizeTerminalText(caption), omitUndefined({ sourceId })).render(size);
1382
1373
  if (!image || this.protocol === "none")
1383
1374
  return label;
1384
1375
  if (this.protocol === "sixel")
@@ -1388,7 +1379,13 @@ ${image.path}` : attachment.url ? `\u56FE\u7247\u94FE\u63A5\uFF1A${attachment.ur
1388
1379
  if (rows + label.lines.length > size.height)
1389
1380
  return label;
1390
1381
  const width = Math.max(1, Math.min(columns, Math.round(rows * 2 * image.width / image.height)));
1391
- return { ...label, lines: [...label.lines, ...Array.from({ length: rows }, () => "")], images: [{ id: image.id, png: image.png, protocol: this.protocol, x: 0, y: label.lines.length, columns: width, rows }] };
1382
+ return {
1383
+ ...label,
1384
+ lines: [...label.lines, ...Array.from({ length: rows }, () => "")],
1385
+ images: [
1386
+ { id: image.id, png: image.png, protocol: this.protocol, x: 0, y: label.lines.length, columns: width, rows }
1387
+ ]
1388
+ };
1392
1389
  }
1393
1390
  renderSixel(image, label, size) {
1394
1391
  const cell = this.options.cellSize?.();
@@ -1415,15 +1412,36 @@ ${image.path}` : attachment.url ? `\u56FE\u7247\u94FE\u63A5\uFF1A${attachment.ur
1415
1412
  const resized = raster.clone().resize({ w: width, h: height });
1416
1413
  const bitmap = new Jimp({ width, height, color: 4294967295 }).composite(resized, 0, 0).bitmap;
1417
1414
  const pixels = utils.PointContainer.fromUint8Array(new Uint8Array(bitmap.data), width, height);
1418
- const palette = buildPaletteSync([pixels], { colors: 256, paletteQuantization: "wuquant", colorDistanceFormula: "euclidean" });
1419
- const quantized = applyPaletteSync(pixels, palette, { imageQuantization: "floyd-steinberg", colorDistanceFormula: "euclidean" });
1415
+ const palette = buildPaletteSync([pixels], {
1416
+ colors: 256,
1417
+ paletteQuantization: "wuquant",
1418
+ colorDistanceFormula: "euclidean"
1419
+ });
1420
+ const quantized = applyPaletteSync(pixels, palette, {
1421
+ imageQuantization: "floyd-steinberg",
1422
+ colorDistanceFormula: "euclidean"
1423
+ });
1420
1424
  const data = new Uint8Array(quantized.toUint8Array());
1421
- image.frame = { key, sixel: introducer(1) + sixelEncode(data, width, height, Array.from(palette.getPointContainer().toUint32Array())) + FINALIZER };
1425
+ image.frame = {
1426
+ key,
1427
+ sixel: introducer(1) + sixelEncode(data, width, height, Array.from(palette.getPointContainer().toUint32Array())) + FINALIZER
1428
+ };
1422
1429
  }
1423
1430
  return {
1424
1431
  ...label,
1425
1432
  lines: [...label.lines, ...Array.from({ length: rows }, () => "")],
1426
- images: [{ id: image.id, png: image.png, protocol: "sixel", sixel: image.frame.sixel, x: 0, y: label.lines.length, columns: Math.ceil(width / cell.width), rows }]
1433
+ images: [
1434
+ {
1435
+ id: image.id,
1436
+ png: image.png,
1437
+ protocol: "sixel",
1438
+ sixel: image.frame.sixel,
1439
+ x: 0,
1440
+ y: label.lines.length,
1441
+ columns: Math.ceil(width / cell.width),
1442
+ rows
1443
+ }
1444
+ ]
1427
1445
  };
1428
1446
  }
1429
1447
  };
@@ -1441,816 +1459,511 @@ function encodeImage(image) {
1441
1459
  }
1442
1460
  __name(encodeImage, "encodeImage");
1443
1461
 
1444
- // packages/ui/tui/dist/agent/tool-renderers.js
1445
- import { stripVTControlCharacters as stripVTControlCharacters3 } from "node:util";
1446
- var ToolRendererRegistry = class {
1447
- static {
1448
- __name(this, "ToolRendererRegistry");
1462
+ // packages/ui/tui/dist/component.js
1463
+ function placeImages(images, y2, height) {
1464
+ return (images ?? []).map((image) => ({ ...image, y: image.y + y2 })).filter((image) => image.y >= 0 && image.y + image.rows <= height);
1465
+ }
1466
+ __name(placeImages, "placeImages");
1467
+ function assertRenderSize(size) {
1468
+ if (!Number.isInteger(size.width) || size.width < 1) {
1469
+ throw new RangeError("Render width must be a positive integer");
1449
1470
  }
1450
- fallback;
1451
- renderers = /* @__PURE__ */ new Map();
1452
- generation = 0;
1453
- get revision() {
1454
- return this.generation;
1471
+ if (!Number.isInteger(size.height) || size.height < 1) {
1472
+ throw new RangeError("Render height must be a positive integer");
1455
1473
  }
1456
- constructor(fallback = genericRenderer) {
1457
- this.fallback = fallback;
1474
+ }
1475
+ __name(assertRenderSize, "assertRenderSize");
1476
+
1477
+ // packages/ui/tui/dist/screen-buffer.js
1478
+ var ScreenBuffer = class _ScreenBuffer {
1479
+ static {
1480
+ __name(this, "ScreenBuffer");
1458
1481
  }
1459
- register(name, renderer) {
1460
- const normalized = name.trim();
1461
- if (normalized === "")
1462
- throw new Error("Tool renderer name cannot be empty");
1463
- this.renderers.set(normalized, renderer);
1464
- this.generation++;
1465
- return this;
1482
+ width;
1483
+ height;
1484
+ lines;
1485
+ cursor;
1486
+ constructor(size, lines, cursor) {
1487
+ this.width = size.width;
1488
+ this.height = size.height;
1489
+ this.lines = lines;
1490
+ this.cursor = cursor;
1466
1491
  }
1467
- render(item, options) {
1468
- return this.renderDocument(item, options).map((line) => line.value).join("\n");
1492
+ static from(result, size) {
1493
+ assertRenderSize(size);
1494
+ const lines = result.lines.slice(0, size.height).map((line) => normalizeLine(line, size.width));
1495
+ const cursor = normalizeCursor(result.cursor, size);
1496
+ return new _ScreenBuffer(size, lines, cursor);
1469
1497
  }
1470
- renderDocument(item, options) {
1471
- const renderer = this.renderers.get(item.call.name) ?? this.fallback;
1472
- return renderer.renderDocument?.(item, options) ?? renderer.render(item, options).split("\n").map((line) => copyLine(line));
1498
+ lineAt(row) {
1499
+ return this.lines[row] ?? "";
1473
1500
  }
1474
1501
  };
1475
- function createCodingToolRendererRegistry() {
1476
- return new ToolRendererRegistry().register("shell", shellRenderer).register("bash", shellRenderer).register("read", readRenderer).register("edit", fileChangeRenderer).register("write", fileChangeRenderer);
1502
+ function normalizeLine(line, width) {
1503
+ if (line.includes("\n") || line.includes("\r")) {
1504
+ throw new Error("A rendered screen line cannot contain a newline");
1505
+ }
1506
+ return stringWidth(line) <= width ? line : sliceAnsi(line, 0, width);
1477
1507
  }
1478
- __name(createCodingToolRendererRegistry, "createCodingToolRendererRegistry");
1479
- var shellRenderer = documentRenderer((item, options) => {
1480
- const command = stringField(item.call.input, "command") ?? inputSummary(item.call.input);
1481
- const lines = [header(item, options, command)];
1482
- appendProgress(lines, item, options);
1483
- const output = objectValue(item.output);
1484
- const stdout = stringField(output, "stdout") ?? item.streamedOutput;
1485
- const stderr = stringField(output, "stderr") ?? "";
1486
- if (stdout !== "")
1487
- appendOutput(lines, stdout, options);
1488
- if (stderr !== "") {
1489
- lines.push(copyLine(styleText(" stderr", options.theme.error), 2));
1490
- appendOutput(lines, stderr, options, options.theme.error);
1508
+ __name(normalizeLine, "normalizeLine");
1509
+ function normalizeCursor(cursor, size) {
1510
+ if (cursor === void 0)
1511
+ return void 0;
1512
+ const y2 = clampInteger(cursor.y, 0, Math.max(0, size.height - 1));
1513
+ const x2 = clampInteger(cursor.x, 0, size.width - 1);
1514
+ return { x: x2, y: y2, visible: cursor.visible ?? true };
1515
+ }
1516
+ __name(normalizeCursor, "normalizeCursor");
1517
+ function clampInteger(value, minimum, maximum) {
1518
+ if (!Number.isFinite(value))
1519
+ return minimum;
1520
+ return Math.min(maximum, Math.max(minimum, Math.trunc(value)));
1521
+ }
1522
+ __name(clampInteger, "clampInteger");
1523
+
1524
+ // packages/ui/tui/dist/renderer.js
1525
+ var FullscreenRenderer = class {
1526
+ static {
1527
+ __name(this, "FullscreenRenderer");
1491
1528
  }
1492
- if (item.status === "completed") {
1493
- const exitCode = primitiveField(output, "exitCode");
1494
- const signal = primitiveField(output, "signal");
1495
- const result = exitCode === void 0 ? "completed" : `exit ${String(exitCode)}`;
1496
- lines.push(copyLine(styleText(` \u2514\u2500 ${result}${signal == null ? "" : ` \xB7 ${String(signal)}`}`, exitCode === 0 || exitCode === void 0 ? options.theme.muted : options.theme.warning), 5));
1529
+ terminal;
1530
+ previous;
1531
+ images = [];
1532
+ hideCursorByDefault;
1533
+ constructor(terminal, options = {}) {
1534
+ this.terminal = terminal;
1535
+ this.hideCursorByDefault = options.hideCursorByDefault ?? true;
1497
1536
  }
1498
- appendFailure(lines, item, options);
1499
- return lines;
1500
- });
1501
- var readRenderer = documentRenderer((item, options) => {
1502
- const inputPath = stringField(item.call.input, "path") ?? "<unknown>";
1503
- const output = objectValue(item.output);
1504
- const path = stringField(output, "path") ?? inputPath;
1505
- const start = numberField(output, "startLine");
1506
- const end = numberField(output, "endLine");
1507
- const total = numberField(output, "totalLines");
1508
- const range = start === void 0 || end === void 0 ? "" : `:${start}-${end}`;
1509
- const lines = [header(item, options, `${path}${range}`)];
1510
- appendProgress(lines, item, options);
1511
- if (options.expanded) {
1512
- const content = stringField(output, "content");
1513
- if (content !== void 0 && content !== "") {
1514
- appendOutput(lines, content, options, options.theme.toolOutput, true, start ?? 1);
1537
+ render(result, size) {
1538
+ const next = ScreenBuffer.from(result, size);
1539
+ const previous = this.previous;
1540
+ const images = placeImages(result.images, 0, size.height);
1541
+ const imagesChanged = images.length !== this.images.length || images.some((image, index) => {
1542
+ const old = this.images[index];
1543
+ return !old || image.id !== old.id || image.y !== old.y || image.x !== old.x || image.rows !== old.rows || image.columns !== old.columns || image.protocol !== old.protocol || image.protocol === "sixel" && old.protocol === "sixel" && image.sixel !== old.sixel;
1544
+ });
1545
+ const resized = previous !== void 0 && (previous.width !== next.width || previous.height !== next.height);
1546
+ let output = "\x1B[?25l";
1547
+ if (previous === void 0 || resized || imagesChanged) {
1548
+ if (this.images.some((image) => image.protocol === "kitty"))
1549
+ output += "\x1B_Ga=d,d=A,q=2\x1B\\";
1550
+ output += "\x1B[2J";
1515
1551
  }
1516
- } else if (total !== void 0) {
1517
- const count = start === void 0 || end === void 0 ? 0 : Math.max(0, end - start + 1);
1518
- const description = `${count} of ${total} lines`;
1519
- lines.push(copyLine(styleText(` \u2514\u2500 ${count} of ${total} lines${options.detailsHint === void 0 ? "" : ` \xB7 ${options.detailsHint}`}`, options.theme.muted), 5, 5 + description.length));
1520
- }
1521
- appendFailure(lines, item, options);
1522
- return lines;
1523
- });
1524
- var fileChangeRenderer = documentRenderer((item, options) => {
1525
- const inputPath = stringField(item.call.input, "path") ?? "<unknown>";
1526
- const preview = item.preview;
1527
- const detail = preview?.status === "ready" ? `${preview.path} +${preview.additions} -${preview.deletions}` : inputPath;
1528
- const lines = [header(item, options, detail)];
1529
- appendProgress(lines, item, options);
1530
- if (preview?.status === "ready") {
1531
- if (options.expanded && preview.diff !== "") {
1532
- lines.push(...renderDiff(preview.diff, options.theme));
1552
+ const rowCount = previous === void 0 || resized ? next.lines.length : Math.max(next.lines.length, previous.lines.length);
1553
+ const erasedRows = /* @__PURE__ */ new Set();
1554
+ for (let row = 0; row < rowCount; row++) {
1555
+ const line = next.lineAt(row);
1556
+ if (!resized && !imagesChanged && previous?.lineAt(row) === line)
1557
+ continue;
1558
+ output += moveTo(row, 0);
1559
+ output += `\x1B[2K${line}\x1B[0m`;
1560
+ erasedRows.add(row);
1561
+ }
1562
+ for (const image of images) {
1563
+ const erased = image.protocol === "sixel" && Array.from({ length: image.rows }, (_2, index) => image.y + index).some((row) => erasedRows.has(row));
1564
+ if (imagesChanged || resized || previous === void 0 || erased)
1565
+ output += moveTo(image.y, image.x) + encodeImage(image);
1566
+ }
1567
+ this.images = images;
1568
+ const cursor = next.cursor;
1569
+ if (cursor !== void 0) {
1570
+ output += moveTo(cursor.y, cursor.x);
1571
+ output += cursor.visible === false ? "\x1B[?25l" : "\x1B[?25h";
1572
+ } else if (this.hideCursorByDefault) {
1573
+ output += "\x1B[?25l";
1533
1574
  } else {
1534
- const hint = options.detailsHint === void 0 ? "" : ` \xB7 ${options.detailsHint}`;
1535
- lines.push(copyLine(styleText(` \u2514\u2500 ${preview.kind}${hint}`, options.theme.muted), 5, 5 + preview.kind.length));
1575
+ output += "\x1B[?25h";
1536
1576
  }
1537
- } else if (preview?.status === "unavailable") {
1538
- lines.push(copyLine(styleText(` Diff unavailable: ${sanitizeTerminalText(preview.reason)}`, options.theme.warning), 2));
1577
+ this.terminal.write(output);
1578
+ this.previous = next;
1539
1579
  }
1540
- if (item.status === "completed" && preview === void 0) {
1541
- appendOutput(lines, stringify(item.output), options);
1580
+ invalidate() {
1581
+ this.previous = void 0;
1542
1582
  }
1543
- appendFailure(lines, item, options);
1544
- return lines;
1545
- });
1546
- var genericRenderer = documentRenderer((item, options) => {
1547
- const lines = [header(item, options, inputSummary(item.call.input))];
1548
- appendProgress(lines, item, options);
1549
- const output = item.streamedOutput !== "" ? item.streamedOutput : item.status === "completed" ? stringify(item.output) : "";
1550
- if (output !== "")
1551
- appendOutput(lines, output, options);
1552
- appendFailure(lines, item, options);
1553
- return lines;
1554
- });
1555
- function documentRenderer(renderDocument) {
1556
- return { renderDocument, render: /* @__PURE__ */ __name((item, options) => renderDocument(item, options).map((line) => line.value).join("\n"), "render") };
1557
- }
1558
- __name(documentRenderer, "documentRenderer");
1559
- function header(item, options, detail) {
1560
- const marker = item.status === "completed" ? "\u2713" : item.status === "failed" ? "\u2717" : "\u25CF";
1561
- const markerStyle = item.status === "completed" ? options.theme.toolSuccess : item.status === "failed" ? options.theme.toolError : options.theme.toolPending;
1562
- const safeDetail = sanitizeTerminalText(detail).replace(/\s+/gu, " ").trim();
1563
- const selection = options.selected === true ? styleText("\u25B8", options.theme.accent) : " ";
1564
- return copyLine(`${selection} ${styleText(marker, markerStyle)} ${styleText(sanitizeTerminalText(item.call.name), options.theme.toolTitle)}${safeDetail === "" ? "" : ` ${safeDetail}`}`, 4);
1565
- }
1566
- __name(header, "header");
1567
- function appendProgress(lines, item, options) {
1568
- for (const progress of item.progress.slice(options.expanded ? 0 : -2)) {
1569
- lines.push(copyLine(styleText(` \u21B3 ${sanitizeTerminalText(progress)}`, options.theme.muted), 4));
1583
+ dispose(options = {}) {
1584
+ this.previous = void 0;
1585
+ this.terminal.write(`${this.images.some((image) => image.protocol === "kitty") ? "\x1B_Ga=d,d=A,q=2\x1B\\" : ""}${options.clear === true || this.images.length ? "\x1B[2J\x1B[H" : ""}\x1B[0m\x1B[?25h`);
1586
+ this.images = [];
1570
1587
  }
1588
+ };
1589
+ function moveTo(row, column) {
1590
+ return `\x1B[${row + 1};${column + 1}H`;
1571
1591
  }
1572
- __name(appendProgress, "appendProgress");
1573
- function appendOutput(lines, value, options, outputStyle = options.theme.toolOutput, forceExpanded = false, numberFrom) {
1574
- const safe = sanitizeTerminalText(value).replace(/\s+$/gu, "");
1575
- if (safe === "")
1576
- return;
1577
- const maximumLines = options.expanded || forceExpanded ? Number.POSITIVE_INFINITY : 4;
1578
- const limitedCharacters = truncateCharacters(safe, options.maximumOutputCharacters);
1579
- const allLines = limitedCharacters.split("\n");
1580
- const displayed = allLines.slice(0, maximumLines);
1581
- const numberWidth = String((numberFrom ?? 1) + allLines.length - 1).length;
1582
- for (const [index, line] of displayed.entries()) {
1583
- const label = numberFrom === void 0 ? "" : `${String(numberFrom + index).padStart(numberWidth)} \u2502 `;
1584
- lines.push(copyLine(`${styleText(" \u2502", options.theme.border)} ${styleText(label + line, outputStyle)}`, 4 + label.length));
1585
- }
1586
- const omittedLines = allLines.length - displayed.length;
1587
- if (omittedLines > 0) {
1588
- const hint = options.detailsHint === void 0 ? "" : ` \xB7 ${options.detailsHint}`;
1589
- lines.push({ value: styleText(` \u2026 ${omittedLines} more lines${hint}`, options.theme.muted) });
1590
- } else if (limitedCharacters.endsWith("\u2026") && safe !== limitedCharacters) {
1591
- lines.push({ value: styleText(" \u2026 output truncated", options.theme.muted) });
1592
- }
1593
- }
1594
- __name(appendOutput, "appendOutput");
1595
- function appendFailure(lines, item, options) {
1596
- if (item.status === "failed" && item.error !== void 0) {
1597
- lines.push(copyLine(styleText(` ${sanitizeTerminalText(item.error)}`, options.theme.error), 2));
1598
- }
1599
- }
1600
- __name(appendFailure, "appendFailure");
1601
- function renderDiff(diff, theme) {
1602
- return sanitizeTerminalText(diff).split("\n").map((line) => {
1603
- const style2 = line.startsWith("+++") || line.startsWith("---") || line.startsWith("@@") ? theme.muted : line.startsWith("+") ? theme.diffAdded : line.startsWith("-") ? theme.diffRemoved : theme.diffContext;
1604
- return copyLine(`${styleText(" \u2502", theme.border)} ${styleText(line, style2)}`, 4);
1605
- });
1606
- }
1607
- __name(renderDiff, "renderDiff");
1608
- function copyLine(value, start = 0, end = stripVTControlCharacters3(value).length) {
1609
- return { value, copy: { start, end } };
1610
- }
1611
- __name(copyLine, "copyLine");
1612
- function inputSummary(input) {
1613
- if (input === void 0)
1614
- return "";
1615
- const value = stringify(input).replace(/\s+/gu, " ");
1616
- return value === "{}" ? "" : truncateCharacters(value, 160);
1617
- }
1618
- __name(inputSummary, "inputSummary");
1619
- function stringify(value) {
1620
- if (typeof value === "string")
1621
- return value;
1622
- try {
1623
- return JSON.stringify(value, null, 2) ?? String(value);
1624
- } catch {
1625
- return String(value);
1626
- }
1627
- }
1628
- __name(stringify, "stringify");
1629
- function objectValue(value) {
1630
- return typeof value === "object" && value !== null ? value : void 0;
1631
- }
1632
- __name(objectValue, "objectValue");
1633
- function stringField(value, name) {
1634
- const object = objectValue(value);
1635
- return typeof object?.[name] === "string" ? object[name] : void 0;
1636
- }
1637
- __name(stringField, "stringField");
1638
- function numberField(value, name) {
1639
- const object = objectValue(value);
1640
- return typeof object?.[name] === "number" ? object[name] : void 0;
1641
- }
1642
- __name(numberField, "numberField");
1643
- function primitiveField(value, name) {
1644
- const object = objectValue(value);
1645
- const field = object?.[name];
1646
- return field === null || ["string", "number", "boolean"].includes(typeof field) ? field : void 0;
1647
- }
1648
- __name(primitiveField, "primitiveField");
1649
- function truncateCharacters(value, maximum) {
1650
- return value.length <= maximum ? value : `${value.slice(0, Math.max(0, maximum - 1)).replace(/[\uD800-\uDBFF]$/u, "")}\u2026`;
1651
- }
1652
- __name(truncateCharacters, "truncateCharacters");
1592
+ __name(moveTo, "moveTo");
1653
1593
 
1654
- // packages/ui/tui/dist/list-selection.js
1655
- var ListSelectionModel = class {
1594
+ // packages/ui/tui/dist/runtime.js
1595
+ var TuiRuntime = class {
1656
1596
  static {
1657
- __name(this, "ListSelectionModel");
1658
- }
1659
- source;
1660
- pageSize;
1661
- filter;
1662
- queryValue = "";
1663
- index;
1664
- constructor(items, options = {}) {
1665
- this.source = [...items];
1666
- this.pageSize = positiveInteger(options.pageSize ?? 10, "pageSize");
1667
- this.filter = options.filter;
1668
- this.index = clampListIndex(options.initialIndex ?? 0, this.items.length);
1597
+ __name(this, "TuiRuntime");
1669
1598
  }
1670
- get query() {
1671
- return this.queryValue;
1599
+ terminal;
1600
+ renderer;
1601
+ root;
1602
+ alternateScreen;
1603
+ onError;
1604
+ disposeKey;
1605
+ disposeResize;
1606
+ disposePointer;
1607
+ scheduled = false;
1608
+ running = false;
1609
+ disposed = false;
1610
+ constructor(options) {
1611
+ this.terminal = options.terminal;
1612
+ this.renderer = options.renderer;
1613
+ this.root = options.root;
1614
+ this.alternateScreen = options.alternateScreen ?? true;
1615
+ this.onError = options.onError ?? ((error) => {
1616
+ queueMicrotask(() => {
1617
+ throw error;
1618
+ });
1619
+ });
1672
1620
  }
1673
- get items() {
1674
- const normalized = this.queryValue.trim().toLowerCase();
1675
- return normalized === "" || this.filter === void 0 ? this.source : this.source.filter((item) => this.filter(item, normalized));
1621
+ get isRunning() {
1622
+ return this.running;
1676
1623
  }
1677
- get selectedIndex() {
1678
- return this.index;
1624
+ start() {
1625
+ this.assertActive();
1626
+ if (this.running)
1627
+ return;
1628
+ let terminalStarted = false;
1629
+ try {
1630
+ this.terminal.start();
1631
+ terminalStarted = true;
1632
+ if (this.alternateScreen)
1633
+ this.terminal.enterAlternateScreen?.();
1634
+ this.disposeKey = this.terminal.onKey(this.handleKey);
1635
+ this.disposeResize = this.terminal.onResize(this.handleResize);
1636
+ this.disposePointer = this.terminal.onPointer?.(this.handlePointer);
1637
+ this.running = true;
1638
+ this.renderNow();
1639
+ } catch (error) {
1640
+ this.release(terminalStarted);
1641
+ throw error;
1642
+ }
1679
1643
  }
1680
- get selected() {
1681
- return this.items[this.index];
1644
+ setRoot(root) {
1645
+ this.assertActive();
1646
+ if (this.root === root)
1647
+ return;
1648
+ this.root.dispose?.();
1649
+ this.root = root;
1650
+ this.renderer.invalidate();
1651
+ this.requestRender();
1682
1652
  }
1683
- setItems(items) {
1684
- this.source = [...items];
1685
- this.index = clampListIndex(this.index, this.items.length);
1653
+ requestRender() {
1654
+ if (!this.running || this.scheduled)
1655
+ return;
1656
+ this.scheduled = true;
1657
+ queueMicrotask(() => {
1658
+ this.scheduled = false;
1659
+ if (this.running)
1660
+ this.safeRender();
1661
+ });
1686
1662
  }
1687
- setQuery(query) {
1688
- this.queryValue = query;
1689
- this.index = 0;
1663
+ renderNow() {
1664
+ if (!this.running)
1665
+ return;
1666
+ this.renderer.render(this.root.render(this.terminal.size), this.terminal.size);
1690
1667
  }
1691
- appendQuery(text) {
1692
- if (text === "")
1668
+ stop() {
1669
+ if (this.disposed)
1693
1670
  return;
1694
- this.setQuery(this.queryValue + text);
1671
+ this.release(this.running);
1695
1672
  }
1696
- backspaceQuery() {
1697
- this.setQuery(removeLastCodePoint(this.queryValue));
1673
+ assertActive() {
1674
+ if (this.disposed)
1675
+ throw new Error("TuiRuntime has stopped. Create a new runtime and root component to start again.");
1698
1676
  }
1699
- clearQuery() {
1700
- this.setQuery("");
1677
+ release(terminalStarted) {
1678
+ this.disposed = true;
1679
+ this.running = false;
1680
+ this.scheduled = false;
1681
+ this.disposeKey?.();
1682
+ this.disposeResize?.();
1683
+ this.disposePointer?.();
1684
+ this.disposeKey = void 0;
1685
+ this.disposeResize = void 0;
1686
+ this.disposePointer = void 0;
1687
+ try {
1688
+ this.root.dispose?.();
1689
+ } finally {
1690
+ try {
1691
+ if (terminalStarted)
1692
+ this.renderer.dispose();
1693
+ } finally {
1694
+ this.terminal.close();
1695
+ }
1696
+ }
1701
1697
  }
1702
- move(action) {
1703
- const count = this.items.length;
1704
- if (count === 0) {
1705
- this.index = 0;
1706
- return;
1698
+ handleKey = /* @__PURE__ */ __name((stroke) => {
1699
+ try {
1700
+ const redraw = this.root.handleKeyResult ? this.root.handleKeyResult(stroke).redraw : this.root.handleKey(stroke);
1701
+ if (redraw)
1702
+ this.requestRender();
1703
+ } catch (error) {
1704
+ this.fail(error);
1707
1705
  }
1708
- switch (action) {
1709
- case "up":
1710
- this.index = this.index === 0 ? count - 1 : this.index - 1;
1711
- break;
1712
- case "down":
1713
- this.index = this.index === count - 1 ? 0 : this.index + 1;
1714
- break;
1715
- case "page-up":
1716
- this.index = Math.max(0, this.index - this.pageSize);
1717
- break;
1718
- case "page-down":
1719
- this.index = Math.min(count - 1, this.index + this.pageSize);
1720
- break;
1721
- case "home":
1722
- this.index = 0;
1723
- break;
1724
- case "end":
1725
- this.index = count - 1;
1726
- break;
1706
+ }, "handleKey");
1707
+ handlePointer = /* @__PURE__ */ __name((event) => {
1708
+ try {
1709
+ if (this.root.handlePointer?.(event))
1710
+ this.requestRender();
1711
+ } catch (error) {
1712
+ this.fail(error);
1713
+ }
1714
+ }, "handlePointer");
1715
+ handleResize = /* @__PURE__ */ __name(() => {
1716
+ this.renderer.invalidate();
1717
+ this.requestRender();
1718
+ }, "handleResize");
1719
+ safeRender() {
1720
+ try {
1721
+ this.renderNow();
1722
+ } catch (error) {
1723
+ this.fail(error);
1727
1724
  }
1728
1725
  }
1726
+ fail(error) {
1727
+ this.stop();
1728
+ this.onError(error);
1729
+ }
1729
1730
  };
1730
- function resolveListInput(items, input, value) {
1731
- const numeric = Number(input);
1732
- return Number.isSafeInteger(numeric) && numeric > 0 ? items[numeric - 1] : items.find((item) => value(item) === input);
1733
- }
1734
- __name(resolveListInput, "resolveListInput");
1735
- function printableKeyText(stroke) {
1736
- if (stroke.ctrl || stroke.alt || stroke.meta)
1737
- return void 0;
1738
- return stroke.text !== void 0 && stroke.text.length > 0 ? stroke.text : void 0;
1739
- }
1740
- __name(printableKeyText, "printableKeyText");
1741
- function clampListIndex(index, count) {
1742
- return count === 0 ? 0 : Math.min(Math.max(index, 0), count - 1);
1743
- }
1744
- __name(clampListIndex, "clampListIndex");
1745
- function removeLastCodePoint(value) {
1746
- return [...value].slice(0, -1).join("");
1747
- }
1748
- __name(removeLastCodePoint, "removeLastCodePoint");
1749
- function positiveInteger(value, name) {
1750
- if (!Number.isSafeInteger(value) || value <= 0) {
1751
- throw new RangeError(`${name} must be a positive safe integer`);
1752
- }
1753
- return value;
1754
- }
1755
- __name(positiveInteger, "positiveInteger");
1756
1731
 
1757
- // packages/ui/tui/dist/workspace-diff.js
1758
- var WorkspaceDiffViewer = class {
1732
+ // packages/ui/tui/dist/select-list.js
1733
+ var SELECT_LIST_KEYBINDINGS = [
1734
+ { context: "select", keys: "up", action: "list.up" },
1735
+ { context: "select", keys: "down", action: "list.down" },
1736
+ { context: "select", keys: "pageup", action: "list.pageUp" },
1737
+ { context: "select", keys: "pagedown", action: "list.pageDown" },
1738
+ { context: "select", keys: "home", action: "list.home" },
1739
+ { context: "select", keys: "end", action: "list.end" },
1740
+ { context: "select", keys: "enter", action: "list.accept" },
1741
+ { context: "select", keys: "escape", action: "list.cancel" }
1742
+ ];
1743
+ var SelectList = class {
1759
1744
  static {
1760
- __name(this, "WorkspaceDiffViewer");
1745
+ __name(this, "SelectList");
1761
1746
  }
1762
- diff;
1763
1747
  options;
1764
- selection;
1765
- mode = "files";
1748
+ items;
1749
+ index;
1766
1750
  offset = 0;
1767
- pageSize = 10;
1768
- query = "";
1769
- notice = "";
1770
- pending = Promise.resolve();
1771
- busy = false;
1772
- constructor(diff, options) {
1773
- this.diff = diff;
1751
+ pageSize = 1;
1752
+ focused = false;
1753
+ keymap;
1754
+ constructor(items, options = {}) {
1774
1755
  this.options = options;
1775
- this.selection = new ListSelectionModel(diff.files, { pageSize: 10 });
1756
+ this.items = [...items];
1757
+ this.index = firstEnabled(this.items, options.selectedIndex ?? 0);
1758
+ this.keymap = new Keymap(mergeKeyBindings(SELECT_LIST_KEYBINDINGS, options.keybindings), {
1759
+ actions: SELECT_LIST_KEYBINDINGS.map((binding) => binding.action)
1760
+ });
1776
1761
  }
1777
- get selectedFile() {
1778
- return this.selection.selected;
1762
+ get selectedIndex() {
1763
+ return this.index;
1779
1764
  }
1780
- get scrollOffset() {
1781
- return this.offset;
1765
+ get selectedItem() {
1766
+ return this.index < 0 ? void 0 : this.items[this.index];
1782
1767
  }
1783
- waitForPending() {
1784
- return this.pending;
1768
+ setItems(items) {
1769
+ this.items = [...items];
1770
+ this.index = firstEnabled(this.items, Math.max(0, this.index));
1771
+ this.offset = 0;
1772
+ }
1773
+ setFocused(focused) {
1774
+ if (focused !== this.focused)
1775
+ this.keymap.reset();
1776
+ this.focused = focused;
1785
1777
  }
1786
1778
  handleKey(stroke) {
1787
- if (this.busy)
1788
- return true;
1789
- if (stroke.ctrl && stroke.key === "c") {
1790
- this.options.onClose();
1791
- return true;
1792
- }
1793
- const commandKey = !stroke.ctrl && !stroke.alt && !stroke.meta;
1794
- if (commandKey && this.mode !== "search" && this.diff.restorePreviewId && stroke.key === "y" && this.options.onApply) {
1795
- this.perform(async () => {
1796
- await this.options.onApply(this.diff.restorePreviewId);
1797
- this.options.onClose();
1798
- });
1799
- return true;
1800
- }
1801
- if (commandKey && this.mode !== "search" && stroke.key === "r" && !this.diff.restorePreviewId && this.selection.selected && this.options.onRestore) {
1802
- const path = this.selection.selected.path;
1803
- this.perform(async () => {
1804
- this.diff = await this.options.onRestore(path);
1805
- this.selection.setItems(this.diff.files);
1806
- this.selection.move("home");
1807
- this.mode = "patch";
1808
- this.offset = 0;
1809
- this.query = "";
1810
- });
1811
- return true;
1812
- }
1813
- if (this.mode === "search") {
1814
- if (stroke.key === "escape") {
1815
- this.mode = "patch";
1816
- this.query = "";
1817
- } else if (stroke.key === "enter") {
1818
- this.mode = "patch";
1819
- this.find(false);
1820
- } else if (stroke.key === "backspace")
1821
- this.query = removeLastCodePoint(this.query);
1822
- else if (stroke.ctrl && stroke.key === "u")
1823
- this.query = "";
1824
- else {
1825
- const text = printableKeyText(stroke);
1826
- if (text)
1827
- this.query += text;
1828
- }
1829
- return true;
1830
- }
1831
- if (stroke.key === "escape") {
1832
- if (this.mode === "patch") {
1833
- this.mode = "files";
1834
- this.offset = 0;
1835
- } else
1836
- this.options.onClose();
1837
- return true;
1838
- }
1839
- if (this.mode === "files") {
1840
- const action = navigation(stroke.key);
1841
- if (action)
1842
- this.selection.move(action);
1843
- if (stroke.key === "enter" && this.selection.selected) {
1844
- this.mode = "patch";
1845
- this.offset = 0;
1846
- this.query = "";
1779
+ if (!this.focused)
1780
+ return false;
1781
+ const result = this.keymap.resolve(stroke, ["select"]);
1782
+ if (result.type !== "action")
1783
+ return result.type === "pending";
1784
+ return this.performAction(result.action);
1785
+ }
1786
+ performAction(action) {
1787
+ switch (action) {
1788
+ case "list.up":
1789
+ this.move(-1);
1790
+ return true;
1791
+ case "list.down":
1792
+ this.move(1);
1793
+ return true;
1794
+ case "list.pageUp":
1795
+ this.move(-this.pageSize);
1796
+ return true;
1797
+ case "list.pageDown":
1798
+ this.move(this.pageSize);
1799
+ return true;
1800
+ case "list.home":
1801
+ this.moveTo(firstEnabled(this.items, 0));
1802
+ return true;
1803
+ case "list.end":
1804
+ this.moveTo(lastEnabled(this.items));
1805
+ return true;
1806
+ case "list.accept": {
1807
+ const item = this.selectedItem;
1808
+ if (item === void 0)
1809
+ return false;
1810
+ this.options.onSelect?.(item, this.index);
1811
+ return true;
1847
1812
  }
1848
- return true;
1849
- }
1850
- const file = this.selection.selected;
1851
- const lines = file?.patch.split("\n") ?? [];
1852
- const maximum = Math.max(0, lines.length - this.pageSize);
1853
- if (stroke.key === "up")
1854
- this.offset = Math.max(0, this.offset - 1);
1855
- else if (stroke.key === "down")
1856
- this.offset = Math.min(maximum, this.offset + 1);
1857
- else if (stroke.key === "pageup")
1858
- this.offset = Math.max(0, this.offset - this.pageSize);
1859
- else if (stroke.key === "pagedown")
1860
- this.offset = Math.min(maximum, this.offset + this.pageSize);
1861
- else if (stroke.key === "home")
1862
- this.offset = 0;
1863
- else if (stroke.key === "end")
1864
- this.offset = maximum;
1865
- else if (stroke.key === "/" || stroke.text === "/")
1866
- this.mode = "search";
1867
- else if (stroke.key === "n")
1868
- this.find(true);
1869
- else if (stroke.key === "]" || stroke.text === "]") {
1870
- const changes = lines.flatMap((line, index) => line.startsWith("@@") ? [index] : []);
1871
- this.offset = changes.find((index) => index > this.offset) ?? changes[0] ?? this.offset;
1813
+ case "list.cancel":
1814
+ this.options.onCancel?.();
1815
+ return this.options.onCancel !== void 0;
1816
+ default:
1817
+ return false;
1872
1818
  }
1819
+ }
1820
+ handlePointer(event) {
1821
+ if (event.button !== 0 || event.type !== "down" || event.y < 0 || event.y >= this.pageSize)
1822
+ return false;
1823
+ const index = this.offset + event.y;
1824
+ if (this.items[index] === void 0 || this.items[index].disabled)
1825
+ return false;
1826
+ this.moveTo(index);
1873
1827
  return true;
1874
1828
  }
1875
1829
  render(size) {
1876
- const theme = this.options.theme ?? DEFAULT_DARK_THEME;
1877
- this.pageSize = Math.max(1, size.height - 5);
1878
- const totals = this.diff.files.reduce((value, file) => ({ additions: value.additions + file.additions, deletions: value.deletions + file.deletions }), { additions: 0, deletions: 0 });
1879
- const header2 = [sanitizeTerminalText(this.diff.title), `${this.diff.from?.slice(0, 12) ?? "\u521D\u59CB\u7248\u672C"} \u2192 ${this.diff.uncommitted ? "\u5F53\u524D\u672A\u63D0\u4EA4\u53D8\u5316" : this.diff.to?.slice(0, 12) ?? "\u76EE\u6807\u7248\u672C"} \xB7 ${this.diff.files.length} \u4E2A\u6587\u4EF6 \xB7 +${totals.additions} -${totals.deletions}`, ""];
1880
- let body;
1881
- if (this.mode === "files") {
1882
- const start = Math.floor(this.selection.selectedIndex / this.pageSize) * this.pageSize;
1883
- body = this.diff.files.slice(start, start + this.pageSize).map((file, index) => styleText(`${start + index === this.selection.selectedIndex ? "\u25B8" : " "} ${sanitizeTerminalText(file.path)} \xB7 ${file.status} \xB7 ${file.binary ? "\u4E8C\u8FDB\u5236\u6587\u4EF6" : `+${file.additions} -${file.deletions}`}`, start + index === this.selection.selectedIndex ? theme.accent : theme.text));
1884
- if (!body.length)
1885
- body.push("\u6CA1\u6709\u6587\u4EF6\u53D8\u5316\u3002");
1886
- } else {
1887
- const file = this.selection.selected;
1888
- body = file?.binary ? ["\u4E8C\u8FDB\u5236\u6587\u4EF6\u65E0\u6CD5\u663E\u793A\u6587\u672C diff\u3002"] : renderDiff(file?.patch ?? "", theme).slice(this.offset, this.offset + this.pageSize).map((line) => line.value);
1889
- header2[2] = `${sanitizeTerminalText(file?.path ?? "")} \xB7 \u7B2C ${this.offset + 1} \u884C`;
1830
+ if (this.items.length === 0) {
1831
+ return {
1832
+ lines: [sliceAnsi(sanitizeTerminalText(this.options.emptyLabel ?? "No items"), 0, size.width)]
1833
+ };
1890
1834
  }
1891
- const footer = this.diff.restorePreviewId ? "\u6062\u590D\u9884\u89C8 \xB7 Y \u786E\u8BA4\u6062\u590D\u6587\u4EF6 \xB7 Esc \u8FD4\u56DE\u6216\u53D6\u6D88" : this.mode === "files" ? `\u2191\u2193 \u9009\u62E9\u6587\u4EF6 \xB7 Enter \u67E5\u770B diff${this.options.onRestore ? " \xB7 R \u9884\u89C8\u6062\u590D" : ""} \xB7 Esc \u5173\u95ED` : this.mode === "search" ? `\u641C\u7D22\uFF1A${sanitizeTerminalText(this.query)} \xB7 Enter \u67E5\u627E \xB7 Esc \u53D6\u6D88` : `\u2191\u2193 \u6EDA\u52A8 \xB7 PgUp/PgDn \u7FFB\u9875 \xB7 / \u641C\u7D22 \xB7 N \u4E0B\u4E00\u5904\u5339\u914D \xB7 ] \u4E0B\u4E00\u5904\u4FEE\u6539${this.options.onRestore ? " \xB7 R \u9884\u89C8\u6062\u590D" : ""} \xB7 Esc \u6587\u4EF6\u5217\u8868`;
1892
- return new Text([...header2, ...body, footer, this.busy ? "\u6B63\u5728\u5904\u7406\u6587\u4EF6\u7248\u672C\u2026" : sanitizeTerminalText(this.notice)].join("\n"), { wrap: false }).render(size);
1893
- }
1894
- find(next) {
1895
- if (!this.query)
1896
- return;
1897
- const lines = this.selection.selected?.patch.split("\n") ?? [];
1898
- const matches = lines.flatMap((line, index) => line.toLocaleLowerCase().includes(this.query.toLocaleLowerCase()) ? [index] : []);
1899
- const target = (next ? matches.find((index) => index > this.offset) : void 0) ?? matches[0];
1900
- if (target === void 0)
1901
- this.notice = "\u6CA1\u6709\u5339\u914D\u7684\u5185\u5BB9\u3002";
1902
- else {
1903
- this.offset = target;
1904
- this.notice = "";
1835
+ this.pageSize = size.height;
1836
+ if (this.index >= 0) {
1837
+ if (this.index < this.offset)
1838
+ this.offset = this.index;
1839
+ if (this.index >= this.offset + size.height) {
1840
+ this.offset = this.index - size.height + 1;
1841
+ }
1905
1842
  }
1843
+ const maximumOffset = Math.max(0, this.items.length - size.height);
1844
+ this.offset = clamp(this.offset, 0, maximumOffset);
1845
+ return {
1846
+ lines: this.items.slice(this.offset, this.offset + size.height).map((item, relativeIndex) => {
1847
+ const index = this.offset + relativeIndex;
1848
+ const marker = index === this.index ? this.focused ? "> " : "\xB7 " : " ";
1849
+ const disabled = item.disabled === true ? " (disabled)" : "";
1850
+ const plainDescription = item.description === void 0 ? "" : ` \u2014 ${singleLine(item.description)}`;
1851
+ if (index === this.index) {
1852
+ const clipped = sliceAnsi(`${marker}${singleLine(item.label)}${disabled}${plainDescription}`, 0, size.width);
1853
+ const padded = `${clipped}${" ".repeat(Math.max(0, size.width - stringWidth(clipped)))}`;
1854
+ return styleText(padded, this.options.selectedStyle);
1855
+ }
1856
+ const description = styleText(plainDescription, this.options.descriptionStyle);
1857
+ const line = `${styleText(marker, this.options.markerStyle)}${singleLine(item.label)}${disabled}${description}`;
1858
+ return sliceAnsi(styleText(line, item.disabled === true ? this.options.disabledStyle : void 0), 0, size.width);
1859
+ })
1860
+ };
1906
1861
  }
1907
- perform(work) {
1908
- this.busy = true;
1909
- this.pending = work().catch((error) => {
1910
- this.notice = error instanceof Error ? error.message : "\u6587\u4EF6\u7248\u672C\u64CD\u4F5C\u5931\u8D25\u3002";
1911
- }).finally(() => {
1912
- this.busy = false;
1913
- this.options.onInvalidate?.();
1914
- });
1915
- this.options.onInvalidate?.();
1862
+ move(offset) {
1863
+ if (this.index < 0 || this.items.length === 0)
1864
+ return false;
1865
+ const direction = offset < 0 ? -1 : 1;
1866
+ let remaining = Math.max(1, Math.abs(offset));
1867
+ let next = this.index;
1868
+ while (remaining > 0) {
1869
+ const candidate = nextEnabled(this.items, next, direction);
1870
+ if (candidate === next)
1871
+ break;
1872
+ next = candidate;
1873
+ remaining -= 1;
1874
+ }
1875
+ return this.moveTo(next);
1876
+ }
1877
+ moveTo(index) {
1878
+ if (index < 0 || index === this.index)
1879
+ return false;
1880
+ this.index = index;
1881
+ return true;
1916
1882
  }
1917
1883
  };
1918
- function navigation(key) {
1919
- if (key === "up" || key === "down" || key === "home" || key === "end")
1920
- return key;
1921
- if (key === "pageup")
1922
- return "page-up";
1923
- if (key === "pagedown")
1924
- return "page-down";
1925
- return void 0;
1926
- }
1927
- __name(navigation, "navigation");
1928
- function workspaceGitLabel(workspace) {
1929
- if (workspace.status === "error")
1930
- return `Git \u9519\u8BEF${workspace.error ? `\uFF1A${sanitizeTerminalText(workspace.error)}` : ""}`;
1931
- if (workspace.status === "initializing")
1932
- return "Git \u5C1A\u672A\u51C6\u5907";
1933
- const version = workspace.detached ? `detached HEAD \xB7 ${workspace.commit?.slice(0, 12) ?? "\u65E0 commit"}` : workspace.branch ?? "Git \u5C1A\u65E0 commit";
1934
- return sanitizeTerminalText(`${version}${workspace.autoCommit === false ? " \xB7 \u81EA\u52A8\u63D0\u4EA4\u5173\u95ED" : ""}`);
1935
- }
1936
- __name(workspaceGitLabel, "workspaceGitLabel");
1937
-
1938
- // packages/ui/tui/dist/component.js
1939
- function placeImages(images, y2, height) {
1940
- return (images ?? []).map((image) => ({ ...image, y: image.y + y2 })).filter((image) => image.y >= 0 && image.y + image.rows <= height);
1941
- }
1942
- __name(placeImages, "placeImages");
1943
- function assertRenderSize(size) {
1944
- if (!Number.isInteger(size.width) || size.width < 1) {
1945
- throw new RangeError("Render width must be a positive integer");
1884
+ function firstEnabled(items, start) {
1885
+ for (let index = clamp(start, 0, Math.max(0, items.length - 1)); index < items.length; index++) {
1886
+ if (items[index].disabled !== true)
1887
+ return index;
1946
1888
  }
1947
- if (!Number.isInteger(size.height) || size.height < 1) {
1948
- throw new RangeError("Render height must be a positive integer");
1889
+ for (let index = 0; index < start && index < items.length; index++) {
1890
+ if (items[index].disabled !== true)
1891
+ return index;
1949
1892
  }
1893
+ return -1;
1950
1894
  }
1951
- __name(assertRenderSize, "assertRenderSize");
1952
-
1953
- // packages/ui/tui/dist/screen-buffer.js
1954
- var ScreenBuffer = class _ScreenBuffer {
1955
- static {
1956
- __name(this, "ScreenBuffer");
1957
- }
1958
- width;
1959
- height;
1960
- lines;
1961
- cursor;
1962
- constructor(size, lines, cursor) {
1963
- this.width = size.width;
1964
- this.height = size.height;
1965
- this.lines = lines;
1966
- this.cursor = cursor;
1967
- }
1968
- static from(result, size) {
1969
- assertRenderSize(size);
1970
- const lines = result.lines.slice(0, size.height).map((line) => normalizeLine(line, size.width));
1971
- const cursor = normalizeCursor(result.cursor, size);
1972
- return new _ScreenBuffer(size, lines, cursor);
1973
- }
1974
- lineAt(row) {
1975
- return this.lines[row] ?? "";
1895
+ __name(firstEnabled, "firstEnabled");
1896
+ function lastEnabled(items) {
1897
+ for (let index = items.length - 1; index >= 0; index--) {
1898
+ if (items[index].disabled !== true)
1899
+ return index;
1976
1900
  }
1977
- };
1978
- function normalizeLine(line, width) {
1979
- if (line.includes("\n") || line.includes("\r")) {
1980
- throw new Error("A rendered screen line cannot contain a newline");
1901
+ return -1;
1902
+ }
1903
+ __name(lastEnabled, "lastEnabled");
1904
+ function nextEnabled(items, current, direction) {
1905
+ for (let index = current + direction; index >= 0 && index < items.length; index += direction) {
1906
+ if (items[index].disabled !== true)
1907
+ return index;
1981
1908
  }
1982
- return stringWidth(line) <= width ? line : sliceAnsi(line, 0, width);
1909
+ return current;
1983
1910
  }
1984
- __name(normalizeLine, "normalizeLine");
1985
- function normalizeCursor(cursor, size) {
1986
- if (cursor === void 0)
1987
- return void 0;
1988
- const y2 = clampInteger(cursor.y, 0, Math.max(0, size.height - 1));
1989
- const x2 = clampInteger(cursor.x, 0, size.width - 1);
1990
- return { x: x2, y: y2, visible: cursor.visible ?? true };
1911
+ __name(nextEnabled, "nextEnabled");
1912
+ function singleLine(value) {
1913
+ return sanitizeTerminalText(value).replace(/\s+/gu, " ").trim();
1991
1914
  }
1992
- __name(normalizeCursor, "normalizeCursor");
1993
- function clampInteger(value, minimum, maximum) {
1994
- if (!Number.isFinite(value))
1995
- return minimum;
1915
+ __name(singleLine, "singleLine");
1916
+ function clamp(value, minimum, maximum) {
1996
1917
  return Math.min(maximum, Math.max(minimum, Math.trunc(value)));
1997
1918
  }
1998
- __name(clampInteger, "clampInteger");
1999
-
2000
- // packages/ui/tui/dist/renderer.js
2001
- var FullscreenRenderer = class {
2002
- static {
2003
- __name(this, "FullscreenRenderer");
2004
- }
2005
- terminal;
2006
- previous;
2007
- images = [];
2008
- hideCursorByDefault;
2009
- constructor(terminal, options = {}) {
2010
- this.terminal = terminal;
2011
- this.hideCursorByDefault = options.hideCursorByDefault ?? true;
2012
- }
2013
- render(result, size) {
2014
- const next = ScreenBuffer.from(result, size);
2015
- const previous = this.previous;
2016
- const images = placeImages(result.images, 0, size.height);
2017
- const imagesChanged = images.length !== this.images.length || images.some((image, index) => {
2018
- const old = this.images[index];
2019
- return !old || image.id !== old.id || image.y !== old.y || image.x !== old.x || image.rows !== old.rows || image.columns !== old.columns || image.protocol !== old.protocol || image.protocol === "sixel" && old.protocol === "sixel" && image.sixel !== old.sixel;
2020
- });
2021
- const resized = previous !== void 0 && (previous.width !== next.width || previous.height !== next.height);
2022
- let output = "\x1B[?25l";
2023
- if (previous === void 0 || resized || imagesChanged) {
2024
- if (this.images.some((image) => image.protocol === "kitty"))
2025
- output += "\x1B_Ga=d,d=A,q=2\x1B\\";
2026
- output += "\x1B[2J";
2027
- }
2028
- const rowCount = previous === void 0 || resized ? next.lines.length : Math.max(next.lines.length, previous.lines.length);
2029
- const erasedRows = /* @__PURE__ */ new Set();
2030
- for (let row = 0; row < rowCount; row++) {
2031
- const line = next.lineAt(row);
2032
- if (!resized && !imagesChanged && previous?.lineAt(row) === line)
2033
- continue;
2034
- output += moveTo(row, 0);
2035
- output += `\x1B[2K${line}\x1B[0m`;
2036
- erasedRows.add(row);
2037
- }
2038
- for (const image of images) {
2039
- const erased = image.protocol === "sixel" && Array.from({ length: image.rows }, (_2, index) => image.y + index).some((row) => erasedRows.has(row));
2040
- if (imagesChanged || resized || previous === void 0 || erased)
2041
- output += moveTo(image.y, image.x) + encodeImage(image);
2042
- }
2043
- this.images = images;
2044
- const cursor = next.cursor;
2045
- if (cursor !== void 0) {
2046
- output += moveTo(cursor.y, cursor.x);
2047
- output += cursor.visible === false ? "\x1B[?25l" : "\x1B[?25h";
2048
- } else if (this.hideCursorByDefault) {
2049
- output += "\x1B[?25l";
2050
- } else {
2051
- output += "\x1B[?25h";
2052
- }
2053
- this.terminal.write(output);
2054
- this.previous = next;
2055
- }
2056
- invalidate() {
2057
- this.previous = void 0;
2058
- }
2059
- dispose(options = {}) {
2060
- this.previous = void 0;
2061
- this.terminal.write(`${this.images.some((image) => image.protocol === "kitty") ? "\x1B_Ga=d,d=A,q=2\x1B\\" : ""}${options.clear === true || this.images.length ? "\x1B[2J\x1B[H" : ""}\x1B[0m\x1B[?25h`);
2062
- this.images = [];
2063
- }
2064
- };
2065
- function moveTo(row, column) {
2066
- return `\x1B[${row + 1};${column + 1}H`;
2067
- }
2068
- __name(moveTo, "moveTo");
1919
+ __name(clamp, "clamp");
2069
1920
 
2070
- // packages/ui/tui/dist/runtime.js
2071
- var TuiRuntime = class {
1921
+ // packages/ui/tui/dist/terminal-driver.js
1922
+ var import_tty_events = __toESM(require_index_min(), 1);
1923
+ import { emitKeypressEvents } from "node:readline";
1924
+ import { PassThrough } from "node:stream";
1925
+ var BRACKETED_PASTE_START = Buffer.from("\x1B[200~");
1926
+ var BRACKETED_PASTE_END = Buffer.from("\x1B[201~");
1927
+ var ESCAPE_PREFIX_TIMEOUT_MS = 25;
1928
+ var NodeTerminalDriver = class {
2072
1929
  static {
2073
- __name(this, "TuiRuntime");
1930
+ __name(this, "NodeTerminalDriver");
2074
1931
  }
2075
- terminal;
2076
- renderer;
2077
- root;
2078
- alternateScreen;
2079
- onError;
2080
- disposeKey;
2081
- disposeResize;
2082
- disposePointer;
2083
- scheduled = false;
2084
- running = false;
2085
- disposed = false;
2086
- constructor(options) {
2087
- this.terminal = options.terminal;
2088
- this.renderer = options.renderer;
2089
- this.root = options.root;
2090
- this.alternateScreen = options.alternateScreen ?? true;
2091
- this.onError = options.onError ?? ((error) => {
2092
- queueMicrotask(() => {
2093
- throw error;
2094
- });
1932
+ imageSupport;
1933
+ input;
1934
+ output;
1935
+ requireTTY;
1936
+ decodedInput = new PassThrough();
1937
+ pointerInput = new PassThrough();
1938
+ pointerDecoder;
1939
+ inputDecoder = new BracketedPasteDecoder((value) => this.pointerInput.write(value), (value) => this.emitPaste(value));
1940
+ keyListeners = /* @__PURE__ */ new Set();
1941
+ resizeListeners = /* @__PURE__ */ new Set();
1942
+ pointerListeners = /* @__PURE__ */ new Set();
1943
+ started = false;
1944
+ alternateScreen = false;
1945
+ previousRawMode = false;
1946
+ inputWasPaused = true;
1947
+ keypressInitialized = false;
1948
+ bracketedPaste = false;
1949
+ constructor(options = {}) {
1950
+ this.input = options.input ?? process.stdin;
1951
+ this.output = options.output ?? process.stdout;
1952
+ this.requireTTY = options.requireTTY ?? true;
1953
+ this.imageSupport = new TerminalImageSupport(this.output);
1954
+ this.imageSupport.onChange(() => {
1955
+ for (const listener of this.resizeListeners)
1956
+ listener(this.size);
2095
1957
  });
2096
1958
  }
2097
- get isRunning() {
2098
- return this.running;
1959
+ get size() {
1960
+ return {
1961
+ width: Math.max(1, this.output.columns ?? 80),
1962
+ height: Math.max(1, this.output.rows ?? 24)
1963
+ };
2099
1964
  }
2100
1965
  start() {
2101
- this.assertActive();
2102
- if (this.running)
2103
- return;
2104
- let terminalStarted = false;
2105
- try {
2106
- this.terminal.start();
2107
- terminalStarted = true;
2108
- if (this.alternateScreen)
2109
- this.terminal.enterAlternateScreen?.();
2110
- this.disposeKey = this.terminal.onKey(this.handleKey);
2111
- this.disposeResize = this.terminal.onResize(this.handleResize);
2112
- this.disposePointer = this.terminal.onPointer?.(this.handlePointer);
2113
- this.running = true;
2114
- this.renderNow();
2115
- } catch (error) {
2116
- this.release(terminalStarted);
2117
- throw error;
2118
- }
2119
- }
2120
- setRoot(root) {
2121
- this.assertActive();
2122
- if (this.root === root)
2123
- return;
2124
- this.root.dispose?.();
2125
- this.root = root;
2126
- this.renderer.invalidate();
2127
- this.requestRender();
2128
- }
2129
- requestRender() {
2130
- if (!this.running || this.scheduled)
2131
- return;
2132
- this.scheduled = true;
2133
- queueMicrotask(() => {
2134
- this.scheduled = false;
2135
- if (this.running)
2136
- this.safeRender();
2137
- });
2138
- }
2139
- renderNow() {
2140
- if (!this.running)
2141
- return;
2142
- this.renderer.render(this.root.render(this.terminal.size), this.terminal.size);
2143
- }
2144
- stop() {
2145
- if (this.disposed)
2146
- return;
2147
- this.release(this.running);
2148
- }
2149
- assertActive() {
2150
- if (this.disposed)
2151
- throw new Error("TuiRuntime has stopped. Create a new runtime and root component to start again.");
2152
- }
2153
- release(terminalStarted) {
2154
- this.disposed = true;
2155
- this.running = false;
2156
- this.scheduled = false;
2157
- this.disposeKey?.();
2158
- this.disposeResize?.();
2159
- this.disposePointer?.();
2160
- this.disposeKey = void 0;
2161
- this.disposeResize = void 0;
2162
- this.disposePointer = void 0;
2163
- try {
2164
- this.root.dispose?.();
2165
- } finally {
2166
- try {
2167
- if (terminalStarted)
2168
- this.renderer.dispose();
2169
- } finally {
2170
- this.terminal.close();
2171
- }
2172
- }
2173
- }
2174
- handleKey = /* @__PURE__ */ __name((stroke) => {
2175
- try {
2176
- const redraw = this.root.handleKeyResult ? this.root.handleKeyResult(stroke).redraw : this.root.handleKey(stroke);
2177
- if (redraw)
2178
- this.requestRender();
2179
- } catch (error) {
2180
- this.fail(error);
2181
- }
2182
- }, "handleKey");
2183
- handlePointer = /* @__PURE__ */ __name((event) => {
2184
- try {
2185
- if (this.root.handlePointer?.(event))
2186
- this.requestRender();
2187
- } catch (error) {
2188
- this.fail(error);
2189
- }
2190
- }, "handlePointer");
2191
- handleResize = /* @__PURE__ */ __name(() => {
2192
- this.renderer.invalidate();
2193
- this.requestRender();
2194
- }, "handleResize");
2195
- safeRender() {
2196
- try {
2197
- this.renderNow();
2198
- } catch (error) {
2199
- this.fail(error);
2200
- }
2201
- }
2202
- fail(error) {
2203
- this.stop();
2204
- this.onError(error);
2205
- }
2206
- };
2207
-
2208
- // packages/ui/tui/dist/terminal-driver.js
2209
- var import_tty_events = __toESM(require_index_min(), 1);
2210
- import { emitKeypressEvents } from "node:readline";
2211
- import { PassThrough } from "node:stream";
2212
- var BRACKETED_PASTE_START = Buffer.from("\x1B[200~");
2213
- var BRACKETED_PASTE_END = Buffer.from("\x1B[201~");
2214
- var ESCAPE_PREFIX_TIMEOUT_MS = 25;
2215
- var NodeTerminalDriver = class {
2216
- static {
2217
- __name(this, "NodeTerminalDriver");
2218
- }
2219
- imageSupport;
2220
- input;
2221
- output;
2222
- requireTTY;
2223
- decodedInput = new PassThrough();
2224
- pointerInput = new PassThrough();
2225
- pointerDecoder;
2226
- inputDecoder = new BracketedPasteDecoder((value) => this.pointerInput.write(value), (value) => this.emitPaste(value));
2227
- keyListeners = /* @__PURE__ */ new Set();
2228
- resizeListeners = /* @__PURE__ */ new Set();
2229
- pointerListeners = /* @__PURE__ */ new Set();
2230
- started = false;
2231
- alternateScreen = false;
2232
- previousRawMode = false;
2233
- inputWasPaused = true;
2234
- keypressInitialized = false;
2235
- bracketedPaste = false;
2236
- constructor(options = {}) {
2237
- this.input = options.input ?? process.stdin;
2238
- this.output = options.output ?? process.stdout;
2239
- this.requireTTY = options.requireTTY ?? true;
2240
- this.imageSupport = new TerminalImageSupport(this.output);
2241
- this.imageSupport.onChange(() => {
2242
- for (const listener of this.resizeListeners)
2243
- listener(this.size);
2244
- });
2245
- }
2246
- get size() {
2247
- return {
2248
- width: Math.max(1, this.output.columns ?? 80),
2249
- height: Math.max(1, this.output.rows ?? 24)
2250
- };
2251
- }
2252
- start() {
2253
- if (this.started)
1966
+ if (this.started)
2254
1967
  return;
2255
1968
  if (this.requireTTY && (this.input.isTTY !== true || this.output.isTTY !== true)) {
2256
1969
  throw new Error("The TUI requires an interactive terminal");
@@ -2474,6 +2187,9 @@ function markerPrefixLength(value, marker) {
2474
2187
  __name(markerPrefixLength, "markerPrefixLength");
2475
2188
 
2476
2189
  // packages/ui/tui/dist/agent/transcript-store.js
2190
+ import { omitUndefined as omitUndefined2 } from "@sortedyuan/may/core";
2191
+ import { isSessionRunTerminalEvent, SessionTranscriptReader, sessionToolFailureStatus } from "@sortedyuan/may/session";
2192
+ import { decodeToolChangePreviewPresentation } from "@sortedyuan/coding-tools/change-preview";
2477
2193
  var TranscriptStore = class {
2478
2194
  static {
2479
2195
  __name(this, "TranscriptStore");
@@ -2483,7 +2199,9 @@ var TranscriptStore = class {
2483
2199
  localSequence = 0;
2484
2200
  currentSessionId;
2485
2201
  latestReplyId;
2486
- steeringInputs = /* @__PURE__ */ new Map();
2202
+ transcriptReader = new SessionTranscriptReader();
2203
+ approvalTools = /* @__PURE__ */ new Map();
2204
+ cancelledApprovals = /* @__PURE__ */ new Set();
2487
2205
  /** 当前轮次完成后可供阅读的最终正文。 */
2488
2206
  get latestReply() {
2489
2207
  const item = this.values.find((item2) => item2.id === this.latestReplyId);
@@ -2502,7 +2220,9 @@ var TranscriptStore = class {
2502
2220
  reset(sessionId) {
2503
2221
  this.values = [];
2504
2222
  this.latestReplyId = void 0;
2505
- this.steeringInputs.clear();
2223
+ this.transcriptReader.reset();
2224
+ this.approvalTools.clear();
2225
+ this.cancelledApprovals.clear();
2506
2226
  this.currentSessionId = sessionId;
2507
2227
  this.changed();
2508
2228
  }
@@ -2529,7 +2249,9 @@ var TranscriptStore = class {
2529
2249
  loadHistory(events) {
2530
2250
  this.values = [];
2531
2251
  this.latestReplyId = void 0;
2532
- this.steeringInputs.clear();
2252
+ this.transcriptReader.reset();
2253
+ this.approvalTools.clear();
2254
+ this.cancelledApprovals.clear();
2533
2255
  this.currentSessionId = events[0]?.sessionId ?? this.currentSessionId;
2534
2256
  for (const event of events)
2535
2257
  this.projectSessionEvent(event);
@@ -2611,9 +2333,10 @@ var TranscriptStore = class {
2611
2333
  case "tool.failed":
2612
2334
  this.updateTool(event.runId, event.call.id, (item) => ({
2613
2335
  ...item,
2614
- status: "failed",
2336
+ status: sessionToolFailureStatus(event.error, this.cancelledApprovals.has(item.id)),
2615
2337
  error: event.error.message
2616
2338
  }), event.step, event.call, event.timestamp);
2339
+ this.cancelledApprovals.delete(toolId(event.runId, event.call.id));
2617
2340
  break;
2618
2341
  case "run.failed":
2619
2342
  this.appendNoticeItem(`run:${event.runId}:failed`, "error", `Run failed: ${event.error.message}`, event.timestamp);
@@ -2624,24 +2347,26 @@ var TranscriptStore = class {
2624
2347
  case "step.started":
2625
2348
  case "step.completed":
2626
2349
  case "run.yielded":
2350
+ case "input.generated":
2351
+ case "run.budget.exceeded":
2627
2352
  break;
2628
2353
  }
2354
+ if (isSessionRunTerminalEvent(event))
2355
+ this.settle(event.runId);
2629
2356
  }
2630
2357
  projectPermissionEvent(event) {
2631
2358
  if (event.type === "approval.requested") {
2359
+ this.approvalTools.set(event.request.id, toolId(event.request.context.runId, event.request.context.toolCallId));
2632
2360
  this.append(approvalItem(event.request, event.timestamp));
2633
2361
  return;
2634
2362
  }
2635
2363
  if (event.type !== "approval.resolved" && event.type !== "approval.cancelled")
2636
2364
  return;
2365
+ this.settleApproval(event);
2637
2366
  this.replace(`approval:${event.requestId}`, (item) => {
2638
2367
  if (item.kind !== "approval")
2639
2368
  return item;
2640
- return event.type === "approval.resolved" ? { ...item, status: "resolved", decision: event.decision } : {
2641
- ...item,
2642
- status: "cancelled",
2643
- ...event.reason === void 0 ? {} : { reason: event.reason }
2644
- };
2369
+ return event.type === "approval.resolved" ? { ...item, status: "resolved", decision: event.decision } : { ...item, status: "cancelled", ...omitUndefined2({ reason: event.reason }) };
2645
2370
  });
2646
2371
  }
2647
2372
  projectChangePreview(runId, step, toolCallId, preview, timestamp) {
@@ -2662,6 +2387,20 @@ var TranscriptStore = class {
2662
2387
  }
2663
2388
  }
2664
2389
  projectSessionEvent(event) {
2390
+ for (const entry of this.transcriptReader.read(event)) {
2391
+ if (entry.type === "user-message") {
2392
+ this.latestReplyId = void 0;
2393
+ this.append({
2394
+ id: entry.source === "steering" ? entry.id : `history:${entry.seq}`,
2395
+ kind: "user",
2396
+ text: contentText(entry.message.content, "text"),
2397
+ timestamp: entry.timestamp
2398
+ });
2399
+ } else
2400
+ this.projectRecordedEvent(entry.event);
2401
+ }
2402
+ }
2403
+ projectRecordedEvent(event) {
2665
2404
  switch (event.type) {
2666
2405
  case "run.started":
2667
2406
  this.latestReplyId = void 0;
@@ -2670,48 +2409,21 @@ var TranscriptStore = class {
2670
2409
  this.completeReply(event);
2671
2410
  break;
2672
2411
  case "run.interrupted":
2412
+ this.settle(event.runId);
2673
2413
  for (const item of event.recoveries) {
2674
2414
  this.appendHistoryTool(historyTool({
2675
2415
  ...event,
2676
2416
  type: "tool.failed",
2677
2417
  step: item.step,
2678
2418
  call: item.call,
2679
- error: { name: "InterruptedToolError", message: item.status === "unknown" ? "Outcome unknown; inspect /recovery before continuing" : "Not executed before interruption" }
2680
- }, "failed"));
2419
+ error: {
2420
+ name: "InterruptedToolError",
2421
+ message: item.status === "unknown" ? "Outcome unknown; inspect /recovery before continuing" : "Not executed before interruption"
2422
+ }
2423
+ }, item.status));
2681
2424
  }
2682
2425
  this.appendNoticeItem(`history:${event.seq}`, "warning", "Run interrupted. Inspect /recovery for unresolved tool outcomes.", event.timestamp);
2683
2426
  break;
2684
- case "recovery.resolved":
2685
- case "input.submitted":
2686
- if (event.type === "input.submitted" && event.inputId !== void 0)
2687
- this.steeringInputs.delete(event.inputId);
2688
- this.latestReplyId = void 0;
2689
- this.append({
2690
- id: `history:${event.seq}`,
2691
- kind: "user",
2692
- text: contentText(event.message.content, "text"),
2693
- timestamp: event.timestamp
2694
- });
2695
- break;
2696
- case "input.steering.queued":
2697
- this.steeringInputs.set(event.input.inputId, event.input.message);
2698
- break;
2699
- case "input.steering.delivered": {
2700
- const messages = event.inputIds.map((inputId) => {
2701
- const message = this.steeringInputs.get(inputId);
2702
- if (message === void 0)
2703
- throw new Error(`Missing steering input in transcript history: ${inputId}`);
2704
- this.steeringInputs.delete(inputId);
2705
- return message;
2706
- });
2707
- this.appendSteering(event.runId, event.step, messages, event.timestamp);
2708
- break;
2709
- }
2710
- case "input.steering.finished":
2711
- if (event.status === "cancelled")
2712
- for (const inputId of event.inputIds)
2713
- this.steeringInputs.delete(inputId);
2714
- break;
2715
2427
  case "assistant.completed": {
2716
2428
  const content = assistantContent(event.message);
2717
2429
  this.append({
@@ -2727,11 +2439,15 @@ var TranscriptStore = class {
2727
2439
  });
2728
2440
  break;
2729
2441
  }
2442
+ case "tool.started":
2443
+ this.ensureTool(event.runId, event.step, event.call, event.timestamp);
2444
+ break;
2730
2445
  case "tool.completed":
2731
2446
  this.appendHistoryTool(historyTool(event, "completed"));
2732
2447
  break;
2733
2448
  case "tool.failed":
2734
- this.appendHistoryTool(historyTool(event, "failed"));
2449
+ this.appendHistoryTool(historyTool(event, sessionToolFailureStatus(event.error, this.cancelledApprovals.has(toolId(event.runId, event.call.id)))));
2450
+ this.cancelledApprovals.delete(toolId(event.runId, event.call.id));
2735
2451
  break;
2736
2452
  case "tool.presentation": {
2737
2453
  const preview = decodeToolChangePreviewPresentation(event.kind, event.version, event.data);
@@ -2741,6 +2457,7 @@ var TranscriptStore = class {
2741
2457
  break;
2742
2458
  }
2743
2459
  case "approval.requested":
2460
+ this.approvalTools.set(event.request.id, toolId(event.request.runId, event.request.toolCallId));
2744
2461
  this.append({
2745
2462
  id: `approval:${event.request.id}`,
2746
2463
  kind: "approval",
@@ -2767,24 +2484,62 @@ var TranscriptStore = class {
2767
2484
  break;
2768
2485
  case "session.created":
2769
2486
  case "run.yielded":
2487
+ case "continuation.submitted":
2488
+ case "history.omitted":
2489
+ case "input.generated":
2490
+ case "model.attempt.completed":
2491
+ case "model.attempt.failed":
2492
+ case "model.attempt.started":
2493
+ case "model.request.defined":
2494
+ case "model.request.prepared":
2495
+ case "rule.created":
2496
+ case "rule.revoked":
2497
+ case "rule.used":
2498
+ case "run.budget.exceeded":
2499
+ case "run.settled":
2500
+ case "runtime.changed":
2501
+ case "runtime.state.saved":
2502
+ case "session.fork.ready":
2503
+ case "state.updated":
2770
2504
  break;
2771
2505
  }
2506
+ if (isSessionRunTerminalEvent(event) && "runId" in event)
2507
+ this.settle(event.runId);
2508
+ }
2509
+ settle(runId) {
2510
+ this.values = this.values.flatMap((item) => {
2511
+ if (item.kind !== "tool" && item.kind !== "assistant" || item.runId !== runId)
2512
+ return [item];
2513
+ if (item.kind === "tool")
2514
+ return [item.status === "running" ? { ...item, status: "unknown" } : item];
2515
+ if (item.status !== "streaming")
2516
+ return [item];
2517
+ return item.text === "" && item.reasoning === "" ? [] : [{ ...item, status: "interrupted" }];
2518
+ });
2519
+ }
2520
+ settleApproval(event) {
2521
+ const id = this.approvalTools.get(event.requestId);
2522
+ if (id !== void 0 && event.type === "approval.cancelled")
2523
+ this.cancelledApprovals.add(id);
2524
+ this.approvalTools.delete(event.requestId);
2772
2525
  }
2773
2526
  applyHistoryApproval(event) {
2527
+ this.settleApproval(event);
2774
2528
  this.replace(`approval:${event.requestId}`, (item) => {
2775
2529
  if (item.kind !== "approval")
2776
2530
  return item;
2777
- return event.type === "approval.resolved" ? { ...item, status: "resolved", decision: event.decision } : {
2778
- ...item,
2779
- status: "cancelled",
2780
- ...event.reason === void 0 ? {} : { reason: event.reason }
2781
- };
2531
+ return event.type === "approval.resolved" ? { ...item, status: "resolved", decision: event.decision } : { ...item, status: "cancelled", ...omitUndefined2({ reason: event.reason }) };
2782
2532
  });
2783
2533
  }
2784
2534
  appendSteering(runId, step, messages, timestamp) {
2785
2535
  this.latestReplyId = void 0;
2786
2536
  for (const [index, message] of messages.entries()) {
2787
- this.append({ id: `steering:${runId}:${step}:${index}`, kind: "user", text: contentText(message.content, "text"), timestamp });
2537
+ this.append({
2538
+ id: `steering:${runId}:${step}:${index}`,
2539
+ kind: "user",
2540
+ text: contentText(message.content, "text"),
2541
+ timestamp
2542
+ });
2788
2543
  }
2789
2544
  }
2790
2545
  completeReply(event) {
@@ -2913,6 +2668,223 @@ function toolId(runId, callId) {
2913
2668
  }
2914
2669
  __name(toolId, "toolId");
2915
2670
 
2671
+ // node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/base.js
2672
+ var Diff = class {
2673
+ static {
2674
+ __name(this, "Diff");
2675
+ }
2676
+ diff(oldStr, newStr, options = {}) {
2677
+ let callback;
2678
+ if (typeof options === "function") {
2679
+ callback = options;
2680
+ options = {};
2681
+ } else if ("callback" in options) {
2682
+ callback = options.callback;
2683
+ }
2684
+ const oldString = this.castInput(oldStr, options);
2685
+ const newString = this.castInput(newStr, options);
2686
+ const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
2687
+ const newTokens = this.removeEmpty(this.tokenize(newString, options));
2688
+ return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
2689
+ }
2690
+ diffWithOptionsObj(oldTokens, newTokens, options, callback) {
2691
+ var _a;
2692
+ const done = /* @__PURE__ */ __name((value) => {
2693
+ value = this.postProcess(value, options);
2694
+ if (callback) {
2695
+ setTimeout(function() {
2696
+ callback(value);
2697
+ }, 0);
2698
+ return void 0;
2699
+ } else {
2700
+ return value;
2701
+ }
2702
+ }, "done");
2703
+ const newLen = newTokens.length, oldLen = oldTokens.length;
2704
+ let editLength = 1;
2705
+ let maxEditLength = newLen + oldLen;
2706
+ if (options.maxEditLength != null) {
2707
+ maxEditLength = Math.min(maxEditLength, options.maxEditLength);
2708
+ }
2709
+ const maxExecutionTime = (_a = options.timeout) !== null && _a !== void 0 ? _a : Infinity;
2710
+ const abortAfterTimestamp = Date.now() + maxExecutionTime;
2711
+ const bestPath = [{ oldPos: -1, lastComponent: void 0 }];
2712
+ let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
2713
+ if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
2714
+ return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
2715
+ }
2716
+ let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
2717
+ const execEditLength = /* @__PURE__ */ __name(() => {
2718
+ for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
2719
+ let basePath;
2720
+ const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
2721
+ if (removePath) {
2722
+ bestPath[diagonalPath - 1] = void 0;
2723
+ }
2724
+ let canAdd = false;
2725
+ if (addPath) {
2726
+ const addPathNewPos = addPath.oldPos - diagonalPath;
2727
+ canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
2728
+ }
2729
+ const canRemove = removePath && removePath.oldPos + 1 < oldLen;
2730
+ if (!canAdd && !canRemove) {
2731
+ bestPath[diagonalPath] = void 0;
2732
+ continue;
2733
+ }
2734
+ if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
2735
+ basePath = this.addToPath(addPath, true, false, 0, options);
2736
+ } else {
2737
+ basePath = this.addToPath(removePath, false, true, 1, options);
2738
+ }
2739
+ newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
2740
+ if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
2741
+ return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
2742
+ } else {
2743
+ bestPath[diagonalPath] = basePath;
2744
+ if (basePath.oldPos + 1 >= oldLen) {
2745
+ maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
2746
+ }
2747
+ if (newPos + 1 >= newLen) {
2748
+ minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
2749
+ }
2750
+ }
2751
+ }
2752
+ editLength++;
2753
+ }, "execEditLength");
2754
+ if (callback) {
2755
+ (/* @__PURE__ */ __name(function exec2() {
2756
+ setTimeout(function() {
2757
+ if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
2758
+ return callback(void 0);
2759
+ }
2760
+ if (!execEditLength()) {
2761
+ exec2();
2762
+ }
2763
+ }, 0);
2764
+ }, "exec"))();
2765
+ } else {
2766
+ while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
2767
+ const ret = execEditLength();
2768
+ if (ret) {
2769
+ return ret;
2770
+ }
2771
+ }
2772
+ }
2773
+ }
2774
+ addToPath(path, added, removed, oldPosInc, options) {
2775
+ const last = path.lastComponent;
2776
+ if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
2777
+ return {
2778
+ oldPos: path.oldPos + oldPosInc,
2779
+ lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
2780
+ };
2781
+ } else {
2782
+ return {
2783
+ oldPos: path.oldPos + oldPosInc,
2784
+ lastComponent: { count: 1, added, removed, previousComponent: last }
2785
+ };
2786
+ }
2787
+ }
2788
+ extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
2789
+ const newLen = newTokens.length, oldLen = oldTokens.length;
2790
+ let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
2791
+ while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
2792
+ newPos++;
2793
+ oldPos++;
2794
+ commonCount++;
2795
+ if (options.oneChangePerToken) {
2796
+ basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
2797
+ }
2798
+ }
2799
+ if (commonCount && !options.oneChangePerToken) {
2800
+ basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
2801
+ }
2802
+ basePath.oldPos = oldPos;
2803
+ return newPos;
2804
+ }
2805
+ equals(left, right, options) {
2806
+ if (options.comparator) {
2807
+ return options.comparator(left, right);
2808
+ } else {
2809
+ return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
2810
+ }
2811
+ }
2812
+ removeEmpty(array) {
2813
+ const ret = [];
2814
+ for (let i = 0; i < array.length; i++) {
2815
+ if (array[i]) {
2816
+ ret.push(array[i]);
2817
+ }
2818
+ }
2819
+ return ret;
2820
+ }
2821
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2822
+ castInput(value, options) {
2823
+ return value;
2824
+ }
2825
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2826
+ tokenize(value, options) {
2827
+ return Array.from(value);
2828
+ }
2829
+ join(chars) {
2830
+ return chars.join("");
2831
+ }
2832
+ postProcess(changeObjects, options) {
2833
+ return changeObjects;
2834
+ }
2835
+ get useLongestToken() {
2836
+ return false;
2837
+ }
2838
+ buildValues(lastComponent, newTokens, oldTokens) {
2839
+ const components = [];
2840
+ let nextComponent;
2841
+ while (lastComponent) {
2842
+ components.push(lastComponent);
2843
+ nextComponent = lastComponent.previousComponent;
2844
+ delete lastComponent.previousComponent;
2845
+ lastComponent = nextComponent;
2846
+ }
2847
+ components.reverse();
2848
+ const componentLen = components.length;
2849
+ let componentPos = 0, newPos = 0, oldPos = 0;
2850
+ for (; componentPos < componentLen; componentPos++) {
2851
+ const component = components[componentPos];
2852
+ if (!component.removed) {
2853
+ if (!component.added && this.useLongestToken) {
2854
+ let value = newTokens.slice(newPos, newPos + component.count);
2855
+ value = value.map(function(value2, i) {
2856
+ const oldValue = oldTokens[oldPos + i];
2857
+ return oldValue.length > value2.length ? oldValue : value2;
2858
+ });
2859
+ component.value = this.join(value);
2860
+ } else {
2861
+ component.value = this.join(newTokens.slice(newPos, newPos + component.count));
2862
+ }
2863
+ newPos += component.count;
2864
+ if (!component.added) {
2865
+ oldPos += component.count;
2866
+ }
2867
+ } else {
2868
+ component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
2869
+ oldPos += component.count;
2870
+ }
2871
+ }
2872
+ return components;
2873
+ }
2874
+ };
2875
+
2876
+ // node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/character.js
2877
+ var CharacterDiff = class extends Diff {
2878
+ static {
2879
+ __name(this, "CharacterDiff");
2880
+ }
2881
+ };
2882
+ var characterDiff = new CharacterDiff();
2883
+ function diffChars(oldStr, newStr, options) {
2884
+ return characterDiff.diff(oldStr, newStr, options);
2885
+ }
2886
+ __name(diffChars, "diffChars");
2887
+
2916
2888
  // node_modules/.pnpm/marked@18.0.11/node_modules/marked/lib/marked.esm.js
2917
2889
  function A() {
2918
2890
  return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
@@ -4228,7 +4200,7 @@ var ln = b.parse;
4228
4200
  var un = x.lex;
4229
4201
 
4230
4202
  // packages/ui/tui/dist/markdown.js
4231
- import { stripVTControlCharacters as stripVTControlCharacters4 } from "node:util";
4203
+ import { stripVTControlCharacters as stripVTControlCharacters3 } from "node:util";
4232
4204
  var Markdown = class {
4233
4205
  static {
4234
4206
  __name(this, "Markdown");
@@ -4254,9 +4226,12 @@ function markdownDocument(source, options) {
4254
4226
  const last = document.at(-1);
4255
4227
  if (last !== void 0) {
4256
4228
  const value = last.value.trimEnd();
4257
- document[document.length - 1] = { value, ...last.copy === void 0 ? {} : {
4258
- copy: { start: last.copy.start, end: Math.min(last.copy.end, stripVTControlCharacters4(value).length) }
4259
- } };
4229
+ document[document.length - 1] = {
4230
+ value,
4231
+ ...last.copy === void 0 ? {} : {
4232
+ copy: { start: last.copy.start, end: Math.min(last.copy.end, stripVTControlCharacters3(value).length) }
4233
+ }
4234
+ };
4260
4235
  }
4261
4236
  return document.length === 0 ? [{ value: "", copy: { start: 0, end: 0 } }] : document;
4262
4237
  }
@@ -4321,155 +4296,377 @@ function renderBlocks(tokens, colors, theme) {
4321
4296
  if (block !== void 0 && block.some((line) => line.value !== ""))
4322
4297
  blocks.push(block);
4323
4298
  }
4324
- return blocks.flatMap((block, index) => index === 0 ? block : [{ value: "", copy: { start: 0, end: 0 } }, ...block]);
4299
+ return blocks.flatMap((block, index) => index === 0 ? block : [{ value: "", copy: { start: 0, end: 0 } }, ...block]);
4300
+ }
4301
+ __name(renderBlocks, "renderBlocks");
4302
+ function renderInline(tokens, colors, theme) {
4303
+ return tokens.map((token) => {
4304
+ switch (token.type) {
4305
+ case "text": {
4306
+ const text = token;
4307
+ return text.tokens === void 0 ? text.text : renderInline(text.tokens, colors, theme);
4308
+ }
4309
+ case "escape":
4310
+ return token.text;
4311
+ case "strong":
4312
+ return style(renderInline(token.tokens, colors, theme), { bold: true }, colors);
4313
+ case "em":
4314
+ return style(renderInline(token.tokens, colors, theme), { italic: true }, colors);
4315
+ case "del":
4316
+ return style(renderInline(token.tokens, colors, theme), { strikethrough: true }, colors);
4317
+ case "codespan":
4318
+ return style(token.text, theme.code, colors);
4319
+ case "br":
4320
+ return "\n";
4321
+ case "link": {
4322
+ const link = token;
4323
+ const label = style(renderInline(link.tokens, colors, theme), theme.link, colors);
4324
+ return link.href === link.text ? label : `${label} ${style(`(${link.href})`, theme.linkUrl, colors)}`;
4325
+ }
4326
+ case "image": {
4327
+ const image = token;
4328
+ return `[image: ${image.text || "unnamed"}] (${image.href})`;
4329
+ }
4330
+ case "html":
4331
+ return stripHtml(token.text);
4332
+ default:
4333
+ return "raw" in token ? sanitizeTerminalText(String(token.raw)) : "";
4334
+ }
4335
+ }).join("");
4336
+ }
4337
+ __name(renderInline, "renderInline");
4338
+ function renderList(list, colors, theme) {
4339
+ const start = typeof list.start === "number" ? list.start : 1;
4340
+ return list.items.flatMap((item, index) => {
4341
+ const task = item.task ? `[${item.checked ? "x" : " "}] ` : "";
4342
+ const marker = list.ordered ? `${start + index}. ` : "\u2022 ";
4343
+ const body = renderBlocks(item.tokens, colors, theme);
4344
+ const continuation = " ".repeat(marker.length + task.length);
4345
+ return body.map((line, lineIndex) => {
4346
+ const prefix = lineIndex === 0 ? `${style(marker, theme.listBullet, colors)}${task}` : continuation;
4347
+ return {
4348
+ value: prefix + line.value,
4349
+ ...line.copy === void 0 ? {} : {
4350
+ copy: {
4351
+ start: line.copy.start === 0 ? 0 : line.copy.start + continuation.length,
4352
+ end: line.copy.end + continuation.length
4353
+ }
4354
+ }
4355
+ };
4356
+ });
4357
+ });
4358
+ }
4359
+ __name(renderList, "renderList");
4360
+ function renderTable(table, colors, theme) {
4361
+ const row = /* @__PURE__ */ __name((cells) => `| ${cells.map((cell) => renderInline(cell.tokens, colors, theme)).join(" | ")} |`, "row");
4362
+ const header2 = row(table.header);
4363
+ const divider = `| ${table.header.map(() => "---").join(" | ")} |`;
4364
+ return [...copyLines(header2), { value: divider }, ...table.rows.flatMap((cells) => copyLines(row(cells)))];
4365
+ }
4366
+ __name(renderTable, "renderTable");
4367
+ function copyLines(value) {
4368
+ return value.split("\n").map((line) => ({ value: line, copy: { start: 0, end: stripVTControlCharacters3(line).length } }));
4369
+ }
4370
+ __name(copyLines, "copyLines");
4371
+ function style(value, textStyle, enabled) {
4372
+ return enabled ? styleText(value, textStyle) : value;
4373
+ }
4374
+ __name(style, "style");
4375
+ function stripHtml(value) {
4376
+ return sanitizeTerminalText(value.replace(/<[^>]*>/gu, ""));
4377
+ }
4378
+ __name(stripHtml, "stripHtml");
4379
+
4380
+ // packages/ui/tui/dist/stack.js
4381
+ var Stack = class {
4382
+ static {
4383
+ __name(this, "Stack");
4384
+ }
4385
+ children;
4386
+ gap;
4387
+ bounds = [];
4388
+ captured;
4389
+ constructor(children, options = {}) {
4390
+ this.children = children;
4391
+ this.gap = options.gap ?? 0;
4392
+ if (!Number.isInteger(this.gap) || this.gap < 0) {
4393
+ throw new RangeError("Stack gap must be a non-negative integer");
4394
+ }
4395
+ }
4396
+ render(size) {
4397
+ const lines = [];
4398
+ const images = [];
4399
+ const textRows = [];
4400
+ this.bounds = [];
4401
+ let cursor;
4402
+ for (const child of this.children) {
4403
+ if (lines.length >= size.height)
4404
+ break;
4405
+ if (lines.length > 0 && this.gap > 0) {
4406
+ const count = Math.min(this.gap, size.height - lines.length);
4407
+ lines.push(...Array.from({ length: count }, () => ""));
4408
+ textRows.push(...Array.from({ length: count }, () => void 0));
4409
+ }
4410
+ if (lines.length >= size.height)
4411
+ break;
4412
+ const offset = lines.length;
4413
+ const result = child.render({
4414
+ width: size.width,
4415
+ height: size.height - lines.length
4416
+ });
4417
+ lines.push(...result.lines.slice(0, size.height - lines.length));
4418
+ textRows.push(...result.lines.map((_2, index) => result.textRows?.[index]));
4419
+ this.bounds.push({ child, y: offset, height: result.lines.length });
4420
+ if (this.captured?.child === child)
4421
+ this.captured.y = offset;
4422
+ images.push(...placeImages(result.images, offset, size.height));
4423
+ if (cursor === void 0 && result.cursor !== void 0) {
4424
+ cursor = { ...result.cursor, y: result.cursor.y + offset };
4425
+ }
4426
+ }
4427
+ return {
4428
+ lines,
4429
+ ...textRows.some((row) => row !== void 0) ? { textRows } : {},
4430
+ ...images.length ? { images } : {},
4431
+ ...cursor === void 0 ? {} : { cursor }
4432
+ };
4433
+ }
4434
+ handlePointer(event) {
4435
+ const target = event.type === "down" ? this.bounds.find((bound) => event.y >= bound.y && event.y < bound.y + bound.height) : this.bounds.find((bound) => bound.child === this.captured?.child);
4436
+ if (event.type === "down")
4437
+ this.captured = void 0;
4438
+ if (target === void 0 || !("handlePointer" in target.child) || typeof target.child.handlePointer !== "function")
4439
+ return false;
4440
+ const consumed = target.child.handlePointer({ ...event, y: event.y - target.y });
4441
+ if (event.type === "down" && consumed)
4442
+ this.captured = { child: target.child, y: target.y };
4443
+ if (event.type === "up")
4444
+ this.captured = void 0;
4445
+ return consumed;
4446
+ }
4447
+ dispose() {
4448
+ this.captured = void 0;
4449
+ this.bounds = [];
4450
+ for (const child of this.children)
4451
+ child.dispose?.();
4452
+ }
4453
+ };
4454
+
4455
+ // packages/ui/tui/dist/agent/tool-renderers.js
4456
+ import { stripVTControlCharacters as stripVTControlCharacters4 } from "node:util";
4457
+ var ToolRendererRegistry = class {
4458
+ static {
4459
+ __name(this, "ToolRendererRegistry");
4460
+ }
4461
+ fallback;
4462
+ renderers = /* @__PURE__ */ new Map();
4463
+ generation = 0;
4464
+ get revision() {
4465
+ return this.generation;
4466
+ }
4467
+ constructor(fallback = genericRenderer) {
4468
+ this.fallback = fallback;
4469
+ }
4470
+ register(name, renderer) {
4471
+ const normalized = name.trim();
4472
+ if (normalized === "")
4473
+ throw new Error("Tool renderer name cannot be empty");
4474
+ this.renderers.set(normalized, renderer);
4475
+ this.generation++;
4476
+ return this;
4477
+ }
4478
+ render(item, options) {
4479
+ return this.renderDocument(item, options).map((line) => line.value).join("\n");
4480
+ }
4481
+ renderDocument(item, options) {
4482
+ const renderer = this.renderers.get(item.call.name) ?? this.fallback;
4483
+ return renderer.renderDocument?.(item, options) ?? renderer.render(item, options).split("\n").map((line) => copyLine(line));
4484
+ }
4485
+ };
4486
+ function createCodingToolRendererRegistry() {
4487
+ return new ToolRendererRegistry().register("shell", shellRenderer).register("bash", shellRenderer).register("read", readRenderer).register("edit", fileChangeRenderer).register("write", fileChangeRenderer);
4488
+ }
4489
+ __name(createCodingToolRendererRegistry, "createCodingToolRendererRegistry");
4490
+ var shellRenderer = documentRenderer((item, options) => {
4491
+ const command = stringField(item.call.input, "command") ?? inputSummary(item.call.input);
4492
+ const lines = [header(item, options, command)];
4493
+ appendProgress(lines, item, options);
4494
+ const output = objectValue(item.output);
4495
+ const stdout = stringField(output, "stdout") ?? item.streamedOutput;
4496
+ const stderr = stringField(output, "stderr") ?? "";
4497
+ if (stdout !== "")
4498
+ appendOutput(lines, stdout, options);
4499
+ if (stderr !== "") {
4500
+ lines.push(copyLine(styleText(" stderr", options.theme.error), 2));
4501
+ appendOutput(lines, stderr, options, options.theme.error);
4502
+ }
4503
+ if (item.status === "completed") {
4504
+ const exitCode = primitiveField(output, "exitCode");
4505
+ const signal = primitiveField(output, "signal");
4506
+ const result = exitCode === void 0 ? "completed" : `exit ${String(exitCode)}`;
4507
+ lines.push(copyLine(styleText(` \u2514\u2500 ${result}${signal == null ? "" : ` \xB7 ${String(signal)}`}`, exitCode === 0 || exitCode === void 0 ? options.theme.muted : options.theme.warning), 5));
4508
+ }
4509
+ appendFailure(lines, item, options);
4510
+ return lines;
4511
+ });
4512
+ var readRenderer = documentRenderer((item, options) => {
4513
+ const inputPath = stringField(item.call.input, "path") ?? "<unknown>";
4514
+ const output = objectValue(item.output);
4515
+ const path = stringField(output, "path") ?? inputPath;
4516
+ const start = numberField(output, "startLine");
4517
+ const end = numberField(output, "endLine");
4518
+ const total = numberField(output, "totalLines");
4519
+ const range = start === void 0 || end === void 0 ? "" : `:${start}-${end}`;
4520
+ const lines = [header(item, options, `${path}${range}`)];
4521
+ appendProgress(lines, item, options);
4522
+ if (options.expanded) {
4523
+ const content = stringField(output, "content");
4524
+ if (content !== void 0 && content !== "") {
4525
+ appendOutput(lines, content, options, options.theme.toolOutput, true, start ?? 1);
4526
+ }
4527
+ } else if (total !== void 0) {
4528
+ const count = start === void 0 || end === void 0 ? 0 : Math.max(0, end - start + 1);
4529
+ const description = `${count} of ${total} lines`;
4530
+ lines.push(copyLine(styleText(` \u2514\u2500 ${count} of ${total} lines${options.detailsHint === void 0 ? "" : ` \xB7 ${options.detailsHint}`}`, options.theme.muted), 5, 5 + description.length));
4531
+ }
4532
+ appendFailure(lines, item, options);
4533
+ return lines;
4534
+ });
4535
+ var fileChangeRenderer = documentRenderer((item, options) => {
4536
+ const inputPath = stringField(item.call.input, "path") ?? "<unknown>";
4537
+ const preview = item.preview;
4538
+ const detail = preview?.status === "ready" ? `${preview.path} +${preview.additions} -${preview.deletions}` : inputPath;
4539
+ const lines = [header(item, options, detail)];
4540
+ appendProgress(lines, item, options);
4541
+ if (preview?.status === "ready") {
4542
+ if (options.expanded && preview.diff !== "") {
4543
+ lines.push(...renderDiff(preview.diff, options.theme));
4544
+ } else {
4545
+ const hint = options.detailsHint === void 0 ? "" : ` \xB7 ${options.detailsHint}`;
4546
+ lines.push(copyLine(styleText(` \u2514\u2500 ${preview.kind}${hint}`, options.theme.muted), 5, 5 + preview.kind.length));
4547
+ }
4548
+ } else if (preview?.status === "unavailable") {
4549
+ lines.push(copyLine(styleText(` Diff unavailable: ${sanitizeTerminalText(preview.reason)}`, options.theme.warning), 2));
4550
+ }
4551
+ if (item.status === "completed" && preview === void 0) {
4552
+ appendOutput(lines, stringify(item.output), options);
4553
+ }
4554
+ appendFailure(lines, item, options);
4555
+ return lines;
4556
+ });
4557
+ var genericRenderer = documentRenderer((item, options) => {
4558
+ const lines = [header(item, options, inputSummary(item.call.input))];
4559
+ appendProgress(lines, item, options);
4560
+ const output = item.streamedOutput !== "" ? item.streamedOutput : item.status === "completed" ? stringify(item.output) : "";
4561
+ if (output !== "")
4562
+ appendOutput(lines, output, options);
4563
+ appendFailure(lines, item, options);
4564
+ return lines;
4565
+ });
4566
+ function documentRenderer(renderDocument) {
4567
+ return {
4568
+ renderDocument,
4569
+ render: /* @__PURE__ */ __name((item, options) => renderDocument(item, options).map((line) => line.value).join("\n"), "render")
4570
+ };
4571
+ }
4572
+ __name(documentRenderer, "documentRenderer");
4573
+ function header(item, options, detail) {
4574
+ const marker = item.status === "completed" ? "\u2713" : item.status === "failed" || item.status === "denied" ? "\u2717" : item.status === "unknown" ? "?" : item.status === "not-started" ? "\u25CB" : "\u25CF";
4575
+ const markerStyle = item.status === "completed" ? options.theme.toolSuccess : item.status === "failed" || item.status === "denied" ? options.theme.toolError : item.status === "unknown" || item.status === "not-started" ? options.theme.warning : options.theme.toolPending;
4576
+ const safeDetail = sanitizeTerminalText(detail).replace(/\s+/gu, " ").trim();
4577
+ const selection = options.selected === true ? styleText("\u25B8", options.theme.accent) : " ";
4578
+ return copyLine(`${selection} ${styleText(marker, markerStyle)} ${styleText(sanitizeTerminalText(item.call.name), options.theme.toolTitle)}${safeDetail === "" ? "" : ` ${safeDetail}`}`, 4);
4579
+ }
4580
+ __name(header, "header");
4581
+ function appendProgress(lines, item, options) {
4582
+ for (const progress of item.progress.slice(options.expanded ? 0 : -2)) {
4583
+ lines.push(copyLine(styleText(` \u21B3 ${sanitizeTerminalText(progress)}`, options.theme.muted), 4));
4584
+ }
4585
+ }
4586
+ __name(appendProgress, "appendProgress");
4587
+ function appendOutput(lines, value, options, outputStyle = options.theme.toolOutput, forceExpanded = false, numberFrom) {
4588
+ const safe = sanitizeTerminalText(value).replace(/\s+$/gu, "");
4589
+ if (safe === "")
4590
+ return;
4591
+ const maximumLines = options.expanded || forceExpanded ? Number.POSITIVE_INFINITY : 4;
4592
+ const limitedCharacters = truncateCharacters(safe, options.maximumOutputCharacters);
4593
+ const allLines = limitedCharacters.split("\n");
4594
+ const displayed = allLines.slice(0, maximumLines);
4595
+ const numberWidth = String((numberFrom ?? 1) + allLines.length - 1).length;
4596
+ for (const [index, line] of displayed.entries()) {
4597
+ const label = numberFrom === void 0 ? "" : `${String(numberFrom + index).padStart(numberWidth)} \u2502 `;
4598
+ lines.push(copyLine(`${styleText(" \u2502", options.theme.border)} ${styleText(label + line, outputStyle)}`, 4 + label.length));
4599
+ }
4600
+ const omittedLines = allLines.length - displayed.length;
4601
+ if (omittedLines > 0) {
4602
+ const hint = options.detailsHint === void 0 ? "" : ` \xB7 ${options.detailsHint}`;
4603
+ lines.push({ value: styleText(` \u2026 ${omittedLines} more lines${hint}`, options.theme.muted) });
4604
+ } else if (limitedCharacters.endsWith("\u2026") && safe !== limitedCharacters) {
4605
+ lines.push({ value: styleText(" \u2026 output truncated", options.theme.muted) });
4606
+ }
4325
4607
  }
4326
- __name(renderBlocks, "renderBlocks");
4327
- function renderInline(tokens, colors, theme) {
4328
- return tokens.map((token) => {
4329
- switch (token.type) {
4330
- case "text": {
4331
- const text = token;
4332
- return text.tokens === void 0 ? text.text : renderInline(text.tokens, colors, theme);
4333
- }
4334
- case "escape":
4335
- return token.text;
4336
- case "strong":
4337
- return style(renderInline(token.tokens, colors, theme), { bold: true }, colors);
4338
- case "em":
4339
- return style(renderInline(token.tokens, colors, theme), { italic: true }, colors);
4340
- case "del":
4341
- return style(renderInline(token.tokens, colors, theme), { strikethrough: true }, colors);
4342
- case "codespan":
4343
- return style(token.text, theme.code, colors);
4344
- case "br":
4345
- return "\n";
4346
- case "link": {
4347
- const link = token;
4348
- const label = style(renderInline(link.tokens, colors, theme), theme.link, colors);
4349
- return link.href === link.text ? label : `${label} ${style(`(${link.href})`, theme.linkUrl, colors)}`;
4350
- }
4351
- case "image": {
4352
- const image = token;
4353
- return `[image: ${image.text || "unnamed"}] (${image.href})`;
4354
- }
4355
- case "html":
4356
- return stripHtml(token.text);
4357
- default:
4358
- return "raw" in token ? sanitizeTerminalText(String(token.raw)) : "";
4359
- }
4360
- }).join("");
4608
+ __name(appendOutput, "appendOutput");
4609
+ function appendFailure(lines, item, options) {
4610
+ const status = item.status === "unknown" ? "Outcome unknown" : item.status === "not-started" ? "Not executed" : item.status === "denied" ? "Permission denied" : void 0;
4611
+ if (status !== void 0)
4612
+ lines.push(copyLine(styleText(` ${status}`, options.theme.warning), 2));
4613
+ if (item.status !== "completed" && item.status !== "running" && item.error !== void 0) {
4614
+ lines.push(copyLine(styleText(` ${sanitizeTerminalText(item.error)}`, item.status === "failed" ? options.theme.error : options.theme.warning), 2));
4615
+ }
4361
4616
  }
4362
- __name(renderInline, "renderInline");
4363
- function renderList(list, colors, theme) {
4364
- const start = typeof list.start === "number" ? list.start : 1;
4365
- return list.items.flatMap((item, index) => {
4366
- const task = item.task ? `[${item.checked ? "x" : " "}] ` : "";
4367
- const marker = list.ordered ? `${start + index}. ` : "\u2022 ";
4368
- const body = renderBlocks(item.tokens, colors, theme);
4369
- const continuation = " ".repeat(marker.length + task.length);
4370
- return body.map((line, lineIndex) => {
4371
- const prefix = lineIndex === 0 ? `${style(marker, theme.listBullet, colors)}${task}` : continuation;
4372
- return { value: prefix + line.value, ...line.copy === void 0 ? {} : {
4373
- copy: { start: line.copy.start === 0 ? 0 : line.copy.start + continuation.length, end: line.copy.end + continuation.length }
4374
- } };
4375
- });
4617
+ __name(appendFailure, "appendFailure");
4618
+ function renderDiff(diff, theme) {
4619
+ return sanitizeTerminalText(diff).split("\n").map((line) => {
4620
+ const style2 = line.startsWith("+++") || line.startsWith("---") || line.startsWith("@@") ? theme.muted : line.startsWith("+") ? theme.diffAdded : line.startsWith("-") ? theme.diffRemoved : theme.diffContext;
4621
+ return copyLine(`${styleText(" \u2502", theme.border)} ${styleText(line, style2)}`, 4);
4376
4622
  });
4377
4623
  }
4378
- __name(renderList, "renderList");
4379
- function renderTable(table, colors, theme) {
4380
- const row = /* @__PURE__ */ __name((cells) => `| ${cells.map((cell) => renderInline(cell.tokens, colors, theme)).join(" | ")} |`, "row");
4381
- const header2 = row(table.header);
4382
- const divider = `| ${table.header.map(() => "---").join(" | ")} |`;
4383
- return [...copyLines(header2), { value: divider }, ...table.rows.flatMap((cells) => copyLines(row(cells)))];
4624
+ __name(renderDiff, "renderDiff");
4625
+ function copyLine(value, start = 0, end = stripVTControlCharacters4(value).length) {
4626
+ return { value, copy: { start, end } };
4384
4627
  }
4385
- __name(renderTable, "renderTable");
4386
- function copyLines(value) {
4387
- return value.split("\n").map((line) => ({ value: line, copy: { start: 0, end: stripVTControlCharacters4(line).length } }));
4628
+ __name(copyLine, "copyLine");
4629
+ function inputSummary(input) {
4630
+ if (input === void 0)
4631
+ return "";
4632
+ const value = stringify(input).replace(/\s+/gu, " ");
4633
+ return value === "{}" ? "" : truncateCharacters(value, 160);
4388
4634
  }
4389
- __name(copyLines, "copyLines");
4390
- function style(value, textStyle, enabled) {
4391
- return enabled ? styleText(value, textStyle) : value;
4635
+ __name(inputSummary, "inputSummary");
4636
+ function stringify(value) {
4637
+ if (typeof value === "string")
4638
+ return value;
4639
+ try {
4640
+ return JSON.stringify(value, null, 2) ?? String(value);
4641
+ } catch {
4642
+ return String(value);
4643
+ }
4392
4644
  }
4393
- __name(style, "style");
4394
- function stripHtml(value) {
4395
- return sanitizeTerminalText(value.replace(/<[^>]*>/gu, ""));
4645
+ __name(stringify, "stringify");
4646
+ function objectValue(value) {
4647
+ return typeof value === "object" && value !== null ? value : void 0;
4396
4648
  }
4397
- __name(stripHtml, "stripHtml");
4398
-
4399
- // packages/ui/tui/dist/stack.js
4400
- var Stack = class {
4401
- static {
4402
- __name(this, "Stack");
4403
- }
4404
- children;
4405
- gap;
4406
- bounds = [];
4407
- captured;
4408
- constructor(children, options = {}) {
4409
- this.children = children;
4410
- this.gap = options.gap ?? 0;
4411
- if (!Number.isInteger(this.gap) || this.gap < 0) {
4412
- throw new RangeError("Stack gap must be a non-negative integer");
4413
- }
4414
- }
4415
- render(size) {
4416
- const lines = [];
4417
- const images = [];
4418
- const textRows = [];
4419
- this.bounds = [];
4420
- let cursor;
4421
- for (const child of this.children) {
4422
- if (lines.length >= size.height)
4423
- break;
4424
- if (lines.length > 0 && this.gap > 0) {
4425
- const count = Math.min(this.gap, size.height - lines.length);
4426
- lines.push(...Array.from({ length: count }, () => ""));
4427
- textRows.push(...Array.from({ length: count }, () => void 0));
4428
- }
4429
- if (lines.length >= size.height)
4430
- break;
4431
- const offset = lines.length;
4432
- const result = child.render({
4433
- width: size.width,
4434
- height: size.height - lines.length
4435
- });
4436
- lines.push(...result.lines.slice(0, size.height - lines.length));
4437
- textRows.push(...result.lines.map((_2, index) => result.textRows?.[index]));
4438
- this.bounds.push({ child, y: offset, height: result.lines.length });
4439
- if (this.captured?.child === child)
4440
- this.captured.y = offset;
4441
- images.push(...placeImages(result.images, offset, size.height));
4442
- if (cursor === void 0 && result.cursor !== void 0) {
4443
- cursor = { ...result.cursor, y: result.cursor.y + offset };
4444
- }
4445
- }
4446
- return {
4447
- lines,
4448
- ...textRows.some((row) => row !== void 0) ? { textRows } : {},
4449
- ...images.length ? { images } : {},
4450
- ...cursor === void 0 ? {} : { cursor }
4451
- };
4452
- }
4453
- handlePointer(event) {
4454
- const target = event.type === "down" ? this.bounds.find((bound) => event.y >= bound.y && event.y < bound.y + bound.height) : this.bounds.find((bound) => bound.child === this.captured?.child);
4455
- if (event.type === "down")
4456
- this.captured = void 0;
4457
- if (target === void 0 || !("handlePointer" in target.child) || typeof target.child.handlePointer !== "function")
4458
- return false;
4459
- const consumed = target.child.handlePointer({ ...event, y: event.y - target.y });
4460
- if (event.type === "down" && consumed)
4461
- this.captured = { child: target.child, y: target.y };
4462
- if (event.type === "up")
4463
- this.captured = void 0;
4464
- return consumed;
4465
- }
4466
- dispose() {
4467
- this.captured = void 0;
4468
- this.bounds = [];
4469
- for (const child of this.children)
4470
- child.dispose?.();
4471
- }
4472
- };
4649
+ __name(objectValue, "objectValue");
4650
+ function stringField(value, name) {
4651
+ const object = objectValue(value);
4652
+ return typeof object?.[name] === "string" ? object[name] : void 0;
4653
+ }
4654
+ __name(stringField, "stringField");
4655
+ function numberField(value, name) {
4656
+ const object = objectValue(value);
4657
+ return typeof object?.[name] === "number" ? object[name] : void 0;
4658
+ }
4659
+ __name(numberField, "numberField");
4660
+ function primitiveField(value, name) {
4661
+ const object = objectValue(value);
4662
+ const field = object?.[name];
4663
+ return field === null || ["string", "number", "boolean"].includes(typeof field) ? field : void 0;
4664
+ }
4665
+ __name(primitiveField, "primitiveField");
4666
+ function truncateCharacters(value, maximum) {
4667
+ return value.length <= maximum ? value : `${value.slice(0, Math.max(0, maximum - 1)).replace(/[\uD800-\uDBFF]$/u, "")}\u2026`;
4668
+ }
4669
+ __name(truncateCharacters, "truncateCharacters");
4473
4670
 
4474
4671
  // packages/ui/tui/dist/agent/transcript-view.js
4475
4672
  var TRANSCRIPT_KEYBINDINGS = [
@@ -4696,13 +4893,16 @@ var TranscriptView = class {
4696
4893
  if (range === void 0)
4697
4894
  return result;
4698
4895
  const sources = new Map(range.sources.map((source, index) => [source.sourceId, index]));
4699
- return { ...result, lines: result.lines.map((line, index) => {
4700
- const row = this.textRows[index];
4701
- const sourceIndex = row === void 0 ? void 0 : sources.get(row.sourceId);
4702
- if (row === void 0 || sourceIndex === void 0 || sourceIndex < range.startIndex || sourceIndex > range.endIndex)
4703
- return line;
4704
- return highlightTextRow(line, row, sourceIndex === range.startIndex ? range.start.offset : 0, sourceIndex === range.endIndex ? range.end.offset : row.source.length);
4705
- }) };
4896
+ return {
4897
+ ...result,
4898
+ lines: result.lines.map((line, index) => {
4899
+ const row = this.textRows[index];
4900
+ const sourceIndex = row === void 0 ? void 0 : sources.get(row.sourceId);
4901
+ if (row === void 0 || sourceIndex === void 0 || sourceIndex < range.startIndex || sourceIndex > range.endIndex)
4902
+ return line;
4903
+ return highlightTextRow(line, row, sourceIndex === range.startIndex ? range.start.offset : 0, sourceIndex === range.endIndex ? range.end.offset : row.source.length);
4904
+ })
4905
+ };
4706
4906
  }
4707
4907
  renderItems(size, retainTail) {
4708
4908
  this.replyAnchor = void 0;
@@ -4771,7 +4971,10 @@ var TranscriptView = class {
4771
4971
  const result = this.renderItem(item, size.width, Number.MAX_SAFE_INTEGER);
4772
4972
  this.rememberSources(item, result);
4773
4973
  const lines2 = result.lines;
4774
- const bodyLines = revealReply ? item.kind === "assistant" && item.content?.some((part) => part.type === "image") ? this.renderItem({ ...item, reasoning: "" }, size.width, Number.MAX_SAFE_INTEGER).lines.length - 1 : new Markdown(item.text, { theme: this.theme.markdown }).render({ width: size.width, height: Number.MAX_SAFE_INTEGER }).lines.length : void 0;
4974
+ const bodyLines = revealReply ? item.kind === "assistant" && item.content?.some((part) => part.type === "image") ? this.renderItem({ ...item, reasoning: "" }, size.width, Number.MAX_SAFE_INTEGER).lines.length - 1 : new Markdown(item.text, { theme: this.theme.markdown }).render({
4975
+ width: size.width,
4976
+ height: Number.MAX_SAFE_INTEGER
4977
+ }).lines.length : void 0;
4775
4978
  cached = {
4776
4979
  key,
4777
4980
  lines: lines2,
@@ -4905,12 +5108,18 @@ var TranscriptItemView = class {
4905
5108
  render: /* @__PURE__ */ __name((size2) => renderTextDocument(descriptionDocument, size2, { sourceId: `${this.item.id}:tool` }), "render")
4906
5109
  };
4907
5110
  const images = this.item.content?.filter((part) => part.type === "image") ?? [];
4908
- return new Stack([description, ...images.map((part, index) => options.images?.component(part.source, `${this.item.id}:image:${index}`) ?? new Text("\u56FE\u7247\u9644\u4EF6\uFF1A\u5BBF\u4E3B\u672A\u914D\u7F6E TerminalImages\u3002"))]).render(size);
5111
+ return new Stack([
5112
+ description,
5113
+ ...images.map((part, index) => options.images?.component(part.source, `${this.item.id}:image:${index}`) ?? new Text("\u56FE\u7247\u9644\u4EF6\uFF1A\u5BBF\u4E3B\u672A\u914D\u7F6E TerminalImages\u3002"))
5114
+ ]).render(size);
4909
5115
  }
4910
5116
  case "user":
4911
5117
  return new Text(renderUser(this.item, options), {
4912
5118
  sourceId: `${this.item.id}:user`,
4913
- copyRanges: [void 0, ...sanitizeTerminalText(this.item.text).split("\n").map((line) => ({ start: 2, end: line.length + 2 }))]
5119
+ copyRanges: [
5120
+ void 0,
5121
+ ...sanitizeTerminalText(this.item.text).split("\n").map((line) => ({ start: 2, end: line.length + 2 }))
5122
+ ]
4914
5123
  }).render(size);
4915
5124
  case "approval":
4916
5125
  return new Text(renderApproval(this.item, options.theme), { sourceId: `${this.item.id}:approval` }).render(size);
@@ -4962,6 +5171,8 @@ function renderAssistantView(item, options, size) {
4962
5171
  } else
4963
5172
  children.push(new Markdown(value, { theme: options.theme.markdown, sourceId: `${item.id}:text:0` }));
4964
5173
  }
5174
+ if (item.status === "interrupted")
5175
+ children.push(new Text("Reply interrupted", { style: options.theme.warning }));
4965
5176
  return new Stack(children).render(size);
4966
5177
  }
4967
5178
  __name(renderAssistantView, "renderAssistantView");
@@ -5239,7 +5450,7 @@ var EditorHistory = class {
5239
5450
  index;
5240
5451
  draft = "";
5241
5452
  constructor(options = {}) {
5242
- this.maximumEntries = positiveInteger2(options.maximumEntries ?? 100, "maximumEntries");
5453
+ this.maximumEntries = positiveInteger(options.maximumEntries ?? 100, "maximumEntries");
5243
5454
  this.entries = (options.entries ?? []).map(normalizeValue).filter((value) => value.trim() !== "").slice(-this.maximumEntries);
5244
5455
  this.index = this.entries.length;
5245
5456
  }
@@ -5337,7 +5548,7 @@ var Editor = class {
5337
5548
  }
5338
5549
  setValue(value, cursor = segment(normalizeValue(value)).length) {
5339
5550
  this.graphemes = segment(normalizeValue(value));
5340
- this.cursorIndex = clamp(cursor, 0, this.graphemes.length);
5551
+ this.cursorIndex = clamp2(cursor, 0, this.graphemes.length);
5341
5552
  this.clearSelection();
5342
5553
  this.preferredColumn = void 0;
5343
5554
  this.stopDragging();
@@ -5418,10 +5629,12 @@ var Editor = class {
5418
5629
  let cursor = rendered.positions[this.cursorIndex];
5419
5630
  if (this.graphemes.length === 0 && this.options.placeholder !== void 0) {
5420
5631
  const prefix = fitPrefix(this.prompt, size.width);
5421
- lines = [sliceAnsi(`${prefix}${styleText(this.options.placeholder.replace(/[\r\n]+/gu, " "), this.options.placeholderStyle)}`, 0, size.width)];
5632
+ lines = [
5633
+ sliceAnsi(`${prefix}${styleText(this.options.placeholder.replace(/[\r\n]+/gu, " "), this.options.placeholderStyle)}`, 0, size.width)
5634
+ ];
5422
5635
  cursor = { x: stringWidth(prefix), y: 0 };
5423
5636
  }
5424
- this.viewportStart = clamp(this.viewportStart, Math.max(0, cursor.y - size.height + 1), cursor.y);
5637
+ this.viewportStart = clamp2(this.viewportStart, Math.max(0, cursor.y - size.height + 1), cursor.y);
5425
5638
  this.viewportStart = Math.min(this.viewportStart, Math.max(0, lines.length - size.height));
5426
5639
  const visibleLines = lines.slice(this.viewportStart, this.viewportStart + size.height);
5427
5640
  return {
@@ -5579,7 +5792,7 @@ var Editor = class {
5579
5792
  this.selectionAnchor ??= previous;
5580
5793
  else
5581
5794
  this.selectionAnchor = void 0;
5582
- this.cursorIndex = clamp(next, 0, this.graphemes.length);
5795
+ this.cursorIndex = clamp2(next, 0, this.graphemes.length);
5583
5796
  if (!preserveColumn)
5584
5797
  this.preferredColumn = void 0;
5585
5798
  if (this.cursorIndex !== previous || this.selectionAnchor !== anchor)
@@ -5719,7 +5932,7 @@ var Editor = class {
5719
5932
  this.viewportStart = Math.max(0, this.viewportStart - 1);
5720
5933
  else if (y2 >= size.height)
5721
5934
  this.viewportStart = Math.min(Math.max(0, layout.rows.length - size.height), this.viewportStart + 1);
5722
- const row = clamp(this.viewportStart + clamp(y2, 0, size.height - 1), 0, layout.rows.length - 1);
5935
+ const row = clamp2(this.viewportStart + clamp2(y2, 0, size.height - 1), 0, layout.rows.length - 1);
5723
5936
  return indexAt(layout.rows[row], x2);
5724
5937
  }
5725
5938
  updateDragScroll(event) {
@@ -5861,10 +6074,10 @@ function lineEnd(graphemes2, cursor) {
5861
6074
  return graphemes2.length;
5862
6075
  }
5863
6076
  __name(lineEnd, "lineEnd");
5864
- function clamp(value, minimum, maximum) {
6077
+ function clamp2(value, minimum, maximum) {
5865
6078
  return Math.min(maximum, Math.max(minimum, Math.trunc(value)));
5866
6079
  }
5867
- __name(clamp, "clamp");
6080
+ __name(clamp2, "clamp");
5868
6081
  function previousWordBoundary(graphemes2, cursor) {
5869
6082
  let index = cursor;
5870
6083
  while (index > 0 && wordClass(graphemes2[index - 1]) === "space")
@@ -5897,13 +6110,13 @@ function wordClass(value) {
5897
6110
  return /^[\p{Letter}\p{Number}\p{Mark}_]+$/u.test(value) ? "word" : "punctuation";
5898
6111
  }
5899
6112
  __name(wordClass, "wordClass");
5900
- function positiveInteger2(value, name) {
6113
+ function positiveInteger(value, name) {
5901
6114
  if (!Number.isSafeInteger(value) || value < 1) {
5902
6115
  throw new RangeError(`${name} must be a positive safe integer`);
5903
6116
  }
5904
6117
  return value;
5905
6118
  }
5906
- __name(positiveInteger2, "positiveInteger");
6119
+ __name(positiveInteger, "positiveInteger");
5907
6120
 
5908
6121
  // packages/ui/tui/dist/focus.js
5909
6122
  var FocusManager = class {
@@ -5960,22 +6173,120 @@ var FocusManager = class {
5960
6173
  this.entries.splice(index, 1);
5961
6174
  if (!wasActive)
5962
6175
  return;
5963
- this.activeId = void 0;
5964
- const next = this.entries[Math.min(index, this.entries.length - 1)];
5965
- if (next !== void 0)
5966
- this.focus(next.id);
6176
+ this.activeId = void 0;
6177
+ const next = this.entries[Math.min(index, this.entries.length - 1)];
6178
+ if (next !== void 0)
6179
+ this.focus(next.id);
6180
+ }
6181
+ move(offset) {
6182
+ if (this.entries.length === 0)
6183
+ return false;
6184
+ const currentIndex = this.entries.findIndex((entry) => entry.id === this.activeId);
6185
+ const index = currentIndex < 0 ? 0 : (currentIndex + offset + this.entries.length) % this.entries.length;
6186
+ return this.focus(this.entries[index].id);
6187
+ }
6188
+ current() {
6189
+ return this.entries.find((entry) => entry.id === this.activeId);
6190
+ }
6191
+ };
6192
+
6193
+ // packages/ui/tui/dist/list-selection.js
6194
+ var ListSelectionModel = class {
6195
+ static {
6196
+ __name(this, "ListSelectionModel");
6197
+ }
6198
+ source;
6199
+ pageSize;
6200
+ filter;
6201
+ queryValue = "";
6202
+ index;
6203
+ constructor(items, options = {}) {
6204
+ this.source = [...items];
6205
+ this.pageSize = positiveInteger2(options.pageSize ?? 10, "pageSize");
6206
+ this.filter = options.filter;
6207
+ this.index = clampListIndex(options.initialIndex ?? 0, this.items.length);
6208
+ }
6209
+ get query() {
6210
+ return this.queryValue;
6211
+ }
6212
+ get items() {
6213
+ const normalized = this.queryValue.trim().toLowerCase();
6214
+ return normalized === "" || this.filter === void 0 ? this.source : this.source.filter((item) => this.filter(item, normalized));
6215
+ }
6216
+ get selectedIndex() {
6217
+ return this.index;
6218
+ }
6219
+ get selected() {
6220
+ return this.items[this.index];
6221
+ }
6222
+ setItems(items) {
6223
+ this.source = [...items];
6224
+ this.index = clampListIndex(this.index, this.items.length);
6225
+ }
6226
+ setQuery(query) {
6227
+ this.queryValue = query;
6228
+ this.index = 0;
6229
+ }
6230
+ appendQuery(text) {
6231
+ if (text === "")
6232
+ return;
6233
+ this.setQuery(this.queryValue + text);
5967
6234
  }
5968
- move(offset) {
5969
- if (this.entries.length === 0)
5970
- return false;
5971
- const currentIndex = this.entries.findIndex((entry) => entry.id === this.activeId);
5972
- const index = currentIndex < 0 ? 0 : (currentIndex + offset + this.entries.length) % this.entries.length;
5973
- return this.focus(this.entries[index].id);
6235
+ backspaceQuery() {
6236
+ this.setQuery(removeLastCodePoint(this.queryValue));
5974
6237
  }
5975
- current() {
5976
- return this.entries.find((entry) => entry.id === this.activeId);
6238
+ clearQuery() {
6239
+ this.setQuery("");
6240
+ }
6241
+ move(action) {
6242
+ const count = this.items.length;
6243
+ if (count === 0) {
6244
+ this.index = 0;
6245
+ return;
6246
+ }
6247
+ switch (action) {
6248
+ case "up":
6249
+ this.index = this.index === 0 ? count - 1 : this.index - 1;
6250
+ break;
6251
+ case "down":
6252
+ this.index = this.index === count - 1 ? 0 : this.index + 1;
6253
+ break;
6254
+ case "page-up":
6255
+ this.index = Math.max(0, this.index - this.pageSize);
6256
+ break;
6257
+ case "page-down":
6258
+ this.index = Math.min(count - 1, this.index + this.pageSize);
6259
+ break;
6260
+ case "home":
6261
+ this.index = 0;
6262
+ break;
6263
+ case "end":
6264
+ this.index = count - 1;
6265
+ break;
6266
+ }
5977
6267
  }
5978
6268
  };
6269
+ function printableKeyText(stroke) {
6270
+ if (stroke.ctrl || stroke.alt || stroke.meta)
6271
+ return void 0;
6272
+ return stroke.text !== void 0 && stroke.text.length > 0 ? stroke.text : void 0;
6273
+ }
6274
+ __name(printableKeyText, "printableKeyText");
6275
+ function clampListIndex(index, count) {
6276
+ return count === 0 ? 0 : Math.min(Math.max(index, 0), count - 1);
6277
+ }
6278
+ __name(clampListIndex, "clampListIndex");
6279
+ function removeLastCodePoint(value) {
6280
+ return [...value].slice(0, -1).join("");
6281
+ }
6282
+ __name(removeLastCodePoint, "removeLastCodePoint");
6283
+ function positiveInteger2(value, name) {
6284
+ if (!Number.isSafeInteger(value) || value <= 0) {
6285
+ throw new RangeError(`${name} must be a positive safe integer`);
6286
+ }
6287
+ return value;
6288
+ }
6289
+ __name(positiveInteger2, "positiveInteger");
5979
6290
 
5980
6291
  // packages/ui/tui/dist/session-fork.js
5981
6292
  var SessionForkTree = class {
@@ -6017,7 +6328,18 @@ var SessionForkTree = class {
6017
6328
  throw new Error("History relations contain a cycle");
6018
6329
  this.rows = rows;
6019
6330
  const newest = rows.filter((row) => row.point.available && (!currentSessionId || row.point.sessionId === currentSessionId)).sort((a, b2) => b2.point.createdAt - a.point.createdAt)[0];
6020
- this.selection = new ListSelectionModel(rows, { initialIndex: newest ? rows.indexOf(newest) : 0, pageSize: 8, filter: /* @__PURE__ */ __name((row, query) => [row.point.id, row.point.sessionId, row.point.userPreview, row.point.assistantPreview, row.point.branch, row.point.commit].some((value) => value?.toLocaleLowerCase().includes(query)), "filter") });
6331
+ this.selection = new ListSelectionModel(rows, {
6332
+ initialIndex: newest ? rows.indexOf(newest) : 0,
6333
+ pageSize: 8,
6334
+ filter: /* @__PURE__ */ __name((row, query) => [
6335
+ row.point.id,
6336
+ row.point.sessionId,
6337
+ row.point.userPreview,
6338
+ row.point.assistantPreview,
6339
+ row.point.branch,
6340
+ row.point.commit
6341
+ ].some((value) => value?.toLocaleLowerCase().includes(query)), "filter")
6342
+ });
6021
6343
  }
6022
6344
  get items() {
6023
6345
  return this.selection.items;
@@ -6229,6 +6551,191 @@ var SessionForkPicker = class {
6229
6551
  }
6230
6552
  };
6231
6553
 
6554
+ // packages/ui/tui/dist/workspace-diff.js
6555
+ var WorkspaceDiffViewer = class {
6556
+ static {
6557
+ __name(this, "WorkspaceDiffViewer");
6558
+ }
6559
+ diff;
6560
+ options;
6561
+ selection;
6562
+ mode = "files";
6563
+ offset = 0;
6564
+ pageSize = 10;
6565
+ query = "";
6566
+ notice = "";
6567
+ pending = Promise.resolve();
6568
+ busy = false;
6569
+ constructor(diff, options) {
6570
+ this.diff = diff;
6571
+ this.options = options;
6572
+ this.selection = new ListSelectionModel(diff.files, { pageSize: 10 });
6573
+ }
6574
+ get selectedFile() {
6575
+ return this.selection.selected;
6576
+ }
6577
+ get scrollOffset() {
6578
+ return this.offset;
6579
+ }
6580
+ waitForPending() {
6581
+ return this.pending;
6582
+ }
6583
+ handleKey(stroke) {
6584
+ if (this.busy)
6585
+ return true;
6586
+ if (stroke.ctrl && stroke.key === "c") {
6587
+ this.options.onClose();
6588
+ return true;
6589
+ }
6590
+ const commandKey = !stroke.ctrl && !stroke.alt && !stroke.meta;
6591
+ if (commandKey && this.mode !== "search" && this.diff.restorePreviewId && stroke.key === "y" && this.options.onApply) {
6592
+ this.perform(async () => {
6593
+ await this.options.onApply(this.diff.restorePreviewId);
6594
+ this.options.onClose();
6595
+ });
6596
+ return true;
6597
+ }
6598
+ if (commandKey && this.mode !== "search" && stroke.key === "r" && !this.diff.restorePreviewId && this.selection.selected && this.options.onRestore) {
6599
+ const path = this.selection.selected.path;
6600
+ this.perform(async () => {
6601
+ this.diff = await this.options.onRestore(path);
6602
+ this.selection.setItems(this.diff.files);
6603
+ this.selection.move("home");
6604
+ this.mode = "patch";
6605
+ this.offset = 0;
6606
+ this.query = "";
6607
+ });
6608
+ return true;
6609
+ }
6610
+ if (this.mode === "search") {
6611
+ if (stroke.key === "escape") {
6612
+ this.mode = "patch";
6613
+ this.query = "";
6614
+ } else if (stroke.key === "enter") {
6615
+ this.mode = "patch";
6616
+ this.find(false);
6617
+ } else if (stroke.key === "backspace")
6618
+ this.query = removeLastCodePoint(this.query);
6619
+ else if (stroke.ctrl && stroke.key === "u")
6620
+ this.query = "";
6621
+ else {
6622
+ const text = printableKeyText(stroke);
6623
+ if (text)
6624
+ this.query += text;
6625
+ }
6626
+ return true;
6627
+ }
6628
+ if (stroke.key === "escape") {
6629
+ if (this.mode === "patch") {
6630
+ this.mode = "files";
6631
+ this.offset = 0;
6632
+ } else
6633
+ this.options.onClose();
6634
+ return true;
6635
+ }
6636
+ if (this.mode === "files") {
6637
+ const action = navigation(stroke.key);
6638
+ if (action)
6639
+ this.selection.move(action);
6640
+ if (stroke.key === "enter" && this.selection.selected) {
6641
+ this.mode = "patch";
6642
+ this.offset = 0;
6643
+ this.query = "";
6644
+ }
6645
+ return true;
6646
+ }
6647
+ const file = this.selection.selected;
6648
+ const lines = file?.patch.split("\n") ?? [];
6649
+ const maximum = Math.max(0, lines.length - this.pageSize);
6650
+ if (stroke.key === "up")
6651
+ this.offset = Math.max(0, this.offset - 1);
6652
+ else if (stroke.key === "down")
6653
+ this.offset = Math.min(maximum, this.offset + 1);
6654
+ else if (stroke.key === "pageup")
6655
+ this.offset = Math.max(0, this.offset - this.pageSize);
6656
+ else if (stroke.key === "pagedown")
6657
+ this.offset = Math.min(maximum, this.offset + this.pageSize);
6658
+ else if (stroke.key === "home")
6659
+ this.offset = 0;
6660
+ else if (stroke.key === "end")
6661
+ this.offset = maximum;
6662
+ else if (stroke.key === "/" || stroke.text === "/")
6663
+ this.mode = "search";
6664
+ else if (stroke.key === "n")
6665
+ this.find(true);
6666
+ else if (stroke.key === "]" || stroke.text === "]") {
6667
+ const changes = lines.flatMap((line, index) => line.startsWith("@@") ? [index] : []);
6668
+ this.offset = changes.find((index) => index > this.offset) ?? changes[0] ?? this.offset;
6669
+ }
6670
+ return true;
6671
+ }
6672
+ render(size) {
6673
+ const theme = this.options.theme ?? DEFAULT_DARK_THEME;
6674
+ this.pageSize = Math.max(1, size.height - 5);
6675
+ const totals = this.diff.files.reduce((value, file) => ({ additions: value.additions + file.additions, deletions: value.deletions + file.deletions }), { additions: 0, deletions: 0 });
6676
+ const header2 = [
6677
+ sanitizeTerminalText(this.diff.title),
6678
+ `${this.diff.from?.slice(0, 12) ?? "\u521D\u59CB\u7248\u672C"} \u2192 ${this.diff.uncommitted ? "\u5F53\u524D\u672A\u63D0\u4EA4\u53D8\u5316" : this.diff.to?.slice(0, 12) ?? "\u76EE\u6807\u7248\u672C"} \xB7 ${this.diff.files.length} \u4E2A\u6587\u4EF6 \xB7 +${totals.additions} -${totals.deletions}`,
6679
+ ""
6680
+ ];
6681
+ let body;
6682
+ if (this.mode === "files") {
6683
+ const start = Math.floor(this.selection.selectedIndex / this.pageSize) * this.pageSize;
6684
+ body = this.diff.files.slice(start, start + this.pageSize).map((file, index) => styleText(`${start + index === this.selection.selectedIndex ? "\u25B8" : " "} ${sanitizeTerminalText(file.path)} \xB7 ${file.status} \xB7 ${file.binary ? "\u4E8C\u8FDB\u5236\u6587\u4EF6" : `+${file.additions} -${file.deletions}`}`, start + index === this.selection.selectedIndex ? theme.accent : theme.text));
6685
+ if (!body.length)
6686
+ body.push("\u6CA1\u6709\u6587\u4EF6\u53D8\u5316\u3002");
6687
+ } else {
6688
+ const file = this.selection.selected;
6689
+ body = file?.binary ? ["\u4E8C\u8FDB\u5236\u6587\u4EF6\u65E0\u6CD5\u663E\u793A\u6587\u672C diff\u3002"] : renderDiff(file?.patch ?? "", theme).slice(this.offset, this.offset + this.pageSize).map((line) => line.value);
6690
+ header2[2] = `${sanitizeTerminalText(file?.path ?? "")} \xB7 \u7B2C ${this.offset + 1} \u884C`;
6691
+ }
6692
+ const footer = this.diff.restorePreviewId ? "\u6062\u590D\u9884\u89C8 \xB7 Y \u786E\u8BA4\u6062\u590D\u6587\u4EF6 \xB7 Esc \u8FD4\u56DE\u6216\u53D6\u6D88" : this.mode === "files" ? `\u2191\u2193 \u9009\u62E9\u6587\u4EF6 \xB7 Enter \u67E5\u770B diff${this.options.onRestore ? " \xB7 R \u9884\u89C8\u6062\u590D" : ""} \xB7 Esc \u5173\u95ED` : this.mode === "search" ? `\u641C\u7D22\uFF1A${sanitizeTerminalText(this.query)} \xB7 Enter \u67E5\u627E \xB7 Esc \u53D6\u6D88` : `\u2191\u2193 \u6EDA\u52A8 \xB7 PgUp/PgDn \u7FFB\u9875 \xB7 / \u641C\u7D22 \xB7 N \u4E0B\u4E00\u5904\u5339\u914D \xB7 ] \u4E0B\u4E00\u5904\u4FEE\u6539${this.options.onRestore ? " \xB7 R \u9884\u89C8\u6062\u590D" : ""} \xB7 Esc \u6587\u4EF6\u5217\u8868`;
6693
+ return new Text([...header2, ...body, footer, this.busy ? "\u6B63\u5728\u5904\u7406\u6587\u4EF6\u7248\u672C\u2026" : sanitizeTerminalText(this.notice)].join("\n"), { wrap: false }).render(size);
6694
+ }
6695
+ find(next) {
6696
+ if (!this.query)
6697
+ return;
6698
+ const lines = this.selection.selected?.patch.split("\n") ?? [];
6699
+ const matches = lines.flatMap((line, index) => line.toLocaleLowerCase().includes(this.query.toLocaleLowerCase()) ? [index] : []);
6700
+ const target = (next ? matches.find((index) => index > this.offset) : void 0) ?? matches[0];
6701
+ if (target === void 0)
6702
+ this.notice = "\u6CA1\u6709\u5339\u914D\u7684\u5185\u5BB9\u3002";
6703
+ else {
6704
+ this.offset = target;
6705
+ this.notice = "";
6706
+ }
6707
+ }
6708
+ perform(work) {
6709
+ this.busy = true;
6710
+ this.pending = work().catch((error) => {
6711
+ this.notice = error instanceof Error ? error.message : "\u6587\u4EF6\u7248\u672C\u64CD\u4F5C\u5931\u8D25\u3002";
6712
+ }).finally(() => {
6713
+ this.busy = false;
6714
+ this.options.onInvalidate?.();
6715
+ });
6716
+ this.options.onInvalidate?.();
6717
+ }
6718
+ };
6719
+ function navigation(key) {
6720
+ if (key === "up" || key === "down" || key === "home" || key === "end")
6721
+ return key;
6722
+ if (key === "pageup")
6723
+ return "page-up";
6724
+ if (key === "pagedown")
6725
+ return "page-down";
6726
+ return void 0;
6727
+ }
6728
+ __name(navigation, "navigation");
6729
+ function workspaceGitLabel(workspace) {
6730
+ if (workspace.status === "error")
6731
+ return `Git \u9519\u8BEF${workspace.error ? `\uFF1A${sanitizeTerminalText(workspace.error)}` : ""}`;
6732
+ if (workspace.status === "initializing")
6733
+ return "Git \u5C1A\u672A\u51C6\u5907";
6734
+ const version = workspace.detached ? `detached HEAD \xB7 ${workspace.commit?.slice(0, 12) ?? "\u65E0 commit"}` : workspace.branch ?? "Git \u5C1A\u65E0 commit";
6735
+ return sanitizeTerminalText(`${version}${workspace.autoCommit === false ? " \xB7 \u81EA\u52A8\u63D0\u4EA4\u5173\u95ED" : ""}`);
6736
+ }
6737
+ __name(workspaceGitLabel, "workspaceGitLabel");
6738
+
6232
6739
  // packages/ui/tui/dist/markdown-excerpt.js
6233
6740
  var graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
6234
6741
 
@@ -6249,8 +6756,8 @@ var Overlay = class {
6249
6756
  }
6250
6757
  render(size) {
6251
6758
  const base = this.base.render(size);
6252
- const width = clamp2(this.options.width ?? Math.min(60, size.width), 1, size.width);
6253
- const height = clamp2(this.options.height ?? Math.min(12, size.height), 1, size.height);
6759
+ const width = clamp3(this.options.width ?? Math.min(60, size.width), 1, size.width);
6760
+ const height = clamp3(this.options.height ?? Math.min(12, size.height), 1, size.height);
6254
6761
  const left = alignmentOffset(size.width, width, this.options.horizontal ?? "center");
6255
6762
  const top = alignmentOffset(size.height, height, this.options.vertical ?? "center");
6256
6763
  this.bounds = { left, top, width, height };
@@ -6307,7 +6814,7 @@ var Panel = class {
6307
6814
  const innerWidth = size.width - 2;
6308
6815
  const innerHeight = size.height - 2;
6309
6816
  const child = innerWidth > 0 && innerHeight > 0 ? this.child.render({ width: innerWidth, height: innerHeight }) : { lines: [] };
6310
- const title = this.options.title === void 0 ? "" : ` ${singleLine(this.options.title)} `;
6817
+ const title = this.options.title === void 0 ? "" : ` ${singleLine2(this.options.title)} `;
6311
6818
  const top = styleText(`\u250C${fitLine(title, innerWidth, "\u2500")}\u2510`, this.options.borderStyle);
6312
6819
  const bottom = styleText(`\u2514${"\u2500".repeat(innerWidth)}\u2518`, this.options.borderStyle);
6313
6820
  const side = styleText("\u2502", this.options.borderStyle);
@@ -6315,14 +6822,16 @@ var Panel = class {
6315
6822
  const styledTop = title === "" || this.options.titleStyle === void 0 ? top : replaceTitleStyle(top, sliceAnsi(title, 0, innerWidth), this.options.titleStyle, this.options.borderStyle);
6316
6823
  return {
6317
6824
  lines: [styledTop, ...body, bottom],
6318
- ...child.textRows === void 0 ? {} : { textRows: [
6319
- void 0,
6320
- ...Array.from({ length: innerHeight }, (_2, index) => {
6321
- const row = child.textRows?.[index];
6322
- return row === void 0 ? void 0 : { ...row, spans: row.spans.map((span) => ({ ...span, x: span.x + 1 })) };
6323
- }),
6324
- void 0
6325
- ] },
6825
+ ...child.textRows === void 0 ? {} : {
6826
+ textRows: [
6827
+ void 0,
6828
+ ...Array.from({ length: innerHeight }, (_2, index) => {
6829
+ const row = child.textRows?.[index];
6830
+ return row === void 0 ? void 0 : { ...row, spans: row.spans.map((span) => ({ ...span, x: span.x + 1 })) };
6831
+ }),
6832
+ void 0
6833
+ ]
6834
+ },
6326
6835
  ...child.images?.length ? { images: placeImages(child.images, 1, size.height - 1).map((image) => ({ ...image, x: image.x + 1 })) } : {},
6327
6836
  ...child.cursor === void 0 ? {} : { cursor: { ...child.cursor, x: child.cursor.x + 1, y: child.cursor.y + 1 } }
6328
6837
  };
@@ -6420,10 +6929,10 @@ function alignmentOffset(available, used, alignment) {
6420
6929
  return Math.floor((available - used) / 2);
6421
6930
  }
6422
6931
  __name(alignmentOffset, "alignmentOffset");
6423
- function singleLine(value) {
6932
+ function singleLine2(value) {
6424
6933
  return value.replace(/\s+/gu, " ").trim();
6425
6934
  }
6426
- __name(singleLine, "singleLine");
6935
+ __name(singleLine2, "singleLine");
6427
6936
  function replaceTitleStyle(line, title, titleStyle, borderStyle) {
6428
6937
  const start = 1;
6429
6938
  const before = sliceAnsi(line, 0, start);
@@ -6431,12 +6940,12 @@ function replaceTitleStyle(line, title, titleStyle, borderStyle) {
6431
6940
  return `${before}${styleText(title, titleStyle)}${styleText(after, borderStyle)}`;
6432
6941
  }
6433
6942
  __name(replaceTitleStyle, "replaceTitleStyle");
6434
- function clamp2(value, minimum, maximum) {
6943
+ function clamp3(value, minimum, maximum) {
6435
6944
  if (!Number.isFinite(value))
6436
6945
  return minimum;
6437
6946
  return Math.min(maximum, Math.max(minimum, Math.trunc(value)));
6438
6947
  }
6439
- __name(clamp2, "clamp");
6948
+ __name(clamp3, "clamp");
6440
6949
 
6441
6950
  // packages/ui/tui/dist/scroll-view.js
6442
6951
  var DEFAULT_SCROLL_KEYBINDINGS = [
@@ -6528,7 +7037,7 @@ var ScrollView = class {
6528
7037
  } else if (region.end >= this.offset + this.lastPageSize - safeMargin) {
6529
7038
  next = region.end - this.lastPageSize + safeMargin + 1;
6530
7039
  }
6531
- next = clamp3(next, 0, this.lastMaximumOffset);
7040
+ next = clamp4(next, 0, this.lastMaximumOffset);
6532
7041
  if (next === this.offset && !this.followEnd)
6533
7042
  return false;
6534
7043
  this.offset = next;
@@ -6538,7 +7047,7 @@ var ScrollView = class {
6538
7047
  scrollBy(lines) {
6539
7048
  this.viewportAnchor = void 0;
6540
7049
  this.topAnchor = void 0;
6541
- const next = clamp3(this.offset + Math.trunc(lines), 0, Math.max(this.offset, this.lastMaximumOffset));
7050
+ const next = clamp4(this.offset + Math.trunc(lines), 0, Math.max(this.offset, this.lastMaximumOffset));
6542
7051
  if (next === this.offset)
6543
7052
  return false;
6544
7053
  this.offset = next;
@@ -6614,10 +7123,7 @@ var ScrollView = class {
6614
7123
  return false;
6615
7124
  if (event.type !== "down" && this.pointer === void 0)
6616
7125
  return false;
6617
- const consumed = this.child.handlePointer({
6618
- ...event,
6619
- y: this.offset + clamp3(event.y, 0, this.lastPageSize - 1)
6620
- });
7126
+ const consumed = this.child.handlePointer({ ...event, y: this.offset + clamp4(event.y, 0, this.lastPageSize - 1) });
6621
7127
  if (event.type === "down" && consumed) {
6622
7128
  this.followEnd = false;
6623
7129
  this.topAnchor = void 0;
@@ -6661,7 +7167,11 @@ var ScrollView = class {
6661
7167
  if (!this.scrollBy(direction))
6662
7168
  return;
6663
7169
  this.followEnd = false;
6664
- this.child.handlePointer?.({ ...event, type: "move", y: this.offset + clamp3(event.y, 0, this.lastPageSize - 1) });
7170
+ this.child.handlePointer?.({
7171
+ ...event,
7172
+ type: "move",
7173
+ y: this.offset + clamp4(event.y, 0, this.lastPageSize - 1)
7174
+ });
6665
7175
  this.onInvalidate?.();
6666
7176
  }, 60);
6667
7177
  this.dragTimer.unref?.();
@@ -6682,7 +7192,7 @@ var ScrollView = class {
6682
7192
  const maximumOffset = this.alignedToStart ? Math.max(0, content.lines.length - 1) : this.lastMaximumOffset;
6683
7193
  const anchor = this.viewportAnchor;
6684
7194
  const anchorIndex = anchor === void 0 ? -1 : (content.textRows ?? []).findIndex((row) => row?.sourceId === anchor.sourceId && row.start <= anchor.offset && row.end > anchor.offset);
6685
- this.offset = topRegion !== void 0 ? clamp3(topRegion.start, 0, maximumOffset) : anchoredRegion !== void 0 && pendingAnchor !== void 0 ? clamp3(anchoredRegion.start - pendingAnchor.screenRow, 0, this.lastMaximumOffset) : this.followEnd ? this.lastMaximumOffset : anchorIndex >= 0 && anchor !== void 0 ? clamp3(anchorIndex - anchor.screenRow, 0, maximumOffset) : clamp3(this.offset, 0, maximumOffset);
7195
+ this.offset = topRegion !== void 0 ? clamp4(topRegion.start, 0, maximumOffset) : anchoredRegion !== void 0 && pendingAnchor !== void 0 ? clamp4(anchoredRegion.start - pendingAnchor.screenRow, 0, this.lastMaximumOffset) : this.followEnd ? this.lastMaximumOffset : anchorIndex >= 0 && anchor !== void 0 ? clamp4(anchorIndex - anchor.screenRow, 0, maximumOffset) : clamp4(this.offset, 0, maximumOffset);
6686
7196
  this.viewportAnchor = void 0;
6687
7197
  for (let index = this.offset; index < Math.min(content.lines.length, this.offset + size.height); index++) {
6688
7198
  const row = content.textRows?.[index];
@@ -6719,502 +7229,11 @@ function isFocusTarget(component) {
6719
7229
  return "setFocused" in component && typeof component.setFocused === "function";
6720
7230
  }
6721
7231
  __name(isFocusTarget, "isFocusTarget");
6722
- function clamp3(value, minimum, maximum) {
6723
- return Math.min(maximum, Math.max(minimum, value));
6724
- }
6725
- __name(clamp3, "clamp");
6726
-
6727
- // packages/ui/tui/dist/select-list.js
6728
- var SELECT_LIST_KEYBINDINGS = [
6729
- { context: "select", keys: "up", action: "list.up" },
6730
- { context: "select", keys: "down", action: "list.down" },
6731
- { context: "select", keys: "pageup", action: "list.pageUp" },
6732
- { context: "select", keys: "pagedown", action: "list.pageDown" },
6733
- { context: "select", keys: "home", action: "list.home" },
6734
- { context: "select", keys: "end", action: "list.end" },
6735
- { context: "select", keys: "enter", action: "list.accept" },
6736
- { context: "select", keys: "escape", action: "list.cancel" }
6737
- ];
6738
- var SelectList = class {
6739
- static {
6740
- __name(this, "SelectList");
6741
- }
6742
- options;
6743
- items;
6744
- index;
6745
- offset = 0;
6746
- pageSize = 1;
6747
- focused = false;
6748
- keymap;
6749
- constructor(items, options = {}) {
6750
- this.options = options;
6751
- this.items = [...items];
6752
- this.index = firstEnabled(this.items, options.selectedIndex ?? 0);
6753
- this.keymap = new Keymap(mergeKeyBindings(SELECT_LIST_KEYBINDINGS, options.keybindings), {
6754
- actions: SELECT_LIST_KEYBINDINGS.map((binding) => binding.action)
6755
- });
6756
- }
6757
- get selectedIndex() {
6758
- return this.index;
6759
- }
6760
- get selectedItem() {
6761
- return this.index < 0 ? void 0 : this.items[this.index];
6762
- }
6763
- setItems(items) {
6764
- this.items = [...items];
6765
- this.index = firstEnabled(this.items, Math.max(0, this.index));
6766
- this.offset = 0;
6767
- }
6768
- setFocused(focused) {
6769
- if (focused !== this.focused)
6770
- this.keymap.reset();
6771
- this.focused = focused;
6772
- }
6773
- handleKey(stroke) {
6774
- if (!this.focused)
6775
- return false;
6776
- const result = this.keymap.resolve(stroke, ["select"]);
6777
- if (result.type !== "action")
6778
- return result.type === "pending";
6779
- return this.performAction(result.action);
6780
- }
6781
- performAction(action) {
6782
- switch (action) {
6783
- case "list.up":
6784
- this.move(-1);
6785
- return true;
6786
- case "list.down":
6787
- this.move(1);
6788
- return true;
6789
- case "list.pageUp":
6790
- this.move(-this.pageSize);
6791
- return true;
6792
- case "list.pageDown":
6793
- this.move(this.pageSize);
6794
- return true;
6795
- case "list.home":
6796
- this.moveTo(firstEnabled(this.items, 0));
6797
- return true;
6798
- case "list.end":
6799
- this.moveTo(lastEnabled(this.items));
6800
- return true;
6801
- case "list.accept": {
6802
- const item = this.selectedItem;
6803
- if (item === void 0)
6804
- return false;
6805
- this.options.onSelect?.(item, this.index);
6806
- return true;
6807
- }
6808
- case "list.cancel":
6809
- this.options.onCancel?.();
6810
- return this.options.onCancel !== void 0;
6811
- default:
6812
- return false;
6813
- }
6814
- }
6815
- handlePointer(event) {
6816
- if (event.button !== 0 || event.type !== "down" || event.y < 0 || event.y >= this.pageSize)
6817
- return false;
6818
- const index = this.offset + event.y;
6819
- if (this.items[index] === void 0 || this.items[index].disabled)
6820
- return false;
6821
- this.moveTo(index);
6822
- return true;
6823
- }
6824
- render(size) {
6825
- if (this.items.length === 0) {
6826
- return {
6827
- lines: [sliceAnsi(sanitizeTerminalText(this.options.emptyLabel ?? "No items"), 0, size.width)]
6828
- };
6829
- }
6830
- this.pageSize = size.height;
6831
- if (this.index >= 0) {
6832
- if (this.index < this.offset)
6833
- this.offset = this.index;
6834
- if (this.index >= this.offset + size.height) {
6835
- this.offset = this.index - size.height + 1;
6836
- }
6837
- }
6838
- const maximumOffset = Math.max(0, this.items.length - size.height);
6839
- this.offset = clamp4(this.offset, 0, maximumOffset);
6840
- return {
6841
- lines: this.items.slice(this.offset, this.offset + size.height).map((item, relativeIndex) => {
6842
- const index = this.offset + relativeIndex;
6843
- const marker = index === this.index ? this.focused ? "> " : "\xB7 " : " ";
6844
- const disabled = item.disabled === true ? " (disabled)" : "";
6845
- const plainDescription = item.description === void 0 ? "" : ` \u2014 ${singleLine2(item.description)}`;
6846
- if (index === this.index) {
6847
- const clipped = sliceAnsi(`${marker}${singleLine2(item.label)}${disabled}${plainDescription}`, 0, size.width);
6848
- const padded = `${clipped}${" ".repeat(Math.max(0, size.width - stringWidth(clipped)))}`;
6849
- return styleText(padded, this.options.selectedStyle);
6850
- }
6851
- const description = styleText(plainDescription, this.options.descriptionStyle);
6852
- const line = `${styleText(marker, this.options.markerStyle)}${singleLine2(item.label)}${disabled}${description}`;
6853
- return sliceAnsi(styleText(line, item.disabled === true ? this.options.disabledStyle : void 0), 0, size.width);
6854
- })
6855
- };
6856
- }
6857
- move(offset) {
6858
- if (this.index < 0 || this.items.length === 0)
6859
- return false;
6860
- const direction = offset < 0 ? -1 : 1;
6861
- let remaining = Math.max(1, Math.abs(offset));
6862
- let next = this.index;
6863
- while (remaining > 0) {
6864
- const candidate = nextEnabled(this.items, next, direction);
6865
- if (candidate === next)
6866
- break;
6867
- next = candidate;
6868
- remaining -= 1;
6869
- }
6870
- return this.moveTo(next);
6871
- }
6872
- moveTo(index) {
6873
- if (index < 0 || index === this.index)
6874
- return false;
6875
- this.index = index;
6876
- return true;
6877
- }
6878
- };
6879
- function firstEnabled(items, start) {
6880
- for (let index = clamp4(start, 0, Math.max(0, items.length - 1)); index < items.length; index++) {
6881
- if (items[index].disabled !== true)
6882
- return index;
6883
- }
6884
- for (let index = 0; index < start && index < items.length; index++) {
6885
- if (items[index].disabled !== true)
6886
- return index;
6887
- }
6888
- return -1;
6889
- }
6890
- __name(firstEnabled, "firstEnabled");
6891
- function lastEnabled(items) {
6892
- for (let index = items.length - 1; index >= 0; index--) {
6893
- if (items[index].disabled !== true)
6894
- return index;
6895
- }
6896
- return -1;
6897
- }
6898
- __name(lastEnabled, "lastEnabled");
6899
- function nextEnabled(items, current, direction) {
6900
- for (let index = current + direction; index >= 0 && index < items.length; index += direction) {
6901
- if (items[index].disabled !== true)
6902
- return index;
6903
- }
6904
- return current;
6905
- }
6906
- __name(nextEnabled, "nextEnabled");
6907
- function singleLine2(value) {
6908
- return sanitizeTerminalText(value).replace(/\s+/gu, " ").trim();
6909
- }
6910
- __name(singleLine2, "singleLine");
6911
7232
  function clamp4(value, minimum, maximum) {
6912
- return Math.min(maximum, Math.max(minimum, Math.trunc(value)));
7233
+ return Math.min(maximum, Math.max(minimum, value));
6913
7234
  }
6914
7235
  __name(clamp4, "clamp");
6915
7236
 
6916
- // apps/maybecode/src/mcp-interaction-ui.ts
6917
- async function presentMcpInteraction(request, app, ask, signal) {
6918
- if (app.respondMcpInteraction === void 0) return;
6919
- const header2 = sanitizeTerminalText(`MCP server: ${request.serverId}
6920
- Session: ${request.owner.sessionId}
6921
- Request: ${request.requestId}
6922
- ${request.params.message}
6923
- `);
6924
- const question = /* @__PURE__ */ __name(async (prompt) => {
6925
- signal.throwIfAborted();
6926
- const answer = await ask(sanitizeTerminalText(prompt), signal);
6927
- signal.throwIfAborted();
6928
- return answer;
6929
- }, "question");
6930
- let error = "";
6931
- while (!signal.aborted) {
6932
- if (request.params.mode === "review") {
6933
- let data = request.params.data;
6934
- let edited = false;
6935
- for (; ; ) {
6936
- const choice = (await question(`${header2}
6937
- Host review: ${request.params.kind}
6938
- ${JSON.stringify(data, null, 2)}
6939
- ${error}Type allow to approve${request.params.editable ? ", edit to change the JSON" : ""}, decline, or cancel: `))?.trim().toLowerCase();
6940
- if (choice === "edit" && request.params.editable) {
6941
- try {
6942
- const input = await question(`${header2}
6943
- Enter the replacement JSON document (reviewed again before sending), or cancel: `);
6944
- if (input === void 0 || input.trim() === "cancel") {
6945
- app.respondMcpInteraction(request.id, { action: "cancel" });
6946
- return;
6947
- }
6948
- if (Buffer.byteLength(input) > 48 * 1024) throw new Error();
6949
- data = JSON.parse(input);
6950
- edited = true;
6951
- error = "";
6952
- } catch {
6953
- error = "Invalid JSON or document too large.\n";
6954
- }
6955
- continue;
6956
- }
6957
- app.respondMcpInteraction(request.id, {
6958
- action: choice === "allow" ? "accept" : choice === "decline" ? "decline" : "cancel",
6959
- ...choice !== "allow" || !edited ? {} : { content: { json: JSON.stringify(data) } }
6960
- });
6961
- return;
6962
- }
6963
- }
6964
- if (request.params.mode === "url") {
6965
- let url;
6966
- try {
6967
- url = new URL(request.params.url);
6968
- if (!["https:", "http:"].includes(url.protocol) || url.username || url.password) throw new Error("Unsafe URL");
6969
- } catch {
6970
- app.respondMcpInteraction(request.id, { action: "decline" });
6971
- return;
6972
- }
6973
- const consent = await question(`${header2}
6974
- External host: ${url.host}
6975
- URL: ${request.params.url}
6976
- This is an untrusted external website, not MCP client login. Nothing opens automatically.
6977
- Type accept to consent, decline to refuse, or cancel to dismiss: `);
6978
- if (consent?.trim().toLowerCase() !== "accept") {
6979
- app.respondMcpInteraction(request.id, { action: consent?.trim().toLowerCase() === "decline" ? "decline" : "cancel" });
6980
- return;
6981
- }
6982
- const resume = await question(`${header2}
6983
- Open the displayed URL yourself if you wish.
6984
- After interacting with the website, type retry to resume the original request, or cancel: `);
6985
- app.respondMcpInteraction(request.id, { action: resume?.trim().toLowerCase() === "retry" ? "accept" : "cancel" });
6986
- return;
6987
- }
6988
- const answer = await question(`${header2}
6989
- Never enter passwords, API keys, tokens or payment credentials.
6990
- Requested form (untrusted):
6991
- ${JSON.stringify(request.params.requestedSchema, null, 2)}
6992
- ${error}Enter a JSON object, decline, or cancel: `);
6993
- if (answer === void 0 || ["decline", "cancel"].includes(answer.trim().toLowerCase())) {
6994
- app.respondMcpInteraction(request.id, { action: answer?.trim().toLowerCase() === "decline" ? "decline" : "cancel" });
6995
- return;
6996
- }
6997
- let content;
6998
- try {
6999
- if (Buffer.byteLength(answer) > 64 * 1024) throw new Error();
7000
- const parsed = JSON.parse(answer);
7001
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error();
7002
- content = parsed;
7003
- } catch {
7004
- error = "Invalid JSON object or response too large.\n";
7005
- continue;
7006
- }
7007
- const review = await question(`${header2}
7008
- Review what will be sent ONLY to this server:
7009
- ${JSON.stringify(content, null, 2)}
7010
- Type send to submit, edit to replace, decline, or cancel: `);
7011
- const action = review?.trim().toLowerCase();
7012
- if (action === "edit") continue;
7013
- if (action !== "send") {
7014
- app.respondMcpInteraction(request.id, { action: action === "decline" ? "decline" : "cancel" });
7015
- return;
7016
- }
7017
- try {
7018
- app.respondMcpInteraction(request.id, { action: "accept", content });
7019
- return;
7020
- } catch {
7021
- error = "The response does not satisfy the form; please correct it.\n";
7022
- }
7023
- }
7024
- }
7025
- __name(presentMcpInteraction, "presentMcpInteraction");
7026
-
7027
- // apps/maybecode/src/terminal-web.ts
7028
- import { randomBytes } from "node:crypto";
7029
- import open from "open";
7030
- import { AsyncEventQueue, isStreamingMayEvent } from "@sortedyuan/core";
7031
- function eventQueue() {
7032
- return new AsyncEventQueue({
7033
- maxBufferedValues: 1024,
7034
- isDroppable: /* @__PURE__ */ __name((event) => event.type === "mcp.resource.updated" || event.type === "run.event" && isStreamingMayEvent(event.event), "isDroppable")
7035
- });
7036
- }
7037
- __name(eventQueue, "eventQueue");
7038
- var MaybeCodeTerminalWeb = class {
7039
- constructor(app, exit) {
7040
- this.app = app;
7041
- this.exit = exit;
7042
- this.host = createMaybeCodeWebHost(app, { events: this.webEvents, closeApplication: false, terminal: true });
7043
- this.events = this.readTerminalEvents();
7044
- this.relay = this.forwardEvents().catch((error) => {
7045
- this.failure = error;
7046
- });
7047
- }
7048
- app;
7049
- exit;
7050
- static {
7051
- __name(this, "MaybeCodeTerminalWeb");
7052
- }
7053
- terminalEvents = eventQueue();
7054
- webEvents = eventQueue();
7055
- host;
7056
- relay;
7057
- failure;
7058
- starting;
7059
- closing;
7060
- events;
7061
- async forwardEvents() {
7062
- try {
7063
- for await (const event of this.app.events) {
7064
- this.terminalEvents.push(event);
7065
- this.webEvents.push(event);
7066
- }
7067
- } catch (error) {
7068
- this.failure = error;
7069
- throw error;
7070
- } finally {
7071
- this.terminalEvents.close();
7072
- this.webEvents.close();
7073
- }
7074
- }
7075
- async *readTerminalEvents() {
7076
- for await (const event of this.terminalEvents) yield event;
7077
- if (this.failure !== void 0) throw this.failure;
7078
- }
7079
- async open() {
7080
- const server = await this.startServer();
7081
- const url = server.createLoginUrl();
7082
- try {
7083
- await open(url);
7084
- } catch {
7085
- throw new Error("\u65E0\u6CD5\u6253\u5F00\u9ED8\u8BA4\u6D4F\u89C8\u5668\uFF0C\u8BF7\u68C0\u67E5\u7CFB\u7EDF\u6D4F\u89C8\u5668\u8BBE\u7F6E\u540E\u91CD\u65B0\u6267\u884C /web\u3002");
7086
- }
7087
- return server.url;
7088
- }
7089
- async startServer() {
7090
- if (this.closing) throw new Error("MaybeCode \u6B63\u5728\u5173\u95ED\u3002");
7091
- this.starting ??= startMaybeCodeWebServer(this.host, { token: randomBytes(32).toString("base64url"), port: 0, browserLogin: true, exit: /* @__PURE__ */ __name(() => {
7092
- if (this.exit) this.exit();
7093
- else void this.close();
7094
- }, "exit") });
7095
- const server = await this.starting;
7096
- if (this.closing) throw new Error("MaybeCode \u6B63\u5728\u5173\u95ED\u3002");
7097
- return server;
7098
- }
7099
- close() {
7100
- return this.closing ??= this.closeOwnedResources();
7101
- }
7102
- async closeOwnedResources() {
7103
- const results = await Promise.allSettled([
7104
- this.app.close(),
7105
- this.starting ? this.starting.then((server) => server.close()) : this.host.close()
7106
- ]);
7107
- await this.relay;
7108
- const failures = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
7109
- if (this.failure !== void 0) failures.push(this.failure);
7110
- if (failures.length) throw new AggregateError(failures, "\u5173\u95ED MaybeCode \u65F6\u53D1\u751F\u9519\u8BEF\u3002");
7111
- }
7112
- };
7113
-
7114
- // apps/maybecode/src/keymap.ts
7115
- var MAYBECODE_KEY_ACTIONS = [
7116
- "app.interrupt",
7117
- "app.tools.toggle",
7118
- "app.thinking.toggle",
7119
- "app.reply.start",
7120
- "app.focus.next",
7121
- "app.focus.previous",
7122
- "app.selection.copy",
7123
- "list.up",
7124
- "list.down",
7125
- "list.pageUp",
7126
- "list.pageDown",
7127
- "list.home",
7128
- "list.end",
7129
- "list.accept",
7130
- "list.cancel",
7131
- "preview.toggle",
7132
- "search.start",
7133
- "search.finish",
7134
- "text.backspace",
7135
- "text.clear",
7136
- "session.rename.start",
7137
- "session.rename.accept",
7138
- "session.delete.request",
7139
- "session.delete.accept",
7140
- "session.delete.cancel",
7141
- "model.default.set",
7142
- "approval.allow",
7143
- "approval.allowSession",
7144
- "approval.deny",
7145
- "request.cancel",
7146
- "request.pageUp",
7147
- "request.pageDown",
7148
- "request.scrollUp",
7149
- "request.scrollDown"
7150
- ];
7151
- var MAYBECODE_EDITOR_KEYBINDINGS = [
7152
- { context: "editor", keys: "ctrl+j", action: "editor.newline" }
7153
- ];
7154
- var MAYBECODE_DEFAULT_KEYBINDINGS = [
7155
- { context: "global", keys: "ctrl+c", action: "app.interrupt" },
7156
- { context: "dialog", keys: "ctrl+c", action: "app.interrupt" },
7157
- { context: "global", keys: "<leader> d", action: "app.tools.toggle" },
7158
- { context: "global", keys: "<leader> t", action: "app.thinking.toggle" },
7159
- { context: "global", keys: "<leader> r", action: "app.reply.start" },
7160
- { context: "global", keys: "tab", action: "app.focus.next" },
7161
- { context: "global", keys: "shift+tab", action: "app.focus.previous" },
7162
- { context: "transcript.selection", keys: "ctrl+c", action: "app.selection.copy" },
7163
- { context: "select", keys: "up", action: "list.up" },
7164
- { context: "select", keys: "down", action: "list.down" },
7165
- { context: "select", keys: "pageup", action: "list.pageUp" },
7166
- { context: "select", keys: "pagedown", action: "list.pageDown" },
7167
- { context: "select", keys: "home", action: "list.home" },
7168
- { context: "select", keys: "end", action: "list.end" },
7169
- { context: "select", keys: "enter", action: "list.accept" },
7170
- { context: "select", keys: "escape", action: "list.cancel" },
7171
- { context: "sessionPicker", keys: "space", action: "preview.toggle" },
7172
- { context: "sessionPicker", keys: "/", action: "search.start" },
7173
- { context: "sessionPicker", keys: "d", action: "session.delete.request" },
7174
- { context: "sessionPicker", keys: "r", action: "session.rename.start" },
7175
- { context: "modelPicker", keys: "d", action: "model.default.set" },
7176
- { context: "approval", keys: "a", action: "approval.allow" },
7177
- { context: "approval", keys: "s", action: "approval.allowSession" },
7178
- { context: "approval", keys: "d", action: "approval.deny" },
7179
- { context: "mcpInput", keys: "escape", action: "request.cancel" },
7180
- { context: "mcpInput", keys: "pageup", action: "request.pageUp" },
7181
- { context: "mcpInput", keys: "pagedown", action: "request.pageDown" },
7182
- { context: "mcpInput", keys: "wheelup", action: "request.scrollUp" },
7183
- { context: "mcpInput", keys: "wheeldown", action: "request.scrollDown" },
7184
- { context: "sessionSearch", keys: "escape", action: "list.cancel" },
7185
- { context: "sessionSearch", keys: "enter", action: "search.finish" },
7186
- { context: "sessionSearch", keys: "backspace", action: "text.backspace" },
7187
- { context: "sessionSearch", keys: "ctrl+u", action: "text.clear" },
7188
- { context: "sessionSearch", keys: "up", action: "list.up" },
7189
- { context: "sessionSearch", keys: "down", action: "list.down" },
7190
- { context: "sessionSearch", keys: "pageup", action: "list.pageUp" },
7191
- { context: "sessionSearch", keys: "pagedown", action: "list.pageDown" },
7192
- { context: "sessionRename", keys: "escape", action: "list.cancel" },
7193
- { context: "sessionRename", keys: "enter", action: "session.rename.accept" },
7194
- { context: "sessionRename", keys: "backspace", action: "text.backspace" },
7195
- { context: "sessionRename", keys: "ctrl+u", action: "text.clear" },
7196
- { context: "sessionDelete", keys: "y", action: "session.delete.accept" },
7197
- { context: "sessionDelete", keys: "n", action: "session.delete.cancel" },
7198
- { context: "sessionDelete", keys: "escape", action: "session.delete.cancel" }
7199
- ];
7200
- function createMaybeCodeKeymap(options = {}) {
7201
- const leader = options.leader ?? "ctrl+g";
7202
- const sequence = parseKeySequence(leader);
7203
- if (sequence.length !== 1 || !sequence[0].ctrl && !sequence[0].alt && !sequence[0].meta) {
7204
- throw new Error("MaybeCode leader must be one modified key, for example ctrl+g");
7205
- }
7206
- const leaderKey = formatKeySequence(sequence);
7207
- if (mergeKeyBindings(DEFAULT_EDITOR_KEYBINDINGS, MAYBECODE_EDITOR_KEYBINDINGS).some((binding) => formatKeySequence(parseKeySequence(binding.keys)) === leaderKey)) {
7208
- throw new Error("MaybeCode leader conflicts with a text editing shortcut");
7209
- }
7210
- return new Keymap(mergeKeyBindings(MAYBECODE_DEFAULT_KEYBINDINGS, options.bindings, { leader }), {
7211
- actions: MAYBECODE_KEY_ACTIONS,
7212
- leader,
7213
- chordTimeoutMs: null
7214
- });
7215
- }
7216
- __name(createMaybeCodeKeymap, "createMaybeCodeKeymap");
7217
-
7218
7237
  export {
7219
7238
  createTerminalClipboard,
7220
7239
  DEFAULT_DARK_THEME,
@@ -7222,15 +7241,11 @@ export {
7222
7241
  Text,
7223
7242
  sanitizeTerminalText,
7224
7243
  TerminalImages,
7225
- encodeImage,
7226
7244
  Column,
7245
+ DEFAULT_EDITOR_KEYBINDINGS,
7227
7246
  EditorHistory,
7228
7247
  Editor,
7229
7248
  FocusManager,
7230
- ListSelectionModel,
7231
- resolveListInput,
7232
- printableKeyText,
7233
- removeLastCodePoint,
7234
7249
  SessionForkPicker,
7235
7250
  WorkspaceDiffViewer,
7236
7251
  workspaceGitLabel,
@@ -7242,10 +7257,6 @@ export {
7242
7257
  SelectList,
7243
7258
  NodeTerminalDriver,
7244
7259
  TranscriptStore,
7245
- TranscriptView,
7246
- MAYBECODE_EDITOR_KEYBINDINGS,
7247
- createMaybeCodeKeymap,
7248
- presentMcpInteraction,
7249
- MaybeCodeTerminalWeb
7260
+ TranscriptView
7250
7261
  };
7251
- //# sourceMappingURL=chunk-LVTRXPDS.js.map
7262
+ //# sourceMappingURL=chunk-4B2Z6KW7.js.map