@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
package/dist/team-v2.js CHANGED
@@ -1,18 +1,21 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { mkdir, open, readFile, realpath, rename, stat } from "node:fs/promises";
2
+ import { mkdir, open, readFile, realpath, stat } from "node:fs/promises";
3
3
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
4
- import { defineAgent } from "@sortedyuan/application";
5
- import { createEditTool, createReadTool, createWriteTool } from "@sortedyuan/coding-tools";
6
- import { loadMayConfig } from "@sortedyuan/config";
7
- import { CoordinationRuntime, createApplicationAgent, FileArtifactStore, FileSharedBudget, TaskWorkspaceManager } from "@sortedyuan/coordination";
4
+ import { defineAgent } from "@sortedyuan/may";
5
+ import { createEditTool, createReadTool, createWriteTool, createGlobTool, createGrepTool, createFetchTool, } from "@sortedyuan/coding-tools";
6
+ import { TeamExecutionEnvironments } from "./team-execution.js";
7
+ import { loadMayConfig } from "@sortedyuan/may/config";
8
+ import { CoordinationRuntime, createApplicationAgent, FileArtifactStore, FileSharedBudget, TaskWorkspaceManager, } from "@sortedyuan/coordination";
8
9
  import { FileCoordinationStore } from "@sortedyuan/coordination/file-store";
9
- import { resolveRunBudget } from "@sortedyuan/core";
10
- import { FileSessionStore } from "@sortedyuan/session/file-store";
11
- import { withFileAccess } from "@sortedyuan/session/file-access";
12
- import { getDefaultMaybeCodeDataDirectory } from "./configured.js";
10
+ import { resolveRunBudget } from "@sortedyuan/may/core";
11
+ import { FileSessionStore } from "@sortedyuan/may/session/file-store";
12
+ import { hasErrorCode, withFileAccess } from "@sortedyuan/may/storage";
13
+ import writeFileAtomic from "write-file-atomic";
14
+ import { getDefaultMaybeCodeDataDirectory, resolveMaybeCodeRecording } from "./configured.js";
15
+ import { readMaybeCodeSettings } from "./settings.js";
13
16
  import { createMaybeCodeModel, selectMaybeCodeModel } from "./model.js";
14
17
  import { createListTool } from "./team.js";
15
- import { createTeamPreset, loadTeamPlan, parseTeamPlan } from "./team-plan.js";
18
+ import { createTeamPreset, loadTeamPlan, parseTeamPlan, } from "./team-plan.js";
16
19
  import { TeamVerificationStore } from "./team-verification.js";
17
20
  import { inspectTeam, readTeamResolution, retryImpact, teamReviewDigest } from "./team-recovery.js";
18
21
  import { applyTeamPatch, createTeamPatch, readTeamPatch, renderTeamPatchDiff } from "./team-patches.js";
@@ -35,21 +38,43 @@ export async function runTeamV2Command(command, dependencies) {
35
38
  if (!(await stat(workspace)).isDirectory() || inside(workspace, directory) || inside(directory, workspace))
36
39
  throw new Error("Team data directory must be outside and not overlap the source workspace");
37
40
  const mode = command.mode ?? "read-only";
38
- const plan = command.planPath ? await loadTeamPlan(command.planPath, { mode })
39
- : createTeamPreset(command.preset ?? "supervisor", command.value, { mode, ...(command.model ? { model: command.model } : {}) });
41
+ const plan = command.planPath
42
+ ? await loadTeamPlan(command.planPath, { mode })
43
+ : createTeamPreset(command.preset ?? "supervisor", command.value, {
44
+ mode,
45
+ ...(command.model ? { model: command.model } : {}),
46
+ });
40
47
  config = await (dependencies.loadConfig ?? loadMayConfig)(command.configPath ? { path: command.configPath } : {});
41
- const fallback = command.model ?? (Object.values(plan.roles).every((role) => role.model !== undefined) ? Object.values(plan.roles)[0].model : undefined);
48
+ const fallback = command.model ??
49
+ (Object.values(plan.roles).every((role) => role.model !== undefined)
50
+ ? Object.values(plan.roles)[0].model
51
+ : undefined);
42
52
  const defaultModel = selectMaybeCodeModel(config, fallback ? { model: fallback } : {});
43
53
  const roleModels = {};
44
54
  for (const [name, role] of Object.entries(plan.roles)) {
45
55
  const selected = selectMaybeCodeModel(config, { model: role.model ?? defaultModel.profile });
46
- const runBudget = resolveRunBudget(resolveRunBudget(config.apps?.maybecode?.runBudget, DEFAULT_RUN_BUDGET), role.runBudget);
56
+ const runBudget = resolveRunBudget(resolveRunBudget(readMaybeCodeSettings(config).runBudget, DEFAULT_RUN_BUDGET), role.runBudget);
47
57
  roleModels[name] = { profile: selected.profile, fingerprint: modelFingerprint(selected), runBudget };
48
58
  }
49
- manifest = { format: 1, version: VERSION, id, createdAt: new Date().toISOString(), workspace, configPath: resolve(config.path),
50
- model: defaultModel.profile, prompt: command.value, mode, allowChecks: command.allowChecks === true, plan, roleModels,
51
- maxModelCalls: command.maxModelCalls ?? 32, maxTotalTokens: command.maxTotalTokens ?? 524_288,
52
- maxConcurrent: command.maxConcurrent ?? plan.limits?.maxConcurrent ?? 2 };
59
+ manifest = {
60
+ execution: readMaybeCodeSettings(config).execution ?? { mode: "host" },
61
+ fetch: readMaybeCodeSettings(config).fetch ?? {},
62
+ format: 1,
63
+ version: VERSION,
64
+ id,
65
+ createdAt: new Date().toISOString(),
66
+ workspace,
67
+ configPath: resolve(config.path),
68
+ model: defaultModel.profile,
69
+ prompt: command.value,
70
+ mode,
71
+ allowChecks: command.allowChecks === true,
72
+ plan,
73
+ roleModels,
74
+ maxModelCalls: command.maxModelCalls ?? 32,
75
+ maxTotalTokens: command.maxTotalTokens ?? 524_288,
76
+ maxConcurrent: command.maxConcurrent ?? plan.limits?.maxConcurrent ?? 2,
77
+ };
53
78
  validateManifest(manifest, id);
54
79
  await mkdir(directory, { recursive: true, mode: 0o700 });
55
80
  await writeJson(join(directory, "manifest.json"), manifest, true);
@@ -69,7 +94,7 @@ export async function runTeamV2Command(command, dependencies) {
69
94
  write(`Last acceptance projection (may be stale): ${await withFileAccess(path, "shared", () => readFile(path, "utf8"))}\n`);
70
95
  }
71
96
  catch (error) {
72
- if (!isMissing(error))
97
+ if (!hasErrorCode(error, "ENOENT"))
73
98
  throw error;
74
99
  }
75
100
  return 0;
@@ -81,8 +106,10 @@ export async function runTeamV2Command(command, dependencies) {
81
106
  }
82
107
  const executes = command.action === "run" || command.action === "resume";
83
108
  const selections = new Map();
109
+ let recording;
84
110
  if (executes) {
85
111
  config ??= await (dependencies.loadConfig ?? loadMayConfig)({ path: manifest.configPath });
112
+ recording = resolveMaybeCodeRecording(config);
86
113
  for (const [name, binding] of Object.entries(manifest.roleModels)) {
87
114
  const selected = selectMaybeCodeModel(config, { model: binding.profile });
88
115
  if (modelFingerprint(selected) !== binding.fingerprint)
@@ -91,6 +118,13 @@ export async function runTeamV2Command(command, dependencies) {
91
118
  }
92
119
  }
93
120
  const ledger = await FileSharedBudget.open(join(directory, "budget"), id, budgetLimits);
121
+ const settings = readMaybeCodeSettings({
122
+ providers: {},
123
+ models: {},
124
+ path: manifest.configPath,
125
+ apps: { maybecode: { execution: manifest.execution ?? { mode: "host" }, fetch: manifest.fetch ?? {} } },
126
+ });
127
+ const executionEnvironments = new TeamExecutionEnvironments(settings.execution);
94
128
  let workspaces;
95
129
  let artifacts;
96
130
  let verification;
@@ -99,13 +133,46 @@ export async function runTeamV2Command(command, dependencies) {
99
133
  let timer;
100
134
  let cancelling;
101
135
  let retryAuthorized = false;
102
- const cancel = () => { if (runtime)
103
- cancelling ??= runtime.cancel(`cancel-${id}`); void cancelling?.catch(() => undefined); };
136
+ const backgroundTasks = new Set();
137
+ const backgroundErrors = [];
138
+ let failBackground;
139
+ const backgroundFailed = new Promise((resolve) => {
140
+ failBackground = resolve;
141
+ });
142
+ const trackBackground = (operation) => {
143
+ const task = operation.then(() => {
144
+ backgroundTasks.delete(task);
145
+ }, (error) => {
146
+ backgroundTasks.delete(task);
147
+ backgroundErrors.push(error);
148
+ failBackground(error);
149
+ cancel();
150
+ });
151
+ backgroundTasks.add(task);
152
+ };
153
+ const cancel = () => {
154
+ if (runtime && !cancelling) {
155
+ cancelling = runtime.cancel(`cancel-${id}`);
156
+ trackBackground(cancelling);
157
+ }
158
+ };
104
159
  try {
105
- artifacts = await FileArtifactStore.open(join(directory, "artifacts"), id, { policyVersion: VERSION,
106
- authorizeRead: () => true, maxArtifacts: 256, maxArtifactBytes: 262_144, maxTotalBytes: 16_777_216 });
107
- workspaces = await TaskWorkspaceManager.open({ sourceDirectory: manifest.workspace, directory: join(directory, "workspaces") });
108
- verification = await TeamVerificationStore.open({ directory: join(directory, "verification"), checks: manifest.plan.checks });
160
+ artifacts = await FileArtifactStore.open(join(directory, "artifacts"), id, {
161
+ policyVersion: VERSION,
162
+ authorizeRead: () => true,
163
+ maxArtifacts: 256,
164
+ maxArtifactBytes: 262_144,
165
+ maxTotalBytes: 16_777_216,
166
+ });
167
+ workspaces = await TaskWorkspaceManager.open({
168
+ sourceDirectory: manifest.workspace,
169
+ directory: join(directory, "workspaces"),
170
+ });
171
+ verification = await TeamVerificationStore.open({
172
+ directory: join(directory, "verification"),
173
+ checks: manifest.plan.checks,
174
+ executionFor: (workspace) => executionEnvironments.get(workspace),
175
+ });
109
176
  const sessionStore = new FileSessionStore(join(directory, "sessions"));
110
177
  const models = new Map();
111
178
  const modelFor = (name) => {
@@ -115,42 +182,86 @@ export async function runTeamV2Command(command, dependencies) {
115
182
  if (!selected)
116
183
  throw new Error("A host control command cannot start a model");
117
184
  const maxOutputTokens = Math.min(4096, selected.limits?.maxOutputTokens ?? 4096, ...[selected.options.maxTokens, selected.options.maxOutputTokens].filter((n) => typeof n === "number" && n > 0 && Number.isSafeInteger(n)));
118
- const selection = { ...selected, options: { ...selected.options, maxTokens: maxOutputTokens, maxOutputTokens },
119
- limits: { ...selected.limits, maxOutputTokens } };
120
- model = ledger.wrapModel((dependencies.createModel ?? createMaybeCodeModel)(selection), { reservation: { totalTokens: RESERVATION } });
185
+ const selection = {
186
+ ...selected,
187
+ options: { ...selected.options, maxTokens: maxOutputTokens, maxOutputTokens },
188
+ limits: { ...selected.limits, maxOutputTokens },
189
+ };
190
+ model = ledger.wrapModel((dependencies.createModel ?? createMaybeCodeModel)(selection), {
191
+ reservation: { totalTokens: RESERVATION },
192
+ });
121
193
  models.set(name, model);
122
194
  }
123
195
  return model;
124
196
  };
125
197
  const agents = {};
126
198
  for (const [name, role] of Object.entries(manifest.plan.roles)) {
127
- const scoped = (execution, workspace) => createApplicationAgent({ version: authorityVersion, store: sessionStore,
128
- delegation: role.delegateTo.length > 0, messaging: role.messaging,
129
- definition: ({ tools }) => {
130
- const available = [createReadTool({ cwd: workspace, maxBytes: 262_144, maxLines: 160 }), createListTool(workspace),
131
- ...artifacts.forTask(execution.task.id).tools(), ...verification.forTask(execution, workspace, { allowCommands: manifest.allowChecks }).tools(),
132
- ...(manifest.mode === "coding" ? [createWriteTool({ cwd: workspace, maxBytes: 262_144 }), createEditTool({ cwd: workspace, maxBytes: 262_144 })] : [])];
133
- const selectedTools = available.filter((tool) => role.tools.includes(tool.name)).map((tool) => {
134
- if (!["write", "edit"].includes(tool.name))
135
- return tool;
136
- return { ...tool, async execute(input, context) {
137
- if ((await verification.snapshot()).checks.some((check) => check.status === "unknown" || (check.taskId === execution.task.id && check.status === "pending")))
138
- throw new Error("Pending or unknown check effects block editing; stop and reconcile uncertain processes first");
139
- return tool.execute(input, context);
140
- } };
141
- });
142
- const allowed = new Set([...selectedTools, ...tools].map((tool) => tool.name));
143
- const roleBudget = manifest.roleModels[name].runBudget;
144
- const budget = config ? resolveRunBudget(roleBudget, config.apps?.maybecode?.runBudget) : roleBudget;
145
- return defineAgent({ model: modelFor(name), tools: [...selectedTools, ...tools], runBudget: budget,
146
- instructions: instructions(manifest, name, role), toolScope: { workspaceId: workspace },
147
- permissionPolicy: (check) => allowed.has(check.tool.name) ? "allow" : "deny" });
148
- },
149
- });
199
+ const scoped = async (execution, workspace) => {
200
+ const environment = await executionEnvironments.get(workspace);
201
+ return createApplicationAgent({
202
+ version: authorityVersion,
203
+ store: sessionStore,
204
+ delegation: role.delegateTo.length > 0,
205
+ messaging: role.messaging,
206
+ definition: ({ tools }) => {
207
+ const available = [
208
+ createReadTool({ cwd: workspace, maxBytes: 262_144, maxLines: 160 }),
209
+ createGlobTool({ cwd: workspace, execution: environment }),
210
+ createGrepTool({ cwd: workspace, execution: environment }),
211
+ createFetchTool(settings?.fetch ?? {}),
212
+ createListTool(workspace),
213
+ ...artifacts.forTask(execution.task.id).tools(),
214
+ ...verification.forTask(execution, workspace, { allowCommands: manifest.allowChecks }).tools(),
215
+ ...(manifest.mode === "coding"
216
+ ? [
217
+ createWriteTool({ cwd: workspace, maxBytes: 262_144 }),
218
+ createEditTool({ cwd: workspace, maxBytes: 262_144 }),
219
+ ]
220
+ : []),
221
+ ];
222
+ const selectedTools = available
223
+ .filter((tool) => role.tools.includes(tool.name))
224
+ .map((tool) => {
225
+ if (!["write", "edit"].includes(tool.name))
226
+ return tool;
227
+ return {
228
+ ...tool,
229
+ async execute(input, context) {
230
+ if ((await verification.snapshot()).checks.some((check) => check.status === "unknown" ||
231
+ (check.taskId === execution.task.id && check.status === "pending")))
232
+ throw new Error("Pending or unknown check effects block editing; stop and reconcile uncertain processes first");
233
+ return tool.execute(input, context);
234
+ },
235
+ };
236
+ });
237
+ const allowed = new Set([...selectedTools, ...tools].map((tool) => tool.name));
238
+ const roleBudget = manifest.roleModels[name].runBudget;
239
+ const budget = config ? resolveRunBudget(roleBudget, readMaybeCodeSettings(config).runBudget) : roleBudget;
240
+ if (!recording)
241
+ throw new Error("A host control command cannot start a model");
242
+ return defineAgent({
243
+ ...recording,
244
+ model: modelFor(name),
245
+ tools: [...selectedTools, ...tools],
246
+ runBudget: budget,
247
+ instructions: instructions(manifest, name, role),
248
+ toolScope: { workspaceId: workspace },
249
+ permissionPolicy: (check) => (allowed.has(check.tool.name) ? "allow" : "deny"),
250
+ });
251
+ },
252
+ });
253
+ };
150
254
  const publish = async (execution, output) => {
151
- await artifacts.forTask(execution.task.id).publish(`${execution.task.dispatchId}-${execution.task.turn ?? 0}-final`, { name: `${execution.task.id.slice(0, 100)}-result.md`, text: output.text, mimeType: "text/markdown" });
255
+ await artifacts
256
+ .forTask(execution.task.id)
257
+ .publish(`${execution.task.dispatchId}-${execution.task.turn ?? 0}-final`, {
258
+ name: `${execution.task.id.slice(0, 100)}-result.md`,
259
+ text: output.text,
260
+ mimeType: "text/markdown",
261
+ });
152
262
  };
153
- agents[name] = { version: authorityVersion,
263
+ agents[name] = {
264
+ version: authorityVersion,
154
265
  async execute(execution, context) {
155
266
  if ((await verification.snapshot()).checks.some((check) => check.status === "unknown"))
156
267
  throw new Error("Unknown check effects block a new Agent Run; reconcile before retrying");
@@ -159,15 +270,25 @@ export async function runTeamV2Command(command, dependencies) {
159
270
  for (const dependency of execution.dependencies) {
160
271
  const source = await workspaces.prepare(dependency.taskId);
161
272
  const acceptance = await verification.acceptance(dependency.taskId, source.directory, executionOf(runtime.snapshot(), dependency.taskId));
162
- const record = { taskId: dependency.taskId, status: acceptance.status, workspaceFingerprint: acceptance.workspaceFingerprint,
163
- checks: acceptance.checks.slice(0, 16), checksTruncated: acceptance.checks.length > 16,
273
+ const record = {
274
+ taskId: dependency.taskId,
275
+ status: acceptance.status,
276
+ workspaceFingerprint: acceptance.workspaceFingerprint,
277
+ checks: acceptance.checks.slice(0, 16),
278
+ checksTruncated: acceptance.checks.length > 16,
164
279
  evidenceValid: acceptance.report?.evidence.every((item) => item.valid) ?? false,
165
- detail: acceptance.detail };
166
- dependencyResults.push({ ...dependency, output: { ...dependency.output,
167
- text: `${dependency.output.text}\n\nHost verification record (scoped to that task's private workspace, not the source checkout or every claim):\n${JSON.stringify(record)}` } });
280
+ detail: acceptance.detail,
281
+ };
282
+ dependencyResults.push({
283
+ ...dependency,
284
+ output: {
285
+ ...dependency.output,
286
+ text: `${dependency.output.text}\n\nHost verification record (scoped to that task's private workspace, not the source checkout or every claim):\n${JSON.stringify(record)}`,
287
+ },
288
+ });
168
289
  }
169
290
  const submitted = { ...execution, dependencies: dependencyResults };
170
- const output = await scoped(submitted, isolated.directory).execute(submitted, context);
291
+ const output = await (await scoped(submitted, isolated.directory)).execute(submitted, context);
171
292
  if (!("yielded" in output)) {
172
293
  await publish(execution, output);
173
294
  // Only deterministic file checks run automatically; command checks need explicit invocation.
@@ -178,24 +299,35 @@ export async function runTeamV2Command(command, dependencies) {
178
299
  return output;
179
300
  },
180
301
  async recover(execution) {
181
- const output = await scoped(execution, manifest.workspace).recover(execution);
302
+ const output = await (await scoped(execution, manifest.workspace)).recover(execution);
182
303
  if (output.status === "completed")
183
304
  await publish(execution, output.output);
184
305
  return output;
185
- }, };
306
+ },
307
+ };
186
308
  }
187
- const options = { id, store: new FileCoordinationStore(join(directory, "coordination")), agents,
188
- policy: { version: authorityVersion,
309
+ const options = {
310
+ id,
311
+ store: new FileCoordinationStore(join(directory, "coordination")),
312
+ agents,
313
+ policy: {
314
+ version: authorityVersion,
189
315
  authorize: (task) => Object.hasOwn(manifest.plan.roles, task.agent),
190
316
  authorizeDelegation: (parent, child) => manifest.plan.roles[parent.agent]?.delegateTo.includes(child.agent) === true,
191
- authorizeMessage: (sender, recipient) => manifest.plan.roles[sender.agent]?.messaging === true && manifest.plan.roles[recipient.agent]?.messaging === true,
317
+ authorizeMessage: (sender, recipient) => manifest.plan.roles[sender.agent]?.messaging === true &&
318
+ manifest.plan.roles[recipient.agent]?.messaging === true,
192
319
  authorizeRetry: (task, finding) => {
193
320
  if (retryAuthorized)
194
321
  return true;
195
322
  // Dispatch rechecks the exact durable host approval, not an ephemeral CLI flag.
196
323
  const state = runtime?.snapshot(), current = state?.tasks.find((entry) => entry.id === task.id);
197
324
  const previous = current?.attempts?.at(-1);
198
- if (current?.status !== "queued" || !previous || previous.task.dispatchId !== task.dispatchId || previous.task.sessionId !== task.sessionId || previous.finding !== finding || !/^retry-[a-f0-9]{64}$/u.test(previous.commandId))
325
+ if (current?.status !== "queued" ||
326
+ !previous ||
327
+ previous.task.dispatchId !== task.dispatchId ||
328
+ previous.task.sessionId !== task.sessionId ||
329
+ previous.finding !== finding ||
330
+ !/^retry-[a-f0-9]{64}$/u.test(previous.commandId))
199
331
  return false;
200
332
  const receipt = state?.commands[previous.commandId];
201
333
  if (!receipt)
@@ -203,10 +335,26 @@ export async function runTeamV2Command(command, dependencies) {
203
335
  const value = JSON.parse(receipt);
204
336
  return value.type === "retry" && value.taskId === task.id && value.finding === finding;
205
337
  },
206
- } };
207
- runtime = command.action === "run" ? await CoordinationRuntime.create({ ...options, tasks: manifest.plan.tasks,
208
- limits: { maxTasks: 128, maxDepth: 2, maxTaskTurns: 4, maxDurationMs: 600_000, maxOutputBytes: 65_536,
209
- maxMessages: 24, maxMessageBytes: 8192, ...manifest.plan.limits, maxConcurrent: manifest.maxConcurrent } }) : await CoordinationRuntime.resume(options);
338
+ },
339
+ };
340
+ runtime =
341
+ command.action === "run"
342
+ ? await CoordinationRuntime.create({
343
+ ...options,
344
+ tasks: manifest.plan.tasks,
345
+ limits: {
346
+ maxTasks: 128,
347
+ maxDepth: 2,
348
+ maxTaskTurns: 4,
349
+ maxDurationMs: 600_000,
350
+ maxOutputBytes: 65_536,
351
+ maxMessages: 24,
352
+ maxMessageBytes: 8192,
353
+ ...manifest.plan.limits,
354
+ maxConcurrent: manifest.maxConcurrent,
355
+ },
356
+ })
357
+ : await CoordinationRuntime.resume(options);
210
358
  write(`Team ${id}\nMode: ${manifest.mode}; source application requires a separate reviewed patch confirmation.\nRecords: ${directory}\n`);
211
359
  if (manifest.allowChecks)
212
360
  write("Configured test processes explicitly authorized; no OS sandbox or automatic dependency installation.\n");
@@ -220,16 +368,20 @@ export async function runTeamV2Command(command, dependencies) {
220
368
  write(`[${task.id}] ${task.status}${task.detail ? `: ${task.detail}` : ""}\n`);
221
369
  }
222
370
  }
223
- else if (event.type === "agent.event" && event.event.type === "run.event" && event.event.event.type === "tool.started")
371
+ else if (event.type === "agent.event" &&
372
+ event.event.type === "run.event" &&
373
+ event.event.event.type === "tool.started")
224
374
  write(`[${event.taskId}] tool ${event.event.event.call.name}\n`);
225
375
  else if (event.type === "runtime.failed")
226
376
  write("Team runtime failed; inspect recovery records.\n");
227
377
  }
228
378
  })();
229
- void relay.catch(cancel);
379
+ trackBackground(relay);
230
380
  if (command.action === "retry" || command.action === "reconcile") {
231
381
  const state = runtime.snapshot(), budget = await ledger.snapshot(), checks = await verification.snapshot();
232
- const operation = command.action === "retry" ? retryImpact(state, command.task, command.finding) : await readTeamResolution(command.resolutionPath);
382
+ const operation = command.action === "retry"
383
+ ? retryImpact(state, command.task, command.finding)
384
+ : await readTeamResolution(command.resolutionPath);
233
385
  // Resume may repeat evidence inspection and increment revision without changing meaning.
234
386
  const { revision: _revision, ...stableState } = state;
235
387
  const digest = teamReviewDigest({ operation, state: stableState, budget, checks });
@@ -241,7 +393,8 @@ export async function runTeamV2Command(command, dependencies) {
241
393
  if (command.confirm !== digest)
242
394
  throw new Error("Review digest changed or mismatched; inspect a fresh preview");
243
395
  if (command.action === "retry") {
244
- if ((await ledger.totals()).blocked || checks.checks.some((check) => ["unknown", "pending"].includes(check.status)))
396
+ if ((await ledger.totals()).blocked ||
397
+ checks.checks.some((check) => ["unknown", "pending"].includes(check.status)))
245
398
  throw new Error("Reconcile unknown usage/check effects before retrying; no reset or replay is allowed");
246
399
  retryAuthorized = true;
247
400
  await runtime.retryTask(`retry-${digest}`, command.task, command.finding);
@@ -253,7 +406,10 @@ export async function runTeamV2Command(command, dependencies) {
253
406
  else if (resolution.kind === "check")
254
407
  await verification.reconcile(resolution.commandId, { status: resolution.outcome }, resolution.finding);
255
408
  else
256
- await runtime.resolveRecovery(`resolve-${digest}`, resolution.taskId, resolution.finding, { status: resolution.outcome, detail: resolution.finding });
409
+ await runtime.resolveRecovery(`resolve-${digest}`, resolution.taskId, resolution.finding, {
410
+ status: resolution.outcome,
411
+ detail: resolution.finding,
412
+ });
257
413
  }
258
414
  write("Recorded. No agents or checks executed. Use team resume explicitly when ready.\n");
259
415
  return 0;
@@ -266,7 +422,9 @@ export async function runTeamV2Command(command, dependencies) {
266
422
  throw new Error("Settle all active/unknown team work before reviewing or applying a patch");
267
423
  if (command.action === "diff") {
268
424
  const taskIds = command.tasks.split(",");
269
- if (!taskIds.length || new Set(taskIds).size !== taskIds.length || taskIds.some((id) => state.tasks.find((task) => task.id === id)?.status !== "completed"))
425
+ if (!taskIds.length ||
426
+ new Set(taskIds).size !== taskIds.length ||
427
+ taskIds.some((id) => state.tasks.find((task) => task.id === id)?.status !== "completed"))
270
428
  throw new Error("Select distinct completed task ids for review");
271
429
  const patch = await createTeamPatch({ directory, workspaces, taskIds });
272
430
  write(renderTeamPatchDiff(patch));
@@ -274,22 +432,31 @@ export async function runTeamV2Command(command, dependencies) {
274
432
  return 0;
275
433
  }
276
434
  const patch = await readTeamPatch(directory, command.patch);
277
- const uncheckedTasks = patch.taskSnapshots.map((task) => task.taskId).filter((taskId) => !manifest.plan.checks.some((check) => check.taskId === taskId));
435
+ const uncheckedTasks = patch.taskSnapshots
436
+ .map((task) => task.taskId)
437
+ .filter((taskId) => !manifest.plan.checks.some((check) => check.taskId === taskId));
278
438
  if (uncheckedTasks.length)
279
439
  write(`Unverified patch tasks (human review only): ${uncheckedTasks.join(", ")}. Other tasks' passing checks do not verify these edits.\n`);
280
- if ((await ledger.totals()).blocked || (await verification.snapshot()).checks.some((check) => ["pending", "unknown"].includes(check.status)))
440
+ if ((await ledger.totals()).blocked ||
441
+ (await verification.snapshot()).checks.some((check) => ["pending", "unknown"].includes(check.status)))
281
442
  throw new Error("Reconcile unknown team effects before applying source changes");
282
443
  for (const checkTaskId of new Set(manifest.plan.checks.map((check) => check.taskId))) {
283
444
  const task = state.tasks.find((task) => task.id === checkTaskId);
284
445
  if (task?.status !== "completed")
285
446
  throw new Error("All configured acceptance tasks must complete before source application");
286
447
  const workspace = await workspaces.prepare(checkTaskId);
287
- if ((await verification.acceptance(checkTaskId, workspace.directory, executionOf(state, checkTaskId))).status !== "passed")
448
+ if ((await verification.acceptance(checkTaskId, workspace.directory, executionOf(state, checkTaskId))).status !==
449
+ "passed")
288
450
  throw new Error(`Acceptance is not passed/current for ${checkTaskId}; use team verify and inspect reports`);
289
451
  }
290
452
  if (!manifest.plan.checks.length)
291
453
  write("No configured acceptance checks: this is an explicit human-reviewed, unverified source application.\n");
292
- const result = await applyTeamPatch({ directory, workspaces, patchId: patch.id, confirmDigest: command.confirm });
454
+ const result = await applyTeamPatch({
455
+ directory,
456
+ workspaces,
457
+ patchId: patch.id,
458
+ confirmDigest: command.confirm,
459
+ });
293
460
  write(`${JSON.stringify(result, null, 2)}\n`);
294
461
  return result.status === "applied" ? 0 : 1;
295
462
  }
@@ -305,14 +472,16 @@ export async function runTeamV2Command(command, dependencies) {
305
472
  controller.abort("Team verification cancelled");
306
473
  }
307
474
  catch (error) {
308
- if (!isMissing(error)) {
475
+ if (!hasErrorCode(error, "ENOENT")) {
309
476
  controller.abort("Cannot establish cancellation state");
310
477
  throw error;
311
478
  }
312
479
  }
313
480
  };
314
481
  await observeCancellation();
315
- timer = setInterval(() => { void observeCancellation().catch(() => controller.abort("Cancellation monitoring failed")); }, 300);
482
+ timer = setInterval(() => {
483
+ trackBackground(observeCancellation());
484
+ }, 300);
316
485
  const state = runtime.snapshot();
317
486
  for (const check of manifest.plan.checks) {
318
487
  if (signal.aborted) {
@@ -324,7 +493,11 @@ export async function runTeamV2Command(command, dependencies) {
324
493
  continue;
325
494
  }
326
495
  const workspace = await workspaces.prepare(check.taskId);
327
- const result = await verification.runCheck(`host-${randomUUID()}`, check, workspace.directory, { allowCommands: manifest.allowChecks, signal, execution: executionOf(state, check.taskId) });
496
+ const result = await verification.runCheck(`host-${randomUUID()}`, check, workspace.directory, {
497
+ allowCommands: manifest.allowChecks,
498
+ signal,
499
+ execution: executionOf(state, check.taskId),
500
+ });
328
501
  write(`Check ${check.id}: ${result.status}${result.detail ? ` (${result.detail})` : ""}\n`);
329
502
  }
330
503
  const acceptance = await summarizeAcceptance(directory, state, manifest, workspaces, verification);
@@ -338,7 +511,7 @@ export async function runTeamV2Command(command, dependencies) {
338
511
  cancel();
339
512
  }
340
513
  catch (error) {
341
- if (!isMissing(error)) {
514
+ if (!hasErrorCode(error, "ENOENT")) {
342
515
  cancel();
343
516
  throw error;
344
517
  }
@@ -348,13 +521,21 @@ export async function runTeamV2Command(command, dependencies) {
348
521
  await checkCancellation();
349
522
  if (dependencies.signal?.aborted)
350
523
  cancel();
351
- timer = setInterval(() => { void checkCancellation().catch(cancel); }, 300);
524
+ timer = setInterval(() => {
525
+ trackBackground(checkCancellation());
526
+ }, 300);
352
527
  await cancelling;
353
- if ((await ledger.totals()).blocked || (await verification.snapshot()).checks.some((check) => check.status === "unknown")) {
528
+ if ((await ledger.totals()).blocked ||
529
+ (await verification.snapshot()).checks.some((check) => check.status === "unknown")) {
354
530
  write("Unknown usage/check effects or exceeded budget block execution. No new Run started; inspect and reconcile explicitly.\n");
355
531
  return 1;
356
532
  }
357
- const result = await runtime.wait();
533
+ const result = await Promise.race([
534
+ runtime.wait(),
535
+ backgroundFailed.then((error) => {
536
+ throw error;
537
+ }),
538
+ ]);
358
539
  await cancelling;
359
540
  const final = result.tasks.find((task) => task.id === manifest.plan.resultTaskId);
360
541
  if (final?.output?.text)
@@ -376,11 +557,26 @@ export async function runTeamV2Command(command, dependencies) {
376
557
  clearInterval(timer);
377
558
  dependencies.signal?.removeEventListener("abort", cancel);
378
559
  try {
379
- await runtime?.close();
380
- await relay;
560
+ const results = await Promise.allSettled([...(runtime ? [runtime.close()] : []), ...(relay ? [relay] : [])]);
561
+ while (backgroundTasks.size)
562
+ await Promise.all(backgroundTasks);
563
+ const failures = [
564
+ ...new Set([
565
+ ...backgroundErrors,
566
+ ...results.flatMap((result) => (result.status === "rejected" ? [result.reason] : [])),
567
+ ]),
568
+ ];
569
+ if (failures.length)
570
+ throw new AggregateError(failures, "Team background operations failed");
381
571
  }
382
572
  finally {
383
- await Promise.all([verification?.close(), workspaces?.close(), artifacts?.close(), ledger.close()]);
573
+ await Promise.all([
574
+ verification?.close(),
575
+ workspaces?.close(),
576
+ artifacts?.close(),
577
+ ledger.close(),
578
+ executionEnvironments.close(),
579
+ ]);
384
580
  }
385
581
  }
386
582
  }
@@ -403,14 +599,33 @@ async function summarizeAcceptance(directory, state, manifest, workspaces, verif
403
599
  }
404
600
  const required = [...new Set(manifest.plan.checks.map((check) => check.taskId))];
405
601
  const failed = Object.values(tasks).some((task) => task.status === "failed");
406
- const status = failed ? "failed" : required.length && state.tasks.every((task) => task.status === "completed") && required.every((id) => tasks[id]?.status === "passed") ? "passed" : "unverified";
407
- const result = { format: 1, revision: state.revision, status, tasks, note: "Scoped configured checks only, not proof of every natural-language claim. Verify rechecks exact workspace fingerprints." };
602
+ const status = failed
603
+ ? "failed"
604
+ : required.length &&
605
+ state.tasks.every((task) => task.status === "completed") &&
606
+ required.every((id) => tasks[id]?.status === "passed")
607
+ ? "passed"
608
+ : "unverified";
609
+ const result = {
610
+ format: 1,
611
+ revision: state.revision,
612
+ status,
613
+ tasks,
614
+ note: "Scoped configured checks only, not proof of every natural-language claim. Verify rechecks exact workspace fingerprints.",
615
+ };
408
616
  await writeJson(join(directory, "acceptance.json"), result);
409
617
  return result;
410
618
  }
411
619
  function modelFingerprint(selection) {
412
- return teamReviewDigest({ profile: selection.profile, provider: selection.provider, adapter: selection.adapter, model: selection.model,
413
- options: selection.options, baseURL: selection.providerConfig.baseURL, limits: selection.limits });
620
+ return teamReviewDigest({
621
+ profile: selection.profile,
622
+ provider: selection.provider,
623
+ adapter: selection.adapter,
624
+ model: selection.model,
625
+ options: selection.options,
626
+ baseURL: selection.providerConfig.baseURL,
627
+ limits: selection.limits,
628
+ });
414
629
  }
415
630
  async function readManifest(directory, id) {
416
631
  const path = join(directory, "manifest.json");
@@ -423,10 +638,22 @@ async function readManifest(directory, id) {
423
638
  });
424
639
  }
425
640
  function validateManifest(value, id) {
426
- if (!value || value.format !== 1 || value.version !== VERSION || value.id !== id || !isAbsolute(value.workspace) || !isAbsolute(value.configPath) || typeof value.prompt !== "string" || typeof value.model !== "string" || !["coding", "read-only"].includes(value.mode) || typeof value.allowChecks !== "boolean")
641
+ if (!value ||
642
+ value.format !== 1 ||
643
+ value.version !== VERSION ||
644
+ value.id !== id ||
645
+ !isAbsolute(value.workspace) ||
646
+ !isAbsolute(value.configPath) ||
647
+ typeof value.prompt !== "string" ||
648
+ typeof value.model !== "string" ||
649
+ !["coding", "read-only"].includes(value.mode) ||
650
+ typeof value.allowChecks !== "boolean")
427
651
  throw new Error("Invalid v2 team manifest");
428
652
  parseTeamPlan(value.plan, { mode: value.mode });
429
- if (![value.maxModelCalls, value.maxTotalTokens, value.maxConcurrent].every((n) => Number.isSafeInteger(n) && n > 0) || value.maxModelCalls > 10_000 || value.maxConcurrent > 8 || value.maxTotalTokens < RESERVATION)
653
+ if (![value.maxModelCalls, value.maxTotalTokens, value.maxConcurrent].every((n) => Number.isSafeInteger(n) && n > 0) ||
654
+ value.maxModelCalls > 10_000 ||
655
+ value.maxConcurrent > 8 ||
656
+ value.maxTotalTokens < RESERVATION)
430
657
  throw new Error("Invalid team limits; token budget must hold at least 32768 tokens");
431
658
  if (!value.roleModels || Object.keys(value.roleModels).length !== Object.keys(value.plan.roles).length)
432
659
  throw new Error("Invalid role model bindings");
@@ -438,27 +665,30 @@ function validateManifest(value, id) {
438
665
  }
439
666
  }
440
667
  async function writeJson(path, value, exclusive = false) {
668
+ const contents = `${JSON.stringify(value, null, 2)}\n`;
441
669
  await withFileAccess(path, "exclusive", async () => {
442
- const target = exclusive ? path : `${path}.${randomUUID()}.tmp`;
443
- const file = await open(target, "wx", 0o600);
670
+ if (!exclusive)
671
+ return writeFileAtomic(path, contents, { mode: 0o600 });
672
+ const file = await open(path, "wx", 0o600);
444
673
  try {
445
- await file.writeFile(`${JSON.stringify(value, null, 2)}\n`);
674
+ await file.writeFile(contents);
446
675
  await file.sync();
447
676
  }
448
677
  finally {
449
678
  await file.close();
450
679
  }
451
- if (!exclusive)
452
- await rename(target, path);
453
680
  });
454
681
  }
455
- function inside(root, path) { const child = relative(root, path); return child === "" || (!isAbsolute(child) && child !== ".." && !child.startsWith(`..${sep}`)); }
682
+ function inside(root, path) {
683
+ const child = relative(root, path);
684
+ return child === "" || (!isAbsolute(child) && child !== ".." && !child.startsWith(`..${sep}`));
685
+ }
456
686
  async function canonicalPotentialPath(path) {
457
687
  try {
458
688
  return await realpath(path);
459
689
  }
460
690
  catch (error) {
461
- if (!isMissing(error))
691
+ if (!hasErrorCode(error, "ENOENT"))
462
692
  throw error;
463
693
  const parent = dirname(path);
464
694
  if (parent === path)
@@ -466,6 +696,7 @@ async function canonicalPotentialPath(path) {
466
696
  return join(await canonicalPotentialPath(parent), relative(parent, path));
467
697
  }
468
698
  }
469
- function safeTerminal(text) { return text.replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/gu, ""); }
470
- function isMissing(error) { return !!error && typeof error === "object" && "code" in error && error.code === "ENOENT"; }
699
+ function safeTerminal(text) {
700
+ return text.replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/gu, "");
701
+ }
471
702
  //# sourceMappingURL=team-v2.js.map