micro-models-agent 2.11.0 → 2.13.1

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 (356) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/assets/app.js +22 -2
  3. package/dist/assets/index.html +39 -9
  4. package/dist/assets/js/dom.js +15 -0
  5. package/dist/assets/js/feed.js +129 -10
  6. package/dist/assets/js/sidebar.js +512 -0
  7. package/dist/assets/js/tabs.js +30 -5
  8. package/dist/assets/setup.js +267 -8
  9. package/dist/assets/styles.css +168 -3
  10. package/dist/cli/cache-line.js +1 -0
  11. package/dist/cli/command-suggest.js +5 -4
  12. package/dist/cli/commands.js +231 -122
  13. package/dist/cli/completer.js +132 -31
  14. package/dist/cli/index.js +1 -0
  15. package/dist/cli/json-payload.js +4 -4
  16. package/dist/cli/main.js +166 -61
  17. package/dist/cli/onboarding-commands.js +126 -0
  18. package/dist/cli/plugin-commands.js +2 -1
  19. package/dist/cli/relaunch.js +16 -13
  20. package/dist/cli/repl-commands-lsp.js +75 -0
  21. package/dist/cli/repl-commands-skills.js +105 -0
  22. package/dist/cli/repl-commands.js +589 -266
  23. package/dist/cli/repl.js +436 -177
  24. package/dist/cli/run-result.js +5 -6
  25. package/dist/cli/security-commands.js +37 -28
  26. package/dist/cli/setup-order.js +4 -55
  27. package/dist/cli/setup-prompt.js +3 -2
  28. package/dist/cli/setup.js +27 -107
  29. package/dist/cli/web-command.js +98 -0
  30. package/dist/config/budget.js +5 -5
  31. package/dist/config/config.js +103 -96
  32. package/dist/config/defaults.js +38 -8
  33. package/dist/config/domains.js +24 -27
  34. package/dist/config/env.js +46 -0
  35. package/dist/config/experts.js +2 -0
  36. package/dist/config/index.js +1 -0
  37. package/dist/config/paths.js +56 -0
  38. package/dist/config/redact.js +44 -0
  39. package/dist/config/registry-extra.js +334 -0
  40. package/dist/config/registry.js +584 -0
  41. package/dist/config/security.js +35 -36
  42. package/dist/config/timeouts.js +74 -0
  43. package/dist/config/utils.js +16 -15
  44. package/dist/core/agent/artifact-progress.js +59 -0
  45. package/dist/core/agent/artifact-resolve.js +79 -0
  46. package/dist/core/agent/audit-gate.js +7 -3
  47. package/dist/core/agent/compaction.js +2 -2
  48. package/dist/core/agent/constants.js +33 -4
  49. package/dist/core/agent/context-log.js +454 -0
  50. package/dist/core/agent/context-renderer.js +5 -0
  51. package/dist/core/agent/critic-gate.js +132 -0
  52. package/dist/core/agent/hallucination-gate.js +148 -38
  53. package/dist/core/agent/loop-state.js +15 -0
  54. package/dist/core/agent/prefix-monitor.js +1 -1
  55. package/dist/core/agent/reasoning-resolver.js +10 -1
  56. package/dist/core/agent/token-tracker.js +7 -4
  57. package/dist/core/agent/tool-batch.js +93 -18
  58. package/dist/core/agent/tool-images.js +18 -0
  59. package/dist/core/agent/tool-output.js +65 -11
  60. package/dist/core/agent/tool-pairing.js +60 -0
  61. package/dist/core/agent-moe.js +25 -24
  62. package/dist/core/agent.js +429 -108
  63. package/dist/core/bootstrap/agent-phase.js +66 -0
  64. package/dist/core/bootstrap/config-phase.js +86 -0
  65. package/dist/core/bootstrap/modules-phase.js +269 -0
  66. package/dist/core/bootstrap/provider-phase.js +183 -0
  67. package/dist/core/bootstrap/session-phase.js +204 -0
  68. package/dist/core/bootstrap/state.js +94 -0
  69. package/dist/core/bootstrap/workspace-phase.js +115 -0
  70. package/dist/core/bootstrap.js +92 -660
  71. package/dist/core/crash-handler.js +17 -7
  72. package/dist/core/environment.js +37 -12
  73. package/dist/core/host-plan.js +43 -0
  74. package/dist/core/host.js +23 -0
  75. package/dist/core/index.js +1 -0
  76. package/dist/core/prompt-builder.js +17 -1
  77. package/dist/core/prompt-overflow.js +42 -43
  78. package/dist/core/session-logger.js +122 -30
  79. package/dist/core/system-prompt.js +117 -0
  80. package/dist/core/version.js +6 -4
  81. package/dist/core/web-host.js +34 -0
  82. package/dist/core/workspace.js +19 -15
  83. package/dist/i18n/en.json +89 -3
  84. package/dist/i18n/index.js +37 -3
  85. package/dist/i18n/ru.json +89 -3
  86. package/dist/index.js +7 -3
  87. package/dist/llm/image-utils.js +55 -64
  88. package/dist/llm/llm-errors.js +9 -0
  89. package/dist/llm/model-loader.js +10 -32
  90. package/dist/llm/models-dev.js +121 -0
  91. package/dist/llm/openai-compat.js +146 -73
  92. package/dist/llm/orchestrator.js +33 -11
  93. package/dist/llm/provider-budget.js +2 -2
  94. package/dist/llm/provider-context.js +233 -0
  95. package/dist/llm/provider.js +1 -1
  96. package/dist/llm/response.js +5 -0
  97. package/dist/llm/token-counter.js +27 -11
  98. package/dist/logger/app-logger.js +48 -22
  99. package/dist/logger/file-log.js +28 -19
  100. package/dist/logger/index.js +1 -0
  101. package/dist/main.js +888 -139
  102. package/dist/migration/backup.js +14 -3
  103. package/dist/migration/detect.js +12 -3
  104. package/dist/migration/index.js +1 -0
  105. package/dist/modules/artifacts/store.js +9 -8
  106. package/dist/modules/browser/actions.js +6 -0
  107. package/dist/modules/browser/bridge-client.js +14 -12
  108. package/dist/modules/browser/bridge-path.js +4 -4
  109. package/dist/modules/browser/console-buffer.js +37 -0
  110. package/dist/modules/browser/cookie-store.js +5 -0
  111. package/dist/modules/browser/driver-types.js +1 -0
  112. package/dist/modules/browser/driver.js +19 -11
  113. package/dist/modules/browser/index.js +3 -1
  114. package/dist/modules/browser/module.js +2 -1
  115. package/dist/modules/browser/session.js +10 -30
  116. package/dist/modules/browser/snapshot.js +19 -13
  117. package/dist/modules/browser/types.js +1 -0
  118. package/dist/modules/certification/cli.js +28 -20
  119. package/dist/modules/certification/fact-checker.js +9 -1
  120. package/dist/modules/certification/loader.js +9 -2
  121. package/dist/modules/certification/manifest.js +83 -21
  122. package/dist/modules/certification/runner.js +23 -13
  123. package/dist/modules/certification/scenarios.js +20 -20
  124. package/dist/modules/certification/syntax-scenarios.js +1 -2
  125. package/dist/modules/context/chunk-query.js +11 -9
  126. package/dist/modules/context/fact-extractor.js +37 -39
  127. package/dist/modules/context/index.js +1 -0
  128. package/dist/modules/context/manager.js +106 -80
  129. package/dist/modules/critic/client.js +176 -0
  130. package/dist/modules/critic/evidence.js +81 -0
  131. package/dist/modules/critic/provider.js +45 -0
  132. package/dist/modules/critic/tools.js +78 -0
  133. package/dist/modules/critic/types.js +1 -0
  134. package/dist/modules/execution/audit-runners.js +28 -34
  135. package/dist/modules/execution/auditor.js +53 -49
  136. package/dist/modules/execution/execution-plugin.js +142 -102
  137. package/dist/modules/execution/index.js +1 -1
  138. package/dist/modules/execution/input-from.js +37 -13
  139. package/dist/modules/execution/module.js +368 -191
  140. package/dist/modules/execution/moe-executor.js +53 -26
  141. package/dist/modules/execution/plan-actions.js +320 -202
  142. package/dist/modules/execution/plan-checks.js +35 -0
  143. package/dist/modules/execution/plan-coverage.js +36 -33
  144. package/dist/modules/execution/plan-steps.js +11 -3
  145. package/dist/modules/execution/plan-store.js +83 -17
  146. package/dist/modules/execution/plan-tool.js +89 -35
  147. package/dist/modules/execution/plan-validator.js +30 -10
  148. package/dist/modules/execution/planner.js +22 -13
  149. package/dist/modules/execution/stuck-detector.js +196 -93
  150. package/dist/modules/execution/tracker.js +22 -8
  151. package/dist/modules/execution/verifier.js +69 -48
  152. package/dist/modules/execution/windows-commands.js +12 -12
  153. package/dist/modules/hallucination/artifact-claim.js +93 -0
  154. package/dist/modules/hallucination/confidence.js +13 -11
  155. package/dist/modules/hallucination/consistency.js +10 -2
  156. package/dist/modules/hallucination/detector.js +10 -5
  157. package/dist/modules/hallucination/factual.js +43 -26
  158. package/dist/modules/hallucination/index.js +1 -0
  159. package/dist/modules/hallucination/js-identifiers.js +44 -45
  160. package/dist/modules/hallucination/llm-judge.js +17 -12
  161. package/dist/modules/hallucination/success-claim.js +59 -0
  162. package/dist/modules/indexer/cache.js +52 -4
  163. package/dist/modules/indexer/index.js +1 -0
  164. package/dist/modules/indexer/map-command.js +2 -4
  165. package/dist/modules/indexer/map-select.js +16 -16
  166. package/dist/modules/indexer/module.js +47 -12
  167. package/dist/modules/indexer/project-profile.js +8 -7
  168. package/dist/modules/indexer/symbols.js +15 -15
  169. package/dist/modules/indexer/walker.js +159 -29
  170. package/dist/modules/lsp/check-tool.js +7 -5
  171. package/dist/modules/lsp/client.js +39 -39
  172. package/dist/modules/lsp/command.js +17 -24
  173. package/dist/modules/lsp/config.js +12 -11
  174. package/dist/modules/lsp/index.js +1 -0
  175. package/dist/modules/lsp/module.js +48 -46
  176. package/dist/modules/lsp/probe.js +13 -14
  177. package/dist/modules/lsp/project-root.js +14 -17
  178. package/dist/modules/lsp/startup-check.js +18 -16
  179. package/dist/modules/mcp/client.js +59 -62
  180. package/dist/modules/mcp/index.js +1 -0
  181. package/dist/modules/mcp/module.js +66 -37
  182. package/dist/modules/mcp/registry.js +5 -0
  183. package/dist/modules/memory/index.js +1 -0
  184. package/dist/modules/memory/module.js +12 -8
  185. package/dist/modules/memory/search.js +4 -1
  186. package/dist/modules/memory/store.js +40 -2
  187. package/dist/modules/onboarding/init.js +47 -0
  188. package/dist/modules/onboarding/meet.js +30 -0
  189. package/dist/modules/onboarding/mode.js +30 -0
  190. package/dist/modules/onboarding/prompts.js +43 -0
  191. package/dist/modules/pipelines/engine.js +10 -0
  192. package/dist/modules/pipelines/index.js +1 -0
  193. package/dist/modules/pipelines/parser.js +4 -1
  194. package/dist/modules/pipelines/template.js +4 -0
  195. package/dist/modules/plugins/builtin/lint-on-write.js +80 -67
  196. package/dist/modules/plugins/builtin/notify.js +2 -0
  197. package/dist/modules/plugins/index.js +1 -0
  198. package/dist/modules/plugins/loader.js +18 -3
  199. package/dist/modules/plugins/manager.js +37 -17
  200. package/dist/modules/pricing/index.js +10 -11
  201. package/dist/modules/pricing/prices.js +12 -12
  202. package/dist/modules/processes/index.js +1 -0
  203. package/dist/modules/processes/kill-tree.js +27 -31
  204. package/dist/modules/processes/registry.js +44 -25
  205. package/dist/modules/processes/runner.js +4 -4
  206. package/dist/modules/providers/capabilities.js +28 -0
  207. package/dist/modules/providers/create.js +3 -4
  208. package/dist/modules/providers/factory.js +7 -7
  209. package/dist/modules/providers/fallback.js +12 -12
  210. package/dist/modules/providers/health.js +4 -4
  211. package/dist/modules/providers/manager.js +50 -19
  212. package/dist/modules/providers/naming.js +15 -0
  213. package/dist/modules/providers/preflight.js +71 -0
  214. package/dist/modules/providers/presets.js +39 -8
  215. package/dist/modules/providers/registry.js +7 -2
  216. package/dist/modules/reasoning/policy.js +8 -6
  217. package/dist/modules/reasoning/probe.js +30 -25
  218. package/dist/modules/security/audit-log.js +19 -36
  219. package/dist/modules/security/audit-notifier.js +35 -75
  220. package/dist/modules/security/command-validator.js +99 -51
  221. package/dist/modules/security/content-scanner.js +8 -8
  222. package/dist/modules/security/data-sanitizer.js +9 -16
  223. package/dist/modules/security/encryption.js +32 -52
  224. package/dist/modules/security/index.js +2 -1
  225. package/dist/modules/security/network-validator.js +120 -43
  226. package/dist/modules/security/path-validator.js +61 -46
  227. package/dist/modules/security/protected-paths.js +73 -0
  228. package/dist/modules/security/rate-limiter.js +17 -49
  229. package/dist/modules/security/security-policies.js +25 -57
  230. package/dist/modules/security/session-encryption.js +32 -71
  231. package/dist/modules/security/session-isolation.js +15 -28
  232. package/dist/modules/session/auto-name.js +63 -0
  233. package/dist/modules/session/export.js +98 -0
  234. package/dist/modules/session/index.js +1 -0
  235. package/dist/modules/session/manager.js +79 -28
  236. package/dist/modules/session/module.js +4 -3
  237. package/dist/modules/session/store.js +57 -20
  238. package/dist/modules/setup/answers.js +35 -0
  239. package/dist/modules/setup/apply.js +79 -0
  240. package/dist/modules/setup/discovery.js +72 -0
  241. package/dist/modules/skills/index.js +1 -0
  242. package/dist/modules/skills/loader.js +9 -1
  243. package/dist/modules/skills/module.js +11 -0
  244. package/dist/modules/updater/changelog-reader.js +15 -16
  245. package/dist/modules/updater/checker.js +9 -4
  246. package/dist/modules/updater/dev-detect.js +7 -6
  247. package/dist/modules/updater/index.js +1 -0
  248. package/dist/modules/updater/module.js +17 -15
  249. package/dist/modules/user-profile/compressor.js +2 -0
  250. package/dist/modules/user-profile/index.js +1 -0
  251. package/dist/modules/user-profile/profile.js +10 -1
  252. package/dist/modules/webui/answer-api.js +29 -0
  253. package/dist/modules/webui/assets.js +50 -0
  254. package/dist/modules/webui/body.js +21 -0
  255. package/dist/modules/webui/commands-settings.js +209 -0
  256. package/dist/modules/webui/commands-shared.js +60 -0
  257. package/dist/modules/webui/commands.js +174 -0
  258. package/dist/modules/webui/config-api.js +134 -0
  259. package/dist/modules/webui/file-api.js +202 -0
  260. package/dist/modules/webui/forward.js +159 -0
  261. package/dist/modules/webui/history-api.js +112 -0
  262. package/dist/modules/webui/host-state.js +60 -0
  263. package/dist/modules/webui/i18n-api.js +9 -0
  264. package/dist/modules/webui/limits.js +6 -0
  265. package/dist/modules/webui/log-forward.js +20 -0
  266. package/dist/modules/webui/memory-commands.js +64 -0
  267. package/dist/modules/webui/model-cache.js +18 -0
  268. package/dist/modules/webui/module.js +148 -0
  269. package/dist/modules/webui/persist.js +24 -0
  270. package/dist/modules/webui/prompt-io.js +97 -0
  271. package/dist/modules/webui/providers-api.js +337 -0
  272. package/dist/modules/webui/providers-view.js +56 -0
  273. package/dist/modules/webui/reasoning-view.js +15 -0
  274. package/dist/modules/webui/run-agent.js +81 -0
  275. package/dist/modules/webui/server.js +284 -0
  276. package/dist/modules/webui/sessions-api.js +178 -0
  277. package/dist/modules/webui/settings-api.js +561 -0
  278. package/dist/modules/webui/setup-api.js +201 -0
  279. package/dist/modules/webui/state.js +74 -0
  280. package/dist/modules/webui/util.js +261 -0
  281. package/dist/output/bus.js +7 -2
  282. package/dist/output/channel.js +80 -28
  283. package/dist/output/format.js +2 -1
  284. package/dist/output/index.js +1 -0
  285. package/dist/output/json-sink.js +5 -3
  286. package/dist/output/machine.js +4 -3
  287. package/dist/output/session-sink.js +4 -4
  288. package/dist/tools/approve.js +4 -0
  289. package/dist/tools/attach-image.js +5 -4
  290. package/dist/tools/auto-fixer.js +26 -44
  291. package/dist/tools/auto-tags.js +83 -0
  292. package/dist/tools/bash.js +193 -116
  293. package/dist/tools/browser.js +76 -31
  294. package/dist/tools/chunk-query.js +14 -6
  295. package/dist/tools/create-dir.js +9 -5
  296. package/dist/tools/delete-file.js +9 -5
  297. package/dist/tools/download-file.js +32 -7
  298. package/dist/tools/edit-file.js +52 -14
  299. package/dist/tools/enable-tools.js +6 -6
  300. package/dist/tools/executor.js +132 -27
  301. package/dist/tools/file-info.js +3 -1
  302. package/dist/tools/filter-tools.js +3 -3
  303. package/dist/tools/glob-tool.js +4 -1
  304. package/dist/tools/grep-tool.js +13 -10
  305. package/dist/tools/hidden-tools-block.js +6 -6
  306. package/dist/tools/index.js +16 -8
  307. package/dist/tools/list-dir.js +4 -2
  308. package/dist/tools/load-skill.js +7 -0
  309. package/dist/tools/mcp-call.js +15 -4
  310. package/dist/tools/meet-done.js +14 -0
  311. package/dist/tools/move-file.js +14 -7
  312. package/dist/tools/path-utils.js +29 -29
  313. package/dist/tools/pipeline-run.js +29 -7
  314. package/dist/tools/preview.js +1 -1
  315. package/dist/tools/process-ids.js +31 -0
  316. package/dist/tools/process-kill.js +9 -16
  317. package/dist/tools/process-list.js +1 -0
  318. package/dist/tools/process-log.js +11 -16
  319. package/dist/tools/process-wait.js +63 -0
  320. package/dist/tools/prompt-io.js +4 -3
  321. package/dist/tools/question.js +172 -25
  322. package/dist/tools/read-file.js +55 -34
  323. package/dist/tools/recall.js +14 -8
  324. package/dist/tools/registry.js +6 -5
  325. package/dist/tools/remember.js +8 -4
  326. package/dist/tools/scope-request.js +11 -6
  327. package/dist/tools/search-history.js +5 -2
  328. package/dist/tools/session-info.js +2 -0
  329. package/dist/tools/set-thinking.js +8 -4
  330. package/dist/tools/subagent.js +59 -39
  331. package/dist/tools/syntax-validator.js +292 -90
  332. package/dist/tools/user-input.js +22 -18
  333. package/dist/tools/web-browse.js +9 -3
  334. package/dist/tools/web-fetch.js +12 -23
  335. package/dist/tools/web-search.js +7 -5
  336. package/dist/tools/write-file.js +45 -15
  337. package/dist/ui/action-log.js +13 -0
  338. package/dist/ui/box.js +4 -3
  339. package/dist/ui/colors.js +2 -0
  340. package/dist/ui/diff.js +6 -5
  341. package/dist/ui/index.js +1 -0
  342. package/dist/ui/line-editor.js +230 -122
  343. package/dist/ui/line-math.js +10 -2
  344. package/dist/ui/md-formatter.js +57 -37
  345. package/dist/ui/output.js +8 -3
  346. package/dist/ui/plan-view.js +21 -10
  347. package/dist/ui/renderer.js +393 -67
  348. package/dist/ui/spinner.js +16 -5
  349. package/dist/ui/table.js +15 -17
  350. package/dist/ui/theme.js +143 -0
  351. package/dist/utils/child-run.js +20 -0
  352. package/dist/utils/error.js +1 -1
  353. package/dist/utils/index.js +2 -0
  354. package/dist/utils/retry.js +2 -2
  355. package/dist/utils/truncate.js +1 -1
  356. 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
+ }