@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,14 +1,25 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
+ import {
3
+ createMaybeCodeSlashCommandSuggester,
4
+ createMaybeCodeWebHost,
5
+ delegationOrder,
6
+ executeMaybeCodeSlashCommand,
7
+ formatDelegationTree,
8
+ formatGoal,
9
+ formatMaybeCodeMcpStatus,
10
+ parseMaybeCodeSlashCommand,
11
+ renderDelegationTask,
12
+ startMaybeCodeWebServer
13
+ } from "./chunk-WMSG5ZTR.js";
2
14
  import {
3
15
  Column,
4
16
  DEFAULT_DARK_THEME,
17
+ DEFAULT_EDITOR_KEYBINDINGS,
5
18
  Dialog,
6
19
  Editor,
7
20
  EditorHistory,
8
21
  FocusManager,
9
22
  FullscreenRenderer,
10
- MAYBECODE_EDITOR_KEYBINDINGS,
11
- MaybeCodeTerminalWeb,
12
23
  NodeTerminalDriver,
13
24
  Panel,
14
25
  ScrollView,
@@ -20,36 +31,140 @@ import {
20
31
  TranscriptView,
21
32
  TuiRuntime,
22
33
  WorkspaceDiffViewer,
23
- createMaybeCodeKeymap,
24
34
  createTerminalClipboard,
25
- presentMcpInteraction,
26
35
  sanitizeTerminalText,
27
36
  styleText,
28
37
  workspaceGitLabel
29
- } from "./chunk-LVTRXPDS.js";
38
+ } from "./chunk-4B2Z6KW7.js";
39
+ import "./chunk-Z3BOPBVU.js";
40
+ import "./chunk-XTEMRAQW.js";
30
41
  import {
31
- createMaybeCodeSlashCommandSuggester,
32
- delegationOrder,
33
- executeMaybeCodeSlashCommand,
34
- formatDelegationTree,
35
- formatGoal,
36
- formatMaybeCodeMcpStatus,
37
- parseMaybeCodeSlashCommand,
38
- renderDelegationTask
39
- } from "./chunk-7ISOHFS7.js";
40
- import "./chunk-HOU5ITUK.js";
41
- import "./chunk-JT6VBKOM.js";
42
- import "./chunk-H7SNBFO4.js";
43
- import "./chunk-VAZMCNBB.js";
44
- import "./chunk-K5JWPNSY.js";
42
+ Keymap,
43
+ formatKeySequence,
44
+ mergeKeyBindings,
45
+ parseKeySequence
46
+ } from "./chunk-4WG6JIJJ.js";
47
+ import "./chunk-MNBYXL5Y.js";
48
+ import "./chunk-5SLWALZK.js";
49
+ import "./chunk-UQDZ55LQ.js";
45
50
  import "./chunk-BSBNNF34.js";
46
51
  import {
47
52
  __name
48
53
  } from "./chunk-E732GDOI.js";
49
54
 
50
55
  // apps/maybecode/src/ui/retained-tui.ts
56
+ import { omitUndefined as omitUndefined2 } from "@sortedyuan/may/core";
51
57
  import { userInfo } from "node:os";
52
58
 
59
+ // apps/maybecode/src/ui/terminal-view.ts
60
+ import { omitUndefined } from "@sortedyuan/may/core";
61
+
62
+ // apps/maybecode/src/keymap.ts
63
+ var MAYBECODE_KEY_ACTIONS = [
64
+ "app.interrupt",
65
+ "app.tools.toggle",
66
+ "app.thinking.toggle",
67
+ "app.reply.start",
68
+ "app.focus.next",
69
+ "app.focus.previous",
70
+ "app.selection.copy",
71
+ "list.up",
72
+ "list.down",
73
+ "list.pageUp",
74
+ "list.pageDown",
75
+ "list.home",
76
+ "list.end",
77
+ "list.accept",
78
+ "list.cancel",
79
+ "preview.toggle",
80
+ "search.start",
81
+ "search.finish",
82
+ "text.backspace",
83
+ "text.clear",
84
+ "session.rename.start",
85
+ "session.rename.accept",
86
+ "session.delete.request",
87
+ "session.delete.accept",
88
+ "session.delete.cancel",
89
+ "model.default.set",
90
+ "approval.allow",
91
+ "approval.allowSession",
92
+ "approval.deny",
93
+ "request.cancel",
94
+ "request.pageUp",
95
+ "request.pageDown",
96
+ "request.scrollUp",
97
+ "request.scrollDown"
98
+ ];
99
+ var MAYBECODE_EDITOR_KEYBINDINGS = [
100
+ { context: "editor", keys: "ctrl+j", action: "editor.newline" }
101
+ ];
102
+ var MAYBECODE_DEFAULT_KEYBINDINGS = [
103
+ { context: "global", keys: "ctrl+c", action: "app.interrupt" },
104
+ { context: "dialog", keys: "ctrl+c", action: "app.interrupt" },
105
+ { context: "global", keys: "<leader> d", action: "app.tools.toggle" },
106
+ { context: "global", keys: "<leader> t", action: "app.thinking.toggle" },
107
+ { context: "global", keys: "<leader> r", action: "app.reply.start" },
108
+ { context: "global", keys: "tab", action: "app.focus.next" },
109
+ { context: "global", keys: "shift+tab", action: "app.focus.previous" },
110
+ { context: "transcript.selection", keys: "ctrl+c", action: "app.selection.copy" },
111
+ { context: "select", keys: "up", action: "list.up" },
112
+ { context: "select", keys: "down", action: "list.down" },
113
+ { context: "select", keys: "pageup", action: "list.pageUp" },
114
+ { context: "select", keys: "pagedown", action: "list.pageDown" },
115
+ { context: "select", keys: "home", action: "list.home" },
116
+ { context: "select", keys: "end", action: "list.end" },
117
+ { context: "select", keys: "enter", action: "list.accept" },
118
+ { context: "select", keys: "escape", action: "list.cancel" },
119
+ { context: "sessionPicker", keys: "space", action: "preview.toggle" },
120
+ { context: "sessionPicker", keys: "/", action: "search.start" },
121
+ { context: "sessionPicker", keys: "d", action: "session.delete.request" },
122
+ { context: "sessionPicker", keys: "r", action: "session.rename.start" },
123
+ { context: "modelPicker", keys: "d", action: "model.default.set" },
124
+ { context: "approval", keys: "a", action: "approval.allow" },
125
+ { context: "approval", keys: "s", action: "approval.allowSession" },
126
+ { context: "approval", keys: "d", action: "approval.deny" },
127
+ { context: "mcpInput", keys: "escape", action: "request.cancel" },
128
+ { context: "mcpInput", keys: "pageup", action: "request.pageUp" },
129
+ { context: "mcpInput", keys: "pagedown", action: "request.pageDown" },
130
+ { context: "mcpInput", keys: "wheelup", action: "request.scrollUp" },
131
+ { context: "mcpInput", keys: "wheeldown", action: "request.scrollDown" },
132
+ { context: "sessionSearch", keys: "escape", action: "list.cancel" },
133
+ { context: "sessionSearch", keys: "enter", action: "search.finish" },
134
+ { context: "sessionSearch", keys: "backspace", action: "text.backspace" },
135
+ { context: "sessionSearch", keys: "ctrl+u", action: "text.clear" },
136
+ { context: "sessionSearch", keys: "up", action: "list.up" },
137
+ { context: "sessionSearch", keys: "down", action: "list.down" },
138
+ { context: "sessionSearch", keys: "pageup", action: "list.pageUp" },
139
+ { context: "sessionSearch", keys: "pagedown", action: "list.pageDown" },
140
+ { context: "sessionRename", keys: "escape", action: "list.cancel" },
141
+ { context: "sessionRename", keys: "enter", action: "session.rename.accept" },
142
+ { context: "sessionRename", keys: "backspace", action: "text.backspace" },
143
+ { context: "sessionRename", keys: "ctrl+u", action: "text.clear" },
144
+ { context: "sessionDelete", keys: "y", action: "session.delete.accept" },
145
+ { context: "sessionDelete", keys: "n", action: "session.delete.cancel" },
146
+ { context: "sessionDelete", keys: "escape", action: "session.delete.cancel" }
147
+ ];
148
+ function createMaybeCodeKeymap(options = {}) {
149
+ const leader = options.leader ?? "ctrl+g";
150
+ const sequence = parseKeySequence(leader);
151
+ if (sequence.length !== 1 || !sequence[0].ctrl && !sequence[0].alt && !sequence[0].meta) {
152
+ throw new Error("MaybeCode leader must be one modified key, for example ctrl+g");
153
+ }
154
+ const leaderKey = formatKeySequence(sequence);
155
+ if (mergeKeyBindings(DEFAULT_EDITOR_KEYBINDINGS, MAYBECODE_EDITOR_KEYBINDINGS).some(
156
+ (binding) => formatKeySequence(parseKeySequence(binding.keys)) === leaderKey
157
+ )) {
158
+ throw new Error("MaybeCode leader conflicts with a text editing shortcut");
159
+ }
160
+ return new Keymap(mergeKeyBindings(MAYBECODE_DEFAULT_KEYBINDINGS, options.bindings, { leader }), {
161
+ actions: MAYBECODE_KEY_ACTIONS,
162
+ leader,
163
+ chordTimeoutMs: null
164
+ });
165
+ }
166
+ __name(createMaybeCodeKeymap, "createMaybeCodeKeymap");
167
+
53
168
  // apps/maybecode/src/ui/theme.ts
54
169
  var MAYBECODE_DARK_THEME = {
55
170
  ...DEFAULT_DARK_THEME,
@@ -134,8 +249,8 @@ var MaybeCodeUiActionRegistry = class {
134
249
  }
135
250
  };
136
251
 
137
- // apps/maybecode/src/ui/prototype-view.ts
138
- var MaybeCodePrototypeView = class {
252
+ // apps/maybecode/src/ui/terminal-view.ts
253
+ var MaybeCodeTerminalView = class {
139
254
  constructor(options) {
140
255
  this.options = options;
141
256
  this.keymap = createMaybeCodeKeymap(options.keymap);
@@ -148,7 +263,7 @@ var MaybeCodePrototypeView = class {
148
263
  assistantLabel: "MaybeCode",
149
264
  selectedToolDetailsHint: "Enter details",
150
265
  toolDetailsHint: `${this.shortcutHint("app.tools.toggle")} all`,
151
- ...options.toolRenderers === void 0 ? {} : { toolRenderers: options.toolRenderers }
266
+ ...omitUndefined({ toolRenderers: options.toolRenderers })
152
267
  });
153
268
  this.transcript = new ScrollView(this.transcriptView, {
154
269
  followEnd: true,
@@ -197,7 +312,7 @@ var MaybeCodePrototypeView = class {
197
312
  }
198
313
  options;
199
314
  static {
200
- __name(this, "MaybeCodePrototypeView");
315
+ __name(this, "MaybeCodeTerminalView");
201
316
  }
202
317
  focus = new FocusManager();
203
318
  keymap;
@@ -236,7 +351,8 @@ var MaybeCodePrototypeView = class {
236
351
  handlePointer: /* @__PURE__ */ __name((event) => {
237
352
  if (event.type === "down") {
238
353
  if (event.button !== 0) return false;
239
- if (event.x < 1 || event.x >= this.editorSize.width - 1 || event.y < 1 || event.y >= this.editorSize.height - 1) return false;
354
+ if (event.x < 1 || event.x >= this.editorSize.width - 1 || event.y < 1 || event.y >= this.editorSize.height - 1)
355
+ return false;
240
356
  this.resetInputContext();
241
357
  this.focus.focus("editor");
242
358
  this.transcriptView.clearSelection();
@@ -296,7 +412,7 @@ var MaybeCodePrototypeView = class {
296
412
  editorOptions() {
297
413
  return {
298
414
  keybindings: MAYBECODE_EDITOR_KEYBINDINGS,
299
- ...this.options.clipboard === void 0 ? {} : { clipboard: this.options.clipboard },
415
+ ...omitUndefined({ clipboard: this.options.clipboard }),
300
416
  onInvalidate: /* @__PURE__ */ __name(() => this.options.onInvalidate?.(), "onInvalidate"),
301
417
  onError: /* @__PURE__ */ __name((error) => this.setStatus(`Error: ${error instanceof Error ? error.message : String(error)}`), "onError")
302
418
  };
@@ -337,29 +453,30 @@ var MaybeCodePrototypeView = class {
337
453
  return new Promise((resolve) => {
338
454
  let settled = false;
339
455
  const abort = /* @__PURE__ */ __name(() => pending.finish(), "abort");
340
- const pending = { prompt, finish: /* @__PURE__ */ __name((value) => {
341
- if (settled) return;
342
- settled = true;
343
- signal.removeEventListener("abort", abort);
344
- const index = this.mcpQuestions.indexOf(pending);
345
- if (index >= 0) this.mcpQuestions.splice(index, 1);
346
- if (index === 0 && this.dialogKind === "mcp") {
347
- this.dialog = void 0;
348
- this.dialogKind = void 0;
349
- this.openCurrentApproval();
350
- }
351
- resolve(value);
352
- this.options.onInvalidate?.();
353
- }, "finish") };
456
+ const pending = {
457
+ prompt,
458
+ finish: /* @__PURE__ */ __name((value) => {
459
+ if (settled) return;
460
+ settled = true;
461
+ signal.removeEventListener("abort", abort);
462
+ const index = this.mcpQuestions.indexOf(pending);
463
+ if (index >= 0) this.mcpQuestions.splice(index, 1);
464
+ if (index === 0 && this.dialogKind === "mcp") {
465
+ this.dialog = void 0;
466
+ this.dialogKind = void 0;
467
+ this.openCurrentApproval();
468
+ }
469
+ resolve(value);
470
+ this.options.onInvalidate?.();
471
+ }, "finish")
472
+ };
354
473
  this.mcpQuestions.push(pending);
355
474
  signal.addEventListener("abort", abort, { once: true });
356
475
  this.openCurrentApproval();
357
476
  });
358
477
  }
359
478
  dismissApproval(requestId) {
360
- const index = this.approvalQueue.findIndex(
361
- (item) => item.request.id === requestId
362
- );
479
+ const index = this.approvalQueue.findIndex((item) => item.request.id === requestId);
363
480
  if (index < 0) return false;
364
481
  const [approval] = this.approvalQueue.splice(index, 1);
365
482
  approval?.resolve(void 0);
@@ -377,15 +494,22 @@ var MaybeCodePrototypeView = class {
377
494
  }
378
495
  return new Promise((resolve) => {
379
496
  this.resolveSessionDialog = resolve;
380
- const prompt = new SessionPrompt(sessions, currentSessionId, this.theme, (action) => {
381
- this.dialog = void 0;
382
- this.dialogKind = void 0;
383
- const complete = this.resolveSessionDialog;
384
- this.resolveSessionDialog = void 0;
385
- complete?.(action);
386
- this.openCurrentApproval();
387
- this.options.onInvalidate?.();
388
- }, this.editorOptions(), this.options.keymap);
497
+ const prompt = new SessionPrompt(
498
+ sessions,
499
+ currentSessionId,
500
+ this.theme,
501
+ (action) => {
502
+ this.dialog = void 0;
503
+ this.dialogKind = void 0;
504
+ const complete = this.resolveSessionDialog;
505
+ this.resolveSessionDialog = void 0;
506
+ complete?.(action);
507
+ this.openCurrentApproval();
508
+ this.options.onInvalidate?.();
509
+ },
510
+ this.editorOptions(),
511
+ this.options.keymap
512
+ );
389
513
  this.dialog = new Dialog(this.baseView, prompt, {
390
514
  open: true,
391
515
  title: "Sessions",
@@ -441,15 +565,20 @@ var MaybeCodePrototypeView = class {
441
565
  }
442
566
  return new Promise((resolve) => {
443
567
  this.resolveEffortDialog = resolve;
444
- const prompt = new EffortPrompt(state, this.theme, (effort) => {
445
- this.dialog = void 0;
446
- this.dialogKind = void 0;
447
- const complete = this.resolveEffortDialog;
448
- this.resolveEffortDialog = void 0;
449
- complete?.(effort);
450
- this.openCurrentApproval();
451
- this.options.onInvalidate?.();
452
- }, this.options.keymap);
568
+ const prompt = new EffortPrompt(
569
+ state,
570
+ this.theme,
571
+ (effort) => {
572
+ this.dialog = void 0;
573
+ this.dialogKind = void 0;
574
+ const complete = this.resolveEffortDialog;
575
+ this.resolveEffortDialog = void 0;
576
+ complete?.(effort);
577
+ this.openCurrentApproval();
578
+ this.options.onInvalidate?.();
579
+ },
580
+ this.options.keymap
581
+ );
453
582
  this.dialog = new Dialog(this.baseView, prompt, {
454
583
  open: true,
455
584
  title: "Reasoning effort",
@@ -479,8 +608,20 @@ var MaybeCodePrototypeView = class {
479
608
  if (this.dialog) return Promise.reject(new Error("Another dialog is already open"));
480
609
  return new Promise((resolve) => {
481
610
  this.resolveVersionDialog = resolve;
482
- const picker = new SessionForkPicker(points, { currentSessionId, theme: this.theme, onComplete: /* @__PURE__ */ __name((selection) => this.completeVersionDialog(selection), "onComplete") });
483
- this.dialog = new Dialog(this.baseView, picker, { open: true, title: "Session \u5206\u652F", width: 100, height: 25, dismissOnEscape: false, borderStyle: this.theme.borderAccent, titleStyle: this.theme.accent });
611
+ const picker = new SessionForkPicker(points, {
612
+ currentSessionId,
613
+ theme: this.theme,
614
+ onComplete: /* @__PURE__ */ __name((selection) => this.completeVersionDialog(selection), "onComplete")
615
+ });
616
+ this.dialog = new Dialog(this.baseView, picker, {
617
+ open: true,
618
+ title: "Session \u5206\u652F",
619
+ width: 100,
620
+ height: 25,
621
+ dismissOnEscape: false,
622
+ borderStyle: this.theme.borderAccent,
623
+ titleStyle: this.theme.accent
624
+ });
484
625
  this.dialogKind = "fork";
485
626
  this.synchronizeDialog();
486
627
  this.options.onInvalidate?.();
@@ -490,8 +631,21 @@ var MaybeCodePrototypeView = class {
490
631
  if (this.dialog) return Promise.reject(new Error("Another dialog is already open"));
491
632
  return new Promise((resolve) => {
492
633
  this.resolveVersionDialog = () => resolve();
493
- const viewer = new WorkspaceDiffViewer(diff, { theme: this.theme, onClose: /* @__PURE__ */ __name(() => this.completeVersionDialog(), "onClose"), ...operations, onInvalidate: /* @__PURE__ */ __name(() => this.options.onInvalidate?.(), "onInvalidate") });
494
- this.dialog = new Dialog(this.baseView, viewer, { open: true, title: "\u6587\u4EF6\u53D8\u5316", width: 110, height: 30, dismissOnEscape: false, borderStyle: this.theme.borderAccent, titleStyle: this.theme.accent });
634
+ const viewer = new WorkspaceDiffViewer(diff, {
635
+ theme: this.theme,
636
+ onClose: /* @__PURE__ */ __name(() => this.completeVersionDialog(), "onClose"),
637
+ ...operations,
638
+ onInvalidate: /* @__PURE__ */ __name(() => this.options.onInvalidate?.(), "onInvalidate")
639
+ });
640
+ this.dialog = new Dialog(this.baseView, viewer, {
641
+ open: true,
642
+ title: "\u6587\u4EF6\u53D8\u5316",
643
+ width: 110,
644
+ height: 30,
645
+ dismissOnEscape: false,
646
+ borderStyle: this.theme.borderAccent,
647
+ titleStyle: this.theme.accent
648
+ });
495
649
  this.dialogKind = "changes";
496
650
  this.synchronizeDialog();
497
651
  this.options.onInvalidate?.();
@@ -543,21 +697,19 @@ var MaybeCodePrototypeView = class {
543
697
  this.layout.setItems([
544
698
  {
545
699
  height: 3,
546
- component: new HeaderView(
547
- this.workspace,
548
- this.model,
549
- this.theme
550
- )
700
+ component: new HeaderView(this.workspace, this.model, this.theme)
551
701
  },
552
702
  { flex: 1, minHeight: 1, component: this.transcriptRegion },
553
- ...suggestionHeight === 0 ? [] : [{
554
- height: suggestionHeight,
555
- component: new Panel(this.suggestionList, {
556
- title: " Commands ",
557
- borderStyle: this.theme.border,
558
- titleStyle: this.theme.accent
559
- })
560
- }],
703
+ ...suggestionHeight === 0 ? [] : [
704
+ {
705
+ height: suggestionHeight,
706
+ component: new Panel(this.suggestionList, {
707
+ title: " Commands ",
708
+ borderStyle: this.theme.border,
709
+ titleStyle: this.theme.accent
710
+ })
711
+ }
712
+ ],
561
713
  {
562
714
  height: 4,
563
715
  component: this.editorRegion
@@ -591,7 +743,10 @@ var MaybeCodePrototypeView = class {
591
743
  this.clearShortcutHint();
592
744
  return true;
593
745
  }
594
- const shortcut = this.keymap.resolve(stroke, this.transcriptView.hasSelection ? ["global", "transcript.selection"] : ["global"]);
746
+ const shortcut = this.keymap.resolve(
747
+ stroke,
748
+ this.transcriptView.hasSelection ? ["global", "transcript.selection"] : ["global"]
749
+ );
595
750
  if (shortcut.type === "pending") {
596
751
  this.statusBeforeShortcut ??= this.status;
597
752
  this.status = `Shortcut: ${shortcut.completions.join(" / ")}`;
@@ -686,7 +841,8 @@ var MaybeCodePrototypeView = class {
686
841
  const previous = this.submissionTail;
687
842
  const pending = (previous ? previous.then(submit) : Promise.resolve(submit())).then(
688
843
  (status) => {
689
- if (epoch === this.submissionEpoch) this.setStatus(status ?? (this.options.isRunning?.() ? "Running" : "Ready"));
844
+ if (epoch === this.submissionEpoch)
845
+ this.setStatus(status ?? (this.options.isRunning?.() ? "Running" : "Ready"));
690
846
  },
691
847
  (error) => {
692
848
  if (this.disposed || epoch !== this.submissionEpoch) return;
@@ -730,11 +886,13 @@ var MaybeCodePrototypeView = class {
730
886
  (suggestions) => {
731
887
  if (version !== this.suggestionVersion || value !== this.editor.value) return;
732
888
  this.suggestions = suggestions;
733
- this.suggestionList.setItems(suggestions.map((suggestion) => ({
734
- value: suggestion,
735
- label: suggestion.label,
736
- ...suggestion.description === void 0 ? {} : { description: suggestion.description }
737
- })));
889
+ this.suggestionList.setItems(
890
+ suggestions.map((suggestion) => ({
891
+ value: suggestion,
892
+ label: suggestion.label,
893
+ ...suggestion.description === void 0 ? {} : { description: suggestion.description }
894
+ }))
895
+ );
738
896
  this.suggestionsVisible = suggestions.length > 0;
739
897
  this.options.onInvalidate?.();
740
898
  },
@@ -772,29 +930,38 @@ var MaybeCodePrototypeView = class {
772
930
  this.dialog = void 0;
773
931
  const question = this.mcpQuestions[0];
774
932
  if (question !== void 0) {
775
- this.dialog = new Dialog(this.baseView, new McpInputPrompt(question.prompt, question.finish, this.editorOptions(), this.options.keymap), {
776
- open: true,
777
- title: "MCP user interaction \u2014 untrusted server",
778
- width: 92,
779
- height: 24,
780
- dismissOnEscape: false,
781
- borderStyle: this.theme.warning,
782
- titleStyle: this.theme.warning
783
- });
933
+ this.dialog = new Dialog(
934
+ this.baseView,
935
+ new McpInputPrompt(question.prompt, question.finish, this.editorOptions(), this.options.keymap),
936
+ {
937
+ open: true,
938
+ title: "MCP user interaction \u2014 untrusted server",
939
+ width: 92,
940
+ height: 24,
941
+ dismissOnEscape: false,
942
+ borderStyle: this.theme.warning,
943
+ titleStyle: this.theme.warning
944
+ }
945
+ );
784
946
  this.dialogKind = "mcp";
785
947
  this.synchronizeDialog();
786
948
  this.options.onInvalidate?.();
787
949
  }
788
950
  return;
789
951
  }
790
- const prompt = new ApprovalPrompt(pending.request, this.theme, (decision) => {
791
- const current = this.approvalQueue.shift();
792
- this.dialog = void 0;
793
- this.dialogKind = void 0;
794
- current?.resolve(decision);
795
- this.openCurrentApproval();
796
- this.options.onInvalidate?.();
797
- }, this.options.keymap);
952
+ const prompt = new ApprovalPrompt(
953
+ pending.request,
954
+ this.theme,
955
+ (decision) => {
956
+ const current = this.approvalQueue.shift();
957
+ this.dialog = void 0;
958
+ this.dialogKind = void 0;
959
+ current?.resolve(decision);
960
+ this.openCurrentApproval();
961
+ this.options.onInvalidate?.();
962
+ },
963
+ this.options.keymap
964
+ );
798
965
  this.dialog = new Dialog(this.baseView, prompt, {
799
966
  open: true,
800
967
  title: `Approval: ${sanitizeTerminalText(pending.request.tool.name)}`,
@@ -818,10 +985,7 @@ var MaybeCodePrototypeView = class {
818
985
  this.transcript.detachFromEnd();
819
986
  return;
820
987
  }
821
- this.transcript.preserveAnchor(
822
- anchor,
823
- () => this.transcriptView.selectedToolAnchor
824
- );
988
+ this.transcript.preserveAnchor(anchor, () => this.transcriptView.selectedToolAnchor);
825
989
  }
826
990
  executeUiAction(id) {
827
991
  const status = this.uiActions.execute(id);
@@ -842,22 +1006,23 @@ var ModelPrompt = class {
842
1006
  constructor(models, currentProfile, theme, complete, keymapOptions = {}) {
843
1007
  this.complete = complete;
844
1008
  this.keymap = createMaybeCodeKeymap(keymapOptions);
845
- const currentIndex = models.findIndex(
846
- (model) => model.name === currentProfile
1009
+ const currentIndex = models.findIndex((model) => model.name === currentProfile);
1010
+ this.list = new SelectList(
1011
+ models.map((model) => ({
1012
+ value: model,
1013
+ label: `${model.name === currentProfile ? "* " : ""}${model.name}${model.isDefault ? " [default]" : ""}`,
1014
+ description: `${model.provider}/${model.model} \xB7 ${model.adapter}`
1015
+ })),
1016
+ {
1017
+ onSelect: /* @__PURE__ */ __name((item) => this.complete({ type: "switch", profile: item.value.name }), "onSelect"),
1018
+ onCancel: /* @__PURE__ */ __name(() => this.complete(void 0), "onCancel"),
1019
+ selectedIndex: Math.max(0, currentIndex),
1020
+ selectedStyle: theme.selected,
1021
+ descriptionStyle: theme.muted,
1022
+ markerStyle: theme.accent,
1023
+ emptyLabel: "No model profiles configured"
1024
+ }
847
1025
  );
848
- this.list = new SelectList(models.map((model) => ({
849
- value: model,
850
- label: `${model.name === currentProfile ? "* " : ""}${model.name}${model.isDefault ? " [default]" : ""}`,
851
- description: `${model.provider}/${model.model} \xB7 ${model.adapter}`
852
- })), {
853
- onSelect: /* @__PURE__ */ __name((item) => this.complete({ type: "switch", profile: item.value.name }), "onSelect"),
854
- onCancel: /* @__PURE__ */ __name(() => this.complete(void 0), "onCancel"),
855
- selectedIndex: Math.max(0, currentIndex),
856
- selectedStyle: theme.selected,
857
- descriptionStyle: theme.muted,
858
- markerStyle: theme.accent,
859
- emptyLabel: "No model profiles configured"
860
- });
861
1026
  this.list.setFocused(true);
862
1027
  }
863
1028
  complete;
@@ -872,7 +1037,9 @@ var ModelPrompt = class {
872
1037
  { flex: 1, minHeight: 1, component: this.list },
873
1038
  {
874
1039
  height: 1,
875
- component: new Text(`${promptShortcut(this.keymap, "list.accept", "select")} select \xB7 ${promptShortcut(this.keymap, "model.default.set", "modelPicker")} set default \xB7 ${promptShortcut(this.keymap, "list.cancel", "select")} close`)
1040
+ component: new Text(
1041
+ `${promptShortcut(this.keymap, "list.accept", "select")} select \xB7 ${promptShortcut(this.keymap, "model.default.set", "modelPicker")} set default \xB7 ${promptShortcut(this.keymap, "list.cancel", "select")} close`
1042
+ )
876
1043
  }
877
1044
  ]);
878
1045
  return this.layout.render(size);
@@ -898,18 +1065,21 @@ var EffortPrompt = class {
898
1065
  this.keymap = createMaybeCodeKeymap(keymapOptions);
899
1066
  const efforts = ["default", ...state.efforts];
900
1067
  const currentIndex = state.overridden ? efforts.indexOf(state.effectiveEffort ?? "") : 0;
901
- this.list = new SelectList(efforts.map((effort) => ({
902
- value: effort,
903
- label: `${effort === efforts[currentIndex] ? "* " : ""}${effort}`,
904
- description: effort === "default" ? `Clear override \xB7 default ${state.defaultEffort ?? "is provider-defined"}` : `Capability source: ${state.source}`
905
- })), {
906
- onSelect: /* @__PURE__ */ __name((item) => this.complete(item.value), "onSelect"),
907
- onCancel: /* @__PURE__ */ __name(() => this.complete(void 0), "onCancel"),
908
- selectedIndex: Math.max(0, currentIndex),
909
- selectedStyle: theme.selected,
910
- descriptionStyle: theme.muted,
911
- markerStyle: theme.accent
912
- });
1068
+ this.list = new SelectList(
1069
+ efforts.map((effort) => ({
1070
+ value: effort,
1071
+ label: `${effort === efforts[currentIndex] ? "* " : ""}${effort}`,
1072
+ description: effort === "default" ? `Clear override \xB7 default ${state.defaultEffort ?? "is provider-defined"}` : `Capability source: ${state.source}`
1073
+ })),
1074
+ {
1075
+ onSelect: /* @__PURE__ */ __name((item) => this.complete(item.value), "onSelect"),
1076
+ onCancel: /* @__PURE__ */ __name(() => this.complete(void 0), "onCancel"),
1077
+ selectedIndex: Math.max(0, currentIndex),
1078
+ selectedStyle: theme.selected,
1079
+ descriptionStyle: theme.muted,
1080
+ markerStyle: theme.accent
1081
+ }
1082
+ );
913
1083
  this.list.setFocused(true);
914
1084
  }
915
1085
  complete;
@@ -922,7 +1092,12 @@ var EffortPrompt = class {
922
1092
  render(size) {
923
1093
  this.layout.setItems([
924
1094
  { flex: 1, minHeight: 1, component: this.list },
925
- { height: 1, component: new Text(`${promptShortcut(this.keymap, "list.accept", "select")} select \xB7 ${promptShortcut(this.keymap, "list.cancel", "select")} close`) }
1095
+ {
1096
+ height: 1,
1097
+ component: new Text(
1098
+ `${promptShortcut(this.keymap, "list.accept", "select")} select \xB7 ${promptShortcut(this.keymap, "list.cancel", "select")} close`
1099
+ )
1100
+ }
926
1101
  ]);
927
1102
  return this.layout.render(size);
928
1103
  }
@@ -940,22 +1115,31 @@ var ApprovalPrompt = class {
940
1115
  this.theme = theme;
941
1116
  this.decide = decide;
942
1117
  this.keymap = createMaybeCodeKeymap(keymapOptions);
943
- this.choices = new SelectList([
944
- { value: "allow", label: "Allow once", description: promptShortcut(this.keymap, "approval.allow", "approval") },
945
- ...request.grantKey === void 0 ? [] : [{
946
- value: "allow-session",
947
- label: "Allow matching calls for this session",
948
- description: promptShortcut(this.keymap, "approval.allowSession", "approval")
949
- }],
950
- { value: "deny", label: "Deny", description: `${promptShortcut(this.keymap, "approval.deny", "approval")} / ${promptShortcut(this.keymap, "list.cancel", "select")}` },
951
- ...request.persistent ? [{ value: "allow-persistent", label: "\u4FDD\u5B58\u5141\u8BB8\u89C4\u5219", description: request.persistent.description }] : []
952
- ], {
953
- onSelect: /* @__PURE__ */ __name((item) => this.decide(item.value), "onSelect"),
954
- onCancel: /* @__PURE__ */ __name(() => this.decide("deny"), "onCancel"),
955
- selectedStyle: this.theme.selected,
956
- descriptionStyle: this.theme.muted,
957
- markerStyle: this.theme.accent
958
- });
1118
+ this.choices = new SelectList(
1119
+ [
1120
+ { value: "allow", label: "Allow once", description: promptShortcut(this.keymap, "approval.allow", "approval") },
1121
+ ...request.grantKey === void 0 ? [] : [
1122
+ {
1123
+ value: "allow-session",
1124
+ label: "Allow matching calls for this session",
1125
+ description: promptShortcut(this.keymap, "approval.allowSession", "approval")
1126
+ }
1127
+ ],
1128
+ {
1129
+ value: "deny",
1130
+ label: "Deny",
1131
+ description: `${promptShortcut(this.keymap, "approval.deny", "approval")} / ${promptShortcut(this.keymap, "list.cancel", "select")}`
1132
+ },
1133
+ ...request.persistent ? [{ value: "allow-persistent", label: "\u4FDD\u5B58\u5141\u8BB8\u89C4\u5219", description: request.persistent.description }] : []
1134
+ ],
1135
+ {
1136
+ onSelect: /* @__PURE__ */ __name((item) => this.decide(item.value), "onSelect"),
1137
+ onCancel: /* @__PURE__ */ __name(() => this.decide("deny"), "onCancel"),
1138
+ selectedStyle: this.theme.selected,
1139
+ descriptionStyle: this.theme.muted,
1140
+ markerStyle: this.theme.accent
1141
+ }
1142
+ );
959
1143
  this.choices.setFocused(true);
960
1144
  }
961
1145
  request;
@@ -972,9 +1156,7 @@ var ApprovalPrompt = class {
972
1156
  this.layout.setItems([
973
1157
  {
974
1158
  height: 1,
975
- component: new Text(
976
- `Tool: ${sanitizeTerminalText(this.request.tool.name)}`
977
- )
1159
+ component: new Text(`Tool: ${sanitizeTerminalText(this.request.tool.name)}`)
978
1160
  },
979
1161
  { flex: 1, minHeight: 1, component: new Text(input) },
980
1162
  {
@@ -1142,11 +1324,13 @@ ${promptShortcut(this.keymap, "list.accept", "select")} resume \xB7 ${promptShor
1142
1324
  const filtered = query === "" ? this.sessions : this.sessions.filter(
1143
1325
  (session) => [session.id, session.title, session.preview].filter((value) => value !== void 0).some((value) => value.toLowerCase().includes(query))
1144
1326
  );
1145
- this.list.setItems(filtered.map((session) => ({
1146
- value: session,
1147
- label: `${session.id === this.currentSessionId ? "* " : ""}${session.title ?? session.id}`,
1148
- description: session.preview ?? (session.turnCount === void 0 ? "No recorded turns" : `${session.turnCount} turns`)
1149
- })));
1327
+ this.list.setItems(
1328
+ filtered.map((session) => ({
1329
+ value: session,
1330
+ label: `${session.id === this.currentSessionId ? "* " : ""}${session.title ?? session.id}`,
1331
+ description: session.preview ?? (session.turnCount === void 0 ? "No recorded turns" : `${session.turnCount} turns`)
1332
+ }))
1333
+ );
1150
1334
  this.status = filtered.length === 0 ? "No matching sessions" : this.status;
1151
1335
  }
1152
1336
  resumeSelected() {
@@ -1305,7 +1489,12 @@ var McpInputPrompt = class {
1305
1489
  this.layout.setItems([
1306
1490
  { flex: 1, minHeight: 1, component: this.body },
1307
1491
  { height: 4, component: this.editor },
1308
- { height: 1, component: new Text(`${promptShortcut(this.keymap, "request.pageUp", "mcpInput")}/${promptShortcut(this.keymap, "request.pageDown", "mcpInput")} review request | Enter continue | ${promptShortcut(this.keymap, "request.cancel", "mcpInput")} cancel`) }
1492
+ {
1493
+ height: 1,
1494
+ component: new Text(
1495
+ `${promptShortcut(this.keymap, "request.pageUp", "mcpInput")}/${promptShortcut(this.keymap, "request.pageDown", "mcpInput")} review request | Enter continue | ${promptShortcut(this.keymap, "request.cancel", "mcpInput")} cancel`
1496
+ )
1497
+ }
1309
1498
  ]);
1310
1499
  return this.layout.render(size);
1311
1500
  }
@@ -1346,21 +1535,256 @@ function promptShortcut(keymap, action, context) {
1346
1535
  }
1347
1536
  __name(promptShortcut, "promptShortcut");
1348
1537
 
1538
+ // apps/maybecode/src/mcp-interaction-ui.ts
1539
+ async function presentMcpInteraction(request, app, ask, signal) {
1540
+ if (app.respondMcpInteraction === void 0) return;
1541
+ const header = sanitizeTerminalText(
1542
+ `MCP server: ${request.serverId}
1543
+ Session: ${request.owner.sessionId}
1544
+ Request: ${request.requestId}
1545
+ ${request.params.message}
1546
+ `
1547
+ );
1548
+ const question = /* @__PURE__ */ __name(async (prompt) => {
1549
+ signal.throwIfAborted();
1550
+ const answer = await ask(sanitizeTerminalText(prompt), signal);
1551
+ signal.throwIfAborted();
1552
+ return answer;
1553
+ }, "question");
1554
+ let error = "";
1555
+ while (!signal.aborted) {
1556
+ if (request.params.mode === "review") {
1557
+ let data = request.params.data;
1558
+ let edited = false;
1559
+ for (; ; ) {
1560
+ const choice = (await question(
1561
+ `${header}
1562
+ Host review: ${request.params.kind}
1563
+ ${JSON.stringify(data, null, 2)}
1564
+ ${error}Type allow to approve${request.params.editable ? ", edit to change the JSON" : ""}, decline, or cancel: `
1565
+ ))?.trim().toLowerCase();
1566
+ if (choice === "edit" && request.params.editable) {
1567
+ try {
1568
+ const input = await question(
1569
+ `${header}
1570
+ Enter the replacement JSON document (reviewed again before sending), or cancel: `
1571
+ );
1572
+ if (input === void 0 || input.trim() === "cancel") {
1573
+ app.respondMcpInteraction(request.id, { action: "cancel" });
1574
+ return;
1575
+ }
1576
+ if (Buffer.byteLength(input) > 48 * 1024) throw new Error();
1577
+ data = JSON.parse(input);
1578
+ edited = true;
1579
+ error = "";
1580
+ } catch {
1581
+ error = "Invalid JSON or document too large.\n";
1582
+ }
1583
+ continue;
1584
+ }
1585
+ app.respondMcpInteraction(request.id, {
1586
+ action: choice === "allow" ? "accept" : choice === "decline" ? "decline" : "cancel",
1587
+ ...choice !== "allow" || !edited ? {} : { content: { json: JSON.stringify(data) } }
1588
+ });
1589
+ return;
1590
+ }
1591
+ }
1592
+ if (request.params.mode === "url") {
1593
+ let url;
1594
+ try {
1595
+ url = new URL(request.params.url);
1596
+ if (!["https:", "http:"].includes(url.protocol) || url.username || url.password) throw new Error("Unsafe URL");
1597
+ } catch {
1598
+ app.respondMcpInteraction(request.id, { action: "decline" });
1599
+ return;
1600
+ }
1601
+ const consent = await question(
1602
+ `${header}
1603
+ External host: ${url.host}
1604
+ URL: ${request.params.url}
1605
+ This is an untrusted external website, not MCP client login. Nothing opens automatically.
1606
+ Type accept to consent, decline to refuse, or cancel to dismiss: `
1607
+ );
1608
+ if (consent?.trim().toLowerCase() !== "accept") {
1609
+ app.respondMcpInteraction(request.id, {
1610
+ action: consent?.trim().toLowerCase() === "decline" ? "decline" : "cancel"
1611
+ });
1612
+ return;
1613
+ }
1614
+ const resume = await question(
1615
+ `${header}
1616
+ Open the displayed URL yourself if you wish.
1617
+ After interacting with the website, type retry to resume the original request, or cancel: `
1618
+ );
1619
+ app.respondMcpInteraction(request.id, { action: resume?.trim().toLowerCase() === "retry" ? "accept" : "cancel" });
1620
+ return;
1621
+ }
1622
+ const answer = await question(
1623
+ `${header}
1624
+ Never enter passwords, API keys, tokens or payment credentials.
1625
+ Requested form (untrusted):
1626
+ ${JSON.stringify(request.params.requestedSchema, null, 2)}
1627
+ ${error}Enter a JSON object, decline, or cancel: `
1628
+ );
1629
+ if (answer === void 0 || ["decline", "cancel"].includes(answer.trim().toLowerCase())) {
1630
+ app.respondMcpInteraction(request.id, {
1631
+ action: answer?.trim().toLowerCase() === "decline" ? "decline" : "cancel"
1632
+ });
1633
+ return;
1634
+ }
1635
+ let content;
1636
+ try {
1637
+ if (Buffer.byteLength(answer) > 64 * 1024) throw new Error();
1638
+ const parsed = JSON.parse(answer);
1639
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error();
1640
+ content = parsed;
1641
+ } catch {
1642
+ error = "Invalid JSON object or response too large.\n";
1643
+ continue;
1644
+ }
1645
+ const review = await question(
1646
+ `${header}
1647
+ Review what will be sent ONLY to this server:
1648
+ ${JSON.stringify(content, null, 2)}
1649
+ Type send to submit, edit to replace, decline, or cancel: `
1650
+ );
1651
+ const action = review?.trim().toLowerCase();
1652
+ if (action === "edit") continue;
1653
+ if (action !== "send") {
1654
+ app.respondMcpInteraction(request.id, { action: action === "decline" ? "decline" : "cancel" });
1655
+ return;
1656
+ }
1657
+ try {
1658
+ app.respondMcpInteraction(request.id, { action: "accept", content });
1659
+ return;
1660
+ } catch {
1661
+ error = "The response does not satisfy the form; please correct it.\n";
1662
+ }
1663
+ }
1664
+ }
1665
+ __name(presentMcpInteraction, "presentMcpInteraction");
1666
+
1667
+ // apps/maybecode/src/terminal-web.ts
1668
+ import { randomBytes } from "node:crypto";
1669
+ import open from "open";
1670
+ import { AsyncEventQueue, isStreamingMayEvent } from "@sortedyuan/may/core";
1671
+ function eventQueue() {
1672
+ return new AsyncEventQueue({
1673
+ maxBufferedValues: 1024,
1674
+ isDroppable: /* @__PURE__ */ __name((event) => event.type === "mcp.resource.updated" || event.type === "run.event" && isStreamingMayEvent(event.event), "isDroppable")
1675
+ });
1676
+ }
1677
+ __name(eventQueue, "eventQueue");
1678
+ var MaybeCodeTerminalWeb = class {
1679
+ constructor(app, exit) {
1680
+ this.app = app;
1681
+ this.exit = exit;
1682
+ this.host = createMaybeCodeWebHost(app, { events: this.webEvents, closeApplication: false, terminal: true });
1683
+ this.events = this.readTerminalEvents();
1684
+ this.relay = this.forwardEvents().catch((error) => {
1685
+ this.failure = error;
1686
+ });
1687
+ }
1688
+ app;
1689
+ exit;
1690
+ static {
1691
+ __name(this, "MaybeCodeTerminalWeb");
1692
+ }
1693
+ terminalEvents = eventQueue();
1694
+ webEvents = eventQueue();
1695
+ host;
1696
+ relay;
1697
+ failure;
1698
+ starting;
1699
+ closing;
1700
+ events;
1701
+ async forwardEvents() {
1702
+ try {
1703
+ for await (const event of this.app.events) {
1704
+ this.terminalEvents.push(event);
1705
+ this.webEvents.push(event);
1706
+ }
1707
+ } catch (error) {
1708
+ this.failure = error;
1709
+ throw error;
1710
+ } finally {
1711
+ this.terminalEvents.close();
1712
+ this.webEvents.close();
1713
+ }
1714
+ }
1715
+ async *readTerminalEvents() {
1716
+ for await (const event of this.terminalEvents) yield event;
1717
+ if (this.failure !== void 0) throw this.failure;
1718
+ }
1719
+ async open() {
1720
+ const server = await this.startServer();
1721
+ const url = server.createLoginUrl();
1722
+ try {
1723
+ await open(url);
1724
+ } catch {
1725
+ 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");
1726
+ }
1727
+ return server.url;
1728
+ }
1729
+ async startServer() {
1730
+ if (this.closing) throw new Error("MaybeCode \u6B63\u5728\u5173\u95ED\u3002");
1731
+ this.starting ??= startMaybeCodeWebServer(this.host, {
1732
+ token: randomBytes(32).toString("base64url"),
1733
+ port: 0,
1734
+ browserLogin: true,
1735
+ exit: /* @__PURE__ */ __name(() => {
1736
+ if (this.exit) this.exit();
1737
+ else this.beginClose();
1738
+ }, "exit")
1739
+ });
1740
+ const server = await this.starting;
1741
+ if (this.closing) throw new Error("MaybeCode \u6B63\u5728\u5173\u95ED\u3002");
1742
+ return server;
1743
+ }
1744
+ close() {
1745
+ this.beginClose();
1746
+ return this.closing.then(() => {
1747
+ if (this.failure !== void 0) throw this.failure;
1748
+ });
1749
+ }
1750
+ beginClose() {
1751
+ this.closing ??= this.closeOwnedResources().catch((error) => {
1752
+ this.failure = error;
1753
+ });
1754
+ }
1755
+ async closeOwnedResources() {
1756
+ const results = await Promise.allSettled([
1757
+ this.app.close(),
1758
+ this.starting ? this.starting.then((server) => server.close()) : this.host.close()
1759
+ ]);
1760
+ await this.relay;
1761
+ const failures = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
1762
+ if (this.failure !== void 0) failures.push(this.failure);
1763
+ if (failures.length) throw new AggregateError(failures, "\u5173\u95ED MaybeCode \u65F6\u53D1\u751F\u9519\u8BEF\u3002");
1764
+ }
1765
+ };
1766
+
1349
1767
  // apps/maybecode/src/ui/retained-tui.ts
1350
1768
  async function runRetainedTerminalUI(app, options = {}) {
1351
1769
  const terminal = options.terminal ?? new NodeTerminalDriver();
1352
1770
  const renderer = options.renderer ?? new FullscreenRenderer(terminal);
1353
1771
  const store = new TranscriptStore();
1354
1772
  const displayedSteering = /* @__PURE__ */ new Set();
1355
- const images = new TerminalImages(void 0, terminal.imageSupport?.protocol, { cellSize: /* @__PURE__ */ __name(() => terminal.imageSupport?.cellSize, "cellSize") });
1773
+ const images = new TerminalImages(void 0, terminal.imageSupport?.protocol, {
1774
+ cellSize: /* @__PURE__ */ __name(() => terminal.imageSupport?.cellSize, "cellSize")
1775
+ });
1356
1776
  try {
1357
1777
  const history = await app.history();
1358
- for (const event of history) if (event.type === "assistant.completed" || event.type === "input.submitted") await images.prepare(event.message.content);
1359
- for (const event of history) if (event.type === "tool.completed" && event.content) await images.prepare(event.content);
1778
+ for (const event of history)
1779
+ if (event.type === "assistant.completed" || event.type === "input.submitted")
1780
+ await images.prepare(event.message.content);
1781
+ for (const event of history)
1782
+ if (event.type === "tool.completed" && event.content) await images.prepare(event.content);
1360
1783
  store.loadHistory(history);
1361
1784
  for (const event of history) {
1362
1785
  if (event.type === "input.submitted" && event.inputId) displayedSteering.add(event.inputId);
1363
- if (event.type === "input.steering.delivered") for (const inputId of event.inputIds) displayedSteering.add(inputId);
1786
+ if (event.type === "input.steering.delivered")
1787
+ for (const inputId of event.inputIds) displayedSteering.add(inputId);
1364
1788
  }
1365
1789
  } catch (error) {
1366
1790
  await app.close();
@@ -1371,9 +1795,12 @@ async function runRetainedTerminalUI(app, options = {}) {
1371
1795
  let eventFailure;
1372
1796
  const pendingRuns = /* @__PURE__ */ new Set();
1373
1797
  const observeRun = /* @__PURE__ */ __name((result) => {
1374
- const pending = result.then(() => void 0, (error) => {
1375
- if (!closing && !isCancellation(error)) store.appendNotice("error", errorMessage(error));
1376
- }).finally(() => {
1798
+ const pending = result.then(
1799
+ () => void 0,
1800
+ (error) => {
1801
+ if (!closing && !isCancellation(error)) store.appendNotice("error", errorMessage(error));
1802
+ }
1803
+ ).finally(() => {
1377
1804
  pendingRuns.delete(pending);
1378
1805
  if (!closing) view.setStatus(app.isRunning ? "Running" : "Ready");
1379
1806
  });
@@ -1392,13 +1819,11 @@ async function runRetainedTerminalUI(app, options = {}) {
1392
1819
  if (app.isRunning) app.cancel("Interrupted by process signal");
1393
1820
  finish();
1394
1821
  }, "handleProcessSignal");
1395
- const view = new MaybeCodePrototypeView({
1822
+ const view = new MaybeCodeTerminalView({
1396
1823
  isRunning: /* @__PURE__ */ __name(() => app.isRunning, "isRunning"),
1397
1824
  permissionMode: /* @__PURE__ */ __name(() => app.permissionMode, "permissionMode"),
1398
1825
  clipboard: options.clipboard ?? createTerminalClipboard({ output: terminal }),
1399
- keymap: options.keymap ?? {
1400
- ...process.env.MAY_TUI_LEADER === void 0 ? {} : { leader: process.env.MAY_TUI_LEADER }
1401
- },
1826
+ keymap: options.keymap ?? omitUndefined2({ leader: process.env.MAY_TUI_LEADER }),
1402
1827
  images,
1403
1828
  store,
1404
1829
  workspace: app.workspace,
@@ -1430,7 +1855,7 @@ async function runRetainedTerminalUI(app, options = {}) {
1430
1855
  });
1431
1856
  process.on("SIGINT", handleProcessSignal);
1432
1857
  process.on("SIGTERM", handleProcessSignal);
1433
- void refreshModelLabel(view, app);
1858
+ await refreshModelLabel(view, app);
1434
1859
  const refreshWorkspace = /* @__PURE__ */ __name(async () => {
1435
1860
  if (!app.getWorkspaceGit || closing) return;
1436
1861
  try {
@@ -1441,10 +1866,14 @@ async function runRetainedTerminalUI(app, options = {}) {
1441
1866
  }, "refreshWorkspace");
1442
1867
  await refreshWorkspace();
1443
1868
  let refreshingWorkspace = false;
1869
+ let workspaceTask;
1444
1870
  const workspaceTimer = app.getWorkspaceGit ? setInterval(() => {
1445
1871
  if (refreshingWorkspace || closing) return;
1446
1872
  refreshingWorkspace = true;
1447
- void refreshWorkspace().finally(() => {
1873
+ workspaceTask = refreshWorkspace().catch((error) => {
1874
+ eventFailure = error;
1875
+ finish();
1876
+ }).finally(() => {
1448
1877
  refreshingWorkspace = false;
1449
1878
  });
1450
1879
  }, 2e3) : void 0;
@@ -1452,11 +1881,13 @@ async function runRetainedTerminalUI(app, options = {}) {
1452
1881
  let eventTask;
1453
1882
  try {
1454
1883
  runtime.start();
1455
- eventTask = consumeEvents(app, store, view, () => closing, web.events, images, displayedSteering).catch((error) => {
1456
- eventFailure = error;
1457
- store.appendNotice("error", `Event stream failed: ${errorMessage(error)}`);
1458
- finish();
1459
- });
1884
+ eventTask = consumeEvents(app, store, view, () => closing, web.events, images, displayedSteering, finish).catch(
1885
+ (error) => {
1886
+ eventFailure = error;
1887
+ store.appendNotice("error", `Event stream failed: ${errorMessage(error)}`);
1888
+ finish();
1889
+ }
1890
+ );
1460
1891
  await exited;
1461
1892
  } finally {
1462
1893
  closing = true;
@@ -1465,138 +1896,197 @@ async function runRetainedTerminalUI(app, options = {}) {
1465
1896
  process.removeListener("SIGTERM", handleProcessSignal);
1466
1897
  runtime.stop();
1467
1898
  view.dispose();
1468
- await web.close();
1469
- await Promise.all(pendingRuns);
1470
- await eventTask;
1899
+ const results = await Promise.allSettled([
1900
+ web.close(),
1901
+ ...pendingRuns,
1902
+ ...workspaceTask ? [workspaceTask] : [],
1903
+ ...eventTask ? [eventTask] : []
1904
+ ]);
1905
+ const failures = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
1906
+ if (failures.length) {
1907
+ if (eventFailure !== void 0) failures.push(eventFailure);
1908
+ throw new AggregateError(failures, "MaybeCode terminal failed to close");
1909
+ }
1471
1910
  }
1472
1911
  if (eventFailure !== void 0) throw eventFailure;
1473
1912
  }
1474
1913
  __name(runRetainedTerminalUI, "runRetainedTerminalUI");
1475
- async function consumeEvents(app, store, view, isClosing, events, images, displayedSteering) {
1914
+ async function consumeEvents(app, store, view, isClosing, events, images, displayedSteering, onStopped) {
1476
1915
  const approvals = /* @__PURE__ */ new Set();
1916
+ const approvalErrors = [];
1917
+ const trackApproval = /* @__PURE__ */ __name((operation, finish) => {
1918
+ const task = operation.catch((error) => {
1919
+ approvalErrors.push(error);
1920
+ onStopped();
1921
+ }).finally(() => {
1922
+ finish?.();
1923
+ approvals.delete(task);
1924
+ });
1925
+ approvals.add(task);
1926
+ }, "trackApproval");
1477
1927
  const interactions = /* @__PURE__ */ new Map();
1478
1928
  const delegationStatus = /* @__PURE__ */ new Map();
1479
1929
  let lastGoalDisplay = "";
1480
- for await (const event of events) {
1481
- if (event.type === "run.event") {
1482
- if (event.event.type === "run.started") {
1483
- view.setStatus("Running");
1484
- const unread = app.listSteeringInputs?.().filter((input) => input.status === "delivered" && !displayedSteering.has(input.inputId)) ?? [];
1485
- if (unread.length > 0) {
1486
- const history = await app.history();
1487
- const runId = event.event.runId;
1488
- const runIndex = history.findIndex((item) => item.type === "run.started" && item.runId === runId);
1489
- const submitted = runIndex < 0 ? void 0 : history.slice(0, runIndex).reverse().find((item) => item.type === "input.submitted");
1490
- if (submitted?.type === "input.submitted" && submitted.inputId && unread.some((input) => input.inputId === submitted.inputId)) {
1491
- store.appendUser(submitted.message.content.filter((part) => part.type === "text").map((part) => part.text).join(""));
1492
- displayedSteering.add(submitted.inputId);
1930
+ try {
1931
+ for await (const event of events) {
1932
+ if (event.type === "run.event") {
1933
+ if (event.event.type === "run.started") {
1934
+ view.setStatus("Running");
1935
+ const unread = app.application.agent.listSteeringInputs().filter((input) => input.status === "delivered" && !displayedSteering.has(input.inputId));
1936
+ if (unread.length > 0) {
1937
+ const history = await app.history();
1938
+ const runId = event.event.runId;
1939
+ const runIndex = history.findIndex((item) => item.type === "run.started" && item.runId === runId);
1940
+ const submitted = runIndex < 0 ? void 0 : history.slice(0, runIndex).reverse().find((item) => item.type === "input.submitted");
1941
+ if (submitted?.type === "input.submitted" && submitted.inputId && unread.some((input) => input.inputId === submitted.inputId)) {
1942
+ store.appendUser(
1943
+ submitted.message.content.filter((part) => part.type === "text").map((part) => part.text).join("")
1944
+ );
1945
+ displayedSteering.add(submitted.inputId);
1946
+ }
1493
1947
  }
1494
1948
  }
1495
- }
1496
- if (event.event.type === "input.received") {
1497
- for (const input of app.listSteeringInputs?.() ?? []) {
1498
- if (input.status === "delivered" && input.runId === event.event.runId) displayedSteering.add(input.inputId);
1949
+ if (event.event.type === "input.received") {
1950
+ for (const input of app.application.agent.listSteeringInputs()) {
1951
+ if (input.status === "delivered" && input.runId === event.event.runId) displayedSteering.add(input.inputId);
1952
+ }
1953
+ }
1954
+ if (event.event.type === "run.completed" || event.event.type === "run.yielded" || event.event.type === "run.cancelled") {
1955
+ view.setStatus(app.isRunning ? "Delegating" : "Ready");
1499
1956
  }
1957
+ if (event.event.type === "run.failed") view.setStatus(`Error: ${event.event.error.message}`);
1500
1958
  }
1501
- if (event.event.type === "run.completed" || event.event.type === "run.yielded" || event.event.type === "run.cancelled") {
1502
- view.setStatus(app.isRunning ? "Delegating" : "Ready");
1959
+ if (event.type === "permission-mode.changed") {
1960
+ view.setStatus(event.mode === "yolo" ? "YOLO enabled" : "YOLO disabled");
1503
1961
  }
1504
- if (event.event.type === "run.failed") view.setStatus(`Error: ${event.event.error.message}`);
1505
- }
1506
- if (event.type === "permission-mode.changed") {
1507
- view.setStatus(event.mode === "yolo" ? "YOLO enabled" : "YOLO disabled");
1508
- }
1509
- if (event.type === "run.event" && event.event.type === "model.completed") await images.prepare(event.event.message.content);
1510
- if (event.type === "run.event" && event.event.type === "tool.completed") await images.prepare(event.event.content);
1511
- if (event.type === "goal.changed") {
1512
- view.setStatus(`Goal ${event.goal.status}`);
1513
- const display = `${event.goal.id}:${event.goal.status}:${event.goal.progress}`;
1514
- if (display !== lastGoalDisplay) {
1515
- lastGoalDisplay = display;
1516
- store.appendNotice("info", formatGoal(event.goal));
1962
+ if (event.type === "run.event" && event.event.type === "model.completed")
1963
+ await images.prepare(event.event.message.content);
1964
+ if (event.type === "run.event" && event.event.type === "tool.completed")
1965
+ await images.prepare(event.event.content);
1966
+ if (event.type === "goal.changed") {
1967
+ view.setStatus(`Goal ${event.goal.status}`);
1968
+ const display = `${event.goal.id}:${event.goal.status}:${event.goal.progress}`;
1969
+ if (display !== lastGoalDisplay) {
1970
+ lastGoalDisplay = display;
1971
+ store.appendNotice("info", formatGoal(event.goal));
1972
+ }
1517
1973
  }
1518
- }
1519
- if (event.type === "delegation.started" || event.type === "delegation.finished") {
1520
- if (event.type === "delegation.started") delegationStatus.clear();
1521
- const label = event.type === "delegation.started" ? "Sub-agent request" : "Sub-agent request finished";
1522
- if (app.delegationNotifications === true) store.appendNotice("info", `${label}
1974
+ if (event.type === "delegation.started" || event.type === "delegation.finished") {
1975
+ if (event.type === "delegation.started") delegationStatus.clear();
1976
+ const label = event.type === "delegation.started" ? "Sub-agent request" : "Sub-agent request finished";
1977
+ if (app.delegationNotifications === true)
1978
+ store.appendNotice("info", `${label}
1523
1979
  ${formatDelegationTree(event.state)}`);
1524
- view.setStatus(event.type === "delegation.started" ? "Delegating" : "Ready");
1525
- } else if (event.type === "delegation.updated") {
1526
- for (const task of delegationOrder(event.state.tasks)) {
1527
- const previous = delegationStatus.get(task.id);
1528
- delegationStatus.set(task.id, task.status);
1529
- if (app.delegationNotifications !== true || previous === task.status) continue;
1530
- store.appendNotice(["failed", "cancelled", "recovery-required"].includes(task.status) ? "warning" : "info", renderDelegationTask(task));
1980
+ view.setStatus(event.type === "delegation.started" ? "Delegating" : "Ready");
1981
+ } else if (event.type === "delegation.updated") {
1982
+ for (const task of delegationOrder(event.state.tasks)) {
1983
+ const previous = delegationStatus.get(task.id);
1984
+ delegationStatus.set(task.id, task.status);
1985
+ if (app.delegationNotifications !== true || previous === task.status) continue;
1986
+ store.appendNotice(
1987
+ ["failed", "cancelled", "recovery-required"].includes(task.status) ? "warning" : "info",
1988
+ renderDelegationTask(task)
1989
+ );
1990
+ }
1531
1991
  }
1532
- }
1533
- applyMaybeCodeEvent(store, event);
1534
- if (event.type === "mcp.interaction.requested") {
1535
- const controller = new AbortController();
1536
- interactions.set(event.request.id, controller);
1537
- const signal = AbortSignal.any([controller.signal, AbortSignal.timeout(Math.max(0, Math.ceil(event.request.expiresAt - Date.now())))]);
1538
- const task = presentMcpInteraction(event.request, app, (prompt, signal2) => view.requestMcpInput(prompt, signal2), signal).catch(() => {
1539
- if (!isClosing() && !signal.aborted) {
1540
- store.appendNotice("warning", "MCP interaction could not be completed");
1541
- app.cancel("User interaction is unavailable");
1992
+ applyMaybeCodeEvent(store, event);
1993
+ if (event.type === "mcp.interaction.requested") {
1994
+ const controller = new AbortController();
1995
+ interactions.set(event.request.id, controller);
1996
+ const signal = AbortSignal.any([
1997
+ controller.signal,
1998
+ AbortSignal.timeout(Math.max(0, Math.ceil(event.request.expiresAt - Date.now())))
1999
+ ]);
2000
+ trackApproval(
2001
+ presentMcpInteraction(
2002
+ event.request,
2003
+ app,
2004
+ (prompt, signal2) => view.requestMcpInput(prompt, signal2),
2005
+ signal
2006
+ ).catch(() => {
2007
+ if (!isClosing() && !signal.aborted) {
2008
+ store.appendNotice("warning", "MCP interaction could not be completed");
2009
+ app.cancel("User interaction is unavailable");
2010
+ }
2011
+ }),
2012
+ () => {
2013
+ interactions.delete(event.request.id);
2014
+ }
2015
+ );
2016
+ } else if (event.type === "mcp.interaction.settled") interactions.get(event.requestId)?.abort();
2017
+ if (event.type === "model.changed") {
2018
+ await refreshModelLabel(view, app);
2019
+ }
2020
+ if (event.type === "session.changed" && event.resumed) {
2021
+ const history = await app.history();
2022
+ for (const event2 of history)
2023
+ if (event2.type === "assistant.completed" || event2.type === "input.submitted")
2024
+ await images.prepare(event2.message.content);
2025
+ for (const event2 of history)
2026
+ if (event2.type === "tool.completed" && event2.content) await images.prepare(event2.content);
2027
+ store.loadHistory(history);
2028
+ displayedSteering.clear();
2029
+ for (const event2 of history) {
2030
+ if (event2.type === "input.submitted" && event2.inputId) displayedSteering.add(event2.inputId);
2031
+ if (event2.type === "input.steering.delivered")
2032
+ for (const inputId of event2.inputIds) displayedSteering.add(inputId);
1542
2033
  }
1543
- }).finally(() => interactions.delete(event.request.id));
1544
- approvals.add(task);
1545
- void task.finally(() => approvals.delete(task));
1546
- } else if (event.type === "mcp.interaction.settled") interactions.get(event.requestId)?.abort();
1547
- if (event.type === "model.changed") {
1548
- void refreshModelLabel(view, app);
1549
- }
1550
- if (event.type === "session.changed" && event.resumed) {
1551
- const history = await app.history();
1552
- for (const event2 of history) if (event2.type === "assistant.completed" || event2.type === "input.submitted") await images.prepare(event2.message.content);
1553
- for (const event2 of history) if (event2.type === "tool.completed" && event2.content) await images.prepare(event2.content);
1554
- store.loadHistory(history);
1555
- displayedSteering.clear();
1556
- for (const event2 of history) {
1557
- if (event2.type === "input.submitted" && event2.inputId) displayedSteering.add(event2.inputId);
1558
- if (event2.type === "input.steering.delivered") for (const inputId of event2.inputIds) displayedSteering.add(inputId);
2034
+ store.appendNotice("info", "Session resumed");
2035
+ continue;
1559
2036
  }
1560
- store.appendNotice("info", "Session resumed");
1561
- continue;
1562
- }
1563
- if (event.type === "permission.event" && event.event.type === "approval.requested") {
1564
- const task = presentApproval(app, view, store, event.event.request, isClosing, approvals);
1565
- approvals.add(task);
1566
- void task.finally(() => approvals.delete(task));
1567
- } else if (event.type === "permission.event" && (event.event.type === "approval.resolved" || event.event.type === "approval.cancelled")) {
1568
- view.dismissApproval(event.event.requestId);
1569
- }
1570
- if (event.type === "delegation.event" && event.event.type === "permission.event") {
1571
- const inner = event.event.event;
1572
- if (inner.type === "approval.requested") {
1573
- store.appendNotice("info", `\u5B50\u4EFB\u52A1 ${event.taskId} \u8BF7\u6C42\u6279\u51C6 ${inner.request.tool.name}`);
1574
- const task = presentApproval(app, view, store, inner.request, isClosing, approvals);
1575
- approvals.add(task);
1576
- void task.finally(() => approvals.delete(task));
1577
- } else if (inner.type === "approval.resolved" || inner.type === "approval.cancelled") {
1578
- view.dismissApproval(inner.requestId);
2037
+ if (event.type === "permission.event" && event.event.type === "approval.requested") {
2038
+ trackApproval(presentApproval(app, view, store, event.event.request, isClosing));
2039
+ } else if (event.type === "permission.event" && (event.event.type === "approval.resolved" || event.event.type === "approval.cancelled")) {
2040
+ view.dismissApproval(event.event.requestId);
2041
+ }
2042
+ if (event.type === "delegation.event" && event.event.type === "permission.event") {
2043
+ const inner = event.event.event;
2044
+ if (inner.type === "approval.requested") {
2045
+ store.appendNotice("info", `\u5B50\u4EFB\u52A1 ${event.taskId} \u8BF7\u6C42\u6279\u51C6 ${inner.request.tool.name}`);
2046
+ trackApproval(presentApproval(app, view, store, inner.request, isClosing));
2047
+ } else if (inner.type === "approval.resolved" || inner.type === "approval.cancelled") {
2048
+ view.dismissApproval(inner.requestId);
2049
+ }
1579
2050
  }
1580
2051
  }
2052
+ } finally {
2053
+ onStopped();
2054
+ for (const controller of interactions.values()) controller.abort();
2055
+ await Promise.all(approvals);
2056
+ if (approvalErrors.length) throw new AggregateError(approvalErrors, "MaybeCode approval operations failed");
1581
2057
  }
1582
- for (const controller of interactions.values()) controller.abort();
1583
- await Promise.all(approvals);
1584
2058
  }
1585
2059
  __name(consumeEvents, "consumeEvents");
1586
- function presentApproval(app, view, store, request, isClosing, approvals) {
2060
+ function presentApproval(app, view, store, request, isClosing) {
1587
2061
  return view.requestApproval(request).then(async (decision) => {
1588
2062
  if (decision !== void 0 && !isClosing()) {
1589
- await app.resolveApproval(request.id, decision, decision === "allow-persistent" ? { createdBy: `local:${userInfo().username}` } : void 0);
2063
+ await app.resolveApproval(
2064
+ request.id,
2065
+ decision,
2066
+ decision === "allow-persistent" ? { createdBy: `local:${userInfo().username}` } : void 0
2067
+ );
1590
2068
  }
1591
2069
  }).catch((error) => {
1592
2070
  if (!isClosing()) {
1593
2071
  store.appendNotice("error", `Approval failed: ${errorMessage(error)}`);
2072
+ } else if (!isCancellation(error)) {
2073
+ throw error;
1594
2074
  }
1595
2075
  });
1596
2076
  }
1597
2077
  __name(presentApproval, "presentApproval");
1598
2078
  function applyMaybeCodeEvent(store, event) {
1599
2079
  switch (event.type) {
2080
+ case "delegation.finished":
2081
+ case "delegation.started":
2082
+ case "delegation.updated":
2083
+ case "goal.changed":
2084
+ case "mcp.interaction.requested":
2085
+ case "mcp.interaction.settled":
2086
+ case "permission-mode.changed":
2087
+ case "session.forked":
2088
+ case "workspace.git.changed":
2089
+ break;
1600
2090
  case "run.event":
1601
2091
  store.applyMayEvent(event.event);
1602
2092
  break;
@@ -1608,26 +2098,15 @@ function applyMaybeCodeEvent(store, event) {
1608
2098
  store.applyPermissionEvent(event.event);
1609
2099
  break;
1610
2100
  case "change.preview":
1611
- store.appendChangePreview(
1612
- event.runId,
1613
- event.step,
1614
- event.toolCallId,
1615
- event.preview
1616
- );
2101
+ store.appendChangePreview(event.runId, event.step, event.toolCallId, event.preview);
1617
2102
  break;
1618
2103
  case "session.changed":
1619
2104
  store.reset(event.sessionId);
1620
- store.appendNotice(
1621
- "info",
1622
- `Session ${event.resumed ? "resumed" : "started"}: ${event.sessionId}`
1623
- );
2105
+ store.appendNotice("info", `Session ${event.resumed ? "resumed" : "started"}: ${event.sessionId}`);
1624
2106
  break;
1625
2107
  case "model.changed": {
1626
2108
  const profile = event.model.profile === void 0 ? "" : ` profile ${event.model.profile}`;
1627
- store.appendNotice(
1628
- "info",
1629
- `Model switched to${profile}: ${event.model.provider}/${event.model.model}`
1630
- );
2109
+ store.appendNotice("info", `Model switched to${profile}: ${event.model.provider}/${event.model.model}`);
1631
2110
  break;
1632
2111
  }
1633
2112
  case "model.default.changed":
@@ -1640,19 +2119,13 @@ function applyMaybeCodeEvent(store, event) {
1640
2119
  store.appendNotice("info", `MCP resource watch closed: ${event.serverId} ${event.uri} (${event.reason})`);
1641
2120
  break;
1642
2121
  case "mcp.server.connected":
1643
- store.appendNotice(
1644
- "info",
1645
- `MCP server connected: ${event.serverId} (${event.toolNames.length} tools)`
1646
- );
2122
+ store.appendNotice("info", `MCP server connected: ${event.serverId} (${event.toolNames.length} tools)`);
1647
2123
  break;
1648
2124
  case "mcp.server.catalog-updated":
1649
2125
  store.appendNotice("info", `MCP catalog updated: ${event.serverId} (revision ${event.revision})`);
1650
2126
  break;
1651
2127
  case "mcp.server.failed":
1652
- store.appendNotice(
1653
- "warning",
1654
- `MCP server failed: ${event.serverId}: ${event.diagnostic.message}`
1655
- );
2128
+ store.appendNotice("warning", `MCP server failed: ${event.serverId}: ${event.diagnostic.message}`);
1656
2129
  break;
1657
2130
  case "mcp.server.disconnected":
1658
2131
  store.appendNotice("info", `MCP server disconnected: ${event.serverId}`);
@@ -1664,10 +2137,7 @@ function applyMaybeCodeEvent(store, event) {
1664
2137
  );
1665
2138
  break;
1666
2139
  case "context.compaction.failed":
1667
- store.appendNotice(
1668
- "warning",
1669
- `Context compaction failed with ${event.strategy}: ${event.error.message}`
1670
- );
2140
+ store.appendNotice("warning", `Context compaction failed with ${event.strategy}: ${event.error.message}`);
1671
2141
  break;
1672
2142
  }
1673
2143
  }
@@ -1675,10 +2145,7 @@ __name(applyMaybeCodeEvent, "applyMaybeCodeEvent");
1675
2145
  async function handleCommand(input, app, store, view, finish, web, observeRun) {
1676
2146
  const parsed = parseMaybeCodeSlashCommand(input);
1677
2147
  if (parsed.type === "command" && parsed.definition.name === "/compact" && parsed.arguments.length === 0) {
1678
- store.appendNotice(
1679
- "info",
1680
- "Pruning old tool results and summarizing context"
1681
- );
2148
+ store.appendNotice("info", "Pruning old tool results and summarizing context");
1682
2149
  }
1683
2150
  const result = await executeMaybeCodeSlashCommand(input, app);
1684
2151
  if (result.type === "web.requested") {
@@ -1697,12 +2164,8 @@ async function presentCommandResult(result, app, store, view, finish, observeRun
1697
2164
  store.appendNotice(
1698
2165
  "info",
1699
2166
  [
1700
- ...result.commands.map(
1701
- (command) => `${command.usage} \u2014 ${command.description}`
1702
- ),
1703
- ...view.displayCommands.map(
1704
- (command) => `${command.command} \u2014 ${command.description} (display only)`
1705
- )
2167
+ ...result.commands.map((command) => `${command.usage} \u2014 ${command.description}`),
2168
+ ...view.displayCommands.map((command) => `${command.command} \u2014 ${command.description} (display only)`)
1706
2169
  ].join("\n")
1707
2170
  );
1708
2171
  break;
@@ -1765,9 +2228,12 @@ Model: ${await resolvedModelLabel(app)}${inspectionText(result.inspection)}`
1765
2228
  });
1766
2229
  break;
1767
2230
  case "worktrees.display":
1768
- store.appendNotice("info", result.worktrees.length ? result.worktrees.map((item) => `${item.id}
2231
+ store.appendNotice(
2232
+ "info",
2233
+ result.worktrees.length ? result.worktrees.map((item) => `${item.id}
1769
2234
  ${item.path}
1770
- ${item.branch} \xB7 ${item.status} \xB7 ${item.commit.slice(0, 12)}`).join("\n\n") : "\u6CA1\u6709\u5DF2\u767B\u8BB0\u7684 worktree\u3002");
2235
+ ${item.branch} \xB7 ${item.status} \xB7 ${item.commit.slice(0, 12)}`).join("\n\n") : "\u6CA1\u6709\u5DF2\u767B\u8BB0\u7684 worktree\u3002"
2236
+ );
1771
2237
  break;
1772
2238
  case "session.resumed":
1773
2239
  store.appendNotice("info", `Resumed session ${result.sessionId}`);
@@ -1779,10 +2245,7 @@ ${item.branch} \xB7 ${item.status} \xB7 ${item.commit.slice(0, 12)}`).join("\n\n
1779
2245
  await refreshModelLabel(view, app);
1780
2246
  break;
1781
2247
  case "model.not-found":
1782
- store.appendNotice(
1783
- "warning",
1784
- `No model profile starts with: ${result.query}`
1785
- );
2248
+ store.appendNotice("warning", `No model profile starts with: ${result.query}`);
1786
2249
  break;
1787
2250
  case "effort.selection.requested":
1788
2251
  if (result.state.status !== "known") {
@@ -1796,10 +2259,7 @@ ${item.branch} \xB7 ${item.status} \xB7 ${item.commit.slice(0, 12)}`).join("\n\n
1796
2259
  store.appendNotice("info", reasoningEffortChanged(result.state));
1797
2260
  break;
1798
2261
  case "effort.not-found":
1799
- store.appendNotice(
1800
- "warning",
1801
- `No reasoning effort starts with: ${result.query}`
1802
- );
2262
+ store.appendNotice("warning", `No reasoning effort starts with: ${result.query}`);
1803
2263
  break;
1804
2264
  case "usage":
1805
2265
  store.appendNotice("warning", `Usage: ${result.usage}`);
@@ -1814,9 +2274,7 @@ async function runEffortDialog(view, app, store, state) {
1814
2274
  const effort = await view.requestReasoningEffortSelection(state);
1815
2275
  if (effort === void 0) return;
1816
2276
  try {
1817
- const changed = await app.setReasoningEffort(
1818
- effort === "default" ? void 0 : effort
1819
- );
2277
+ const changed = await app.setReasoningEffort(effort === "default" ? void 0 : effort);
1820
2278
  view.setModel(modelLabel(app, changed));
1821
2279
  store.appendNotice("info", reasoningEffortChanged(changed));
1822
2280
  } catch (error) {
@@ -1827,10 +2285,7 @@ __name(runEffortDialog, "runEffortDialog");
1827
2285
  async function runModelDialog(view, app, store, initialModels) {
1828
2286
  let models = initialModels;
1829
2287
  while (true) {
1830
- const action = await view.requestModelAction(
1831
- models,
1832
- app.modelInfo?.profile
1833
- );
2288
+ const action = await view.requestModelAction(models, app.application.modelInfo?.profile);
1834
2289
  if (action === void 0) return;
1835
2290
  try {
1836
2291
  if (action.type === "switch") {
@@ -1884,9 +2339,10 @@ Context: ~${inspection.effectiveTokens}${window} tokens, ${inspection.messageCou
1884
2339
  }
1885
2340
  __name(inspectionText, "inspectionText");
1886
2341
  function modelLabel(app, effort = "loading") {
1887
- if (app.modelInfo === void 0) return "unknown \xB7 effort: unknown";
1888
- const endpoint = `${app.modelInfo.provider}/${app.modelInfo.model}`;
1889
- const model = app.modelInfo.profile === void 0 ? endpoint : `${app.modelInfo.profile} (${endpoint})`;
2342
+ const info = app.application.modelInfo;
2343
+ if (info === void 0) return "unknown \xB7 effort: unknown";
2344
+ const endpoint = `${info.provider}/${info.model}`;
2345
+ const model = info.profile === void 0 ? endpoint : `${info.profile} (${endpoint})`;
1890
2346
  return `${model} \xB7 effort: ${reasoningEffortLabel(effort)}`;
1891
2347
  }
1892
2348
  __name(modelLabel, "modelLabel");
@@ -1912,7 +2368,7 @@ async function refreshModelLabel(view, app) {
1912
2368
  }
1913
2369
  __name(refreshModelLabel, "refreshModelLabel");
1914
2370
  function modelIdentity(app) {
1915
- const model = app.modelInfo;
2371
+ const model = app.application.modelInfo;
1916
2372
  return model === void 0 ? "" : `${model.profile ?? ""}\0${model.provider}\0${model.model}`;
1917
2373
  }
1918
2374
  __name(modelIdentity, "modelIdentity");
@@ -1945,4 +2401,4 @@ __name(errorMessage, "errorMessage");
1945
2401
  export {
1946
2402
  runRetainedTerminalUI
1947
2403
  };
1948
- //# sourceMappingURL=retained-tui-VJ3VX4R3.js.map
2404
+ //# sourceMappingURL=retained-tui-QF5VMYLC.js.map