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,3 +1,4 @@
1
+ /** Глобальные обработчики падений: запись краша в ~/.mma/logs/crash.jsonl. */
1
2
  import { appendFileSync, mkdirSync } from "fs";
2
3
  import { join } from "path";
3
4
  import { homedir } from "os";
@@ -5,9 +6,15 @@ import { collectEnvironment } from "./environment";
5
6
  import { sanitizeLogMessage } from "../modules/security/data-sanitizer";
6
7
  import { t } from "../i18n/index";
7
8
  import { errMsg } from "../utils";
8
- export const CRASH_LOG_DIR = join(homedir(), ".mma", "logs");
9
+ import { globalLogsDir } from "../config/paths";
10
+ /** Каталог краш-логов. */
11
+ export const CRASH_LOG_DIR = globalLogsDir();
12
+ /** Имя файла краш-лога. */
9
13
  export const CRASH_LOG_FILE = "crash.jsonl";
10
- /** Build a sanitized crash entry. Environment is captured at crash time (no tool scan). */
14
+ /**
15
+ * Строит санитизированную запись о падении. Окружение снимается в момент
16
+ * краша (без сканирования тулов).
17
+ */
11
18
  export function formatCrashEntry(type, err) {
12
19
  const message = errMsg(err);
13
20
  const stack = err instanceof Error && err.stack ? err.stack : message;
@@ -19,20 +26,23 @@ export function formatCrashEntry(type, err) {
19
26
  environment: collectEnvironment({ configDir: homedir(), scanTools: false }),
20
27
  };
21
28
  }
29
+ /**
30
+ * Дописывает запись в краш-лог. Best-effort: отчёт о краше никогда не роняет процесс.
31
+ */
22
32
  export function writeCrashEntry(dir, entry) {
23
33
  try {
24
34
  mkdirSync(dir, { recursive: true });
25
- appendFileSync(join(dir, CRASH_LOG_FILE), JSON.stringify(entry) + "\n", "utf-8");
35
+ appendFileSync(join(dir, CRASH_LOG_FILE), `${JSON.stringify(entry)}\n`, "utf-8");
26
36
  }
27
37
  catch {
28
- // Best effort — never crash while reporting a crash
38
+ // Best-effort — отчёт о краше не должен ронять процесс
29
39
  }
30
40
  }
31
41
  let installed = false;
32
42
  /**
33
- * Global crash handlers. uncaughtException is logged + re-raised (exit 1 so the
34
- * process never continues in a broken state); unhandledRejection is logged only
35
- * (the event loop keeps running). Entries land in ~/.mma/logs/crash.jsonl.
43
+ * Ставит глобальные обработчики. uncaughtException логируется и завершает
44
+ * процесс (exit 1 — продолжение в битом состоянии недопустимо);
45
+ * unhandledRejection только логируется (цикл продолжает работу).
36
46
  */
37
47
  export function installCrashHandlers() {
38
48
  if (installed)
@@ -1,3 +1,4 @@
1
+ /** Отчёт об окружении: рантайм, ОС, тулы, провайдер, Playwright. */
1
2
  import { existsSync, readFileSync, readdirSync } from "fs";
2
3
  import { spawnSync } from "child_process";
3
4
  import { createRequire } from "module";
@@ -8,7 +9,7 @@ import { env } from "process";
8
9
  import { readMmaVersion } from "./version";
9
10
  import { sanitizeUrl } from "../modules/security/network-validator";
10
11
  import { t } from "../i18n/index";
11
- /** Tools probed for availability on PATH (real executables only — no .cmd shims). */
12
+ /** Тулы, проверяемые в PATH (только реальные бинари, без .cmd-шимов). */
12
13
  const TOOL_CHECKS = ["bun", "node", "git", "python"];
13
14
  function readEngineRequirement() {
14
15
  const here = dirname(fileURLToPath(import.meta.url));
@@ -22,12 +23,16 @@ function readEngineRequirement() {
22
23
  return String(raw.engines.node);
23
24
  }
24
25
  catch {
25
- // Broken package.json — fall through
26
+ // Битый package.json — пропускаем
26
27
  }
27
28
  }
28
29
  return ">=20";
29
30
  }
30
- /** Numeric tuple comparison: does `version` meet the minimum in `requirement` (e.g. `>=20`)? */
31
+ /**
32
+ * Проверяет версию against минимума из requirement (напр. `>=20`).
33
+ * @param version проверяемая версия; @param requirement требование engines.
34
+ * @returns true, если версия не ниже минимальной.
35
+ */
31
36
  export function satisfiesMinimum(version, requirement) {
32
37
  const minMatch = requirement.match(/(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
33
38
  if (!minMatch)
@@ -51,6 +56,10 @@ export function satisfiesMinimum(version, requirement) {
51
56
  }
52
57
  return true;
53
58
  }
59
+ /**
60
+ * Детектит рантайм (Bun vs Node) и сверяет Node с engines из package.json.
61
+ * @returns информация о рантайме.
62
+ */
54
63
  export function detectRuntime() {
55
64
  const bun = globalThis.Bun;
56
65
  const isBun = typeof bun !== "undefined" && typeof bun?.version !== "undefined";
@@ -62,9 +71,9 @@ export function detectRuntime() {
62
71
  runtimeVersion,
63
72
  nodeVersion: process.version,
64
73
  engine,
65
- // engines.node applies to the Node runtime. Bun satisfies it through its
66
- // embedded Node (process.version) — never compare the Bun version itself
67
- // against a Node requirement (Bun 1.x would always look "too old").
74
+ // engines.node — про Node-рантайм. Bun проходит через встроенный Node
75
+ // (process.version); версию самого Bun с требованием не сравниваем
76
+ // (Bun 1.x всегда выглядел бы «слишком старым»).
68
77
  engineOk: satisfiesMinimum(process.version, engine),
69
78
  };
70
79
  }
@@ -85,7 +94,10 @@ function toolVersion(cmd) {
85
94
  return "missing";
86
95
  }
87
96
  }
88
- /** Where Playwright keeps downloaded browser binaries (env override wins). */
97
+ /**
98
+ * Каталог бинарников браузеров Playwright (env-переменная приоритетнее).
99
+ * @returns путь к каталогу браузеров.
100
+ */
89
101
  export function playwrightBrowsersDir() {
90
102
  if (process.env.PLAYWRIGHT_BROWSERS_PATH)
91
103
  return process.env.PLAYWRIGHT_BROWSERS_PATH;
@@ -93,14 +105,17 @@ export function playwrightBrowsersDir() {
93
105
  ? join(homedir(), "AppData", "Local", "ms-playwright")
94
106
  : join(homedir(), ".cache", "ms-playwright");
95
107
  }
96
- /** Playwright package presence/version + whether browser binaries are downloaded. */
108
+ /**
109
+ * Наличие/версия пакета Playwright + скачаны ли бинарники браузеров.
110
+ * @returns installed/version/browsersDir/browsersInstalled.
111
+ */
97
112
  export function playwrightInfo() {
98
113
  let installed = false;
99
114
  let version = "";
100
115
  const browsersDir = playwrightBrowsersDir();
101
116
  try {
102
- // Rule #12: resolve from disk at runtime — works in both src/ and dist/
103
- // layouts, and under both Bun and Node (the bridge uses createRequire too).
117
+ // Правило №12: резолв с диска в рантайме — работает и в src/, и в dist/,
118
+ // и под Bun, и под Node (мост тоже через createRequire).
104
119
  const require = createRequire(import.meta.url);
105
120
  const pkgPath = require.resolve("playwright/package.json");
106
121
  installed = existsSync(pkgPath);
@@ -120,7 +135,10 @@ export function playwrightInfo() {
120
135
  }
121
136
  return { installed, version, browsersDir, browsersInstalled };
122
137
  }
123
- /** Pure requirements check — produces warnings from a report (no side effects). */
138
+ /**
139
+ * Чистая проверка требований — варнинги из отчёта, без сайд-эффектов.
140
+ * @param report отчёт collectEnvironment; @returns список варнингов.
141
+ */
124
142
  export function checkEnvironmentRequirements(report) {
125
143
  const warnings = [];
126
144
  if (report.runtime.runtime === "node") {
@@ -148,6 +166,10 @@ export function checkEnvironmentRequirements(report) {
148
166
  }
149
167
  return warnings;
150
168
  }
169
+ /**
170
+ * Собирает полный отчёт об окружении (рантайм, ОС, тулы, провайдер).
171
+ * @param opts configDir/baseDir/config/scanTools; @returns готовый отчёт.
172
+ */
151
173
  export function collectEnvironment(opts) {
152
174
  const runtime = detectRuntime();
153
175
  const tools = {};
@@ -192,7 +214,10 @@ export function collectEnvironment(opts) {
192
214
  report.warnings = checkEnvironmentRequirements(report);
193
215
  return report;
194
216
  }
195
- /** Compact human line + full structured report into the JSONL log. */
217
+ /**
218
+ * Компактная строка для человека + полный отчёт в JSONL-лог.
219
+ * @param report отчёт окружения; @param logger логгер сессии.
220
+ */
196
221
  export function logEnvironment(report, logger) {
197
222
  logger.info(`Environment: ${report.os.platform} ${report.os.arch} | ${report.runtime.runtime} ${report.runtime.runtimeVersion} (node ${report.runtime.nodeVersion}) | mma ${report.mmaVersion} | ${report.provider?.model ?? "no provider"}`);
198
223
  logger.logStructured("environment", report);
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Чистая проекция плана модуля исполнения в план снапшота хоста.
3
+ * @param plan план в форме ActivePlanLike; @returns план снапшота либо null.
4
+ */
5
+ export function planSnapshotFromModule(plan) {
6
+ if (!plan)
7
+ return null;
8
+ return {
9
+ steps: plan.steps.map((s) => ({ text: s.text, status: s.status })),
10
+ currentIndex: plan.currentIndex,
11
+ };
12
+ }
13
+ /**
14
+ * Планы несут пятый статус (`skipped`) без `currentIndex`. Маппим на контракт
15
+ * хоста: skipped — settled, читается как done; текущий индекс — первый шаг
16
+ * не в done/skipped.
17
+ */
18
+ function toPlanStepStatus(status) {
19
+ switch (status) {
20
+ case "skipped":
21
+ return "done";
22
+ case "pending":
23
+ case "in_progress":
24
+ case "done":
25
+ case "failed":
26
+ return status;
27
+ }
28
+ }
29
+ /**
30
+ * Адаптирует реальный `Plan` модуля исполнения под вход снапшота.
31
+ * @param plan план исполнения; @returns ActivePlanLike либо null.
32
+ */
33
+ export function adaptActivePlan(plan) {
34
+ if (!plan)
35
+ return null;
36
+ return {
37
+ steps: plan.steps.map((s) => ({
38
+ text: s.description,
39
+ status: toPlanStepStatus(s.status),
40
+ })),
41
+ currentIndex: plan.steps.findIndex((s) => s.status !== "done" && s.status !== "skipped"),
42
+ };
43
+ }
@@ -0,0 +1,23 @@
1
+ import { defaultOutputBus } from "../output/bus";
2
+ /**
3
+ * Строит HostBridge для плагинов (`ctx.hostBridge`). Веб-клиенты (и любой
4
+ * плагин) шлют сообщения через ТОТ ЖЕ runAgent-путь, что и терминальный ввод:
5
+ * рендеринг, лог сессии и single-flight guard общие, без дублирования.
6
+ */
7
+ export function createHostBridge(opts) {
8
+ return {
9
+ isBusy: opts.isBusy,
10
+ async submit(text, o) {
11
+ if (opts.isBusy())
12
+ throw new Error("agent is busy");
13
+ for (const url of o?.images ?? [])
14
+ opts.addPendingImage(url);
15
+ return opts.runAgent(text);
16
+ },
17
+ interrupt() {
18
+ if (opts.isBusy())
19
+ opts.interruptRun();
20
+ },
21
+ subscribeOutput: (fn) => defaultOutputBus.subscribe(fn),
22
+ };
23
+ }
@@ -1,2 +1,3 @@
1
+ /** Ядро агента: реэкспорт Agent, PromptBuilder и базовых типов. */
1
2
  export { PromptBuilder } from "./prompt-builder";
2
3
  export { Agent } from "./agent";
@@ -6,22 +6,38 @@ const PRIORITY_ORDER = {
6
6
  };
7
7
  function blockLabel(content) {
8
8
  const firstLine = content.split("\n")[0].trim();
9
- return firstLine.length > 70 ? firstLine.slice(0, 67) + "..." : firstLine;
9
+ return firstLine.length > 70 ? `${firstLine.slice(0, 67)}...` : firstLine;
10
10
  }
11
+ /**
12
+ * Собирает системный промпт из блоков: essential всегда, остальные по
13
+ * приоритету, пока влезают в бюджет.
14
+ */
11
15
  export class PromptBuilder {
12
16
  blocks = [];
13
17
  budget;
14
18
  constructor(budget) {
15
19
  this.budget = budget;
16
20
  }
21
+ /**
22
+ * Добавляет один блок.
23
+ * @param block блок промпта с приоритетом и оценкой токенов.
24
+ */
17
25
  addBlock(block) {
18
26
  this.blocks.push(block);
19
27
  }
28
+ /**
29
+ * Добавляет несколько блоков.
30
+ * @param blocks массив блоков промпта.
31
+ */
20
32
  addBlocks(blocks) {
21
33
  for (const b of blocks) {
22
34
  this.blocks.push(b);
23
35
  }
24
36
  }
37
+ /**
38
+ * Строит промпт: essential-блоки всегда, остальные по приоритету в бюджет.
39
+ * @returns промпт, исключённое и поблочная разбивка.
40
+ */
25
41
  build() {
26
42
  const essential = [];
27
43
  const nonEssential = [];
@@ -1,13 +1,13 @@
1
- // src/core/prompt-overflow.ts
1
+ /** Переполнение системного промпта: dry-run, суммаризация, подсказки. */
2
2
  import { createHash } from "crypto";
3
3
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
4
4
  import { join } from "path";
5
5
  import { PromptBuilder } from "./prompt-builder";
6
6
  import { estimateTokens } from "../llm/token-counter";
7
7
  import { t } from "../i18n/index";
8
- /** How many tokens the model-facing hint block costs (upper bound for allocation). */
8
+ /** Цена model-facing hint-блока в токенах (верхняя граница для аллокации). */
9
9
  export const HINT_BLOCK_TOKENS = 60;
10
- /** Rough chars-per-token factor used for hard truncation fallback. */
10
+ /** Грубый фактор символов на токен для жёсткого усечения. */
11
11
  const CHARS_PER_TOKEN = 4;
12
12
  const KIND_ORDER = ["instructions", "project-map"];
13
13
  const KIND_LABEL = {
@@ -19,9 +19,8 @@ const KIND_SOURCE_FILE = {
19
19
  "project-map": "",
20
20
  };
21
21
  /**
22
- * Static dry-run of the system-prompt budget: which kind-carrying blocks do
23
- * not fit. Used by bootstrap for the startup banner and by Agent before the
24
- * first LLM call (the real resolution).
22
+ * Статический dry-run бюджета системного промпта: какие kind-блоки не влезают.
23
+ * Нужен bootstrap для стартового баннера и Agent перед первым LLM-вызовом.
25
24
  */
26
25
  export function dryRunOverflow(allBlocks, systemBudget) {
27
26
  const builder = new PromptBuilder(systemBudget);
@@ -51,13 +50,13 @@ function readCache(cacheDir, key) {
51
50
  }
52
51
  }
53
52
  catch {
54
- // Legacy plain-text entry — treat as a summary hit
53
+ // Легаси plain-text запись — считаем попаданием суммаризации
55
54
  return { mode: "summary", text: raw };
56
55
  }
57
56
  return null;
58
57
  }
59
58
  catch {
60
- // Corrupted cache — fall through to re-summarize
59
+ // Битый кэш — идём на повторную суммаризацию
61
60
  }
62
61
  return null;
63
62
  }
@@ -67,16 +66,16 @@ function writeCache(cacheDir, key, entry) {
67
66
  writeFileSync(join(cacheDir, `${key}.md`), JSON.stringify(entry), "utf-8");
68
67
  }
69
68
  catch {
70
- // Best-effort — cache failure must not crash the agent
69
+ // Best-effort — падение кэша не должно ронять агента
71
70
  }
72
71
  }
73
- /** Collect a full text response from the streaming provider API. */
72
+ /** Собирает полный текстовый ответ через стриминговый API провайдера. */
74
73
  async function collectText(provider, prompt, maxTokens) {
75
74
  let text = "";
76
- // Reasoning must be off: a thinking model would burn the completion cap on
77
- // <think> before emitting any summary content (observed on qwen3.5-9b).
78
- // 2x headroom over the target: token estimates are heuristics, and the
79
- // clamp below enforces the real cap no matter what the model returns.
75
+ // Reasoning выкл: думающая модель сожгла бы cap на <think> до любого
76
+ // суммаризирующего контента (наблюдалось на qwen3.5-9b).
77
+ // 2x запас сверх цели: оценки токенов эвристичны, а clamp ниже держит
78
+ // реальный cap независимо от ответа модели.
80
79
  for await (const chunk of provider.chat([{ role: "user", content: prompt }], undefined, undefined, {
81
80
  maxTokens: maxTokens * 2,
82
81
  reasoningEffort: "none",
@@ -96,17 +95,16 @@ function truncateToTokens(content, maxTokens) {
96
95
  cut = cut.slice(0, lastBreak);
97
96
  return `${cut.trimEnd()}\n\n[...truncated — read the full file for details...]`;
98
97
  }
99
- /** One-line first-line label for warnings/logs. */
98
+ /** Однострочная метка по первой строке (для варнингов/логов). */
100
99
  function blockLabel(content) {
101
100
  const first = content.split("\n")[0].trim();
102
101
  return first.length > 60 ? `${first.slice(0, 57)}...` : first;
103
102
  }
104
103
  /**
105
- * Summarize (or, failing that, truncate) prompt blocks that exceeded the
106
- * system-prompt budget so the project instructions / project map still reach
107
- * the model. Summaries are cached on disk keyed by kind + content + budget.
108
- * Blocks are resolved in KIND_ORDER priority; the first gets the full
109
- * remaining budget, later blocks get whatever is left.
104
+ * Суммаризирует (или, не вышло, усекает) блоки сверх бюджета, чтобы инструкции
105
+ * проекта/карта всё равно дошли до модели. Суммаризации кэшируются на диске
106
+ * (ключ: kind + контент + бюджет). Порядок — KIND_ORDER; первый забирает весь
107
+ * остаток бюджета, остальным — что останется.
110
108
  */
111
109
  export async function resolvePromptOverflow(opts) {
112
110
  const { overflow, includedTokens, systemBudget, provider, cacheDir, logger } = opts;
@@ -114,10 +112,10 @@ export async function resolvePromptOverflow(opts) {
114
112
  const replacements = [];
115
113
  const warnings = [];
116
114
  let used = includedTokens;
117
- let unresolved = [];
118
- // The bootstrap dry-run only warns that blocks "will be summarized before the
119
- // first run". Without a notice here the first prompt appears to hang while
120
- // the model rewrites AGENTS.md / the project map — surface it.
115
+ const unresolved = [];
116
+ // Dry-run bootstrap лишь предупреждает, что блоки «будут суммаризированы
117
+ // перед первым запуском». Без нотиса тут первый промпт выглядит зависшим,
118
+ // пока модель переписывает AGENTS.md / карту — показываем явно.
121
119
  if (sorted.length > 0) {
122
120
  logger?.warn(t("prompt.overflow.compressing", { count: String(sorted.length) }));
123
121
  }
@@ -147,8 +145,8 @@ export async function resolvePromptOverflow(opts) {
147
145
  try {
148
146
  const prompt = [
149
147
  `Summarize the following ${KIND_LABEL[kind]} document.`,
150
- // 3 chars/token (not 4): non-Latin text (Cyrillic etc.) is ~2-3 chars
151
- // per token, so a 4x target lands the summary over the clamp.
148
+ // 3 символа/токен (не 4): нелатиница (кириллица и т.п.) — ~2–3 символа
149
+ // на токен, поэтому цель x4 уводит суммаризацию за clamp.
152
150
  `Target length: at most ${targetChars} characters (~${maxTokens} tokens). Be strict about it.`,
153
151
  `Preserve concrete facts: file paths, commands, rules, naming conventions, workflow steps.`,
154
152
  `Keep the structure (headings / bullet lists). Output ONLY the summary text.`,
@@ -158,10 +156,9 @@ export async function resolvePromptOverflow(opts) {
158
156
  `--- DOCUMENT END ---`,
159
157
  ].join("\n");
160
158
  text = await collectText(provider, prompt, maxTokens);
161
- // Small models routinely ignore length instructions (observed: the 9B
162
- // model produced ~4700 chars against a 3170-char target). One
163
- // self-compression retry on the overshoot — the shorter input makes
164
- // compliance much likelier — before falling back to the hard clamp.
159
+ // Маленькие модели регулярно игнорируют лимит длины (наблюдалось: 9B
160
+ // выдала ~4700 символов при цели 3170). Один retry самокомпрессии на
161
+ // перелёт — короткий вход резко повышает послушание — затем жёсткий clamp.
165
162
  let retries = 0;
166
163
  while (text && estimateTokens(text) > maxTokens && retries < 1) {
167
164
  retries++;
@@ -186,7 +183,7 @@ export async function resolvePromptOverflow(opts) {
186
183
  }
187
184
  }
188
185
  if (!text) {
189
- // No provider or summarization failed — hard truncation fallback.
186
+ // Нет провайдера или суммаризация упала — фолбэк жёсткого усечения.
190
187
  mode = "truncate";
191
188
  logger?.warn(t("prompt.overflow.truncating", {
192
189
  label: blockLabel(block.content),
@@ -194,7 +191,7 @@ export async function resolvePromptOverflow(opts) {
194
191
  }));
195
192
  text = truncateToTokens(block.content, maxTokens);
196
193
  }
197
- // LLMs overshoot: enforce the cap no matter what produced the text.
194
+ // LLM перелетают: держим cap независимо от источника текста.
198
195
  if (estimateTokens(text) > maxTokens) {
199
196
  if (mode === "summary") {
200
197
  mode = "truncate";
@@ -238,6 +235,10 @@ export async function resolvePromptOverflow(opts) {
238
235
  : null;
239
236
  return { replacements, hintBlock, warnings };
240
237
  }
238
+ /**
239
+ * Резолвит источник активного окна контекста (запись провайдера или глобал).
240
+ * @param config конфиг приложения; @returns источник и значение окна.
241
+ */
241
242
  export function resolveContextWindowSource(config) {
242
243
  const entries = config.provider.entries ?? [];
243
244
  const activeLabel = config.provider.active;
@@ -249,9 +250,8 @@ export function resolveContextWindowSource(config) {
249
250
  return { source: "global", value: config.contextWindow };
250
251
  }
251
252
  /**
252
- * Human-facing hint on how to raise the context window, aware of whether the
253
- * active value comes from the global config (`mma context <N>`) or from a
254
- * provider entry override (must be edited in the provider domain file).
253
+ * Человеческая подсказка, как поднять окно контекста: глобал (`mma context <N>`)
254
+ * или override записи провайдера (править файл домена провайдера).
255
255
  */
256
256
  export function contextWindowHint(config, configDir, recommended) {
257
257
  const src = resolveContextWindowSource(config);
@@ -261,29 +261,28 @@ export function contextWindowHint(config, configDir, recommended) {
261
261
  return `edit "${join(configDir, "config", "provider.json")}" → provider.entries[label="${src.label}"].contextWindow = ${recommended}`;
262
262
  }
263
263
  /**
264
- * Recommend the next standard context size whose system budget (10%)
265
- * accommodates `neededSystemTokens`. Falls back to the largest known size.
264
+ * Ближайший стандартный размер контекста, чей системный бюджет (10%)
265
+ * вмещает `neededSystemTokens`. Фолбэк — крупнейший известный.
266
266
  */
267
267
  export function recommendContextSize(neededSystemTokens) {
268
268
  const sizes = [8192, 16384, 32768, 65536, 131072, 262144];
269
269
  return (sizes.find((s) => Math.floor(s * 0.1) >= neededSystemTokens) ?? sizes[sizes.length - 1]);
270
270
  }
271
- /** Context window needed so that `systemFraction` of it covers `neededTokens`. */
271
+ /** Окно контекста, чтобы доля `systemFraction` покрыла `neededTokens`. */
272
272
  export function requiredContextWindow(neededTokens, systemFraction) {
273
273
  const fraction = systemFraction > 0 ? systemFraction : 0.1;
274
274
  return Math.ceil(neededTokens / fraction);
275
275
  }
276
- /** System-prompt share of the CURRENT window needed to cover `neededTokens`. */
276
+ /** Доля системного промпта ТЕКУЩЕГО окна, чтобы покрыть `neededTokens`. */
277
277
  export function requiredSystemFraction(neededTokens, contextWindow) {
278
278
  if (contextWindow <= 0)
279
279
  return 1;
280
280
  return Math.min(1, Math.ceil((neededTokens / contextWindow) * 100) / 100);
281
281
  }
282
282
  /**
283
- * Localized, concrete fix for an oversized system prompt. Instead of only
284
- * snapping to a coarse standard size (which makes a 32K project jump straight
285
- * to 131072), it states the raw requirement and both levers: a bigger window
286
- * or a bigger share of the current window.
283
+ * Локализованный конкретный фикс переполненного системного промпта. Вместо
284
+ * грубого стандартного размера (проект 32K прыгал бы сразу на 131072) даёт
285
+ * сырое требование и оба рычага: больше окно или больше доля текущего окна.
287
286
  */
288
287
  export function overflowHint(config, configDir, neededTokens) {
289
288
  const fraction = config.contextBudget?.systemPrompt ?? 0.1;