micro-models-agent 2.11.0 → 2.12.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 (347) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/assets/js/tabs.js +22 -3
  3. package/dist/cli/cache-line.js +1 -0
  4. package/dist/cli/command-suggest.js +5 -4
  5. package/dist/cli/commands.js +231 -122
  6. package/dist/cli/completer.js +132 -31
  7. package/dist/cli/index.js +1 -0
  8. package/dist/cli/json-payload.js +4 -4
  9. package/dist/cli/main.js +166 -61
  10. package/dist/cli/onboarding-commands.js +126 -0
  11. package/dist/cli/plugin-commands.js +2 -1
  12. package/dist/cli/relaunch.js +16 -13
  13. package/dist/cli/repl-commands-lsp.js +75 -0
  14. package/dist/cli/repl-commands-skills.js +105 -0
  15. package/dist/cli/repl-commands.js +589 -266
  16. package/dist/cli/repl.js +436 -177
  17. package/dist/cli/run-result.js +5 -6
  18. package/dist/cli/security-commands.js +37 -28
  19. package/dist/cli/setup-order.js +4 -55
  20. package/dist/cli/setup-prompt.js +3 -2
  21. package/dist/cli/setup.js +27 -107
  22. package/dist/cli/web-command.js +98 -0
  23. package/dist/config/budget.js +5 -5
  24. package/dist/config/config.js +103 -96
  25. package/dist/config/defaults.js +38 -8
  26. package/dist/config/domains.js +24 -27
  27. package/dist/config/env.js +46 -0
  28. package/dist/config/experts.js +2 -0
  29. package/dist/config/index.js +1 -0
  30. package/dist/config/paths.js +56 -0
  31. package/dist/config/redact.js +44 -0
  32. package/dist/config/registry-extra.js +334 -0
  33. package/dist/config/registry.js +584 -0
  34. package/dist/config/security.js +35 -36
  35. package/dist/config/timeouts.js +74 -0
  36. package/dist/config/utils.js +16 -15
  37. package/dist/core/agent/artifact-progress.js +59 -0
  38. package/dist/core/agent/artifact-resolve.js +79 -0
  39. package/dist/core/agent/audit-gate.js +7 -3
  40. package/dist/core/agent/compaction.js +2 -2
  41. package/dist/core/agent/constants.js +33 -4
  42. package/dist/core/agent/context-log.js +454 -0
  43. package/dist/core/agent/context-renderer.js +5 -0
  44. package/dist/core/agent/critic-gate.js +132 -0
  45. package/dist/core/agent/hallucination-gate.js +148 -38
  46. package/dist/core/agent/loop-state.js +15 -0
  47. package/dist/core/agent/prefix-monitor.js +1 -1
  48. package/dist/core/agent/reasoning-resolver.js +10 -1
  49. package/dist/core/agent/token-tracker.js +7 -4
  50. package/dist/core/agent/tool-batch.js +93 -18
  51. package/dist/core/agent/tool-images.js +18 -0
  52. package/dist/core/agent/tool-output.js +65 -11
  53. package/dist/core/agent/tool-pairing.js +60 -0
  54. package/dist/core/agent-moe.js +25 -24
  55. package/dist/core/agent.js +429 -108
  56. package/dist/core/bootstrap/agent-phase.js +66 -0
  57. package/dist/core/bootstrap/config-phase.js +86 -0
  58. package/dist/core/bootstrap/modules-phase.js +269 -0
  59. package/dist/core/bootstrap/provider-phase.js +183 -0
  60. package/dist/core/bootstrap/session-phase.js +204 -0
  61. package/dist/core/bootstrap/state.js +94 -0
  62. package/dist/core/bootstrap/workspace-phase.js +115 -0
  63. package/dist/core/bootstrap.js +92 -660
  64. package/dist/core/crash-handler.js +17 -7
  65. package/dist/core/environment.js +37 -12
  66. package/dist/core/host-plan.js +43 -0
  67. package/dist/core/host.js +23 -0
  68. package/dist/core/index.js +1 -0
  69. package/dist/core/prompt-builder.js +17 -1
  70. package/dist/core/prompt-overflow.js +42 -43
  71. package/dist/core/session-logger.js +122 -30
  72. package/dist/core/system-prompt.js +117 -0
  73. package/dist/core/version.js +6 -4
  74. package/dist/core/web-host.js +34 -0
  75. package/dist/core/workspace.js +19 -15
  76. package/dist/i18n/index.js +37 -3
  77. package/dist/index.js +7 -3
  78. package/dist/llm/image-utils.js +55 -64
  79. package/dist/llm/llm-errors.js +9 -0
  80. package/dist/llm/model-loader.js +10 -32
  81. package/dist/llm/models-dev.js +121 -0
  82. package/dist/llm/openai-compat.js +146 -73
  83. package/dist/llm/orchestrator.js +33 -11
  84. package/dist/llm/provider-budget.js +2 -2
  85. package/dist/llm/provider-context.js +233 -0
  86. package/dist/llm/provider.js +1 -1
  87. package/dist/llm/response.js +5 -0
  88. package/dist/llm/token-counter.js +27 -11
  89. package/dist/logger/app-logger.js +48 -22
  90. package/dist/logger/file-log.js +28 -19
  91. package/dist/logger/index.js +1 -0
  92. package/dist/main.js +273 -47
  93. package/dist/migration/backup.js +14 -3
  94. package/dist/migration/detect.js +12 -3
  95. package/dist/migration/index.js +1 -0
  96. package/dist/modules/artifacts/store.js +9 -8
  97. package/dist/modules/browser/actions.js +6 -0
  98. package/dist/modules/browser/bridge-client.js +14 -12
  99. package/dist/modules/browser/bridge-path.js +4 -4
  100. package/dist/modules/browser/console-buffer.js +37 -0
  101. package/dist/modules/browser/cookie-store.js +5 -0
  102. package/dist/modules/browser/driver-types.js +1 -0
  103. package/dist/modules/browser/driver.js +19 -11
  104. package/dist/modules/browser/index.js +3 -1
  105. package/dist/modules/browser/module.js +2 -1
  106. package/dist/modules/browser/session.js +10 -30
  107. package/dist/modules/browser/snapshot.js +19 -13
  108. package/dist/modules/browser/types.js +1 -0
  109. package/dist/modules/certification/cli.js +28 -20
  110. package/dist/modules/certification/fact-checker.js +9 -1
  111. package/dist/modules/certification/loader.js +9 -2
  112. package/dist/modules/certification/manifest.js +83 -21
  113. package/dist/modules/certification/runner.js +23 -13
  114. package/dist/modules/certification/scenarios.js +20 -20
  115. package/dist/modules/certification/syntax-scenarios.js +1 -2
  116. package/dist/modules/context/chunk-query.js +11 -9
  117. package/dist/modules/context/fact-extractor.js +37 -39
  118. package/dist/modules/context/index.js +1 -0
  119. package/dist/modules/context/manager.js +106 -80
  120. package/dist/modules/critic/client.js +176 -0
  121. package/dist/modules/critic/evidence.js +81 -0
  122. package/dist/modules/critic/provider.js +45 -0
  123. package/dist/modules/critic/tools.js +78 -0
  124. package/dist/modules/critic/types.js +1 -0
  125. package/dist/modules/execution/audit-runners.js +28 -34
  126. package/dist/modules/execution/auditor.js +53 -49
  127. package/dist/modules/execution/execution-plugin.js +142 -102
  128. package/dist/modules/execution/index.js +1 -1
  129. package/dist/modules/execution/input-from.js +37 -13
  130. package/dist/modules/execution/module.js +368 -191
  131. package/dist/modules/execution/moe-executor.js +53 -26
  132. package/dist/modules/execution/plan-actions.js +320 -202
  133. package/dist/modules/execution/plan-checks.js +35 -0
  134. package/dist/modules/execution/plan-coverage.js +36 -33
  135. package/dist/modules/execution/plan-steps.js +11 -3
  136. package/dist/modules/execution/plan-store.js +83 -17
  137. package/dist/modules/execution/plan-tool.js +89 -35
  138. package/dist/modules/execution/plan-validator.js +30 -10
  139. package/dist/modules/execution/planner.js +22 -13
  140. package/dist/modules/execution/stuck-detector.js +196 -93
  141. package/dist/modules/execution/tracker.js +22 -8
  142. package/dist/modules/execution/verifier.js +69 -48
  143. package/dist/modules/execution/windows-commands.js +12 -12
  144. package/dist/modules/hallucination/artifact-claim.js +93 -0
  145. package/dist/modules/hallucination/confidence.js +13 -11
  146. package/dist/modules/hallucination/consistency.js +10 -2
  147. package/dist/modules/hallucination/detector.js +10 -5
  148. package/dist/modules/hallucination/factual.js +43 -26
  149. package/dist/modules/hallucination/index.js +1 -0
  150. package/dist/modules/hallucination/js-identifiers.js +44 -45
  151. package/dist/modules/hallucination/llm-judge.js +17 -12
  152. package/dist/modules/hallucination/success-claim.js +59 -0
  153. package/dist/modules/indexer/cache.js +52 -4
  154. package/dist/modules/indexer/index.js +1 -0
  155. package/dist/modules/indexer/map-command.js +2 -4
  156. package/dist/modules/indexer/map-select.js +16 -16
  157. package/dist/modules/indexer/module.js +47 -12
  158. package/dist/modules/indexer/project-profile.js +8 -7
  159. package/dist/modules/indexer/symbols.js +15 -15
  160. package/dist/modules/indexer/walker.js +159 -29
  161. package/dist/modules/lsp/check-tool.js +7 -5
  162. package/dist/modules/lsp/client.js +39 -39
  163. package/dist/modules/lsp/command.js +17 -24
  164. package/dist/modules/lsp/config.js +12 -11
  165. package/dist/modules/lsp/index.js +1 -0
  166. package/dist/modules/lsp/module.js +48 -46
  167. package/dist/modules/lsp/probe.js +13 -14
  168. package/dist/modules/lsp/project-root.js +14 -17
  169. package/dist/modules/lsp/startup-check.js +18 -16
  170. package/dist/modules/mcp/client.js +59 -62
  171. package/dist/modules/mcp/index.js +1 -0
  172. package/dist/modules/mcp/module.js +66 -37
  173. package/dist/modules/mcp/registry.js +5 -0
  174. package/dist/modules/memory/index.js +1 -0
  175. package/dist/modules/memory/module.js +12 -8
  176. package/dist/modules/memory/search.js +4 -1
  177. package/dist/modules/memory/store.js +40 -2
  178. package/dist/modules/onboarding/init.js +47 -0
  179. package/dist/modules/onboarding/meet.js +30 -0
  180. package/dist/modules/onboarding/mode.js +30 -0
  181. package/dist/modules/onboarding/prompts.js +43 -0
  182. package/dist/modules/pipelines/engine.js +10 -0
  183. package/dist/modules/pipelines/index.js +1 -0
  184. package/dist/modules/pipelines/parser.js +4 -1
  185. package/dist/modules/pipelines/template.js +4 -0
  186. package/dist/modules/plugins/builtin/lint-on-write.js +80 -67
  187. package/dist/modules/plugins/builtin/notify.js +2 -0
  188. package/dist/modules/plugins/index.js +1 -0
  189. package/dist/modules/plugins/loader.js +18 -3
  190. package/dist/modules/plugins/manager.js +37 -17
  191. package/dist/modules/pricing/index.js +10 -11
  192. package/dist/modules/pricing/prices.js +12 -12
  193. package/dist/modules/processes/index.js +1 -0
  194. package/dist/modules/processes/kill-tree.js +27 -31
  195. package/dist/modules/processes/registry.js +44 -25
  196. package/dist/modules/processes/runner.js +4 -4
  197. package/dist/modules/providers/capabilities.js +28 -0
  198. package/dist/modules/providers/create.js +3 -4
  199. package/dist/modules/providers/factory.js +7 -7
  200. package/dist/modules/providers/fallback.js +12 -12
  201. package/dist/modules/providers/health.js +4 -4
  202. package/dist/modules/providers/manager.js +50 -19
  203. package/dist/modules/providers/naming.js +15 -0
  204. package/dist/modules/providers/preflight.js +71 -0
  205. package/dist/modules/providers/presets.js +39 -8
  206. package/dist/modules/providers/registry.js +7 -2
  207. package/dist/modules/reasoning/policy.js +8 -6
  208. package/dist/modules/reasoning/probe.js +30 -25
  209. package/dist/modules/security/audit-log.js +19 -36
  210. package/dist/modules/security/audit-notifier.js +35 -75
  211. package/dist/modules/security/command-validator.js +99 -51
  212. package/dist/modules/security/content-scanner.js +8 -8
  213. package/dist/modules/security/data-sanitizer.js +9 -16
  214. package/dist/modules/security/encryption.js +32 -52
  215. package/dist/modules/security/index.js +2 -1
  216. package/dist/modules/security/network-validator.js +120 -43
  217. package/dist/modules/security/path-validator.js +61 -46
  218. package/dist/modules/security/protected-paths.js +73 -0
  219. package/dist/modules/security/rate-limiter.js +17 -49
  220. package/dist/modules/security/security-policies.js +25 -57
  221. package/dist/modules/security/session-encryption.js +32 -71
  222. package/dist/modules/security/session-isolation.js +15 -28
  223. package/dist/modules/session/auto-name.js +63 -0
  224. package/dist/modules/session/export.js +98 -0
  225. package/dist/modules/session/index.js +1 -0
  226. package/dist/modules/session/manager.js +79 -28
  227. package/dist/modules/session/module.js +4 -3
  228. package/dist/modules/session/store.js +57 -20
  229. package/dist/modules/setup/answers.js +35 -0
  230. package/dist/modules/setup/apply.js +79 -0
  231. package/dist/modules/setup/discovery.js +72 -0
  232. package/dist/modules/skills/index.js +1 -0
  233. package/dist/modules/skills/loader.js +9 -1
  234. package/dist/modules/skills/module.js +11 -0
  235. package/dist/modules/updater/changelog-reader.js +15 -16
  236. package/dist/modules/updater/checker.js +9 -4
  237. package/dist/modules/updater/dev-detect.js +7 -6
  238. package/dist/modules/updater/index.js +1 -0
  239. package/dist/modules/updater/module.js +17 -15
  240. package/dist/modules/user-profile/compressor.js +2 -0
  241. package/dist/modules/user-profile/index.js +1 -0
  242. package/dist/modules/user-profile/profile.js +10 -1
  243. package/dist/modules/webui/answer-api.js +29 -0
  244. package/dist/modules/webui/assets.js +50 -0
  245. package/dist/modules/webui/body.js +21 -0
  246. package/dist/modules/webui/commands-settings.js +209 -0
  247. package/dist/modules/webui/commands-shared.js +60 -0
  248. package/dist/modules/webui/commands.js +174 -0
  249. package/dist/modules/webui/config-api.js +134 -0
  250. package/dist/modules/webui/file-api.js +202 -0
  251. package/dist/modules/webui/forward.js +159 -0
  252. package/dist/modules/webui/history-api.js +112 -0
  253. package/dist/modules/webui/host-state.js +60 -0
  254. package/dist/modules/webui/i18n-api.js +9 -0
  255. package/dist/modules/webui/limits.js +6 -0
  256. package/dist/modules/webui/log-forward.js +20 -0
  257. package/dist/modules/webui/memory-commands.js +64 -0
  258. package/dist/modules/webui/model-cache.js +18 -0
  259. package/dist/modules/webui/module.js +148 -0
  260. package/dist/modules/webui/persist.js +24 -0
  261. package/dist/modules/webui/prompt-io.js +97 -0
  262. package/dist/modules/webui/providers-api.js +337 -0
  263. package/dist/modules/webui/providers-view.js +56 -0
  264. package/dist/modules/webui/reasoning-view.js +15 -0
  265. package/dist/modules/webui/run-agent.js +81 -0
  266. package/dist/modules/webui/server.js +284 -0
  267. package/dist/modules/webui/sessions-api.js +178 -0
  268. package/dist/modules/webui/settings-api.js +561 -0
  269. package/dist/modules/webui/setup-api.js +201 -0
  270. package/dist/modules/webui/state.js +74 -0
  271. package/dist/modules/webui/util.js +261 -0
  272. package/dist/output/bus.js +7 -2
  273. package/dist/output/channel.js +80 -28
  274. package/dist/output/format.js +2 -1
  275. package/dist/output/index.js +1 -0
  276. package/dist/output/json-sink.js +5 -3
  277. package/dist/output/machine.js +4 -3
  278. package/dist/output/session-sink.js +4 -4
  279. package/dist/tools/approve.js +4 -0
  280. package/dist/tools/attach-image.js +5 -4
  281. package/dist/tools/auto-fixer.js +26 -44
  282. package/dist/tools/auto-tags.js +83 -0
  283. package/dist/tools/bash.js +193 -116
  284. package/dist/tools/browser.js +76 -31
  285. package/dist/tools/chunk-query.js +14 -6
  286. package/dist/tools/create-dir.js +9 -5
  287. package/dist/tools/delete-file.js +9 -5
  288. package/dist/tools/download-file.js +32 -7
  289. package/dist/tools/edit-file.js +52 -14
  290. package/dist/tools/enable-tools.js +6 -6
  291. package/dist/tools/executor.js +132 -27
  292. package/dist/tools/file-info.js +3 -1
  293. package/dist/tools/filter-tools.js +3 -3
  294. package/dist/tools/glob-tool.js +4 -1
  295. package/dist/tools/grep-tool.js +13 -10
  296. package/dist/tools/hidden-tools-block.js +6 -6
  297. package/dist/tools/index.js +16 -8
  298. package/dist/tools/list-dir.js +4 -2
  299. package/dist/tools/load-skill.js +7 -0
  300. package/dist/tools/mcp-call.js +15 -4
  301. package/dist/tools/meet-done.js +14 -0
  302. package/dist/tools/move-file.js +14 -7
  303. package/dist/tools/path-utils.js +29 -29
  304. package/dist/tools/pipeline-run.js +29 -7
  305. package/dist/tools/preview.js +1 -1
  306. package/dist/tools/process-ids.js +31 -0
  307. package/dist/tools/process-kill.js +9 -16
  308. package/dist/tools/process-list.js +1 -0
  309. package/dist/tools/process-log.js +11 -16
  310. package/dist/tools/process-wait.js +63 -0
  311. package/dist/tools/prompt-io.js +4 -3
  312. package/dist/tools/question.js +172 -25
  313. package/dist/tools/read-file.js +55 -34
  314. package/dist/tools/recall.js +14 -8
  315. package/dist/tools/registry.js +6 -5
  316. package/dist/tools/remember.js +8 -4
  317. package/dist/tools/scope-request.js +11 -6
  318. package/dist/tools/search-history.js +5 -2
  319. package/dist/tools/session-info.js +2 -0
  320. package/dist/tools/set-thinking.js +8 -4
  321. package/dist/tools/subagent.js +59 -39
  322. package/dist/tools/syntax-validator.js +292 -90
  323. package/dist/tools/user-input.js +22 -18
  324. package/dist/tools/web-browse.js +9 -3
  325. package/dist/tools/web-fetch.js +12 -23
  326. package/dist/tools/web-search.js +7 -5
  327. package/dist/tools/write-file.js +45 -15
  328. package/dist/ui/action-log.js +13 -0
  329. package/dist/ui/box.js +4 -3
  330. package/dist/ui/colors.js +2 -0
  331. package/dist/ui/diff.js +6 -5
  332. package/dist/ui/index.js +1 -0
  333. package/dist/ui/line-editor.js +230 -122
  334. package/dist/ui/line-math.js +10 -2
  335. package/dist/ui/md-formatter.js +57 -37
  336. package/dist/ui/output.js +8 -3
  337. package/dist/ui/plan-view.js +21 -10
  338. package/dist/ui/renderer.js +393 -67
  339. package/dist/ui/spinner.js +16 -5
  340. package/dist/ui/table.js +15 -17
  341. package/dist/ui/theme.js +143 -0
  342. package/dist/utils/child-run.js +20 -0
  343. package/dist/utils/error.js +1 -1
  344. package/dist/utils/index.js +2 -0
  345. package/dist/utils/retry.js +2 -2
  346. package/dist/utils/truncate.js +1 -1
  347. package/package.json +1 -1
@@ -1,5 +1,19 @@
1
1
  import { readdirSync, statSync } from "fs";
2
2
  import { join } from "path";
3
+ import { allConfigNames, canonicalKeys, resolveConfigKey } from "../config/registry";
4
+ import { t } from "../i18n/index";
5
+ /**
6
+ * Строит slash-варианты из реестра команд. `commands` ключуется И каноническими
7
+ * именами, И алиасами — каждый алиас становится дополняемым токеном с описанием
8
+ * своей команды.
9
+ */
10
+ export function buildSlashCompletions(commands) {
11
+ return Array.from(commands.entries()).map(([name, cmd]) => ({
12
+ name,
13
+ description: cmd.description,
14
+ }));
15
+ }
16
+ /** Дополняет slash-команды в позиции 0. */
3
17
  export class SlashCommandProvider {
4
18
  name = "slash-commands";
5
19
  commands;
@@ -10,24 +24,30 @@ export class SlashCommandProvider {
10
24
  return ctx.tokenIndex === 0 && ctx.line.startsWith("/");
11
25
  }
12
26
  complete(ctx) {
13
- return this.commands.filter((c) => c.startsWith(ctx.partial.slice(1))).map((c) => `/${c}`);
27
+ return this.commands
28
+ .filter((c) => c.name.startsWith(ctx.partial.slice(1)))
29
+ .map((c) => ({ value: `/${c.name}`, description: c.description }));
14
30
  }
15
31
  }
32
+ /** Дополняет субкоманды (`/model use`, `/skill load`, …) в позиции 1. */
16
33
  export class SubcommandProvider {
17
34
  name = "subcommands";
18
35
  command;
19
36
  subcommands;
20
37
  constructor(command, subcommands) {
21
38
  this.command = command;
22
- this.subcommands = subcommands;
39
+ this.subcommands = subcommands.map((s) => (typeof s === "string" ? { name: s } : s));
23
40
  }
24
41
  match(ctx) {
25
42
  return ctx.tokenIndex === 1 && ctx.tokens[0] === `/${this.command}`;
26
43
  }
27
44
  complete(ctx) {
28
- return this.subcommands.filter((s) => s.startsWith(ctx.partial));
45
+ return this.subcommands
46
+ .filter((s) => s.name.startsWith(ctx.partial))
47
+ .map((s) => ({ value: s.name, description: s.description }));
29
48
  }
30
49
  }
50
+ /** Дополняет имена моделей для `/model use`. */
31
51
  export class ModelArgProvider {
32
52
  name = "model-args";
33
53
  getModels;
@@ -38,30 +58,25 @@ export class ModelArgProvider {
38
58
  return ctx.tokenIndex === 2 && ctx.tokens[0] === "/model" && ctx.tokens[1] === "use";
39
59
  }
40
60
  complete(ctx) {
41
- return this.getModels().filter((m) => m.startsWith(ctx.partial));
42
- }
43
- }
44
- export class ConfigKeyProvider {
45
- name = "config-keys";
46
- keys;
47
- constructor(keys) {
48
- this.keys = keys;
49
- }
50
- match(ctx) {
51
- return ctx.tokenIndex >= 1 && ctx.tokens[0] === "/config" && ctx.tokens[1] === "set";
52
- }
53
- complete(ctx) {
54
- return this.keys.filter((k) => k.startsWith(ctx.partial));
61
+ return this.getModels()
62
+ .filter((m) => m.startsWith(ctx.partial))
63
+ .map((m) => ({ value: m }));
55
64
  }
56
65
  }
66
+ /** Дополняет файловые пути (до 20 вариантов, каталоги со `/`). */
57
67
  export class FilePathProvider {
58
68
  name = "file-paths";
69
+ root;
70
+ constructor(root) {
71
+ this.root = root;
72
+ }
59
73
  match(ctx) {
60
- return ctx.partial.includes("/") || ctx.partial.includes("\\");
74
+ return (ctx.tokenIndex >= 1 &&
75
+ (ctx.partial.includes("/") || ctx.partial.includes("\\")));
61
76
  }
62
77
  complete(ctx) {
63
78
  try {
64
- const cwd = process.cwd();
79
+ const cwd = this.root ?? process.cwd();
65
80
  const partialPath = ctx.partial;
66
81
  const lastSlash = Math.max(partialPath.lastIndexOf("/"), partialPath.lastIndexOf("\\"));
67
82
  const dirPath = lastSlash > 0 ? partialPath.slice(0, lastSlash) : ".";
@@ -77,13 +92,14 @@ export class FilePathProvider {
77
92
  matches.push(completion);
78
93
  }
79
94
  }
80
- return matches.slice(0, 20);
95
+ return matches.slice(0, 20).map((m) => ({ value: m }));
81
96
  }
82
97
  catch {
83
98
  return [];
84
99
  }
85
100
  }
86
101
  }
102
+ /** Дополняет имена провайдеров для `/provider use`. */
87
103
  export class ProviderArgProvider {
88
104
  name = "provider-args";
89
105
  providers;
@@ -94,25 +110,30 @@ export class ProviderArgProvider {
94
110
  return ctx.tokenIndex === 2 && ctx.tokens[0] === "/provider" && ctx.tokens[1] === "use";
95
111
  }
96
112
  complete(ctx) {
97
- return this.providers.filter((p) => p.startsWith(ctx.partial));
113
+ return this.providers.filter((p) => p.startsWith(ctx.partial)).map((p) => ({ value: p }));
98
114
  }
99
115
  }
116
+ /** Дополняет имена сессий для `/resume` и др. */
100
117
  export class SessionNameProvider {
101
118
  name = "session-names";
102
119
  getNames;
103
- constructor(getNames) {
120
+ commands;
121
+ constructor(getNames, commands = ["/resume"]) {
104
122
  this.getNames = getNames;
123
+ this.commands = commands;
105
124
  }
106
125
  match(ctx) {
107
- return ctx.tokenIndex >= 1 && ctx.tokens[0] === "/resume";
126
+ return ctx.tokenIndex >= 1 && this.commands.includes(ctx.tokens[0]);
108
127
  }
109
128
  complete(ctx) {
110
129
  const names = this.getNames();
111
- if (!ctx.partial)
112
- return names;
113
- return names.filter((n) => n.toLowerCase().includes(ctx.partial.toLowerCase()));
130
+ const filtered = !ctx.partial
131
+ ? names
132
+ : names.filter((n) => n.toLowerCase().includes(ctx.partial.toLowerCase()));
133
+ return filtered.map((n) => ({ value: n }));
114
134
  }
115
135
  }
136
+ /** Дополняет имена скиллов для `/skill load|unload`. */
116
137
  export class SkillNameProvider {
117
138
  name = "skill-names";
118
139
  skillsModule;
@@ -133,21 +154,101 @@ export class SkillNameProvider {
133
154
  if (!source)
134
155
  return [];
135
156
  const names = source();
136
- if (!ctx.partial)
137
- return names;
138
- return names.filter((n) => n.toLowerCase().includes(ctx.partial.toLowerCase()));
157
+ const filtered = !ctx.partial
158
+ ? names
159
+ : names.filter((n) => n.toLowerCase().includes(ctx.partial.toLowerCase()));
160
+ return filtered.map((n) => ({ value: n }));
161
+ }
162
+ }
163
+ /**
164
+ * Дополняет ключи `/config` (канонические и алиасы). Partial без точки листает
165
+ * верхние группы + подходящие ключи; partial с точкой — следующий сегмент
166
+ * точечного дерева (напр. `contextBudget.` → systemPrompt).
167
+ */
168
+ export class ConfigKeyProvider {
169
+ name = "config-keys";
170
+ match(ctx) {
171
+ return ctx.tokenIndex === 1 && ctx.tokens[0] === "/config";
172
+ }
173
+ complete(ctx) {
174
+ const partial = ctx.partial;
175
+ const items = allConfigNames().map(({ name, def, alias }) => ({
176
+ value: name,
177
+ description: alias ? `${t("config.alias_label")} ${def.key}` : def.domain,
178
+ }));
179
+ if (!partial.includes(".")) {
180
+ const groups = [...new Set(canonicalKeys().filter((k) => k.includes(".")).map((k) => k.split(".")[0]))];
181
+ const groupItems = groups.map((g) => ({
182
+ value: g,
183
+ description: t("config.group_label"),
184
+ }));
185
+ return [...groupItems, ...items].filter((i) => i.value.startsWith(partial));
186
+ }
187
+ return items.filter((i) => i.value.startsWith(partial));
188
+ }
189
+ }
190
+ /** Дополняет enum-значения в позиции значения `/config <ключ> <значение>`. */
191
+ export class ConfigValueProvider {
192
+ name = "config-values";
193
+ match(ctx) {
194
+ return ctx.tokenIndex === 2 && ctx.tokens[0] === "/config";
195
+ }
196
+ complete(ctx) {
197
+ const def = resolveConfigKey(ctx.tokens[1]);
198
+ if (!def?.enumValues)
199
+ return [];
200
+ return def.enumValues
201
+ .filter((v) => v.startsWith(ctx.partial))
202
+ .map((v) => ({ value: v }));
203
+ }
204
+ }
205
+ /** Дополняет флаги `/provider add`. */
206
+ export class FlagProvider {
207
+ name = "provider-add-flags";
208
+ match(ctx) {
209
+ return ctx.tokens[0] === "/provider" && ctx.tokens[1] === "add" && ctx.tokenIndex >= 2;
210
+ }
211
+ complete(ctx) {
212
+ const flags = [
213
+ { value: "--url", description: t("repl.provider_flag_url") },
214
+ { value: "--key", description: t("repl.provider_flag_key") },
215
+ { value: "--priority", description: t("repl.provider_flag_priority") },
216
+ { value: "--context-window", description: t("repl.provider_flag_context_window") },
217
+ { value: "--rpm", description: t("repl.provider_flag_rpm") },
218
+ { value: "--parallel", description: t("repl.provider_flag_parallel") },
219
+ ];
220
+ return flags.filter((f) => f.value.startsWith(ctx.partial));
221
+ }
222
+ }
223
+ /** Дополняет имена команд для `/help <команда>`. */
224
+ export class CommandArgProvider {
225
+ name = "help-command-args";
226
+ getNames;
227
+ constructor(getNames) {
228
+ this.getNames = getNames;
229
+ }
230
+ match(ctx) {
231
+ return ctx.tokenIndex === 1 && ctx.tokens[0] === "/help";
232
+ }
233
+ complete(ctx) {
234
+ return this.getNames()
235
+ .filter((n) => n.startsWith(ctx.partial))
236
+ .map((n) => ({ value: n }));
139
237
  }
140
238
  }
239
+ /** Комплитер: гоняет ввод через провайдеров, первый с хитами побеждает. */
141
240
  export class Completer {
142
241
  providers = [];
242
+ /** Регистрирует провайдера. */
143
243
  registerProvider(provider) {
144
244
  this.providers.push(provider);
145
245
  }
146
- /** Drop all registered providers — used before a rebuild (e.g. /reload)
147
- * so re-registering never accumulates duplicates. */
246
+ /** Сброс всех провайдеров — перед пересборкой (напр. /reload), чтобы
247
+ * перерегистрация не копила дубликаты. */
148
248
  reset() {
149
249
  this.providers = [];
150
250
  }
251
+ /** Дополняет строку; возвращает [варианты, partial]. */
151
252
  complete(line) {
152
253
  const cursor = line.length;
153
254
  const tokens = line.split(/\s+/);
package/dist/cli/index.js CHANGED
@@ -1,2 +1,3 @@
1
+ // Вход CLI-пакета: main и фабрика commander-программы.
1
2
  export { main } from "./main";
2
3
  export { createProgram } from "./commands";
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Machine-readable result document for a completed `--json` run. The
3
- * `diagnostics` array carries the warn/error bus events the human channel
4
- * suppressed, so a machine consumer sees probe/config/security failures.
2
+ * Машиночитаемый документ завершённого `--json`-прогона. Массив `diagnostics`
3
+ * несёт warn/error-события шины, погашенные человеческим каналом, чтобы
4
+ * машинный потребитель видел провалы проб/конфига/безопасности.
5
5
  */
6
6
  export function buildJsonResult(result, diagnostics) {
7
7
  return {
@@ -20,7 +20,7 @@ export function buildJsonResult(result, diagnostics) {
20
20
  diagnostics,
21
21
  };
22
22
  }
23
- /** Failure document for a throw that never produced an `AgentResult`. */
23
+ /** Документ провала для throw, так и не давшего `AgentResult`. */
24
24
  export function buildJsonError(error, diagnostics = []) {
25
25
  return {
26
26
  success: false,
package/dist/cli/main.js CHANGED
@@ -1,37 +1,64 @@
1
+ // Точка входа CLI: parse, one-shot/REPL/web-ветки, JSON-режим, автоапдейт.
1
2
  import { createProgram } from "./commands";
2
3
  import { bootstrap, setOneShotMode, applyReasoningCliOverride } from "../core/bootstrap";
3
4
  import { Repl } from "./repl";
4
5
  import { Renderer } from "../ui/renderer";
6
+ import { resolveVerbosity } from "../ui/theme";
5
7
  import { printRunResult } from "./run-result";
6
8
  import { runSetup } from "./setup";
9
+ import { runWeb, parsePort } from "./web-command";
7
10
  import { applyAnswersToConfig } from "./setup-order";
8
11
  import { relaunchCli } from "./relaunch";
9
12
  import { defaultOutputBus, getDefaultChannel, JsonOutputSink, writeMachineJson } from "../output";
10
13
  import { buildJsonError, buildJsonResult } from "./json-payload";
11
14
  import { saveConfig, loadConfig } from "../config/config";
12
- import { t } from "../i18n/index";
15
+ import { t, setLocale } from "../i18n/index";
13
16
  import { pc } from "../ui/colors";
14
- import { existsSync } from "fs";
17
+ import { existsSync, readFileSync } from "fs";
15
18
  import { join, dirname } from "path";
16
- import { homedir } from "os";
17
19
  import { fileURLToPath } from "url";
18
20
  import { UpdaterModule, isDevEntryPath } from "../modules/updater/index";
19
21
  import { installCrashHandlers } from "../core/crash-handler";
20
22
  import { readMmaVersion } from "../core/version";
21
23
  import { closestCommand } from "./command-suggest";
22
24
  import { errMsg } from "../utils";
25
+ import { globalMmaDir } from "../config/paths";
26
+ import { MMA_ENV, readEnv } from "../config/env";
23
27
  /**
24
- * Set only for one-shot `--json` runs (a positional prompt exists). Module-scoped
25
- * so the top-level `main().catch` can still emit a valid document when `bootstrap`
26
- * (or anything before the JSON branch) throws with empty stdout. Interactive
27
- * `mma --json` (no prompt) must not set it, or a REPL crash would emit JSON.
28
+ * Взведён только для one-shot `--json`-прогонов (позиционный промпт есть). На уровне
29
+ * модуля, чтобы топ-уровневый `main().catch` отдал валидный документ, даже когда
30
+ * `bootstrap` (или что-то до JSON-ветки) бросил с пустым stdout. Интерактивный
31
+ * `mma --json` (без промпта) его не ставит, иначе краш REPL эмитил бы JSON.
28
32
  */
29
33
  let jsonMode = false;
30
- /** Fire-and-forget self-update in the background (never blocks startup). */
34
+ /**
35
+ * Резолвит UI-локаль ДО `createProgram()`: описания команд и подсказка-тайпоупор
36
+ * строятся через `t()` в момент регистрации, так что установка локали только в
37
+ * bootstrap оставляла `--help` и near-miss хинты английскими при `locale: ru`.
38
+ * Дешёвое защитное чтение файла, не полный лоад конфига.
39
+ */
40
+ function resolveEarlyLocale() {
41
+ const env = readEnv("LOCALE");
42
+ if (env)
43
+ return env;
44
+ const dir = globalMmaDir();
45
+ for (const p of [join(dir, "config", "core.json"), join(dir, "config.json")]) {
46
+ try {
47
+ const parsed = JSON.parse(readFileSync(p, "utf-8"));
48
+ if (typeof parsed.locale === "string")
49
+ return parsed.locale;
50
+ }
51
+ catch {
52
+ /* missing/invalid file — try the next candidate */
53
+ }
54
+ }
55
+ return undefined;
56
+ }
57
+ /** Fire-and-forget самоапдейт фоном (старт никогда не блокирует). */
31
58
  function startAutoUpdate(config) {
32
- // Dev runs load TypeScript sources; the published bundle runs dist/main.js.
33
- // Never auto-update from a checkout — its package.json version may trail npm
34
- // and global-installing over the user's install is destructive.
59
+ // Dev-прогоны грузят TypeScript-исходники; опубликованный бандл — dist/main.js.
60
+ // Из чекаута не автоапдейтимся: его package.json может отставать от npm, а
61
+ // global-install поверх юзерской установки деструктивен.
35
62
  if (isDevEntryPath(fileURLToPath(import.meta.url)))
36
63
  return undefined;
37
64
  try {
@@ -44,20 +71,20 @@ function startAutoUpdate(config) {
44
71
  return module;
45
72
  }
46
73
  catch {
47
- // Auto-update is best-effort; never let it crash startup.
74
+ // Автоапдейт best-effort; ронять старт ему нельзя.
48
75
  return undefined;
49
76
  }
50
77
  }
51
78
  async function main() {
52
- // Install global crash handlers first — every crash lands in
53
- // ~/.mma/logs/crash.jsonl (with env report) instead of a bare stderr stack.
79
+ // Глобальные краш-хендлеры первым делом: каждый краш ложится в
80
+ // ~/.mma/logs/crash.jsonl (с env-репортом), а не голым стеком в stderr.
54
81
  installCrashHandlers();
55
- // Eagerly create the default channel so it subscribes to `defaultOutputBus`
56
- // BEFORE any config/bootstrap code can emit (config warnings, migration
57
- // summary, updater notices). The channel is created lazily by
58
- // `getDefaultChannel()`; without this call every bus event emitted before the
59
- // first channel use would have no terminal subscriber and be dropped.
82
+ // Канал-дефолт создаём жадно, чтобы подписался на `defaultOutputBus` ДО того, как
83
+ // конфиг/bootstrap что-то эмитит (варнинги конфига, сводка миграции, апдейтер).
84
+ // Канал ленив через `getDefaultChannel()`: без этого вызова каждое событие шины
85
+ // до первого использования канала осталось бы без терминального подписчика и дропнулось.
60
86
  getDefaultChannel();
87
+ setLocale(resolveEarlyLocale() ?? "en");
61
88
  const program = createProgram();
62
89
  // Определяем подкоманду ДО parse: commander запускает async-action синхронно
63
90
  // из parse(), поэтому флаг one-shot нужно выставить заранее, иначе bootstrap
@@ -76,49 +103,116 @@ async function main() {
76
103
  firstPositional = a;
77
104
  break;
78
105
  }
79
- if (firstPositional && program.commands.some((c) => c.name() === firstPositional)) {
106
+ const onboardingStart = firstPositional === "meet" ? "meet" : firstPositional === "agents" ? "init" : null;
107
+ if (firstPositional &&
108
+ !onboardingStart &&
109
+ program.commands.some((c) => c.name() === firstPositional)) {
80
110
  setOneShotMode(true);
81
111
  }
82
112
  program.parse(process.argv);
83
113
  const cmdNames = new Set(program.commands.map((c) => c.name()));
84
114
  const opts = program.opts();
85
- const noAgentsMd = opts.noAgentsMd === true;
115
+ // commander превращает `--no-agents-md` в отрицаемый `agentsMd`-bool
116
+ // (дефолт true); ключа `noAgentsMd` нет.
117
+ const noAgentsMd = opts.agentsMd === false;
86
118
  const projectDir = opts.dir;
87
119
  const exitOnComplete = opts.exitOnComplete === true;
88
120
  const jsonOpt = opts.json === true;
89
121
  const reasoningLevel = opts.reasoning;
90
- const isSubcommand = program.args.length > 0 && cmdNames.has(program.args[0]);
122
+ const verboseOpt = opts.verbose === true;
123
+ const contextLog = opts.contextLog === true;
124
+ // Quiet-чат прячет структурные info-логи; --verbose (или verbose-конфиг) их
125
+ // возвращает. Ставим до bootstrap, чтобы его собственные логи уважали флаг.
126
+ // Диагностика петли (`Logger.diagnostic`) следует тому же правилу видимости.
127
+ const applyLogVisibility = (verbose) => {
128
+ getDefaultChannel().setSuppressInfoLogs(!verbose);
129
+ getDefaultChannel().setShowDiagnostics(verbose);
130
+ };
131
+ applyLogVisibility(verboseOpt);
132
+ // `web` долгоживущий: его action — no-op, сервер стартует здесь, после parse,
133
+ // чтобы пережить one-shot exit-хук (на `web` в commands.ts он осознанно не вешается).
134
+ if (program.args[0] === "web") {
135
+ const webOpts = (program.commands.find((c) => c.name() === "web")?.opts() ?? {});
136
+ let port;
137
+ try {
138
+ port = parsePort(webOpts.port);
139
+ }
140
+ catch (err) {
141
+ getDefaultChannel().writeLine(pc.red(` ${errMsg(err)}`), "stderr");
142
+ process.exit(2);
143
+ }
144
+ await runWeb({
145
+ port,
146
+ host: webOpts.host,
147
+ token: webOpts.token,
148
+ noOpen: webOpts.open === false,
149
+ projectDir,
150
+ noAgentsMd,
151
+ });
152
+ process.exit(0);
153
+ }
154
+ const isSubcommand = program.args.length > 0 && cmdNames.has(program.args[0]) && !onboardingStart;
91
155
  if (isSubcommand) {
92
156
  return;
93
157
  }
94
- // Typo guard: a misspelled subcommand must not be silently sent to the LLM
95
- // as a prompt ("mma sesion list" → chat). Warn and exit when args[0] is a
96
- // near-miss of a known command; free-form prompts never look like that.
97
- if (program.args.length > 0) {
158
+ // Тайпо-сторож: субкоманда с опечаткой не должна молча уходить в LLM как
159
+ // промпт ("mma sesion list" → чат). На near-miss известной команды — warn и выход;
160
+ // свободные промпты так не выглядят никогда.
161
+ if (program.args.length > 0 && !onboardingStart) {
98
162
  const suggestion = closestCommand(program.args[0], [...cmdNames]);
99
163
  if (suggestion && suggestion !== program.args[0]) {
100
164
  getDefaultChannel().writeLine(pc.yellow(`${t("cli.unknown_command", { input: program.args[0], suggestion })}`), "stderr");
101
165
  process.exit(2);
102
166
  }
103
167
  }
104
- if (program.args.length > 0) {
105
- // `--json` owns stdout for ONE-SHOT runs only: silence the human channel
106
- // before bootstrap so config warnings cannot pollute the machine-readable
107
- // document, and subscribe the sink BEFORE bootstrap so warn/error events
108
- // emitted during bootstrap are captured and surfaced as diagnostics.
109
- // Info-level migration notices are intentionally not captured (diagnostics
110
- // are warn/error only). A no-prompt invocation (`mma --json`) opens the
111
- // interactive REPL, so neither quiet nor the sink is set there.
168
+ if (program.args.length > 0 && !onboardingStart) {
169
+ // `--json` владеет stdout ТОЛЬКО в one-shot: гасим человеческий канал до
170
+ // bootstrap, чтобы варнинги конфига не запачкали машиночитаемый документ,
171
+ // и подписываем sink ДО bootstrap, чтобы warn/error bootstrap попали в
172
+ // captured-диагностику. Info-нотисы миграции осознанно не каптурятся
173
+ // (диагностика — только warn/error). Вызов без промпта (`mma --json`)
174
+ // открывает интерактивный REPL: ни quiet, ни sink там не ставятся.
112
175
  if (jsonOpt) {
113
176
  jsonMode = true;
114
177
  getDefaultChannel().setQuiet(true);
115
178
  }
116
179
  const jsonSink = jsonOpt ? new JsonOutputSink(defaultOutputBus) : undefined;
117
180
  const prompt = program.args.join(" ");
118
- const { agent, config, baseDir, legacyDetected } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete, reasoningLevel);
181
+ const mmaDir = globalMmaDir();
182
+ const { hasDomainFiles } = await import("../config/domains");
183
+ const virgin = !existsSync(join(mmaDir, "config.json")) && !hasDomainFiles(mmaDir);
184
+ const { agent, config, baseDir, legacyDetected, contextProbe } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete, reasoningLevel, contextLog);
185
+ if (verboseOpt)
186
+ config.ui.verbosity = "verbose";
187
+ applyLogVisibility(verboseOpt || config.ui.verbose || config.ui.verbosity === "verbose");
119
188
  if (legacyDetected) {
120
189
  getDefaultChannel().writeLine(pc.yellow(` ${t("config.legacy_hint")}`), "stderr");
121
190
  }
191
+ if (virgin && !jsonOpt) {
192
+ getDefaultChannel().writeLine(pc.yellow(` ${t("cli.first_run_oneshot")}`), "stderr");
193
+ }
194
+ // Расхождение загруженного и настроенного контекста показываем и в one-shot
195
+ // (раньше только Repl.start() рендерил). Под --json скипаем.
196
+ if (contextProbe && !jsonOpt) {
197
+ try {
198
+ const probe = await contextProbe;
199
+ if (probe) {
200
+ if (probe.actual < config.contextWindow) {
201
+ getDefaultChannel().writeLine(pc.yellow(t("repl.context_probe_small", {
202
+ model: probe.model,
203
+ actual: String(probe.actual),
204
+ configured: String(config.contextWindow),
205
+ })));
206
+ }
207
+ else if (probe.actual > config.contextWindow) {
208
+ getDefaultChannel().writeLine(pc.dim(t("repl.context_probe_big", { model: probe.model, actual: String(probe.actual) })));
209
+ }
210
+ }
211
+ }
212
+ catch {
213
+ // best-effort.
214
+ }
215
+ }
122
216
  const updater = exitOnComplete ? undefined : startAutoUpdate(config);
123
217
  if (jsonMode) {
124
218
  let result;
@@ -126,9 +220,9 @@ async function main() {
126
220
  result = await agent.run(prompt);
127
221
  }
128
222
  catch (err) {
129
- // --json must never emit a raw stack trace: an AbortError or a
130
- // crashing tool/plugin still yields a valid machine-readable result,
131
- // and shutdown/waitForIdle still run.
223
+ // --json не эмитит сырые стеки никогда: и AbortError, и рухнувший
224
+ // тул/плагин дают валидный машиночитаемый результат; shutdown/waitForIdle
225
+ // всё равно отрабатывают.
132
226
  const message = errMsg(err);
133
227
  agent.shutdown();
134
228
  const diagnostics = jsonSink?.diagnostics() ?? [];
@@ -144,12 +238,13 @@ async function main() {
144
238
  await updater?.waitForIdle(10_000);
145
239
  process.exit(result.success ? 0 : 1);
146
240
  }
147
- // TODO(output): one-shot runs don't surface the context-probe warning
148
- // (only Repl.start() renders it). Surface it here when bootstrap exposes
149
- // the probe result to this branch.
241
+ // TODO(output): one-shot прогоны не показывают варнинг контекст-пробника
242
+ // (рендерит только Repl.start()). Показать здесь, когда bootstrap отдаст
243
+ // результат пробника в эту ветку.
150
244
  const renderer = new Renderer({
151
245
  spinner: config.ui?.spinner ?? true,
152
246
  baseDir,
247
+ verbosity: resolveVerbosity(config.ui),
153
248
  });
154
249
  renderer.showLoader();
155
250
  let result;
@@ -168,11 +263,11 @@ async function main() {
168
263
  else {
169
264
  renderer.thinkingEnd();
170
265
  }
171
- });
266
+ }, (reasoning) => renderer.reasoning(reasoning));
172
267
  }
173
268
  catch (err) {
174
- // A throw from the agent loop must not skip shutdown/updater or dump a
175
- // bare stack — surface it as a clean error result.
269
+ // Throw из цикла агента не должен скипать shutdown/updater или дампить
270
+ // голый стек: показываем как чистый error-результат.
176
271
  result = {
177
272
  success: false,
178
273
  text: "",
@@ -190,7 +285,11 @@ async function main() {
190
285
  process.exit(exitCode);
191
286
  }
192
287
  else {
193
- const mmaDir = process.env.MMA_CONFIG_DIR || join(homedir(), ".mma");
288
+ if (onboardingStart === "meet")
289
+ process.env[MMA_ENV.START_MEET] = "1";
290
+ if (onboardingStart === "init")
291
+ process.env[MMA_ENV.START_INIT] = "1";
292
+ const mmaDir = globalMmaDir();
194
293
  const legacyConfigPath = join(mmaDir, "config.json");
195
294
  let hasAnyConfig = existsSync(legacyConfigPath);
196
295
  if (!hasAnyConfig) {
@@ -198,38 +297,43 @@ async function main() {
198
297
  const { hasDomainFiles } = await import("../config/domains");
199
298
  hasAnyConfig = hasDomainFiles(mmaDir);
200
299
  }
201
- catch { }
300
+ catch {
301
+ // Пробник доменов best-effort: отсутствующий/битый модуль не блокирует
302
+ // CLI. Фолбэк — проверка legacy config.json выше.
303
+ }
202
304
  }
203
305
  const projectConfigPath = projectDir ? join(projectDir, ".mmrc") : join(process.cwd(), ".mmrc");
204
- // First run: collect settings, persist them, then RE-EXEC the CLI in a fresh
205
- // process and exit. The wizard and the REPL must not share a process: on
206
- // Bun/Windows the raw-mode LineEditor only receives keypresses when it is
207
- // the first consumer of stdin, and reusing one editor across
208
- // wizard → bootstrap → REPL leaks prompt/frame state. The relaunched
209
- // process sees the saved config, skips the wizard, and creates its editor
210
- // first thing. `MMA_POST_SETUP=1` guards against a re-run loop.
211
- if (!hasAnyConfig && !exitOnComplete && process.env.MMA_POST_SETUP !== "1") {
212
- getDefaultChannel().writeLine("\n " + t("cli.first_run") + "\n");
306
+ // Первый запуск: собираем настройки, персистим, затем ПЕРЕИСПОЛНЯЕМ CLI в свежем
307
+ // процессе и выходим. Визард и REPL не делят процесс: на Bun/Windows raw-режимный
308
+ // LineEditor получает keypress, только будучи первым потребителем stdin, а
309
+ // переиспользование одного редактора через wizard → bootstrap → REPL протекает
310
+ // состоянием промпта/кадра. Перезапущенный процесс видит сохранённый конфиг,
311
+ // скипает визард и создаёт редактор первым делом. `MMA_POST_SETUP=1` сторожит
312
+ // от петли перезапуска.
313
+ if (!hasAnyConfig && !exitOnComplete && readEnv("POST_SETUP") !== "1") {
314
+ getDefaultChannel().writeLine(`\n ${t("cli.first_run")}\n`);
213
315
  const answers = await runSetup();
214
316
  const { config } = loadConfig({ configDir: mmaDir, projectConfigPath });
215
- // Preserve the CLI --reasoning override (bootstrap in the fresh process
216
- // would apply it too, but persist it now so the child reads the final
217
- // config).
317
+ // Сохраняем CLI-оверрайд --reasoning (bootstrap в свежем процессе применил бы
318
+ // его тоже, но персистим сейчас, чтобы ребёнок прочитал финальный конфиг).
218
319
  applyReasoningCliOverride(config, reasoningLevel);
219
320
  applyAnswersToConfig(config, answers);
220
321
  saveConfig(config, legacyConfigPath, dirname(legacyConfigPath));
221
322
  getDefaultChannel().writeLine(pc.dim(` ${t("cli.setup_saved_restart")}`));
222
323
  relaunchCli();
223
324
  }
224
- const { agent, config, sessionManager, skillsModule, pluginManager, execModule, configDir, baseDir, logger, envReport, contextProbe, } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete, reasoningLevel);
325
+ const { agent, config, sessionManager, skillsModule, pluginManager, execModule, configDir, baseDir, logger, envReport, contextProbe, } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete, reasoningLevel, contextLog);
326
+ if (verboseOpt)
327
+ config.ui.verbosity = "verbose";
328
+ applyLogVisibility(verboseOpt || config.ui.verbose || config.ui.verbosity === "verbose");
225
329
  const repl = new Repl(agent, config, sessionManager, skillsModule, pluginManager, configDir, baseDir, noAgentsMd, logger, true, envReport, undefined, execModule, contextProbe);
226
330
  startAutoUpdate(config);
227
331
  await repl.start();
228
332
  }
229
333
  }
230
334
  main().catch((err) => {
231
- // A throw before/during bootstrap would otherwise leave `--json` callers with
232
- // empty stdout; emit a valid failure document instead of a human stack.
335
+ // Throw до/во время bootstrap иначе оставил бы `--json`-вызывающих с пустым
336
+ // stdout; эмитим валидный failure-документ вместо человеческого стека.
233
337
  if (jsonMode) {
234
338
  writeMachineJson(buildJsonError(errMsg(err)));
235
339
  }
@@ -238,4 +342,5 @@ main().catch((err) => {
238
342
  }
239
343
  process.exit(1);
240
344
  });
345
+ /** Точка входа CLI (диспатч веток + топ-уровневый catch для `--json`). */
241
346
  export { main };