micro-models-agent 2.16.0 → 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 +34 -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 -1211
  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 -277
  48. package/dist/assets/setup.js +3 -816
  49. package/dist/assets/smd.js +29 -1665
  50. package/dist/assets/styles.css +1 -1592
  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,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
- }