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
@@ -1,15 +1,19 @@
1
+ // Математика строк редактора: ANSI-стрип, перенос по ширине, буфер↔экран маппинг.
1
2
  import stringWidth from "string-width";
2
3
  const ANSI_RE = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
4
+ /** Срезает ANSI-последовательности. */
3
5
  export function stripAnsi(s) {
4
6
  return s.replace(ANSI_RE, "");
5
7
  }
8
+ /** Длина в символах (не в байтах/ячейках). */
6
9
  export function charLen(s) {
7
10
  return Array.from(s).length;
8
11
  }
12
+ /** Перенос строки по ширине (по словам, CJK-корректно). */
9
13
  export function wrapLine(line, width, firstRowWidth) {
10
14
  const w = width > 0 ? width : 80;
11
- // Only the FIRST visual row shares its screen line with something else
12
- // (e.g. the prompt); every continuation row uses the full width.
15
+ // Только ПЕРВАЯ визуальная строка делит экранную строку с чем-то ещё
16
+ // (напр. с промптом); все продолжения — на полную ширину.
13
17
  let limit = firstRowWidth !== undefined && firstRowWidth > 0 ? firstRowWidth : w;
14
18
  const chars = Array.from(line);
15
19
  const rows = [];
@@ -54,6 +58,7 @@ export function wrapLine(line, width, firstRowWidth) {
54
58
  rows.push({ text: chars.slice(start).join(""), charStart: start });
55
59
  return rows;
56
60
  }
61
+ /** Раскладка всех строк буфера в визуальные ряды. */
57
62
  export function buildLayout(lines, width, firstRowWidth) {
58
63
  const rows = [];
59
64
  for (let b = 0; b < lines.length; b++) {
@@ -63,6 +68,7 @@ export function buildLayout(lines, width, firstRowWidth) {
63
68
  }
64
69
  return rows;
65
70
  }
71
+ /** Индекс визуального ряда по позиции буфера. */
66
72
  export function layoutIndexFor(rows, bufRow, col) {
67
73
  let idx = 0;
68
74
  for (let i = 0; i < rows.length; i++) {
@@ -71,11 +77,13 @@ export function layoutIndexFor(rows, bufRow, col) {
71
77
  }
72
78
  return idx;
73
79
  }
80
+ /** Визуальная колонка по смещению в буфере. */
74
81
  export function visualColAt(rows, idx, col) {
75
82
  const r = rows[idx];
76
83
  const upTo = col - r.charStart;
77
84
  return stringWidth(Array.from(r.text).slice(0, upTo).join(""));
78
85
  }
86
+ /** Смещение в буфере по визуальной колонке. */
79
87
  export function charOffsetFor(rows, idx, visualCol) {
80
88
  const r = rows[idx];
81
89
  const chars = Array.from(r.text);
@@ -1,7 +1,9 @@
1
+ // Markdown-форматтер чата: стриминг строк, подсветка кода, таблицы (см. STYLE.md).
1
2
  import { pc } from "./colors";
2
3
  import stringWidth from "string-width";
3
4
  import { t } from "../i18n/index";
4
5
  import { formatTable, getTerminalWidth } from "./table";
6
+ import { glyph } from "./theme";
5
7
  const KW = /\b(import|export|from|const|let|var|function|return|if|else|for|while|do|switch|case|break|continue|new|class|extends|implements|interface|type|enum|namespace|module|declare|abstract|async|await|yield|throw|try|catch|finally|typeof|instanceof|in|of|as|is|keyof|readonly|static|private|public|protected|get|set|constructor|this|super|void|never|any|unknown|boolean|string|number|symbol|object|true|false|null|undefined|default)\b/g;
6
8
  const STRING = /('[^']*'|"[^"]*"|`[^`]*`)/g;
7
9
  const COMMENT = /(\/\/[^\n]*|\/\*[\s\S]*?\*\/|#[^\n]*)/g;
@@ -11,8 +13,8 @@ const ATTR = /\b([a-zA-Z-]+=)"([^"]*)"/g;
11
13
  function highlight(code, lang) {
12
14
  if (lang === "html" || lang === "xml" || lang === "svg") {
13
15
  code = code.replace(COMMENT, (m) => pc.dim(pc.green(m)));
14
- code = code.replace(ATTR, (_m, attr, val) => pc.yellow(attr) + "=" + pc.green('"' + val + '"'));
15
- code = code.replace(TAG, (_m, tag) => "<" + pc.cyan(tag));
16
+ code = code.replace(ATTR, (_m, attr, val) => `${pc.yellow(attr)}=${pc.green(`"${val}"`)}`);
17
+ code = code.replace(TAG, (_m, tag) => `<${pc.cyan(tag)}`);
16
18
  }
17
19
  else if (lang === "css" || lang === "scss" || lang === "less") {
18
20
  code = code.replace(COMMENT, (m) => pc.dim(pc.green(m)));
@@ -46,6 +48,7 @@ function isTableRow(line) {
46
48
  function isHorizontalRule(line) {
47
49
  return /^(-{3,}|\*{3,}|_{3,})\s*$/.test(line.trim());
48
50
  }
51
+ /** Стриминговый форматтер markdown в терминальные строки. */
49
52
  export class FormattingStream {
50
53
  buffer = "";
51
54
  inCodeBlock = false;
@@ -55,15 +58,15 @@ export class FormattingStream {
55
58
  onWrite;
56
59
  onRawWrite;
57
60
  width;
58
- /** Display columns of the raw partial currently shown on the terminal. */
61
+ /** Колонок сырого партиала, показанного сейчас в терминале. */
59
62
  partialWritten = 0;
60
- /** How many chars of the pending line have already been streamed raw. */
63
+ /** Сколько символов pending-строки уже стримлено сырьём. */
61
64
  streamedChars = 0;
62
- /** Columns reserved on the left (caller prefix) so a partial never wraps. */
65
+ /** Колонок зарезервировано слева (префикс вызывающего), чтобы партиал не враппился. */
63
66
  reservedCols;
64
67
  /**
65
- * Stream the current (not-yet-newline-terminated) line raw for live
66
- * feedback. Off by default — offline callers use `formatMarkdown`.
68
+ * Стрим текущей (ещё не завершённой переводом строки) строки сырьём для живого
69
+ * фидбэка. По умолчанию выкл; офлайн-вызывающие используют `formatMarkdown`.
67
70
  */
68
71
  streamPartials;
69
72
  constructor(onWrite, width, onRawWrite, opts = {}) {
@@ -87,16 +90,15 @@ export class FormattingStream {
87
90
  }
88
91
  }
89
92
  /**
90
- * Stream the pending line raw for real-time feedback; the formatted line
91
- * replaces it once the newline arrives.
93
+ * Стримит pending-строку сырьём для real-time фидбэка; форматированная строка
94
+ * заменяет её по приходу перевода строки.
92
95
  *
93
- * The replacement uses a RELATIVE cursor move (`\x1b[<cols>D`), which is only
94
- * correct while the streamed text stays on the single visual line it started
95
- * on. If the partial would exceed the terminal width it wraps and every
96
- * relative move lands in the wrong place — the garbled output observed after
97
- * the 1.0.0 output refactor (missing/swapped characters, leaked markers,
98
- * broken tables). So streaming freezes at the last chunk that fits and the
99
- * line is rendered when it completes.
96
+ * Замена — ОТНОСИТЕЛЬНЫМ движением курсора (`\x1b[<cols>D`), корректным лишь
97
+ * пока стримленный текст сидит на одной визуальной строке, с которой начал.
98
+ * Если партиал шире терминала, он враппится и каждый относительный сдвиг бьёт
99
+ * мимо — та самая битая выдача после рефактора вывода 1.0.0 (потерянные/
100
+ * переставленные символы, потёкшие маркеры, ломаные таблицы). Поэтому стрим
101
+ * замирает на последнем влезшем чанке, а строка рендерится по завершении.
100
102
  */
101
103
  streamPartial() {
102
104
  if (!this.streamPartials)
@@ -113,36 +115,36 @@ export class FormattingStream {
113
115
  }
114
116
  emitPartialRewind() {
115
117
  if (this.partialWritten > 0) {
116
- // Move back over the streamed partial and erase any tail left by a
117
- // shorter formatted replacement before the caller renders the line.
118
+ // Откат поверх стримленного партиала + стереть хвост, оставшийся от более
119
+ // короткой форматированной замены, до рендера строки вызывающим.
118
120
  this.onRawWrite(`\x1b[${this.partialWritten}D\x1b[K`);
119
121
  this.partialWritten = 0;
120
122
  }
121
123
  this.streamedChars = 0;
122
124
  }
123
- /** True when there is displayed partial output or unprocessed buffered text. @internal */
125
+ /** Есть ли показанный партиал или необработанный буфер. @internal */
124
126
  hasPartial() {
125
127
  return this.partialWritten > 0 || this.buffer.length > 0 || this.tableBuffer.length > 0;
126
128
  }
127
129
  /**
128
- * Finalize a displayed raw partial so the next write starts on a fresh line.
129
- * Only the already-streamed partial is terminated (with a single newline via
130
- * `onRawWrite`); any pending table buffer is flushed. An open code block is
131
- * intentionally left untouched — closing it here would make the real closing
132
- * fence look like a new opening fence and corrupt all following prose. The
133
- * code block is emitted by the final `flush()`. Idempotent.
130
+ * Финализирует показанный сырой партиал, чтобы следующая запись началась с новой строки.
131
+ * Терминируется только уже стримленный партиал (одиночный перевод строки через
132
+ * `onRawWrite`); pending-буфер таблицы сбрасывается. Открытый кодовый блок
133
+ * осознанно не трогается: закрытие здесь сделало бы настоящий закрывающий fence
134
+ * похожим на новый открывающий и испортило бы всю прозу дальше. Блок эмитит
135
+ * финальный `flush()`. Идемпотентно.
134
136
  */
135
137
  flushPartialNow() {
136
138
  if (this.partialWritten > 0) {
137
- // The line is already on screen raw; terminate it as-is (it may be
138
- // interrupted mid-markdown) and drop it so it is not rendered twice.
139
+ // Строка уже на экране сырьём; терминируем как есть (может быть оборвана
140
+ // посреди markdown) и дропаем, чтобы не отрендерить дважды.
139
141
  this.onRawWrite("\n");
140
142
  this.partialWritten = 0;
141
143
  this.streamedChars = 0;
142
144
  this.buffer = "";
143
145
  }
144
146
  else if (this.buffer.length > 0 && !this.inCodeBlock) {
145
- // Never streamed (plain mode) — render the pending line now.
147
+ // Не стримлено (plain-режим) — рендерим pending-строку сейчас.
146
148
  const line = this.buffer;
147
149
  this.buffer = "";
148
150
  this.streamedChars = 0;
@@ -158,8 +160,15 @@ export class FormattingStream {
158
160
  }
159
161
  if (this.inCodeBlock) {
160
162
  if (this.buffer.length > 0) {
161
- this.codeLines.push(this.buffer);
162
- this.buffer = "";
163
+ // Закрывающий fence в EOF без trailing newline: считаем закрытием, а не
164
+ // контентом кода (иначе "```" потечёт в блок).
165
+ if (this.buffer.trim().startsWith("```")) {
166
+ this.buffer = "";
167
+ }
168
+ else {
169
+ this.codeLines.push(this.buffer);
170
+ this.buffer = "";
171
+ }
163
172
  }
164
173
  if (this.codeLines.length > 0) {
165
174
  this.emitCodeBlock();
@@ -181,6 +190,10 @@ export class FormattingStream {
181
190
  this.emitCodeBlock();
182
191
  }
183
192
  else {
193
+ // Pending-таблица не должна эмититься ПОСЛЕ идущего за ней кодового блока:
194
+ // сбрасываем до входа в fence.
195
+ if (this.tableBuffer.length > 0)
196
+ this.flushTable();
184
197
  this.inCodeBlock = true;
185
198
  this.codeLang = line.trim().slice(3).trim();
186
199
  this.codeLines = [];
@@ -220,19 +233,19 @@ export class FormattingStream {
220
233
  if (this.codeLines.length > 0) {
221
234
  const code = this.codeLines.join("\n");
222
235
  const highlighted = highlight(code, this.codeLang);
223
- const lang = this.codeLang ? ` ${this.codeLang} ` : " ";
224
- const top = pc.dim(`┌─${lang}${"─".repeat(Math.max(0, this.width - 3 - lang.length))}┐`);
225
- this.onWrite(top);
236
+ // Без рамки: только dim-ярлык языка и левый гуттер. Коробочные кодовые
237
+ // блоки запрещены стилем чата (docs/design/ui/STYLE.md).
238
+ if (this.codeLang)
239
+ this.onWrite(pc.dim(` ${this.codeLang}`));
226
240
  for (const l of highlighted.split("\n")) {
227
- this.onWrite(pc.dim("│ ") + l);
241
+ this.onWrite(pc.dim(`${glyph.group} `) + l);
228
242
  }
229
- this.onWrite(pc.dim(`└${"─".repeat(Math.max(0, this.width - 1))}┘`));
230
243
  }
231
244
  this.codeLines = [];
232
245
  this.codeLang = "";
233
246
  }
234
247
  formatLine(line) {
235
- let result = line;
248
+ const result = line;
236
249
  const heading = result.match(/^(#{1,6})\s+(.+)$/);
237
250
  if (heading) {
238
251
  const level = heading[1].length;
@@ -272,18 +285,22 @@ export class FormattingStream {
272
285
  codeSpans.push(pc.yellow(c));
273
286
  return `\u0000${codeSpans.length - 1}\u0000`;
274
287
  });
288
+ // `***text***` (bold+italic) до одиночных `**`/`*`, иначе вложенность
289
+ // рвётся и во вложении остаётся висящая звёздочка.
290
+ result = result.replace(/\*\*\*(.+?)\*\*\*/g, (_, s) => pc.bold(pc.italic(s)));
275
291
  result = result.replace(/\*\*(.+?)\*\*/g, (_, s) => pc.bold(s));
276
292
  result = result.replace(/~~(.+?)~~/g, (_, s) => pc.strikethrough(s));
277
293
  result = result.replace(/\*([^*]+)\*/g, (_, s) => pc.italic(s));
278
294
  result = result.replace(/(^|\s)_([^_\n]+)_(?=\s|$)/g, (_m, pre, s) => pre + pc.italic(s));
279
295
  result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, label, url) => {
280
- const short = url.length > 80 ? url.slice(0, 77) + "…" : url;
296
+ const short = url.length > 80 ? `${url.slice(0, 77)}…` : url;
281
297
  return `${pc.cyan(label)} ${pc.dim(`(${short})`)}`;
282
298
  });
283
299
  result = result.replace(/\u0000(\d+)\u0000/g, (_m, i) => codeSpans[Number(i)]);
284
300
  return result;
285
301
  }
286
302
  }
303
+ /** Форматирует markdown-текст целиком в терминальные строки. */
287
304
  export function formatMarkdown(text) {
288
305
  const lines = [];
289
306
  const stream = new FormattingStream((l) => lines.push(l));
@@ -291,12 +308,15 @@ export function formatMarkdown(text) {
291
308
  stream.flush();
292
309
  return lines.join("\n");
293
310
  }
311
+ /** Форматирует ошибку (красный префикс из i18n). */
294
312
  export function formatError(text) {
295
313
  return pc.red(pc.bold(t("ui.error_prefix")) + text);
296
314
  }
315
+ /** Форматирует успех (зелёный префикс из i18n). */
297
316
  export function formatSuccess(text) {
298
317
  return pc.green(pc.bold(t("ui.success_prefix")) + text);
299
318
  }
319
+ /** Форматирует предупреждение (жёлтый префикс из i18n). */
300
320
  export function formatWarning(text) {
301
321
  return pc.yellow(pc.bold(t("ui.warning_prefix")) + text);
302
322
  }
package/dist/ui/output.js CHANGED
@@ -1,14 +1,19 @@
1
+ // Короткие писатели в канал: markdown/ошибка/успех/предупреждение.
1
2
  import { getDefaultChannel } from "../output";
2
3
  import { formatMarkdown, formatError, formatSuccess, formatWarning } from "./md-formatter";
4
+ /** Пишет markdown-текст в stdout. */
3
5
  export function writeOutput(text) {
4
- getDefaultChannel().writeRaw(formatMarkdown(text) + "\n");
6
+ getDefaultChannel().writeRaw(`${formatMarkdown(text)}\n`);
5
7
  }
8
+ /** Пишет ошибку в stderr. */
6
9
  export function writeError(text) {
7
- getDefaultChannel().writeRaw(formatError(text) + "\n", "stderr");
10
+ getDefaultChannel().writeRaw(`${formatError(text)}\n`, "stderr");
8
11
  }
12
+ /** Пишет успех в stdout. */
9
13
  export function writeSuccess(text) {
10
- getDefaultChannel().writeRaw(formatSuccess(text) + "\n");
14
+ getDefaultChannel().writeRaw(`${formatSuccess(text)}\n`);
11
15
  }
16
+ /** Пишет предупреждение блочной строкой. */
12
17
  export function writeWarning(text) {
13
18
  getDefaultChannel().writeLine(formatWarning(text));
14
19
  }
@@ -1,10 +1,14 @@
1
+ // Вид плана в чате: чтение active.json, чеклист с прогресс-баром, контекст шага.
1
2
  import { existsSync, readFileSync } from "fs";
2
3
  import { join } from "path";
3
4
  import { pc } from "./colors";
5
+ import { glyph } from "./theme";
4
6
  import { extractFileLikeTokens, stripUrls } from "../modules/hallucination/js-identifiers";
5
7
  import { t } from "../i18n/index";
8
+ import { projectMmaDir } from "../config/paths";
9
+ /** Читает активный план из .mma/plans/active.json. Нет/бит — null. */
6
10
  export function readActivePlan(baseDir) {
7
- const p = join(baseDir, ".mma", "plans", "active.json");
11
+ const p = join(projectMmaDir(baseDir), "plans", "active.json");
8
12
  if (!existsSync(p))
9
13
  return null;
10
14
  try {
@@ -27,34 +31,36 @@ export function readActivePlan(baseDir) {
27
31
  return null;
28
32
  }
29
33
  }
34
+ /** Индекс текущего шага (первый не done/skipped). */
30
35
  export function currentStepIndex(plan) {
31
36
  return plan.steps.findIndex((s) => s.status !== "done" && s.status !== "skipped");
32
37
  }
33
38
  function stepMark(step) {
34
39
  switch (step.status) {
35
40
  case "done":
36
- return pc.green("[x]");
41
+ return pc.green(glyph.success);
37
42
  case "in_progress":
38
- return pc.yellow("[*]");
43
+ return pc.cyan(glyph.action);
39
44
  case "failed":
40
- return pc.red("[!]");
45
+ return pc.red(glyph.failure);
41
46
  case "skipped":
42
- return pc.dim("[-]");
47
+ return pc.dim("–");
43
48
  default:
44
- return pc.dim("[ ]");
49
+ return pc.dim("○");
45
50
  }
46
51
  }
52
+ /** Рендерит чеклист плана с прогресс-баром ▰▱ построчно. */
47
53
  export function formatPlanChecklist(plan) {
48
54
  const done = plan.steps.filter((s) => s.status === "done" || s.status === "skipped").length;
49
55
  const total = plan.steps.length;
50
56
  const pct = total === 0 ? 0 : Math.round((done / total) * 100);
51
57
  const cur = currentStepIndex(plan);
52
- const barLen = 15;
58
+ const barLen = 10;
53
59
  const filled = Math.round((pct / 100) * barLen);
54
- const bar = pc.green("█".repeat(filled)) + pc.dim("░".repeat(barLen - filled));
60
+ const bar = pc.green("▰".repeat(filled)) + pc.dim("▱".repeat(barLen - filled));
55
61
  const title = plan.title.replace(/^\[\d+[^]]*\]\s*/, "");
56
62
  const lines = [
57
- `${pc.cyan(`[${plan.id}]`)} ${pc.bold(title)} ${bar} ${pc.dim(`${done}/${total} ${pct}%`)}`,
63
+ `${pc.cyan(glyph.action)} ${pc.bold(title)} ${bar} ${pc.dim(`${done}/${total}`)}`,
58
64
  ];
59
65
  for (let i = 0; i < plan.steps.length; i++) {
60
66
  const step = plan.steps[i];
@@ -62,13 +68,14 @@ export function formatPlanChecklist(plan) {
62
68
  const desc = active ? pc.yellow(step.description) : pc.dim(step.description);
63
69
  lines.push(` ${stepMark(step)} ${step.id}. ${desc}`);
64
70
  for (const sub of step.subtasks ?? []) {
65
- lines.push(` ${sub.done ? pc.green("[x]") : pc.dim("[ ]")} ${sub.text}`);
71
+ lines.push(` ${sub.done ? pc.green(glyph.success) : pc.dim("○")} [${sub.id}] ${sub.text}`);
66
72
  }
67
73
  }
68
74
  return lines;
69
75
  }
70
76
  const STRUCTURAL_TOOLS = new Set([
71
77
  "plan",
78
+ "plan_step",
72
79
  "todo",
73
80
  "verify",
74
81
  "project_map",
@@ -78,6 +85,10 @@ const STRUCTURAL_TOOLS = new Set([
78
85
  function truncate(s, max = 48) {
79
86
  return s.length > max ? `${s.slice(0, max - 1)}…` : s;
80
87
  }
88
+ /**
89
+ * Подбирает шаг плана под вызов тула по файловым токенам аргументов.
90
+ * Структурные тулы и вызовы без путей — null.
91
+ */
81
92
  export function stepContextForTool(plan, tool, args) {
82
93
  if (!plan || STRUCTURAL_TOOLS.has(tool))
83
94
  return null;