@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,15 +1,15 @@
1
1
  import { isAbsolute, relative, resolve, sep } from "node:path";
2
2
  import { GitRequestController, requestMainRunIds, startGitGoalRequest, startGitRequest } from "./git-request.js";
3
3
  import { mediaHistory } from "./media-history.js";
4
- import { applicationServices, defineAgent, withDefaultCompactionThreshold, } from "@sortedyuan/application";
5
- import { createToolChangePreview, decodeToolChangePreviewPresentation, TOOL_CHANGE_PREVIEW_PRESENTATION_KIND, TOOL_CHANGE_PREVIEW_PRESENTATION_VERSION, } from "@sortedyuan/coding-tools";
6
- import { PruneOldToolResultsStrategy, } from "@sortedyuan/context";
7
- import { AsyncEventQueue, RunCancelledError, isStreamingMayEvent, ToolRegistry, } from "@sortedyuan/core";
8
- import { loadMaybeCodeInstructions, MaybeCodeInstructionState, } from "./instructions.js";
9
- import { historyMemoryService } from "@sortedyuan/plugin-history-memory";
10
- import { goalsService } from "@sortedyuan/plugin-goals";
11
- import { delegationService } from "@sortedyuan/plugin-delegation";
12
- import { mcpService } from "@sortedyuan/plugin-mcp";
4
+ import { applicationServices, defineAgent, withDefaultCompactionThreshold } from "@sortedyuan/may";
5
+ import { createToolChangePreview, decodeToolChangePreviewPresentation, TOOL_CHANGE_PREVIEW_PRESENTATION_KIND, TOOL_CHANGE_PREVIEW_PRESENTATION_VERSION, openCodingExecutionEnvironment, } from "@sortedyuan/coding-tools";
6
+ import { PruneOldToolResultsStrategy, } from "@sortedyuan/may/context";
7
+ import { AsyncEventQueue, RunCancelledError, isStreamingMayEvent, omitUndefined, ToolRegistry, } from "@sortedyuan/may/core";
8
+ import { loadMaybeCodeInstructions, MaybeCodeInstructionState } from "./instructions.js";
9
+ import { historyMemoryService } from "@sortedyuan/may/history-memory";
10
+ import { goalsService } from "@sortedyuan/may/goals/plugin";
11
+ import { delegationService } from "@sortedyuan/coordination/delegation";
12
+ import { mcpService } from "@sortedyuan/mcp/plugin";
13
13
  import { createMaybeCodePlugins, requestRecord } from "./plugins/application.js";
14
14
  import { createMaybeCodeInstructionsPlugin } from "./plugins/instructions.js";
15
15
  export { DEFAULT_MAYBE_CODE_INSTRUCTIONS } from "./instructions.js";
@@ -21,15 +21,16 @@ const MAYBECODE_MAX_STEPS = 32;
21
21
  *
22
22
  * Coding tools, prompts, permission defaults, preview presentation and named
23
23
  * compaction choices remain product policy. Session/run/approval persistence and
24
- * cancellation are delegated to `@sortedyuan/application`.
24
+ * cancellation are delegated to `@sortedyuan/may`.
25
25
  */
26
26
  export class MaybeCodeApplication {
27
27
  createModelPlugins;
28
+ execution;
28
29
  events;
29
30
  sessionId;
30
31
  workspace;
31
32
  instructionState;
32
- application;
33
+ agent;
33
34
  serviceReferences;
34
35
  updatingModel = false;
35
36
  modelUpdate;
@@ -51,44 +52,69 @@ export class MaybeCodeApplication {
51
52
  inputEpoch = 0;
52
53
  steeringCancellation = Promise.resolve();
53
54
  removeGoalListener;
54
- constructor(workspace, application, instructions, createModelPlugins) {
55
+ backgroundTasks = new Set();
56
+ backgroundErrors = [];
57
+ constructor(workspace, application, instructions, createModelPlugins, execution) {
55
58
  this.createModelPlugins = createModelPlugins;
59
+ this.execution = execution;
56
60
  this.workspace = workspace;
57
- this.application = application;
61
+ this.agent = application;
58
62
  this.sessionId = application.sessionId;
59
63
  this.instructionState = instructions;
60
64
  this.serviceReferences = this.readServices();
61
- this.events = this.eventQueue;
65
+ this.events = this.readEvents();
62
66
  this.eventRelay = this.relayEvents(application.events);
67
+ this.trackBackground(this.eventRelay);
63
68
  this.connectServiceEvents();
64
69
  }
65
70
  static async open(options) {
71
+ const execution = await openCodingExecutionEnvironment({
72
+ workspace: options.workspace,
73
+ isolation: options.execution ?? { mode: "host" },
74
+ });
75
+ let opened = false;
76
+ try {
77
+ const product = await MaybeCodeApplication.openWithExecution(options, execution);
78
+ opened = true;
79
+ return product;
80
+ }
81
+ finally {
82
+ if (!opened)
83
+ await execution.close();
84
+ }
85
+ }
86
+ static async openWithExecution(options, execution) {
66
87
  const workspace = resolve(options.workspace);
67
88
  const configuredTools = ToolRegistry.compose(options.tools ?? [], options.additionalTools ?? []);
68
- const created = options.resume && options.sessionId && options.store.inspect ? (await options.store.inspect(options.sessionId))[0] : undefined;
89
+ const created = options.resume && options.sessionId && options.store.inspect
90
+ ? (await options.store.inspect(options.sessionId))[0]
91
+ : undefined;
69
92
  const sessionMetadata = options.sessionMetadata ?? (created?.type === "session.created" ? created.metadata : undefined);
70
93
  const fork = sessionMetadata?.workspaceFork;
71
94
  const forkOrigin = options.fork ?? (created?.type === "session.created" ? created.fork : undefined);
72
95
  const instructions = await loadMaybeCodeInstructions({
73
96
  workspace,
74
- ...(options.instructions === undefined
75
- ? {}
76
- : { instructions: options.instructions }),
77
- ...(options.instructionsDirectory === undefined
78
- ? {}
79
- : { instructionsDirectory: options.instructionsDirectory }),
97
+ ...(options.instructions === undefined ? {} : { instructions: options.instructions }),
98
+ ...(options.instructionsDirectory === undefined ? {} : { instructionsDirectory: options.instructionsDirectory }),
80
99
  });
81
100
  const instructionState = new MaybeCodeInstructionState(workspace, instructions);
82
- const initialModelInfo = options.plugins?.some(plugin => plugin.provides?.some(service => service.id === applicationServices.model.id && service.scope === applicationServices.model.scope))
83
- ? undefined : options.modelInfo;
101
+ const initialModelInfo = options.plugins?.some((plugin) => plugin.provides?.some((service) => service.id === applicationServices.model.id && service.scope === applicationServices.model.scope))
102
+ ? undefined
103
+ : options.modelInfo;
84
104
  let product;
85
105
  const gitRequest = new GitRequestController(options.gitWorkspace);
86
- const createPlugins = (current) => createMaybeCodePlugins({ ...current,
87
- plugins: [createMaybeCodeInstructionsPlugin(instructionState, {
88
- workspace, options: current, historicalBranch: forkOrigin !== undefined || fork !== undefined,
89
- ...(forkOrigin === undefined ? {} : { historicalSource: forkOrigin.sessionId }),
90
- }), ...(current.plugins ?? [])],
91
- onGitCheckpoint: checkpoint => {
106
+ const createPlugins = (current) => createMaybeCodePlugins({
107
+ ...current,
108
+ plugins: [
109
+ createMaybeCodeInstructionsPlugin(instructionState, {
110
+ workspace,
111
+ options: current,
112
+ historicalBranch: forkOrigin !== undefined || fork !== undefined,
113
+ ...omitUndefined({ historicalSource: forkOrigin?.sessionId }),
114
+ }),
115
+ ...(current.plugins ?? []),
116
+ ],
117
+ onGitCheckpoint: (checkpoint) => {
92
118
  options.onGitCheckpoint?.(checkpoint);
93
119
  if (!product)
94
120
  throw new Error("Git checkpoint completed before the MaybeCode application was ready");
@@ -96,15 +122,20 @@ export class MaybeCodeApplication {
96
122
  },
97
123
  }, {
98
124
  workspace,
125
+ execution,
99
126
  gitRequest,
100
127
  instructions: instructions.system.content,
101
128
  instructionsSource: () => instructionState.current.system.content,
102
129
  projectInstructionsSource: () => instructionState.projectInstructions(),
103
130
  prepareInstructions: () => instructionState.refreshProject(),
104
- ...(current.contextBudget === undefined ? {} : { contextBudget: withDefaultCompactionThreshold(current.contextBudget) }),
131
+ ...(current.contextBudget === undefined
132
+ ? {}
133
+ : { contextBudget: withDefaultCompactionThreshold(current.contextBudget) }),
105
134
  });
106
135
  const composition = createPlugins(options);
107
136
  const definition = defineAgent({
137
+ requestRecording: options.requestRecording ?? "required",
138
+ providerBodyRecording: options.providerBodyRecording,
108
139
  plugins: composition.plugins,
109
140
  forkStateKeys: ["maybecode.context-notes", "maybecode.model"],
110
141
  forkPluginIds: ["may.history-memory"],
@@ -112,27 +143,23 @@ export class MaybeCodeApplication {
112
143
  tools: configuredTools,
113
144
  toolScope: { workspaceId: resolve(options.workspace) },
114
145
  beforeToolExecute: gitRequest.beforeToolExecute,
115
- ...(options.permissionRuleStore === undefined ? {} : { permissionRuleStore: options.permissionRuleStore }),
116
146
  instructions: instructions.system.content,
117
- ...(options.tracer === undefined ? {} : { tracer: options.tracer }),
147
+ ...omitUndefined({
148
+ permissionRuleStore: options.permissionRuleStore,
149
+ tracer: options.tracer,
150
+ runBudget: options.runBudget,
151
+ }),
118
152
  traceAttributes: {
119
153
  ...(options.traceAttributes ?? {}),
120
154
  "may.agent.name": "maybecode",
121
- ...(initialModelInfo?.profile === undefined
122
- ? {}
123
- : { "may.model.profile": initialModelInfo.profile }),
124
- ...(initialModelInfo?.provider === undefined
125
- ? {}
126
- : { "may.model.provider": initialModelInfo.provider }),
127
- ...(initialModelInfo?.adapter === undefined
128
- ? {}
129
- : { "may.model.adapter": initialModelInfo.adapter }),
130
- ...(initialModelInfo?.model === undefined
131
- ? {}
132
- : { "may.model.name": initialModelInfo.model }),
155
+ ...omitUndefined({
156
+ "may.model.profile": initialModelInfo?.profile,
157
+ "may.model.provider": initialModelInfo?.provider,
158
+ "may.model.adapter": initialModelInfo?.adapter,
159
+ "may.model.name": initialModelInfo?.model,
160
+ }),
133
161
  },
134
162
  maxSteps: options.maxSteps ?? MAYBECODE_MAX_STEPS,
135
- ...(options.runBudget === undefined ? {} : { runBudget: options.runBudget }),
136
163
  sessionHistory: { retrieval: true },
137
164
  createToolPresentation: async (check) => {
138
165
  const preview = await createToolChangePreview(workspace, check.tool.name, check.input);
@@ -151,22 +178,20 @@ export class MaybeCodeApplication {
151
178
  store: options.store,
152
179
  metadata: { ...options.sessionMetadata, workspace },
153
180
  contextMetadata: { workspace },
154
- ...(options.sessionId === undefined
155
- ? {}
156
- : { sessionId: options.sessionId }),
157
- ...(options.resume === undefined ? {} : { resume: options.resume }),
158
- ...(options.fork === undefined ? {} : { fork: options.fork }),
181
+ ...omitUndefined({ sessionId: options.sessionId, resume: options.resume, fork: options.fork }),
159
182
  });
160
- product = new MaybeCodeApplication(workspace, application, instructionState, update => {
161
- if (options.plugins?.some(plugin => plugin.provides?.some(service => service.id === applicationServices.model.id && service.scope === applicationServices.model.scope))) {
183
+ product = new MaybeCodeApplication(workspace, application, instructionState, (update) => {
184
+ if (options.plugins?.some((plugin) => plugin.provides?.some((service) => service.id === applicationServices.model.id && service.scope === applicationServices.model.scope))) {
162
185
  throw new Error("The configured Model plugin owns model selection");
163
186
  }
164
187
  const { model: _model, modelInfo: _modelInfo, modelRuntimeOptions: _modelRuntimeOptions, contextBudget: _contextBudget, ...base } = options;
165
188
  return createPlugins({ ...base, ...update });
166
- });
189
+ }, execution);
167
190
  product.gitRequest = gitRequest;
168
- product.permissionScopeId = options.permissionRuleStore === undefined ? undefined
169
- : options.permissionScopeId ?? `maybecode:${workspace}:main`;
191
+ product.permissionScopeId =
192
+ options.permissionRuleStore === undefined
193
+ ? undefined
194
+ : (options.permissionScopeId ?? `maybecode:${workspace}:main`);
170
195
  try {
171
196
  await product.recordModel(options.modelRuntimeOptions);
172
197
  }
@@ -178,38 +203,51 @@ export class MaybeCodeApplication {
178
203
  }
179
204
  readServices() {
180
205
  return {
181
- history: this.application.getService(historyMemoryService),
182
- modelInfo: this.application.getOptionalService(applicationServices.modelInfo),
183
- goals: this.application.getOptionalService(goalsService),
184
- subagents: this.application.getOptionalService(delegationService)?.get(),
185
- mcp: this.application.getOptionalService(mcpService),
206
+ history: this.agent.getService(historyMemoryService),
207
+ modelInfo: this.agent.getOptionalService(applicationServices.modelInfo),
208
+ goals: this.agent.getOptionalService(goalsService),
209
+ subagents: this.agent.getOptionalService(delegationService)?.get(),
210
+ mcp: this.agent.getOptionalService(mcpService),
186
211
  };
187
212
  }
188
- get modelInfo() { return this.serviceReferences.modelInfo; }
189
- get goals() { return this.serviceReferences.goals; }
190
- get subagents() { return this.serviceReferences.subagents; }
191
- get mcp() { return this.serviceReferences.mcp; }
192
- get modelUpdateFailed() { return this.modelUpdateFailure !== undefined; }
193
- get historyMemory() { return this.serviceReferences.history.memory; }
213
+ get modelInfo() {
214
+ return this.serviceReferences.modelInfo;
215
+ }
216
+ get goals() {
217
+ return this.serviceReferences.goals;
218
+ }
219
+ get subagents() {
220
+ return this.serviceReferences.subagents;
221
+ }
222
+ get mcp() {
223
+ return this.serviceReferences.mcp;
224
+ }
225
+ get modelUpdateFailed() {
226
+ return this.modelUpdateFailure !== undefined;
227
+ }
228
+ get historyMemory() {
229
+ return this.serviceReferences.history.memory;
230
+ }
194
231
  connectServiceEvents() {
195
232
  const { goals, subagents } = this.serviceReferences;
196
- this.removeGoalListener = goals?.subscribe(event => {
233
+ this.removeGoalListener = goals?.subscribe((event) => {
197
234
  this.eventQueue.push(event);
198
235
  if (!this.updatingModel && !goals.isRunning)
199
- void this.resumeSteering();
236
+ this.trackBackground(this.resumeSteering());
200
237
  });
201
238
  this.subagentRelay = subagents === undefined ? undefined : this.relaySubagentEvents(subagents.events);
239
+ if (this.subagentRelay)
240
+ this.trackBackground(this.subagentRelay);
202
241
  }
203
242
  async recordModel(runtimeOptions) {
204
243
  const info = this.modelInfo;
205
244
  if (info === undefined)
206
245
  return;
207
- await this.application.recordState("maybecode.model", {
208
- provider: info.provider, model: info.model,
209
- ...(info.adapter === undefined ? {} : { adapter: info.adapter }),
210
- ...(info.profile === undefined ? {} : { profile: info.profile }),
211
- runtimeOptions: typeof runtimeOptions?.reasoningEffort === "string"
212
- ? { reasoningEffort: runtimeOptions.reasoningEffort } : {},
246
+ await this.agent.recordState("maybecode.model", {
247
+ provider: info.provider,
248
+ model: info.model,
249
+ ...omitUndefined({ adapter: info.adapter, profile: info.profile }),
250
+ runtimeOptions: typeof runtimeOptions?.reasoningEffort === "string" ? { reasoningEffort: runtimeOptions.reasoningEffort } : {},
213
251
  });
214
252
  }
215
253
  async updateModel(update) {
@@ -218,7 +256,7 @@ export class MaybeCodeApplication {
218
256
  if (this.isRunning || this.compaction || this.getGoal()?.status === "active") {
219
257
  throw new Error("Finish the active operation before changing the model");
220
258
  }
221
- if ([this.sessionId, ...this.ownedDelegatedSessions()].some(sessionId => this.mcp?.interactions?.list({ workspaceId: this.workspace, sessionId }).length)) {
259
+ if ([this.sessionId, ...this.ownedDelegatedSessions()].some((sessionId) => this.mcp?.interactions?.list({ workspaceId: this.workspace, sessionId }).length)) {
222
260
  throw new Error("Finish the MCP interaction before changing the model");
223
261
  }
224
262
  const composition = this.createModelPlugins(update);
@@ -235,7 +273,7 @@ export class MaybeCodeApplication {
235
273
  }
236
274
  async replaceModelPlugins(composition, update) {
237
275
  try {
238
- await this.application.updatePlugins(composition.plugins);
276
+ await this.agent.updatePlugins(composition.plugins);
239
277
  this.removeGoalListener?.();
240
278
  await this.subagentRelay;
241
279
  this.serviceReferences = this.readServices();
@@ -249,12 +287,18 @@ export class MaybeCodeApplication {
249
287
  }
250
288
  }
251
289
  get isRunning() {
252
- return this.updatingModel || this.inputOperations > 0 || this.currentRun !== undefined || this.application.isRunning ||
253
- this.goals?.isRunning === true || this.subagents?.isRunning === true;
290
+ return (this.updatingModel ||
291
+ this.inputOperations > 0 ||
292
+ this.currentRun !== undefined ||
293
+ this.agent.isRunning ||
294
+ this.goals?.isRunning === true ||
295
+ this.subagents?.isRunning === true);
254
296
  }
255
297
  get instructions() {
256
- return { ...this.instructionState.current,
257
- effective: this.application.getService(applicationServices.instructionSources).snapshot() };
298
+ return {
299
+ ...this.instructionState.current,
300
+ effective: this.agent.getService(applicationServices.instructionSources).snapshot(),
301
+ };
258
302
  }
259
303
  submit(options) {
260
304
  const epoch = this.inputEpoch;
@@ -266,24 +310,24 @@ export class MaybeCodeApplication {
266
310
  const goalPause = this.goals?.isRunning ? this.goals.pause("Paused for a new user message") : undefined;
267
311
  if (run || compaction) {
268
312
  this.historyMemory.cancelRequest();
269
- this.application.cancel("Interrupted by a new user message");
313
+ this.agent.cancel("Interrupted by a new user message");
270
314
  await this.subagents?.cancel("Interrupted by a new user message");
271
315
  }
272
- await this.application.cancelSteeringInputs("Replaced by a new user message");
316
+ await this.agent.cancelSteeringInputs("Replaced by a new user message");
273
317
  await goalPause;
274
318
  await Promise.allSettled([...(run ? [run.result] : []), ...(compaction ? [compaction] : [])]);
275
319
  if (epoch !== this.inputEpoch)
276
320
  throw new RunCancelledError("Input cancelled before execution");
277
321
  options.signal?.throwIfAborted();
278
- const next = this.track(await this.startRequest({
322
+ const next = this.track(await this.startRequest(omitUndefined({
279
323
  mode: "submit",
280
324
  input: options.input,
281
325
  record: requestRecord(options.input),
282
- ...(options.runBudget === undefined ? {} : { runBudget: options.runBudget }),
283
- ...(options.shouldYield === undefined ? {} : { shouldYield: options.shouldYield }),
284
- ...(options.signal === undefined ? {} : { signal: options.signal }),
285
- ...(options.traceAttributes === undefined ? {} : { traceAttributes: options.traceAttributes }),
286
- }, options));
326
+ runBudget: options.runBudget,
327
+ shouldYield: options.shouldYield,
328
+ signal: options.signal,
329
+ traceAttributes: options.traceAttributes,
330
+ }), options));
287
331
  if (epoch !== this.inputEpoch) {
288
332
  next.cancel("Input cancelled during startup");
289
333
  await next.result.catch(() => undefined);
@@ -297,10 +341,10 @@ export class MaybeCodeApplication {
297
341
  if (epoch !== this.inputEpoch)
298
342
  throw new RunCancelledError("Input cancelled before acceptance");
299
343
  await this.steeringCancellation;
300
- const input = await this.application.steer(options);
344
+ const input = await this.agent.steer(options);
301
345
  if (epoch !== this.inputEpoch) {
302
346
  await this.steeringCancellation;
303
- return this.application.listSteeringInputs().find(item => item.inputId === input.inputId);
347
+ return this.agent.listSteeringInputs().find((item) => item.inputId === input.inputId);
304
348
  }
305
349
  if (input.status === "idle" && !this.goals?.isRunning && this.subagents?.isRunning !== true) {
306
350
  const run = this.track(await this.startRequest({
@@ -312,10 +356,9 @@ export class MaybeCodeApplication {
312
356
  if (epoch !== this.inputEpoch)
313
357
  run.cancel("Input cancelled during startup");
314
358
  }
315
- return this.application.listSteeringInputs().find(item => item.inputId === input.inputId);
359
+ return this.agent.listSteeringInputs().find((item) => item.inputId === input.inputId);
316
360
  });
317
361
  }
318
- listSteeringInputs() { return this.application.listSteeringInputs(); }
319
362
  serializeInput(operation, allowClosed = false) {
320
363
  this.inputOperations++;
321
364
  const result = this.inputTail.then(() => {
@@ -324,10 +367,16 @@ export class MaybeCodeApplication {
324
367
  if (this.updatingModel)
325
368
  throw new Error("Finish the model update before submitting input");
326
369
  if (this.modelUpdateFailure !== undefined)
327
- throw new Error("Model update failed; retry the model update before continuing", { cause: this.modelUpdateFailure });
370
+ throw new Error("Model update failed; retry the model update before continuing", {
371
+ cause: this.modelUpdateFailure,
372
+ });
328
373
  return operation();
329
374
  });
330
- this.inputTail = result.then(() => { this.inputOperations--; }, () => { this.inputOperations--; });
375
+ this.inputTail = result.then(() => {
376
+ this.inputOperations--;
377
+ }, () => {
378
+ this.inputOperations--;
379
+ });
331
380
  return result;
332
381
  }
333
382
  track(run) {
@@ -335,23 +384,29 @@ export class MaybeCodeApplication {
335
384
  const settled = () => {
336
385
  if (this.currentRun === run)
337
386
  this.currentRun = undefined;
338
- void this.resumeSteering();
387
+ return this.resumeSteering();
339
388
  };
340
- void run.result.then(settled, settled);
389
+ this.trackBackground(run.result.then(settled, settled));
341
390
  return run;
342
391
  }
343
392
  async resumeSteering() {
344
- if (this.closed || this.updatingModel || this.modelUpdateFailure !== undefined || !this.application.listSteeringInputs().some(input => input.status === "idle"))
393
+ if (this.closed ||
394
+ this.updatingModel ||
395
+ this.modelUpdateFailure !== undefined ||
396
+ !this.agent.listSteeringInputs().some((input) => input.status === "idle"))
345
397
  return;
346
398
  const epoch = this.inputEpoch;
347
399
  await this.serializeInput(async () => {
348
- if (this.closed || epoch !== this.inputEpoch || this.application.isRunning ||
349
- this.goals?.isRunning || this.subagents?.isRunning)
400
+ if (this.closed ||
401
+ epoch !== this.inputEpoch ||
402
+ this.agent.isRunning ||
403
+ this.goals?.isRunning ||
404
+ this.subagents?.isRunning)
350
405
  return;
351
406
  await this.steeringCancellation;
352
407
  if (this.closed || epoch !== this.inputEpoch)
353
408
  return;
354
- const input = this.application.listSteeringInputs().find(item => item.status === "idle");
409
+ const input = this.agent.listSteeringInputs().find((item) => item.status === "idle");
355
410
  if (input) {
356
411
  this.track(await this.startRequest({
357
412
  mode: "steer",
@@ -362,18 +417,28 @@ export class MaybeCodeApplication {
362
417
  }
363
418
  }, true);
364
419
  }
365
- getGoal() { return this.goals?.getGoal(); }
366
- getService(service) { return this.application.getService(service); }
367
- getOptionalService(service) { return this.application.getOptionalService(service); }
368
- startGoal(objective, budget) { return this.requireGoals().start(objective, budget); }
369
- resumeGoal() { return this.requireGoals().resume(); }
370
- pauseGoal() { return this.requireGoals().pause(); }
371
- cancelGoal() { return this.requireGoals().cancel(); }
420
+ getGoal() {
421
+ return this.goals?.getGoal();
422
+ }
423
+ startGoal(objective, budget) {
424
+ return this.requireGoals().start(objective, budget);
425
+ }
426
+ resumeGoal() {
427
+ return this.requireGoals().resume();
428
+ }
429
+ pauseGoal() {
430
+ return this.requireGoals().pause();
431
+ }
432
+ cancelGoal() {
433
+ return this.requireGoals().cancel();
434
+ }
372
435
  requireGoals() {
373
436
  if (this.updatingModel)
374
437
  throw new Error("Finish the model update before changing the goal");
375
438
  if (this.modelUpdateFailure !== undefined)
376
- throw new Error("Model update failed; retry the model update before continuing", { cause: this.modelUpdateFailure });
439
+ throw new Error("Model update failed; retry the model update before continuing", {
440
+ cause: this.modelUpdateFailure,
441
+ });
377
442
  if (!this.goals)
378
443
  throw new Error("Goals are disabled in this application");
379
444
  return this.goals;
@@ -392,26 +457,26 @@ export class MaybeCodeApplication {
392
457
  }
393
458
  /** 启动一次用户请求;未启用委派时启动一个普通 Run。 */
394
459
  async startRequest(plan, options, inputId) {
395
- return startGitRequest(this.gitRequest, this.sessionId, () => this.startRequestRun(plan, options, inputId), checkpoint => this.eventQueue.push({ type: "workspace.git.changed", checkpoint }), async (runId) => (await this.application.branchPositions()).find(position => position.runId === runId)?.positionSeq, async (firstRunId) => requestMainRunIds(await this.application.history(), firstRunId));
460
+ return startGitRequest(this.gitRequest, this.sessionId, () => this.startRequestRun(plan, options, inputId), (checkpoint) => this.eventQueue.push({ type: "workspace.git.changed", checkpoint }), async (runId) => (await this.agent.branchPositions()).find((position) => position.runId === runId)?.positionSeq, async (firstRunId) => requestMainRunIds(await this.agent.history(), firstRunId));
396
461
  }
397
462
  async startRequestRun(plan, options, inputId) {
398
463
  if (this.subagents !== undefined) {
399
- return this.subagents.start({
464
+ return this.subagents.start(omitUndefined({
400
465
  input: plan.input,
401
466
  record: plan.record,
402
- ...(inputId === undefined ? {} : { inputId }),
403
- ...(plan.runBudget === undefined ? {} : { runBudget: plan.runBudget }),
404
- ...(plan.shouldYield === undefined ? {} : { shouldYield: plan.shouldYield }),
405
- ...(plan.signal === undefined ? {} : { signal: plan.signal }),
406
- ...(plan.traceAttributes === undefined ? {} : { traceAttributes: plan.traceAttributes }),
407
- }, plan.mode === "continue" ? "continue" : "submit");
467
+ inputId,
468
+ runBudget: plan.runBudget,
469
+ shouldYield: plan.shouldYield,
470
+ signal: plan.signal,
471
+ traceAttributes: plan.traceAttributes,
472
+ }), plan.mode === "continue" ? "continue" : "submit");
408
473
  }
409
474
  if (plan.mode === "continue")
410
- return this.plainRun(await this.application.retry());
475
+ return this.plainRun(await this.agent.retry());
411
476
  if (plan.mode === "steer") {
412
- return this.plainRun(await this.application.startSteeringInput(inputId));
477
+ return this.plainRun(await this.agent.startSteeringInput(inputId));
413
478
  }
414
- return this.plainRun(await this.application.submit(options));
479
+ return this.plainRun(await this.agent.submit(options));
415
480
  }
416
481
  /** 没有委派的单个 Run 同样以一次请求的身份报告。 */
417
482
  plainRun(run) {
@@ -420,7 +485,7 @@ export class MaybeCodeApplication {
420
485
  id: run.id,
421
486
  requestId: `run-${run.id}`,
422
487
  result: run.result,
423
- ...(run.traceContext === undefined ? {} : { traceContext: run.traceContext }),
488
+ ...omitUndefined({ traceContext: run.traceContext }),
424
489
  cancel: (reason) => run.cancel(reason),
425
490
  runs: async () => [{ runId: run.id, sessionId, turn: 0, result: await run.result }],
426
491
  };
@@ -436,24 +501,26 @@ export class MaybeCodeApplication {
436
501
  return {
437
502
  sessionId: this.sessionId,
438
503
  get isRunning() {
439
- return owner.application.isRunning || owner.subagents?.isRunning === true;
504
+ return owner.agent.isRunning || owner.subagents?.isRunning === true;
440
505
  },
441
- submit: (options) => startGitGoalRequest(owner.gitRequest, owner.sessionId, () => owner.startRequestRun({
506
+ submit: (options) => startGitGoalRequest(owner.gitRequest, owner.sessionId, () => owner.startRequestRun(omitUndefined({
442
507
  mode: "submit",
443
508
  input: options.input,
444
509
  record: requestRecord(options.input),
445
- ...(options.runBudget === undefined ? {} : { runBudget: options.runBudget }),
446
- ...(options.shouldYield === undefined ? {} : { shouldYield: options.shouldYield }),
447
- ...(options.signal === undefined ? {} : { signal: options.signal }),
448
- }, { ...options, input: options.input }), checkpoint => owner.eventQueue.push({ type: "workspace.git.changed", checkpoint }), runId => owner.application.saveBranchPosition(runId, { allowYielded: true }), async (runId) => (await owner.application.branchPositions()).find(position => position.runId === runId)?.positionSeq, async (firstRunId) => requestMainRunIds(await owner.application.history(), firstRunId)),
449
- continue: (options) => startGitGoalRequest(owner.gitRequest, owner.sessionId, () => owner.subagents ? owner.startRequestRun({
450
- mode: "continue",
451
- input: "",
452
- record: "Continue the active goal",
453
- ...(options.runBudget === undefined ? {} : { runBudget: options.runBudget }),
454
- ...(options.shouldYield === undefined ? {} : { shouldYield: options.shouldYield }),
455
- ...(options.signal === undefined ? {} : { signal: options.signal }),
456
- }) : owner.application.continue(options), checkpoint => owner.eventQueue.push({ type: "workspace.git.changed", checkpoint }), runId => owner.application.saveBranchPosition(runId, { allowYielded: true }), async (runId) => (await owner.application.branchPositions()).find(position => position.runId === runId)?.positionSeq, async (firstRunId) => requestMainRunIds(await owner.application.history(), firstRunId)),
510
+ runBudget: options.runBudget,
511
+ shouldYield: options.shouldYield,
512
+ signal: options.signal,
513
+ }), { ...options, input: options.input }), (checkpoint) => owner.eventQueue.push({ type: "workspace.git.changed", checkpoint }), (runId) => owner.agent.saveBranchPosition(runId, { allowYielded: true }), async (runId) => (await owner.agent.branchPositions()).find((position) => position.runId === runId)?.positionSeq, async (firstRunId) => requestMainRunIds(await owner.agent.history(), firstRunId)),
514
+ continue: (options) => startGitGoalRequest(owner.gitRequest, owner.sessionId, () => owner.subagents
515
+ ? owner.startRequestRun(omitUndefined({
516
+ mode: "continue",
517
+ input: "",
518
+ record: "Continue the active goal",
519
+ runBudget: options.runBudget,
520
+ shouldYield: options.shouldYield,
521
+ signal: options.signal,
522
+ }))
523
+ : owner.agent.continue(options), (checkpoint) => owner.eventQueue.push({ type: "workspace.git.changed", checkpoint }), (runId) => owner.agent.saveBranchPosition(runId, { allowYielded: true }), async (runId) => (await owner.agent.branchPositions()).find((position) => position.runId === runId)?.positionSeq, async (firstRunId) => requestMainRunIds(await owner.agent.history(), firstRunId)),
457
524
  };
458
525
  }
459
526
  listDelegationRequests() {
@@ -484,97 +551,151 @@ export class MaybeCodeApplication {
484
551
  this.inputEpoch++;
485
552
  const request = this.subagents?.isRunning === true;
486
553
  if (request)
487
- void this.subagents?.cancel(reason ?? "Cancelled by user");
488
- const pending = this.inputOperations > 0 || this.application.listSteeringInputs().some(input => input.status === "pending" || input.status === "idle");
489
- this.steeringCancellation = this.application.cancelSteeringInputs(reason);
554
+ this.trackBackground(this.subagents.cancel(reason ?? "Cancelled by user"));
555
+ const pending = this.inputOperations > 0 ||
556
+ this.agent.listSteeringInputs().some((input) => input.status === "pending" || input.status === "idle");
557
+ this.steeringCancellation = this.agent.cancelSteeringInputs(reason);
558
+ this.trackBackground(this.steeringCancellation);
490
559
  this.historyMemory.cancelRequest();
491
560
  if (this.goals?.interrupt(reason))
492
561
  return true;
493
- return this.application.cancel(reason) || pending || request;
562
+ return this.agent.cancel(reason) || pending || request;
494
563
  }
495
564
  resolveApproval(requestId, decision, options) {
496
565
  const subagent = this.subagents?.resolveApproval(requestId, decision);
497
566
  return subagent === undefined
498
- ? this.application.resolveApproval(requestId, decision, options)
499
- : subagent.then(resolved => resolved || this.application.resolveApproval(requestId, decision, options));
567
+ ? this.agent.resolveApproval(requestId, decision, options)
568
+ : subagent.then((resolved) => resolved || this.agent.resolveApproval(requestId, decision, options));
569
+ }
570
+ get persistentRulesEnabled() {
571
+ return this.permissionScopeId !== undefined;
500
572
  }
501
- get persistentRulesEnabled() { return this.permissionScopeId !== undefined; }
502
573
  async listPermissionRules(scopeId) {
503
574
  if (this.permissionScopeId === undefined)
504
575
  throw new Error("持久权限规则没有启用。");
505
576
  if (scopeId !== undefined && scopeId !== this.permissionScopeId)
506
577
  throw new Error("权限规则范围不属于当前宿主。");
507
- return this.application.listPermissionRules(this.permissionScopeId);
578
+ return this.agent.listPermissionRules(this.permissionScopeId);
579
+ }
580
+ createPermissionRule(check, options) {
581
+ return this.agent.createPermissionRule(check, options);
508
582
  }
509
- createPermissionRule(check, options) { return this.application.createPermissionRule(check, options); }
510
583
  async createPermissionRuleFrom(id, options) {
511
- if (!(await this.listPermissionRules()).some(rule => rule.id === id))
584
+ if (!(await this.listPermissionRules()).some((rule) => rule.id === id))
512
585
  throw new Error("规则不属于当前宿主。");
513
- return this.application.createPermissionRuleFrom(id, options);
586
+ return this.agent.createPermissionRuleFrom(id, options);
514
587
  }
515
588
  async revokePermissionRule(id) {
516
- if (!(await this.listPermissionRules()).some(rule => rule.id === id))
589
+ if (!(await this.listPermissionRules()).some((rule) => rule.id === id))
517
590
  return false;
518
- return this.application.revokePermissionRule(id);
591
+ return this.agent.revokePermissionRule(id);
519
592
  }
520
593
  async history() {
521
- return mediaHistory(await this.application.history());
594
+ return mediaHistory(await this.agent.history());
595
+ }
596
+ listRecoveries() {
597
+ return this.agent.listRecoveries();
598
+ }
599
+ listSkills() {
600
+ const skills = this.agent.skills;
601
+ const active = new Map(skills?.listActive().map((item) => [item.name, item]));
602
+ const all = new Map(skills?.registry.list().map((item) => [item.name, item]));
603
+ for (const [name, item] of active)
604
+ all.set(name, item);
605
+ return [...all.values()].map((item) => ({ ...item, active: active.has(item.name) }));
522
606
  }
523
- listRecoveries() { return this.application.listRecoveries(); }
524
- get skills() { return this.application.skills; }
525
607
  activateSkill(name) {
526
608
  if (this.isRunning)
527
609
  throw new Error("Cannot activate a skill while an operation is active");
528
- return this.application.activateSkill(name);
610
+ return this.agent.activateSkill(name);
529
611
  }
530
612
  resolveRecovery(id, finding) {
531
613
  if (this.isRunning)
532
614
  throw new Error("Cannot resolve recovery while an operation is active");
533
- return this.application.resolveRecovery(id, finding);
615
+ return this.agent.resolveRecovery(id, finding);
534
616
  }
535
617
  queryHistory(query) {
536
- return this.application.queryHistory(query);
618
+ return this.agent.queryHistory(query);
537
619
  }
538
620
  branchPositions() {
539
- return this.application.branchPositions();
621
+ return this.agent.branchPositions();
540
622
  }
541
623
  inspectContext() {
542
624
  if (this.modelUpdateFailure !== undefined)
543
- throw new Error("Model update failed; retry the model update before continuing", { cause: this.modelUpdateFailure });
544
- return this.application.inspectContext();
625
+ throw new Error("Model update failed; retry the model update before continuing", {
626
+ cause: this.modelUpdateFailure,
627
+ });
628
+ return this.agent.inspectContext();
545
629
  }
546
630
  compactContext(selection) {
547
631
  if (this.updatingModel || this.subagents?.isRunning === true || this.goals?.isRunning === true) {
548
632
  throw new Error("Cannot compact context while a request or goal is active");
549
633
  }
550
634
  if (this.modelUpdateFailure !== undefined)
551
- throw new Error("Model update failed; retry the model update before continuing", { cause: this.modelUpdateFailure });
552
- const result = this.application.compactContext(this.resolveCompactionStrategy(selection));
635
+ throw new Error("Model update failed; retry the model update before continuing", {
636
+ cause: this.modelUpdateFailure,
637
+ });
638
+ const result = this.agent.compactContext(this.resolveCompactionStrategy(selection));
553
639
  this.compaction = result;
554
- const finished = () => { if (this.compaction === result)
555
- this.compaction = undefined; };
640
+ const finished = () => {
641
+ if (this.compaction === result)
642
+ this.compaction = undefined;
643
+ };
556
644
  void result.then(finished, finished);
557
645
  return result;
558
646
  }
559
647
  close() {
560
- return this.closing ??= this.closeOnce();
648
+ return (this.closing ??= this.closeOnce());
561
649
  }
562
650
  async closeOnce() {
563
651
  this.closed = true;
652
+ this.removeGoalListener?.();
564
653
  try {
565
654
  if (this.modelUpdate)
566
655
  await Promise.allSettled([this.modelUpdate]);
567
- await this.steeringCancellation;
568
- await this.application.close();
569
- await this.inputTail;
570
- await this.eventRelay;
571
- await this.subagentRelay;
656
+ const results = await Promise.allSettled([
657
+ this.steeringCancellation,
658
+ this.agent.close(),
659
+ this.inputTail,
660
+ this.eventRelay,
661
+ ...(this.subagentRelay ? [this.subagentRelay] : []),
662
+ ]);
663
+ while (this.backgroundTasks.size)
664
+ await Promise.all(this.backgroundTasks);
665
+ const failures = [
666
+ ...new Set([
667
+ ...this.backgroundErrors,
668
+ ...results.flatMap((result) => (result.status === "rejected" ? [result.reason] : [])),
669
+ ]),
670
+ ];
671
+ if (failures.length)
672
+ throw new AggregateError(failures, "MaybeCode background operations failed");
572
673
  }
573
674
  finally {
574
- this.removeGoalListener?.();
575
- this.eventQueue.close();
675
+ try {
676
+ await this.execution.close();
677
+ }
678
+ finally {
679
+ this.eventQueue.close();
680
+ }
576
681
  }
577
682
  }
683
+ trackBackground(operation) {
684
+ const task = operation.then(() => {
685
+ this.backgroundTasks.delete(task);
686
+ }, (error) => {
687
+ this.backgroundTasks.delete(task);
688
+ this.backgroundErrors.push(error);
689
+ this.eventQueue.close();
690
+ });
691
+ this.backgroundTasks.add(task);
692
+ }
693
+ async *readEvents() {
694
+ for await (const event of this.eventQueue)
695
+ yield event;
696
+ if (this.backgroundErrors.length)
697
+ throw new AggregateError(this.backgroundErrors, "MaybeCode background operations failed");
698
+ }
578
699
  async relaySubagentEvents(events) {
579
700
  for await (const event of events)
580
701
  this.eventQueue.push(event);
@@ -623,8 +744,7 @@ function requireNativeCompaction(strategy) {
623
744
  }
624
745
  function assertWorkspace(metadata, workspace) {
625
746
  const stored = metadata?.workspace;
626
- if (typeof stored === "string" &&
627
- normalizePath(stored) !== normalizePath(workspace)) {
747
+ if (typeof stored === "string" && normalizePath(stored) !== normalizePath(workspace)) {
628
748
  throw new Error(`Session belongs to another workspace: ${stored}`);
629
749
  }
630
750
  }