micro-models-agent 2.16.1 → 2.17.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 (427) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/assets/app.js +1 -314
  3. package/dist/assets/hljs.js +5 -1244
  4. package/dist/assets/index.html +11 -0
  5. package/dist/assets/js/api.js +1 -28
  6. package/dist/assets/js/core/menus.js +1 -0
  7. package/dist/assets/js/core/store/feed.js +1 -0
  8. package/dist/assets/js/core/store/index.js +1 -0
  9. package/dist/assets/js/core/store/session.js +1 -0
  10. package/dist/assets/js/core/store/settings.js +1 -0
  11. package/dist/assets/js/core/store/tabs.js +1 -0
  12. package/dist/assets/js/dialog.js +1 -105
  13. package/dist/assets/js/dom.js +1 -178
  14. package/dist/assets/js/feed/core.js +1 -0
  15. package/dist/assets/js/feed/history.js +1 -0
  16. package/dist/assets/js/feed/plan.js +1 -0
  17. package/dist/assets/js/feed/question.js +3 -0
  18. package/dist/assets/js/feed/sidebar.js +1 -0
  19. package/dist/assets/js/feed/stream.js +1 -0
  20. package/dist/assets/js/feed/turn.js +5 -0
  21. package/dist/assets/js/feed.js +1 -1250
  22. package/dist/assets/js/format.js +2 -122
  23. package/dist/assets/js/i18n.js +1 -46
  24. package/dist/assets/js/rail.js +1 -114
  25. package/dist/assets/js/session/cmdk.js +1 -0
  26. package/dist/assets/js/session/composer.js +1 -0
  27. package/dist/assets/js/session/sessions-menu.js +1 -0
  28. package/dist/assets/js/session/tabs.js +1 -0
  29. package/dist/assets/js/settings/controls.js +1 -0
  30. package/dist/assets/js/settings/editors.js +1 -0
  31. package/dist/assets/js/settings/form.js +1 -0
  32. package/dist/assets/js/settings/modal.js +1 -0
  33. package/dist/assets/js/settings/panels.js +1 -0
  34. package/dist/assets/js/settings/providers.js +1 -0
  35. package/dist/assets/js/settings/search.js +1 -0
  36. package/dist/assets/js/settings/subdialog.js +1 -0
  37. package/dist/assets/js/settings/write.js +1 -0
  38. package/dist/assets/js/settings.js +1 -1914
  39. package/dist/assets/js/sidebar/core.js +1 -0
  40. package/dist/assets/js/sidebar/lsp.js +2 -0
  41. package/dist/assets/js/sidebar/map.js +1 -0
  42. package/dist/assets/js/sidebar/state.js +1 -0
  43. package/dist/assets/js/sidebar/trace.js +5 -0
  44. package/dist/assets/js/sidebar.js +1 -705
  45. package/dist/assets/js/store.js +1 -82
  46. package/dist/assets/js/subdialog.js +1 -0
  47. package/dist/assets/md.js +1 -291
  48. package/dist/assets/setup.js +3 -816
  49. package/dist/assets/smd.js +29 -1665
  50. package/dist/assets/styles.css +1 -1598
  51. package/dist/certification/certifications.json +1 -494
  52. package/dist/i18n/en.json +1 -1851
  53. package/dist/i18n/ru.json +1 -1854
  54. package/dist/main.js +815 -55797
  55. package/dist/modules/browser/bridge-server.mjs +2 -252
  56. package/package.json +10 -5
  57. package/dist/assets/js/settings-controls.js +0 -452
  58. package/dist/assets/js/tabs.js +0 -867
  59. package/dist/cli/cache-line.js +0 -31
  60. package/dist/cli/command-suggest.js +0 -39
  61. package/dist/cli/commands.js +0 -781
  62. package/dist/cli/completer.js +0 -268
  63. package/dist/cli/index.js +0 -3
  64. package/dist/cli/json-payload.js +0 -32
  65. package/dist/cli/main.js +0 -346
  66. package/dist/cli/onboarding-commands.js +0 -126
  67. package/dist/cli/plugin-commands.js +0 -38
  68. package/dist/cli/relaunch.js +0 -40
  69. package/dist/cli/repl-commands-lsp.js +0 -75
  70. package/dist/cli/repl-commands-skills.js +0 -105
  71. package/dist/cli/repl-commands.js +0 -1218
  72. package/dist/cli/repl.js +0 -1238
  73. package/dist/cli/run-result.js +0 -38
  74. package/dist/cli/security-commands.js +0 -177
  75. package/dist/cli/setup-order.js +0 -6
  76. package/dist/cli/setup-prompt.js +0 -50
  77. package/dist/cli/setup.js +0 -161
  78. package/dist/cli/web-command.js +0 -98
  79. package/dist/config/budget.js +0 -48
  80. package/dist/config/config.js +0 -345
  81. package/dist/config/defaults.js +0 -197
  82. package/dist/config/domains.js +0 -135
  83. package/dist/config/env.js +0 -46
  84. package/dist/config/experts.js +0 -17
  85. package/dist/config/index.js +0 -5
  86. package/dist/config/paths.js +0 -56
  87. package/dist/config/redact.js +0 -44
  88. package/dist/config/registry-extra.js +0 -334
  89. package/dist/config/registry.js +0 -584
  90. package/dist/config/security.js +0 -212
  91. package/dist/config/timeouts.js +0 -74
  92. package/dist/config/types.js +0 -1
  93. package/dist/config/utils.js +0 -57
  94. package/dist/core/agent/artifact-progress.js +0 -59
  95. package/dist/core/agent/artifact-resolve.js +0 -79
  96. package/dist/core/agent/audit-gate.js +0 -53
  97. package/dist/core/agent/compaction.js +0 -89
  98. package/dist/core/agent/constants.js +0 -90
  99. package/dist/core/agent/context-log.js +0 -454
  100. package/dist/core/agent/context-renderer.js +0 -45
  101. package/dist/core/agent/critic-gate.js +0 -132
  102. package/dist/core/agent/hallucination-gate.js +0 -197
  103. package/dist/core/agent/loop-state.js +0 -68
  104. package/dist/core/agent/prefix-monitor.js +0 -101
  105. package/dist/core/agent/reasoning-resolver.js +0 -65
  106. package/dist/core/agent/token-tracker.js +0 -99
  107. package/dist/core/agent/tool-batch.js +0 -312
  108. package/dist/core/agent/tool-images.js +0 -18
  109. package/dist/core/agent/tool-output.js +0 -116
  110. package/dist/core/agent/tool-pairing.js +0 -60
  111. package/dist/core/agent-moe.js +0 -248
  112. package/dist/core/agent.js +0 -1299
  113. package/dist/core/bootstrap/agent-phase.js +0 -66
  114. package/dist/core/bootstrap/config-phase.js +0 -86
  115. package/dist/core/bootstrap/modules-phase.js +0 -269
  116. package/dist/core/bootstrap/provider-phase.js +0 -183
  117. package/dist/core/bootstrap/session-phase.js +0 -204
  118. package/dist/core/bootstrap/state.js +0 -94
  119. package/dist/core/bootstrap/workspace-phase.js +0 -115
  120. package/dist/core/bootstrap.js +0 -112
  121. package/dist/core/crash-handler.js +0 -62
  122. package/dist/core/environment.js +0 -224
  123. package/dist/core/host-plan.js +0 -43
  124. package/dist/core/host.js +0 -23
  125. package/dist/core/index.js +0 -3
  126. package/dist/core/prompt-builder.js +0 -95
  127. package/dist/core/prompt-overflow.js +0 -306
  128. package/dist/core/session-logger.js +0 -375
  129. package/dist/core/system-prompt.js +0 -117
  130. package/dist/core/types.js +0 -1
  131. package/dist/core/version.js +0 -28
  132. package/dist/core/web-host.js +0 -34
  133. package/dist/core/workspace.js +0 -80
  134. package/dist/i18n/index.js +0 -80
  135. package/dist/index.js +0 -30
  136. package/dist/llm/cache-usage.js +0 -76
  137. package/dist/llm/image-utils.js +0 -138
  138. package/dist/llm/index.js +0 -4
  139. package/dist/llm/llm-errors.js +0 -50
  140. package/dist/llm/model-loader.js +0 -86
  141. package/dist/llm/models-dev.js +0 -121
  142. package/dist/llm/openai-compat.js +0 -756
  143. package/dist/llm/orchestrator.js +0 -294
  144. package/dist/llm/provider-budget.js +0 -68
  145. package/dist/llm/provider-context.js +0 -233
  146. package/dist/llm/provider.js +0 -9
  147. package/dist/llm/response.js +0 -44
  148. package/dist/llm/stream-state.js +0 -26
  149. package/dist/llm/token-counter.js +0 -83
  150. package/dist/llm/types.js +0 -1
  151. package/dist/logger/app-logger.js +0 -212
  152. package/dist/logger/file-log.js +0 -160
  153. package/dist/logger/index.js +0 -2
  154. package/dist/migration/backup.js +0 -56
  155. package/dist/migration/detect.js +0 -61
  156. package/dist/migration/index.js +0 -3
  157. package/dist/modules/artifacts/store.js +0 -62
  158. package/dist/modules/browser/actions.js +0 -79
  159. package/dist/modules/browser/bridge-client.js +0 -203
  160. package/dist/modules/browser/bridge-path.js +0 -10
  161. package/dist/modules/browser/console-buffer.js +0 -37
  162. package/dist/modules/browser/cookie-store.js +0 -29
  163. package/dist/modules/browser/driver-types.js +0 -1
  164. package/dist/modules/browser/driver.js +0 -186
  165. package/dist/modules/browser/index.js +0 -9
  166. package/dist/modules/browser/module.js +0 -30
  167. package/dist/modules/browser/session.js +0 -322
  168. package/dist/modules/browser/snapshot.js +0 -154
  169. package/dist/modules/browser/types.js +0 -13
  170. package/dist/modules/certification/cli.js +0 -264
  171. package/dist/modules/certification/fact-checker.js +0 -90
  172. package/dist/modules/certification/loader.js +0 -127
  173. package/dist/modules/certification/manifest.js +0 -231
  174. package/dist/modules/certification/runner.js +0 -233
  175. package/dist/modules/certification/scenarios.js +0 -586
  176. package/dist/modules/certification/syntax-scenarios.js +0 -50
  177. package/dist/modules/certification/types.js +0 -1
  178. package/dist/modules/context/chunk-query.js +0 -122
  179. package/dist/modules/context/fact-extractor.js +0 -170
  180. package/dist/modules/context/history.js +0 -15
  181. package/dist/modules/context/index.js +0 -2
  182. package/dist/modules/context/manager.js +0 -482
  183. package/dist/modules/critic/client.js +0 -176
  184. package/dist/modules/critic/evidence.js +0 -81
  185. package/dist/modules/critic/provider.js +0 -45
  186. package/dist/modules/critic/tools.js +0 -78
  187. package/dist/modules/critic/types.js +0 -1
  188. package/dist/modules/execution/audit-runners.js +0 -206
  189. package/dist/modules/execution/auditor.js +0 -222
  190. package/dist/modules/execution/execution-plugin.js +0 -478
  191. package/dist/modules/execution/index.js +0 -8
  192. package/dist/modules/execution/input-from.js +0 -70
  193. package/dist/modules/execution/module.js +0 -891
  194. package/dist/modules/execution/moe-executor.js +0 -443
  195. package/dist/modules/execution/plan-actions.js +0 -642
  196. package/dist/modules/execution/plan-checks.js +0 -35
  197. package/dist/modules/execution/plan-coverage.js +0 -71
  198. package/dist/modules/execution/plan-persister.js +0 -46
  199. package/dist/modules/execution/plan-steps.js +0 -31
  200. package/dist/modules/execution/plan-store.js +0 -274
  201. package/dist/modules/execution/plan-tool.js +0 -249
  202. package/dist/modules/execution/plan-validator.js +0 -197
  203. package/dist/modules/execution/planner.js +0 -103
  204. package/dist/modules/execution/stuck-detector.js +0 -834
  205. package/dist/modules/execution/tracker.js +0 -92
  206. package/dist/modules/execution/transient-error.js +0 -30
  207. package/dist/modules/execution/types.js +0 -1
  208. package/dist/modules/execution/verifier.js +0 -343
  209. package/dist/modules/execution/windows-commands.js +0 -52
  210. package/dist/modules/hallucination/artifact-claim.js +0 -93
  211. package/dist/modules/hallucination/confidence.js +0 -81
  212. package/dist/modules/hallucination/consistency.js +0 -37
  213. package/dist/modules/hallucination/detector.js +0 -57
  214. package/dist/modules/hallucination/factual.js +0 -205
  215. package/dist/modules/hallucination/index.js +0 -6
  216. package/dist/modules/hallucination/js-identifiers.js +0 -261
  217. package/dist/modules/hallucination/llm-judge.js +0 -116
  218. package/dist/modules/hallucination/success-claim.js +0 -59
  219. package/dist/modules/index.js +0 -5
  220. package/dist/modules/indexer/cache.js +0 -88
  221. package/dist/modules/indexer/index.js +0 -4
  222. package/dist/modules/indexer/map-command.js +0 -33
  223. package/dist/modules/indexer/map-select.js +0 -87
  224. package/dist/modules/indexer/module.js +0 -293
  225. package/dist/modules/indexer/project-profile.js +0 -184
  226. package/dist/modules/indexer/symbols.js +0 -189
  227. package/dist/modules/indexer/walker.js +0 -285
  228. package/dist/modules/lsp/check-tool.js +0 -61
  229. package/dist/modules/lsp/client.js +0 -406
  230. package/dist/modules/lsp/command.js +0 -53
  231. package/dist/modules/lsp/config.js +0 -189
  232. package/dist/modules/lsp/index.js +0 -4
  233. package/dist/modules/lsp/module.js +0 -295
  234. package/dist/modules/lsp/probe.js +0 -86
  235. package/dist/modules/lsp/project-root.js +0 -69
  236. package/dist/modules/lsp/startup-check.js +0 -154
  237. package/dist/modules/lsp/types.js +0 -1
  238. package/dist/modules/mcp/client.js +0 -445
  239. package/dist/modules/mcp/index.js +0 -4
  240. package/dist/modules/mcp/module.js +0 -295
  241. package/dist/modules/mcp/registry.js +0 -20
  242. package/dist/modules/memory/index.js +0 -2
  243. package/dist/modules/memory/module.js +0 -101
  244. package/dist/modules/memory/search.js +0 -45
  245. package/dist/modules/memory/store.js +0 -107
  246. package/dist/modules/onboarding/init.js +0 -47
  247. package/dist/modules/onboarding/meet.js +0 -30
  248. package/dist/modules/onboarding/mode.js +0 -30
  249. package/dist/modules/onboarding/prompts.js +0 -43
  250. package/dist/modules/pipelines/engine.js +0 -70
  251. package/dist/modules/pipelines/index.js +0 -4
  252. package/dist/modules/pipelines/parser.js +0 -59
  253. package/dist/modules/pipelines/template.js +0 -18
  254. package/dist/modules/plugins/builtin/lint-on-write.js +0 -377
  255. package/dist/modules/plugins/builtin/notify.js +0 -11
  256. package/dist/modules/plugins/index.js +0 -2
  257. package/dist/modules/plugins/loader.js +0 -85
  258. package/dist/modules/plugins/manager.js +0 -244
  259. package/dist/modules/plugins/types.js +0 -1
  260. package/dist/modules/pricing/index.js +0 -70
  261. package/dist/modules/pricing/prices.js +0 -147
  262. package/dist/modules/processes/detect.js +0 -34
  263. package/dist/modules/processes/index.js +0 -4
  264. package/dist/modules/processes/kill-tree.js +0 -52
  265. package/dist/modules/processes/registry.js +0 -294
  266. package/dist/modules/processes/runner.js +0 -23
  267. package/dist/modules/providers/cache.js +0 -23
  268. package/dist/modules/providers/capabilities.js +0 -28
  269. package/dist/modules/providers/create.js +0 -21
  270. package/dist/modules/providers/factory.js +0 -28
  271. package/dist/modules/providers/fallback.js +0 -81
  272. package/dist/modules/providers/health.js +0 -47
  273. package/dist/modules/providers/index.js +0 -6
  274. package/dist/modules/providers/manager.js +0 -207
  275. package/dist/modules/providers/naming.js +0 -15
  276. package/dist/modules/providers/preflight.js +0 -71
  277. package/dist/modules/providers/presets.js +0 -232
  278. package/dist/modules/providers/registry.js +0 -27
  279. package/dist/modules/providers/types.js +0 -1
  280. package/dist/modules/reasoning/policy.js +0 -42
  281. package/dist/modules/reasoning/probe.js +0 -116
  282. package/dist/modules/registry.js +0 -48
  283. package/dist/modules/security/audit-log.js +0 -119
  284. package/dist/modules/security/audit-notifier.js +0 -267
  285. package/dist/modules/security/command-validator.js +0 -272
  286. package/dist/modules/security/content-scanner.js +0 -53
  287. package/dist/modules/security/data-sanitizer.js +0 -82
  288. package/dist/modules/security/encryption.js +0 -216
  289. package/dist/modules/security/index.js +0 -15
  290. package/dist/modules/security/network-validator.js +0 -236
  291. package/dist/modules/security/path-validator.js +0 -261
  292. package/dist/modules/security/protected-paths.js +0 -73
  293. package/dist/modules/security/rate-limiter.js +0 -98
  294. package/dist/modules/security/security-policies.js +0 -499
  295. package/dist/modules/security/session-encryption.js +0 -182
  296. package/dist/modules/security/session-isolation.js +0 -75
  297. package/dist/modules/session/auto-name.js +0 -63
  298. package/dist/modules/session/export.js +0 -98
  299. package/dist/modules/session/index.js +0 -4
  300. package/dist/modules/session/manager.js +0 -234
  301. package/dist/modules/session/module.js +0 -33
  302. package/dist/modules/session/store.js +0 -295
  303. package/dist/modules/session/types.js +0 -1
  304. package/dist/modules/setup/answers.js +0 -35
  305. package/dist/modules/setup/apply.js +0 -79
  306. package/dist/modules/setup/discovery.js +0 -72
  307. package/dist/modules/skills/index.js +0 -3
  308. package/dist/modules/skills/loader.js +0 -86
  309. package/dist/modules/skills/matcher.js +0 -27
  310. package/dist/modules/skills/module.js +0 -141
  311. package/dist/modules/types.js +0 -1
  312. package/dist/modules/updater/changelog-reader.js +0 -93
  313. package/dist/modules/updater/checker.js +0 -101
  314. package/dist/modules/updater/dev-detect.js +0 -18
  315. package/dist/modules/updater/index.js +0 -4
  316. package/dist/modules/updater/module.js +0 -129
  317. package/dist/modules/user-profile/compressor.js +0 -18
  318. package/dist/modules/user-profile/index.js +0 -2
  319. package/dist/modules/user-profile/profile.js +0 -77
  320. package/dist/modules/webui/answer-api.js +0 -29
  321. package/dist/modules/webui/assets.js +0 -50
  322. package/dist/modules/webui/body.js +0 -21
  323. package/dist/modules/webui/commands-settings.js +0 -209
  324. package/dist/modules/webui/commands-shared.js +0 -60
  325. package/dist/modules/webui/commands.js +0 -174
  326. package/dist/modules/webui/config-api.js +0 -134
  327. package/dist/modules/webui/file-api.js +0 -202
  328. package/dist/modules/webui/forward.js +0 -159
  329. package/dist/modules/webui/history-api.js +0 -112
  330. package/dist/modules/webui/host-state.js +0 -60
  331. package/dist/modules/webui/i18n-api.js +0 -9
  332. package/dist/modules/webui/limits.js +0 -6
  333. package/dist/modules/webui/log-forward.js +0 -20
  334. package/dist/modules/webui/memory-commands.js +0 -64
  335. package/dist/modules/webui/model-cache.js +0 -18
  336. package/dist/modules/webui/module.js +0 -148
  337. package/dist/modules/webui/persist.js +0 -24
  338. package/dist/modules/webui/prompt-io.js +0 -97
  339. package/dist/modules/webui/providers-api.js +0 -337
  340. package/dist/modules/webui/providers-view.js +0 -56
  341. package/dist/modules/webui/reasoning-view.js +0 -15
  342. package/dist/modules/webui/run-agent.js +0 -81
  343. package/dist/modules/webui/server.js +0 -284
  344. package/dist/modules/webui/sessions-api.js +0 -178
  345. package/dist/modules/webui/settings-api.js +0 -561
  346. package/dist/modules/webui/setup-api.js +0 -201
  347. package/dist/modules/webui/state.js +0 -74
  348. package/dist/modules/webui/util.js +0 -261
  349. package/dist/output/bus.js +0 -37
  350. package/dist/output/channel.js +0 -285
  351. package/dist/output/format.js +0 -15
  352. package/dist/output/index.js +0 -8
  353. package/dist/output/json-sink.js +0 -24
  354. package/dist/output/machine.js +0 -9
  355. package/dist/output/session-sink.js +0 -27
  356. package/dist/output/types.js +0 -1
  357. package/dist/tools/approve.js +0 -41
  358. package/dist/tools/attach-image.js +0 -102
  359. package/dist/tools/auto-fixer.js +0 -180
  360. package/dist/tools/auto-tags.js +0 -83
  361. package/dist/tools/bash.js +0 -649
  362. package/dist/tools/browser.js +0 -160
  363. package/dist/tools/chunk-query.js +0 -112
  364. package/dist/tools/create-dir.js +0 -60
  365. package/dist/tools/delete-file.js +0 -67
  366. package/dist/tools/download-file.js +0 -142
  367. package/dist/tools/edit-file.js +0 -136
  368. package/dist/tools/enable-tools.js +0 -59
  369. package/dist/tools/executor.js +0 -304
  370. package/dist/tools/file-info.js +0 -49
  371. package/dist/tools/filter-tools.js +0 -17
  372. package/dist/tools/glob-tool.js +0 -37
  373. package/dist/tools/grep-tool.js +0 -142
  374. package/dist/tools/hidden-tools-block.js +0 -37
  375. package/dist/tools/index.js +0 -88
  376. package/dist/tools/list-dir.js +0 -53
  377. package/dist/tools/load-skill.js +0 -51
  378. package/dist/tools/mcp-call.js +0 -80
  379. package/dist/tools/meet-done.js +0 -14
  380. package/dist/tools/move-file.js +0 -94
  381. package/dist/tools/path-utils.js +0 -108
  382. package/dist/tools/pipeline-run.js +0 -167
  383. package/dist/tools/preview.js +0 -2
  384. package/dist/tools/process-ids.js +0 -31
  385. package/dist/tools/process-kill.js +0 -33
  386. package/dist/tools/process-list.js +0 -38
  387. package/dist/tools/process-log.js +0 -49
  388. package/dist/tools/process-wait.js +0 -63
  389. package/dist/tools/prompt-io.js +0 -29
  390. package/dist/tools/question.js +0 -288
  391. package/dist/tools/read-file.js +0 -200
  392. package/dist/tools/recall.js +0 -124
  393. package/dist/tools/registry.js +0 -48
  394. package/dist/tools/remember.js +0 -72
  395. package/dist/tools/scope-check.js +0 -32
  396. package/dist/tools/scope-request.js +0 -96
  397. package/dist/tools/search-history.js +0 -88
  398. package/dist/tools/session-info.js +0 -46
  399. package/dist/tools/set-thinking.js +0 -75
  400. package/dist/tools/subagent.js +0 -257
  401. package/dist/tools/syntax-validator.js +0 -379
  402. package/dist/tools/types.js +0 -1
  403. package/dist/tools/user-input.js +0 -134
  404. package/dist/tools/web-browse.js +0 -93
  405. package/dist/tools/web-fetch.js +0 -108
  406. package/dist/tools/web-search.js +0 -107
  407. package/dist/tools/write-file.js +0 -128
  408. package/dist/ui/action-log.js +0 -13
  409. package/dist/ui/box.js +0 -78
  410. package/dist/ui/colors.js +0 -6
  411. package/dist/ui/diff.js +0 -189
  412. package/dist/ui/index.js +0 -7
  413. package/dist/ui/line-editor.js +0 -1083
  414. package/dist/ui/line-math.js +0 -98
  415. package/dist/ui/md-formatter.js +0 -322
  416. package/dist/ui/output.js +0 -19
  417. package/dist/ui/plan-view.js +0 -109
  418. package/dist/ui/renderer.js +0 -589
  419. package/dist/ui/spinner.js +0 -91
  420. package/dist/ui/table.js +0 -142
  421. package/dist/ui/theme.js +0 -143
  422. package/dist/utils/child-run.js +0 -20
  423. package/dist/utils/error.js +0 -4
  424. package/dist/utils/index.js +0 -6
  425. package/dist/utils/retry.js +0 -17
  426. package/dist/utils/sleep.js +0 -23
  427. package/dist/utils/truncate.js +0 -9
@@ -1,834 +0,0 @@
1
- // Детектор застревания: повторы, фейлы, read-only петли, bash-флейлинг, хинты.
2
- import { t } from "../../i18n/index";
3
- import { isTransientError } from "./transient-error";
4
- const BLOCKING_PATTERNS = [
5
- /EACCES/i,
6
- /permission denied/i,
7
- /EPERM/i,
8
- /ENOENT.*node_modules/i,
9
- /ENOTDIR/i,
10
- /invalid.*token/i,
11
- /unauthorized/i,
12
- /401/i,
13
- /403/i,
14
- ];
15
- /** Классифицирует вывод ошибки: транзиентная / блокирующая / системная. */
16
- export function classifyError(output) {
17
- if (isTransientError(output))
18
- return "transient";
19
- for (const p of BLOCKING_PATTERNS) {
20
- if (p.test(output))
21
- return "blocking";
22
- }
23
- return "systematic";
24
- }
25
- /**
26
- * Тулы только чтения: состояние наблюдают, не меняют. Длинная серия только их
27
- * без write/exec между — модель читает/разведывает, ничего не производя:
28
- * read-only петля, которую детектор обязан подсветить (было: 50+ read_file
29
- * итераций с нулём записей после ложноположительного реджекта готового
30
- * аудита задачи).
31
- */
32
- const READ_ONLY_TOOLS = new Set([
33
- "read_file",
34
- "glob",
35
- "grep",
36
- "list_dir",
37
- "file_info",
38
- "browser",
39
- "web_search",
40
- "web_fetch",
41
- "web_browse",
42
- "search_history",
43
- "recall",
44
- "project_map",
45
- "chunk_query",
46
- "process_list",
47
- "process_log",
48
- "plan",
49
- "plan_step",
50
- "todo",
51
- "verify",
52
- "load_skill",
53
- ]);
54
- /** Подряд read-only вызовов, образующих петлю. */
55
- const READ_ONLY_LOOP_THRESHOLD = 10;
56
- /**
57
- * Bash-флейлинг: ≥BASH_FLAIL_THRESHOLD фейлов в последних BASH_FLAIL_WINDOW
58
- * bash-попытках, независимо от перемежающихся успехов. Per-word hard-stop
59
- * (bash.ts) обходится ротацией команд (wc → cat → Get-Content → …); окно
60
- * ловит саму ротацию (было в ses_mt4x3zbo: 8 фейловых shell-уловок за ~12
61
- * итераций при подсчёте/склейке файлов на Windows).
62
- */
63
- const BASH_FLAIL_WINDOW = 6;
64
- const BASH_FLAIL_THRESHOLD = 4;
65
- const ANSI_RE = /\x1b\[[0-9;]*m/g;
66
- /** Пути (абсолютные/относительные) + опционально :line:col. */
67
- const ERROR_LOC_RE = /(?:[A-Za-z]:[\\/])?(?:[\w.@+-]+[\\/])+[\w.@+-]+\.[a-zA-Z0-9]{1,6}(?::\d+(?::\d+)?)?/g;
68
- const SIGNATURE_MAX_CHARS = 120;
69
- const SEARCHABLE_PATTERNS = [
70
- /error TS\d+/i,
71
- /ERR_[A-Z_]+/,
72
- /ENOENT|EACCES|EPERM|ECONNREFUSED|ETIMEDOUT|ECONNRESET|ENOTFOUND|EADDRINUSE/i,
73
- /Cannot find module|Module not found|ERR_MODULE_NOT_FOUND/i,
74
- /TypeError|ReferenceError|SyntaxError|RangeError/i,
75
- /is not a function|is not defined|is not a constructor/i,
76
- /Cannot read properties of/i,
77
- /failed to (compile|build|resolve|parse)/i,
78
- /fatal error|panic/i,
79
- ];
80
- const RUNTIME_WORDS = [
81
- "bun",
82
- "node",
83
- "deno",
84
- "npm",
85
- "yarn",
86
- "pnpm",
87
- "pip",
88
- "pip3",
89
- "python",
90
- "python3",
91
- "tsc",
92
- "tsx",
93
- "npx",
94
- "go",
95
- "cargo",
96
- "gradle",
97
- "maven",
98
- "make",
99
- ];
100
- const FRAMEWORK_WORDS = [
101
- "react",
102
- "vue",
103
- "angular",
104
- "svelte",
105
- "vite",
106
- "next",
107
- "nest",
108
- "express",
109
- "fastify",
110
- "flask",
111
- "django",
112
- "spring",
113
- "webpack",
114
- "tailwind",
115
- ];
116
- /**
117
- * Стабильная идентичность ошибки: тул + нормализованные первые error-строки
118
- * (ANSI вычищен, пути/локации заменены, пробелы склеены, кап 120 символов).
119
- * Два прогона с одной первопричиной дают одну сигнатуру — она и триггерит
120
- * автопоиск в вебе.
121
- */
122
- export function normalizeErrorSignature(toolName, output) {
123
- if (!output)
124
- return null;
125
- const cleaned = output
126
- .replace(ANSI_RE, "")
127
- .replace(ERROR_LOC_RE, " <path>")
128
- .split("\n")
129
- .map((l) => l.trim())
130
- .filter(Boolean)
131
- .join(" ")
132
- .replace(/\s+/g, " ")
133
- .trim();
134
- if (!cleaned)
135
- return null;
136
- return `${toolName}::${cleaned.slice(0, SIGNATURE_MAX_CHARS)}`;
137
- }
138
- /**
139
- * Гейт автопоиска в вебе: искать стоит только реальный содержательный текст
140
- * ошибки. "Command failed with exit code 1" без деталей — шум, поиск по нему
141
- * лишь жжёт запрос.
142
- */
143
- export function isSearchableError(output) {
144
- if (!output?.trim())
145
- return false;
146
- const text = output.trim();
147
- return SEARCHABLE_PATTERNS.some((p) => p.test(text));
148
- }
149
- /**
150
- * Строит поисковый запрос по падающей ошибке: до 3 чищенных error-строк (пути
151
- * вырезаны) с префиксом рантайма/фреймворка из step/bash-контекста и суффиксом
152
- * "how to fix". На пустом тексте — фолбэк `tool step`. Кап maxQueryChars.
153
- */
154
- export function buildSearchQuery(stepDescription, lastBashCommand, lastErrorOutput, toolName, maxQueryChars) {
155
- const errorText = (lastErrorOutput || "")
156
- .replace(ANSI_RE, "")
157
- .replace(ERROR_LOC_RE, " <path>")
158
- .split("\n")
159
- .map((l) => l.trim())
160
- .filter(Boolean)
161
- .slice(0, 3)
162
- .join(" ")
163
- .replace(/\s+/g, " ")
164
- .trim();
165
- const context = `${stepDescription} ${lastBashCommand}`.toLowerCase();
166
- const runtime = RUNTIME_WORDS.find((w) => context.includes(w)) || "";
167
- const framework = FRAMEWORK_WORDS.find((w) => context.includes(w)) || "";
168
- let query;
169
- if (errorText) {
170
- query =
171
- runtime && !errorText.toLowerCase().includes(runtime) ? `${runtime} ${errorText}` : errorText;
172
- if (framework && !query.toLowerCase().includes(framework))
173
- query = `${query} ${framework}`;
174
- query = `${query} how to fix`;
175
- }
176
- else if (runtime || framework) {
177
- query = `${[runtime, framework, "error", "how to fix"].filter(Boolean).join(" ")}`;
178
- }
179
- else {
180
- query = `${toolName} ${stepDescription} how to fix`;
181
- }
182
- return query.slice(0, maxQueryChars);
183
- }
184
- /** Детектор застревания: счётчики итераций, ошибок, повторов, петель, эскалаций. */
185
- export class StuckDetector {
186
- threshold;
187
- errorThreshold;
188
- iterationsOnCurrentStep = 0;
189
- currentStepId = null;
190
- toolErrors = new Map();
191
- currentStepDescription = "";
192
- recentToolCalls = [];
193
- maxRecentCalls = 10;
194
- repetitionThreshold = 3;
195
- consecutiveFailures = 0;
196
- lastFailedTool = "";
197
- lastErrorOutput = "";
198
- escalationCount = 0;
199
- escalationThreshold = 3;
200
- fileRewriteCount = new Map();
201
- fileRewriteThreshold = 3;
202
- lastBashCommand = "";
203
- lastBashOutput = "";
204
- emptyBashRunCount = 0;
205
- readOnlyStreak = 0;
206
- bashRecent = [];
207
- errorSignatureCounts = new Map();
208
- searchedErrorSignatures = new Set();
209
- webSearchThreshold;
210
- constructor(threshold = 6, errorThreshold = 3, webSearchThreshold = 5) {
211
- this.threshold = threshold;
212
- this.errorThreshold = errorThreshold;
213
- this.webSearchThreshold = webSearchThreshold;
214
- }
215
- recordIteration(stepId) {
216
- if (stepId === this.currentStepId) {
217
- this.iterationsOnCurrentStep++;
218
- }
219
- else {
220
- this.resetStepState(stepId);
221
- }
222
- }
223
- /** Отмечает вызов тула (для детекции повторов; write/exec сбрасывают read-only стрик). */
224
- recordToolCall(name, args) {
225
- const argsKey = JSON.stringify(args);
226
- this.recentToolCalls.push({ name, argsKey });
227
- if (this.recentToolCalls.length > this.maxRecentCalls) {
228
- this.recentToolCalls.shift();
229
- }
230
- // Трекаем подряд read-only стрик. Пишущий/исполняющий тул сбрасывает;
231
- // plan/todo-бухгалтерия считается read-only (не реальный прогресс).
232
- if (READ_ONLY_TOOLS.has(name)) {
233
- this.readOnlyStreak++;
234
- }
235
- else {
236
- this.readOnlyStreak = 0;
237
- }
238
- }
239
- /**
240
- * True после длинной серии read-only вызовов без записей между. Модель
241
- * исследует/петляет, ничего не производя — инжектим recovery-хинт, чтобы
242
- * перестала перечитывать и реально правила файлы.
243
- */
244
- hasReadOnlyLoop() {
245
- return this.readOnlyStreak >= READ_ONLY_LOOP_THRESHOLD;
246
- }
247
- /** Отмечает ошибку тула (счётчики + сигнатура для автопоиска). */
248
- recordToolError(toolName, output) {
249
- this.toolErrors.set(toolName, (this.toolErrors.get(toolName) || 0) + 1);
250
- this.consecutiveFailures++;
251
- this.lastFailedTool = toolName;
252
- if (output)
253
- this.lastErrorOutput = output;
254
- const sig = normalizeErrorSignature(toolName, output);
255
- if (sig) {
256
- this.errorSignatureCounts.set(sig, (this.errorSignatureCounts.get(sig) || 0) + 1);
257
- }
258
- }
259
- /** Последний текст ошибки. */
260
- getLastErrorOutput() {
261
- return this.lastErrorOutput;
262
- }
263
- /**
264
- * Записывает КАЖДЫЙ вызов bash (успех или нет): детекция рассуждает о
265
- * повторных прогонах с пустым выводом, проблемах entry-point и ошибках
266
- * платформы (PowerShell-командлеты в cmd.exe, bash-heredoc'и, …).
267
- */
268
- recordBashOutput(command, output) {
269
- const trimmed = output.trim();
270
- if (command === this.lastBashCommand && !trimmed) {
271
- this.emptyBashRunCount++;
272
- }
273
- else {
274
- this.emptyBashRunCount = 0;
275
- }
276
- this.lastBashCommand = command;
277
- this.lastBashOutput = output;
278
- }
279
- /** Исход одной bash-попытки (успех/фейл) — для детекции флейлинга. */
280
- recordBashAttempt(success) {
281
- this.bashRecent.push(success);
282
- if (this.bashRecent.length > BASH_FLAIL_WINDOW)
283
- this.bashRecent.shift();
284
- }
285
- /** True, если свежие bash-попытки в массе фейлятся — модель флейлит. */
286
- hasBashFlailing() {
287
- if (this.bashRecent.length < BASH_FLAIL_THRESHOLD)
288
- return false;
289
- let failures = 0;
290
- for (const ok of this.bashRecent)
291
- if (!ok)
292
- failures++;
293
- return failures >= BASH_FLAIL_THRESHOLD;
294
- }
295
- /** Последняя bash-команда. */
296
- getLastBashCommand() {
297
- return this.lastBashCommand;
298
- }
299
- /** Вывод последней bash-команды. */
300
- getLastBashOutput() {
301
- return this.lastBashOutput;
302
- }
303
- /** Последний упавший тул. */
304
- getLastFailedTool() {
305
- return this.lastFailedTool;
306
- }
307
- /**
308
- * Первая сигнатура ошибки, чей счётчик повторов достиг порога веб-поиска и
309
- * которая ЕЩЁ не искалась (или размаркирована для ретрая). Именно она
310
- * триггерит автопоиск — не итерации и не per-tool счётчик ошибок.
311
- */
312
- getRepeatedErrorSignature() {
313
- for (const [sig, count] of this.errorSignatureCounts) {
314
- if (count >= this.webSearchThreshold && !this.searchedErrorSignatures.has(sig)) {
315
- return sig;
316
- }
317
- }
318
- return null;
319
- }
320
- /** Счётчик повторов сигнатуры ошибки. */
321
- getErrorSignatureCount(sig) {
322
- return this.errorSignatureCounts.get(sig) || 0;
323
- }
324
- /** Помечает сигнатуру как уже искавшуюся. */
325
- markErrorSearched(sig) {
326
- this.searchedErrorSignatures.add(sig);
327
- }
328
- /** Снимает метку поиска (разрешает один ретрай). */
329
- unmarkErrorSearched(sig) {
330
- this.searchedErrorSignatures.delete(sig);
331
- }
332
- /** True, если сигнатура уже искалась. */
333
- hasErrorSearched(sig) {
334
- return this.searchedErrorSignatures.has(sig);
335
- }
336
- /** Итераций на текущем шаге. */
337
- getIterationsOnCurrentStep() {
338
- return this.iterationsOnCurrentStep;
339
- }
340
- /** Отмечает успешный тул: сброс фейлов, затухание per-tool счётчиков и итераций. */
341
- recordToolSuccess() {
342
- this.consecutiveFailures = 0;
343
- this.lastFailedTool = "";
344
- // NOTE: escalationCount осознанно НЕ сбрасываем. Один тривиальный успех
345
- // (напр. один read_file) раньше его чистил, и shouldEscalate() на флейлящей
346
- // сессии почти не достигался — в ущерб анти-гейминг свойству, которое
347
- // resetStepState() явно хранит.
348
- // Затухание per-tool счётчиков на продуктивных вызовах: рано упавший тул не
349
- // держит варнинг "Tool X failed N times" вечно (ses_mt4fn58c — bash упал 3x,
350
- // варнинг перелоггировался после 30 успешных записей). Свежие фейлы счёт
351
- // набирают заново.
352
- for (const [tool, count] of this.toolErrors) {
353
- if (count <= 1)
354
- this.toolErrors.delete(tool);
355
- else
356
- this.toolErrors.set(tool, count - 1);
357
- }
358
- // Затухание счётчика итераций на продуктивных вызовах: чтение новых файлов,
359
- // записи, правки — всё прогресс. Защита от ложных stuck-варнингов при
360
- // легитимной разведке файлов (напр. чтение 12 файлов в analytic-шаге).
361
- if (this.iterationsOnCurrentStep > 0) {
362
- this.iterationsOnCurrentStep = Math.max(0, this.iterationsOnCurrentStep - 1);
363
- }
364
- }
365
- /** Ставит текущий шаг (сброс per-step состояния при смене). */
366
- setCurrentStep(stepId, description) {
367
- if (stepId !== this.currentStepId) {
368
- this.resetStepState(stepId);
369
- }
370
- this.currentStepDescription = description;
371
- }
372
- /** True, если итераций на шаге больше порога. */
373
- isStuck() {
374
- return this.iterationsOnCurrentStep > this.threshold;
375
- }
376
- /** True, если тул (или любой) ошибался ≥ порога. */
377
- hasRepetitiveErrors(toolName) {
378
- if (toolName) {
379
- return (this.toolErrors.get(toolName) || 0) >= this.errorThreshold;
380
- }
381
- return Array.from(this.toolErrors.values()).some((c) => c >= this.errorThreshold);
382
- }
383
- /** True при повторяющихся вызовах: подряд идентичных или перемежающихся (A,B,A,B,A). */
384
- hasRepetitiveToolCalls() {
385
- if (this.recentToolCalls.length < this.repetitionThreshold)
386
- return false;
387
- const last = this.recentToolCalls[this.recentToolCalls.length - 1];
388
- // Проверка подряд идентичных (исходная логика)
389
- let consecutiveCount = 1;
390
- for (let i = this.recentToolCalls.length - 2; i >= 0; i--) {
391
- if (this.recentToolCalls[i].name === last.name &&
392
- this.recentToolCalls[i].argsKey === last.argsKey) {
393
- consecutiveCount++;
394
- }
395
- else {
396
- break;
397
- }
398
- }
399
- if (consecutiveCount >= this.repetitionThreshold)
400
- return true;
401
- // Плюс перемежающиеся паттерны (A, B, A, B, A): считаем каждую связку
402
- // тул+args в окне и флагуем при ≥ порога
403
- const counts = new Map();
404
- for (const call of this.recentToolCalls) {
405
- const key = `${call.name}::${call.argsKey}`;
406
- counts.set(key, (counts.get(key) || 0) + 1);
407
- }
408
- for (const count of counts.values()) {
409
- if (count >= this.repetitionThreshold)
410
- return true;
411
- }
412
- return false;
413
- }
414
- /** True при ≥ порога подряд фейлов. */
415
- hasConsecutiveFailures() {
416
- return this.consecutiveFailures >= this.errorThreshold;
417
- }
418
- /** Число подряд фейлов. */
419
- getConsecutiveFailuresCount() {
420
- return this.consecutiveFailures;
421
- }
422
- /** Отмечает эскалацию (счётчик для shouldEscalate). */
423
- recordEscalation() {
424
- this.escalationCount++;
425
- }
426
- /** True, если эскалаций набралось на порог. */
427
- shouldEscalate() {
428
- return this.escalationCount >= this.escalationThreshold;
429
- }
430
- /** Сбрасывает счётчик эскалаций. */
431
- resetEscalation() {
432
- this.escalationCount = 0;
433
- }
434
- /** Число эскалаций. */
435
- getEscalationCount() {
436
- return this.escalationCount;
437
- }
438
- /** Хинты по описанию шага + состояниям, ещё не покрытым recovery-сообщением. */
439
- getHints() {
440
- const hints = [];
441
- const desc = this.currentStepDescription.toLowerCase();
442
- if (desc.includes("install") || desc.includes("npm") || desc.includes("pip")) {
443
- hints.push(t("exec.hint_deps"));
444
- }
445
- if (desc.includes("test") || desc.includes("spec")) {
446
- hints.push(t("exec.hint_test"));
447
- }
448
- if (desc.includes("build") || desc.includes("compile")) {
449
- hints.push(t("exec.hint_build"));
450
- }
451
- if (desc.includes("deploy") || desc.includes("publish")) {
452
- hints.push(t("exec.hint_deploy"));
453
- }
454
- // State-based буллеты. Recovery-сообщение (getRecoveryMessage) уже репортит
455
- // ПЕРВИЧНУЮ причину (приоритет: stuck > tool-errors > consecutive >
456
- // repetitive > read-only). Дублировать то же состояние хинтом — задвоить
457
- // гайданс в одном cooldown-блоке. Буллет добавляем, только если recovery
458
- // это состояние НЕ покрывает.
459
- const primary = this.getPrimaryReason();
460
- if (this.hasRepetitiveToolCalls() && primary !== "repetitive") {
461
- hints.push(t("exec.hint_repetitive"));
462
- }
463
- if (this.hasConsecutiveFailures() && primary !== "consecutive") {
464
- hints.push(t("exec.hint_consecutive"));
465
- }
466
- if (this.hasReadOnlyLoop() && primary !== "read-only") {
467
- hints.push(t("exec.hint_read_only"));
468
- }
469
- return hints;
470
- }
471
- /** Actionable-хинты по последней ошибке: рантаймы, синтаксис, сеть, шелл-несоответствия. */
472
- getActionableHints() {
473
- const hints = [];
474
- const error = this.lastErrorOutput;
475
- // Bash-хинты от фейла тула не зависят — срабатывают, даже когда команда
476
- // "успешна" с пустым выводом (потерянный entry point).
477
- const isScriptRun = /(^|[\s&])(bun|node|tsx|ts-node|deno|python|python3)\S*\s+[^|&]+\s+[^\s]+$/.test(this.lastBashCommand);
478
- if (isScriptRun && !this.lastBashOutput.trim() && this.emptyBashRunCount >= 2) {
479
- hints.push(`The command "${this.lastBashCommand}" ran ${this.emptyBashRunCount} times with EMPTY output. The program likely has no entry point — read the file with read_file and check that it actually calls its main function with process.argv / CLI arguments and prints results (console.log). Then run it again.`);
480
- }
481
- if (!error)
482
- return hints;
483
- // Несовместимость рантайма — тул/модуль крашится на этой версии Node
484
- if (/Cannot read properties of undefined|is not a function|is not a constructor/i.test(error)) {
485
- if (/node_modules/.test(error)) {
486
- hints.push("A dependency is incompatible with your Node.js version. Check if there is an alternative package or use a different runtime.");
487
- }
488
- }
489
- // Синтаксические ошибки TypeScript — модель сгенерила невалидный код
490
- if (/TS1005|TS1003|TS1109|TS1128|TS1434/i.test(error)) {
491
- hints.push("TypeScript syntax error. Read the error message carefully — it tells you the exact line and column. Fix the syntax before retrying.");
492
- }
493
- // Ошибки типов TypeScript — модель не понимает типы
494
- if (/TS2322|TS2345|TS2769|TS7006|TS7016/i.test(error)) {
495
- hints.push("TypeScript type mismatch. Check the type signature of the function/API you are using. If a package lacks type declarations, install @types/<package> or use skipLibCheck.");
496
- }
497
- // Модуль не найден — нет зависимости или неверный импорт
498
- if (/Cannot find module|Module not found|ERR_MODULE_NOT_FOUND/i.test(error)) {
499
- hints.push("Module not found. Run npm install or check if the import path is correct.");
500
- }
501
- // Ошибки прав доступа
502
- if (/EACCES|EPERM|permission denied/i.test(error)) {
503
- hints.push("Permission denied. Check file permissions or run with appropriate privileges.");
504
- }
505
- // Сетевые ошибки
506
- if (/ECONNREFUSED|ETIMEDOUT|ENOTFOUND|fetch failed/i.test(error)) {
507
- hints.push("Network error. Check if the server is running and accessible.");
508
- }
509
- // Команда не найдена
510
- if (/is not recognized|command not found|not found in path/i.test(error)) {
511
- hints.push("Command not found. Check if the tool is installed and in PATH.");
512
- }
513
- // Петля перезаписи: один файл безуспешно переписывается
514
- if (this.hasExcessiveRewrites()) {
515
- const file = this.getExcessiveRewriteFile();
516
- hints.push(`File ${file} has been rewritten ${this.getFileRewriteCount(file)} times without success. Stop rewriting and try a fundamentally different approach.`);
517
- }
518
- // Повторные идентичные bash-прогоны с пустым выводом — вероятно, потерянный
519
- // entry point (программа не вызывает main).
520
- // PowerShell-командлеты внутри cmd.exe (шелл-несоответствие Windows).
521
- if (/Write-Host|Get-Content|Select-String|Out-File|Set-Content/i.test(error)) {
522
- hints.push("That looks like a PowerShell cmdlet — the shell here is cmd.exe. Use echo/type for output or the read_file/write_file tools instead.");
523
- }
524
- // Модель выдумала несуществующий Bun API.
525
- if (/Bun\.\w+ is not a function|Bun\.\w+ is not defined|Bun\.\w+ is not a constructor/i.test(error)) {
526
- hints.push("That Bun API does not exist. Verify the API name in the Bun docs — common ones are Bun.file, Bun.write, Bun.spawn, Bun.serve. For file checks use fs.existsSync from node:fs.");
527
- }
528
- // Модель продолжает писать файл, в выводе которого type/syntax ошибка —
529
- // читай реальную ошибку и чини её, не переписывай вслепую.
530
- if (/error TS\d+|typecheck failed|syntax check failed/i.test(error)) {
531
- hints.push("The file still has a type/syntax error (see the error line in the output). Read the file with read_file around the reported line, fix the actual error, then re-run — rewriting the whole file blindly usually makes it worse.");
532
- }
533
- // Bash-heredoc в cmd.exe.
534
- if (/unexpected.*<<|Непредвиденное появление/i.test(error)) {
535
- hints.push("Heredoc (<< EOF) is a bash feature — this shell is cmd.exe and does not support it. Write the file with write_file instead.");
536
- }
537
- return hints;
538
- }
539
- /** Альтернативный тул при рантайм-краше (ts-node→tsx, jest→vitest, …). Null, если нечего предложить. */
540
- getToolAlternative() {
541
- const tool = this.lastFailedTool;
542
- const error = this.lastErrorOutput;
543
- if (!tool)
544
- return null;
545
- // Упавший тул с рантайм-крашем — предлагаем альтернативы
546
- if (/Cannot read properties of undefined|is not a function|TypeError|ReferenceError/i.test(error)) {
547
- // Карта упавших тулов на частые альтернативы
548
- const alternatives = {
549
- "ts-node": "tsx",
550
- jest: "vitest",
551
- mocha: "vitest",
552
- webpack: "vite",
553
- rollup: "vite",
554
- parcel: "vite",
555
- babel: "tsc",
556
- eslint: "biome",
557
- prettier: "biome",
558
- };
559
- for (const [failed, alt] of Object.entries(alternatives)) {
560
- if (tool.includes(failed) || error.includes(failed)) {
561
- return alt;
562
- }
563
- }
564
- }
565
- return null;
566
- }
567
- /** Отмечает перезапись файла (счётчик для детекции петли). */
568
- recordFileRewrite(filePath) {
569
- const count = (this.fileRewriteCount.get(filePath) || 0) + 1;
570
- this.fileRewriteCount.set(filePath, count);
571
- }
572
- /** Число перезаписей файла. */
573
- getFileRewriteCount(filePath) {
574
- return this.fileRewriteCount.get(filePath) || 0;
575
- }
576
- /** True, если какой-то файл переписывается ≥ порога. */
577
- hasExcessiveRewrites() {
578
- return Array.from(this.fileRewriteCount.values()).some((c) => c >= this.fileRewriteThreshold);
579
- }
580
- /** Файл с избыточными перезаписями, или null. */
581
- getExcessiveRewriteFile() {
582
- for (const [file, count] of this.fileRewriteCount) {
583
- if (count >= this.fileRewriteThreshold)
584
- return file;
585
- }
586
- return null;
587
- }
588
- /** Сообщение о повторяющемся туле (+хинт про process_wait для process_log). */
589
- getRepetitiveToolMessage() {
590
- if (!this.hasRepetitiveToolCalls())
591
- return "";
592
- const last = this.recentToolCalls[this.recentToolCalls.length - 1];
593
- const base = t("exec.repetitive_tool", {
594
- tool: last.name,
595
- count: this.repetitionThreshold,
596
- });
597
- // Опрос фонового процесса по одному process_log за раз жжёт LLM-вызов на
598
- // опрос — указываем на одиночное блокирующее ожидание.
599
- if (last.name === "process_log") {
600
- return `${base} ${t("exec.repetitive_process_log_hint")}`;
601
- }
602
- return base;
603
- }
604
- /**
605
- * Стабильная идентичность варнинга для анти-спам дедупа: тот же ключ каждую
606
- * итерацию — спам, НОВЫЙ ключ (или длинная пауза) заслуживает re-warn.
607
- */
608
- getWarningKey() {
609
- if (this.isStuck())
610
- return "stuck";
611
- const errorTool = Array.from(this.toolErrors.entries()).find(([_, c]) => c >= this.errorThreshold);
612
- if (errorTool)
613
- return `tool-errors:${errorTool[0]}`;
614
- if (this.hasBashFlailing())
615
- return "bash-flailing";
616
- if (this.hasConsecutiveFailures())
617
- return "consecutive";
618
- if (this.hasRepetitiveToolCalls())
619
- return "repetitive";
620
- if (this.hasReadOnlyLoop())
621
- return "read-only";
622
- return "";
623
- }
624
- /** Причина застревания для лога (пусто если здоров). */
625
- getStuckReason() {
626
- if (this.isStuck()) {
627
- return t("exec.stuck", {
628
- stepId: String(this.currentStepId ?? "?"),
629
- description: this.currentStepDescription,
630
- iterations: this.iterationsOnCurrentStep,
631
- });
632
- }
633
- const errorTool = Array.from(this.toolErrors.entries()).find(([_, c]) => c >= this.errorThreshold);
634
- if (errorTool) {
635
- return t("exec.tool_errors", { tool: errorTool[0], count: errorTool[1] });
636
- }
637
- if (this.hasBashFlailing()) {
638
- const fails = this.bashRecent.filter((ok) => !ok).length;
639
- return t("exec.bash_flailing", {
640
- fails: String(fails),
641
- window: String(this.bashRecent.length),
642
- });
643
- }
644
- if (this.hasConsecutiveFailures()) {
645
- return t("exec.consecutive_failures", { count: String(this.consecutiveFailures) });
646
- }
647
- // Повторные идентичные вызовы — петля, даже если ничего не фейлится (напр.
648
- // цикл опроса process_log): без этой ветки оставались невидимы —
649
- // getWarningKey репортил "repetitive", но причина не логгировалась.
650
- if (this.hasRepetitiveToolCalls()) {
651
- return this.getRepetitiveToolMessage();
652
- }
653
- if (this.hasReadOnlyLoop()) {
654
- return t("exec.read_only_loop", {
655
- count: String(this.readOnlyStreak),
656
- });
657
- }
658
- return "";
659
- }
660
- /** Recovery-сообщение по первичной причине (пусто если здоров). */
661
- getRecoveryMessage() {
662
- const reason = this.getPrimaryReason();
663
- if (reason === "stuck") {
664
- return t("exec.stuck_recovery", {
665
- iterations: this.iterationsOnCurrentStep,
666
- stepId: String(this.currentStepId ?? "?"),
667
- description: this.currentStepDescription,
668
- });
669
- }
670
- // Per-tool recovery (конкретнее — напр. "bash упал 3 раза")
671
- if (reason === "tool-errors") {
672
- const errorTool = Array.from(this.toolErrors.entries()).find(([_, c]) => c >= this.errorThreshold);
673
- return t("exec.tool_errors_recovery", {
674
- tool: errorTool[0],
675
- count: errorTool[1],
676
- });
677
- }
678
- // Подряд фейлы разных тулов (общее — напр. "5 consecutive failures")
679
- if (reason === "consecutive") {
680
- return t("exec.consecutive_failures_recovery", {
681
- count: this.consecutiveFailures,
682
- });
683
- }
684
- if (reason === "bash-flailing") {
685
- const fails = this.bashRecent.filter((ok) => !ok).length;
686
- return t("exec.bash_flailing_recovery", {
687
- fails: String(fails),
688
- window: String(this.bashRecent.length),
689
- });
690
- }
691
- if (reason === "repetitive") {
692
- return this.getRepetitiveToolMessage();
693
- }
694
- if (reason === "read-only") {
695
- return t("exec.read_only_loop_recovery", {
696
- count: String(this.readOnlyStreak),
697
- });
698
- }
699
- return "";
700
- }
701
- /**
702
- * Классифицирует текущее состояние фейла в стабильный {@link FailureType}
703
- * для диагностики/логов. Null если здоров. `iteration` даёт вызывающий
704
- * (детектор глобальный счётчик цикла не ведёт).
705
- */
706
- classifyFailure(iteration = 0) {
707
- const primary = this.getPrimaryReason();
708
- if (!primary)
709
- return null;
710
- switch (primary) {
711
- case "stuck":
712
- return { type: "timeout", iteration };
713
- case "tool-errors": {
714
- const entry = Array.from(this.toolErrors.entries()).find(([, c]) => c >= this.errorThreshold);
715
- return { type: "error_loop", tool: entry?.[0], count: entry?.[1], iteration };
716
- }
717
- case "consecutive":
718
- return { type: "error_loop", count: this.consecutiveFailures, iteration };
719
- case "repetitive": {
720
- const last = this.recentToolCalls[this.recentToolCalls.length - 1];
721
- return { type: "repeat", tool: last?.name, count: this.repetitionThreshold, iteration };
722
- }
723
- case "bash-flailing": {
724
- const fails = this.bashRecent.filter((ok) => !ok).length;
725
- return { type: "bash_flailing", count: fails, iteration };
726
- }
727
- case "read-only":
728
- return { type: "read_only", count: this.readOnlyStreak, iteration };
729
- }
730
- }
731
- /** Компактный маркер `[STUCK: type=..., tool=..., count=..., iteration=N]`. */
732
- formatFailureDiagnostic(c) {
733
- const parts = [`type=${c.type}`];
734
- if (c.tool)
735
- parts.push(`tool=${c.tool}`);
736
- if (typeof c.count === "number")
737
- parts.push(`count=${c.count}`);
738
- if (c.iteration > 0)
739
- parts.push(`iteration=${c.iteration}`);
740
- return `[STUCK: ${parts.join(", ")}]`;
741
- }
742
- /** Диагностический маркер текущего состояния, или "" если здоров. */
743
- getStuckDiagnostic(iteration = 0) {
744
- const c = this.classifyFailure(iteration);
745
- return c ? this.formatFailureDiagnostic(c) : "";
746
- }
747
- /**
748
- * Единый источник правды приоритета recovery-причины. Общий для
749
- * getRecoveryMessage() и getHints(), чтобы не расходились: bullet состояния,
750
- * которое getRecoveryMessage уже репортит, хинтом НЕ дублируется
751
- * (приоритет: stuck > tool-errors > consecutive > repetitive > read-only).
752
- */
753
- getPrimaryReason() {
754
- if (this.isStuck())
755
- return "stuck";
756
- const errorTool = Array.from(this.toolErrors.entries()).find(([_, c]) => c >= this.errorThreshold);
757
- if (errorTool)
758
- return "tool-errors";
759
- if (this.hasBashFlailing())
760
- return "bash-flailing";
761
- if (this.hasConsecutiveFailures())
762
- return "consecutive";
763
- if (this.hasRepetitiveToolCalls())
764
- return "repetitive";
765
- if (this.hasReadOnlyLoop())
766
- return "read-only";
767
- return null;
768
- }
769
- /** Полный сброс всего состояния детектора. */
770
- reset() {
771
- this.currentStepId = null;
772
- this.iterationsOnCurrentStep = 0;
773
- this.toolErrors.clear();
774
- this.consecutiveFailures = 0;
775
- this.lastFailedTool = "";
776
- this.lastErrorOutput = "";
777
- this.recentToolCalls = [];
778
- this.fileRewriteCount.clear();
779
- this.escalationCount = 0;
780
- this.lastBashCommand = "";
781
- this.lastBashOutput = "";
782
- this.emptyBashRunCount = 0;
783
- this.bashRecent = [];
784
- this.readOnlyStreak = 0;
785
- this.errorSignatureCounts.clear();
786
- this.searchedErrorSignatures.clear();
787
- }
788
- /**
789
- * Сбрасывает только step-прогресс, храня историю вызовов и read-only стрик.
790
- * Нужно, когда план готов, но цикл продолжается (напр. audit-gate реджектнул
791
- * готовую задачу): step-stuck варнинги глушатся, а петля чтения-без-записи
792
- * всё равно детектится.
793
- */
794
- resetStepProgress() {
795
- this.currentStepId = null;
796
- this.iterationsOnCurrentStep = 0;
797
- this.toolErrors.clear();
798
- this.consecutiveFailures = 0;
799
- this.lastFailedTool = "";
800
- this.lastErrorOutput = "";
801
- this.fileRewriteCount.clear();
802
- this.escalationCount = 0;
803
- this.lastBashCommand = "";
804
- this.lastBashOutput = "";
805
- this.emptyBashRunCount = 0;
806
- this.bashRecent = [];
807
- this.errorSignatureCounts.clear();
808
- this.searchedErrorSignatures.clear();
809
- }
810
- /**
811
- * Сбрасывает всё per-step состояние при переходе на новый шаг. Не даёт
812
- * ошибкам и повторам одного шага протекать в следующий (ложные
813
- * stuck/recovery на первой итерации нового шага).
814
- */
815
- resetStepState(stepId) {
816
- this.currentStepId = stepId;
817
- this.iterationsOnCurrentStep = 1;
818
- this.toolErrors.clear();
819
- this.consecutiveFailures = 0;
820
- this.lastFailedTool = "";
821
- this.lastErrorOutput = "";
822
- this.recentToolCalls = [];
823
- this.fileRewriteCount.clear();
824
- this.lastBashCommand = "";
825
- this.lastBashOutput = "";
826
- this.emptyBashRunCount = 0;
827
- this.bashRecent = [];
828
- this.readOnlyStreak = 0;
829
- this.errorSignatureCounts.clear();
830
- this.searchedErrorSignatures.clear();
831
- // escalationCount храним — иначе агент "геймит" детекцию, маркируя шаг
832
- // done и переходя к следующему
833
- }
834
- }