micro-models-agent 2.10.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 (359) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/assets/app.js +22 -4
  3. package/dist/assets/index.html +29 -0
  4. package/dist/assets/js/dom.js +2 -1
  5. package/dist/assets/js/feed.js +38 -26
  6. package/dist/assets/js/format.js +1 -1
  7. package/dist/assets/js/rail.js +114 -0
  8. package/dist/assets/js/settings-controls.js +2 -2
  9. package/dist/assets/js/settings.js +246 -51
  10. package/dist/assets/js/store.js +3 -0
  11. package/dist/assets/js/tabs.js +104 -2
  12. package/dist/assets/styles.css +215 -66
  13. package/dist/cli/cache-line.js +1 -0
  14. package/dist/cli/command-suggest.js +5 -4
  15. package/dist/cli/commands.js +231 -122
  16. package/dist/cli/completer.js +132 -31
  17. package/dist/cli/index.js +1 -0
  18. package/dist/cli/json-payload.js +4 -4
  19. package/dist/cli/main.js +166 -61
  20. package/dist/cli/onboarding-commands.js +126 -0
  21. package/dist/cli/plugin-commands.js +2 -1
  22. package/dist/cli/relaunch.js +16 -13
  23. package/dist/cli/repl-commands-lsp.js +75 -0
  24. package/dist/cli/repl-commands-skills.js +105 -0
  25. package/dist/cli/repl-commands.js +589 -266
  26. package/dist/cli/repl.js +436 -177
  27. package/dist/cli/run-result.js +5 -6
  28. package/dist/cli/security-commands.js +37 -28
  29. package/dist/cli/setup-order.js +4 -55
  30. package/dist/cli/setup-prompt.js +3 -2
  31. package/dist/cli/setup.js +27 -107
  32. package/dist/cli/web-command.js +98 -0
  33. package/dist/config/budget.js +5 -5
  34. package/dist/config/config.js +103 -96
  35. package/dist/config/defaults.js +38 -8
  36. package/dist/config/domains.js +24 -27
  37. package/dist/config/env.js +46 -0
  38. package/dist/config/experts.js +2 -0
  39. package/dist/config/index.js +1 -0
  40. package/dist/config/paths.js +56 -0
  41. package/dist/config/redact.js +44 -0
  42. package/dist/config/registry-extra.js +334 -0
  43. package/dist/config/registry.js +584 -0
  44. package/dist/config/security.js +35 -36
  45. package/dist/config/timeouts.js +74 -0
  46. package/dist/config/utils.js +16 -15
  47. package/dist/core/agent/artifact-progress.js +59 -0
  48. package/dist/core/agent/artifact-resolve.js +79 -0
  49. package/dist/core/agent/audit-gate.js +7 -3
  50. package/dist/core/agent/compaction.js +2 -2
  51. package/dist/core/agent/constants.js +33 -4
  52. package/dist/core/agent/context-log.js +454 -0
  53. package/dist/core/agent/context-renderer.js +5 -0
  54. package/dist/core/agent/critic-gate.js +132 -0
  55. package/dist/core/agent/hallucination-gate.js +148 -38
  56. package/dist/core/agent/loop-state.js +15 -0
  57. package/dist/core/agent/prefix-monitor.js +1 -1
  58. package/dist/core/agent/reasoning-resolver.js +10 -1
  59. package/dist/core/agent/token-tracker.js +7 -4
  60. package/dist/core/agent/tool-batch.js +93 -18
  61. package/dist/core/agent/tool-images.js +18 -0
  62. package/dist/core/agent/tool-output.js +65 -11
  63. package/dist/core/agent/tool-pairing.js +60 -0
  64. package/dist/core/agent-moe.js +25 -24
  65. package/dist/core/agent.js +429 -108
  66. package/dist/core/bootstrap/agent-phase.js +66 -0
  67. package/dist/core/bootstrap/config-phase.js +86 -0
  68. package/dist/core/bootstrap/modules-phase.js +269 -0
  69. package/dist/core/bootstrap/provider-phase.js +183 -0
  70. package/dist/core/bootstrap/session-phase.js +204 -0
  71. package/dist/core/bootstrap/state.js +94 -0
  72. package/dist/core/bootstrap/workspace-phase.js +115 -0
  73. package/dist/core/bootstrap.js +92 -660
  74. package/dist/core/crash-handler.js +17 -7
  75. package/dist/core/environment.js +37 -12
  76. package/dist/core/host-plan.js +43 -0
  77. package/dist/core/host.js +23 -0
  78. package/dist/core/index.js +1 -0
  79. package/dist/core/prompt-builder.js +17 -1
  80. package/dist/core/prompt-overflow.js +42 -43
  81. package/dist/core/session-logger.js +122 -30
  82. package/dist/core/system-prompt.js +117 -0
  83. package/dist/core/version.js +6 -4
  84. package/dist/core/web-host.js +34 -0
  85. package/dist/core/workspace.js +19 -15
  86. package/dist/i18n/en.json +106 -21
  87. package/dist/i18n/index.js +37 -3
  88. package/dist/i18n/ru.json +109 -21
  89. package/dist/index.js +7 -3
  90. package/dist/llm/image-utils.js +55 -64
  91. package/dist/llm/llm-errors.js +9 -0
  92. package/dist/llm/model-loader.js +10 -32
  93. package/dist/llm/models-dev.js +121 -0
  94. package/dist/llm/openai-compat.js +146 -73
  95. package/dist/llm/orchestrator.js +33 -11
  96. package/dist/llm/provider-budget.js +2 -2
  97. package/dist/llm/provider-context.js +233 -0
  98. package/dist/llm/provider.js +1 -1
  99. package/dist/llm/response.js +5 -0
  100. package/dist/llm/token-counter.js +27 -11
  101. package/dist/logger/app-logger.js +48 -22
  102. package/dist/logger/file-log.js +28 -19
  103. package/dist/logger/index.js +1 -0
  104. package/dist/main.js +24285 -22447
  105. package/dist/migration/backup.js +14 -3
  106. package/dist/migration/detect.js +12 -3
  107. package/dist/migration/index.js +1 -0
  108. package/dist/modules/artifacts/store.js +9 -8
  109. package/dist/modules/browser/actions.js +6 -0
  110. package/dist/modules/browser/bridge-client.js +14 -12
  111. package/dist/modules/browser/bridge-path.js +4 -4
  112. package/dist/modules/browser/console-buffer.js +37 -0
  113. package/dist/modules/browser/cookie-store.js +5 -0
  114. package/dist/modules/browser/driver-types.js +1 -0
  115. package/dist/modules/browser/driver.js +19 -11
  116. package/dist/modules/browser/index.js +3 -1
  117. package/dist/modules/browser/module.js +2 -1
  118. package/dist/modules/browser/session.js +10 -30
  119. package/dist/modules/browser/snapshot.js +19 -13
  120. package/dist/modules/browser/types.js +1 -0
  121. package/dist/modules/certification/cli.js +28 -20
  122. package/dist/modules/certification/fact-checker.js +9 -1
  123. package/dist/modules/certification/loader.js +9 -2
  124. package/dist/modules/certification/manifest.js +83 -21
  125. package/dist/modules/certification/runner.js +23 -13
  126. package/dist/modules/certification/scenarios.js +20 -20
  127. package/dist/modules/certification/syntax-scenarios.js +1 -2
  128. package/dist/modules/context/chunk-query.js +11 -9
  129. package/dist/modules/context/fact-extractor.js +37 -39
  130. package/dist/modules/context/index.js +1 -0
  131. package/dist/modules/context/manager.js +106 -80
  132. package/dist/modules/critic/client.js +176 -0
  133. package/dist/modules/critic/evidence.js +81 -0
  134. package/dist/modules/critic/provider.js +45 -0
  135. package/dist/modules/critic/tools.js +78 -0
  136. package/dist/modules/critic/types.js +1 -0
  137. package/dist/modules/execution/audit-runners.js +28 -34
  138. package/dist/modules/execution/auditor.js +53 -49
  139. package/dist/modules/execution/execution-plugin.js +142 -102
  140. package/dist/modules/execution/index.js +1 -1
  141. package/dist/modules/execution/input-from.js +37 -13
  142. package/dist/modules/execution/module.js +368 -191
  143. package/dist/modules/execution/moe-executor.js +53 -26
  144. package/dist/modules/execution/plan-actions.js +320 -202
  145. package/dist/modules/execution/plan-checks.js +35 -0
  146. package/dist/modules/execution/plan-coverage.js +36 -33
  147. package/dist/modules/execution/plan-steps.js +11 -3
  148. package/dist/modules/execution/plan-store.js +83 -17
  149. package/dist/modules/execution/plan-tool.js +89 -35
  150. package/dist/modules/execution/plan-validator.js +30 -10
  151. package/dist/modules/execution/planner.js +22 -13
  152. package/dist/modules/execution/stuck-detector.js +196 -93
  153. package/dist/modules/execution/tracker.js +22 -8
  154. package/dist/modules/execution/verifier.js +69 -48
  155. package/dist/modules/execution/windows-commands.js +12 -12
  156. package/dist/modules/hallucination/artifact-claim.js +93 -0
  157. package/dist/modules/hallucination/confidence.js +13 -11
  158. package/dist/modules/hallucination/consistency.js +10 -2
  159. package/dist/modules/hallucination/detector.js +10 -5
  160. package/dist/modules/hallucination/factual.js +43 -26
  161. package/dist/modules/hallucination/index.js +1 -0
  162. package/dist/modules/hallucination/js-identifiers.js +44 -45
  163. package/dist/modules/hallucination/llm-judge.js +17 -12
  164. package/dist/modules/hallucination/success-claim.js +59 -0
  165. package/dist/modules/indexer/cache.js +52 -4
  166. package/dist/modules/indexer/index.js +1 -0
  167. package/dist/modules/indexer/map-command.js +2 -4
  168. package/dist/modules/indexer/map-select.js +16 -16
  169. package/dist/modules/indexer/module.js +47 -12
  170. package/dist/modules/indexer/project-profile.js +8 -7
  171. package/dist/modules/indexer/symbols.js +15 -15
  172. package/dist/modules/indexer/walker.js +159 -29
  173. package/dist/modules/lsp/check-tool.js +7 -5
  174. package/dist/modules/lsp/client.js +39 -39
  175. package/dist/modules/lsp/command.js +17 -24
  176. package/dist/modules/lsp/config.js +12 -11
  177. package/dist/modules/lsp/index.js +1 -0
  178. package/dist/modules/lsp/module.js +48 -46
  179. package/dist/modules/lsp/probe.js +13 -14
  180. package/dist/modules/lsp/project-root.js +14 -17
  181. package/dist/modules/lsp/startup-check.js +18 -16
  182. package/dist/modules/mcp/client.js +59 -62
  183. package/dist/modules/mcp/index.js +1 -0
  184. package/dist/modules/mcp/module.js +66 -37
  185. package/dist/modules/mcp/registry.js +5 -0
  186. package/dist/modules/memory/index.js +1 -0
  187. package/dist/modules/memory/module.js +12 -8
  188. package/dist/modules/memory/search.js +4 -1
  189. package/dist/modules/memory/store.js +40 -2
  190. package/dist/modules/onboarding/init.js +47 -0
  191. package/dist/modules/onboarding/meet.js +30 -0
  192. package/dist/modules/onboarding/mode.js +30 -0
  193. package/dist/modules/onboarding/prompts.js +43 -0
  194. package/dist/modules/pipelines/engine.js +10 -0
  195. package/dist/modules/pipelines/index.js +1 -0
  196. package/dist/modules/pipelines/parser.js +4 -1
  197. package/dist/modules/pipelines/template.js +4 -0
  198. package/dist/modules/plugins/builtin/lint-on-write.js +80 -67
  199. package/dist/modules/plugins/builtin/notify.js +2 -0
  200. package/dist/modules/plugins/index.js +1 -0
  201. package/dist/modules/plugins/loader.js +18 -3
  202. package/dist/modules/plugins/manager.js +37 -17
  203. package/dist/modules/pricing/index.js +10 -11
  204. package/dist/modules/pricing/prices.js +12 -12
  205. package/dist/modules/processes/index.js +1 -0
  206. package/dist/modules/processes/kill-tree.js +27 -31
  207. package/dist/modules/processes/registry.js +44 -25
  208. package/dist/modules/processes/runner.js +4 -4
  209. package/dist/modules/providers/capabilities.js +28 -0
  210. package/dist/modules/providers/create.js +3 -4
  211. package/dist/modules/providers/factory.js +7 -7
  212. package/dist/modules/providers/fallback.js +12 -12
  213. package/dist/modules/providers/health.js +4 -4
  214. package/dist/modules/providers/manager.js +50 -19
  215. package/dist/modules/providers/naming.js +15 -0
  216. package/dist/modules/providers/preflight.js +71 -0
  217. package/dist/modules/providers/presets.js +39 -8
  218. package/dist/modules/providers/registry.js +7 -2
  219. package/dist/modules/reasoning/policy.js +8 -6
  220. package/dist/modules/reasoning/probe.js +30 -25
  221. package/dist/modules/security/audit-log.js +19 -36
  222. package/dist/modules/security/audit-notifier.js +35 -75
  223. package/dist/modules/security/command-validator.js +99 -51
  224. package/dist/modules/security/content-scanner.js +8 -8
  225. package/dist/modules/security/data-sanitizer.js +9 -16
  226. package/dist/modules/security/encryption.js +32 -52
  227. package/dist/modules/security/index.js +2 -1
  228. package/dist/modules/security/network-validator.js +120 -43
  229. package/dist/modules/security/path-validator.js +61 -46
  230. package/dist/modules/security/protected-paths.js +73 -0
  231. package/dist/modules/security/rate-limiter.js +17 -49
  232. package/dist/modules/security/security-policies.js +25 -57
  233. package/dist/modules/security/session-encryption.js +32 -71
  234. package/dist/modules/security/session-isolation.js +15 -28
  235. package/dist/modules/session/auto-name.js +63 -0
  236. package/dist/modules/session/export.js +98 -0
  237. package/dist/modules/session/index.js +1 -0
  238. package/dist/modules/session/manager.js +79 -28
  239. package/dist/modules/session/module.js +4 -3
  240. package/dist/modules/session/store.js +57 -20
  241. package/dist/modules/setup/answers.js +35 -0
  242. package/dist/modules/setup/apply.js +79 -0
  243. package/dist/modules/setup/discovery.js +72 -0
  244. package/dist/modules/skills/index.js +1 -0
  245. package/dist/modules/skills/loader.js +9 -1
  246. package/dist/modules/skills/module.js +11 -0
  247. package/dist/modules/updater/changelog-reader.js +15 -16
  248. package/dist/modules/updater/checker.js +9 -4
  249. package/dist/modules/updater/dev-detect.js +7 -6
  250. package/dist/modules/updater/index.js +1 -0
  251. package/dist/modules/updater/module.js +17 -15
  252. package/dist/modules/user-profile/compressor.js +2 -0
  253. package/dist/modules/user-profile/index.js +1 -0
  254. package/dist/modules/user-profile/profile.js +10 -1
  255. package/dist/modules/webui/answer-api.js +29 -0
  256. package/dist/modules/webui/assets.js +50 -0
  257. package/dist/modules/webui/body.js +21 -0
  258. package/dist/modules/webui/commands-settings.js +209 -0
  259. package/dist/modules/webui/commands-shared.js +60 -0
  260. package/dist/modules/webui/commands.js +174 -0
  261. package/dist/modules/webui/config-api.js +134 -0
  262. package/dist/modules/webui/file-api.js +202 -0
  263. package/dist/modules/webui/forward.js +159 -0
  264. package/dist/modules/webui/history-api.js +112 -0
  265. package/dist/modules/webui/host-state.js +60 -0
  266. package/dist/modules/webui/i18n-api.js +9 -0
  267. package/dist/modules/webui/limits.js +6 -0
  268. package/dist/modules/webui/log-forward.js +20 -0
  269. package/dist/modules/webui/memory-commands.js +64 -0
  270. package/dist/modules/webui/model-cache.js +18 -0
  271. package/dist/modules/webui/module.js +148 -0
  272. package/dist/modules/webui/persist.js +24 -0
  273. package/dist/modules/webui/prompt-io.js +97 -0
  274. package/dist/modules/webui/providers-api.js +337 -0
  275. package/dist/modules/webui/providers-view.js +56 -0
  276. package/dist/modules/webui/reasoning-view.js +15 -0
  277. package/dist/modules/webui/run-agent.js +81 -0
  278. package/dist/modules/webui/server.js +284 -0
  279. package/dist/modules/webui/sessions-api.js +178 -0
  280. package/dist/modules/webui/settings-api.js +561 -0
  281. package/dist/modules/webui/setup-api.js +201 -0
  282. package/dist/modules/webui/state.js +74 -0
  283. package/dist/modules/webui/util.js +261 -0
  284. package/dist/output/bus.js +7 -2
  285. package/dist/output/channel.js +80 -28
  286. package/dist/output/format.js +2 -1
  287. package/dist/output/index.js +1 -0
  288. package/dist/output/json-sink.js +5 -3
  289. package/dist/output/machine.js +4 -3
  290. package/dist/output/session-sink.js +4 -4
  291. package/dist/tools/approve.js +4 -0
  292. package/dist/tools/attach-image.js +5 -4
  293. package/dist/tools/auto-fixer.js +26 -44
  294. package/dist/tools/auto-tags.js +83 -0
  295. package/dist/tools/bash.js +193 -116
  296. package/dist/tools/browser.js +76 -31
  297. package/dist/tools/chunk-query.js +14 -6
  298. package/dist/tools/create-dir.js +9 -5
  299. package/dist/tools/delete-file.js +9 -5
  300. package/dist/tools/download-file.js +32 -7
  301. package/dist/tools/edit-file.js +52 -14
  302. package/dist/tools/enable-tools.js +6 -6
  303. package/dist/tools/executor.js +132 -27
  304. package/dist/tools/file-info.js +3 -1
  305. package/dist/tools/filter-tools.js +3 -3
  306. package/dist/tools/glob-tool.js +4 -1
  307. package/dist/tools/grep-tool.js +13 -10
  308. package/dist/tools/hidden-tools-block.js +6 -6
  309. package/dist/tools/index.js +16 -8
  310. package/dist/tools/list-dir.js +4 -2
  311. package/dist/tools/load-skill.js +7 -0
  312. package/dist/tools/mcp-call.js +15 -4
  313. package/dist/tools/meet-done.js +14 -0
  314. package/dist/tools/move-file.js +14 -7
  315. package/dist/tools/path-utils.js +29 -29
  316. package/dist/tools/pipeline-run.js +29 -7
  317. package/dist/tools/preview.js +1 -1
  318. package/dist/tools/process-ids.js +31 -0
  319. package/dist/tools/process-kill.js +9 -16
  320. package/dist/tools/process-list.js +1 -0
  321. package/dist/tools/process-log.js +11 -16
  322. package/dist/tools/process-wait.js +63 -0
  323. package/dist/tools/prompt-io.js +4 -3
  324. package/dist/tools/question.js +172 -25
  325. package/dist/tools/read-file.js +55 -34
  326. package/dist/tools/recall.js +14 -8
  327. package/dist/tools/registry.js +6 -5
  328. package/dist/tools/remember.js +8 -4
  329. package/dist/tools/scope-request.js +11 -6
  330. package/dist/tools/search-history.js +5 -2
  331. package/dist/tools/session-info.js +2 -0
  332. package/dist/tools/set-thinking.js +8 -4
  333. package/dist/tools/subagent.js +59 -39
  334. package/dist/tools/syntax-validator.js +292 -90
  335. package/dist/tools/user-input.js +22 -18
  336. package/dist/tools/web-browse.js +9 -3
  337. package/dist/tools/web-fetch.js +12 -23
  338. package/dist/tools/web-search.js +7 -5
  339. package/dist/tools/write-file.js +45 -15
  340. package/dist/ui/action-log.js +13 -0
  341. package/dist/ui/box.js +4 -3
  342. package/dist/ui/colors.js +2 -0
  343. package/dist/ui/diff.js +6 -5
  344. package/dist/ui/index.js +1 -0
  345. package/dist/ui/line-editor.js +230 -122
  346. package/dist/ui/line-math.js +10 -2
  347. package/dist/ui/md-formatter.js +57 -37
  348. package/dist/ui/output.js +8 -3
  349. package/dist/ui/plan-view.js +21 -10
  350. package/dist/ui/renderer.js +393 -67
  351. package/dist/ui/spinner.js +16 -5
  352. package/dist/ui/table.js +15 -17
  353. package/dist/ui/theme.js +143 -0
  354. package/dist/utils/child-run.js +20 -0
  355. package/dist/utils/error.js +1 -1
  356. package/dist/utils/index.js +2 -0
  357. package/dist/utils/retry.js +2 -2
  358. package/dist/utils/truncate.js +1 -1
  359. package/package.json +1 -1
@@ -9,8 +9,9 @@ import { isTransientError } from "./transient-error";
9
9
  import { sleep } from "../../utils/sleep";
10
10
  import { backoffDelay } from "../../utils/retry";
11
11
  import { errMsg } from "../../utils";
12
+ /** Макс. циклов расширения scope на подзадачу. */
12
13
  export const MAX_SCOPE_EXPANSION_CYCLES = 2;
13
- /** Uniform interrupt error recognized by the agent loop (err.name === "AbortError"). */
14
+ /** Униформная ошибка прерывания для цикла агента (err.name === "AbortError"). */
14
15
  export function newAbortError() {
15
16
  const e = new Error(t("tool.aborted", { name: "MoE execution" }));
16
17
  e.name = "AbortError";
@@ -28,10 +29,11 @@ function buildErrorDetail(stuckDetector, baseError, lastError) {
28
29
  }
29
30
  if (lastError) {
30
31
  errorDetail +=
31
- "\n\nIf relevant skills are available, consider loading one with load_skill for expert guidance.";
32
+ `\n\n${t("exec.skills_hint")}`;
32
33
  }
33
34
  return errorDetail;
34
35
  }
36
+ /** Топосорт подзадач в волны готовых (зависимости удовлетворены). Пусто при цикле. */
35
37
  export function topologicalSort(subtasks) {
36
38
  const sorted = [];
37
39
  const remaining = new Set(subtasks.map((s) => s.id));
@@ -95,6 +97,9 @@ async function executeSubtask(subtask, deps, depResults, sharedContext, onUsage)
95
97
  let lastError = "";
96
98
  const stuckDetector = new StuckDetector(maxAttempts * 2, maxAttempts);
97
99
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
100
+ // Стабильный id между попытками: передача `attempt` ресетила состояние
101
+ // детектора на каждом ретрае (новый stepId → resetStepState), ошибки тулов
102
+ // не накапливались и exhausted-retries диагностика всегда пустовала.
98
103
  stuckDetector.recordIteration(1);
99
104
  try {
100
105
  const allowedFiles = subtask.allowed_files || [];
@@ -143,15 +148,15 @@ async function executeSubtask(subtask, deps, depResults, sharedContext, onUsage)
143
148
  });
144
149
  if (result.success) {
145
150
  if (deps.config.subagent?.resultMode === "file") {
146
- // Structured field from the subagent tool — locale-independent
147
- // (parsing the localized output string broke under ru).
151
+ // Структурное поле из тула subagent — языконезависимо (парсинг
152
+ // локализованной строки вывода ломался под ru).
148
153
  const abs = result.artifactPath ?? "";
149
154
  if (abs) {
150
155
  const store = new ArtifactStore({
151
156
  baseDir: deps.baseDir,
152
157
  sessionId: deps.sessionId || "moe",
153
158
  });
154
- const full = store.read(abs.split(/[\\/]/).pop() || ""); // file name only, scoped to root
159
+ const full = store.read(abs.split(/[\\/]/).pop() || ""); // только имя файла, в jail root
155
160
  deps.logger.debug(`MoE subtask "${subtask.id}" attached artifact ${abs} (${full?.length ?? 0} chars) to Router`);
156
161
  return {
157
162
  subtaskId: subtask.id,
@@ -172,7 +177,7 @@ async function executeSubtask(subtask, deps, depResults, sharedContext, onUsage)
172
177
  }
173
178
  lastError = result.output;
174
179
  stuckDetector.recordToolError("subagent", result.output);
175
- // Inject actionable hints into the next retry's prompt
180
+ // Инжектим actionable-хинты в промпт следующего ретрая
176
181
  if (attempt < maxAttempts) {
177
182
  const hints = stuckDetector.getActionableHints();
178
183
  const recovery = stuckDetector.getRecoveryMessage();
@@ -186,10 +191,10 @@ async function executeSubtask(subtask, deps, depResults, sharedContext, onUsage)
186
191
  if (isTransientError(lastError) && attempt < maxAttempts) {
187
192
  const delay = backoffDelay(attempt - 1, 1000, 8000);
188
193
  deps.logger.debug(`Retrying subtask "${subtask.id}" (attempt ${attempt}/${maxAttempts}) after ${delay}ms: transient error`);
189
- await sleep(delay);
194
+ await sleep(delay, deps.signal);
190
195
  continue;
191
196
  }
192
- // Non-transient failure — build detailed error with hints
197
+ // Нетранзиентный фейл — собираем детальную ошибку с хинтами
193
198
  const errorDetail = buildErrorDetail(stuckDetector, result.output, lastError);
194
199
  return {
195
200
  subtaskId: subtask.id,
@@ -204,15 +209,15 @@ async function executeSubtask(subtask, deps, depResults, sharedContext, onUsage)
204
209
  catch (e) {
205
210
  lastError = e.message;
206
211
  stuckDetector.recordToolError("subagent", e.message);
207
- // User interrupt (Esc) is NEVER transient — propagate immediately so
208
- // the wave barrier and the agent loop see the abort instead of retrying.
212
+ // Прерывание юзера (Esc) — НИКОГДА не транзиент: пробрасываем сразу, чтобы
213
+ // барьер волны и цикл агента увидели abort вместо ретрая.
209
214
  if (e?.name === "AbortError") {
210
215
  throw e;
211
216
  }
212
217
  if (isTransientError(lastError) && attempt < maxAttempts) {
213
218
  const delay = backoffDelay(attempt - 1, 1000, 8000);
214
219
  deps.logger.debug(`Retrying subtask "${subtask.id}" (attempt ${attempt}/${maxAttempts}) after ${delay}ms: ${lastError}`);
215
- await sleep(delay);
220
+ await sleep(delay, deps.signal);
216
221
  continue;
217
222
  }
218
223
  const errorDetail = buildErrorDetail(stuckDetector, e.message, lastError);
@@ -226,7 +231,7 @@ async function executeSubtask(subtask, deps, depResults, sharedContext, onUsage)
226
231
  };
227
232
  }
228
233
  }
229
- // Exhausted retries — build detailed failure
234
+ // Ретраи исчерпаны — собираем итоговый фейл
230
235
  const stuckReason = stuckDetector.getStuckReason();
231
236
  let finalError = lastError;
232
237
  if (stuckReason) {
@@ -241,13 +246,14 @@ async function executeSubtask(subtask, deps, depResults, sharedContext, onUsage)
241
246
  durationMs: Date.now() - startTime,
242
247
  };
243
248
  }
249
+ /** Исполнитель MoE-плана: волны, параллелизм, scope-ретраи, usage по тегам. */
244
250
  export class MoEExecutor {
245
251
  deps;
246
252
  usageByTag = new Map();
247
253
  constructor(deps) {
248
254
  this.deps = deps;
249
255
  }
250
- /** Aggregated token usage per expert_tag across all executed subtasks. */
256
+ /** Агрегированный usage токенов по expert_tag всех исполненных подзадач. */
251
257
  getUsageByTag() {
252
258
  return Object.fromEntries(this.usageByTag);
253
259
  }
@@ -264,6 +270,14 @@ export class MoEExecutor {
264
270
  entry.subtasks += 1;
265
271
  this.usageByTag.set(expertTag, entry);
266
272
  }
273
+ /**
274
+ * Исполняет план волнами топосорта с капом параллелизма. Поддерживает
275
+ * селективный re-plan (skipIds + carriedResults). Abort (Esc) останавливает
276
+ * на барьере волны.
277
+ * @param opts.skipIds подзадачи, НЕ переисполняемые — их прошлые успешные
278
+ * результаты инжектятся как carriedResults, чтобы резолвились зависимости
279
+ * переисполняемых.
280
+ */
267
281
  async executePlan(plan, opts) {
268
282
  const skipIds = opts?.skipIds;
269
283
  const carried = opts?.carriedResults ?? [];
@@ -271,6 +285,12 @@ export class MoEExecutor {
271
285
  const errors = [];
272
286
  const warnings = [];
273
287
  const subtasks = skipIds && skipIds.size > 0 ? plan.subtasks.filter((s) => !skipIds.has(s.id)) : plan.subtasks;
288
+ // Селективный re-plan, где все подзадачи уже успешны: исполнять нечего.
289
+ // Раньше проваливалось в topologicalSort([]) и репортилось bogus
290
+ // "possible cycle", сжигая оставшиеся re-plan циклы.
291
+ if (subtasks.length === 0) {
292
+ return { success: true, results, errors: [], warnings };
293
+ }
274
294
  const waves = topologicalSort(subtasks);
275
295
  if (waves.length === 0) {
276
296
  return {
@@ -280,7 +300,7 @@ export class MoEExecutor {
280
300
  warnings: [],
281
301
  };
282
302
  }
283
- // Verify all subtasks are included — catch silent drops from unresolved dependencies
303
+ // Проверяем, что все подзадачи вошли — ловим молчаливые дропы от висячих зависимостей
284
304
  const sortedCount = waves.flat().length;
285
305
  if (sortedCount < subtasks.length) {
286
306
  const missing = subtasks
@@ -298,7 +318,7 @@ export class MoEExecutor {
298
318
  for (let waveIdx = 0; waveIdx < waves.length; waveIdx++) {
299
319
  const wave = waves[waveIdx];
300
320
  const depResults = new Map(results.map((r) => [r.subtaskId, r]));
301
- // Cap concurrent subtasks per wave (rateLimits.maxParallelTasks, default 5).
321
+ // Кап конкурентных подзадач на волну (rateLimits.maxParallelTasks, по умолчанию 5).
302
322
  const maxParallel = this.deps.config?.security?.rateLimits?.maxParallelTasks ?? 5;
303
323
  let active = 0;
304
324
  const waiters = [];
@@ -314,8 +334,8 @@ export class MoEExecutor {
314
334
  const wavePromises = wave.map(async (subtask) => {
315
335
  await acquire();
316
336
  if (this.deps.signal?.aborted) {
317
- // Checked after acquiring so subtasks queued behind an in-flight one
318
- // never start once Esc was pressed mid-wave.
337
+ // Проверяем после acquire: подзадачи, queued за летящей, не стартуют,
338
+ // если Esc нажат посреди волны.
319
339
  release();
320
340
  throw newAbortError();
321
341
  }
@@ -359,8 +379,8 @@ export class MoEExecutor {
359
379
  return result;
360
380
  });
361
381
  await Promise.all(wavePromises);
362
- // Wave barrier: once interrupted, stop before the next wave instead of
363
- // starting new sub-agents after Esc.
382
+ // Барьер волны: при прерывании встаём перед следующей волной, а не
383
+ // стартуем новых сабагентов после Esc.
364
384
  if (this.deps.signal?.aborted)
365
385
  throw newAbortError();
366
386
  }
@@ -377,13 +397,17 @@ export class MoEExecutor {
377
397
  };
378
398
  }
379
399
  /**
380
- * Scope expansion protocol (spec §Post-MVP): a failed sub-agent's
381
- * <scope-request> goes to the Router; approve extends the subtask scope and
382
- * re-executes ONLY this subtask, reject fails it (it can still be fixed by
383
- * a full re-plan). Expansion is capped — never automatic.
400
+ * Scope-протокол (спек §Post-MVP): <scope-request> упавшего сабагента идёт
401
+ * роутеру; approve расширяет scope подзадачи и переисполняет ТОЛЬКО её,
402
+ * reject фейлит её (чинится полным re-plan). Расширение капировано, не
403
+ * автоматически.
384
404
  */
385
405
  async resolveScopeAndRetry(subtask, failed, depResults, sharedContext) {
386
406
  let current = failed;
407
+ // Расширение scope применяем к ЛОКАЛЬНОЙ копии: оригинальный объект плана
408
+ // остаётся неизменным для verifier/re-plan (иначе верификация видит scope,
409
+ // которого не было в утверждённом плане).
410
+ let scoped = subtask;
387
411
  for (let cycle = 0; cycle < MAX_SCOPE_EXPANSION_CYCLES; cycle++) {
388
412
  const req = current.scopeRequest;
389
413
  if (!req)
@@ -396,10 +420,13 @@ export class MoEExecutor {
396
420
  error: `${current.error}\nRouter rejected scope request for files: ${req.files.join(", ")}`,
397
421
  };
398
422
  }
399
- subtask.allowed_files = uniq([...(subtask.allowed_files || []), ...decision.write]);
400
- subtask.read_only_files = uniq([...(subtask.read_only_files || []), ...decision.read]);
423
+ scoped = {
424
+ ...scoped,
425
+ allowed_files: uniq([...(scoped.allowed_files || []), ...decision.write]),
426
+ read_only_files: uniq([...(scoped.read_only_files || []), ...decision.read]),
427
+ };
401
428
  this.deps.logger.info?.(`MoE: approved scope expansion for "${subtask.id}": +write [${decision.write.join(", ")}] +read [${decision.read.join(", ")}]`);
402
- const retry = await executeSubtask(subtask, this.deps, depResults, sharedContext, (tag, usage) => this.recordUsage(tag, usage));
429
+ const retry = await executeSubtask(scoped, this.deps, depResults, sharedContext, (tag, usage) => this.recordUsage(tag, usage));
403
430
  if (retry.success || !retry.scopeRequest)
404
431
  return retry;
405
432
  current = retry;