micro-models-agent 2.16.1 → 2.17.2

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 (428) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +8 -3
  3. package/dist/assets/app.js +1 -314
  4. package/dist/assets/hljs.js +5 -1244
  5. package/dist/assets/index.html +11 -0
  6. package/dist/assets/js/api.js +1 -28
  7. package/dist/assets/js/core/menus.js +1 -0
  8. package/dist/assets/js/core/store/feed.js +1 -0
  9. package/dist/assets/js/core/store/index.js +1 -0
  10. package/dist/assets/js/core/store/session.js +1 -0
  11. package/dist/assets/js/core/store/settings.js +1 -0
  12. package/dist/assets/js/core/store/tabs.js +1 -0
  13. package/dist/assets/js/dialog.js +1 -105
  14. package/dist/assets/js/dom.js +1 -178
  15. package/dist/assets/js/feed/core.js +1 -0
  16. package/dist/assets/js/feed/history.js +1 -0
  17. package/dist/assets/js/feed/plan.js +1 -0
  18. package/dist/assets/js/feed/question.js +3 -0
  19. package/dist/assets/js/feed/sidebar.js +1 -0
  20. package/dist/assets/js/feed/stream.js +1 -0
  21. package/dist/assets/js/feed/turn.js +5 -0
  22. package/dist/assets/js/feed.js +1 -1250
  23. package/dist/assets/js/format.js +2 -122
  24. package/dist/assets/js/i18n.js +1 -46
  25. package/dist/assets/js/rail.js +1 -114
  26. package/dist/assets/js/session/cmdk.js +1 -0
  27. package/dist/assets/js/session/composer.js +1 -0
  28. package/dist/assets/js/session/sessions-menu.js +1 -0
  29. package/dist/assets/js/session/tabs.js +1 -0
  30. package/dist/assets/js/settings/controls.js +1 -0
  31. package/dist/assets/js/settings/editors.js +1 -0
  32. package/dist/assets/js/settings/form.js +1 -0
  33. package/dist/assets/js/settings/modal.js +1 -0
  34. package/dist/assets/js/settings/panels.js +1 -0
  35. package/dist/assets/js/settings/providers.js +1 -0
  36. package/dist/assets/js/settings/search.js +1 -0
  37. package/dist/assets/js/settings/subdialog.js +1 -0
  38. package/dist/assets/js/settings/write.js +1 -0
  39. package/dist/assets/js/settings.js +1 -1914
  40. package/dist/assets/js/sidebar/core.js +1 -0
  41. package/dist/assets/js/sidebar/lsp.js +2 -0
  42. package/dist/assets/js/sidebar/map.js +1 -0
  43. package/dist/assets/js/sidebar/state.js +1 -0
  44. package/dist/assets/js/sidebar/trace.js +5 -0
  45. package/dist/assets/js/sidebar.js +1 -705
  46. package/dist/assets/js/store.js +1 -82
  47. package/dist/assets/js/subdialog.js +1 -0
  48. package/dist/assets/md.js +1 -291
  49. package/dist/assets/setup.js +3 -816
  50. package/dist/assets/smd.js +29 -1665
  51. package/dist/assets/styles.css +1 -1598
  52. package/dist/certification/certifications.json +1 -494
  53. package/dist/i18n/en.json +1 -1851
  54. package/dist/i18n/ru.json +1 -1854
  55. package/dist/main.js +815 -55797
  56. package/dist/modules/browser/bridge-server.mjs +2 -252
  57. package/package.json +10 -5
  58. package/dist/assets/js/settings-controls.js +0 -452
  59. package/dist/assets/js/tabs.js +0 -867
  60. package/dist/cli/cache-line.js +0 -31
  61. package/dist/cli/command-suggest.js +0 -39
  62. package/dist/cli/commands.js +0 -781
  63. package/dist/cli/completer.js +0 -268
  64. package/dist/cli/index.js +0 -3
  65. package/dist/cli/json-payload.js +0 -32
  66. package/dist/cli/main.js +0 -346
  67. package/dist/cli/onboarding-commands.js +0 -126
  68. package/dist/cli/plugin-commands.js +0 -38
  69. package/dist/cli/relaunch.js +0 -40
  70. package/dist/cli/repl-commands-lsp.js +0 -75
  71. package/dist/cli/repl-commands-skills.js +0 -105
  72. package/dist/cli/repl-commands.js +0 -1218
  73. package/dist/cli/repl.js +0 -1238
  74. package/dist/cli/run-result.js +0 -38
  75. package/dist/cli/security-commands.js +0 -177
  76. package/dist/cli/setup-order.js +0 -6
  77. package/dist/cli/setup-prompt.js +0 -50
  78. package/dist/cli/setup.js +0 -161
  79. package/dist/cli/web-command.js +0 -98
  80. package/dist/config/budget.js +0 -48
  81. package/dist/config/config.js +0 -345
  82. package/dist/config/defaults.js +0 -197
  83. package/dist/config/domains.js +0 -135
  84. package/dist/config/env.js +0 -46
  85. package/dist/config/experts.js +0 -17
  86. package/dist/config/index.js +0 -5
  87. package/dist/config/paths.js +0 -56
  88. package/dist/config/redact.js +0 -44
  89. package/dist/config/registry-extra.js +0 -334
  90. package/dist/config/registry.js +0 -584
  91. package/dist/config/security.js +0 -212
  92. package/dist/config/timeouts.js +0 -74
  93. package/dist/config/types.js +0 -1
  94. package/dist/config/utils.js +0 -57
  95. package/dist/core/agent/artifact-progress.js +0 -59
  96. package/dist/core/agent/artifact-resolve.js +0 -79
  97. package/dist/core/agent/audit-gate.js +0 -53
  98. package/dist/core/agent/compaction.js +0 -89
  99. package/dist/core/agent/constants.js +0 -90
  100. package/dist/core/agent/context-log.js +0 -454
  101. package/dist/core/agent/context-renderer.js +0 -45
  102. package/dist/core/agent/critic-gate.js +0 -132
  103. package/dist/core/agent/hallucination-gate.js +0 -197
  104. package/dist/core/agent/loop-state.js +0 -68
  105. package/dist/core/agent/prefix-monitor.js +0 -101
  106. package/dist/core/agent/reasoning-resolver.js +0 -65
  107. package/dist/core/agent/token-tracker.js +0 -99
  108. package/dist/core/agent/tool-batch.js +0 -312
  109. package/dist/core/agent/tool-images.js +0 -18
  110. package/dist/core/agent/tool-output.js +0 -116
  111. package/dist/core/agent/tool-pairing.js +0 -60
  112. package/dist/core/agent-moe.js +0 -248
  113. package/dist/core/agent.js +0 -1299
  114. package/dist/core/bootstrap/agent-phase.js +0 -66
  115. package/dist/core/bootstrap/config-phase.js +0 -86
  116. package/dist/core/bootstrap/modules-phase.js +0 -269
  117. package/dist/core/bootstrap/provider-phase.js +0 -183
  118. package/dist/core/bootstrap/session-phase.js +0 -204
  119. package/dist/core/bootstrap/state.js +0 -94
  120. package/dist/core/bootstrap/workspace-phase.js +0 -115
  121. package/dist/core/bootstrap.js +0 -112
  122. package/dist/core/crash-handler.js +0 -62
  123. package/dist/core/environment.js +0 -224
  124. package/dist/core/host-plan.js +0 -43
  125. package/dist/core/host.js +0 -23
  126. package/dist/core/index.js +0 -3
  127. package/dist/core/prompt-builder.js +0 -95
  128. package/dist/core/prompt-overflow.js +0 -306
  129. package/dist/core/session-logger.js +0 -375
  130. package/dist/core/system-prompt.js +0 -117
  131. package/dist/core/types.js +0 -1
  132. package/dist/core/version.js +0 -28
  133. package/dist/core/web-host.js +0 -34
  134. package/dist/core/workspace.js +0 -80
  135. package/dist/i18n/index.js +0 -80
  136. package/dist/index.js +0 -30
  137. package/dist/llm/cache-usage.js +0 -76
  138. package/dist/llm/image-utils.js +0 -138
  139. package/dist/llm/index.js +0 -4
  140. package/dist/llm/llm-errors.js +0 -50
  141. package/dist/llm/model-loader.js +0 -86
  142. package/dist/llm/models-dev.js +0 -121
  143. package/dist/llm/openai-compat.js +0 -756
  144. package/dist/llm/orchestrator.js +0 -294
  145. package/dist/llm/provider-budget.js +0 -68
  146. package/dist/llm/provider-context.js +0 -233
  147. package/dist/llm/provider.js +0 -9
  148. package/dist/llm/response.js +0 -44
  149. package/dist/llm/stream-state.js +0 -26
  150. package/dist/llm/token-counter.js +0 -83
  151. package/dist/llm/types.js +0 -1
  152. package/dist/logger/app-logger.js +0 -212
  153. package/dist/logger/file-log.js +0 -160
  154. package/dist/logger/index.js +0 -2
  155. package/dist/migration/backup.js +0 -56
  156. package/dist/migration/detect.js +0 -61
  157. package/dist/migration/index.js +0 -3
  158. package/dist/modules/artifacts/store.js +0 -62
  159. package/dist/modules/browser/actions.js +0 -79
  160. package/dist/modules/browser/bridge-client.js +0 -203
  161. package/dist/modules/browser/bridge-path.js +0 -10
  162. package/dist/modules/browser/console-buffer.js +0 -37
  163. package/dist/modules/browser/cookie-store.js +0 -29
  164. package/dist/modules/browser/driver-types.js +0 -1
  165. package/dist/modules/browser/driver.js +0 -186
  166. package/dist/modules/browser/index.js +0 -9
  167. package/dist/modules/browser/module.js +0 -30
  168. package/dist/modules/browser/session.js +0 -322
  169. package/dist/modules/browser/snapshot.js +0 -154
  170. package/dist/modules/browser/types.js +0 -13
  171. package/dist/modules/certification/cli.js +0 -264
  172. package/dist/modules/certification/fact-checker.js +0 -90
  173. package/dist/modules/certification/loader.js +0 -127
  174. package/dist/modules/certification/manifest.js +0 -231
  175. package/dist/modules/certification/runner.js +0 -233
  176. package/dist/modules/certification/scenarios.js +0 -586
  177. package/dist/modules/certification/syntax-scenarios.js +0 -50
  178. package/dist/modules/certification/types.js +0 -1
  179. package/dist/modules/context/chunk-query.js +0 -122
  180. package/dist/modules/context/fact-extractor.js +0 -170
  181. package/dist/modules/context/history.js +0 -15
  182. package/dist/modules/context/index.js +0 -2
  183. package/dist/modules/context/manager.js +0 -482
  184. package/dist/modules/critic/client.js +0 -176
  185. package/dist/modules/critic/evidence.js +0 -81
  186. package/dist/modules/critic/provider.js +0 -45
  187. package/dist/modules/critic/tools.js +0 -78
  188. package/dist/modules/critic/types.js +0 -1
  189. package/dist/modules/execution/audit-runners.js +0 -206
  190. package/dist/modules/execution/auditor.js +0 -222
  191. package/dist/modules/execution/execution-plugin.js +0 -478
  192. package/dist/modules/execution/index.js +0 -8
  193. package/dist/modules/execution/input-from.js +0 -70
  194. package/dist/modules/execution/module.js +0 -891
  195. package/dist/modules/execution/moe-executor.js +0 -443
  196. package/dist/modules/execution/plan-actions.js +0 -642
  197. package/dist/modules/execution/plan-checks.js +0 -35
  198. package/dist/modules/execution/plan-coverage.js +0 -71
  199. package/dist/modules/execution/plan-persister.js +0 -46
  200. package/dist/modules/execution/plan-steps.js +0 -31
  201. package/dist/modules/execution/plan-store.js +0 -274
  202. package/dist/modules/execution/plan-tool.js +0 -249
  203. package/dist/modules/execution/plan-validator.js +0 -197
  204. package/dist/modules/execution/planner.js +0 -103
  205. package/dist/modules/execution/stuck-detector.js +0 -834
  206. package/dist/modules/execution/tracker.js +0 -92
  207. package/dist/modules/execution/transient-error.js +0 -30
  208. package/dist/modules/execution/types.js +0 -1
  209. package/dist/modules/execution/verifier.js +0 -343
  210. package/dist/modules/execution/windows-commands.js +0 -52
  211. package/dist/modules/hallucination/artifact-claim.js +0 -93
  212. package/dist/modules/hallucination/confidence.js +0 -81
  213. package/dist/modules/hallucination/consistency.js +0 -37
  214. package/dist/modules/hallucination/detector.js +0 -57
  215. package/dist/modules/hallucination/factual.js +0 -205
  216. package/dist/modules/hallucination/index.js +0 -6
  217. package/dist/modules/hallucination/js-identifiers.js +0 -261
  218. package/dist/modules/hallucination/llm-judge.js +0 -116
  219. package/dist/modules/hallucination/success-claim.js +0 -59
  220. package/dist/modules/index.js +0 -5
  221. package/dist/modules/indexer/cache.js +0 -88
  222. package/dist/modules/indexer/index.js +0 -4
  223. package/dist/modules/indexer/map-command.js +0 -33
  224. package/dist/modules/indexer/map-select.js +0 -87
  225. package/dist/modules/indexer/module.js +0 -293
  226. package/dist/modules/indexer/project-profile.js +0 -184
  227. package/dist/modules/indexer/symbols.js +0 -189
  228. package/dist/modules/indexer/walker.js +0 -285
  229. package/dist/modules/lsp/check-tool.js +0 -61
  230. package/dist/modules/lsp/client.js +0 -406
  231. package/dist/modules/lsp/command.js +0 -53
  232. package/dist/modules/lsp/config.js +0 -189
  233. package/dist/modules/lsp/index.js +0 -4
  234. package/dist/modules/lsp/module.js +0 -295
  235. package/dist/modules/lsp/probe.js +0 -86
  236. package/dist/modules/lsp/project-root.js +0 -69
  237. package/dist/modules/lsp/startup-check.js +0 -154
  238. package/dist/modules/lsp/types.js +0 -1
  239. package/dist/modules/mcp/client.js +0 -445
  240. package/dist/modules/mcp/index.js +0 -4
  241. package/dist/modules/mcp/module.js +0 -295
  242. package/dist/modules/mcp/registry.js +0 -20
  243. package/dist/modules/memory/index.js +0 -2
  244. package/dist/modules/memory/module.js +0 -101
  245. package/dist/modules/memory/search.js +0 -45
  246. package/dist/modules/memory/store.js +0 -107
  247. package/dist/modules/onboarding/init.js +0 -47
  248. package/dist/modules/onboarding/meet.js +0 -30
  249. package/dist/modules/onboarding/mode.js +0 -30
  250. package/dist/modules/onboarding/prompts.js +0 -43
  251. package/dist/modules/pipelines/engine.js +0 -70
  252. package/dist/modules/pipelines/index.js +0 -4
  253. package/dist/modules/pipelines/parser.js +0 -59
  254. package/dist/modules/pipelines/template.js +0 -18
  255. package/dist/modules/plugins/builtin/lint-on-write.js +0 -377
  256. package/dist/modules/plugins/builtin/notify.js +0 -11
  257. package/dist/modules/plugins/index.js +0 -2
  258. package/dist/modules/plugins/loader.js +0 -85
  259. package/dist/modules/plugins/manager.js +0 -244
  260. package/dist/modules/plugins/types.js +0 -1
  261. package/dist/modules/pricing/index.js +0 -70
  262. package/dist/modules/pricing/prices.js +0 -147
  263. package/dist/modules/processes/detect.js +0 -34
  264. package/dist/modules/processes/index.js +0 -4
  265. package/dist/modules/processes/kill-tree.js +0 -52
  266. package/dist/modules/processes/registry.js +0 -294
  267. package/dist/modules/processes/runner.js +0 -23
  268. package/dist/modules/providers/cache.js +0 -23
  269. package/dist/modules/providers/capabilities.js +0 -28
  270. package/dist/modules/providers/create.js +0 -21
  271. package/dist/modules/providers/factory.js +0 -28
  272. package/dist/modules/providers/fallback.js +0 -81
  273. package/dist/modules/providers/health.js +0 -47
  274. package/dist/modules/providers/index.js +0 -6
  275. package/dist/modules/providers/manager.js +0 -207
  276. package/dist/modules/providers/naming.js +0 -15
  277. package/dist/modules/providers/preflight.js +0 -71
  278. package/dist/modules/providers/presets.js +0 -232
  279. package/dist/modules/providers/registry.js +0 -27
  280. package/dist/modules/providers/types.js +0 -1
  281. package/dist/modules/reasoning/policy.js +0 -42
  282. package/dist/modules/reasoning/probe.js +0 -116
  283. package/dist/modules/registry.js +0 -48
  284. package/dist/modules/security/audit-log.js +0 -119
  285. package/dist/modules/security/audit-notifier.js +0 -267
  286. package/dist/modules/security/command-validator.js +0 -272
  287. package/dist/modules/security/content-scanner.js +0 -53
  288. package/dist/modules/security/data-sanitizer.js +0 -82
  289. package/dist/modules/security/encryption.js +0 -216
  290. package/dist/modules/security/index.js +0 -15
  291. package/dist/modules/security/network-validator.js +0 -236
  292. package/dist/modules/security/path-validator.js +0 -261
  293. package/dist/modules/security/protected-paths.js +0 -73
  294. package/dist/modules/security/rate-limiter.js +0 -98
  295. package/dist/modules/security/security-policies.js +0 -499
  296. package/dist/modules/security/session-encryption.js +0 -182
  297. package/dist/modules/security/session-isolation.js +0 -75
  298. package/dist/modules/session/auto-name.js +0 -63
  299. package/dist/modules/session/export.js +0 -98
  300. package/dist/modules/session/index.js +0 -4
  301. package/dist/modules/session/manager.js +0 -234
  302. package/dist/modules/session/module.js +0 -33
  303. package/dist/modules/session/store.js +0 -295
  304. package/dist/modules/session/types.js +0 -1
  305. package/dist/modules/setup/answers.js +0 -35
  306. package/dist/modules/setup/apply.js +0 -79
  307. package/dist/modules/setup/discovery.js +0 -72
  308. package/dist/modules/skills/index.js +0 -3
  309. package/dist/modules/skills/loader.js +0 -86
  310. package/dist/modules/skills/matcher.js +0 -27
  311. package/dist/modules/skills/module.js +0 -141
  312. package/dist/modules/types.js +0 -1
  313. package/dist/modules/updater/changelog-reader.js +0 -93
  314. package/dist/modules/updater/checker.js +0 -101
  315. package/dist/modules/updater/dev-detect.js +0 -18
  316. package/dist/modules/updater/index.js +0 -4
  317. package/dist/modules/updater/module.js +0 -129
  318. package/dist/modules/user-profile/compressor.js +0 -18
  319. package/dist/modules/user-profile/index.js +0 -2
  320. package/dist/modules/user-profile/profile.js +0 -77
  321. package/dist/modules/webui/answer-api.js +0 -29
  322. package/dist/modules/webui/assets.js +0 -50
  323. package/dist/modules/webui/body.js +0 -21
  324. package/dist/modules/webui/commands-settings.js +0 -209
  325. package/dist/modules/webui/commands-shared.js +0 -60
  326. package/dist/modules/webui/commands.js +0 -174
  327. package/dist/modules/webui/config-api.js +0 -134
  328. package/dist/modules/webui/file-api.js +0 -202
  329. package/dist/modules/webui/forward.js +0 -159
  330. package/dist/modules/webui/history-api.js +0 -112
  331. package/dist/modules/webui/host-state.js +0 -60
  332. package/dist/modules/webui/i18n-api.js +0 -9
  333. package/dist/modules/webui/limits.js +0 -6
  334. package/dist/modules/webui/log-forward.js +0 -20
  335. package/dist/modules/webui/memory-commands.js +0 -64
  336. package/dist/modules/webui/model-cache.js +0 -18
  337. package/dist/modules/webui/module.js +0 -148
  338. package/dist/modules/webui/persist.js +0 -24
  339. package/dist/modules/webui/prompt-io.js +0 -97
  340. package/dist/modules/webui/providers-api.js +0 -337
  341. package/dist/modules/webui/providers-view.js +0 -56
  342. package/dist/modules/webui/reasoning-view.js +0 -15
  343. package/dist/modules/webui/run-agent.js +0 -81
  344. package/dist/modules/webui/server.js +0 -284
  345. package/dist/modules/webui/sessions-api.js +0 -178
  346. package/dist/modules/webui/settings-api.js +0 -561
  347. package/dist/modules/webui/setup-api.js +0 -201
  348. package/dist/modules/webui/state.js +0 -74
  349. package/dist/modules/webui/util.js +0 -261
  350. package/dist/output/bus.js +0 -37
  351. package/dist/output/channel.js +0 -285
  352. package/dist/output/format.js +0 -15
  353. package/dist/output/index.js +0 -8
  354. package/dist/output/json-sink.js +0 -24
  355. package/dist/output/machine.js +0 -9
  356. package/dist/output/session-sink.js +0 -27
  357. package/dist/output/types.js +0 -1
  358. package/dist/tools/approve.js +0 -41
  359. package/dist/tools/attach-image.js +0 -102
  360. package/dist/tools/auto-fixer.js +0 -180
  361. package/dist/tools/auto-tags.js +0 -83
  362. package/dist/tools/bash.js +0 -649
  363. package/dist/tools/browser.js +0 -160
  364. package/dist/tools/chunk-query.js +0 -112
  365. package/dist/tools/create-dir.js +0 -60
  366. package/dist/tools/delete-file.js +0 -67
  367. package/dist/tools/download-file.js +0 -142
  368. package/dist/tools/edit-file.js +0 -136
  369. package/dist/tools/enable-tools.js +0 -59
  370. package/dist/tools/executor.js +0 -304
  371. package/dist/tools/file-info.js +0 -49
  372. package/dist/tools/filter-tools.js +0 -17
  373. package/dist/tools/glob-tool.js +0 -37
  374. package/dist/tools/grep-tool.js +0 -142
  375. package/dist/tools/hidden-tools-block.js +0 -37
  376. package/dist/tools/index.js +0 -88
  377. package/dist/tools/list-dir.js +0 -53
  378. package/dist/tools/load-skill.js +0 -51
  379. package/dist/tools/mcp-call.js +0 -80
  380. package/dist/tools/meet-done.js +0 -14
  381. package/dist/tools/move-file.js +0 -94
  382. package/dist/tools/path-utils.js +0 -108
  383. package/dist/tools/pipeline-run.js +0 -167
  384. package/dist/tools/preview.js +0 -2
  385. package/dist/tools/process-ids.js +0 -31
  386. package/dist/tools/process-kill.js +0 -33
  387. package/dist/tools/process-list.js +0 -38
  388. package/dist/tools/process-log.js +0 -49
  389. package/dist/tools/process-wait.js +0 -63
  390. package/dist/tools/prompt-io.js +0 -29
  391. package/dist/tools/question.js +0 -288
  392. package/dist/tools/read-file.js +0 -200
  393. package/dist/tools/recall.js +0 -124
  394. package/dist/tools/registry.js +0 -48
  395. package/dist/tools/remember.js +0 -72
  396. package/dist/tools/scope-check.js +0 -32
  397. package/dist/tools/scope-request.js +0 -96
  398. package/dist/tools/search-history.js +0 -88
  399. package/dist/tools/session-info.js +0 -46
  400. package/dist/tools/set-thinking.js +0 -75
  401. package/dist/tools/subagent.js +0 -257
  402. package/dist/tools/syntax-validator.js +0 -379
  403. package/dist/tools/types.js +0 -1
  404. package/dist/tools/user-input.js +0 -134
  405. package/dist/tools/web-browse.js +0 -93
  406. package/dist/tools/web-fetch.js +0 -108
  407. package/dist/tools/web-search.js +0 -107
  408. package/dist/tools/write-file.js +0 -128
  409. package/dist/ui/action-log.js +0 -13
  410. package/dist/ui/box.js +0 -78
  411. package/dist/ui/colors.js +0 -6
  412. package/dist/ui/diff.js +0 -189
  413. package/dist/ui/index.js +0 -7
  414. package/dist/ui/line-editor.js +0 -1083
  415. package/dist/ui/line-math.js +0 -98
  416. package/dist/ui/md-formatter.js +0 -322
  417. package/dist/ui/output.js +0 -19
  418. package/dist/ui/plan-view.js +0 -109
  419. package/dist/ui/renderer.js +0 -589
  420. package/dist/ui/spinner.js +0 -91
  421. package/dist/ui/table.js +0 -142
  422. package/dist/ui/theme.js +0 -143
  423. package/dist/utils/child-run.js +0 -20
  424. package/dist/utils/error.js +0 -4
  425. package/dist/utils/index.js +0 -6
  426. package/dist/utils/retry.js +0 -17
  427. package/dist/utils/sleep.js +0 -23
  428. package/dist/utils/truncate.js +0 -9
@@ -1,891 +0,0 @@
1
- import { t } from "../../i18n/index";
2
- import { PlanTracker } from "./tracker";
3
- import { StepVerifier } from "./verifier";
4
- import { StuckDetector, isSearchableError, buildSearchQuery } from "./stuck-detector";
5
- import { Auditor, findExistingFile } from "./auditor";
6
- import { PlanStore } from "./plan-store";
7
- import { getMessageText } from "../../llm/provider";
8
- import { extractFileLikeTokens, stripUrls } from "../hallucination/js-identifiers";
9
- import { toForwardSlash } from "../../tools/path-utils";
10
- import { existsSync, readFileSync } from "fs";
11
- import { resolve } from "path";
12
- import { performWebSearch } from "../../tools/web-search";
13
- import { getSessionSecurityConfig } from "../security/session-isolation";
14
- import { createPlanToolDefinitions } from "./plan-tool";
15
- import { isValidCheck } from "./plan-checks";
16
- import { createExecutionPlugin, STUCK_RECOVERY_COOLDOWN, STUCK_WARN_REPEAT_EVERY, } from "./execution-plugin";
17
- import { EXECUTION_ERROR_SEARCH_MIN_INTERVAL_MS as ERROR_SEARCH_MIN_INTERVAL_MS } from "../../config/timeouts";
18
- /**
19
- * Минимальный интервал между автопоисками ошибок. Спек просил кап
20
- * STUCK_RECOVERY_COOLDOWN-итераций, но в onAfterTool нет счётчика итераций
21
- * (контекст экзекутора) — та же анти-спам защита, но по времени. Инжектится
22
- * через конструктор для тестов (0 отключает).
23
- */
24
- /**
25
- * Тулы, которым можно при активном шаге плана БЕЗ проверки step-alignment.
26
- * Либо не трогают ФС, либо структурно/read-only инспекции, нужные агенту в
27
- * любой точке (диагностика, индекс/поиск, память, интроспекция процессов,
28
- * интерактивные промпты). К текущему шагу пинятся только файл-мутирующие.
29
- *
30
- * `lsp_check` и `project_map` здесь явно: оба alwaysOn, а системный промпт
31
- * ТРЕБУЕТ `lsp_check` после каждой записи (включая переписи файлов уже
32
- * закрытых шагов). Без них каждый диагностический вызов жёг plan-warning и мог
33
- * hard-block'нуть легитимную запись на 3-м вызове (было: "3 вызовов подряд вне
34
- * текущего шага", пока агент писал deliverable текущего же шага).
35
- */
36
- const PLAN_ALIGNMENT_EXEMPT_TOOLS = new Set([
37
- // structural / execution control
38
- "plan",
39
- "plan_step",
40
- "todo",
41
- "verify",
42
- "enable_tools",
43
- // filesystem reads
44
- "list_dir",
45
- "read_file",
46
- "glob",
47
- "grep",
48
- "file_info",
49
- // read-only diagnostics + code index
50
- "lsp_check",
51
- "project_map",
52
- "chunk_query",
53
- // web / memory / session reads
54
- "web_search",
55
- "web_fetch",
56
- "web_browse",
57
- "recall",
58
- "search_history",
59
- "session_info",
60
- // process introspection
61
- "process_list",
62
- "process_log",
63
- // interactive prompts (no filesystem mutation)
64
- "question",
65
- "approve",
66
- // skills
67
- "load_skill",
68
- ]);
69
- /**
70
- * Каноническая форма файлового токена для alignment: прямые слэши + lowercase.
71
- * Вызовы тулов несут абсолютные Windows-пути (`C:\…\test\src\main.ts`), а шаги
72
- * плана — относительные (`src/main.ts`); сравнение сырых строк делало каждый
73
- * on-track write off-path (бэкслэш vs прямой слэш не пересекаются).
74
- * Нормализация обеих сторон чинит overlap через substring/`endsWith` ниже.
75
- */
76
- function planPathToken(p) {
77
- return toForwardSlash(p).toLowerCase();
78
- }
79
- /** Execution-модуль: план, stuck-детектор, аудитор, гейты выравнивания и автопоиск ошибок. */
80
- export class ExecutionModule {
81
- name = "execution";
82
- tracker = null;
83
- /** Сессия-владелец текущего трекера. План следует за сессией: смена
84
- * сессии через switchSession() персистит трекер в слот старой сессии
85
- * и загружает план новой (см. docs/specs/2026-09-29-session-plan-binding-design.md). */
86
- sessionId = null;
87
- verifier;
88
- stuckDetector;
89
- auditor;
90
- store;
91
- baseDir;
92
- // Пропуск первого аудита после восстановления плана с диска — даём юзеру
93
- // шанс сменить тему, прежде чем audit-gate зафиксируется.
94
- _auditSkipsRemaining = 0;
95
- /**
96
- * Последний план, ЗАВЕРШЁННЫЙ и авто-архивированный. `plan update` на
97
- * финальном шаге чистит трекер — раньше runFinalAudit() возвращал null и
98
- * молча скипал финальный аудит (тесты + tsc + файлы) готовой задачи.
99
- * Храним завершённый план, чтобы audit-gate отработал.
100
- */
101
- completedPlan = null;
102
- /**
103
- * Отложенные <system-summary>. Инжектятся onBeforeTool/onAfterTool, но
104
- * флашатся в onBeforeThink — никогда не встают между assistant tool_call и
105
- * его tool-результатами (рвёт спаривание и хоронит варнинги, на которые
106
- * модель должна реагировать).
107
- */
108
- pendingMessages = [];
109
- // Per-командные счётчики фейлов запрещённых Windows-команд (grep/sed/ls/
110
- // find/… через тул bash). Hard stop после второго фейла evidence-based
111
- // (реальные фейлы команд), не классификация задач (правило #10).
112
- forbiddenBashFailures = new Map();
113
- searchRunner;
114
- searchesThisSession = 0;
115
- retryWebSearchSignatures = new Set();
116
- lastErrorSearchAt = 0;
117
- errorSearchCooldownMs;
118
- hallucinationDetector = null;
119
- /**
120
- * Мутабельное состояние execution-плагина. Владеем ЗДЕСЬ, передаём ПО ССЫЛКЕ
121
- * фабрике плагина — плагин пишет deps.state.* напрямую, записи видны модулю
122
- * без write-back.
123
- */
124
- state = {
125
- lastRecoveryIteration: -STUCK_RECOVERY_COOLDOWN,
126
- consecutivePlanWarnings: 0,
127
- lastStepId: -1,
128
- stuckNotified: false,
129
- lastStuckWarnKey: "",
130
- lastStuckWarnIter: -STUCK_WARN_REPEAT_EVERY,
131
- escalationDirectiveSent: false,
132
- depsGateHints: new Map(),
133
- mutationsWithoutPlan: 0,
134
- planNudgeSent: false,
135
- typecheckFailures: new Map(),
136
- };
137
- /**
138
- * Read/write доступ к трекеру, общий для фабрик plan-tool и execution-plugin.
139
- * Abort тула `plan` чистит его (current = null) — сеттер держит this.tracker
140
- * в синхроне. Геттеры литерала биндят `this` на литерал, поэтому инстанс
141
- * захвачен замыканием.
142
- *
143
- * Сеттер зеркалит per-session слот (план следует за сессией): план-тулы
144
- * (`abort/switch/delete/purge/...`) пишут через trackerRef напрямую, минуя
145
- * setPlan — без хука слот протух бы и воскрешал отменённый план возвратом
146
- * в сессию. IO fail-open: слот не должен ронять тулы.
147
- */
148
- trackerRef = (() => {
149
- const self = this;
150
- return {
151
- get current() {
152
- return self.tracker;
153
- },
154
- set current(v) {
155
- self.tracker = v;
156
- self.flushSessionPlan();
157
- },
158
- };
159
- })();
160
- /** Зеркалит текущий трекер в слот активной сессии (null → clear).
161
- * Вызывать после прямых присвоений this.tracker вне setPlan/switchSession. */
162
- flushSessionPlan() {
163
- if (!this.sessionId)
164
- return;
165
- try {
166
- if (this.tracker)
167
- this.store.saveSessionActive(this.sessionId, this.tracker.getPlan());
168
- else
169
- this.store.clearSessionActive(this.sessionId);
170
- }
171
- catch {
172
- // fail-open: per-session слот не должен ронять тулы/гейты
173
- }
174
- }
175
- constructor(baseDir, stuckThreshold = 6, webSearchThreshold = 5, searchRunner = performWebSearch, errorSearchCooldownMs = ERROR_SEARCH_MIN_INTERVAL_MS) {
176
- this.baseDir = baseDir;
177
- this.verifier = new StepVerifier(baseDir);
178
- this.stuckDetector = new StuckDetector(stuckThreshold, 3, webSearchThreshold);
179
- this.auditor = new Auditor(baseDir);
180
- this.store = new PlanStore(baseDir);
181
- this.searchRunner = searchRunner;
182
- this.errorSearchCooldownMs = errorSearchCooldownMs;
183
- }
184
- /** Ставит план активным (синхрон указателя, персист, сброс завершённого/скипов). */
185
- setPlan(plan) {
186
- this.tracker = new PlanTracker(plan);
187
- // Указатель мимо done/skipped шагов восстановленного/перепланированного
188
- // плана: display ("current: step N") и off-track alignment матчатся с
189
- // реальностью, а не вечно указывают на шаг 1.
190
- this.tracker.syncCurrentStep();
191
- this.store.saveActive(plan);
192
- if (this.sessionId) {
193
- try {
194
- this.store.saveSessionActive(this.sessionId, plan);
195
- }
196
- catch {
197
- // fail-open: per-session слот не должен ронять создание плана
198
- }
199
- }
200
- this.completedPlan = null; // новый план вытесняет завершённый
201
- this._auditSkipsRemaining = 0; // план явно создан — взводим audit-gate
202
- }
203
- /** Переключает трекер на план другой сессии. Персистит текущий трекер
204
- * в слот старой сессии (пустота тоже запоминается через clear, чтобы
205
- * возврат не воскрешал чужой план), загружает план новой сессии.
206
- * Завершённый на диске план — в архив, как в restorePlan. */
207
- switchSession(id) {
208
- const prev = this.sessionId;
209
- if (prev === id)
210
- return;
211
- // Персист уходящей стороны. Стартовый трекер без sessionId (restorePlan
212
- // до известной сессии) усыновляется новой сессией, а не теряется.
213
- if (this.tracker) {
214
- try {
215
- this.store.saveSessionActive(prev ?? id ?? "", this.tracker.getPlan());
216
- }
217
- catch {
218
- // fail-open: битый id слота / ФС — трекер в памяти остаётся
219
- }
220
- }
221
- else if (prev) {
222
- try {
223
- this.store.clearSessionActive(prev);
224
- }
225
- catch {
226
- /* best-effort */
227
- }
228
- }
229
- this.sessionId = id;
230
- this.completedPlan = null;
231
- if (!id) {
232
- this.tracker = null;
233
- this._auditSkipsRemaining = 0;
234
- return;
235
- }
236
- let plan = null;
237
- try {
238
- plan = this.store.loadSessionActive(id);
239
- }
240
- catch {
241
- plan = null;
242
- }
243
- if (!plan) {
244
- this.tracker = null;
245
- this._auditSkipsRemaining = 0;
246
- return;
247
- }
248
- const restored = new PlanTracker(plan);
249
- if (restored.isComplete()) {
250
- this.store.archivePlan(plan);
251
- try {
252
- this.store.clearSessionActive(id);
253
- }
254
- catch {
255
- /* best-effort */
256
- }
257
- this.tracker = null;
258
- return;
259
- }
260
- this.tracker = restored;
261
- this.tracker.syncCurrentStep();
262
- this._auditSkipsRemaining = 1; // как восстановленный план
263
- }
264
- /** Забывает сессию: чистит её слот плана. Удаляемая сессия не может быть
265
- * текущей (web гардит 409), но REPL /delete — может: тогда сбрасываем
266
- * и трекер, чтобы не висел план-призрак. */
267
- forgetSession(id) {
268
- try {
269
- this.store.clearSessionActive(id);
270
- }
271
- catch {
272
- /* best-effort */
273
- }
274
- if (this.sessionId === id) {
275
- this.sessionId = null;
276
- this.tracker = null;
277
- this.completedPlan = null;
278
- this._auditSkipsRemaining = 0;
279
- }
280
- }
281
- /** Вяжет детектор галлюцинаций: тул plan проверяет удалённость файлов (auto-switch kind gate). */
282
- setHallucinationDetector(detector) {
283
- this.hallucinationDetector = detector;
284
- }
285
- /** Запоминает последний завершённый план: финальный аудит проверит его и
286
- * после очистки трекера авто-архивом. */
287
- recordCompleted(plan) {
288
- this.completedPlan = plan;
289
- }
290
- /** Забывает завершённый план (abort/delete/purge — аудитить нечего). */
291
- clearCompleted() {
292
- this.completedPlan = null;
293
- }
294
- /** Восстанавливает активный план с диска. False, если нет/уже завершён (тогда в архив). */
295
- restorePlan() {
296
- const plan = this.store.loadActive();
297
- if (!plan)
298
- return false;
299
- const restored = new PlanTracker(plan);
300
- // План, уже завершённый на момент сохранения, активным не возвращается —
301
- // архивируем, чтобы не якорил агента (восстановленные готовые планы давали
302
- // петлю "continue step 4" на рестарте).
303
- if (restored.isComplete()) {
304
- this.store.archivePlan(plan);
305
- this.tracker = null;
306
- return false;
307
- }
308
- this.tracker = restored;
309
- // Двигаем к первому недонесённому шагу
310
- this.tracker.syncCurrentStep();
311
- this._auditSkipsRemaining = 1; // восстановленный план — один свободный проход
312
- return true;
313
- }
314
- /** Трекер (null без активного плана). */
315
- getTracker() {
316
- return this.tracker;
317
- }
318
- /** Текущий трекаемый план (единый источник правды для UI).
319
- * Null в свежей сессии — план с диска восстанавливается только при resume
320
- * сессии с историей, REPL протухших планов не видит. */
321
- getActivePlan() {
322
- return this.tracker?.getPlan() ?? null;
323
- }
324
- /** Стор планов. */
325
- getStore() {
326
- return this.store;
327
- }
328
- /** Stuck-детектор. */
329
- getStuckDetector() {
330
- return this.stuckDetector;
331
- }
332
- /**
333
- * Автопоиск в вебе повторяющейся ошибки (≥ порога errorWebSearch одинаковых
334
- * сигнатур). Поиск fire-and-forget (результат тула не блокирует), результаты
335
- * очередятся <system-summary> в pendingMessages.
336
- *
337
- * Гейты: мастер-свитч webSearch + свитч errorWebSearch → повторная сигнатура
338
- * → не-исканная (или ретрайная) → сессионный кап → содержательный текст ошибки →
339
- * кулдаун. Один поиск на сигнатуру; пустые результаты — один ретрай
340
- * (размаркировка раз), затем сигнатура считается исканной.
341
- */
342
- maybeSearchError(ctx, call) {
343
- if (ctx.config?.webSearch?.enabled === false)
344
- return;
345
- const cfg = ctx.config?.errorWebSearch;
346
- if (!cfg?.enabled)
347
- return;
348
- const sig = this.stuckDetector.getRepeatedErrorSignature();
349
- if (!sig)
350
- return;
351
- if (this.stuckDetector.hasErrorSearched(sig) && !this.retryWebSearchSignatures.has(sig))
352
- return;
353
- if (this.searchesThisSession >= (cfg.maxSearchesPerSession ?? 3))
354
- return;
355
- const lastError = this.stuckDetector.getLastErrorOutput();
356
- if (!isSearchableError(lastError)) {
357
- ctx.logger?.debug(t("exec.error_search_no_query"));
358
- return;
359
- }
360
- const now = Date.now();
361
- if (now - this.lastErrorSearchAt < this.errorSearchCooldownMs)
362
- return;
363
- const stepDesc = this.tracker?.getCurrentStep()?.description ?? "";
364
- const query = buildSearchQuery(stepDesc, this.stuckDetector.getLastBashCommand(), lastError, call.name, cfg.maxQueryChars ?? 200);
365
- const count = this.stuckDetector.getErrorSignatureCount(sig);
366
- this.stuckDetector.markErrorSearched(sig);
367
- this.searchesThisSession++;
368
- this.lastErrorSearchAt = now;
369
- const networkConfig = getSessionSecurityConfig(ctx.config, ctx.sessionContext).network;
370
- this.searchRunner(query, cfg.maxResults ?? 5, networkConfig, cfg.requestTimeoutMs ?? 10000)
371
- .then((res) => {
372
- if (!res.success || res.results.length === 0) {
373
- if (!this.retryWebSearchSignatures.has(sig)) {
374
- this.retryWebSearchSignatures.add(sig);
375
- this.stuckDetector.unmarkErrorSearched(sig);
376
- }
377
- ctx.logger?.warn(t("exec.error_search_failed", { query }));
378
- ctx.sessionLog?.plan("web-search", `empty/failed: ${query}`);
379
- return;
380
- }
381
- const resultsText = res.results
382
- .map((r, i) => `${i + 1}. ${r.title} \u2014 ${r.url}\n ${r.snippet}`)
383
- .join("\n");
384
- this.pendingMessages.push({
385
- role: "user",
386
- content: `<system-summary>${t("exec.error_search_results", {
387
- sig,
388
- count: String(count),
389
- query,
390
- results: resultsText,
391
- })}</system-summary>`,
392
- });
393
- })
394
- .catch((e) => ctx.logger?.warn(`error web search: ${e.message}`));
395
- }
396
- /**
397
- * Финальный аудит перед правом агента заявить "готово". Null без активного
398
- * плана; иначе — готовность плана + существование артефактов.
399
- */
400
- /**
401
- * Evidence-based автозакрытие пендинг шагов с deliverables на диске. Мелкие
402
- * модели рутинно доделывают работу, но забывают бухгалтерию `plan update`
403
- * (было в ses_mthn3c2a: 2/5 шагов done при всех артефактах на месте — audit-gate
404
- * реджектил корректный финальный ответ и жёг retry-бюджет на бухгалтерию, не
405
- * на работу).
406
- *
407
- * Стандарт ТОТ ЖЕ, что аудитор применяет к done-шагам: каждый файлоподобный
408
- * токен описания резолвится в существующий файл. Шаги без файловых токенов
409
- * остаются пендинг (верифицировать нечего).
410
- */
411
- autoCloseEvidenceSteps(plan) {
412
- let closed = 0;
413
- for (const step of plan.steps) {
414
- if (step.status === "done" || step.status === "skipped")
415
- continue;
416
- const tokens = extractFileLikeTokens(stripUrls(step.description));
417
- if (tokens.length === 0)
418
- continue;
419
- const resolved = tokens.map((f) => findExistingFile(this.baseDir, f));
420
- if (step.kind === "delete") {
421
- // Delete-шаг закрыт, только если каждая именованная цель ОТСУТСТВУЕТ.
422
- // (Старая existence-проверка маркила done при файлах на месте —
423
- // deliverable-gate инвертировался.)
424
- if (resolved.some((r) => r !== null))
425
- continue;
426
- }
427
- else {
428
- // create: каждая цель существует И непуста. Пустой плейсхолдер — не
429
- // deliverable, а аудитор смотрит только существование — автозакрытие
430
- // дало бы ложный "passed".
431
- if (resolved.some((r) => r === null))
432
- continue;
433
- const empty = resolved.some((r) => {
434
- try {
435
- return readFileSync(r, "utf-8").trim().length < 10;
436
- }
437
- catch {
438
- return false; // unreadable — fall back to existence
439
- }
440
- });
441
- if (empty)
442
- continue;
443
- }
444
- step.status = "done";
445
- step.note = `auto-closed by final audit: ${step.kind === "delete" ? "all named files removed" : "all named files exist with content"} (${tokens.join(", ")})`;
446
- closed++;
447
- }
448
- return closed;
449
- }
450
- /** Финальный аудит активного/завершённого плана: файлы, тесты, tsc, пендинги. Null — аудитить нечего. */
451
- async runFinalAudit() {
452
- // Нет активного трекера: аудитим последний завершённый план вместо bail.
453
- // План, закрытый через `plan update`, авто-архивируется и чистит трекер;
454
- // без этого финальный аудит (тесты + tsc + файлы) молча скипался и модель
455
- // заявляла успех на битых артефактах.
456
- if (!this.tracker) {
457
- if (!this.completedPlan)
458
- return null;
459
- const plan = this.completedPlan;
460
- const autoClosed = this.autoCloseEvidenceSteps(plan);
461
- const audit = await this.auditor.audit(plan);
462
- const pendingSteps = plan.steps.flatMap((s) => s.status !== "done" && s.status !== "skipped" ? [`${s.id}. ${s.description}`] : []);
463
- const done = plan.steps.filter((s) => s.status === "done").length;
464
- if (autoClosed > 0) {
465
- this.store.saveActive(plan);
466
- this.flushSessionPlan();
467
- }
468
- return {
469
- passed: audit.passed && pendingSteps.length === 0,
470
- done,
471
- total: plan.steps.length,
472
- pendingSteps,
473
- missingFiles: audit.missingFiles,
474
- summary: audit.summary,
475
- };
476
- }
477
- if (this._auditSkipsRemaining > 0) {
478
- this._auditSkipsRemaining--;
479
- return null;
480
- }
481
- const plan = this.tracker.getPlan();
482
- const autoClosed = this.autoCloseEvidenceSteps(plan);
483
- if (autoClosed > 0) {
484
- this.store.saveActive(plan);
485
- this.flushSessionPlan();
486
- }
487
- const audit = await this.auditor.audit(plan);
488
- const pendingSteps = plan.steps.flatMap((s) => s.status !== "done" && s.status !== "skipped" ? [`${s.id}. ${s.description}`] : []);
489
- const done = plan.steps.filter((s) => s.status === "done").length;
490
- const passed = audit.passed && pendingSteps.length === 0;
491
- return {
492
- passed,
493
- done,
494
- total: plan.steps.length,
495
- pendingSteps,
496
- missingFiles: audit.missingFiles,
497
- summary: audit.summary,
498
- };
499
- }
500
- /** Блок системного промпта с чеклистом плана (null без активного/незавершённого). */
501
- getSystemPromptBlock() {
502
- if (!this.tracker || this.tracker.isComplete())
503
- return null;
504
- return {
505
- content: this.tracker.toPromptBlock(),
506
- priority: "critical",
507
- essential: true,
508
- estimatedTokens: 200,
509
- };
510
- }
511
- /**
512
- * Короткая строка "текущий план" для сводки компакции. Null без активного
513
- * плана. Для 9B-моделей важна явная инструкция "continue it, do NOT create
514
- * a new plan" — после компакции блок плана виден, но модель всё равно
515
- * пересоздаёт план (было: ses_msvuao0h).
516
- *
517
- * Готовый план в сводке — "план done, можно новый", а НЕ "continue step 4,
518
- * do NOT create a new plan", якоривший петлю ses_msxjbnm4.
519
- */
520
- getPlanSummary() {
521
- if (!this.tracker)
522
- return null;
523
- const plan = this.tracker.getPlan();
524
- const done = plan.steps.filter((s) => s.status === "done").length;
525
- const total = plan.steps.length;
526
- if (this.tracker.isComplete()) {
527
- return t("exec.plan_summary_complete", {
528
- id: plan.id,
529
- title: plan.title,
530
- done: String(done),
531
- total: String(total),
532
- });
533
- }
534
- const current = this.tracker.getCurrentStepIndex() + 1;
535
- return t("exec.plan_summary_continue", {
536
- id: plan.id,
537
- title: plan.title,
538
- done: String(done),
539
- total: String(total),
540
- current: String(current),
541
- });
542
- }
543
- /** Определения тулов модуля (plan/todo/verify через фабрику plan-tool). */
544
- getToolDefinitions() {
545
- return createPlanToolDefinitions({
546
- store: this.store,
547
- verifier: this.verifier,
548
- trackerRef: this.trackerRef,
549
- preserveActive: () => this.preserveActive(),
550
- setPlan: (p) => this.setPlan(p),
551
- recordCompleted: (p) => this.recordCompleted(p),
552
- clearCompleted: () => this.clearCompleted(),
553
- hasStepDeliverables: (s) => this.hasStepDeliverables(s),
554
- missingStepDeliverables: (s) => this.missingStepDeliverables(s),
555
- stillExistingDeliverables: (s) => this.stillExistingDeliverables(s),
556
- parseKinds: (a, st) => this.parseKinds(a, st),
557
- parseChecks: (a, st) => this.parseChecks(a, st),
558
- getTaskText: (c) => this.getTaskText(c),
559
- typecheckFailures: this.state.typecheckFailures,
560
- baseDir: this.baseDir,
561
- wasFileDeleted: this.hallucinationDetector
562
- ? (path) => this.hallucinationDetector.getConsistencyCheck().getDeletedFiles().includes(path)
563
- : undefined,
564
- });
565
- }
566
- /** Плагин модуля (хуки цикла из фабрики execution-plugin). */
567
- getPlugin() {
568
- return createExecutionPlugin({
569
- stuckDetector: this.stuckDetector,
570
- trackerRef: this.trackerRef,
571
- pendingMessages: this.pendingMessages,
572
- forbiddenBashFailures: this.forbiddenBashFailures,
573
- state: this.state,
574
- store: this.store,
575
- checkPlanAlignment: (call) => this.checkPlanAlignment(call),
576
- advancePlanIfStepComplete: (sl) => this.advancePlanIfStepComplete(sl),
577
- maybeSearchError: (ctx, call) => this.maybeSearchError(ctx, call),
578
- });
579
- }
580
- preserveActive() {
581
- if (!this.tracker)
582
- return;
583
- const plan = this.tracker.getPlan();
584
- if (plan.steps.every((s) => s.status === "done" || s.status === "skipped")) {
585
- this.store.archivePlan(plan);
586
- }
587
- else {
588
- this.store.saveDraft(plan);
589
- }
590
- }
591
- checkPlanAlignment(call) {
592
- if (!this.tracker)
593
- return null;
594
- const step = this.tracker.getCurrentStep();
595
- if (!step)
596
- return null;
597
- if (PLAN_ALIGNMENT_EXEMPT_TOOLS.has(call.name))
598
- return null;
599
- const stepPaths = extractFileLikeTokens(stripUrls(step.description)).map(planPathToken);
600
- if (stepPaths.length === 0)
601
- return null;
602
- // Инспектируем только path-like аргументы. JSON-стринг всего blob'а args
603
- // скармливал кодовые токены `content` write_file/edit_file в off-path чек
604
- // (напр. `import "./styles.css"` в теле файла) и давал фантомные alignment-
605
- // варнинги на on-track записях.
606
- const argStr = this.pathArgStrings(call.arguments).join(" ");
607
- const callPaths = extractFileLikeTokens(stripUrls(argStr)).map(planPathToken);
608
- if (callPaths.length === 0)
609
- return null;
610
- // Файлы уже ЗАКРЫТЫХ (done/skipped) шагов — легитимные цели переписи:
611
- // агент итерируется по ним, чиня LSP/type-ошибки. Блок здесь остановил бы
612
- // нормальный багфикс.
613
- const plan = this.tracker.getPlan();
614
- const finishedPaths = new Set();
615
- for (const s of plan.steps) {
616
- if (s.status === "done" || s.status === "skipped") {
617
- extractFileLikeTokens(stripUrls(s.description))
618
- .map(planPathToken)
619
- .forEach((p) => finishedPaths.add(p));
620
- }
621
- }
622
- // Двунаправленный overlap path-токенов, общий для ОБЕИХ проверок ниже. Шаг
623
- // может звать "main.ts", а тул — "src/main.ts" (или наоборот): односторонний
624
- // `s.includes(p)` частый nested/частичный кейс пропускал (было: перепись
625
- // src/main.ts закрытого шага флаговалась off-path текущего и помогла
626
- // hard-block'нуть третий вызов).
627
- const matchesAny = (p, tokens) => tokens.some((t) => t === p || t.includes(p) || p.includes(t));
628
- const finished = [...finishedPaths];
629
- const offPath = callPaths.some((p) => {
630
- if (matchesAny(p, finished))
631
- return false;
632
- return !matchesAny(p, stepPaths);
633
- });
634
- if (!offPath)
635
- return null;
636
- return t("exec.plan_warning", {
637
- step: String(step.id),
638
- description: step.description,
639
- tool: call.name,
640
- });
641
- }
642
- /** Строковые значения path-like аргументов вызова. Ограничивает off-path
643
- * чек аргументами, реально именующими файлы (path, file, dir, src, dst,
644
- * source, target, input, output, destination, glob, workdir, cwd, command,
645
- * pattern), полезную нагрузку не сканирует. */
646
- pathArgStrings(args) {
647
- if (!args)
648
- return [];
649
- const out = [];
650
- for (const [key, value] of Object.entries(args)) {
651
- if (!/path|file|dir|src|dst|source|target|input|output|destination|glob|workdir|cwd|command|pattern|query/i.test(key)) {
652
- continue;
653
- }
654
- if (typeof value === "string")
655
- out.push(value);
656
- else if (Array.isArray(value)) {
657
- for (const v of value)
658
- if (typeof v === "string")
659
- out.push(v);
660
- }
661
- }
662
- return out;
663
- }
664
- advancePlanIfStepComplete(sessionLog) {
665
- const step = this.tracker?.getCurrentStep();
666
- if (!step)
667
- return;
668
- const stepText = step.description.toLowerCase();
669
- // Общий файловый фильтр (allow-list реальных расширений, сегменты только
670
- // из расширения отброшены). Шаг "Удалить .js, оставить .tsx/.ts" НЕ даёт
671
- // фантомный токен "tsx/.ts" — его не существует, allGone тривиально true и
672
- // автопродвинуло бы delete-шаг при живых файлах на удаление (сырой regex
673
- // делал ровно так).
674
- const stepPaths = extractFileLikeTokens(stripUrls(step.description)) || [];
675
- // Гейт шагов: зависимости проверяем при упоминании — ДО путей файлов.
676
- // Нужен реальный глагол пакетного менеджера (правило #10 — без голого
677
- // keyword-матчинга: один "init" или "setup project" локфайловый хинт НЕ
678
- // триггерят, только конкретные install-команды).
679
- const isDepsStep = /(?:npm|bun|yarn|pnpm|pip|pip3|pipenv|poetry|composer|deno|go|gem|cargo)\s+(?:install|add|init|i|get)\b|bun\s+(?:add|install)|npm\s+(?:i|install|add)|(?:install|установ\w*)\s+(?:dependencies|зависимост\w*|пакет\w*|packages?)/i.test(stepText);
680
- if (isDepsStep) {
681
- const lockFiles = [
682
- "package-lock.json",
683
- "bun.lockb",
684
- "yarn.lock",
685
- "pnpm-lock.yaml",
686
- "node_modules",
687
- "go.sum",
688
- "Cargo.lock",
689
- "Pipfile.lock",
690
- "poetry.lock",
691
- "requirements.txt",
692
- ];
693
- const hasLockFile = lockFiles.some((f) => existsSync(resolve(this.baseDir, f)));
694
- if (!hasLockFile) {
695
- const hints = this.state.depsGateHints.get(step.id) || 0;
696
- this.state.depsGateHints.set(step.id, hints + 1);
697
- const force = hints >= 1;
698
- const content = force
699
- ? t("exec.step_gate_deps_force", { step: String(step.id) })
700
- : t("exec.step_gate_deps", {
701
- step: String(step.id),
702
- description: step.description,
703
- });
704
- this.pendingMessages.push({
705
- role: "user",
706
- content: `<system-summary>${content}</system-summary>`,
707
- });
708
- return;
709
- }
710
- }
711
- if (stepPaths.length === 0)
712
- return;
713
- // Токены резолвим ТЕМ ЖЕ обходом поддерева, что deliverable-gate и аудитор
714
- // (findExistingFile): вложенный файл ("bicycle-shop/src/bicycles.ts" для
715
- // токена "src/bicycles.ts") засчитывается. Старый точный
716
- // existsSync(resolve()) вложенные проекты не матчил — автопродвижение
717
- // молчало и после записи реального файла.
718
- const resolved = stepPaths.map((p) => findExistingFile(this.baseDir, p));
719
- const allExist = resolved.every((r) => r !== null);
720
- const allGone = resolved.every((r) => r === null);
721
- const satisfied = step.kind === "delete" ? allGone && !allExist : allExist;
722
- if (!satisfied)
723
- return;
724
- // Гейт шагов: файлы проверяем на контент (не пустые)
725
- if (step.kind !== "delete") {
726
- const emptyFiles = [];
727
- for (const r of resolved) {
728
- if (!r)
729
- continue;
730
- try {
731
- const content = readFileSync(r, "utf-8");
732
- if (content.trim().length < 10) {
733
- emptyFiles.push(r);
734
- }
735
- }
736
- catch {
737
- // Нечитаем — откат на existence
738
- }
739
- }
740
- if (emptyFiles.length > 0) {
741
- this.pendingMessages.push({
742
- role: "user",
743
- content: `<system-summary>${t("exec.step_gate_empty", { step: String(step.id), files: emptyFiles.join(", ") })}</system-summary>`,
744
- });
745
- return;
746
- }
747
- }
748
- // Все проверки прошли — двигаем
749
- this.tracker?.updateStepStatus(step.id, "done");
750
- const hadNext = this.tracker?.advance() ?? false;
751
- if (this.tracker) {
752
- this.store.saveActive(this.tracker.getPlan());
753
- this.flushSessionPlan();
754
- sessionLog?.plan("auto-advance", `Step ${step.id} auto-completed | ${this.tracker.getProgressString()} | current: step ${this.tracker.getCurrentStepIndex() + 1}`);
755
- }
756
- const nextStep = hadNext ? this.tracker?.getCurrentStep() : null;
757
- const nextMsg = nextStep
758
- ? t("exec.step_gate_ok", {
759
- step: String(step.id),
760
- nextStep: String(nextStep.id),
761
- nextDesc: nextStep.description,
762
- })
763
- : t("exec.step_gate_last", { step: String(step.id) });
764
- this.pendingMessages.push({
765
- role: "user",
766
- content: `<system-summary>${nextMsg}</system-summary>`,
767
- });
768
- // Авто-архив только что завершённого плана (все шаги done/skipped).
769
- // Готовый план не висит активным вечно, якоря агента на готовую задачу
770
- // ("continue step 4, do NOT create a new plan" — петля ses_msxjbnm4).
771
- // Per-step deliverable-gate файлы уже проверил.
772
- if (this.tracker?.isComplete()) {
773
- const completed = this.tracker.getPlan();
774
- this.store.archivePlan(completed);
775
- this.recordCompleted(completed); // final audit still verifies it
776
- this.tracker = null;
777
- this.flushSessionPlan(); // завершённый план не висит в слоте сессии
778
- sessionLog?.plan("auto-archive", `Plan ${completed.id} complete — archived`);
779
- }
780
- }
781
- /**
782
- * Файловые токены из описания шага, не резолвящиеся в реальный файл.
783
- * Тот же общий экстрактор токенов (allow-list реальных расширений, URL
784
- * вырезаны) и subtree-резолвер аудитора: "bicycles.ts" находит
785
- * "bicycle-shop/src/data/bicycles.ts", а hostname в описании — никогда
786
- * missing deliverable. Шаги без файловых токенов (чистые команды, прогоны
787
- * проверок) неверифицируемы.
788
- */
789
- missingStepDeliverables(step) {
790
- const tokens = extractFileLikeTokens(stripUrls(step.description));
791
- if (tokens.length === 0)
792
- return [];
793
- return tokens.filter((p) => !findExistingFile(this.baseDir, p));
794
- }
795
- /**
796
- * Файловые токены из описания шага, всё ещё резолвящиеся в реальный файл.
797
- * Инверсия missingStepDeliverables — для гейта delete-шагов ("done" значит
798
- * файлы пропали).
799
- */
800
- stillExistingDeliverables(step) {
801
- const tokens = extractFileLikeTokens(stripUrls(step.description));
802
- if (tokens.length === 0)
803
- return [];
804
- return tokens.filter((p) => findExistingFile(this.baseDir, p));
805
- }
806
- /** Есть ли в описании шага хоть один реальный файловый токен. Шаги без
807
- * токенов (чистые команды, прогоны проверок) не автоверифицируются —
808
- * done-gate для них vacuous. */
809
- hasStepDeliverables(step) {
810
- return extractFileLikeTokens(stripUrls(step.description)).length > 0;
811
- }
812
- /**
813
- * Валидирует опциональный пер-шаговый аргумент `kinds` для create плана и
814
- * update-с-шагами. Возвращает выровненные по длине kinds или i18n-строку
815
- * ошибки. Нет kinds → null (вызывающий фолбэчится на all-create). Общий для
816
- * ОБЕИХ веток: перестройка через update не дропает kinds молча.
817
- */
818
- parseKinds(args, steps) {
819
- if (args.kinds === undefined)
820
- return { kinds: null, error: null };
821
- if (!Array.isArray(args.kinds)) {
822
- return { kinds: null, error: t("plan.kinds_not_array") };
823
- }
824
- const kindsRaw = args.kinds.map(String);
825
- if (kindsRaw.length !== steps.length) {
826
- return { kinds: null, error: t("plan.kinds_mismatch") };
827
- }
828
- const invalid = kindsRaw.filter((k) => k !== "create" && k !== "delete");
829
- if (invalid.length > 0) {
830
- return {
831
- kinds: null,
832
- error: t("plan.kinds_invalid", {
833
- kinds: invalid.join(", "),
834
- }),
835
- };
836
- }
837
- return { kinds: kindsRaw, error: null };
838
- }
839
- /**
840
- * Валидирует пер-шаговый аргумент `checks` для create / re-plan плана.
841
- * Checks ОБЯЗАТЕЛЬНЫ (шаг без контракта верификации свой done не докажет):
842
- * отсутствующие, несовпавшие по длине или с битым префиксом возвращают
843
- * i18n-строку ошибки. Валидные префиксы: file-exists: / command: /
844
- * manual: (см. plan-checks.ts).
845
- */
846
- parseChecks(args, steps) {
847
- if (args.checks === undefined) {
848
- return { checks: null, error: t("plan.checks_required") };
849
- }
850
- if (!Array.isArray(args.checks)) {
851
- return { checks: null, error: t("plan.checks_not_array") };
852
- }
853
- const raw = args.checks.map(String);
854
- if (raw.length !== steps.length) {
855
- return { checks: null, error: t("plan.checks_mismatch") };
856
- }
857
- const bad = raw.filter((c) => !isValidCheck(c));
858
- if (bad.length > 0) {
859
- return {
860
- checks: null,
861
- error: t("plan.checks_invalid", {
862
- kinds: bad.slice(0, 3).join("; "),
863
- }),
864
- };
865
- }
866
- return { checks: raw.map((c) => c.trim()), error: null };
867
- }
868
- /**
869
- * Достаёт исходную формулировку задачи из первого user-сообщения истории.
870
- * Нужно для валидации покрытия плана против требований.
871
- */
872
- getTaskText(ctx) {
873
- const manager = ctx?.contextManager;
874
- if (!manager)
875
- return "";
876
- const history = manager.getActiveHistory();
877
- // Первое user-сообщение может быть инжектированным <system-summary>
878
- // (блок компакции) — это НЕ задача. Покрытие сравнивает план с реальной
879
- // инструкцией модели (было: протухший файловый список сводки компакции дал
880
- // bogus-варнинг "в плане не хватает файлов").
881
- const firstUser = history.find((m) => {
882
- if (m.role !== "user")
883
- return false;
884
- const text = getMessageText(m.content);
885
- return !text.startsWith("<system-summary>") && !text.includes("[Compressed:");
886
- });
887
- if (!firstUser)
888
- return "";
889
- return getMessageText(firstUser.content).trim();
890
- }
891
- }