@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
@@ -2,58 +2,49 @@ import { realpath, stat } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
4
4
  import { pathToFileURL } from "node:url";
5
- import { loadMayConfig, updateDefaultMayModel, } from "@sortedyuan/config";
6
- import { resolveRunBudget } from "@sortedyuan/core";
5
+ import { loadMayConfig, updateDefaultMayModel, } from "@sortedyuan/may/config";
6
+ import { omitUndefined, resolveRunBudget } from "@sortedyuan/may/core";
7
7
  import { createMcpModelSampler, validateMcpServerOptions, } from "@sortedyuan/mcp";
8
- import { mcpHostService, mcpService } from "@sortedyuan/plugin-mcp";
9
- import { createSharedObservabilityPlugin, observabilityHostService, observabilityService } from "@sortedyuan/plugin-observability";
10
- import { services } from "@sortedyuan/plugin-services";
8
+ import { mcpHostService, mcpService } from "@sortedyuan/mcp/plugin";
9
+ import { createSharedObservabilityPlugin, observabilityHostService, observabilityService, } from "@sortedyuan/observability/plugin";
10
+ import { services } from "@sortedyuan/may/services";
11
11
  import { createMaybeCodeResourcePlugins, createMaybeCodeSharedPlugins } from "./plugins/resources.js";
12
12
  import { createModelCapabilityResolver, createBuiltinProviderAdapterRegistry, withModelRetry, } from "@sortedyuan/providers";
13
- import { FileSessionStore } from "@sortedyuan/session/file-store";
14
- import { FilePermissionRuleStore } from "@sortedyuan/permissions/file-store";
13
+ import { FileSessionStore } from "@sortedyuan/may/session/file-store";
14
+ import { FilePermissionRuleStore } from "@sortedyuan/may/permissions/file-store";
15
15
  import { userInfo } from "node:os";
16
- import { FileSessionCatalog } from "@sortedyuan/session/catalog";
16
+ import { FileSessionCatalog } from "@sortedyuan/may/session/catalog";
17
17
  import { MaybeCodeConfigError } from "./errors.js";
18
18
  import { createMaybeCodeModel, selectMaybeCodeModel, } from "./model.js";
19
- import { MAYBECODE_APPLICATION_ID, resolveMaybeCodeInstructionsDirectory, } from "./instructions.js";
19
+ import { resolveMaybeCodeInstructionsDirectory } from "./instructions.js";
20
+ import { readMaybeCodeSettings } from "./settings.js";
20
21
  import { MaybeCodeWorkspace } from "./workspace.js";
21
- import { PluginHost, loadPluginModules, parsePluginSelections } from "@sortedyuan/plugin";
22
+ import { PluginHost, loadPluginModules } from "@sortedyuan/may/plugin";
22
23
  import { resolveMaybeCodeSkillDirectories } from "./skills.js";
23
24
  import { parsePermissionMode } from "./policy.js";
24
- import { resolveSubagentConfiguration } from "./subagents.js";
25
+ import { resolveSubagentConfiguration, } from "@sortedyuan/coordination/delegation/configuration";
25
26
  export function getDefaultMaybeCodeDataDirectory() {
26
27
  return join(homedir(), ".may", "maybecode");
27
28
  }
28
- export function resolveMaybeCodeGit(config) {
29
- const value = config.apps?.maybecode?.git;
30
- if (value === undefined)
31
- return {};
32
- if (value === false)
33
- return false;
34
- if (!value || typeof value !== "object" || Array.isArray(value))
35
- throw new MaybeCodeConfigError("apps.maybecode.git must be false or an object");
36
- const fields = value;
37
- const allowed = ["autoCommit", "readOnly", "dataRoot", "worktreesRoot", "excludedPaths"];
38
- for (const name of Object.keys(fields))
39
- if (!allowed.includes(name))
40
- throw new MaybeCodeConfigError(`Unknown apps.maybecode.git field: ${name}`);
41
- for (const name of ["autoCommit", "readOnly"])
42
- if (fields[name] !== undefined && typeof fields[name] !== "boolean")
43
- throw new MaybeCodeConfigError(`apps.maybecode.git.${name} must be boolean`);
44
- for (const name of ["dataRoot", "worktreesRoot"])
45
- if (fields[name] !== undefined && (typeof fields[name] !== "string" || !fields[name].trim()))
46
- throw new MaybeCodeConfigError(`apps.maybecode.git.${name} must be a non-empty path`);
47
- if (fields.excludedPaths !== undefined && (!Array.isArray(fields.excludedPaths) || fields.excludedPaths.some(path => typeof path !== "string" || !path.trim())))
48
- throw new MaybeCodeConfigError("apps.maybecode.git.excludedPaths must contain non-empty paths");
29
+ export function resolveMaybeCodeRecording(config) {
30
+ const settings = readMaybeCodeSettings(config);
49
31
  return {
50
- ...(fields.autoCommit === undefined ? {} : { autoCommit: fields.autoCommit }),
51
- ...(fields.readOnly === undefined ? {} : { readOnly: fields.readOnly }),
52
- ...(fields.dataRoot === undefined ? {} : { dataRoot: resolveGitConfigurationPath(config.path, fields.dataRoot) }),
53
- ...(fields.worktreesRoot === undefined ? {} : { worktreesRoot: resolveGitConfigurationPath(config.path, fields.worktreesRoot) }),
54
- ...(fields.excludedPaths === undefined ? {} : { excludedPaths: fields.excludedPaths }),
32
+ requestRecording: settings.requestRecording ?? "required",
33
+ providerBodyRecording: settings.providerBodyRecording ?? false,
55
34
  };
56
35
  }
36
+ export function resolveMaybeCodeGit(config) {
37
+ const git = readMaybeCodeSettings(config).git;
38
+ if (git === false)
39
+ return false;
40
+ return omitUndefined({
41
+ autoCommit: git?.autoCommit,
42
+ readOnly: git?.readOnly,
43
+ dataRoot: git?.dataRoot === undefined ? undefined : resolveGitConfigurationPath(config.path, git.dataRoot),
44
+ worktreesRoot: git?.worktreesRoot === undefined ? undefined : resolveGitConfigurationPath(config.path, git.worktreesRoot),
45
+ excludedPaths: git?.excludedPaths === undefined ? undefined : [...git.excludedPaths],
46
+ });
47
+ }
57
48
  function resolveGitConfigurationPath(configPath, path) {
58
49
  if (path === "~")
59
50
  return homedir();
@@ -61,35 +52,28 @@ function resolveGitConfigurationPath(configPath, path) {
61
52
  return resolve(homedir(), path.slice(2));
62
53
  return resolve(dirname(configPath), path);
63
54
  }
55
+ /** @experimental */
64
56
  export async function openConfiguredMaybeCode(options = {}, dependencies = {}) {
65
57
  const workspace = await resolveWorkspace(options.workspace ?? process.cwd());
66
58
  const loadConfig = dependencies.loadConfig ?? loadMayConfig;
67
- const config = await loadConfig(options.configPath === undefined ? {} : { path: options.configPath });
59
+ const config = await loadConfig(omitUndefined({ path: options.configPath }));
60
+ const settings = readMaybeCodeSettings(config);
68
61
  const retry = options.retry ?? resolveMaybeCodeRetry(config);
69
- const plugins = options.plugins ?? await loadPluginModules(parsePluginSelections(config.apps?.maybecode?.plugins), config.path);
70
- const provided = (service) => plugins.some(plugin => plugin.provides?.some(candidate => candidate.id === service.id && candidate.scope === service.scope));
62
+ const plugins = options.plugins ?? (await loadPluginModules(settings.plugins ?? [], config.path));
63
+ const provided = (service) => plugins.some((plugin) => plugin.provides?.some((candidate) => candidate.id === service.id && candidate.scope === service.scope));
71
64
  const pluginModel = provided(services.model);
72
- const configuredPermissionMode = config.apps?.maybecode?.permissionMode;
73
- const configuredDelegationNotifications = options.delegationNotifications === undefined
74
- ? config.apps?.maybecode?.delegationNotifications : options.delegationNotifications;
75
- const delegationNotifications = configuredDelegationNotifications === undefined ? false : configuredDelegationNotifications;
76
- if (typeof delegationNotifications !== "boolean")
77
- throw new MaybeCodeConfigError("apps.maybecode.delegationNotifications must be boolean");
65
+ const { requestRecording, providerBodyRecording } = resolveMaybeCodeRecording(config);
66
+ const delegationNotifications = options.delegationNotifications ?? settings.delegationNotifications ?? false;
78
67
  const git = options.git ?? resolveMaybeCodeGit(config);
79
68
  const permissionMode = options.permissionMode === undefined
80
- ? configuredPermissionMode === undefined ? "default" : parsePermissionMode(configuredPermissionMode)
69
+ ? (settings.permissionMode ?? "default")
81
70
  : parsePermissionMode(options.permissionMode);
82
- const persistentRules = options.persistentRules ?? config.apps?.maybecode?.persistentRules ?? false;
83
- if (typeof persistentRules !== "boolean")
84
- throw new MaybeCodeConfigError("apps.maybecode.persistentRules must be boolean");
71
+ const persistentRules = options.persistentRules ?? settings.persistentRules ?? false;
85
72
  const skillDirectories = options.skillDirectories ?? resolveMaybeCodeSkillDirectories(config, workspace);
86
- const runBudget = resolveRunBudget(options.runBudget ?? config.apps?.maybecode?.runBudget);
87
- const capabilityResolver = dependencies.capabilityResolver ??
88
- createModelCapabilityResolver();
73
+ const runBudget = resolveRunBudget(options.runBudget ?? settings.runBudget);
74
+ const capabilityResolver = dependencies.capabilityResolver ?? createModelCapabilityResolver();
89
75
  const adapterRegistry = dependencies.adapterRegistry ?? createBuiltinProviderAdapterRegistry({ resolver: capabilityResolver });
90
- const selectionFor = (profile) => selectMaybeCodeModel(config, {
91
- ...(profile === undefined ? {} : { model: profile }),
92
- });
76
+ const selectionFor = (profile) => selectMaybeCodeModel(config, omitUndefined({ model: profile }));
93
77
  const configureModel = (profile, runtimeOptions = {}) => {
94
78
  const selected = selectionFor(profile);
95
79
  const selection = {
@@ -101,7 +85,7 @@ export async function openConfiguredMaybeCode(options = {}, dependencies = {}) {
101
85
  : dependencies.createModel(selection);
102
86
  const model = retry === false ? baseModel : withModelRetry(baseModel, retry);
103
87
  const contextBudget = options.contextBudget ?? createContextBudget(model, selection);
104
- return {
88
+ return omitUndefined({
105
89
  model,
106
90
  modelInfo: {
107
91
  profile: selection.profile,
@@ -109,41 +93,37 @@ export async function openConfiguredMaybeCode(options = {}, dependencies = {}) {
109
93
  adapter: selection.adapter,
110
94
  model: selection.model,
111
95
  },
112
- ...(contextBudget === undefined ? {} : { contextBudget }),
113
- };
96
+ contextBudget,
97
+ });
114
98
  };
115
99
  const initialModel = pluginModel ? undefined : configureModel(options.model);
116
- const modelProfiles = pluginModel ? [] : Object.entries(config.models).map(([name, profile]) => {
117
- const provider = config.providers[profile.provider];
118
- const reasoningEffort = {
119
- ...(provider.options ?? {}),
120
- ...(profile.options ?? {}),
121
- }.reasoningEffort;
122
- return {
123
- name,
124
- provider: profile.provider,
125
- adapter: profile.adapter ?? provider.adapter,
126
- model: profile.model,
127
- isDefault: config.defaultModel === name,
128
- ...(typeof reasoningEffort === "string" ? { reasoningEffort } : {}),
129
- };
130
- });
131
- const instructionsDirectory = options.instructions === undefined
132
- ? resolveMaybeCodeInstructionsDirectory(config)
133
- : undefined;
134
- const autoCompactionMode = options.autoCompactionMode ??
135
- (options.providerNativeAutoCompaction === undefined
136
- ? resolveMaybeCodeAutoCompactionMode(config)
137
- : options.providerNativeAutoCompaction ? "provider-native" : "prune-summary");
100
+ const modelProfiles = pluginModel
101
+ ? []
102
+ : Object.entries(config.models).map(([name, profile]) => {
103
+ const provider = config.providers[profile.provider];
104
+ const reasoningEffort = {
105
+ ...(provider.options ?? {}),
106
+ ...(profile.options ?? {}),
107
+ }.reasoningEffort;
108
+ return {
109
+ name,
110
+ provider: profile.provider,
111
+ adapter: profile.adapter ?? provider.adapter,
112
+ model: profile.model,
113
+ isDefault: config.defaultModel === name,
114
+ ...(typeof reasoningEffort === "string" ? { reasoningEffort } : {}),
115
+ };
116
+ });
117
+ const instructionsDirectory = options.instructions === undefined ? resolveMaybeCodeInstructionsDirectory(config) : undefined;
118
+ const autoCompactionMode = options.autoCompactionMode ?? resolveMaybeCodeAutoCompactionMode(config);
138
119
  const dataDirectory = resolve(options.dataDirectory ?? getDefaultMaybeCodeDataDirectory());
139
- const observabilityOptions = provided(observabilityService) || provided(services.tracer) ? false : options.observability ??
140
- resolveMaybeCodeObservability(config);
141
- const subagents = resolveMaybeCodeSubagents(options.subagents, config);
120
+ const observabilityOptions = provided(observabilityService) || provided(services.tracer)
121
+ ? false
122
+ : (options.observability ?? resolveMaybeCodeObservability(config));
123
+ const subagents = resolveMaybeCodeSubagents(options.subagents, settings);
142
124
  const subagentCreateModel = (role) => role.model === undefined
143
125
  ? initialModel
144
- : configureModel(role.model, role.reasoningEffort === undefined
145
- ? {}
146
- : { reasoningEffort: role.reasoningEffort });
126
+ : configureModel(role.model, role.reasoningEffort === undefined ? {} : { reasoningEffort: role.reasoningEffort });
147
127
  let mcp;
148
128
  let resourceHost;
149
129
  const workspaceResourceHosts = new Map();
@@ -171,43 +151,62 @@ export async function openConfiguredMaybeCode(options = {}, dependencies = {}) {
171
151
  }
172
152
  };
173
153
  const mcpForWorkspace = (nextWorkspace) => {
174
- const next = provided(mcpService) ? false : options.mcp === undefined
175
- ? resolveMaybeCodeMcp(config, nextWorkspace)
176
- : options.mcp === false ? false : { ...options.mcp, servers: options.mcp.servers.map(server => {
177
- if (server.transport === "streamable-http")
178
- return server;
179
- const source = resolve(workspace, server.cwd ?? ".");
180
- const path = relative(workspace, source);
181
- const inside = path === "" || path !== ".." && !path.startsWith("..\\") && !path.startsWith("../") && !isAbsolute(path);
182
- return { ...server, cwd: inside ? resolve(nextWorkspace, path) : source };
183
- }) };
154
+ const next = provided(mcpService)
155
+ ? false
156
+ : options.mcp === undefined
157
+ ? resolveMaybeCodeMcp(config, nextWorkspace)
158
+ : options.mcp === false
159
+ ? false
160
+ : {
161
+ ...options.mcp,
162
+ servers: options.mcp.servers.map((server) => {
163
+ if (server.transport === "streamable-http")
164
+ return server;
165
+ const source = resolve(workspace, server.cwd ?? ".");
166
+ const path = relative(workspace, source);
167
+ const inside = path === "" ||
168
+ (path !== ".." && !path.startsWith("..\\") && !path.startsWith("../") && !isAbsolute(path));
169
+ return { ...server, cwd: inside ? resolve(nextWorkspace, path) : source };
170
+ }),
171
+ };
184
172
  if (next === false)
185
173
  return false;
186
- const tracer = resourceHost?.provides(observabilityHostService) ? resourceHost.get(observabilityHostService).tracer : undefined;
174
+ const tracer = resourceHost?.provides(observabilityHostService)
175
+ ? resourceHost.get(observabilityHostService).tracer
176
+ : undefined;
187
177
  return {
188
178
  servers: next.servers,
189
- ...(next.taskJournal === undefined ? {} : { taskJournal: next.taskJournal }),
190
- ...(next.oauth === undefined ? {} : { oauth: next.oauth }),
191
- ...(tracer === undefined ? {} : { tracer }),
192
- ...(dependencies.openMcp === undefined ? {} : { open: dependencies.openMcp }),
179
+ ...omitUndefined({ taskJournal: next.taskJournal, oauth: next.oauth, tracer, open: dependencies.openMcp }),
193
180
  enableInteractions: options.mcpInteractions === true,
194
181
  hostServices: {
195
- roots: async (context) => { checkHostOwner(context); return [{ uri: pathToFileURL(application.workspace).href, name: "MaybeCode workspace" }]; },
196
- ...(pluginModel ? {} : { sampling: createMcpModelSampler((maxTokens, context) => {
197
- checkHostOwner(context);
198
- const selected = selectionFor(application.modelInfo?.profile);
199
- const selection = { ...selected, options: { ...selected.options, maxTokens, maxOutputTokens: maxTokens } };
200
- // sampling 使用独立 provider 实例和本次调用的模型预算。
201
- const model = dependencies.createModel === undefined ? createMaybeCodeModel(selection, dependencies.adapterRegistry) : dependencies.createModel(selection);
202
- return { model, name: selected.model };
203
- }) }),
182
+ roots: async (context) => {
183
+ checkHostOwner(context);
184
+ return [{ uri: pathToFileURL(application.workspace).href, name: "MaybeCode workspace" }];
185
+ },
186
+ ...(pluginModel
187
+ ? {}
188
+ : {
189
+ sampling: createMcpModelSampler((maxTokens, context) => {
190
+ checkHostOwner(context);
191
+ const selected = selectionFor(application.application.modelInfo?.profile);
192
+ const selection = {
193
+ ...selected,
194
+ options: { ...selected.options, maxTokens, maxOutputTokens: maxTokens },
195
+ };
196
+ // sampling 使用独立 provider 实例和本次调用的模型预算。
197
+ const model = dependencies.createModel === undefined
198
+ ? createMaybeCodeModel(selection, dependencies.adapterRegistry)
199
+ : dependencies.createModel(selection);
200
+ return { model, name: selected.model };
201
+ }),
202
+ }),
204
203
  },
205
204
  traceAttributes: { "may.agent.name": "maybecode" },
206
205
  };
207
206
  };
208
207
  const closeResources = async () => {
209
- const results = await Promise.allSettled([...workspaceResourceHosts.values()].map(host => host.close()));
210
- const failures = results.flatMap(result => result.status === "rejected" ? [result.reason] : []);
208
+ const results = await Promise.allSettled([...workspaceResourceHosts.values()].map((host) => host.close()));
209
+ const failures = results.flatMap((result) => (result.status === "rejected" ? [result.reason] : []));
211
210
  try {
212
211
  await resourceHost?.close();
213
212
  }
@@ -226,80 +225,82 @@ export async function openConfiguredMaybeCode(options = {}, dependencies = {}) {
226
225
  throw new AggregateError(failures, "MaybeCode configured resources failed to close");
227
226
  };
228
227
  try {
229
- const resourcePlugins = createMaybeCodeResourcePlugins({ dataDirectory, observability: observabilityOptions, mcp: mcpForWorkspace(workspace) });
228
+ const resourcePlugins = createMaybeCodeResourcePlugins({
229
+ dataDirectory,
230
+ observability: observabilityOptions,
231
+ mcp: mcpForWorkspace(workspace),
232
+ });
230
233
  resourceHost = await PluginHost.create({ plugins: resourcePlugins });
231
234
  if (resourceHost.provides(mcpHostService))
232
235
  mcp = resourceHost.get(mcpHostService);
233
- const observability = resourceHost.provides(observabilityHostService) ? resourceHost.get(observabilityHostService) : undefined;
236
+ const observability = resourceHost.provides(observabilityHostService)
237
+ ? resourceHost.get(observabilityHostService)
238
+ : undefined;
234
239
  const applicationPlugins = createMaybeCodeSharedPlugins(resourceHost, plugins);
235
240
  workspacePlugins.set(workspace, applicationPlugins);
236
241
  application = await MaybeCodeWorkspace.open({
237
242
  git,
238
- ...await permissionsFor(workspace),
243
+ ...omitUndefined({ execution: settings.execution, fetch: settings.fetch }),
244
+ ...(await permissionsFor(workspace)),
239
245
  configureWorkspace: async (nextWorkspace) => {
240
246
  const directories = options.skillDirectories ?? resolveMaybeCodeSkillDirectories(config, nextWorkspace);
241
247
  let configuredPlugins = workspacePlugins.get(nextWorkspace);
242
248
  if (configuredPlugins === undefined) {
243
- const nextHost = await PluginHost.create({ plugins: createMaybeCodeResourcePlugins({
244
- dataDirectory, observability: false, mcp: mcpForWorkspace(nextWorkspace),
245
- }) });
249
+ const nextHost = await PluginHost.create({
250
+ plugins: createMaybeCodeResourcePlugins({
251
+ dataDirectory,
252
+ observability: false,
253
+ mcp: mcpForWorkspace(nextWorkspace),
254
+ }),
255
+ });
246
256
  workspaceResourceHosts.set(nextWorkspace, nextHost);
247
257
  configuredPlugins = createMaybeCodeSharedPlugins(nextHost, [
248
- ...(observability === undefined ? [] : [createSharedObservabilityPlugin(observability)]), ...plugins,
258
+ ...(observability === undefined ? [] : [createSharedObservabilityPlugin(observability)]),
259
+ ...plugins,
249
260
  ]);
250
261
  workspacePlugins.set(nextWorkspace, configuredPlugins);
251
262
  }
252
- return { plugins: configuredPlugins, ...await permissionsFor(nextWorkspace), ...(directories === false ? { skills: false } : { skillDirectories: directories }) };
263
+ return {
264
+ plugins: configuredPlugins,
265
+ ...(await permissionsFor(nextWorkspace)),
266
+ ...(directories === false ? { skills: false } : { skillDirectories: directories }),
267
+ };
253
268
  },
254
269
  permissionMode,
270
+ requestRecording,
271
+ providerBodyRecording,
255
272
  delegationNotifications,
256
273
  workspace,
257
274
  ...(initialModel === undefined ? {} : { model: initialModel.model, modelInfo: initialModel.modelInfo }),
258
275
  modelProfiles,
259
- ...(pluginModel ? {} : {
260
- createModelConfiguration: (profile, runtimeOptions) => configureModel(profile, runtimeOptions),
261
- resolveModelCapabilities: async (profile, options) => capabilityResolver.resolve(selectionFor(profile), options),
262
- }),
276
+ ...(pluginModel
277
+ ? {}
278
+ : {
279
+ createModelConfiguration: (profile, runtimeOptions) => configureModel(profile, runtimeOptions),
280
+ resolveModelCapabilities: async (profile, options) => capabilityResolver.resolve(selectionFor(profile), options),
281
+ }),
263
282
  ...resolveDefaultModelPersistence(config, dependencies),
264
283
  store: new FileSessionStore(join(dataDirectory, "sessions")),
265
284
  plugins: applicationPlugins,
266
285
  catalog: new FileSessionCatalog(join(dataDirectory, "catalog.json")),
267
- ...(mcp === undefined
268
- ? {}
269
- : { mcp }),
270
286
  closeOwnedResources: closeResources,
271
- ...(options.sessionId === undefined
272
- ? {}
273
- : { sessionId: options.sessionId }),
274
- ...(options.autoResume === undefined
275
- ? {}
276
- : { autoResume: options.autoResume }),
277
- ...(options.contextFactory === undefined
278
- ? {}
279
- : { contextFactory: options.contextFactory }),
280
- ...((options.contextBudget ?? initialModel?.contextBudget) === undefined
281
- ? {}
282
- : { contextBudget: options.contextBudget ?? initialModel.contextBudget }),
283
- ...(options.compactionStrategy === undefined
284
- ? {}
285
- : { compactionStrategy: options.compactionStrategy }),
286
- ...(options.autoCompactionStrategies === undefined
287
- ? {}
288
- : { autoCompactionStrategies: options.autoCompactionStrategies }),
289
287
  autoCompactionMode,
290
- ...(options.contextSummarizer === undefined
291
- ? {}
292
- : { contextSummarizer: options.contextSummarizer }),
293
- ...(options.instructions === undefined
294
- ? {}
295
- : { instructions: options.instructions }),
296
- ...(instructionsDirectory === undefined
297
- ? {}
298
- : { instructionsDirectory }),
299
- ...(options.maxSteps === undefined ? {} : { maxSteps: options.maxSteps }),
300
288
  runBudget,
301
- ...(options.skills === undefined ? {} : { skills: options.skills }),
302
- ...(options.goals === undefined ? {} : { goals: options.goals }),
289
+ ...omitUndefined({
290
+ mcp,
291
+ sessionId: options.sessionId,
292
+ autoResume: options.autoResume,
293
+ contextFactory: options.contextFactory,
294
+ contextBudget: options.contextBudget ?? initialModel?.contextBudget,
295
+ compactionStrategy: options.compactionStrategy,
296
+ autoCompactionStrategies: options.autoCompactionStrategies,
297
+ contextSummarizer: options.contextSummarizer,
298
+ instructions: options.instructions,
299
+ instructionsDirectory,
300
+ maxSteps: options.maxSteps,
301
+ skills: options.skills,
302
+ goals: options.goals,
303
+ }),
303
304
  ...(subagents === false
304
305
  ? { subagents: false }
305
306
  : {
@@ -312,7 +313,9 @@ export async function openConfiguredMaybeCode(options = {}, dependencies = {}) {
312
313
  },
313
314
  }),
314
315
  ...(skillDirectories === false
315
- ? (options.skills === undefined ? { skills: false } : {})
316
+ ? options.skills === undefined
317
+ ? { skills: false }
318
+ : {}
316
319
  : { skillDirectories }),
317
320
  });
318
321
  return application;
@@ -328,164 +331,77 @@ export async function openConfiguredMaybeCode(options = {}, dependencies = {}) {
328
331
  }
329
332
  }
330
333
  export function resolveMaybeCodeMcp(config, workspace, environment = process.env) {
331
- const value = config.apps?.[MAYBECODE_APPLICATION_ID]?.mcpServers;
332
- if (value === undefined || value === false)
334
+ const servers = readMaybeCodeSettings(config).mcpServers;
335
+ if (servers === undefined || servers === false)
333
336
  return false;
334
- const servers = objectValue(value, "apps.maybecode.mcpServers");
335
337
  const resolved = [];
336
- for (const [id, raw] of Object.entries(servers)) {
337
- if (!/^[A-Za-z0-9_-]+$/u.test(id)) {
338
- throw new MaybeCodeConfigError(`apps.maybecode.mcpServers server id "${id}" may contain only letters, digits, underscores, and hyphens`);
339
- }
340
- const field = `apps.maybecode.mcpServers.${id}`;
341
- const server = objectValue(raw, field);
342
- rejectUnknownOptions(server, [
343
- "enabled",
344
- "required",
345
- "transport",
346
- "protocolMode",
347
- "host",
348
- "tasks",
349
- "url",
350
- "headers",
351
- "auth",
352
- "command",
353
- "args",
354
- "cwd",
355
- "env",
356
- "requestTimeoutMs",
357
- "maxTotalTimeoutMs",
358
- "maxBufferSize",
359
- "stderrMaxBytes",
360
- ], field);
361
- if (server.enabled !== undefined && typeof server.enabled !== "boolean") {
362
- throw new MaybeCodeConfigError(`${field}.enabled must be a boolean`);
363
- }
338
+ for (const [id, server] of Object.entries(servers)) {
364
339
  if (server.enabled === false)
365
340
  continue;
366
- if (server.required !== undefined && typeof server.required !== "boolean") {
367
- throw new MaybeCodeConfigError(`${field}.required must be a boolean`);
368
- }
369
- if (server.transport !== undefined && server.transport !== "stdio" &&
370
- server.transport !== "streamable-http") {
371
- throw new MaybeCodeConfigError(`${field}.transport must be "stdio" or "streamable-http"`);
372
- }
373
- if (server.protocolMode !== undefined && server.protocolMode !== "legacy" &&
374
- server.protocolMode !== "auto") {
375
- throw new MaybeCodeConfigError(`${field}.protocolMode must be "legacy" or "auto"`);
376
- }
377
- const requestTimeoutMs = optionalPositiveInteger(server.requestTimeoutMs, `${field}.requestTimeoutMs`);
378
- const maxTotalTimeoutMs = optionalPositiveInteger(server.maxTotalTimeoutMs, `${field}.maxTotalTimeoutMs`);
379
- const common = {
341
+ const field = `apps.maybecode.mcpServers.${id}`;
342
+ const common = omitUndefined({
380
343
  id,
381
- ...(server.required === undefined ? {} : { required: server.required }),
382
- ...(server.protocolMode === undefined ? {} : { protocolMode: server.protocolMode }),
383
- ...(server.tasks === undefined ? {} : { tasks: server.tasks }),
384
- ...(server.host === undefined ? {} : { host: objectValue(server.host, `${field}.host`) }),
385
- ...(requestTimeoutMs === undefined ? {} : { requestTimeoutMs }),
386
- ...(maxTotalTimeoutMs === undefined ? {} : { maxTotalTimeoutMs }),
387
- };
344
+ required: server.required,
345
+ protocolMode: server.protocolMode,
346
+ tasks: server.tasks,
347
+ host: server.host,
348
+ requestTimeoutMs: server.requestTimeoutMs,
349
+ maxTotalTimeoutMs: server.maxTotalTimeoutMs,
350
+ });
388
351
  if (server.transport === "streamable-http") {
389
- for (const key of ["command", "args", "cwd", "env", "maxBufferSize", "stderrMaxBytes"]) {
390
- if (key in server)
391
- throw new MaybeCodeConfigError(`${field}.${key} is stdio-only`);
392
- }
393
- const headers = resolveMcpEnvironment(server.headers, `${field}.headers`, environment);
394
- const endpoint = {
352
+ const endpoint = omitUndefined({
395
353
  ...common,
396
354
  transport: "streamable-http",
397
- url: nonEmptyString(server.url, `${field}.url`),
398
- ...(headers === undefined ? {} : { headers }),
399
- ...(server.auth === undefined ? {} : { auth: objectValue(server.auth, `${field}.auth`) }),
400
- };
355
+ url: server.url,
356
+ headers: resolveMcpEnvironment(server.headers, `${field}.headers`, environment),
357
+ auth: server.auth,
358
+ });
401
359
  try {
402
360
  validateMcpServerOptions(endpoint);
403
361
  }
404
362
  catch (error) {
405
- throw new MaybeCodeConfigError(error instanceof Error ? error.message : "Invalid MCP endpoint");
363
+ throw new MaybeCodeConfigError(error.message, { cause: error });
406
364
  }
407
365
  resolved.push(endpoint);
408
366
  continue;
409
367
  }
410
- for (const key of ["url", "headers", "auth"]) {
411
- if (key in server)
412
- throw new MaybeCodeConfigError(`${field}.${key} requires streamable-http`);
413
- }
414
- const command = nonEmptyString(server.command, `${field}.command`);
415
- const args = optionalStringArray(server.args, `${field}.args`);
416
- const cwd = server.cwd === undefined
417
- ? workspace
418
- : resolve(workspace, nonEmptyString(server.cwd, `${field}.cwd`));
419
- const env = resolveMcpEnvironment(server.env, `${field}.env`, environment);
420
- const maxBufferSize = optionalPositiveInteger(server.maxBufferSize, `${field}.maxBufferSize`);
421
- const stderrMaxBytes = optionalPositiveInteger(server.stderrMaxBytes, `${field}.stderrMaxBytes`);
422
- resolved.push({
368
+ resolved.push(omitUndefined({
423
369
  ...common,
424
- command,
425
- ...(args === undefined ? {} : { args }),
426
- cwd,
427
- ...(env === undefined ? {} : { env }),
428
- ...(maxBufferSize === undefined ? {} : { maxBufferSize }),
429
- ...(stderrMaxBytes === undefined ? {} : { stderrMaxBytes }),
430
- });
370
+ command: server.command,
371
+ args: server.args,
372
+ cwd: server.cwd === undefined ? workspace : resolve(workspace, server.cwd),
373
+ env: resolveMcpEnvironment(server.env, `${field}.env`, environment),
374
+ maxBufferSize: server.maxBufferSize,
375
+ stderrMaxBytes: server.stderrMaxBytes,
376
+ }));
431
377
  }
432
378
  return { servers: resolved };
433
379
  }
434
380
  export function resolveMaybeCodeObservability(config) {
435
- const value = config.apps?.[MAYBECODE_APPLICATION_ID]?.observability;
436
- if (value === undefined || value === false)
381
+ const observability = readMaybeCodeSettings(config).observability;
382
+ if (observability === undefined || observability === false)
437
383
  return false;
438
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
439
- throw new MaybeCodeConfigError("apps.maybecode.observability must be false or an object");
440
- }
441
- const candidate = value;
442
- rejectUnknownOptions(candidate, [
443
- "enabled",
444
- "exporter",
445
- "file",
446
- "samplingRatio",
447
- "retentionDays",
448
- "batch",
449
- ], "apps.maybecode.observability");
450
- const enabled = candidate.enabled;
451
- if (enabled !== undefined && typeof enabled !== "boolean") {
452
- throw new MaybeCodeConfigError("apps.maybecode.observability.enabled must be a boolean");
453
- }
454
- if (candidate.exporter !== undefined && candidate.exporter !== "file") {
455
- throw new MaybeCodeConfigError('apps.maybecode.observability.exporter must be "file"');
456
- }
457
- const file = candidate.file === undefined
458
- ? undefined
459
- : nonEmptyString(candidate.file, "apps.maybecode.observability.file");
460
- const samplingRatio = optionalRatio(candidate.samplingRatio, "apps.maybecode.observability.samplingRatio");
461
- const retentionDays = optionalPositiveInteger(candidate.retentionDays, "apps.maybecode.observability.retentionDays");
462
- const batch = candidate.batch === undefined
463
- ? {}
464
- : objectValue(candidate.batch, "apps.maybecode.observability.batch");
465
- rejectUnknownOptions(batch, ["maxQueueSize", "maxExportBatchSize", "scheduledDelayMs"], "apps.maybecode.observability.batch");
466
- const maxQueueSize = optionalPositiveInteger(batch.maxQueueSize, "apps.maybecode.observability.batch.maxQueueSize");
467
- const maxExportBatchSize = optionalPositiveInteger(batch.maxExportBatchSize, "apps.maybecode.observability.batch.maxExportBatchSize");
468
- const scheduledDelayMs = optionalNonNegativeNumber(batch.scheduledDelayMs, "apps.maybecode.observability.batch.scheduledDelayMs");
469
- if ((maxExportBatchSize ?? 512) > (maxQueueSize ?? 2_048)) {
384
+ const batch = observability.batch ?? {};
385
+ if ((batch.maxExportBatchSize ?? 512) > (batch.maxQueueSize ?? 2_048)) {
470
386
  throw new MaybeCodeConfigError("apps.maybecode.observability.batch.maxExportBatchSize cannot exceed maxQueueSize");
471
387
  }
472
- if (enabled === false)
388
+ if (observability.enabled === false)
473
389
  return false;
474
- return {
475
- ...(file === undefined ? {} : { file }),
476
- ...(samplingRatio === undefined ? {} : { samplingRatio }),
477
- ...(retentionDays === undefined ? {} : { retentionDays }),
478
- ...(maxQueueSize === undefined ? {} : { maxQueueSize }),
479
- ...(maxExportBatchSize === undefined ? {} : { maxExportBatchSize }),
480
- ...(scheduledDelayMs === undefined ? {} : { scheduledDelayMs }),
481
- };
390
+ return omitUndefined({
391
+ file: observability.file,
392
+ samplingRatio: observability.samplingRatio,
393
+ retentionDays: observability.retentionDays,
394
+ maxQueueSize: batch.maxQueueSize,
395
+ maxExportBatchSize: batch.maxExportBatchSize,
396
+ scheduledDelayMs: batch.scheduledDelayMs,
397
+ });
482
398
  }
483
- function resolveMaybeCodeSubagents(value, config) {
399
+ function resolveMaybeCodeSubagents(value, settings) {
484
400
  if (value === false)
485
401
  return false;
486
402
  if (value?.configuration !== undefined)
487
403
  return value;
488
- const resolved = resolveSubagentConfiguration(config);
404
+ const resolved = resolveSubagentConfiguration(settings.subagents);
489
405
  if (resolved === false)
490
406
  return false;
491
407
  return { ...(value ?? {}), configuration: resolved };
@@ -503,63 +419,24 @@ function resolveDefaultModelPersistence(config, dependencies) {
503
419
  };
504
420
  }
505
421
  export function resolveMaybeCodeAutoCompactionMode(config) {
506
- const value = config.apps?.[MAYBECODE_APPLICATION_ID]?.autoCompaction;
507
- if (value === undefined)
508
- return "prune-summary";
509
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
510
- throw new MaybeCodeConfigError("apps.maybecode.autoCompaction must be an object");
511
- }
512
- const { mode, providerNative } = value;
513
- if (providerNative !== undefined && typeof providerNative !== "boolean") {
514
- throw new MaybeCodeConfigError("apps.maybecode.autoCompaction.providerNative must be a boolean");
515
- }
516
- if (mode === undefined)
517
- return providerNative === true ? "provider-native" : "prune-summary";
518
- if (mode !== "prune-summary" && mode !== "history-reference" && mode !== "provider-native") {
519
- throw new MaybeCodeConfigError("apps.maybecode.autoCompaction.mode must be prune-summary, history-reference, or provider-native");
520
- }
521
- return mode;
522
- }
523
- /** @deprecated Use resolveMaybeCodeAutoCompactionMode instead. */
524
- export function resolveProviderNativeAutoCompaction(config) {
525
- return resolveMaybeCodeAutoCompactionMode(config) === "provider-native";
422
+ return readMaybeCodeSettings(config).autoCompaction?.mode ?? "prune-summary";
526
423
  }
527
424
  export function resolveMaybeCodeRetry(config) {
528
- const value = config.apps?.[MAYBECODE_APPLICATION_ID]?.retry;
529
- if (value === undefined)
530
- return {};
531
- if (value === false)
425
+ const retry = readMaybeCodeSettings(config).retry;
426
+ if (retry === false)
532
427
  return false;
533
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
534
- throw new MaybeCodeConfigError("apps.maybecode.retry must be false or an object");
535
- }
536
- const retry = value;
537
- const maxAttempts = optionalPositiveInteger(retry.maxAttempts, "apps.maybecode.retry.maxAttempts");
538
- const baseDelayMs = optionalNonNegativeNumber(retry.baseDelayMs, "apps.maybecode.retry.baseDelayMs");
539
- const maxDelayMs = optionalNonNegativeNumber(retry.maxDelayMs, "apps.maybecode.retry.maxDelayMs");
540
- const jitterRatio = optionalRatio(retry.jitterRatio, "apps.maybecode.retry.jitterRatio");
541
- if ((baseDelayMs ?? 500) > (maxDelayMs ?? 8_000)) {
428
+ if ((retry?.baseDelayMs ?? 500) > (retry?.maxDelayMs ?? 8_000)) {
542
429
  throw new MaybeCodeConfigError("apps.maybecode.retry.baseDelayMs cannot exceed maxDelayMs");
543
430
  }
544
- return {
545
- ...(maxAttempts === undefined ? {} : { maxAttempts }),
546
- ...(baseDelayMs === undefined ? {} : { baseDelayMs }),
547
- ...(maxDelayMs === undefined ? {} : { maxDelayMs }),
548
- ...(jitterRatio === undefined ? {} : { jitterRatio }),
549
- };
431
+ return { ...retry };
550
432
  }
551
433
  function createContextBudget(model, selection) {
552
- const contextWindowTokens = model.limits?.contextWindowTokens ??
553
- selection.limits?.contextWindowTokens;
554
- const outputReserveTokens = model.limits?.maxOutputTokens ??
555
- selection.limits?.maxOutputTokens;
434
+ const contextWindowTokens = model.limits?.contextWindowTokens ?? selection.limits?.contextWindowTokens;
435
+ const outputReserveTokens = model.limits?.maxOutputTokens ?? selection.limits?.maxOutputTokens;
556
436
  if (contextWindowTokens === undefined && outputReserveTokens === undefined) {
557
437
  return undefined;
558
438
  }
559
- return {
560
- ...(contextWindowTokens === undefined ? {} : { contextWindowTokens }),
561
- ...(outputReserveTokens === undefined ? {} : { outputReserveTokens }),
562
- };
439
+ return omitUndefined({ contextWindowTokens, outputReserveTokens });
563
440
  }
564
441
  async function resolveWorkspace(workspace) {
565
442
  if (process.platform === "win32" && /^[A-Za-z]:(?:$|[^\\/])/u.test(workspace)) {
@@ -574,58 +451,11 @@ async function resolveWorkspace(workspace) {
574
451
  }
575
452
  return path;
576
453
  }
577
- function optionalPositiveInteger(value, field) {
578
- if (value === undefined)
579
- return undefined;
580
- if (!Number.isSafeInteger(value) || value < 1) {
581
- throw new MaybeCodeConfigError(`${field} must be a positive safe integer`);
582
- }
583
- return value;
584
- }
585
- function optionalNonNegativeNumber(value, field) {
586
- if (value === undefined)
587
- return undefined;
588
- if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
589
- throw new MaybeCodeConfigError(`${field} must be a non-negative number`);
590
- }
591
- return value;
592
- }
593
- function optionalRatio(value, field) {
594
- const number = optionalNonNegativeNumber(value, field);
595
- if (number !== undefined && number > 1) {
596
- throw new MaybeCodeConfigError(`${field} must be between 0 and 1`);
597
- }
598
- return number;
599
- }
600
- function nonEmptyString(value, field) {
601
- if (typeof value !== "string" || value.trim() === "") {
602
- throw new MaybeCodeConfigError(`${field} must be a non-empty string`);
603
- }
604
- return value;
605
- }
606
- function objectValue(value, field) {
607
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
608
- throw new MaybeCodeConfigError(`${field} must be an object`);
609
- }
610
- return value;
611
- }
612
- function optionalStringArray(value, field) {
613
- if (value === undefined)
614
- return undefined;
615
- if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
616
- throw new MaybeCodeConfigError(`${field} must be an array of strings`);
617
- }
618
- return [...value];
619
- }
620
- function resolveMcpEnvironment(value, field, environment) {
621
- if (value === undefined)
454
+ function resolveMcpEnvironment(configured, field, environment) {
455
+ if (configured === undefined)
622
456
  return undefined;
623
- const configured = objectValue(value, field);
624
457
  const resolved = {};
625
458
  for (const [name, raw] of Object.entries(configured)) {
626
- if (name === "" || typeof raw !== "string") {
627
- throw new MaybeCodeConfigError(`${field} must contain string values`);
628
- }
629
459
  resolved[name] = raw.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/gu, (_match, environmentName) => {
630
460
  const replacement = environment[environmentName];
631
461
  if (replacement === undefined) {
@@ -636,11 +466,4 @@ function resolveMcpEnvironment(value, field, environment) {
636
466
  }
637
467
  return resolved;
638
468
  }
639
- function rejectUnknownOptions(value, allowed, field) {
640
- const names = new Set(allowed);
641
- const unknown = Object.keys(value).find((name) => !names.has(name));
642
- if (unknown !== undefined) {
643
- throw new MaybeCodeConfigError(`${field}.${unknown} is not supported`);
644
- }
645
- }
646
469
  //# sourceMappingURL=configured.js.map