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
@@ -0,0 +1,584 @@
1
+ import { DEFAULTS } from "./defaults";
2
+ import { DEFAULT_SECURITY_CONFIG } from "./security";
3
+ import { setBudgetShare } from "./budget";
4
+ import { readMmaVersion } from "../core/version";
5
+ import { EXTRA_DEFS } from "./registry-extra";
6
+ /** Допустимые уровни reasoning. */
7
+ export const REASONING_LEVELS = [
8
+ "auto",
9
+ "default",
10
+ "none",
11
+ "low",
12
+ "medium",
13
+ "high",
14
+ "max",
15
+ ];
16
+ /** Допустимые уровни лога. */
17
+ export const LOG_LEVELS = ["silent", "error", "warn", "info", "debug"];
18
+ /** Допустимые уровни болтливости. */
19
+ export const VERBOSITY_LEVELS = ["quiet", "normal", "verbose"];
20
+ /** Допустимые локали. */
21
+ export const LOCALES = ["en", "ru"];
22
+ const MIN_SHARE = 0.05;
23
+ const MAX_SHARE = 0.9;
24
+ const MAX_COMBINED = 0.95;
25
+ function shareField(key, canonical) {
26
+ const field = key === "system" ? "systemPrompt" : "responseReserve";
27
+ const other = key === "system" ? "responseReserve" : "systemPrompt";
28
+ return {
29
+ key: canonical,
30
+ aliases: [`context.${key}`],
31
+ domain: "budget",
32
+ valueType: "share",
33
+ min: MIN_SHARE,
34
+ max: MAX_SHARE,
35
+ step: 0.01,
36
+ reconfigure: true,
37
+ get: (c) => c.contextBudget[field],
38
+ set: (c, v) => setBudgetShare(c, key, v),
39
+ extraValidate: (c, v) => {
40
+ const n = v;
41
+ const total = n + c.contextBudget[other];
42
+ return total > MAX_COMBINED ? "combined" : null;
43
+ },
44
+ };
45
+ }
46
+ function securityToggle(field, canonical) {
47
+ return {
48
+ key: canonical,
49
+ aliases: [],
50
+ domain: "security",
51
+ valueType: "bool",
52
+ // Тулы читают `config.security` живьём; пересборка агента не нужна. Шифрование
53
+ // сессии снапшотится в стор на bootstrap, так что полный эффект — только со
54
+ // следующего запуска: reconfigure его всё равно не пересобрал бы.
55
+ reconfigure: false,
56
+ get: (c) => {
57
+ const sec = c.security;
58
+ if (!sec)
59
+ return false;
60
+ return field === "enabled" ? sec.enabled : sec[field].enabled;
61
+ },
62
+ set: (c, v) => {
63
+ if (!c.security)
64
+ c.security = structuredClone(DEFAULT_SECURITY_CONFIG);
65
+ if (field === "enabled")
66
+ c.security.enabled = v;
67
+ else
68
+ c.security[field].enabled = v;
69
+ },
70
+ };
71
+ }
72
+ const DEFINITIONS = [
73
+ {
74
+ key: "model",
75
+ aliases: [],
76
+ domain: "agent",
77
+ valueType: "string",
78
+ reconfigure: true,
79
+ get: (c) => c.model,
80
+ set: (c, v) => {
81
+ c.model = String(v);
82
+ },
83
+ },
84
+ {
85
+ key: "provider.active",
86
+ aliases: [],
87
+ domain: "provider",
88
+ valueType: "string",
89
+ reconfigure: true,
90
+ get: (c) => c.provider.active ?? c.provider.type,
91
+ set: (c, v) => {
92
+ c.provider.active = String(v);
93
+ },
94
+ extraValidate: (c, v) => {
95
+ const entries = c.provider.entries ?? [];
96
+ if (entries.length === 0)
97
+ return null;
98
+ const name = String(v);
99
+ const found = entries.some((e) => e.label === name || e.type === name);
100
+ return found ? null : "invalid";
101
+ },
102
+ },
103
+ {
104
+ key: "contextWindow",
105
+ aliases: ["context.window"],
106
+ domain: "budget",
107
+ valueType: "int",
108
+ min: 1024,
109
+ step: 1024,
110
+ reconfigure: true,
111
+ get: (c) => c.contextWindow,
112
+ set: (c, v) => {
113
+ c.contextWindow = v;
114
+ },
115
+ },
116
+ shareField("system", "contextBudget.systemPrompt"),
117
+ shareField("reserve", "contextBudget.responseReserve"),
118
+ {
119
+ key: "showReasoning",
120
+ aliases: ["reasoning.show"],
121
+ domain: "reasoning",
122
+ valueType: "bool",
123
+ reconfigure: false,
124
+ get: (c) => c.showReasoning,
125
+ set: (c, v) => {
126
+ c.showReasoning = v;
127
+ },
128
+ },
129
+ {
130
+ key: "reasoning.mode",
131
+ aliases: ["reasoning.level"],
132
+ domain: "reasoning",
133
+ valueType: "enum",
134
+ enumValues: REASONING_LEVELS,
135
+ reconfigure: true,
136
+ get: (c) => c.reasoning?.mode ?? "auto",
137
+ set: (c, v) => {
138
+ const base = c.reasoning ?? structuredClone(DEFAULTS.reasoning);
139
+ c.reasoning = { ...base, mode: v };
140
+ },
141
+ },
142
+ {
143
+ key: "ui.verbosity",
144
+ aliases: ["verbosity"],
145
+ domain: "ui",
146
+ valueType: "enum",
147
+ enumValues: VERBOSITY_LEVELS,
148
+ reconfigure: false,
149
+ get: (c) => c.ui.verbosity ?? (c.ui.verbose ? "verbose" : "quiet"),
150
+ set: (c, v) => {
151
+ c.ui.verbosity = v;
152
+ },
153
+ },
154
+ {
155
+ key: "maxToolIterations",
156
+ aliases: [],
157
+ domain: "agent",
158
+ valueType: "int",
159
+ min: 1,
160
+ step: 1,
161
+ reconfigure: false,
162
+ get: (c) => c.maxToolIterations,
163
+ set: (c, v) => {
164
+ c.maxToolIterations = v;
165
+ },
166
+ },
167
+ {
168
+ key: "stuckThreshold",
169
+ aliases: [],
170
+ domain: "agent",
171
+ valueType: "int",
172
+ min: 1,
173
+ step: 1,
174
+ reconfigure: false,
175
+ get: (c) => c.stuckThreshold,
176
+ set: (c, v) => {
177
+ c.stuckThreshold = v;
178
+ },
179
+ },
180
+ {
181
+ key: "moe.enabled",
182
+ aliases: [],
183
+ domain: "agent",
184
+ valueType: "bool",
185
+ reconfigure: true,
186
+ get: (c) => c.moe?.enabled ?? DEFAULTS.moe.enabled,
187
+ set: (c, v) => {
188
+ c.moe = { ...(c.moe ?? DEFAULTS.moe), enabled: v };
189
+ },
190
+ },
191
+ {
192
+ key: "moe.maxReplanCycles",
193
+ aliases: [],
194
+ domain: "agent",
195
+ valueType: "int",
196
+ min: 0,
197
+ max: 10,
198
+ step: 1,
199
+ reconfigure: true,
200
+ get: (c) => c.moe?.maxReplanCycles ?? DEFAULTS.moe.maxReplanCycles,
201
+ set: (c, v) => {
202
+ c.moe = { ...(c.moe ?? DEFAULTS.moe), maxReplanCycles: v };
203
+ },
204
+ },
205
+ {
206
+ key: "critic.enabled",
207
+ aliases: [],
208
+ domain: "agent",
209
+ valueType: "bool",
210
+ reconfigure: true,
211
+ get: (c) => c.critic?.enabled ?? DEFAULTS.critic.enabled,
212
+ set: (c, v) => {
213
+ c.critic = { ...(c.critic ?? DEFAULTS.critic), enabled: v };
214
+ },
215
+ },
216
+ {
217
+ key: "critic.maxCalls",
218
+ aliases: [],
219
+ domain: "agent",
220
+ valueType: "int",
221
+ min: 0,
222
+ max: 20,
223
+ step: 1,
224
+ reconfigure: true,
225
+ get: (c) => c.critic?.maxCalls ?? DEFAULTS.critic.maxCalls,
226
+ set: (c, v) => {
227
+ c.critic = { ...(c.critic ?? DEFAULTS.critic), maxCalls: v };
228
+ },
229
+ },
230
+ {
231
+ key: "critic.maxRepairCycles",
232
+ aliases: [],
233
+ domain: "agent",
234
+ valueType: "int",
235
+ min: 0,
236
+ max: 5,
237
+ step: 1,
238
+ reconfigure: true,
239
+ get: (c) => c.critic?.maxRepairCycles ?? DEFAULTS.critic.maxRepairCycles,
240
+ set: (c, v) => {
241
+ c.critic = { ...(c.critic ?? DEFAULTS.critic), maxRepairCycles: v };
242
+ },
243
+ },
244
+ {
245
+ key: "critic.timeoutMs",
246
+ aliases: [],
247
+ domain: "agent",
248
+ valueType: "int",
249
+ min: 1000,
250
+ max: 120000,
251
+ step: 1000,
252
+ reconfigure: true,
253
+ get: (c) => c.critic?.timeoutMs ?? DEFAULTS.critic.timeoutMs,
254
+ set: (c, v) => {
255
+ c.critic = { ...(c.critic ?? DEFAULTS.critic), timeoutMs: v };
256
+ },
257
+ },
258
+ {
259
+ key: "critic.model",
260
+ aliases: [],
261
+ domain: "agent",
262
+ valueType: "string",
263
+ reconfigure: true,
264
+ get: (c) => c.critic?.model ?? "",
265
+ set: (c, v) => {
266
+ const s = String(v).trim();
267
+ c.critic = { ...(c.critic ?? DEFAULTS.critic), model: s ? s : undefined };
268
+ },
269
+ },
270
+ {
271
+ key: "critic.tools",
272
+ aliases: [],
273
+ domain: "agent",
274
+ valueType: "bool",
275
+ reconfigure: true,
276
+ get: (c) => c.critic?.tools ?? DEFAULTS.critic.tools,
277
+ set: (c, v) => {
278
+ c.critic = { ...(c.critic ?? DEFAULTS.critic), tools: v };
279
+ },
280
+ },
281
+ {
282
+ key: "critic.provider",
283
+ aliases: [],
284
+ domain: "agent",
285
+ valueType: "json",
286
+ reconfigure: true,
287
+ get: (c) => c.critic?.provider ?? {},
288
+ set: (c, v) => {
289
+ const rec = v;
290
+ c.critic = {
291
+ ...(c.critic ?? DEFAULTS.critic),
292
+ provider: Object.keys(rec).length > 0
293
+ ? rec
294
+ : undefined,
295
+ };
296
+ },
297
+ extraValidate: (_c, v) => {
298
+ if (!v || typeof v !== "object" || Array.isArray(v))
299
+ return "invalid";
300
+ const rec = v;
301
+ if (rec.type !== undefined && typeof rec.type !== "string")
302
+ return "invalid";
303
+ if (rec.baseUrl !== undefined && typeof rec.baseUrl !== "string")
304
+ return "invalid";
305
+ if (rec.active !== undefined && typeof rec.active !== "string")
306
+ return "invalid";
307
+ if (rec.entries !== undefined && !Array.isArray(rec.entries))
308
+ return "invalid";
309
+ return null;
310
+ },
311
+ },
312
+ {
313
+ key: "logLevel",
314
+ aliases: [],
315
+ domain: "agent",
316
+ valueType: "enum",
317
+ enumValues: LOG_LEVELS,
318
+ reconfigure: false,
319
+ get: (c) => c.logLevel,
320
+ set: (c, v) => {
321
+ c.logLevel = String(v);
322
+ },
323
+ },
324
+ {
325
+ key: "locale",
326
+ aliases: [],
327
+ domain: "i18n",
328
+ valueType: "enum",
329
+ enumValues: LOCALES,
330
+ reconfigure: false,
331
+ get: (c) => c.locale,
332
+ set: (c, v) => {
333
+ c.locale = String(v);
334
+ },
335
+ },
336
+ {
337
+ key: "version",
338
+ aliases: [],
339
+ domain: "agent",
340
+ valueType: "string",
341
+ reconfigure: false,
342
+ readOnly: true,
343
+ // Версия *установленного пакета*, а не `config.version` (то — версия схемы
344
+ // конфига для детекта миграций, с релизом не совпадает никогда). Читается
345
+ // в момент вызова, так что следует за обновлениями без рестарта.
346
+ get: () => readMmaVersion(),
347
+ },
348
+ securityToggle("enabled", "security.enabled"),
349
+ securityToggle("bash", "security.bash.enabled"),
350
+ {
351
+ key: "security.bash.blockDangerousFlags",
352
+ aliases: [],
353
+ domain: "security",
354
+ valueType: "bool",
355
+ reconfigure: false,
356
+ get: (c) => c.security?.bash.blockDangerousFlags ?? true,
357
+ set: (c, v) => {
358
+ if (!c.security)
359
+ c.security = structuredClone(DEFAULT_SECURITY_CONFIG);
360
+ c.security.bash.blockDangerousFlags = v;
361
+ },
362
+ },
363
+ securityToggle("paths", "security.paths.enabled"),
364
+ securityToggle("contentScan", "security.contentScan.enabled"),
365
+ securityToggle("sessionEncryption", "security.sessionEncryption.enabled"),
366
+ securityToggle("network", "security.network.enabled"),
367
+ ...EXTRA_DEFS,
368
+ ];
369
+ const BY_NAME = new Map();
370
+ for (const def of DEFINITIONS) {
371
+ BY_NAME.set(def.key, def);
372
+ for (const alias of def.aliases)
373
+ BY_NAME.set(alias, def);
374
+ }
375
+ /** Резолвит ключ/алиас в деф. Нет такого — null. */
376
+ export function resolveConfigKey(name) {
377
+ return BY_NAME.get(name) ?? null;
378
+ }
379
+ /** Все дефы реестра (идут и в комплитер без правок). */
380
+ export function configDefs() {
381
+ return DEFINITIONS;
382
+ }
383
+ /** Все канонические ключи (для дампа), в порядке реестра. */
384
+ export function canonicalKeys() {
385
+ return DEFINITIONS.map((d) => d.key);
386
+ }
387
+ /**
388
+ * Ключи канонической группы по префиксу (напр. "contextBudget" → systemPrompt,
389
+ * responseReserve). Матчит ровно `prefix.`, так что `/config contextBudget`
390
+ * листает обе доли.
391
+ */
392
+ export function keysForGroup(prefix) {
393
+ return DEFINITIONS.filter((d) => d.key.startsWith(`${prefix}.`));
394
+ }
395
+ /** Канонические + алиасные имена, для автокомплита. */
396
+ export function allConfigNames() {
397
+ const out = [];
398
+ for (const def of DEFINITIONS) {
399
+ out.push({ name: def.key, def, alias: false });
400
+ for (const a of def.aliases)
401
+ out.push({ name: a, def, alias: true });
402
+ }
403
+ return out;
404
+ }
405
+ /** Человекочитаемое форматирование значения (bool → on/off, массивы через запятую). */
406
+ export function formatConfigValue(value) {
407
+ if (typeof value === "boolean")
408
+ return value ? "on" : "off";
409
+ if (Array.isArray(value))
410
+ return value.join(", ");
411
+ if (typeof value === "object" && value !== null)
412
+ return JSON.stringify(value);
413
+ return String(value);
414
+ }
415
+ function parseBool(raw) {
416
+ const v = raw.trim().toLowerCase();
417
+ if (["on", "true", "1", "yes", "y", "enable", "enabled"].includes(v))
418
+ return { ok: true, value: true };
419
+ if (["off", "false", "0", "no", "n", "disable", "disabled"].includes(v))
420
+ return { ok: true, value: false };
421
+ return { ok: false, reason: "invalid" };
422
+ }
423
+ /** Парсит сырую строку по типу ключа (bool/enum/int/share/list/json). */
424
+ export function parseConfigValue(def, raw) {
425
+ const trimmed = raw.trim();
426
+ switch (def.valueType) {
427
+ case "string":
428
+ return trimmed.length > 0 ? { ok: true, value: trimmed } : { ok: false, reason: "invalid" };
429
+ case "bool":
430
+ return parseBool(trimmed);
431
+ case "enum": {
432
+ const v = trimmed.toLowerCase();
433
+ if (def.enumValues && !def.enumValues.includes(v))
434
+ return { ok: false, reason: "invalid" };
435
+ return { ok: true, value: v };
436
+ }
437
+ case "int": {
438
+ if (!/^-?\d+$/.test(trimmed))
439
+ return { ok: false, reason: "invalid" };
440
+ const n = Number(trimmed);
441
+ if (!Number.isFinite(n))
442
+ return { ok: false, reason: "invalid" };
443
+ if (def.min !== undefined && n < def.min)
444
+ return { ok: false, reason: "invalid" };
445
+ if (def.max !== undefined && n > def.max)
446
+ return { ok: false, reason: "invalid" };
447
+ return { ok: true, value: n };
448
+ }
449
+ case "share": {
450
+ // Доля (0.1) или проценты (10%).
451
+ const isPct = trimmed.endsWith("%");
452
+ const body = isPct ? trimmed.slice(0, -1).trim() : trimmed;
453
+ if (!/^-?\d+(\.\d+)?$/.test(body))
454
+ return { ok: false, reason: "invalid" };
455
+ let n = Number(body);
456
+ if (isPct)
457
+ n = n / 100;
458
+ if (!Number.isFinite(n) || n < MIN_SHARE || n > MAX_SHARE)
459
+ return { ok: false, reason: "invalid" };
460
+ return { ok: true, value: n };
461
+ }
462
+ case "list": {
463
+ if (trimmed.length === 0)
464
+ return { ok: true, value: [] };
465
+ // Структурные редакторы постят JSON-массив (значения могут содержать запятые,
466
+ // напр. regex вида `a{1,3}`); REPL держит синтаксис через запятую.
467
+ if (trimmed.startsWith("[")) {
468
+ try {
469
+ const parsed = JSON.parse(trimmed);
470
+ if (Array.isArray(parsed) && parsed.every((x) => typeof x === "string")) {
471
+ return { ok: true, value: parsed };
472
+ }
473
+ }
474
+ catch {
475
+ /* fall through to comma splitting */
476
+ }
477
+ }
478
+ const items = trimmed.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
479
+ return { ok: true, value: items };
480
+ }
481
+ case "json": {
482
+ if (trimmed.length > 20000)
483
+ return { ok: false, reason: "invalid" };
484
+ try {
485
+ return { ok: true, value: JSON.parse(trimmed) };
486
+ }
487
+ catch {
488
+ return { ok: false, reason: "invalid" };
489
+ }
490
+ }
491
+ }
492
+ }
493
+ /** Читает ключ конфига по имени/алиасу. */
494
+ export function getConfigValue(config, name) {
495
+ const def = resolveConfigKey(name);
496
+ if (!def)
497
+ return { ok: false, reason: "unknown-key", input: name };
498
+ const value = def.get(config);
499
+ return { ok: true, key: def.key, def, value, display: formatConfigValue(value) };
500
+ }
501
+ /**
502
+ * Держит `provider.models` (последняя модель каждого провайдера) в синхроне. Запись
503
+ * `model` запоминается под активным провайдером; смена `provider.active`
504
+ * восстанавливает запомненную модель провайдера, чтобы свитч молча не оставлял
505
+ * модель, которую новый бэкенд не обслуживает. Заодно зеркалит легаси-плоские
506
+ * поля (`type`/`baseUrl`/`apiKey`) из активной записи — иначе они протухают
507
+ * после hot-swap, а баннер и внеполосные читатели плоских полей врут.
508
+ */
509
+ /**
510
+ * Зеркалит легаси-плоские поля (`type`/`baseUrl`/`apiKey`) из активной записи:
511
+ * после hot-swap `/provider use` они протухают, а баннер и внеполосные читатели
512
+ * плоских полей врут.
513
+ */
514
+ function mirrorActiveEntryFields(provider, activeName) {
515
+ const entry = (provider.entries ?? []).find((e) => e.label === activeName || e.type === activeName);
516
+ if (!entry)
517
+ return;
518
+ provider.type = entry.type;
519
+ provider.baseUrl = entry.baseUrl;
520
+ provider.apiKey = entry.apiKey;
521
+ }
522
+ function applyProviderModelMemory(config, key, value) {
523
+ const provider = config.provider;
524
+ const activeName = provider.active ?? provider.type;
525
+ if (key === "model") {
526
+ if (!activeName)
527
+ return;
528
+ provider.models = { ...(provider.models ?? {}), [activeName]: String(value) };
529
+ return;
530
+ }
531
+ if (key === "provider.active") {
532
+ const remembered = provider.models?.[String(value)];
533
+ if (remembered)
534
+ config.model = remembered;
535
+ mirrorActiveEntryFields(provider, String(value));
536
+ }
537
+ }
538
+ /** Пишет ключ: резолв → парсинг → валидация → set + память моделей провайдера. */
539
+ export function setConfigValue(config, name, raw) {
540
+ const def = resolveConfigKey(name);
541
+ if (!def)
542
+ return { ok: false, reason: "unknown-key", input: name };
543
+ if (def.readOnly)
544
+ return { ok: false, reason: "read-only", input: name, key: def.key, def };
545
+ const parsed = parseConfigValue(def, raw);
546
+ if (!parsed.ok)
547
+ return { ok: false, reason: "invalid-value", input: name, key: def.key, def };
548
+ const extra = def.extraValidate?.(config, parsed.value);
549
+ if (extra)
550
+ return { ok: false, reason: extra, input: name, key: def.key, def };
551
+ def.set(config, parsed.value);
552
+ applyProviderModelMemory(config, def.key, parsed.value);
553
+ return {
554
+ ok: true,
555
+ key: def.key,
556
+ def,
557
+ value: parsed.value,
558
+ display: formatConfigValue(parsed.value),
559
+ reconfigure: def.reconfigure,
560
+ reasoningChanged: def.key === "reasoning.mode",
561
+ };
562
+ }
563
+ /** Проверка известности ключа (для подсказок). */
564
+ export function isKnownConfigKey(name) {
565
+ return BY_NAME.has(name);
566
+ }
567
+ /**
568
+ * Снимает текущие значения всех канонических ключей. На старте REPL — "boot-снапшот",
569
+ * чтобы `/config reset` откатывал изменения сессии (а не прыгал к дефолтам схемы,
570
+ * неоднозначным для полей вида `provider.active`).
571
+ */
572
+ export function captureConfigSnapshot(config) {
573
+ const snapshot = new Map();
574
+ for (const def of DEFINITIONS) {
575
+ try {
576
+ snapshot.set(def.key, structuredClone(def.get(config)));
577
+ }
578
+ catch {
579
+ // Частичные/мок-конфиги (тесты) могут не иметь поля — скипаем его, а не весь
580
+ // снапшот. Реальные конфиги полны.
581
+ }
582
+ }
583
+ return snapshot;
584
+ }