muonroi-cli 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2000) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +122 -122
  3. package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
  4. package/dist/src/agent-harness/__tests__/mock-model.spec.js +48 -1
  5. package/dist/src/agent-harness/mock-model.d.ts +11 -0
  6. package/dist/src/agent-harness/mock-model.js +21 -0
  7. package/dist/src/cli/cost-forensics.js +12 -12
  8. package/dist/src/council/__tests__/clarification-prompt.test.js +51 -0
  9. package/dist/src/council/__tests__/clarifier-ready-gate.test.js +32 -0
  10. package/dist/src/council/__tests__/decisions-lock.test.js +17 -1
  11. package/dist/src/council/__tests__/oauth-reachable.test.d.ts +1 -0
  12. package/dist/src/council/__tests__/oauth-reachable.test.js +31 -0
  13. package/dist/src/council/__tests__/parse-outcome-fallback.test.js +11 -0
  14. package/dist/src/council/clarifier.js +9 -1
  15. package/dist/src/council/debate.js +5 -1
  16. package/dist/src/council/decisions-lock.js +3 -3
  17. package/dist/src/council/index.js +12 -5
  18. package/dist/src/council/leader.d.ts +0 -17
  19. package/dist/src/council/leader.js +22 -15
  20. package/dist/src/council/planner.js +1 -1
  21. package/dist/src/council/prompts.js +63 -57
  22. package/dist/src/council/types.d.ts +7 -0
  23. package/dist/src/ee/__tests__/ee-onboarding.test.d.ts +1 -0
  24. package/dist/src/ee/__tests__/ee-onboarding.test.js +32 -0
  25. package/dist/src/ee/auth.d.ts +9 -0
  26. package/dist/src/ee/auth.js +19 -0
  27. package/dist/src/ee/ee-onboarding.d.ts +5 -0
  28. package/dist/src/ee/ee-onboarding.js +76 -0
  29. package/dist/src/generated/version.d.ts +1 -1
  30. package/dist/src/generated/version.js +1 -1
  31. package/dist/src/headless/output.js +6 -4
  32. package/dist/src/headless/output.test.js +4 -3
  33. package/dist/src/index.js +20 -1
  34. package/dist/src/mcp/__tests__/auto-setup.test.js +74 -0
  35. package/dist/src/mcp/__tests__/client-pool.spec.d.ts +1 -0
  36. package/dist/src/mcp/__tests__/client-pool.spec.js +98 -0
  37. package/dist/src/mcp/__tests__/parallel-build.spec.d.ts +1 -0
  38. package/dist/src/mcp/__tests__/parallel-build.spec.js +67 -0
  39. package/dist/src/mcp/__tests__/smart-filter.test.js +56 -0
  40. package/dist/src/mcp/auto-setup.js +56 -2
  41. package/dist/src/mcp/client-pool.d.ts +46 -0
  42. package/dist/src/mcp/client-pool.js +212 -0
  43. package/dist/src/mcp/oauth-callback.js +2 -2
  44. package/dist/src/mcp/parse-headers.test.js +14 -14
  45. package/dist/src/mcp/runtime.d.ts +28 -0
  46. package/dist/src/mcp/runtime.js +117 -51
  47. package/dist/src/mcp/self-verify-runner.d.ts +14 -0
  48. package/dist/src/mcp/self-verify-runner.js +38 -0
  49. package/dist/src/mcp/setup-guide-text.d.ts +9 -0
  50. package/dist/src/mcp/setup-guide-text.js +84 -0
  51. package/dist/src/mcp/smart-filter.js +49 -0
  52. package/dist/src/mcp/smoke.test.js +43 -43
  53. package/dist/src/mcp/tools-server.d.ts +7 -0
  54. package/dist/src/mcp/tools-server.js +19 -22
  55. package/dist/src/models/catalog.json +349 -349
  56. package/dist/src/ops/__tests__/doctor-ee-health.test.js +21 -0
  57. package/dist/src/ops/doctor.d.ts +3 -2
  58. package/dist/src/ops/doctor.js +47 -11
  59. package/dist/src/ops/doctor.test.js +4 -3
  60. package/dist/src/orchestrator/__tests__/mcp-capability-block.test.d.ts +1 -0
  61. package/dist/src/orchestrator/__tests__/mcp-capability-block.test.js +39 -0
  62. package/dist/src/orchestrator/__tests__/project-stack.test.d.ts +1 -0
  63. package/dist/src/orchestrator/__tests__/project-stack.test.js +65 -0
  64. package/dist/src/orchestrator/batch-turn-runner.js +7 -11
  65. package/dist/src/orchestrator/message-processor.js +57 -27
  66. package/dist/src/orchestrator/orchestrator.js +26 -0
  67. package/dist/src/orchestrator/prompts.d.ts +51 -0
  68. package/dist/src/orchestrator/prompts.js +257 -134
  69. package/dist/src/orchestrator/scope-ceiling.js +6 -1
  70. package/dist/src/orchestrator/stream-runner.js +20 -15
  71. package/dist/src/orchestrator/text-tool-call-detector.test.js +13 -13
  72. package/dist/src/pil/__tests__/clarity-gate.test.js +24 -215
  73. package/dist/src/pil/__tests__/config.test.js +1 -17
  74. package/dist/src/pil/__tests__/discovery.test.js +144 -11
  75. package/dist/src/pil/__tests__/layer1-intent-trace.test.js +7 -2
  76. package/dist/src/pil/__tests__/layer1-intent.test.js +3 -0
  77. package/dist/src/pil/__tests__/layer16-clarity.test.js +32 -116
  78. package/dist/src/pil/__tests__/layer4-gsd.test.js +37 -0
  79. package/dist/src/pil/__tests__/layer6-output.test.js +137 -18
  80. package/dist/src/pil/__tests__/llm-classify.test.js +49 -2
  81. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  82. package/dist/src/pil/agent-operating-contract.js +2 -0
  83. package/dist/src/pil/agent-operating-contract.test.js +7 -2
  84. package/dist/src/pil/cheap-model-playbook.js +35 -35
  85. package/dist/src/pil/cheap-model-workbooks.js +16 -13
  86. package/dist/src/pil/clarity-gate.d.ts +21 -19
  87. package/dist/src/pil/clarity-gate.js +26 -153
  88. package/dist/src/pil/config.d.ts +9 -1
  89. package/dist/src/pil/config.js +15 -4
  90. package/dist/src/pil/discovery.js +211 -136
  91. package/dist/src/pil/layer1-intent.d.ts +12 -0
  92. package/dist/src/pil/layer1-intent.js +283 -38
  93. package/dist/src/pil/layer1-intent.test.js +210 -4
  94. package/dist/src/pil/layer16-clarity.d.ts +25 -11
  95. package/dist/src/pil/layer16-clarity.js +19 -306
  96. package/dist/src/pil/layer4-gsd.js +18 -6
  97. package/dist/src/pil/layer6-output.d.ts +2 -0
  98. package/dist/src/pil/layer6-output.js +137 -22
  99. package/dist/src/pil/llm-classify.d.ts +26 -0
  100. package/dist/src/pil/llm-classify.js +34 -5
  101. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  102. package/dist/src/pil/native-capabilities-workbook.js +82 -76
  103. package/dist/src/pil/schema.d.ts +8 -0
  104. package/dist/src/pil/schema.js +12 -1
  105. package/dist/src/pil/task-tier-map.js +4 -0
  106. package/dist/src/pil/types.d.ts +11 -1
  107. package/dist/src/product-loop/done-gate.js +3 -3
  108. package/dist/src/product-loop/loop-driver.js +18 -18
  109. package/dist/src/product-loop/progress-snapshot.js +4 -4
  110. package/dist/src/providers/auth/gemini-oauth.js +6 -15
  111. package/dist/src/providers/auth/grok-oauth.js +6 -15
  112. package/dist/src/providers/auth/openai-oauth.js +6 -15
  113. package/dist/src/providers/mcp-vision-bridge.js +48 -48
  114. package/dist/src/reporter/index.js +1 -1
  115. package/dist/src/scaffold/bb-ecosystem-apply.js +47 -47
  116. package/dist/src/scaffold/bb-quality-gate.js +5 -5
  117. package/dist/src/scaffold/continuation-prompt.js +60 -60
  118. package/dist/src/scaffold/init-new.js +453 -453
  119. package/dist/src/self-qa/__tests__/scenario-planner.test.js +3 -3
  120. package/dist/src/self-qa/agentic-loop.js +24 -19
  121. package/dist/src/self-qa/spec-emitter.js +26 -23
  122. package/dist/src/storage/__tests__/migrations.test.js +2 -2
  123. package/dist/src/storage/interaction-log.js +5 -5
  124. package/dist/src/storage/migrations.js +122 -122
  125. package/dist/src/storage/sessions.js +42 -42
  126. package/dist/src/storage/transcript.js +91 -84
  127. package/dist/src/storage/usage.js +14 -14
  128. package/dist/src/storage/workspaces.js +12 -12
  129. package/dist/src/tools/__tests__/native-tools.test.d.ts +1 -0
  130. package/dist/src/tools/__tests__/native-tools.test.js +53 -0
  131. package/dist/src/tools/git-safety.d.ts +61 -0
  132. package/dist/src/tools/git-safety.js +141 -0
  133. package/dist/src/tools/git-safety.test.d.ts +1 -0
  134. package/dist/src/tools/git-safety.test.js +111 -0
  135. package/dist/src/tools/native-tools.d.ts +31 -0
  136. package/dist/src/tools/native-tools.js +273 -0
  137. package/dist/src/tools/registry-git-safety.test.d.ts +7 -0
  138. package/dist/src/tools/registry-git-safety.test.js +92 -0
  139. package/dist/src/tools/registry.js +39 -4
  140. package/dist/src/ui/__tests__/markdown-render.test.d.ts +1 -0
  141. package/dist/src/ui/__tests__/markdown-render.test.js +48 -0
  142. package/dist/src/ui/app.js +0 -0
  143. package/dist/src/ui/components/message-view.js +4 -1
  144. package/dist/src/ui/components/structured-response-view.js +7 -3
  145. package/dist/src/ui/components/tool-group.js +7 -1
  146. package/dist/src/ui/markdown-render.d.ts +41 -0
  147. package/dist/src/ui/markdown-render.js +223 -0
  148. package/dist/src/ui/markdown.d.ts +10 -0
  149. package/dist/src/ui/markdown.js +12 -35
  150. package/dist/src/ui/slash/council-inspect.js +4 -4
  151. package/dist/src/ui/slash/export.js +4 -4
  152. package/dist/src/ui/utils/text.d.ts +8 -0
  153. package/dist/src/ui/utils/text.js +16 -0
  154. package/dist/src/ui/utils/text.test.d.ts +1 -0
  155. package/dist/src/ui/utils/text.test.js +23 -0
  156. package/dist/src/usage/ledger.js +48 -15
  157. package/dist/src/utils/__tests__/footprint-gitignore.test.d.ts +1 -0
  158. package/dist/src/utils/__tests__/footprint-gitignore.test.js +50 -0
  159. package/dist/src/utils/clipboard-image.js +23 -23
  160. package/dist/src/utils/open-url.d.ts +56 -0
  161. package/dist/src/utils/open-url.js +58 -0
  162. package/dist/src/utils/open-url.test.d.ts +1 -0
  163. package/dist/src/utils/open-url.test.js +86 -0
  164. package/dist/src/utils/settings.d.ts +12 -0
  165. package/dist/src/utils/settings.js +48 -0
  166. package/dist/src/utils/side-question.js +2 -2
  167. package/dist/src/utils/skills.js +3 -3
  168. package/dist/src/verify/__tests__/coverage-parsers.test.js +30 -30
  169. package/dist/src/verify/environment.js +2 -1
  170. package/package.json +3 -2
  171. package/dist/muonroi-cli-standalone.exe +0 -0
  172. package/dist/packages/agent-harness-core/src/driver.js.map +0 -1
  173. package/dist/packages/agent-harness-core/src/event-filter.js.map +0 -1
  174. package/dist/packages/agent-harness-core/src/event-redact.js.map +0 -1
  175. package/dist/packages/agent-harness-core/src/idle.js.map +0 -1
  176. package/dist/packages/agent-harness-core/src/index.js.map +0 -1
  177. package/dist/packages/agent-harness-core/src/mcp-server.js.map +0 -1
  178. package/dist/packages/agent-harness-core/src/mock-llm.js.map +0 -1
  179. package/dist/packages/agent-harness-core/src/predicate.js.map +0 -1
  180. package/dist/packages/agent-harness-core/src/protocol.js.map +0 -1
  181. package/dist/packages/agent-harness-core/src/registry.js.map +0 -1
  182. package/dist/packages/agent-harness-core/src/selector.js.map +0 -1
  183. package/dist/packages/agent-harness-core/src/spec-helpers.js.map +0 -1
  184. package/dist/packages/agent-harness-core/src/transports/sidechannel.js.map +0 -1
  185. package/dist/packages/agent-harness-core/src/transports/ws.js.map +0 -1
  186. package/dist/packages/agent-harness-opentui/src/agent-mode.js.map +0 -1
  187. package/dist/packages/agent-harness-opentui/src/index.js.map +0 -1
  188. package/dist/packages/agent-harness-opentui/src/input-bridge.js.map +0 -1
  189. package/dist/packages/agent-harness-opentui/src/install.js.map +0 -1
  190. package/dist/packages/agent-harness-opentui/src/reconciler-hook.js.map +0 -1
  191. package/dist/packages/agent-harness-opentui/src/semantic.js.map +0 -1
  192. package/dist/src/__test-helpers__/catalog-fixtures.js.map +0 -1
  193. package/dist/src/__test-stubs__/ee-server.js.map +0 -1
  194. package/dist/src/__test-stubs__/vitest-setup.js.map +0 -1
  195. package/dist/src/__tests__/council/bubble-layout.test.js.map +0 -1
  196. package/dist/src/__tests__/council/code-block-truncate.test.js.map +0 -1
  197. package/dist/src/__tests__/council/role-palette.test.js.map +0 -1
  198. package/dist/src/__tests__/first-run-wizard.test.js.map +0 -1
  199. package/dist/src/agent-harness/__tests__/cli-flags.spec.js.map +0 -1
  200. package/dist/src/agent-harness/__tests__/driver.spec.js.map +0 -1
  201. package/dist/src/agent-harness/__tests__/idle.spec.js.map +0 -1
  202. package/dist/src/agent-harness/__tests__/mock-llm.spec.js.map +0 -1
  203. package/dist/src/agent-harness/__tests__/mock-model.spec.js.map +0 -1
  204. package/dist/src/agent-harness/__tests__/predicate.spec.js.map +0 -1
  205. package/dist/src/agent-harness/__tests__/protocol.spec.js.map +0 -1
  206. package/dist/src/agent-harness/__tests__/schema.spec.js.map +0 -1
  207. package/dist/src/agent-harness/__tests__/selector.spec.js.map +0 -1
  208. package/dist/src/agent-harness/__tests__/sidechannel.spec.js.map +0 -1
  209. package/dist/src/agent-harness/__tests__/spec-helpers.spec.js.map +0 -1
  210. package/dist/src/agent-harness/index.js.map +0 -1
  211. package/dist/src/agent-harness/mock-model.js.map +0 -1
  212. package/dist/src/agent-harness/test-spawn.js.map +0 -1
  213. package/dist/src/billing/index.js.map +0 -1
  214. package/dist/src/chat/__tests__/broadcast-bus.test.js.map +0 -1
  215. package/dist/src/chat/__tests__/channel-manager.test.js.map +0 -1
  216. package/dist/src/chat/__tests__/client.test.js.map +0 -1
  217. package/dist/src/chat/__tests__/discord-integration.test.js.map +0 -1
  218. package/dist/src/chat/__tests__/intent-prompt.test.js.map +0 -1
  219. package/dist/src/chat/__tests__/verdict-resolver.test.js.map +0 -1
  220. package/dist/src/chat/broadcast-bus.js.map +0 -1
  221. package/dist/src/chat/channel-manager.js.map +0 -1
  222. package/dist/src/chat/chat-keychain.js.map +0 -1
  223. package/dist/src/chat/factory.js.map +0 -1
  224. package/dist/src/chat/intent-prompt.js.map +0 -1
  225. package/dist/src/chat/providers/discord/client.js.map +0 -1
  226. package/dist/src/chat/types.js.map +0 -1
  227. package/dist/src/chat/verdict-constants.js.map +0 -1
  228. package/dist/src/chat/verdict-resolver.js.map +0 -1
  229. package/dist/src/cli/__tests__/bw-vault.test.js.map +0 -1
  230. package/dist/src/cli/__tests__/keys-bundle.test.js.map +0 -1
  231. package/dist/src/cli/__tests__/share-cmd.test.js.map +0 -1
  232. package/dist/src/cli/bw-vault.js.map +0 -1
  233. package/dist/src/cli/config/__tests__/model-picker.test.js.map +0 -1
  234. package/dist/src/cli/config/__tests__/provider-fetch.test.js.map +0 -1
  235. package/dist/src/cli/config/index.js.map +0 -1
  236. package/dist/src/cli/config/model-picker.js.map +0 -1
  237. package/dist/src/cli/config/provider-fetch.js.map +0 -1
  238. package/dist/src/cli/config/screen-council.js.map +0 -1
  239. package/dist/src/cli/config/screen-models.js.map +0 -1
  240. package/dist/src/cli/config/screen-providers.js.map +0 -1
  241. package/dist/src/cli/config/tui.js.map +0 -1
  242. package/dist/src/cli/cost-forensics.js.map +0 -1
  243. package/dist/src/cli/cost-forensics.test.js.map +0 -1
  244. package/dist/src/cli/keys-bundle.js.map +0 -1
  245. package/dist/src/cli/keys.js.map +0 -1
  246. package/dist/src/cli/keys.test.js.map +0 -1
  247. package/dist/src/cli/pil-report.js.map +0 -1
  248. package/dist/src/cli/reporter-cmd.js.map +0 -1
  249. package/dist/src/cli/share-cmd.js.map +0 -1
  250. package/dist/src/cli/usage-report.js.map +0 -1
  251. package/dist/src/cloud/index.js.map +0 -1
  252. package/dist/src/council/__tests__/accounting.test.js.map +0 -1
  253. package/dist/src/council/__tests__/audit-replay.test.js.map +0 -1
  254. package/dist/src/council/__tests__/clarifier-max-rounds.test.js.map +0 -1
  255. package/dist/src/council/__tests__/clarifier-options.test.js.map +0 -1
  256. package/dist/src/council/__tests__/clarifier-ready-gate.test.js.map +0 -1
  257. package/dist/src/council/__tests__/cost-aware.test.js.map +0 -1
  258. package/dist/src/council/__tests__/debate-planner-structured.test.js.map +0 -1
  259. package/dist/src/council/__tests__/decisions-lock.test.js.map +0 -1
  260. package/dist/src/council/__tests__/evaluator-metrics.test.js.map +0 -1
  261. package/dist/src/council/__tests__/parse-outcome-fallback.test.js.map +0 -1
  262. package/dist/src/council/__tests__/research-tools.test.js.map +0 -1
  263. package/dist/src/council/__tests__/round-tools.test.js.map +0 -1
  264. package/dist/src/council/__tests__/tool-trace.test.js.map +0 -1
  265. package/dist/src/council/__tests__/types-contract.test.js.map +0 -1
  266. package/dist/src/council/clarifier.js.map +0 -1
  267. package/dist/src/council/context.js.map +0 -1
  268. package/dist/src/council/debate-planner.js.map +0 -1
  269. package/dist/src/council/debate.js.map +0 -1
  270. package/dist/src/council/decisions-lock.js.map +0 -1
  271. package/dist/src/council/executor.js.map +0 -1
  272. package/dist/src/council/index.js.map +0 -1
  273. package/dist/src/council/leader.js.map +0 -1
  274. package/dist/src/council/llm.js.map +0 -1
  275. package/dist/src/council/phase-events.js.map +0 -1
  276. package/dist/src/council/planner.js.map +0 -1
  277. package/dist/src/council/preflight.js.map +0 -1
  278. package/dist/src/council/prompts.js.map +0 -1
  279. package/dist/src/council/types.js.map +0 -1
  280. package/dist/src/daemon/scheduler.js.map +0 -1
  281. package/dist/src/daemon/scheduler.test.js.map +0 -1
  282. package/dist/src/ee/__tests__/bb-design.test.js.map +0 -1
  283. package/dist/src/ee/__tests__/export-transcripts.test.js.map +0 -1
  284. package/dist/src/ee/__tests__/pil-context-bridge.test.js.map +0 -1
  285. package/dist/src/ee/__tests__/pipeline.integration.test.js.map +0 -1
  286. package/dist/src/ee/__tests__/recall-format.test.js.map +0 -1
  287. package/dist/src/ee/__tests__/recall-ledger.test.js.map +0 -1
  288. package/dist/src/ee/__tests__/render-sink-wiring.test.js.map +0 -1
  289. package/dist/src/ee/auth.js.map +0 -1
  290. package/dist/src/ee/auth.test.js.map +0 -1
  291. package/dist/src/ee/bb-design.js.map +0 -1
  292. package/dist/src/ee/bb-retrieval.js.map +0 -1
  293. package/dist/src/ee/bridge.js.map +0 -1
  294. package/dist/src/ee/bridge.test.js.map +0 -1
  295. package/dist/src/ee/client-mode.js.map +0 -1
  296. package/dist/src/ee/client.js.map +0 -1
  297. package/dist/src/ee/client.test.js.map +0 -1
  298. package/dist/src/ee/council-bridge.js.map +0 -1
  299. package/dist/src/ee/embedding-cache.js.map +0 -1
  300. package/dist/src/ee/export-transcripts.js.map +0 -1
  301. package/dist/src/ee/extract-session.js.map +0 -1
  302. package/dist/src/ee/extract-session.test.js.map +0 -1
  303. package/dist/src/ee/health.js.map +0 -1
  304. package/dist/src/ee/index.js.map +0 -1
  305. package/dist/src/ee/intercept.js.map +0 -1
  306. package/dist/src/ee/intercept.test.js.map +0 -1
  307. package/dist/src/ee/judge.js.map +0 -1
  308. package/dist/src/ee/judge.test.js.map +0 -1
  309. package/dist/src/ee/mistake-detector.js.map +0 -1
  310. package/dist/src/ee/mistake-detector.test.js.map +0 -1
  311. package/dist/src/ee/offline-queue.js.map +0 -1
  312. package/dist/src/ee/offline-queue.test.js.map +0 -1
  313. package/dist/src/ee/phase-outcome.js.map +0 -1
  314. package/dist/src/ee/phase-outcome.test.js.map +0 -1
  315. package/dist/src/ee/phase-tracker.js.map +0 -1
  316. package/dist/src/ee/phase-tracker.test.js.map +0 -1
  317. package/dist/src/ee/posttool.js.map +0 -1
  318. package/dist/src/ee/posttool.test.js.map +0 -1
  319. package/dist/src/ee/prompt-stale.js.map +0 -1
  320. package/dist/src/ee/prompt-stale.test.js.map +0 -1
  321. package/dist/src/ee/recall-ledger.js.map +0 -1
  322. package/dist/src/ee/recall-mirror.test.js.map +0 -1
  323. package/dist/src/ee/render.js.map +0 -1
  324. package/dist/src/ee/render.test.js.map +0 -1
  325. package/dist/src/ee/scope.js.map +0 -1
  326. package/dist/src/ee/scope.test.js.map +0 -1
  327. package/dist/src/ee/search.js.map +0 -1
  328. package/dist/src/ee/session-trajectory.js.map +0 -1
  329. package/dist/src/ee/session-trajectory.test.js.map +0 -1
  330. package/dist/src/ee/tenant.js.map +0 -1
  331. package/dist/src/ee/touch.test.js.map +0 -1
  332. package/dist/src/ee/transcript-emit.js.map +0 -1
  333. package/dist/src/ee/types.js.map +0 -1
  334. package/dist/src/flow/__tests__/migration.test.js.map +0 -1
  335. package/dist/src/flow/__tests__/parser.test.js.map +0 -1
  336. package/dist/src/flow/__tests__/run-manager-product.test.js.map +0 -1
  337. package/dist/src/flow/__tests__/run-manager.test.js.map +0 -1
  338. package/dist/src/flow/__tests__/scaffold-checkpoint.test.js.map +0 -1
  339. package/dist/src/flow/__tests__/scaffold.test.js.map +0 -1
  340. package/dist/src/flow/__tests__/warning-persist.test.js.map +0 -1
  341. package/dist/src/flow/artifact-io.js.map +0 -1
  342. package/dist/src/flow/compaction/__tests__/compress.test.js.map +0 -1
  343. package/dist/src/flow/compaction/__tests__/extract.test.js.map +0 -1
  344. package/dist/src/flow/compaction/__tests__/preserve.test.js.map +0 -1
  345. package/dist/src/flow/compaction/compress.js.map +0 -1
  346. package/dist/src/flow/compaction/extract.js.map +0 -1
  347. package/dist/src/flow/compaction/index.js.map +0 -1
  348. package/dist/src/flow/compaction/preserve.js.map +0 -1
  349. package/dist/src/flow/index.js.map +0 -1
  350. package/dist/src/flow/migration.js.map +0 -1
  351. package/dist/src/flow/parser.js.map +0 -1
  352. package/dist/src/flow/run-manager.js.map +0 -1
  353. package/dist/src/flow/scaffold-checkpoint.js.map +0 -1
  354. package/dist/src/flow/scaffold.js.map +0 -1
  355. package/dist/src/flow/warning-persist.js.map +0 -1
  356. package/dist/src/generated/version.js.map +0 -1
  357. package/dist/src/gsd/__tests__/complexity.test.js.map +0 -1
  358. package/dist/src/gsd/__tests__/directives.test.js.map +0 -1
  359. package/dist/src/gsd/__tests__/gray-areas.test.js.map +0 -1
  360. package/dist/src/gsd/__tests__/types.test.js.map +0 -1
  361. package/dist/src/gsd/complexity.js.map +0 -1
  362. package/dist/src/gsd/directives.js.map +0 -1
  363. package/dist/src/gsd/gray-areas.js.map +0 -1
  364. package/dist/src/gsd/index.js.map +0 -1
  365. package/dist/src/gsd/types.js.map +0 -1
  366. package/dist/src/headless/__tests__/council-answers.test.js.map +0 -1
  367. package/dist/src/headless/council-answers.js.map +0 -1
  368. package/dist/src/headless/output.js.map +0 -1
  369. package/dist/src/headless/output.test.js.map +0 -1
  370. package/dist/src/hooks/config.js.map +0 -1
  371. package/dist/src/hooks/index.js.map +0 -1
  372. package/dist/src/hooks/types.js.map +0 -1
  373. package/dist/src/index.js.map +0 -1
  374. package/dist/src/lsp/builtins.js.map +0 -1
  375. package/dist/src/lsp/builtins.test.js.map +0 -1
  376. package/dist/src/lsp/client.js.map +0 -1
  377. package/dist/src/lsp/manager.js.map +0 -1
  378. package/dist/src/lsp/manager.test.js.map +0 -1
  379. package/dist/src/lsp/npm-cache.js.map +0 -1
  380. package/dist/src/lsp/npm-cache.test.js.map +0 -1
  381. package/dist/src/lsp/runtime.js.map +0 -1
  382. package/dist/src/lsp/smoke.test.js.map +0 -1
  383. package/dist/src/lsp/types.js.map +0 -1
  384. package/dist/src/maintain/__tests__/codebase-intel.test.js.map +0 -1
  385. package/dist/src/maintain/__tests__/gh-create-pr.test.js.map +0 -1
  386. package/dist/src/maintain/__tests__/pr-builder.test.js.map +0 -1
  387. package/dist/src/maintain/__tests__/repo-map.test.js.map +0 -1
  388. package/dist/src/maintain/__tests__/task-runner.test.js.map +0 -1
  389. package/dist/src/maintain/codebase-intel.js.map +0 -1
  390. package/dist/src/maintain/gh-create-pr.js.map +0 -1
  391. package/dist/src/maintain/index.js.map +0 -1
  392. package/dist/src/maintain/pr-builder.js.map +0 -1
  393. package/dist/src/maintain/repo-map.js.map +0 -1
  394. package/dist/src/maintain/task-runner.js.map +0 -1
  395. package/dist/src/maintain/types.js.map +0 -1
  396. package/dist/src/mcp/__tests__/auto-setup.test.js.map +0 -1
  397. package/dist/src/mcp/__tests__/cap-tool-result.test.js.map +0 -1
  398. package/dist/src/mcp/__tests__/ee-tools.test.js.map +0 -1
  399. package/dist/src/mcp/__tests__/forensics-tools.test.js.map +0 -1
  400. package/dist/src/mcp/__tests__/harness-driver-action-tools.spec.js.map +0 -1
  401. package/dist/src/mcp/__tests__/harness-driver-async-tools.spec.js.map +0 -1
  402. package/dist/src/mcp/__tests__/harness-driver-read-tools.spec.js.map +0 -1
  403. package/dist/src/mcp/__tests__/harness-driver-security.spec.js.map +0 -1
  404. package/dist/src/mcp/__tests__/harness-driver.spec.js.map +0 -1
  405. package/dist/src/mcp/__tests__/lazy-schema.spec.js.map +0 -1
  406. package/dist/src/mcp/__tests__/lsp-tools.test.js.map +0 -1
  407. package/dist/src/mcp/__tests__/mcp-keychain.test.js.map +0 -1
  408. package/dist/src/mcp/__tests__/research-onboarding.test.js.map +0 -1
  409. package/dist/src/mcp/__tests__/runtime-hydration.test.js.map +0 -1
  410. package/dist/src/mcp/__tests__/runtime-output-cap.test.js.map +0 -1
  411. package/dist/src/mcp/__tests__/runtime-sanitize.test.js.map +0 -1
  412. package/dist/src/mcp/__tests__/self-verify-jobs.test.js.map +0 -1
  413. package/dist/src/mcp/__tests__/smart-filter.test.js.map +0 -1
  414. package/dist/src/mcp/__tests__/tools-server.smoke.test.js.map +0 -1
  415. package/dist/src/mcp/auto-setup.js.map +0 -1
  416. package/dist/src/mcp/cap-tool-result.js.map +0 -1
  417. package/dist/src/mcp/catalog.js.map +0 -1
  418. package/dist/src/mcp/ee-tools.js.map +0 -1
  419. package/dist/src/mcp/forensics-tools.js.map +0 -1
  420. package/dist/src/mcp/lsp-tools.js.map +0 -1
  421. package/dist/src/mcp/mcp-keychain.js.map +0 -1
  422. package/dist/src/mcp/oauth-callback.js.map +0 -1
  423. package/dist/src/mcp/oauth-provider.js.map +0 -1
  424. package/dist/src/mcp/opentui-spawn.js.map +0 -1
  425. package/dist/src/mcp/parse-headers.js.map +0 -1
  426. package/dist/src/mcp/parse-headers.test.js.map +0 -1
  427. package/dist/src/mcp/research-onboarding.js.map +0 -1
  428. package/dist/src/mcp/runtime.js.map +0 -1
  429. package/dist/src/mcp/self-verify-jobs.js.map +0 -1
  430. package/dist/src/mcp/smart-filter.js.map +0 -1
  431. package/dist/src/mcp/smoke.test.js.map +0 -1
  432. package/dist/src/mcp/tools-server.js.map +0 -1
  433. package/dist/src/mcp/validate.js.map +0 -1
  434. package/dist/src/models/__tests__/registry.test.js.map +0 -1
  435. package/dist/src/models/catalog-client.js.map +0 -1
  436. package/dist/src/models/catalog-gemini.test.js.map +0 -1
  437. package/dist/src/models/catalog-url.test.js.map +0 -1
  438. package/dist/src/models/catalog-validation.test.js.map +0 -1
  439. package/dist/src/models/classify-tier.js.map +0 -1
  440. package/dist/src/models/index.js.map +0 -1
  441. package/dist/src/models/registry.js.map +0 -1
  442. package/dist/src/ops/__tests__/doctor-council-mcp.test.js.map +0 -1
  443. package/dist/src/ops/__tests__/doctor-ee-health.test.js.map +0 -1
  444. package/dist/src/ops/bug-report.js.map +0 -1
  445. package/dist/src/ops/bug-report.test.js.map +0 -1
  446. package/dist/src/ops/doctor.js.map +0 -1
  447. package/dist/src/ops/doctor.test.js.map +0 -1
  448. package/dist/src/orchestrator/__tests__/agent-base-url-switch.test.js.map +0 -1
  449. package/dist/src/orchestrator/__tests__/batch-turn-runner.test.js.map +0 -1
  450. package/dist/src/orchestrator/__tests__/council-manager.test.js.map +0 -1
  451. package/dist/src/orchestrator/__tests__/cross-turn-dedup.test.js.map +0 -1
  452. package/dist/src/orchestrator/__tests__/current-call-id.test.js.map +0 -1
  453. package/dist/src/orchestrator/__tests__/error-forensics.test.js.map +0 -1
  454. package/dist/src/orchestrator/__tests__/flow-resume.test.js.map +0 -1
  455. package/dist/src/orchestrator/__tests__/humanize-api-error.test.js.map +0 -1
  456. package/dist/src/orchestrator/__tests__/message-processor.test.js.map +0 -1
  457. package/dist/src/orchestrator/__tests__/message-write-ahead.test.js.map +0 -1
  458. package/dist/src/orchestrator/__tests__/read-path-budget.test.js.map +0 -1
  459. package/dist/src/orchestrator/__tests__/retry-classifier.test.js.map +0 -1
  460. package/dist/src/orchestrator/__tests__/retry-stream.test.js.map +0 -1
  461. package/dist/src/orchestrator/__tests__/route-feedback.test.js.map +0 -1
  462. package/dist/src/orchestrator/__tests__/stream-runner.test.js.map +0 -1
  463. package/dist/src/orchestrator/__tests__/sub-agent-model-tier.test.js.map +0 -1
  464. package/dist/src/orchestrator/__tests__/usage-events-shape.test.js.map +0 -1
  465. package/dist/src/orchestrator/__tests__/usage-normalizer-c1.test.js.map +0 -1
  466. package/dist/src/orchestrator/__tests__/usage-shape-threading.test.js.map +0 -1
  467. package/dist/src/orchestrator/__tests__/write-ahead.test.js.map +0 -1
  468. package/dist/src/orchestrator/abort.js.map +0 -1
  469. package/dist/src/orchestrator/abort.test.js.map +0 -1
  470. package/dist/src/orchestrator/agent-options.js.map +0 -1
  471. package/dist/src/orchestrator/agent.test.js.map +0 -1
  472. package/dist/src/orchestrator/batch-turn-runner.js.map +0 -1
  473. package/dist/src/orchestrator/batch-utils.js.map +0 -1
  474. package/dist/src/orchestrator/cleanup.test.js.map +0 -1
  475. package/dist/src/orchestrator/compaction.js.map +0 -1
  476. package/dist/src/orchestrator/compaction.test.js.map +0 -1
  477. package/dist/src/orchestrator/council-manager.js.map +0 -1
  478. package/dist/src/orchestrator/cross-turn-dedup.js.map +0 -1
  479. package/dist/src/orchestrator/delegations.js.map +0 -1
  480. package/dist/src/orchestrator/delegations.test.js.map +0 -1
  481. package/dist/src/orchestrator/error-utils.js.map +0 -1
  482. package/dist/src/orchestrator/flow-resume.js.map +0 -1
  483. package/dist/src/orchestrator/grounding-check.js.map +0 -1
  484. package/dist/src/orchestrator/grounding-check.test.js.map +0 -1
  485. package/dist/src/orchestrator/interrupted-turn.js.map +0 -1
  486. package/dist/src/orchestrator/interrupted-turn.test.js.map +0 -1
  487. package/dist/src/orchestrator/message-processor.js.map +0 -1
  488. package/dist/src/orchestrator/message-seq.js.map +0 -1
  489. package/dist/src/orchestrator/message-seq.test.js.map +0 -1
  490. package/dist/src/orchestrator/orchestrator.js.map +0 -1
  491. package/dist/src/orchestrator/pending-calls.js.map +0 -1
  492. package/dist/src/orchestrator/pending-calls.test.js.map +0 -1
  493. package/dist/src/orchestrator/prompts.js.map +0 -1
  494. package/dist/src/orchestrator/provider-options-shape.js.map +0 -1
  495. package/dist/src/orchestrator/provider-options-shape.spec.js.map +0 -1
  496. package/dist/src/orchestrator/read-path-budget.js.map +0 -1
  497. package/dist/src/orchestrator/reasoning.js.map +0 -1
  498. package/dist/src/orchestrator/reasoning.test.js.map +0 -1
  499. package/dist/src/orchestrator/repair-tool-call.js.map +0 -1
  500. package/dist/src/orchestrator/repetition-detector.js.map +0 -1
  501. package/dist/src/orchestrator/repetition-detector.test.js.map +0 -1
  502. package/dist/src/orchestrator/retry-classifier.js.map +0 -1
  503. package/dist/src/orchestrator/retry-stream.js.map +0 -1
  504. package/dist/src/orchestrator/sandbox.test.js.map +0 -1
  505. package/dist/src/orchestrator/scope-ceiling.js.map +0 -1
  506. package/dist/src/orchestrator/scope-ceiling.test.js.map +0 -1
  507. package/dist/src/orchestrator/scope-reminder.js.map +0 -1
  508. package/dist/src/orchestrator/scope-reminder.test.js.map +0 -1
  509. package/dist/src/orchestrator/stall-rescue.js.map +0 -1
  510. package/dist/src/orchestrator/stall-rescue.test.js.map +0 -1
  511. package/dist/src/orchestrator/stall-watchdog.js.map +0 -1
  512. package/dist/src/orchestrator/stall-watchdog.test.js.map +0 -1
  513. package/dist/src/orchestrator/stream-runner.js.map +0 -1
  514. package/dist/src/orchestrator/sub-agent-cap.js.map +0 -1
  515. package/dist/src/orchestrator/sub-agent-cap.test.js.map +0 -1
  516. package/dist/src/orchestrator/sub-agent-model-tier.js.map +0 -1
  517. package/dist/src/orchestrator/subagent-compactor.js.map +0 -1
  518. package/dist/src/orchestrator/subagent-compactor.spec.js.map +0 -1
  519. package/dist/src/orchestrator/text-tool-call-detector.js.map +0 -1
  520. package/dist/src/orchestrator/text-tool-call-detector.test.js.map +0 -1
  521. package/dist/src/orchestrator/token-counter.js.map +0 -1
  522. package/dist/src/orchestrator/token-counter.test.js.map +0 -1
  523. package/dist/src/orchestrator/tool-args-hash.js.map +0 -1
  524. package/dist/src/orchestrator/tool-args-hash.test.js.map +0 -1
  525. package/dist/src/orchestrator/tool-args-repair.js.map +0 -1
  526. package/dist/src/orchestrator/tool-args-repair.test.js.map +0 -1
  527. package/dist/src/orchestrator/tool-loop-cap.js.map +0 -1
  528. package/dist/src/orchestrator/tool-loop-cap.test.js.map +0 -1
  529. package/dist/src/orchestrator/tool-repetition-detector.js.map +0 -1
  530. package/dist/src/orchestrator/tool-repetition-detector.test.js.map +0 -1
  531. package/dist/src/orchestrator/tool-utils.js.map +0 -1
  532. package/dist/src/orchestrator/turn-runner-deps.js.map +0 -1
  533. package/dist/src/pil/__tests__/budget.test.js.map +0 -1
  534. package/dist/src/pil/__tests__/clarity-gate.test.js.map +0 -1
  535. package/dist/src/pil/__tests__/config.test.js.map +0 -1
  536. package/dist/src/pil/__tests__/discovery-cache.test.js.map +0 -1
  537. package/dist/src/pil/__tests__/discovery-types.test.js.map +0 -1
  538. package/dist/src/pil/__tests__/discovery.test.js.map +0 -1
  539. package/dist/src/pil/__tests__/dual-run.test.js.map +0 -1
  540. package/dist/src/pil/__tests__/layer1-intent-trace.test.js.map +0 -1
  541. package/dist/src/pil/__tests__/layer1-intent.test.js.map +0 -1
  542. package/dist/src/pil/__tests__/layer15-context-scan.test.js.map +0 -1
  543. package/dist/src/pil/__tests__/layer16-clarity.test.js.map +0 -1
  544. package/dist/src/pil/__tests__/layer17-feasibility.test.js.map +0 -1
  545. package/dist/src/pil/__tests__/layer18-acceptance.test.js.map +0 -1
  546. package/dist/src/pil/__tests__/layer2-personality.test.js.map +0 -1
  547. package/dist/src/pil/__tests__/layer3-ee-injection.test.js.map +0 -1
  548. package/dist/src/pil/__tests__/layer3-injected-chunk.test.js.map +0 -1
  549. package/dist/src/pil/__tests__/layer4-gsd.test.js.map +0 -1
  550. package/dist/src/pil/__tests__/layer5-context.test.js.map +0 -1
  551. package/dist/src/pil/__tests__/layer6-output.test.js.map +0 -1
  552. package/dist/src/pil/__tests__/llm-classify.test.js.map +0 -1
  553. package/dist/src/pil/__tests__/native-capabilities-workbook.test.js.map +0 -1
  554. package/dist/src/pil/__tests__/ollama-classify.test.js.map +0 -1
  555. package/dist/src/pil/__tests__/orchestrator-integration.test.js.map +0 -1
  556. package/dist/src/pil/__tests__/pipeline.test.js.map +0 -1
  557. package/dist/src/pil/__tests__/renderer-coverage.test.js.map +0 -1
  558. package/dist/src/pil/__tests__/response-tools.test.js.map +0 -1
  559. package/dist/src/pil/__tests__/schema.test.js.map +0 -1
  560. package/dist/src/pil/__tests__/scoreComplexity.test.js.map +0 -1
  561. package/dist/src/pil/__tests__/scoreSufficiency.test.js.map +0 -1
  562. package/dist/src/pil/__tests__/store.test.js.map +0 -1
  563. package/dist/src/pil/__tests__/task-tier-map.test.js.map +0 -1
  564. package/dist/src/pil/agent-operating-contract.js.map +0 -1
  565. package/dist/src/pil/agent-operating-contract.test.js.map +0 -1
  566. package/dist/src/pil/budget-log.js.map +0 -1
  567. package/dist/src/pil/budget.js.map +0 -1
  568. package/dist/src/pil/cheap-model-playbook.js.map +0 -1
  569. package/dist/src/pil/cheap-model-playbook.test.js.map +0 -1
  570. package/dist/src/pil/cheap-model-workbooks.js.map +0 -1
  571. package/dist/src/pil/cheap-model-workbooks.test.js.map +0 -1
  572. package/dist/src/pil/clarity-gate.js.map +0 -1
  573. package/dist/src/pil/config.js.map +0 -1
  574. package/dist/src/pil/discovery-cache.js.map +0 -1
  575. package/dist/src/pil/discovery-types.js.map +0 -1
  576. package/dist/src/pil/discovery.js.map +0 -1
  577. package/dist/src/pil/index.js.map +0 -1
  578. package/dist/src/pil/layer1-intent.js.map +0 -1
  579. package/dist/src/pil/layer1-intent.test.js.map +0 -1
  580. package/dist/src/pil/layer15-context-scan.js.map +0 -1
  581. package/dist/src/pil/layer16-clarity.js.map +0 -1
  582. package/dist/src/pil/layer16-clarity.test.js +0 -31
  583. package/dist/src/pil/layer16-clarity.test.js.map +0 -1
  584. package/dist/src/pil/layer17-feasibility.js.map +0 -1
  585. package/dist/src/pil/layer18-acceptance.js.map +0 -1
  586. package/dist/src/pil/layer1_5-complexity-size.js.map +0 -1
  587. package/dist/src/pil/layer1_5-complexity-size.test.js.map +0 -1
  588. package/dist/src/pil/layer2-personality.js.map +0 -1
  589. package/dist/src/pil/layer3-ee-injection.js.map +0 -1
  590. package/dist/src/pil/layer4-gsd.js.map +0 -1
  591. package/dist/src/pil/layer5-context.js.map +0 -1
  592. package/dist/src/pil/layer6-output.js.map +0 -1
  593. package/dist/src/pil/llm-classify.js.map +0 -1
  594. package/dist/src/pil/native-capabilities-workbook.js.map +0 -1
  595. package/dist/src/pil/ollama-classify.js.map +0 -1
  596. package/dist/src/pil/pipeline.js.map +0 -1
  597. package/dist/src/pil/response-tools.js.map +0 -1
  598. package/dist/src/pil/schema.js.map +0 -1
  599. package/dist/src/pil/session-state.js.map +0 -1
  600. package/dist/src/pil/session-state.test.js.map +0 -1
  601. package/dist/src/pil/store.js.map +0 -1
  602. package/dist/src/pil/task-tier-map.js.map +0 -1
  603. package/dist/src/pil/timeout.js.map +0 -1
  604. package/dist/src/pil/types.js.map +0 -1
  605. package/dist/src/product-loop/__tests__/artifact-io.test.js.map +0 -1
  606. package/dist/src/product-loop/__tests__/assumption-ledger.test.js.map +0 -1
  607. package/dist/src/product-loop/__tests__/backlog-builder.test.js.map +0 -1
  608. package/dist/src/product-loop/__tests__/backlog-store.test.js.map +0 -1
  609. package/dist/src/product-loop/__tests__/cb2-retry-bonus.test.js.map +0 -1
  610. package/dist/src/product-loop/__tests__/circuit-breakers-coverage.test.js.map +0 -1
  611. package/dist/src/product-loop/__tests__/circuit-breakers.test.js.map +0 -1
  612. package/dist/src/product-loop/__tests__/complexity-routing.spec.js.map +0 -1
  613. package/dist/src/product-loop/__tests__/context-policy.test.js.map +0 -1
  614. package/dist/src/product-loop/__tests__/cost-preview.test.js.map +0 -1
  615. package/dist/src/product-loop/__tests__/cost-scoper.test.js.map +0 -1
  616. package/dist/src/product-loop/__tests__/cross-run-memory.test.js.map +0 -1
  617. package/dist/src/product-loop/__tests__/design-output.spec.js.map +0 -1
  618. package/dist/src/product-loop/__tests__/discover.test.js.map +0 -1
  619. package/dist/src/product-loop/__tests__/discovery-context-format.test.js.map +0 -1
  620. package/dist/src/product-loop/__tests__/discovery-council-runner.test.js.map +0 -1
  621. package/dist/src/product-loop/__tests__/discovery-detection.test.js.map +0 -1
  622. package/dist/src/product-loop/__tests__/discovery-ecosystem.test.js.map +0 -1
  623. package/dist/src/product-loop/__tests__/discovery-integration.test.js.map +0 -1
  624. package/dist/src/product-loop/__tests__/discovery-interview.test.js.map +0 -1
  625. package/dist/src/product-loop/__tests__/discovery-migrations.test.js.map +0 -1
  626. package/dist/src/product-loop/__tests__/discovery-persistence.test.js.map +0 -1
  627. package/dist/src/product-loop/__tests__/discovery-prompt-parser.test.js.map +0 -1
  628. package/dist/src/product-loop/__tests__/discovery-prompt-specificity.test.js.map +0 -1
  629. package/dist/src/product-loop/__tests__/discovery-recommender-ecosystem.test.js.map +0 -1
  630. package/dist/src/product-loop/__tests__/discovery-recommender.test.js.map +0 -1
  631. package/dist/src/product-loop/__tests__/discovery-schema.test.js.map +0 -1
  632. package/dist/src/product-loop/__tests__/done-gate-coverage.test.js.map +0 -1
  633. package/dist/src/product-loop/__tests__/done-gate.test.js.map +0 -1
  634. package/dist/src/product-loop/__tests__/ee-extract-wiring.test.js.map +0 -1
  635. package/dist/src/product-loop/__tests__/extract-to-ee.test.js.map +0 -1
  636. package/dist/src/product-loop/__tests__/feedback-routing.test.js.map +0 -1
  637. package/dist/src/product-loop/__tests__/gather-selectable-alts.test.js.map +0 -1
  638. package/dist/src/product-loop/__tests__/hot-path.spec.js.map +0 -1
  639. package/dist/src/product-loop/__tests__/integration.test.js.map +0 -1
  640. package/dist/src/product-loop/__tests__/loop-driver-audit.test.js.map +0 -1
  641. package/dist/src/product-loop/__tests__/loop-driver.test.js.map +0 -1
  642. package/dist/src/product-loop/__tests__/maintenance-task-synthesis.test.js.map +0 -1
  643. package/dist/src/product-loop/__tests__/phase-a1-a3-sprint-runner.test.js.map +0 -1
  644. package/dist/src/product-loop/__tests__/phase-a2-backlog-build.test.js.map +0 -1
  645. package/dist/src/product-loop/__tests__/phase-budget.test.js.map +0 -1
  646. package/dist/src/product-loop/__tests__/phase-orchestrator-integration.test.js.map +0 -1
  647. package/dist/src/product-loop/__tests__/phase-plan.test.js.map +0 -1
  648. package/dist/src/product-loop/__tests__/phase-rituals.test.js.map +0 -1
  649. package/dist/src/product-loop/__tests__/phase-runner.test.js.map +0 -1
  650. package/dist/src/product-loop/__tests__/phase-tracker-bridge.test.js.map +0 -1
  651. package/dist/src/product-loop/__tests__/pick-backend-stack.test.js.map +0 -1
  652. package/dist/src/product-loop/__tests__/product-identity.test.js.map +0 -1
  653. package/dist/src/product-loop/__tests__/progress-snapshot.test.js.map +0 -1
  654. package/dist/src/product-loop/__tests__/reality-anchor.test.js.map +0 -1
  655. package/dist/src/product-loop/__tests__/repo-audit.test.js.map +0 -1
  656. package/dist/src/product-loop/__tests__/repo-brief.test.js.map +0 -1
  657. package/dist/src/product-loop/__tests__/role-memory.test.js.map +0 -1
  658. package/dist/src/product-loop/__tests__/role-registry.test.js.map +0 -1
  659. package/dist/src/product-loop/__tests__/role-routing-ee.test.js.map +0 -1
  660. package/dist/src/product-loop/__tests__/route-decision-emit.test.js.map +0 -1
  661. package/dist/src/product-loop/__tests__/seed-questions.test.js.map +0 -1
  662. package/dist/src/product-loop/__tests__/ship-polish.test.js.map +0 -1
  663. package/dist/src/product-loop/__tests__/sprint-planner.test.js.map +0 -1
  664. package/dist/src/product-loop/__tests__/sprint-runner-backlog.test.js.map +0 -1
  665. package/dist/src/product-loop/__tests__/sprint-runner-emit.test.js.map +0 -1
  666. package/dist/src/product-loop/__tests__/sprint-runner-phase-chunks.test.js.map +0 -1
  667. package/dist/src/product-loop/__tests__/sprint-runner.test.js.map +0 -1
  668. package/dist/src/product-loop/__tests__/sprint-self-verify.test.js.map +0 -1
  669. package/dist/src/product-loop/__tests__/sprint-store.test.js.map +0 -1
  670. package/dist/src/product-loop/__tests__/stakeholder-acl.test.js.map +0 -1
  671. package/dist/src/product-loop/__tests__/state-md-ee-injections.test.js.map +0 -1
  672. package/dist/src/product-loop/__tests__/sufficiency-routing.spec.js.map +0 -1
  673. package/dist/src/product-loop/__tests__/typed-artifacts.test.js.map +0 -1
  674. package/dist/src/product-loop/__tests__/types.test.js.map +0 -1
  675. package/dist/src/product-loop/__tests__/verify-failure-threshold.test.js.map +0 -1
  676. package/dist/src/product-loop/__tests__/verify-failure-tracking.test.js.map +0 -1
  677. package/dist/src/product-loop/__tests__/verify-result.test.js.map +0 -1
  678. package/dist/src/product-loop/artifact-io.js.map +0 -1
  679. package/dist/src/product-loop/assumption-ledger.js.map +0 -1
  680. package/dist/src/product-loop/backlog-builder.js.map +0 -1
  681. package/dist/src/product-loop/backlog-store.js.map +0 -1
  682. package/dist/src/product-loop/circuit-breakers.js.map +0 -1
  683. package/dist/src/product-loop/context-policy.js.map +0 -1
  684. package/dist/src/product-loop/cost-preview.js.map +0 -1
  685. package/dist/src/product-loop/cost-scoper.js.map +0 -1
  686. package/dist/src/product-loop/cross-run-memory.js.map +0 -1
  687. package/dist/src/product-loop/design-output.js.map +0 -1
  688. package/dist/src/product-loop/discover.js.map +0 -1
  689. package/dist/src/product-loop/discovery-context-format.js.map +0 -1
  690. package/dist/src/product-loop/discovery-council-runner.js.map +0 -1
  691. package/dist/src/product-loop/discovery-detection.js.map +0 -1
  692. package/dist/src/product-loop/discovery-ecosystem.js.map +0 -1
  693. package/dist/src/product-loop/discovery-interview.js.map +0 -1
  694. package/dist/src/product-loop/discovery-migrations.js.map +0 -1
  695. package/dist/src/product-loop/discovery-persistence.js.map +0 -1
  696. package/dist/src/product-loop/discovery-prompt-parser.js.map +0 -1
  697. package/dist/src/product-loop/discovery-recommender.js.map +0 -1
  698. package/dist/src/product-loop/discovery-schema.js.map +0 -1
  699. package/dist/src/product-loop/done-gate.js.map +0 -1
  700. package/dist/src/product-loop/feedback-routing.js.map +0 -1
  701. package/dist/src/product-loop/gather.js.map +0 -1
  702. package/dist/src/product-loop/index.js.map +0 -1
  703. package/dist/src/product-loop/loop-driver.js.map +0 -1
  704. package/dist/src/product-loop/phase-budget.js.map +0 -1
  705. package/dist/src/product-loop/phase-plan.js.map +0 -1
  706. package/dist/src/product-loop/phase-rituals.js.map +0 -1
  707. package/dist/src/product-loop/phase-runner.js.map +0 -1
  708. package/dist/src/product-loop/phase-tracker-bridge.js.map +0 -1
  709. package/dist/src/product-loop/product-identity.js.map +0 -1
  710. package/dist/src/product-loop/progress-snapshot.js.map +0 -1
  711. package/dist/src/product-loop/reality-anchor.js.map +0 -1
  712. package/dist/src/product-loop/repo-audit.js.map +0 -1
  713. package/dist/src/product-loop/repo-brief.js.map +0 -1
  714. package/dist/src/product-loop/role-memory.js.map +0 -1
  715. package/dist/src/product-loop/role-registry.js.map +0 -1
  716. package/dist/src/product-loop/seed-questions.js.map +0 -1
  717. package/dist/src/product-loop/ship-polish.js.map +0 -1
  718. package/dist/src/product-loop/sprint-planner.js.map +0 -1
  719. package/dist/src/product-loop/sprint-runner.js.map +0 -1
  720. package/dist/src/product-loop/sprint-self-verify.js.map +0 -1
  721. package/dist/src/product-loop/sprint-store.js.map +0 -1
  722. package/dist/src/product-loop/stakeholder-acl.js.map +0 -1
  723. package/dist/src/product-loop/typed-artifacts.js.map +0 -1
  724. package/dist/src/product-loop/types.js.map +0 -1
  725. package/dist/src/product-loop/verify-failure-tracking.js.map +0 -1
  726. package/dist/src/product-loop/verify-result.js.map +0 -1
  727. package/dist/src/providers/__test-utils__/load-fixture.js.map +0 -1
  728. package/dist/src/providers/__tests__/adapter-oauth-wiring.test.js.map +0 -1
  729. package/dist/src/providers/__tests__/capabilities-cosmetic.test.js.map +0 -1
  730. package/dist/src/providers/__tests__/capabilities-flags.test.js.map +0 -1
  731. package/dist/src/providers/__tests__/capabilities-provider-options.test.js.map +0 -1
  732. package/dist/src/providers/__tests__/capabilities-sanitize.test.js.map +0 -1
  733. package/dist/src/providers/__tests__/capabilities.test.js.map +0 -1
  734. package/dist/src/providers/__tests__/provider-coverage.test.js.map +0 -1
  735. package/dist/src/providers/__tests__/reasoning-roundtrip.test.js.map +0 -1
  736. package/dist/src/providers/__tests__/runtime-integration.test.js.map +0 -1
  737. package/dist/src/providers/__tests__/runtime.test.js.map +0 -1
  738. package/dist/src/providers/__tests__/siliconflow-sse-repair.test.js.map +0 -1
  739. package/dist/src/providers/__tests__/strategies-registry.test.js.map +0 -1
  740. package/dist/src/providers/__tests__/strategies-resolve.test.js.map +0 -1
  741. package/dist/src/providers/__tests__/wire-debug.test.js.map +0 -1
  742. package/dist/src/providers/adapter.js.map +0 -1
  743. package/dist/src/providers/adapter.test.js.map +0 -1
  744. package/dist/src/providers/anthropic.js.map +0 -1
  745. package/dist/src/providers/auth/__tests__/browser-flow.test.js.map +0 -1
  746. package/dist/src/providers/auth/__tests__/device-flow.test.js.map +0 -1
  747. package/dist/src/providers/auth/__tests__/gemini-oauth.test.js.map +0 -1
  748. package/dist/src/providers/auth/__tests__/grok-oauth.test.js.map +0 -1
  749. package/dist/src/providers/auth/__tests__/openai-oauth.test.js.map +0 -1
  750. package/dist/src/providers/auth/__tests__/token-store.test.js.map +0 -1
  751. package/dist/src/providers/auth/browser-flow.js.map +0 -1
  752. package/dist/src/providers/auth/device-flow.js.map +0 -1
  753. package/dist/src/providers/auth/gemini-oauth.js.map +0 -1
  754. package/dist/src/providers/auth/grok-oauth.js.map +0 -1
  755. package/dist/src/providers/auth/openai-oauth.js.map +0 -1
  756. package/dist/src/providers/auth/registry.js.map +0 -1
  757. package/dist/src/providers/auth/token-store.js.map +0 -1
  758. package/dist/src/providers/auth/types.js.map +0 -1
  759. package/dist/src/providers/capabilities.js.map +0 -1
  760. package/dist/src/providers/endpoints.js.map +0 -1
  761. package/dist/src/providers/errors.js.map +0 -1
  762. package/dist/src/providers/errors.test.js.map +0 -1
  763. package/dist/src/providers/gemini.js.map +0 -1
  764. package/dist/src/providers/gemini.test.js.map +0 -1
  765. package/dist/src/providers/index.js.map +0 -1
  766. package/dist/src/providers/keychain.js.map +0 -1
  767. package/dist/src/providers/keychain.test.js.map +0 -1
  768. package/dist/src/providers/mcp-vision-bridge.js.map +0 -1
  769. package/dist/src/providers/mcp-vision-bridge.test.js.map +0 -1
  770. package/dist/src/providers/ollama.js.map +0 -1
  771. package/dist/src/providers/ollama.test.js.map +0 -1
  772. package/dist/src/providers/openai-compatible.js.map +0 -1
  773. package/dist/src/providers/openai-compatible.test.js.map +0 -1
  774. package/dist/src/providers/openai.js.map +0 -1
  775. package/dist/src/providers/openai.test.js.map +0 -1
  776. package/dist/src/providers/patch-zod-schema.js.map +0 -1
  777. package/dist/src/providers/pricing.js.map +0 -1
  778. package/dist/src/providers/pricing.test.js.map +0 -1
  779. package/dist/src/providers/prompt-cache-key.spec.js.map +0 -1
  780. package/dist/src/providers/runtime-mock.spec.js.map +0 -1
  781. package/dist/src/providers/runtime.js.map +0 -1
  782. package/dist/src/providers/siliconflow-sse-repair.js.map +0 -1
  783. package/dist/src/providers/strategies/anthropic.strategy.js.map +0 -1
  784. package/dist/src/providers/strategies/base.strategy.js.map +0 -1
  785. package/dist/src/providers/strategies/deepseek.strategy.js.map +0 -1
  786. package/dist/src/providers/strategies/google.strategy.js.map +0 -1
  787. package/dist/src/providers/strategies/ollama.strategy.js.map +0 -1
  788. package/dist/src/providers/strategies/openai.strategy.js.map +0 -1
  789. package/dist/src/providers/strategies/registry.js.map +0 -1
  790. package/dist/src/providers/strategies/siliconflow.strategy.js.map +0 -1
  791. package/dist/src/providers/strategies/xai.strategy.js.map +0 -1
  792. package/dist/src/providers/stream-loop.js.map +0 -1
  793. package/dist/src/providers/types.js.map +0 -1
  794. package/dist/src/providers/vision-proxy.js.map +0 -1
  795. package/dist/src/providers/vision-proxy.test.js.map +0 -1
  796. package/dist/src/providers/wire-debug.js.map +0 -1
  797. package/dist/src/reporter/__tests__/acl-check.test.js.map +0 -1
  798. package/dist/src/reporter/__tests__/auto-fire.test.js.map +0 -1
  799. package/dist/src/reporter/__tests__/budget.test.js.map +0 -1
  800. package/dist/src/reporter/__tests__/handlers.test.js.map +0 -1
  801. package/dist/src/reporter/__tests__/query-router.test.js.map +0 -1
  802. package/dist/src/reporter/acl-check.js.map +0 -1
  803. package/dist/src/reporter/auto-fire.js.map +0 -1
  804. package/dist/src/reporter/budget.js.map +0 -1
  805. package/dist/src/reporter/handlers.js.map +0 -1
  806. package/dist/src/reporter/index.js.map +0 -1
  807. package/dist/src/reporter/query-router.js.map +0 -1
  808. package/dist/src/router/__tests__/step-router.test.js.map +0 -1
  809. package/dist/src/router/classifier/grammars.js.map +0 -1
  810. package/dist/src/router/classifier/index.js.map +0 -1
  811. package/dist/src/router/classifier/index.test.js.map +0 -1
  812. package/dist/src/router/classifier/regex.js.map +0 -1
  813. package/dist/src/router/classifier/regex.test.js.map +0 -1
  814. package/dist/src/router/classifier/tree-sitter.js.map +0 -1
  815. package/dist/src/router/classifier/tree-sitter.test.js.map +0 -1
  816. package/dist/src/router/cold.js.map +0 -1
  817. package/dist/src/router/cold.test.js.map +0 -1
  818. package/dist/src/router/decide.js.map +0 -1
  819. package/dist/src/router/decide.test.js.map +0 -1
  820. package/dist/src/router/health.js.map +0 -1
  821. package/dist/src/router/health.test.js.map +0 -1
  822. package/dist/src/router/provider-sentinel.js.map +0 -1
  823. package/dist/src/router/provider-sentinel.test.js.map +0 -1
  824. package/dist/src/router/role-override.test.js.map +0 -1
  825. package/dist/src/router/step-router.js.map +0 -1
  826. package/dist/src/router/store.js.map +0 -1
  827. package/dist/src/router/types.js.map +0 -1
  828. package/dist/src/router/warm.js.map +0 -1
  829. package/dist/src/router/warm.test.js.map +0 -1
  830. package/dist/src/scaffold/__tests__/continuation-prompt.test.js.map +0 -1
  831. package/dist/src/scaffold/__tests__/continue-as-council.spec.js.map +0 -1
  832. package/dist/src/scaffold/__tests__/dotnet-assembly-name.test.js.map +0 -1
  833. package/dist/src/scaffold/__tests__/fe-scaffold-contents.test.js.map +0 -1
  834. package/dist/src/scaffold/__tests__/init-new.smoke.spec.js.map +0 -1
  835. package/dist/src/scaffold/__tests__/init-new.spec.js.map +0 -1
  836. package/dist/src/scaffold/__tests__/install-bb-templates.spec.js.map +0 -1
  837. package/dist/src/scaffold/__tests__/point-to-existing.spec.js.map +0 -1
  838. package/dist/src/scaffold/bb-ecosystem-apply.js.map +0 -1
  839. package/dist/src/scaffold/bb-quality-gate.js.map +0 -1
  840. package/dist/src/scaffold/continuation-prompt.js.map +0 -1
  841. package/dist/src/scaffold/continue-as-council.js.map +0 -1
  842. package/dist/src/scaffold/init-new.js.map +0 -1
  843. package/dist/src/scaffold/point-to-existing.js.map +0 -1
  844. package/dist/src/scaffold/resume-from-gate-failures.js.map +0 -1
  845. package/dist/src/self-qa/__tests__/agentic-context.test.js.map +0 -1
  846. package/dist/src/self-qa/__tests__/agentic-loop.test.js.map +0 -1
  847. package/dist/src/self-qa/__tests__/delta-encoder.test.js.map +0 -1
  848. package/dist/src/self-qa/__tests__/judge.test.js.map +0 -1
  849. package/dist/src/self-qa/__tests__/scenario-planner.test.js.map +0 -1
  850. package/dist/src/self-qa/__tests__/spec-emitter.test.js.map +0 -1
  851. package/dist/src/self-qa/agentic-context.js.map +0 -1
  852. package/dist/src/self-qa/agentic-loop.js.map +0 -1
  853. package/dist/src/self-qa/delta-encoder.js.map +0 -1
  854. package/dist/src/self-qa/index.js.map +0 -1
  855. package/dist/src/self-qa/judge.js.map +0 -1
  856. package/dist/src/self-qa/orchestrator.js.map +0 -1
  857. package/dist/src/self-qa/scenario-planner.js.map +0 -1
  858. package/dist/src/self-qa/spec-emitter.js.map +0 -1
  859. package/dist/src/self-qa/types.js.map +0 -1
  860. package/dist/src/storage/__tests__/migrations.test.js.map +0 -1
  861. package/dist/src/storage/__tests__/sweep-stale-pending.test.js.map +0 -1
  862. package/dist/src/storage/__tests__/ui-interaction-log.test.js.map +0 -1
  863. package/dist/src/storage/atomic-io.js.map +0 -1
  864. package/dist/src/storage/atomic-io.test.js.map +0 -1
  865. package/dist/src/storage/config.js.map +0 -1
  866. package/dist/src/storage/config.test.js.map +0 -1
  867. package/dist/src/storage/db.js.map +0 -1
  868. package/dist/src/storage/index.js.map +0 -1
  869. package/dist/src/storage/interaction-log.js.map +0 -1
  870. package/dist/src/storage/migrations.js.map +0 -1
  871. package/dist/src/storage/session-dir.js.map +0 -1
  872. package/dist/src/storage/sessions.js.map +0 -1
  873. package/dist/src/storage/tool-results.js.map +0 -1
  874. package/dist/src/storage/transcript-response-entry.test.js.map +0 -1
  875. package/dist/src/storage/transcript-view.js.map +0 -1
  876. package/dist/src/storage/transcript.js.map +0 -1
  877. package/dist/src/storage/transcript.test.js.map +0 -1
  878. package/dist/src/storage/ui-interaction-log.js.map +0 -1
  879. package/dist/src/storage/usage-cap.js.map +0 -1
  880. package/dist/src/storage/usage-cap.test.js.map +0 -1
  881. package/dist/src/storage/usage.js.map +0 -1
  882. package/dist/src/storage/workspaces.js.map +0 -1
  883. package/dist/src/tools/__tests__/vision-gate.test.js.map +0 -1
  884. package/dist/src/tools/bash-output-cache.js.map +0 -1
  885. package/dist/src/tools/bash-output-cache.test.js.map +0 -1
  886. package/dist/src/tools/bash-output-integration.test.js.map +0 -1
  887. package/dist/src/tools/bash.js.map +0 -1
  888. package/dist/src/tools/bash.test.js.map +0 -1
  889. package/dist/src/tools/computer.js.map +0 -1
  890. package/dist/src/tools/computer.test.js.map +0 -1
  891. package/dist/src/tools/file-tracker.js.map +0 -1
  892. package/dist/src/tools/file-tracker.test.js.map +0 -1
  893. package/dist/src/tools/file.js.map +0 -1
  894. package/dist/src/tools/file.test.js.map +0 -1
  895. package/dist/src/tools/grep.js.map +0 -1
  896. package/dist/src/tools/registry-bash-empty-command.test.js.map +0 -1
  897. package/dist/src/tools/registry-bash-footer.test.js.map +0 -1
  898. package/dist/src/tools/registry-ee-query.test.js.map +0 -1
  899. package/dist/src/tools/registry-session-repeat.test.js.map +0 -1
  900. package/dist/src/tools/registry.js.map +0 -1
  901. package/dist/src/tools/registry.test.js.map +0 -1
  902. package/dist/src/tools/schedule.js.map +0 -1
  903. package/dist/src/tools/schedule.test.js.map +0 -1
  904. package/dist/src/tools/todo-write-snapshot.js.map +0 -1
  905. package/dist/src/tools/todo-write-snapshot.test.js.map +0 -1
  906. package/dist/src/tools/vision-gate.js.map +0 -1
  907. package/dist/src/types/index.js.map +0 -1
  908. package/dist/src/ui/__tests__/picker-providers.test.js.map +0 -1
  909. package/dist/src/ui/agents-modal.js.map +0 -1
  910. package/dist/src/ui/app.js.map +0 -1
  911. package/dist/src/ui/cards/__tests__/product-status-card.test.js.map +0 -1
  912. package/dist/src/ui/cards/product-status-card.js.map +0 -1
  913. package/dist/src/ui/components/SuggestionOverlay.js.map +0 -1
  914. package/dist/src/ui/components/Toast.js.map +0 -1
  915. package/dist/src/ui/components/__tests__/council-leader-bubble.test.js.map +0 -1
  916. package/dist/src/ui/components/__tests__/council-message-bubble.test.js.map +0 -1
  917. package/dist/src/ui/components/__tests__/council-phase-timeline.test.js.map +0 -1
  918. package/dist/src/ui/components/__tests__/council-placeholder-bubble.test.js.map +0 -1
  919. package/dist/src/ui/components/__tests__/council-question-card.test.js.map +0 -1
  920. package/dist/src/ui/components/__tests__/council-synthesis-banner.test.js.map +0 -1
  921. package/dist/src/ui/components/__tests__/task-list-panel.test.js.map +0 -1
  922. package/dist/src/ui/components/__tests__/use-pair-quote-buffer.test.js.map +0 -1
  923. package/dist/src/ui/components/btw-overlay.js.map +0 -1
  924. package/dist/src/ui/components/bubble-layout.js.map +0 -1
  925. package/dist/src/ui/components/code-block-truncate.js.map +0 -1
  926. package/dist/src/ui/components/copy-flash-banner.js.map +0 -1
  927. package/dist/src/ui/components/council-info-card.js.map +0 -1
  928. package/dist/src/ui/components/council-leader-bubble.js.map +0 -1
  929. package/dist/src/ui/components/council-message-bubble.js.map +0 -1
  930. package/dist/src/ui/components/council-phase-timeline.js.map +0 -1
  931. package/dist/src/ui/components/council-placeholder-bubble.js.map +0 -1
  932. package/dist/src/ui/components/council-question-card.js.map +0 -1
  933. package/dist/src/ui/components/council-status-list.js.map +0 -1
  934. package/dist/src/ui/components/council-synthesis-banner.js.map +0 -1
  935. package/dist/src/ui/components/diff-view.js.map +0 -1
  936. package/dist/src/ui/components/halt-recovery-card.js.map +0 -1
  937. package/dist/src/ui/components/hero-logo.js.map +0 -1
  938. package/dist/src/ui/components/init-new-form-card.js.map +0 -1
  939. package/dist/src/ui/components/lsp-views.js.map +0 -1
  940. package/dist/src/ui/components/media-views.js.map +0 -1
  941. package/dist/src/ui/components/message-view.js.map +0 -1
  942. package/dist/src/ui/components/point-to-existing-form-card.js.map +0 -1
  943. package/dist/src/ui/components/prompt-box.js.map +0 -1
  944. package/dist/src/ui/components/role-palette.js.map +0 -1
  945. package/dist/src/ui/components/session-header.js.map +0 -1
  946. package/dist/src/ui/components/slash-inline-menu.js.map +0 -1
  947. package/dist/src/ui/components/structured-response-view.js.map +0 -1
  948. package/dist/src/ui/components/task-list-panel.js.map +0 -1
  949. package/dist/src/ui/components/tool-group.js.map +0 -1
  950. package/dist/src/ui/components/tool-result-views.js.map +0 -1
  951. package/dist/src/ui/components/use-pair-quote-buffer.js.map +0 -1
  952. package/dist/src/ui/constants.js.map +0 -1
  953. package/dist/src/ui/hooks/use-agent-editor.js.map +0 -1
  954. package/dist/src/ui/hooks/use-mcp-editor.js.map +0 -1
  955. package/dist/src/ui/hooks/use-model-picker.js.map +0 -1
  956. package/dist/src/ui/hooks/useTypeahead.js.map +0 -1
  957. package/dist/src/ui/markdown.js.map +0 -1
  958. package/dist/src/ui/mcp-modal-types.js.map +0 -1
  959. package/dist/src/ui/mcp-modal.js.map +0 -1
  960. package/dist/src/ui/modals/api-key-modal.js.map +0 -1
  961. package/dist/src/ui/modals/connect-modal.js.map +0 -1
  962. package/dist/src/ui/modals/model-picker-modal.js.map +0 -1
  963. package/dist/src/ui/modals/sandbox-picker-modal.js.map +0 -1
  964. package/dist/src/ui/modals/update-modal.js.map +0 -1
  965. package/dist/src/ui/modals/wallet-picker-modal.js.map +0 -1
  966. package/dist/src/ui/picker-providers.js.map +0 -1
  967. package/dist/src/ui/plan.js.map +0 -1
  968. package/dist/src/ui/schedule-modal.js.map +0 -1
  969. package/dist/src/ui/slash/__tests__/clear.test.js.map +0 -1
  970. package/dist/src/ui/slash/__tests__/compact.test.js.map +0 -1
  971. package/dist/src/ui/slash/__tests__/cost.test.js.map +0 -1
  972. package/dist/src/ui/slash/__tests__/discuss.test.js.map +0 -1
  973. package/dist/src/ui/slash/__tests__/execute.test.js.map +0 -1
  974. package/dist/src/ui/slash/__tests__/expand.test.js.map +0 -1
  975. package/dist/src/ui/slash/__tests__/ideal.test.js.map +0 -1
  976. package/dist/src/ui/slash/__tests__/menu-parity.test.js.map +0 -1
  977. package/dist/src/ui/slash/__tests__/optimize.test.js.map +0 -1
  978. package/dist/src/ui/slash/__tests__/pin.test.js.map +0 -1
  979. package/dist/src/ui/slash/__tests__/plan.test.js.map +0 -1
  980. package/dist/src/ui/slash/__tests__/status-render.test.js.map +0 -1
  981. package/dist/src/ui/slash/clear.js.map +0 -1
  982. package/dist/src/ui/slash/compact.js.map +0 -1
  983. package/dist/src/ui/slash/cost.js.map +0 -1
  984. package/dist/src/ui/slash/council-inspect.js.map +0 -1
  985. package/dist/src/ui/slash/council.js.map +0 -1
  986. package/dist/src/ui/slash/debug.js.map +0 -1
  987. package/dist/src/ui/slash/discuss.js.map +0 -1
  988. package/dist/src/ui/slash/ee.js.map +0 -1
  989. package/dist/src/ui/slash/execute.js.map +0 -1
  990. package/dist/src/ui/slash/expand.js.map +0 -1
  991. package/dist/src/ui/slash/export.js.map +0 -1
  992. package/dist/src/ui/slash/ideal.js.map +0 -1
  993. package/dist/src/ui/slash/menu-items.js.map +0 -1
  994. package/dist/src/ui/slash/optimize.js.map +0 -1
  995. package/dist/src/ui/slash/pin.js.map +0 -1
  996. package/dist/src/ui/slash/plan.js.map +0 -1
  997. package/dist/src/ui/slash/registry.js.map +0 -1
  998. package/dist/src/ui/slash/route.js.map +0 -1
  999. package/dist/src/ui/slash/route.test.js.map +0 -1
  1000. package/dist/src/ui/slash/status.js.map +0 -1
  1001. package/dist/src/ui/state/active-run.js.map +0 -1
  1002. package/dist/src/ui/status-bar/index.js.map +0 -1
  1003. package/dist/src/ui/status-bar/index.test.js.map +0 -1
  1004. package/dist/src/ui/status-bar/store.js.map +0 -1
  1005. package/dist/src/ui/status-bar/store.test.js.map +0 -1
  1006. package/dist/src/ui/status-bar/tier-badge.js.map +0 -1
  1007. package/dist/src/ui/status-bar/tier-badge.test.js.map +0 -1
  1008. package/dist/src/ui/status-bar/usd-meter.js.map +0 -1
  1009. package/dist/src/ui/status-bar/usd-meter.test.js.map +0 -1
  1010. package/dist/src/ui/syntax-highlight.js.map +0 -1
  1011. package/dist/src/ui/terminal-selection-text.js.map +0 -1
  1012. package/dist/src/ui/theme.js.map +0 -1
  1013. package/dist/src/ui/types.js.map +0 -1
  1014. package/dist/src/ui/utils/__tests__/format.test.js.map +0 -1
  1015. package/dist/src/ui/utils/__tests__/tools.test.js.map +0 -1
  1016. package/dist/src/ui/utils/color.js.map +0 -1
  1017. package/dist/src/ui/utils/format.js.map +0 -1
  1018. package/dist/src/ui/utils/modal.js.map +0 -1
  1019. package/dist/src/ui/utils/text.js.map +0 -1
  1020. package/dist/src/ui/utils/tools.js.map +0 -1
  1021. package/dist/src/usage/__tests__/product-ledger.test.js.map +0 -1
  1022. package/dist/src/usage/cost-log.js.map +0 -1
  1023. package/dist/src/usage/decision-log.js.map +0 -1
  1024. package/dist/src/usage/downgrade.js.map +0 -1
  1025. package/dist/src/usage/downgrade.test.js.map +0 -1
  1026. package/dist/src/usage/estimator.js.map +0 -1
  1027. package/dist/src/usage/estimator.test.js.map +0 -1
  1028. package/dist/src/usage/ledger.js.map +0 -1
  1029. package/dist/src/usage/ledger.test.js.map +0 -1
  1030. package/dist/src/usage/midstream.js.map +0 -1
  1031. package/dist/src/usage/midstream.test.js.map +0 -1
  1032. package/dist/src/usage/product-ledger.js.map +0 -1
  1033. package/dist/src/usage/thresholds.js.map +0 -1
  1034. package/dist/src/usage/thresholds.test.js.map +0 -1
  1035. package/dist/src/usage/types.js.map +0 -1
  1036. package/dist/src/utils/__tests__/auto-council-settings.test.js.map +0 -1
  1037. package/dist/src/utils/__tests__/ee-logger.test.js.map +0 -1
  1038. package/dist/src/utils/__tests__/file-lock.test.js.map +0 -1
  1039. package/dist/src/utils/__tests__/llm-deadline.test.js.map +0 -1
  1040. package/dist/src/utils/__tests__/rate-limit.test.js.map +0 -1
  1041. package/dist/src/utils/__tests__/settings-disabled-models.test.js.map +0 -1
  1042. package/dist/src/utils/__tests__/settings-web-research.test.js.map +0 -1
  1043. package/dist/src/utils/__tests__/slugify.test.js.map +0 -1
  1044. package/dist/src/utils/__tests__/visible-retry.test.js.map +0 -1
  1045. package/dist/src/utils/at-mentions.js.map +0 -1
  1046. package/dist/src/utils/clipboard-image.js.map +0 -1
  1047. package/dist/src/utils/ee-logger.js.map +0 -1
  1048. package/dist/src/utils/file-index.js.map +0 -1
  1049. package/dist/src/utils/file-lock.js.map +0 -1
  1050. package/dist/src/utils/git-root.js.map +0 -1
  1051. package/dist/src/utils/host-clipboard.js.map +0 -1
  1052. package/dist/src/utils/install-manager.js.map +0 -1
  1053. package/dist/src/utils/install-manager.test.js.map +0 -1
  1054. package/dist/src/utils/instructions.js.map +0 -1
  1055. package/dist/src/utils/instructions.test.js.map +0 -1
  1056. package/dist/src/utils/llm-deadline.js.map +0 -1
  1057. package/dist/src/utils/permission-mode.js.map +0 -1
  1058. package/dist/src/utils/permission-mode.test.js.map +0 -1
  1059. package/dist/src/utils/rate-limit.js.map +0 -1
  1060. package/dist/src/utils/redactor.js.map +0 -1
  1061. package/dist/src/utils/redactor.test.js.map +0 -1
  1062. package/dist/src/utils/settings.js.map +0 -1
  1063. package/dist/src/utils/settings.test.js.map +0 -1
  1064. package/dist/src/utils/shell.js.map +0 -1
  1065. package/dist/src/utils/shell.test.js.map +0 -1
  1066. package/dist/src/utils/side-question.js.map +0 -1
  1067. package/dist/src/utils/skills.js.map +0 -1
  1068. package/dist/src/utils/skills.test.js.map +0 -1
  1069. package/dist/src/utils/slugify.js.map +0 -1
  1070. package/dist/src/utils/subagent-display.js.map +0 -1
  1071. package/dist/src/utils/subagent-display.test.js.map +0 -1
  1072. package/dist/src/utils/subagents-settings.test.js.map +0 -1
  1073. package/dist/src/utils/telegram-audio-settings.test.js.map +0 -1
  1074. package/dist/src/utils/update-checker.js.map +0 -1
  1075. package/dist/src/utils/update-checker.test.js.map +0 -1
  1076. package/dist/src/utils/visible-retry.js.map +0 -1
  1077. package/dist/src/verify/__tests__/coverage-parsers.test.js.map +0 -1
  1078. package/dist/src/verify/__tests__/dotnet-recipe.test.js.map +0 -1
  1079. package/dist/src/verify/checkpoint.js.map +0 -1
  1080. package/dist/src/verify/checkpoint.test.js.map +0 -1
  1081. package/dist/src/verify/coverage-parsers.js.map +0 -1
  1082. package/dist/src/verify/entrypoint.js.map +0 -1
  1083. package/dist/src/verify/entrypoint.test.js.map +0 -1
  1084. package/dist/src/verify/environment.js.map +0 -1
  1085. package/dist/src/verify/environment.test.js.map +0 -1
  1086. package/dist/src/verify/evidence.js.map +0 -1
  1087. package/dist/src/verify/orchestrator.js.map +0 -1
  1088. package/dist/src/verify/orchestrator.test.js.map +0 -1
  1089. package/dist/src/verify/recipes.js.map +0 -1
  1090. package/dist/src/verify/retry.js.map +0 -1
  1091. package/dist/src/verify/runtime-prep.test.js.map +0 -1
  1092. package/src/__test-helpers__/catalog-fixtures.ts +0 -57
  1093. package/src/__test-stubs__/ee-server.ts +0 -173
  1094. package/src/__test-stubs__/vitest-setup.ts +0 -36
  1095. package/src/__tests__/council/bubble-layout.test.ts +0 -45
  1096. package/src/__tests__/council/code-block-truncate.test.ts +0 -50
  1097. package/src/__tests__/council/role-palette.test.ts +0 -66
  1098. package/src/__tests__/first-run-wizard.test.ts +0 -9
  1099. package/src/agent-harness/__tests__/cli-flags.spec.ts +0 -35
  1100. package/src/agent-harness/__tests__/driver.spec.ts +0 -154
  1101. package/src/agent-harness/__tests__/idle.spec.ts +0 -90
  1102. package/src/agent-harness/__tests__/mock-llm.spec.ts +0 -126
  1103. package/src/agent-harness/__tests__/mock-model.spec.ts +0 -195
  1104. package/src/agent-harness/__tests__/predicate.spec.ts +0 -33
  1105. package/src/agent-harness/__tests__/protocol.spec.ts +0 -62
  1106. package/src/agent-harness/__tests__/schema.spec.ts +0 -81
  1107. package/src/agent-harness/__tests__/selector.spec.ts +0 -82
  1108. package/src/agent-harness/__tests__/sidechannel.spec.ts +0 -40
  1109. package/src/agent-harness/__tests__/spec-helpers.spec.ts +0 -76
  1110. package/src/agent-harness/index.ts +0 -24
  1111. package/src/agent-harness/mock-model.ts +0 -445
  1112. package/src/agent-harness/test-spawn.ts +0 -221
  1113. package/src/billing/index.ts +0 -5
  1114. package/src/bun-sqlite.d.ts +0 -15
  1115. package/src/chat/__tests__/broadcast-bus.test.ts +0 -90
  1116. package/src/chat/__tests__/channel-manager.test.ts +0 -149
  1117. package/src/chat/__tests__/client.test.ts +0 -118
  1118. package/src/chat/__tests__/discord-integration.test.ts +0 -162
  1119. package/src/chat/__tests__/intent-prompt.test.ts +0 -92
  1120. package/src/chat/__tests__/verdict-resolver.test.ts +0 -336
  1121. package/src/chat/broadcast-bus.ts +0 -53
  1122. package/src/chat/channel-manager.ts +0 -146
  1123. package/src/chat/chat-keychain.ts +0 -137
  1124. package/src/chat/factory.ts +0 -37
  1125. package/src/chat/intent-prompt.ts +0 -72
  1126. package/src/chat/providers/discord/client.ts +0 -91
  1127. package/src/chat/types.ts +0 -42
  1128. package/src/chat/verdict-constants.ts +0 -26
  1129. package/src/chat/verdict-resolver.ts +0 -231
  1130. package/src/cli/__tests__/bw-vault.test.ts +0 -97
  1131. package/src/cli/__tests__/keys-bundle.test.ts +0 -46
  1132. package/src/cli/__tests__/share-cmd.test.ts +0 -197
  1133. package/src/cli/bw-vault.ts +0 -184
  1134. package/src/cli/config/__tests__/model-picker.test.ts +0 -59
  1135. package/src/cli/config/__tests__/provider-fetch.test.ts +0 -38
  1136. package/src/cli/config/index.ts +0 -112
  1137. package/src/cli/config/model-picker.ts +0 -193
  1138. package/src/cli/config/provider-fetch.ts +0 -75
  1139. package/src/cli/config/screen-council.ts +0 -245
  1140. package/src/cli/config/screen-models.ts +0 -104
  1141. package/src/cli/config/screen-providers.ts +0 -197
  1142. package/src/cli/config/tui.ts +0 -153
  1143. package/src/cli/cost-forensics.test.ts +0 -273
  1144. package/src/cli/cost-forensics.ts +0 -337
  1145. package/src/cli/keys-bundle.ts +0 -91
  1146. package/src/cli/keys.test.ts +0 -104
  1147. package/src/cli/keys.ts +0 -816
  1148. package/src/cli/pil-report.ts +0 -202
  1149. package/src/cli/reporter-cmd.ts +0 -154
  1150. package/src/cli/share-cmd.ts +0 -132
  1151. package/src/cli/usage-report.ts +0 -398
  1152. package/src/cloud/index.ts +0 -5
  1153. package/src/council/__tests__/accounting.test.ts +0 -72
  1154. package/src/council/__tests__/audit-replay.test.ts +0 -344
  1155. package/src/council/__tests__/clarifier-max-rounds.test.ts +0 -90
  1156. package/src/council/__tests__/clarifier-options.test.ts +0 -63
  1157. package/src/council/__tests__/clarifier-ready-gate.test.ts +0 -268
  1158. package/src/council/__tests__/cost-aware.test.ts +0 -60
  1159. package/src/council/__tests__/debate-planner-structured.test.ts +0 -236
  1160. package/src/council/__tests__/decisions-lock.test.ts +0 -404
  1161. package/src/council/__tests__/evaluator-metrics.test.ts +0 -513
  1162. package/src/council/__tests__/parse-outcome-fallback.test.ts +0 -125
  1163. package/src/council/__tests__/research-tools.test.ts +0 -239
  1164. package/src/council/__tests__/round-tools.test.ts +0 -334
  1165. package/src/council/__tests__/tool-trace.test.ts +0 -152
  1166. package/src/council/__tests__/types-contract.test.ts +0 -88
  1167. package/src/council/clarifier.ts +0 -507
  1168. package/src/council/context.ts +0 -249
  1169. package/src/council/debate-planner.ts +0 -303
  1170. package/src/council/debate.ts +0 -1179
  1171. package/src/council/decisions-lock.ts +0 -312
  1172. package/src/council/executor.ts +0 -27
  1173. package/src/council/index.ts +0 -956
  1174. package/src/council/leader.ts +0 -281
  1175. package/src/council/llm.ts +0 -939
  1176. package/src/council/phase-events.ts +0 -64
  1177. package/src/council/planner.ts +0 -303
  1178. package/src/council/preflight.ts +0 -86
  1179. package/src/council/prompts.ts +0 -698
  1180. package/src/council/types.ts +0 -304
  1181. package/src/daemon/scheduler.test.ts +0 -128
  1182. package/src/daemon/scheduler.ts +0 -152
  1183. package/src/ee/.gitkeep +0 -0
  1184. package/src/ee/__tests__/bb-design.test.ts +0 -223
  1185. package/src/ee/__tests__/export-transcripts.test.ts +0 -222
  1186. package/src/ee/__tests__/pil-context-bridge.test.ts +0 -59
  1187. package/src/ee/__tests__/pipeline.integration.test.ts +0 -193
  1188. package/src/ee/__tests__/recall-format.test.ts +0 -66
  1189. package/src/ee/__tests__/recall-ledger.test.ts +0 -55
  1190. package/src/ee/__tests__/render-sink-wiring.test.ts +0 -89
  1191. package/src/ee/auth.test.ts +0 -76
  1192. package/src/ee/auth.ts +0 -80
  1193. package/src/ee/bb-design.ts +0 -284
  1194. package/src/ee/bb-retrieval.ts +0 -467
  1195. package/src/ee/bridge.test.ts +0 -283
  1196. package/src/ee/bridge.ts +0 -443
  1197. package/src/ee/client-mode.ts +0 -161
  1198. package/src/ee/client.test.ts +0 -201
  1199. package/src/ee/client.ts +0 -683
  1200. package/src/ee/council-bridge.ts +0 -89
  1201. package/src/ee/embedding-cache.ts +0 -42
  1202. package/src/ee/export-transcripts.ts +0 -160
  1203. package/src/ee/extract-session.test.ts +0 -231
  1204. package/src/ee/extract-session.ts +0 -71
  1205. package/src/ee/health.ts +0 -83
  1206. package/src/ee/index.ts +0 -33
  1207. package/src/ee/intercept.test.ts +0 -197
  1208. package/src/ee/intercept.ts +0 -168
  1209. package/src/ee/judge.test.ts +0 -213
  1210. package/src/ee/judge.ts +0 -126
  1211. package/src/ee/mistake-detector.test.ts +0 -252
  1212. package/src/ee/mistake-detector.ts +0 -297
  1213. package/src/ee/offline-queue.test.ts +0 -302
  1214. package/src/ee/offline-queue.ts +0 -205
  1215. package/src/ee/phase-outcome.test.ts +0 -107
  1216. package/src/ee/phase-outcome.ts +0 -165
  1217. package/src/ee/phase-tracker.test.ts +0 -175
  1218. package/src/ee/phase-tracker.ts +0 -180
  1219. package/src/ee/posttool.test.ts +0 -81
  1220. package/src/ee/posttool.ts +0 -16
  1221. package/src/ee/prompt-stale.test.ts +0 -92
  1222. package/src/ee/prompt-stale.ts +0 -39
  1223. package/src/ee/recall-ledger.ts +0 -71
  1224. package/src/ee/recall-mirror.test.ts +0 -74
  1225. package/src/ee/render.test.ts +0 -74
  1226. package/src/ee/render.ts +0 -68
  1227. package/src/ee/scope.test.ts +0 -112
  1228. package/src/ee/scope.ts +0 -93
  1229. package/src/ee/search.ts +0 -259
  1230. package/src/ee/session-trajectory.test.ts +0 -139
  1231. package/src/ee/session-trajectory.ts +0 -226
  1232. package/src/ee/tenant.ts +0 -14
  1233. package/src/ee/touch.test.ts +0 -73
  1234. package/src/ee/transcript-emit.ts +0 -174
  1235. package/src/ee/types.ts +0 -432
  1236. package/src/flow/.gitkeep +0 -0
  1237. package/src/flow/__tests__/migration.test.ts +0 -133
  1238. package/src/flow/__tests__/parser.test.ts +0 -77
  1239. package/src/flow/__tests__/run-manager-product.test.ts +0 -59
  1240. package/src/flow/__tests__/run-manager.test.ts +0 -95
  1241. package/src/flow/__tests__/scaffold-checkpoint.test.ts +0 -113
  1242. package/src/flow/__tests__/scaffold.test.ts +0 -57
  1243. package/src/flow/__tests__/warning-persist.test.ts +0 -112
  1244. package/src/flow/artifact-io.ts +0 -41
  1245. package/src/flow/compaction/__tests__/compress.test.ts +0 -69
  1246. package/src/flow/compaction/__tests__/extract.test.ts +0 -74
  1247. package/src/flow/compaction/__tests__/preserve.test.ts +0 -69
  1248. package/src/flow/compaction/compress.ts +0 -67
  1249. package/src/flow/compaction/extract.ts +0 -60
  1250. package/src/flow/compaction/index.ts +0 -86
  1251. package/src/flow/compaction/preserve.ts +0 -48
  1252. package/src/flow/index.ts +0 -18
  1253. package/src/flow/migration.ts +0 -139
  1254. package/src/flow/parser.ts +0 -78
  1255. package/src/flow/run-manager.ts +0 -162
  1256. package/src/flow/scaffold-checkpoint.ts +0 -132
  1257. package/src/flow/scaffold.ts +0 -52
  1258. package/src/flow/warning-persist.ts +0 -84
  1259. package/src/generated/version.ts +0 -5
  1260. package/src/gsd/.gitkeep +0 -0
  1261. package/src/gsd/__tests__/complexity.test.ts +0 -0
  1262. package/src/gsd/__tests__/directives.test.ts +0 -88
  1263. package/src/gsd/__tests__/gray-areas.test.ts +0 -33
  1264. package/src/gsd/__tests__/types.test.ts +0 -91
  1265. package/src/gsd/complexity.ts +0 -124
  1266. package/src/gsd/directives.ts +0 -141
  1267. package/src/gsd/gray-areas.ts +0 -144
  1268. package/src/gsd/index.ts +0 -1
  1269. package/src/gsd/types.ts +0 -63
  1270. package/src/headless/__tests__/council-answers.test.ts +0 -300
  1271. package/src/headless/council-answers.ts +0 -152
  1272. package/src/headless/output.test.ts +0 -201
  1273. package/src/headless/output.ts +0 -312
  1274. package/src/hooks/config.ts +0 -41
  1275. package/src/hooks/index.ts +0 -569
  1276. package/src/hooks/types.ts +0 -263
  1277. package/src/index.ts +0 -1762
  1278. package/src/lsp/builtins.test.ts +0 -129
  1279. package/src/lsp/builtins.ts +0 -453
  1280. package/src/lsp/client.ts +0 -342
  1281. package/src/lsp/manager.test.ts +0 -198
  1282. package/src/lsp/manager.ts +0 -343
  1283. package/src/lsp/npm-cache.test.ts +0 -70
  1284. package/src/lsp/npm-cache.ts +0 -111
  1285. package/src/lsp/runtime.ts +0 -70
  1286. package/src/lsp/smoke.test.ts +0 -74
  1287. package/src/lsp/types.ts +0 -119
  1288. package/src/maintain/__tests__/codebase-intel.test.ts +0 -320
  1289. package/src/maintain/__tests__/gh-create-pr.test.ts +0 -195
  1290. package/src/maintain/__tests__/pr-builder.test.ts +0 -282
  1291. package/src/maintain/__tests__/repo-map.test.ts +0 -128
  1292. package/src/maintain/__tests__/task-runner.test.ts +0 -347
  1293. package/src/maintain/codebase-intel.ts +0 -595
  1294. package/src/maintain/gh-create-pr.ts +0 -148
  1295. package/src/maintain/index.ts +0 -14
  1296. package/src/maintain/pr-builder.ts +0 -373
  1297. package/src/maintain/repo-map.ts +0 -205
  1298. package/src/maintain/task-runner.ts +0 -481
  1299. package/src/maintain/types.ts +0 -49
  1300. package/src/mcp/__tests__/auto-setup.test.ts +0 -88
  1301. package/src/mcp/__tests__/cap-tool-result.test.ts +0 -65
  1302. package/src/mcp/__tests__/ee-tools.test.ts +0 -248
  1303. package/src/mcp/__tests__/forensics-tools.test.ts +0 -66
  1304. package/src/mcp/__tests__/harness-driver-action-tools.spec.ts +0 -116
  1305. package/src/mcp/__tests__/harness-driver-async-tools.spec.ts +0 -129
  1306. package/src/mcp/__tests__/harness-driver-read-tools.spec.ts +0 -140
  1307. package/src/mcp/__tests__/harness-driver-security.spec.ts +0 -69
  1308. package/src/mcp/__tests__/harness-driver.spec.ts +0 -21
  1309. package/src/mcp/__tests__/lazy-schema.spec.ts +0 -173
  1310. package/src/mcp/__tests__/lsp-tools.test.ts +0 -72
  1311. package/src/mcp/__tests__/mcp-keychain.test.ts +0 -46
  1312. package/src/mcp/__tests__/research-onboarding.test.ts +0 -163
  1313. package/src/mcp/__tests__/runtime-hydration.test.ts +0 -86
  1314. package/src/mcp/__tests__/runtime-output-cap.test.ts +0 -49
  1315. package/src/mcp/__tests__/runtime-sanitize.test.ts +0 -44
  1316. package/src/mcp/__tests__/self-verify-jobs.test.ts +0 -102
  1317. package/src/mcp/__tests__/smart-filter.test.ts +0 -139
  1318. package/src/mcp/__tests__/tools-server.smoke.test.ts +0 -41
  1319. package/src/mcp/auto-setup.ts +0 -99
  1320. package/src/mcp/cap-tool-result.ts +0 -68
  1321. package/src/mcp/catalog.ts +0 -155
  1322. package/src/mcp/ee-tools.ts +0 -204
  1323. package/src/mcp/forensics-tools.ts +0 -65
  1324. package/src/mcp/lsp-tools.ts +0 -78
  1325. package/src/mcp/mcp-keychain.ts +0 -85
  1326. package/src/mcp/oauth-callback.ts +0 -75
  1327. package/src/mcp/oauth-provider.ts +0 -128
  1328. package/src/mcp/opentui-spawn.ts +0 -64
  1329. package/src/mcp/parse-headers.test.ts +0 -54
  1330. package/src/mcp/parse-headers.ts +0 -35
  1331. package/src/mcp/research-onboarding.ts +0 -143
  1332. package/src/mcp/runtime.ts +0 -182
  1333. package/src/mcp/self-verify-jobs.ts +0 -137
  1334. package/src/mcp/smart-filter.ts +0 -138
  1335. package/src/mcp/smoke.test.ts +0 -170
  1336. package/src/mcp/tools-server.ts +0 -174
  1337. package/src/mcp/validate.ts +0 -48
  1338. package/src/models/__tests__/registry.test.ts +0 -95
  1339. package/src/models/catalog-client.ts +0 -234
  1340. package/src/models/catalog-gemini.test.ts +0 -52
  1341. package/src/models/catalog-url.test.ts +0 -27
  1342. package/src/models/catalog-validation.test.ts +0 -74
  1343. package/src/models/catalog.README.md +0 -136
  1344. package/src/models/catalog.json +0 -349
  1345. package/src/models/classify-tier.ts +0 -48
  1346. package/src/models/index.ts +0 -9
  1347. package/src/models/registry.ts +0 -87
  1348. package/src/ops/__tests__/doctor-council-mcp.test.ts +0 -161
  1349. package/src/ops/__tests__/doctor-ee-health.test.ts +0 -129
  1350. package/src/ops/bug-report.test.ts +0 -172
  1351. package/src/ops/bug-report.ts +0 -80
  1352. package/src/ops/doctor.test.ts +0 -108
  1353. package/src/ops/doctor.ts +0 -366
  1354. package/src/orchestrator/__tests__/agent-base-url-switch.test.ts +0 -87
  1355. package/src/orchestrator/__tests__/batch-turn-runner.test.ts +0 -186
  1356. package/src/orchestrator/__tests__/council-manager.test.ts +0 -171
  1357. package/src/orchestrator/__tests__/cross-turn-dedup.test.ts +0 -201
  1358. package/src/orchestrator/__tests__/current-call-id.test.ts +0 -160
  1359. package/src/orchestrator/__tests__/error-forensics.test.ts +0 -99
  1360. package/src/orchestrator/__tests__/flow-resume.test.ts +0 -71
  1361. package/src/orchestrator/__tests__/humanize-api-error.test.ts +0 -74
  1362. package/src/orchestrator/__tests__/message-processor.test.ts +0 -201
  1363. package/src/orchestrator/__tests__/message-write-ahead.test.ts +0 -170
  1364. package/src/orchestrator/__tests__/read-path-budget.test.ts +0 -170
  1365. package/src/orchestrator/__tests__/retry-classifier.test.ts +0 -131
  1366. package/src/orchestrator/__tests__/retry-stream.test.ts +0 -186
  1367. package/src/orchestrator/__tests__/route-feedback.test.ts +0 -55
  1368. package/src/orchestrator/__tests__/stream-runner.test.ts +0 -201
  1369. package/src/orchestrator/__tests__/sub-agent-model-tier.test.ts +0 -53
  1370. package/src/orchestrator/__tests__/usage-events-shape.test.ts +0 -80
  1371. package/src/orchestrator/__tests__/usage-normalizer-c1.test.ts +0 -172
  1372. package/src/orchestrator/__tests__/usage-shape-threading.test.ts +0 -111
  1373. package/src/orchestrator/__tests__/write-ahead.test.ts +0 -162
  1374. package/src/orchestrator/abort.test.ts +0 -37
  1375. package/src/orchestrator/abort.ts +0 -51
  1376. package/src/orchestrator/agent-options.ts +0 -167
  1377. package/src/orchestrator/agent.test.ts +0 -191
  1378. package/src/orchestrator/batch-turn-runner.ts +0 -425
  1379. package/src/orchestrator/batch-utils.ts +0 -340
  1380. package/src/orchestrator/cleanup.test.ts +0 -86
  1381. package/src/orchestrator/compaction.test.ts +0 -200
  1382. package/src/orchestrator/compaction.ts +0 -626
  1383. package/src/orchestrator/council-manager.ts +0 -572
  1384. package/src/orchestrator/cross-turn-dedup.ts +0 -208
  1385. package/src/orchestrator/delegations.test.ts +0 -145
  1386. package/src/orchestrator/delegations.ts +0 -370
  1387. package/src/orchestrator/error-utils.ts +0 -165
  1388. package/src/orchestrator/flow-resume.ts +0 -54
  1389. package/src/orchestrator/grounding-check.test.ts +0 -111
  1390. package/src/orchestrator/grounding-check.ts +0 -138
  1391. package/src/orchestrator/interrupted-turn.test.ts +0 -39
  1392. package/src/orchestrator/interrupted-turn.ts +0 -27
  1393. package/src/orchestrator/message-processor.ts +0 -3364
  1394. package/src/orchestrator/message-seq.test.ts +0 -29
  1395. package/src/orchestrator/message-seq.ts +0 -19
  1396. package/src/orchestrator/orchestrator.ts +0 -2752
  1397. package/src/orchestrator/pending-calls.test.ts +0 -226
  1398. package/src/orchestrator/pending-calls.ts +0 -240
  1399. package/src/orchestrator/prompts.ts +0 -579
  1400. package/src/orchestrator/provider-options-shape.spec.ts +0 -67
  1401. package/src/orchestrator/provider-options-shape.ts +0 -70
  1402. package/src/orchestrator/read-path-budget.ts +0 -205
  1403. package/src/orchestrator/reasoning.test.ts +0 -114
  1404. package/src/orchestrator/reasoning.ts +0 -116
  1405. package/src/orchestrator/repair-tool-call.ts +0 -54
  1406. package/src/orchestrator/repetition-detector.test.ts +0 -127
  1407. package/src/orchestrator/repetition-detector.ts +0 -140
  1408. package/src/orchestrator/retry-classifier.ts +0 -140
  1409. package/src/orchestrator/retry-stream.ts +0 -159
  1410. package/src/orchestrator/sandbox.test.ts +0 -117
  1411. package/src/orchestrator/scope-ceiling.test.ts +0 -215
  1412. package/src/orchestrator/scope-ceiling.ts +0 -234
  1413. package/src/orchestrator/scope-reminder.test.ts +0 -232
  1414. package/src/orchestrator/scope-reminder.ts +0 -230
  1415. package/src/orchestrator/stall-rescue.test.ts +0 -100
  1416. package/src/orchestrator/stall-rescue.ts +0 -95
  1417. package/src/orchestrator/stall-watchdog.test.ts +0 -83
  1418. package/src/orchestrator/stall-watchdog.ts +0 -87
  1419. package/src/orchestrator/stream-runner.ts +0 -939
  1420. package/src/orchestrator/sub-agent-cap.test.ts +0 -227
  1421. package/src/orchestrator/sub-agent-cap.ts +0 -240
  1422. package/src/orchestrator/sub-agent-model-tier.ts +0 -58
  1423. package/src/orchestrator/subagent-compactor.spec.ts +0 -332
  1424. package/src/orchestrator/subagent-compactor.ts +0 -456
  1425. package/src/orchestrator/text-tool-call-detector.test.ts +0 -99
  1426. package/src/orchestrator/text-tool-call-detector.ts +0 -200
  1427. package/src/orchestrator/token-counter.test.ts +0 -69
  1428. package/src/orchestrator/token-counter.ts +0 -81
  1429. package/src/orchestrator/tool-args-hash.test.ts +0 -121
  1430. package/src/orchestrator/tool-args-hash.ts +0 -221
  1431. package/src/orchestrator/tool-args-repair.test.ts +0 -156
  1432. package/src/orchestrator/tool-args-repair.ts +0 -227
  1433. package/src/orchestrator/tool-loop-cap.test.ts +0 -193
  1434. package/src/orchestrator/tool-loop-cap.ts +0 -174
  1435. package/src/orchestrator/tool-repetition-detector.test.ts +0 -119
  1436. package/src/orchestrator/tool-repetition-detector.ts +0 -0
  1437. package/src/orchestrator/tool-utils.ts +0 -214
  1438. package/src/orchestrator/turn-runner-deps.ts +0 -85
  1439. package/src/pil/__tests__/budget.test.ts +0 -39
  1440. package/src/pil/__tests__/clarity-gate.test.ts +0 -299
  1441. package/src/pil/__tests__/config.test.ts +0 -78
  1442. package/src/pil/__tests__/discovery-cache.test.ts +0 -45
  1443. package/src/pil/__tests__/discovery-types.test.ts +0 -68
  1444. package/src/pil/__tests__/discovery.test.ts +0 -141
  1445. package/src/pil/__tests__/dual-run.test.ts +0 -53
  1446. package/src/pil/__tests__/layer1-intent-trace.test.ts +0 -142
  1447. package/src/pil/__tests__/layer1-intent.test.ts +0 -365
  1448. package/src/pil/__tests__/layer15-context-scan.test.ts +0 -76
  1449. package/src/pil/__tests__/layer16-clarity.test.ts +0 -184
  1450. package/src/pil/__tests__/layer17-feasibility.test.ts +0 -42
  1451. package/src/pil/__tests__/layer18-acceptance.test.ts +0 -116
  1452. package/src/pil/__tests__/layer2-personality.test.ts +0 -63
  1453. package/src/pil/__tests__/layer3-ee-injection.test.ts +0 -189
  1454. package/src/pil/__tests__/layer3-injected-chunk.test.ts +0 -122
  1455. package/src/pil/__tests__/layer4-gsd.test.ts +0 -109
  1456. package/src/pil/__tests__/layer5-context.test.ts +0 -157
  1457. package/src/pil/__tests__/layer6-output.test.ts +0 -362
  1458. package/src/pil/__tests__/llm-classify.test.ts +0 -140
  1459. package/src/pil/__tests__/native-capabilities-workbook.test.ts +0 -45
  1460. package/src/pil/__tests__/ollama-classify.test.ts +0 -81
  1461. package/src/pil/__tests__/orchestrator-integration.test.ts +0 -107
  1462. package/src/pil/__tests__/pipeline.test.ts +0 -191
  1463. package/src/pil/__tests__/renderer-coverage.test.ts +0 -46
  1464. package/src/pil/__tests__/response-tools.test.ts +0 -239
  1465. package/src/pil/__tests__/schema.test.ts +0 -233
  1466. package/src/pil/__tests__/scoreComplexity.test.ts +0 -134
  1467. package/src/pil/__tests__/scoreSufficiency.test.ts +0 -104
  1468. package/src/pil/__tests__/store.test.ts +0 -49
  1469. package/src/pil/__tests__/task-tier-map.test.ts +0 -41
  1470. package/src/pil/agent-operating-contract.test.ts +0 -84
  1471. package/src/pil/agent-operating-contract.ts +0 -70
  1472. package/src/pil/budget-log.ts +0 -86
  1473. package/src/pil/budget.ts +0 -18
  1474. package/src/pil/cheap-model-playbook.test.ts +0 -191
  1475. package/src/pil/cheap-model-playbook.ts +0 -153
  1476. package/src/pil/cheap-model-workbooks.test.ts +0 -154
  1477. package/src/pil/cheap-model-workbooks.ts +0 -109
  1478. package/src/pil/clarity-gate.ts +0 -188
  1479. package/src/pil/config.ts +0 -25
  1480. package/src/pil/discovery-cache.ts +0 -20
  1481. package/src/pil/discovery-types.ts +0 -97
  1482. package/src/pil/discovery.ts +0 -397
  1483. package/src/pil/index.ts +0 -24
  1484. package/src/pil/layer1-intent.test.ts +0 -520
  1485. package/src/pil/layer1-intent.ts +0 -1236
  1486. package/src/pil/layer15-context-scan.ts +0 -159
  1487. package/src/pil/layer16-clarity.test.ts +0 -35
  1488. package/src/pil/layer16-clarity.ts +0 -417
  1489. package/src/pil/layer17-feasibility.ts +0 -40
  1490. package/src/pil/layer18-acceptance.ts +0 -98
  1491. package/src/pil/layer1_5-complexity-size.test.ts +0 -279
  1492. package/src/pil/layer1_5-complexity-size.ts +0 -175
  1493. package/src/pil/layer2-personality.ts +0 -46
  1494. package/src/pil/layer3-ee-injection.ts +0 -406
  1495. package/src/pil/layer4-gsd.ts +0 -124
  1496. package/src/pil/layer5-context.ts +0 -171
  1497. package/src/pil/layer6-output.ts +0 -364
  1498. package/src/pil/llm-classify.ts +0 -199
  1499. package/src/pil/native-capabilities-workbook.ts +0 -124
  1500. package/src/pil/ollama-classify.ts +0 -49
  1501. package/src/pil/pipeline.ts +0 -313
  1502. package/src/pil/response-tools.ts +0 -187
  1503. package/src/pil/schema.ts +0 -111
  1504. package/src/pil/session-state.test.ts +0 -88
  1505. package/src/pil/session-state.ts +0 -157
  1506. package/src/pil/store.ts +0 -29
  1507. package/src/pil/task-tier-map.ts +0 -97
  1508. package/src/pil/timeout.ts +0 -10
  1509. package/src/pil/types.ts +0 -168
  1510. package/src/product-loop/__tests__/artifact-io.test.ts +0 -97
  1511. package/src/product-loop/__tests__/assumption-ledger.test.ts +0 -292
  1512. package/src/product-loop/__tests__/backlog-builder.test.ts +0 -200
  1513. package/src/product-loop/__tests__/backlog-store.test.ts +0 -119
  1514. package/src/product-loop/__tests__/cb2-retry-bonus.test.ts +0 -182
  1515. package/src/product-loop/__tests__/circuit-breakers-coverage.test.ts +0 -82
  1516. package/src/product-loop/__tests__/circuit-breakers.test.ts +0 -90
  1517. package/src/product-loop/__tests__/complexity-routing.spec.ts +0 -315
  1518. package/src/product-loop/__tests__/context-policy.test.ts +0 -280
  1519. package/src/product-loop/__tests__/cost-preview.test.ts +0 -118
  1520. package/src/product-loop/__tests__/cost-scoper.test.ts +0 -76
  1521. package/src/product-loop/__tests__/cross-run-memory.test.ts +0 -195
  1522. package/src/product-loop/__tests__/design-output.spec.ts +0 -39
  1523. package/src/product-loop/__tests__/discover.test.ts +0 -98
  1524. package/src/product-loop/__tests__/discovery-context-format.test.ts +0 -111
  1525. package/src/product-loop/__tests__/discovery-council-runner.test.ts +0 -13
  1526. package/src/product-loop/__tests__/discovery-detection.test.ts +0 -180
  1527. package/src/product-loop/__tests__/discovery-ecosystem.test.ts +0 -246
  1528. package/src/product-loop/__tests__/discovery-integration.test.ts +0 -133
  1529. package/src/product-loop/__tests__/discovery-interview.test.ts +0 -305
  1530. package/src/product-loop/__tests__/discovery-migrations.test.ts +0 -75
  1531. package/src/product-loop/__tests__/discovery-persistence.test.ts +0 -171
  1532. package/src/product-loop/__tests__/discovery-prompt-parser.test.ts +0 -77
  1533. package/src/product-loop/__tests__/discovery-prompt-specificity.test.ts +0 -65
  1534. package/src/product-loop/__tests__/discovery-recommender-ecosystem.test.ts +0 -192
  1535. package/src/product-loop/__tests__/discovery-recommender.test.ts +0 -382
  1536. package/src/product-loop/__tests__/discovery-schema.test.ts +0 -102
  1537. package/src/product-loop/__tests__/done-gate-coverage.test.ts +0 -151
  1538. package/src/product-loop/__tests__/done-gate.test.ts +0 -140
  1539. package/src/product-loop/__tests__/ee-extract-wiring.test.ts +0 -222
  1540. package/src/product-loop/__tests__/extract-to-ee.test.ts +0 -205
  1541. package/src/product-loop/__tests__/feedback-routing.test.ts +0 -93
  1542. package/src/product-loop/__tests__/gather-selectable-alts.test.ts +0 -119
  1543. package/src/product-loop/__tests__/hot-path.spec.ts +0 -177
  1544. package/src/product-loop/__tests__/integration.test.ts +0 -350
  1545. package/src/product-loop/__tests__/loop-driver-audit.test.ts +0 -327
  1546. package/src/product-loop/__tests__/loop-driver.test.ts +0 -253
  1547. package/src/product-loop/__tests__/maintenance-task-synthesis.test.ts +0 -78
  1548. package/src/product-loop/__tests__/phase-a1-a3-sprint-runner.test.ts +0 -315
  1549. package/src/product-loop/__tests__/phase-a2-backlog-build.test.ts +0 -189
  1550. package/src/product-loop/__tests__/phase-budget.test.ts +0 -172
  1551. package/src/product-loop/__tests__/phase-orchestrator-integration.test.ts +0 -143
  1552. package/src/product-loop/__tests__/phase-plan.test.ts +0 -241
  1553. package/src/product-loop/__tests__/phase-rituals.test.ts +0 -205
  1554. package/src/product-loop/__tests__/phase-runner.test.ts +0 -454
  1555. package/src/product-loop/__tests__/phase-tracker-bridge.test.ts +0 -85
  1556. package/src/product-loop/__tests__/pick-backend-stack.test.ts +0 -117
  1557. package/src/product-loop/__tests__/product-identity.test.ts +0 -47
  1558. package/src/product-loop/__tests__/progress-snapshot.test.ts +0 -180
  1559. package/src/product-loop/__tests__/reality-anchor.test.ts +0 -58
  1560. package/src/product-loop/__tests__/repo-audit.test.ts +0 -103
  1561. package/src/product-loop/__tests__/repo-brief.test.ts +0 -155
  1562. package/src/product-loop/__tests__/role-memory.test.ts +0 -70
  1563. package/src/product-loop/__tests__/role-registry.test.ts +0 -235
  1564. package/src/product-loop/__tests__/role-routing-ee.test.ts +0 -90
  1565. package/src/product-loop/__tests__/route-decision-emit.test.ts +0 -258
  1566. package/src/product-loop/__tests__/seed-questions.test.ts +0 -33
  1567. package/src/product-loop/__tests__/ship-polish.test.ts +0 -109
  1568. package/src/product-loop/__tests__/sprint-planner.test.ts +0 -166
  1569. package/src/product-loop/__tests__/sprint-runner-backlog.test.ts +0 -248
  1570. package/src/product-loop/__tests__/sprint-runner-emit.test.ts +0 -324
  1571. package/src/product-loop/__tests__/sprint-runner-phase-chunks.test.ts +0 -220
  1572. package/src/product-loop/__tests__/sprint-runner.test.ts +0 -501
  1573. package/src/product-loop/__tests__/sprint-self-verify.test.ts +0 -77
  1574. package/src/product-loop/__tests__/sprint-store.test.ts +0 -98
  1575. package/src/product-loop/__tests__/stakeholder-acl.test.ts +0 -94
  1576. package/src/product-loop/__tests__/state-md-ee-injections.test.ts +0 -229
  1577. package/src/product-loop/__tests__/sufficiency-routing.spec.ts +0 -183
  1578. package/src/product-loop/__tests__/typed-artifacts.test.ts +0 -259
  1579. package/src/product-loop/__tests__/types.test.ts +0 -103
  1580. package/src/product-loop/__tests__/verify-failure-threshold.test.ts +0 -178
  1581. package/src/product-loop/__tests__/verify-failure-tracking.test.ts +0 -154
  1582. package/src/product-loop/__tests__/verify-result.test.ts +0 -60
  1583. package/src/product-loop/artifact-io.ts +0 -239
  1584. package/src/product-loop/assumption-ledger.ts +0 -270
  1585. package/src/product-loop/backlog-builder.ts +0 -253
  1586. package/src/product-loop/backlog-store.ts +0 -62
  1587. package/src/product-loop/circuit-breakers.ts +0 -76
  1588. package/src/product-loop/context-policy.ts +0 -180
  1589. package/src/product-loop/cost-preview.ts +0 -139
  1590. package/src/product-loop/cost-scoper.ts +0 -49
  1591. package/src/product-loop/cross-run-memory.ts +0 -450
  1592. package/src/product-loop/design-output.ts +0 -24
  1593. package/src/product-loop/discover.ts +0 -159
  1594. package/src/product-loop/discovery-context-format.ts +0 -56
  1595. package/src/product-loop/discovery-council-runner.ts +0 -78
  1596. package/src/product-loop/discovery-detection.ts +0 -161
  1597. package/src/product-loop/discovery-ecosystem.ts +0 -239
  1598. package/src/product-loop/discovery-interview.ts +0 -288
  1599. package/src/product-loop/discovery-migrations.ts +0 -40
  1600. package/src/product-loop/discovery-persistence.ts +0 -219
  1601. package/src/product-loop/discovery-prompt-parser.ts +0 -80
  1602. package/src/product-loop/discovery-recommender.ts +0 -514
  1603. package/src/product-loop/discovery-schema.ts +0 -143
  1604. package/src/product-loop/done-gate.ts +0 -224
  1605. package/src/product-loop/feedback-routing.ts +0 -82
  1606. package/src/product-loop/gather.ts +0 -386
  1607. package/src/product-loop/index.ts +0 -1855
  1608. package/src/product-loop/loop-driver.ts +0 -900
  1609. package/src/product-loop/phase-budget.ts +0 -182
  1610. package/src/product-loop/phase-plan.ts +0 -158
  1611. package/src/product-loop/phase-rituals.ts +0 -158
  1612. package/src/product-loop/phase-runner.ts +0 -455
  1613. package/src/product-loop/phase-tracker-bridge.ts +0 -60
  1614. package/src/product-loop/product-identity.ts +0 -11
  1615. package/src/product-loop/progress-snapshot.ts +0 -216
  1616. package/src/product-loop/reality-anchor.ts +0 -45
  1617. package/src/product-loop/repo-audit.ts +0 -314
  1618. package/src/product-loop/repo-brief.ts +0 -235
  1619. package/src/product-loop/role-memory.ts +0 -72
  1620. package/src/product-loop/role-registry.ts +0 -175
  1621. package/src/product-loop/seed-questions.ts +0 -51
  1622. package/src/product-loop/ship-polish.ts +0 -164
  1623. package/src/product-loop/sprint-planner.ts +0 -241
  1624. package/src/product-loop/sprint-runner.ts +0 -801
  1625. package/src/product-loop/sprint-self-verify.ts +0 -189
  1626. package/src/product-loop/sprint-store.ts +0 -96
  1627. package/src/product-loop/stakeholder-acl.ts +0 -82
  1628. package/src/product-loop/typed-artifacts.ts +0 -332
  1629. package/src/product-loop/types.ts +0 -570
  1630. package/src/product-loop/verify-failure-tracking.ts +0 -225
  1631. package/src/product-loop/verify-result.ts +0 -39
  1632. package/src/providers/.gitkeep +0 -0
  1633. package/src/providers/__test-utils__/load-fixture.ts +0 -36
  1634. package/src/providers/__tests__/adapter-oauth-wiring.test.ts +0 -147
  1635. package/src/providers/__tests__/capabilities-cosmetic.test.ts +0 -119
  1636. package/src/providers/__tests__/capabilities-flags.test.ts +0 -166
  1637. package/src/providers/__tests__/capabilities-provider-options.test.ts +0 -232
  1638. package/src/providers/__tests__/capabilities-sanitize.test.ts +0 -66
  1639. package/src/providers/__tests__/capabilities.test.ts +0 -44
  1640. package/src/providers/__tests__/provider-coverage.test.ts +0 -48
  1641. package/src/providers/__tests__/reasoning-roundtrip.test.ts +0 -150
  1642. package/src/providers/__tests__/runtime-integration.test.ts +0 -106
  1643. package/src/providers/__tests__/runtime.test.ts +0 -94
  1644. package/src/providers/__tests__/siliconflow-sse-repair.test.ts +0 -300
  1645. package/src/providers/__tests__/strategies-registry.test.ts +0 -55
  1646. package/src/providers/__tests__/strategies-resolve.test.ts +0 -137
  1647. package/src/providers/__tests__/wire-debug.test.ts +0 -42
  1648. package/src/providers/adapter.test.ts +0 -21
  1649. package/src/providers/adapter.ts +0 -156
  1650. package/src/providers/anthropic.ts +0 -174
  1651. package/src/providers/auth/__tests__/browser-flow.test.ts +0 -230
  1652. package/src/providers/auth/__tests__/device-flow.test.ts +0 -263
  1653. package/src/providers/auth/__tests__/gemini-oauth.test.ts +0 -387
  1654. package/src/providers/auth/__tests__/grok-oauth.test.ts +0 -283
  1655. package/src/providers/auth/__tests__/openai-oauth.test.ts +0 -378
  1656. package/src/providers/auth/__tests__/token-store.test.ts +0 -152
  1657. package/src/providers/auth/browser-flow.ts +0 -140
  1658. package/src/providers/auth/device-flow.ts +0 -221
  1659. package/src/providers/auth/gemini-oauth.ts +0 -351
  1660. package/src/providers/auth/grok-oauth.ts +0 -406
  1661. package/src/providers/auth/openai-oauth.ts +0 -455
  1662. package/src/providers/auth/registry.ts +0 -138
  1663. package/src/providers/auth/token-store.ts +0 -154
  1664. package/src/providers/auth/types.ts +0 -111
  1665. package/src/providers/capabilities.ts +0 -355
  1666. package/src/providers/endpoints.ts +0 -68
  1667. package/src/providers/errors.test.ts +0 -76
  1668. package/src/providers/errors.ts +0 -46
  1669. package/src/providers/gemini.test.ts +0 -46
  1670. package/src/providers/gemini.ts +0 -42
  1671. package/src/providers/index.ts +0 -28
  1672. package/src/providers/keychain.test.ts +0 -100
  1673. package/src/providers/keychain.ts +0 -278
  1674. package/src/providers/mcp-vision-bridge.test.ts +0 -513
  1675. package/src/providers/mcp-vision-bridge.ts +0 -1020
  1676. package/src/providers/ollama.test.ts +0 -46
  1677. package/src/providers/ollama.ts +0 -36
  1678. package/src/providers/openai-compatible.test.ts +0 -63
  1679. package/src/providers/openai-compatible.ts +0 -62
  1680. package/src/providers/openai.test.ts +0 -65
  1681. package/src/providers/openai.ts +0 -56
  1682. package/src/providers/patch-zod-schema.ts +0 -126
  1683. package/src/providers/pricing.test.ts +0 -97
  1684. package/src/providers/pricing.ts +0 -128
  1685. package/src/providers/prompt-cache-key.spec.ts +0 -28
  1686. package/src/providers/runtime-mock.spec.ts +0 -86
  1687. package/src/providers/runtime.ts +0 -311
  1688. package/src/providers/siliconflow-sse-repair.ts +0 -201
  1689. package/src/providers/strategies/anthropic.strategy.ts +0 -25
  1690. package/src/providers/strategies/base.strategy.ts +0 -76
  1691. package/src/providers/strategies/deepseek.strategy.ts +0 -55
  1692. package/src/providers/strategies/google.strategy.ts +0 -28
  1693. package/src/providers/strategies/ollama.strategy.ts +0 -22
  1694. package/src/providers/strategies/openai.strategy.ts +0 -55
  1695. package/src/providers/strategies/registry.ts +0 -43
  1696. package/src/providers/strategies/siliconflow.strategy.ts +0 -28
  1697. package/src/providers/strategies/xai.strategy.ts +0 -33
  1698. package/src/providers/stream-loop.ts +0 -83
  1699. package/src/providers/types.ts +0 -145
  1700. package/src/providers/vision-proxy.test.ts +0 -252
  1701. package/src/providers/vision-proxy.ts +0 -317
  1702. package/src/providers/wire-debug.ts +0 -163
  1703. package/src/reporter/__tests__/acl-check.test.ts +0 -71
  1704. package/src/reporter/__tests__/auto-fire.test.ts +0 -161
  1705. package/src/reporter/__tests__/budget.test.ts +0 -74
  1706. package/src/reporter/__tests__/handlers.test.ts +0 -192
  1707. package/src/reporter/__tests__/query-router.test.ts +0 -115
  1708. package/src/reporter/acl-check.ts +0 -54
  1709. package/src/reporter/auto-fire.ts +0 -168
  1710. package/src/reporter/budget.ts +0 -59
  1711. package/src/reporter/handlers.ts +0 -212
  1712. package/src/reporter/index.ts +0 -210
  1713. package/src/reporter/query-router.ts +0 -51
  1714. package/src/router/.gitkeep +0 -0
  1715. package/src/router/__tests__/step-router.test.ts +0 -150
  1716. package/src/router/classifier/grammars.ts +0 -17
  1717. package/src/router/classifier/index.test.ts +0 -33
  1718. package/src/router/classifier/index.ts +0 -21
  1719. package/src/router/classifier/regex.test.ts +0 -51
  1720. package/src/router/classifier/regex.ts +0 -160
  1721. package/src/router/classifier/tree-sitter.test.ts +0 -26
  1722. package/src/router/classifier/tree-sitter.ts +0 -87
  1723. package/src/router/cold.test.ts +0 -62
  1724. package/src/router/cold.ts +0 -27
  1725. package/src/router/decide.test.ts +0 -209
  1726. package/src/router/decide.ts +0 -509
  1727. package/src/router/health.test.ts +0 -59
  1728. package/src/router/health.ts +0 -49
  1729. package/src/router/provider-sentinel.test.ts +0 -22
  1730. package/src/router/provider-sentinel.ts +0 -20
  1731. package/src/router/role-override.test.ts +0 -37
  1732. package/src/router/step-router.ts +0 -194
  1733. package/src/router/store.ts +0 -47
  1734. package/src/router/types.ts +0 -20
  1735. package/src/router/warm.test.ts +0 -234
  1736. package/src/router/warm.ts +0 -93
  1737. package/src/scaffold/__tests__/continuation-prompt.test.ts +0 -93
  1738. package/src/scaffold/__tests__/continue-as-council.spec.ts +0 -122
  1739. package/src/scaffold/__tests__/dotnet-assembly-name.test.ts +0 -28
  1740. package/src/scaffold/__tests__/fe-scaffold-contents.test.ts +0 -127
  1741. package/src/scaffold/__tests__/init-new.smoke.spec.ts +0 -99
  1742. package/src/scaffold/__tests__/init-new.spec.ts +0 -450
  1743. package/src/scaffold/__tests__/install-bb-templates.spec.ts +0 -86
  1744. package/src/scaffold/__tests__/point-to-existing.spec.ts +0 -114
  1745. package/src/scaffold/bb-ecosystem-apply.ts +0 -457
  1746. package/src/scaffold/bb-quality-gate.ts +0 -287
  1747. package/src/scaffold/continuation-prompt.ts +0 -80
  1748. package/src/scaffold/continue-as-council.ts +0 -99
  1749. package/src/scaffold/init-new.ts +0 -1691
  1750. package/src/scaffold/point-to-existing.ts +0 -83
  1751. package/src/scaffold/resume-from-gate-failures.ts +0 -167
  1752. package/src/self-qa/__tests__/agentic-context.test.ts +0 -104
  1753. package/src/self-qa/__tests__/agentic-loop.test.ts +0 -70
  1754. package/src/self-qa/__tests__/delta-encoder.test.ts +0 -113
  1755. package/src/self-qa/__tests__/judge.test.ts +0 -152
  1756. package/src/self-qa/__tests__/scenario-planner.test.ts +0 -87
  1757. package/src/self-qa/__tests__/spec-emitter.test.ts +0 -67
  1758. package/src/self-qa/agentic-context.ts +0 -211
  1759. package/src/self-qa/agentic-loop.ts +0 -590
  1760. package/src/self-qa/delta-encoder.ts +0 -149
  1761. package/src/self-qa/index.ts +0 -117
  1762. package/src/self-qa/judge.ts +0 -248
  1763. package/src/self-qa/orchestrator.ts +0 -269
  1764. package/src/self-qa/scenario-planner.ts +0 -289
  1765. package/src/self-qa/spec-emitter.ts +0 -152
  1766. package/src/self-qa/types.ts +0 -98
  1767. package/src/storage/__tests__/migrations.test.ts +0 -395
  1768. package/src/storage/__tests__/sweep-stale-pending.test.ts +0 -112
  1769. package/src/storage/__tests__/ui-interaction-log.test.ts +0 -136
  1770. package/src/storage/atomic-io.test.ts +0 -92
  1771. package/src/storage/atomic-io.ts +0 -160
  1772. package/src/storage/config.test.ts +0 -33
  1773. package/src/storage/config.ts +0 -53
  1774. package/src/storage/db.ts +0 -184
  1775. package/src/storage/index.ts +0 -26
  1776. package/src/storage/interaction-log.ts +0 -126
  1777. package/src/storage/migrations.ts +0 -205
  1778. package/src/storage/session-dir.ts +0 -37
  1779. package/src/storage/sessions.ts +0 -225
  1780. package/src/storage/tool-results.ts +0 -56
  1781. package/src/storage/transcript-response-entry.test.ts +0 -115
  1782. package/src/storage/transcript-view.ts +0 -45
  1783. package/src/storage/transcript.test.ts +0 -24
  1784. package/src/storage/transcript.ts +0 -637
  1785. package/src/storage/ui-interaction-log.ts +0 -170
  1786. package/src/storage/usage-cap.test.ts +0 -59
  1787. package/src/storage/usage-cap.ts +0 -81
  1788. package/src/storage/usage.ts +0 -117
  1789. package/src/storage/workspaces.ts +0 -84
  1790. package/src/tools/__tests__/vision-gate.test.ts +0 -66
  1791. package/src/tools/bash-output-cache.test.ts +0 -113
  1792. package/src/tools/bash-output-cache.ts +0 -156
  1793. package/src/tools/bash-output-integration.test.ts +0 -33
  1794. package/src/tools/bash.test.ts +0 -447
  1795. package/src/tools/bash.ts +0 -769
  1796. package/src/tools/computer.test.ts +0 -187
  1797. package/src/tools/computer.ts +0 -632
  1798. package/src/tools/file-tracker.test.ts +0 -101
  1799. package/src/tools/file-tracker.ts +0 -70
  1800. package/src/tools/file.test.ts +0 -151
  1801. package/src/tools/file.ts +0 -203
  1802. package/src/tools/grep.ts +0 -187
  1803. package/src/tools/registry-bash-empty-command.test.ts +0 -64
  1804. package/src/tools/registry-bash-footer.test.ts +0 -95
  1805. package/src/tools/registry-ee-query.test.ts +0 -57
  1806. package/src/tools/registry-session-repeat.test.ts +0 -105
  1807. package/src/tools/registry.test.ts +0 -38
  1808. package/src/tools/registry.ts +0 -704
  1809. package/src/tools/schedule.test.ts +0 -143
  1810. package/src/tools/schedule.ts +0 -610
  1811. package/src/tools/todo-write-snapshot.test.ts +0 -53
  1812. package/src/tools/todo-write-snapshot.ts +0 -63
  1813. package/src/tools/vision-gate.ts +0 -74
  1814. package/src/types/index.ts +0 -550
  1815. package/src/ui/__tests__/picker-providers.test.ts +0 -37
  1816. package/src/ui/agents-modal.tsx +0 -293
  1817. package/src/ui/app.tsx +0 -7084
  1818. package/src/ui/cards/__tests__/product-status-card.test.ts +0 -30
  1819. package/src/ui/cards/product-status-card.tsx +0 -117
  1820. package/src/ui/components/SuggestionOverlay.tsx +0 -38
  1821. package/src/ui/components/Toast.tsx +0 -100
  1822. package/src/ui/components/__tests__/council-leader-bubble.test.ts +0 -16
  1823. package/src/ui/components/__tests__/council-message-bubble.test.ts +0 -85
  1824. package/src/ui/components/__tests__/council-phase-timeline.test.ts +0 -57
  1825. package/src/ui/components/__tests__/council-placeholder-bubble.test.ts +0 -16
  1826. package/src/ui/components/__tests__/council-question-card.test.ts +0 -133
  1827. package/src/ui/components/__tests__/council-synthesis-banner.test.ts +0 -12
  1828. package/src/ui/components/__tests__/task-list-panel.test.ts +0 -37
  1829. package/src/ui/components/__tests__/use-pair-quote-buffer.test.ts +0 -41
  1830. package/src/ui/components/btw-overlay.tsx +0 -66
  1831. package/src/ui/components/bubble-layout.ts +0 -66
  1832. package/src/ui/components/code-block-truncate.ts +0 -24
  1833. package/src/ui/components/copy-flash-banner.tsx +0 -31
  1834. package/src/ui/components/council-info-card.tsx +0 -44
  1835. package/src/ui/components/council-leader-bubble.tsx +0 -40
  1836. package/src/ui/components/council-message-bubble.tsx +0 -110
  1837. package/src/ui/components/council-phase-timeline.tsx +0 -112
  1838. package/src/ui/components/council-placeholder-bubble.tsx +0 -64
  1839. package/src/ui/components/council-question-card.tsx +0 -256
  1840. package/src/ui/components/council-status-list.tsx +0 -111
  1841. package/src/ui/components/council-synthesis-banner.tsx +0 -36
  1842. package/src/ui/components/diff-view.tsx +0 -225
  1843. package/src/ui/components/halt-recovery-card.tsx +0 -84
  1844. package/src/ui/components/hero-logo.tsx +0 -62
  1845. package/src/ui/components/init-new-form-card.tsx +0 -470
  1846. package/src/ui/components/lsp-views.tsx +0 -104
  1847. package/src/ui/components/media-views.tsx +0 -66
  1848. package/src/ui/components/message-view.tsx +0 -442
  1849. package/src/ui/components/point-to-existing-form-card.tsx +0 -136
  1850. package/src/ui/components/prompt-box.tsx +0 -306
  1851. package/src/ui/components/role-palette.ts +0 -62
  1852. package/src/ui/components/session-header.tsx +0 -68
  1853. package/src/ui/components/slash-inline-menu.tsx +0 -63
  1854. package/src/ui/components/structured-response-view.tsx +0 -191
  1855. package/src/ui/components/task-list-panel.tsx +0 -127
  1856. package/src/ui/components/tool-group.tsx +0 -129
  1857. package/src/ui/components/tool-result-views.tsx +0 -258
  1858. package/src/ui/components/use-pair-quote-buffer.ts +0 -23
  1859. package/src/ui/constants.ts +0 -242
  1860. package/src/ui/hooks/use-agent-editor.ts +0 -61
  1861. package/src/ui/hooks/use-mcp-editor.ts +0 -39
  1862. package/src/ui/hooks/use-model-picker.ts +0 -50
  1863. package/src/ui/hooks/useTypeahead.ts +0 -160
  1864. package/src/ui/markdown.tsx +0 -49
  1865. package/src/ui/mcp-modal-types.ts +0 -33
  1866. package/src/ui/mcp-modal.tsx +0 -484
  1867. package/src/ui/modals/api-key-modal.tsx +0 -99
  1868. package/src/ui/modals/connect-modal.tsx +0 -259
  1869. package/src/ui/modals/model-picker-modal.tsx +0 -347
  1870. package/src/ui/modals/sandbox-picker-modal.tsx +0 -99
  1871. package/src/ui/modals/update-modal.tsx +0 -67
  1872. package/src/ui/modals/wallet-picker-modal.tsx +0 -186
  1873. package/src/ui/picker-providers.ts +0 -41
  1874. package/src/ui/plan.tsx +0 -346
  1875. package/src/ui/schedule-modal.tsx +0 -138
  1876. package/src/ui/slash/__tests__/clear.test.ts +0 -86
  1877. package/src/ui/slash/__tests__/compact.test.ts +0 -56
  1878. package/src/ui/slash/__tests__/cost.test.ts +0 -62
  1879. package/src/ui/slash/__tests__/discuss.test.ts +0 -101
  1880. package/src/ui/slash/__tests__/execute.test.ts +0 -86
  1881. package/src/ui/slash/__tests__/expand.test.ts +0 -86
  1882. package/src/ui/slash/__tests__/ideal.test.ts +0 -182
  1883. package/src/ui/slash/__tests__/menu-parity.test.ts +0 -44
  1884. package/src/ui/slash/__tests__/optimize.test.ts +0 -155
  1885. package/src/ui/slash/__tests__/pin.test.ts +0 -47
  1886. package/src/ui/slash/__tests__/plan.test.ts +0 -98
  1887. package/src/ui/slash/__tests__/status-render.test.ts +0 -82
  1888. package/src/ui/slash/clear.ts +0 -89
  1889. package/src/ui/slash/compact.ts +0 -46
  1890. package/src/ui/slash/cost.ts +0 -63
  1891. package/src/ui/slash/council-inspect.ts +0 -188
  1892. package/src/ui/slash/council.ts +0 -30
  1893. package/src/ui/slash/debug.ts +0 -153
  1894. package/src/ui/slash/discuss.ts +0 -71
  1895. package/src/ui/slash/ee.ts +0 -304
  1896. package/src/ui/slash/execute.ts +0 -44
  1897. package/src/ui/slash/expand.ts +0 -51
  1898. package/src/ui/slash/export.ts +0 -309
  1899. package/src/ui/slash/ideal.ts +0 -292
  1900. package/src/ui/slash/menu-items.ts +0 -107
  1901. package/src/ui/slash/optimize.ts +0 -47
  1902. package/src/ui/slash/pin.ts +0 -41
  1903. package/src/ui/slash/plan.ts +0 -62
  1904. package/src/ui/slash/registry.ts +0 -47
  1905. package/src/ui/slash/route.test.ts +0 -82
  1906. package/src/ui/slash/route.ts +0 -43
  1907. package/src/ui/slash/status.ts +0 -36
  1908. package/src/ui/state/active-run.ts +0 -56
  1909. package/src/ui/status-bar/index.test.tsx +0 -154
  1910. package/src/ui/status-bar/index.tsx +0 -126
  1911. package/src/ui/status-bar/store.test.ts +0 -131
  1912. package/src/ui/status-bar/store.ts +0 -332
  1913. package/src/ui/status-bar/tier-badge.test.tsx +0 -38
  1914. package/src/ui/status-bar/tier-badge.tsx +0 -29
  1915. package/src/ui/status-bar/usd-meter.test.tsx +0 -37
  1916. package/src/ui/status-bar/usd-meter.tsx +0 -22
  1917. package/src/ui/syntax-highlight.ts +0 -627
  1918. package/src/ui/terminal-selection-text.ts +0 -72
  1919. package/src/ui/theme.ts +0 -95
  1920. package/src/ui/types.ts +0 -83
  1921. package/src/ui/utils/__tests__/format.test.ts +0 -71
  1922. package/src/ui/utils/__tests__/tools.test.ts +0 -57
  1923. package/src/ui/utils/color.ts +0 -19
  1924. package/src/ui/utils/format.ts +0 -133
  1925. package/src/ui/utils/modal.ts +0 -9
  1926. package/src/ui/utils/text.ts +0 -32
  1927. package/src/ui/utils/tools.ts +0 -137
  1928. package/src/usage/.gitkeep +0 -0
  1929. package/src/usage/__tests__/product-ledger.test.ts +0 -86
  1930. package/src/usage/cost-log.ts +0 -158
  1931. package/src/usage/decision-log.ts +0 -86
  1932. package/src/usage/downgrade.test.ts +0 -86
  1933. package/src/usage/downgrade.ts +0 -88
  1934. package/src/usage/estimator.test.ts +0 -43
  1935. package/src/usage/estimator.ts +0 -58
  1936. package/src/usage/ledger.test.ts +0 -200
  1937. package/src/usage/ledger.ts +0 -253
  1938. package/src/usage/midstream.test.ts +0 -55
  1939. package/src/usage/midstream.ts +0 -51
  1940. package/src/usage/product-ledger.ts +0 -119
  1941. package/src/usage/thresholds.test.ts +0 -83
  1942. package/src/usage/thresholds.ts +0 -74
  1943. package/src/usage/types.ts +0 -41
  1944. package/src/utils/__tests__/auto-council-settings.test.ts +0 -46
  1945. package/src/utils/__tests__/ee-logger.test.ts +0 -197
  1946. package/src/utils/__tests__/file-lock.test.ts +0 -74
  1947. package/src/utils/__tests__/llm-deadline.test.ts +0 -64
  1948. package/src/utils/__tests__/rate-limit.test.ts +0 -42
  1949. package/src/utils/__tests__/settings-disabled-models.test.ts +0 -113
  1950. package/src/utils/__tests__/settings-web-research.test.ts +0 -45
  1951. package/src/utils/__tests__/slugify.test.ts +0 -45
  1952. package/src/utils/__tests__/visible-retry.test.ts +0 -195
  1953. package/src/utils/at-mentions.ts +0 -120
  1954. package/src/utils/clipboard-image.ts +0 -139
  1955. package/src/utils/ee-logger.ts +0 -163
  1956. package/src/utils/file-index.ts +0 -152
  1957. package/src/utils/file-lock.ts +0 -66
  1958. package/src/utils/git-root.ts +0 -17
  1959. package/src/utils/host-clipboard.ts +0 -68
  1960. package/src/utils/install-manager.test.ts +0 -167
  1961. package/src/utils/install-manager.ts +0 -429
  1962. package/src/utils/instructions.test.ts +0 -112
  1963. package/src/utils/instructions.ts +0 -149
  1964. package/src/utils/llm-deadline.ts +0 -80
  1965. package/src/utils/permission-mode.test.ts +0 -121
  1966. package/src/utils/permission-mode.ts +0 -94
  1967. package/src/utils/rate-limit.ts +0 -21
  1968. package/src/utils/redactor.test.ts +0 -100
  1969. package/src/utils/redactor.ts +0 -223
  1970. package/src/utils/settings.test.ts +0 -181
  1971. package/src/utils/settings.ts +0 -1163
  1972. package/src/utils/shell.test.ts +0 -102
  1973. package/src/utils/shell.ts +0 -204
  1974. package/src/utils/side-question.ts +0 -39
  1975. package/src/utils/skills.test.ts +0 -58
  1976. package/src/utils/skills.ts +0 -207
  1977. package/src/utils/slugify.ts +0 -9
  1978. package/src/utils/subagent-display.test.ts +0 -23
  1979. package/src/utils/subagent-display.ts +0 -11
  1980. package/src/utils/subagents-settings.test.ts +0 -84
  1981. package/src/utils/telegram-audio-settings.test.ts +0 -44
  1982. package/src/utils/update-checker.test.ts +0 -182
  1983. package/src/utils/update-checker.ts +0 -33
  1984. package/src/utils/visible-retry.ts +0 -56
  1985. package/src/verify/__tests__/coverage-parsers.test.ts +0 -86
  1986. package/src/verify/__tests__/dotnet-recipe.test.ts +0 -88
  1987. package/src/verify/checkpoint.test.ts +0 -186
  1988. package/src/verify/checkpoint.ts +0 -239
  1989. package/src/verify/coverage-parsers.ts +0 -76
  1990. package/src/verify/entrypoint.test.ts +0 -293
  1991. package/src/verify/entrypoint.ts +0 -495
  1992. package/src/verify/environment.test.ts +0 -119
  1993. package/src/verify/environment.ts +0 -115
  1994. package/src/verify/evidence.ts +0 -104
  1995. package/src/verify/orchestrator.test.ts +0 -159
  1996. package/src/verify/orchestrator.ts +0 -129
  1997. package/src/verify/recipes.ts +0 -592
  1998. package/src/verify/retry.ts +0 -62
  1999. package/src/verify/runtime-prep.test.ts +0 -47
  2000. /package/dist/src/{pil/layer16-clarity.test.d.ts → council/__tests__/clarification-prompt.test.d.ts} +0 -0
@@ -1,3364 +0,0 @@
1
- // MessageProcessor — extracted from orchestrator.ts as part of Phase 12.4.
2
- //
3
- // Owns the main streaming turn loop that lives in `Agent.processMessage`:
4
- // - Abort wiring (external AbortContext + per-turn AbortController)
5
- // - Trajectory + phase tracker observations on user_turn / abort
6
- // - PIL enrichment pipeline (layers 1/3/6 — fail-open with logging)
7
- // - ROUTE-11 per-turn model routing (decide + fallback to non-disabled
8
- // provider via CouncilManager)
9
- // - Vision proxy (history + current turn)
10
- // - Auto-council gate (PIL taskType + heavy tier + role count) — routes
11
- // into runCouncilV2 and re-enters processMessage with synthesis
12
- // - System prompt assembly (chitchat / playwright gating + PIL suffix +
13
- // model constraints)
14
- // - SAMR step-aware routing (phase1 reasoning → phase2 execution)
15
- // - Tool roundtrip loop:
16
- // - Compaction (relax on overflow recovery, B4 top-level prepareStep)
17
- // - Tool set assembly: builtin + MCP (smart filter for chitchat /
18
- // browser-vocab) + PIL response tools, all wrapped with top-level
19
- // cumulative cap (F1), cross-turn dedup (C3), read-path budget
20
- // - ProviderOptions composition (buildTurnProviderOptions +
21
- // taskTypeToReasoningEffort budget + thinkingType adaptive override
22
- // + O1 shape capture)
23
- // - streamText({...}) with prepareStep (top-level compactor +
24
- // capability sanitizeHistory), onStepStart/Finish, onFinish
25
- // (correlation cleanup)
26
- // - fullStream consumer (text-delta / reasoning-delta / tool-call
27
- // with EE PreToolUse intercept / tool-result with EE PostToolUse
28
- // and vision-bridge / tool-error / tool-approval-request /
29
- // error / abort)
30
- // - Write-ahead persistence (Phase A4 tool_calls, A5 message_seq)
31
- // - Context-overflow recovery + transient retry with exponential backoff
32
- // - Post-turn compact + Stop / StopFailure hooks
33
- // - Debug pipeline trace
34
- //
35
- // Zero behavioral changes — every method body mirrors the original
36
- // `processMessage` (see commit history). The DI surface (`MessageProcessorDeps`)
37
- // is the minimum proxy onto Agent state needed to reach back into Agent
38
- // without holding a circular reference. Public `Agent.processMessage`
39
- // signature is unchanged and continues to be the entrypoint; internally it
40
- // constructs a `MessageProcessor` per call.
41
- //
42
- // Cost-leak code paths preserved here:
43
- // - F1 (top-level cumulative cap) — wrapToolSetWithCap (top-level)
44
- // - F1 (openai.promptCacheKey) — buildTurnProviderOptions
45
- // - G1 (OAuth `maxOutputTokens` drop) — shouldDropParam(runtime, ...)
46
- // - B4 (top-level prepareStep compaction) — compactSubAgentMessages
47
- // - C3 (cross-turn dedup wrap) — wrapToolSetWithDedup
48
- // - A4 (tool_call write-ahead) — persistToolCallWriteAhead
49
- // - A5 (message_seq write-ahead) — persistMessageWriteAhead
50
- // - O1 (providerOptions shape forensics) — extractProviderOptionsShape
51
- // - siliconflow reasoning-strip — turnCaps.sanitizeHistory
52
-
53
- import { type ModelMessage, type StopCondition, stepCountIs, streamText, type ToolSet } from "ai";
54
- import { getCachedAuthToken, getCachedServerBaseUrl } from "../ee/auth.js";
55
- import { routeFeedback, routeModel } from "../ee/bridge.js";
56
- import { getDefaultEEClient } from "../ee/intercept.js";
57
- import { getMistakeDetector } from "../ee/mistake-detector.js";
58
- import { fireAndForgetPhaseOutcome } from "../ee/phase-outcome.js";
59
- import * as phaseTracker from "../ee/phase-tracker.js";
60
- import { buildScope as buildScopeForVeto } from "../ee/scope.js";
61
- import { fireTrajectoryEvent } from "../ee/session-trajectory.js";
62
- import { getTenantId as getTenantIdForVeto } from "../ee/tenant.js";
63
- import type {
64
- PostToolUseFailureHookInput,
65
- PostToolUseHookInput,
66
- PreToolUseHookInput,
67
- SessionStartHookInput,
68
- StopFailureHookInput,
69
- StopHookInput,
70
- UserPromptSubmitHookInput,
71
- } from "../hooks/types";
72
- import { buildMcpToolSet } from "../mcp/runtime";
73
- import { dropRedundantFsMcpTools, filterMcpServersByMessage } from "../mcp/smart-filter";
74
- import { getModelInfo } from "../models/registry.js";
75
- import {
76
- cheapModelShellLine,
77
- injectCheapModelPlaybook,
78
- injectCheapModelShellDirective,
79
- shouldInjectCheapModelPlaybook,
80
- } from "../pil/cheap-model-playbook.js";
81
- import { injectCheapModelWorkbook, shouldInjectCheapModelWorkbook } from "../pil/cheap-model-workbooks.js";
82
- import type { DiscoveryInteractionHandler } from "../pil/discovery-types.js";
83
- import {
84
- applyPilSuffix,
85
- getResponseTaskType,
86
- getResponseToolSet,
87
- isResponseTool,
88
- runPipeline,
89
- shouldHaltOnResponseTool,
90
- } from "../pil/index.js";
91
- import { taskTypeToMaxTokens, taskTypeToReasoningEffort, taskTypeToTier } from "../pil/task-tier-map.js";
92
- import { getProviderCapabilities } from "../providers/capabilities.js";
93
- import { loadKeyForProvider } from "../providers/keychain.js";
94
- import {
95
- bridgeMcpToolResult,
96
- getVisionGuidanceForTextOnly,
97
- listCachedImages,
98
- scrubImagePayloadsInMessages,
99
- } from "../providers/mcp-vision-bridge.js";
100
- import { captureToolSchemas } from "../providers/patch-zod-schema.js";
101
- import {
102
- buildTurnProviderOptions,
103
- detectProviderForModel,
104
- type ResolvedModelRuntime,
105
- requireRuntimeProvider,
106
- resolveModelRuntime,
107
- shouldDropParam,
108
- } from "../providers/runtime.js";
109
- import type { ProviderId } from "../providers/types.js";
110
- import { needsVisionProxy, proxyVision } from "../providers/vision-proxy.js";
111
- import { wireDebug } from "../providers/wire-debug.js";
112
- import { reportRouteOutcome } from "../router/decide.js";
113
- import { decideStepRouting, getStepRouterConfig } from "../router/step-router.js";
114
- import { routerStore } from "../router/store.js";
115
- import {
116
- getNextMessageSequence,
117
- logInteraction,
118
- markMessageErrored,
119
- markToolCallErrored,
120
- persistMessageWriteAhead,
121
- persistToolCallWriteAhead,
122
- type SessionStore,
123
- } from "../storage/index.js";
124
- import { createBuiltinTools } from "../tools/registry.js";
125
- import { snapshotFromTodoWriteArgs } from "../tools/todo-write-snapshot.js";
126
- import { visionToolsNeeded } from "../tools/vision-gate.js";
127
- import type { SessionInfo, StreamChunk, SubagentStatus, ToolCall } from "../types/index";
128
- import { isDebugEnabled, type PipelineStep, recordTurnTrace, type TurnTrace } from "../ui/slash/debug.js";
129
- import { statusBarStore } from "../ui/status-bar/store.js";
130
- import { appendDecisionLog } from "../usage/decision-log.js";
131
- import { appendAudit, type PermissionMode, toolNeedsApproval } from "../utils/permission-mode.js";
132
- import {
133
- getAutoCouncilConfidence,
134
- getAutoCouncilMinRoles,
135
- getProviderStallTimeoutMs,
136
- getRoleModels,
137
- getTopLevelCompactKeepLast,
138
- getTopLevelCompactThresholdChars,
139
- getTopLevelToolBudgetChars,
140
- isAutoCouncilEnabled,
141
- isProviderDisabled,
142
- loadMcpServers,
143
- loadValidSubAgents,
144
- } from "../utils/settings";
145
- import { resolveShell } from "../utils/shell.js";
146
- import type { AbortContext } from "./abort.js";
147
- import type { LegacyProvider, ProcessMessageObserver } from "./agent-options";
148
- import { relaxCompactionSettings } from "./compaction";
149
- import type { CouncilManager } from "./council-manager.js";
150
- import type { CrossTurnDedup } from "./cross-turn-dedup.js";
151
- import { wrapToolSetWithDedup } from "./cross-turn-dedup.js";
152
- import { humanizeApiError, isAuthenticationError, isContextLimitError, summarizeApiErrorForLog } from "./error-utils";
153
- import { buildGroundingFootnote, findUnverifiedClaims } from "./grounding-check.js";
154
- import { buildInterruptedTurnNote } from "./interrupted-turn.js";
155
- import type { PendingCallsLog } from "./pending-calls.js";
156
- import { stableCallId } from "./pending-calls.js";
157
- import { applyModelConstraints, buildSystemPromptParts } from "./prompts";
158
- import { extractProviderOptionsShape } from "./provider-options-shape.js";
159
- import type { ReadPathBudget } from "./read-path-budget.js";
160
- import { wrapToolSetWithReadBudget } from "./read-path-budget.js";
161
- import { containsEncryptedReasoning, sanitizeModelMessages } from "./reasoning";
162
- import { repairToolCallHook } from "./repair-tool-call.js";
163
- import {
164
- buildRepetitionReminder,
165
- recordAssistantBurst,
166
- shouldInjectRepetitionReminder,
167
- } from "./repetition-detector.js";
168
- import { classifyStreamError } from "./retry-classifier.js";
169
- import {
170
- forcedFinalize,
171
- getSessionLastTask,
172
- incSessionStep,
173
- parseBudgetOverride,
174
- recordSessionLastTask,
175
- resetSessionStep,
176
- resolveCeiling,
177
- } from "./scope-ceiling.js";
178
- import {
179
- attachReminderToMessages,
180
- buildCheckpointReminder,
181
- buildScopeReminder,
182
- type ComplexitySize,
183
- cadenceForSize,
184
- shouldInjectCeilingCrossing,
185
- shouldInjectReminder,
186
- shouldInjectSoftWarn,
187
- } from "./scope-reminder.js";
188
- import { attemptStallRescue, pushStallToolResult, type StallToolResult } from "./stall-rescue.js";
189
- import { createStallWatchdog, STALL_ERROR_MESSAGE } from "./stall-watchdog.js";
190
- import { wrapToolSetWithCap } from "./sub-agent-cap.js";
191
- import { compactSubAgentMessages } from "./subagent-compactor.js";
192
- import { detectTextEmittedToolCall, parseDsmlToolCalls } from "./text-tool-call-detector.js";
193
- import { createToolLoopCapPredicate, type ToolLoopCapAsk } from "./tool-loop-cap.js";
194
- import {
195
- buildToolRepetitionAbortMessage,
196
- recordToolError as recordToolRepetitionError,
197
- recordToolSuccess as recordToolRepetitionSuccess,
198
- } from "./tool-repetition-detector.js";
199
-
200
- /**
201
- * F2 — approximate the char cost of the FIXED prompt envelope (system +
202
- * tools JSON-Schema) that streamText re-sends on every step. Used to feed
203
- * the compactor a realistic total-prompt size so it fires when billed input
204
- * is actually large, not when only `messages[]` is.
205
- */
206
- function computeEnvelopeChars(system: unknown, tools: unknown): number {
207
- let n = 0;
208
- if (typeof system === "string") n += system.length;
209
- else if (system && typeof system === "object") {
210
- try {
211
- n += JSON.stringify(system).length;
212
- } catch {
213
- /* ignore — best-effort estimate */
214
- }
215
- }
216
- if (tools && typeof tools === "object") {
217
- try {
218
- n += JSON.stringify(tools).length;
219
- } catch {
220
- /* ignore */
221
- }
222
- }
223
- return n;
224
- }
225
-
226
- import {
227
- combineAbortSignals,
228
- getFinishReason,
229
- getStepNumber,
230
- getUsage,
231
- notifyObserver,
232
- toToolCall,
233
- toToolResult,
234
- } from "./tool-utils";
235
- import type { TurnRunnerDepsBase } from "./turn-runner-deps.js";
236
-
237
- /**
238
- * Dependency surface the MessageProcessor needs to reach back into Agent
239
- * state without holding a circular reference. Properties expose array
240
- * references (mutating push() must affect the same array the Agent reads on
241
- * subsequent turns). Method callbacks delegate to Agent private methods.
242
- */
243
- export interface MessageProcessorDeps extends TurnRunnerDepsBase {
244
- // ---- Read/write state references --------------------------------------
245
- // (messages, bash, mode, maxToolRounds, schedules, sendTelegramFile inherited)
246
- /** Live messageSeqs array (mutated by push; parallel to messages). */
247
- readonly messageSeqs: Array<number | null>;
248
- /** Session bookkeeping. */
249
- readonly session: SessionInfo | null;
250
- readonly sessionStore: SessionStore | null;
251
- readonly modelId: string;
252
- readonly providerId: ProviderId;
253
- readonly batchApi: boolean;
254
- readonly permissionMode: PermissionMode;
255
- readonly externalAbortContext: AbortContext | null;
256
- readonly pendingCalls: PendingCallsLog | null;
257
- readonly councilManager: CouncilManager;
258
- readonly crossTurnDedup: CrossTurnDedup | null;
259
- readonly readBudget: ReadPathBudget | null;
260
- readonly priorWarningIdsInSession: Set<string>;
261
- readonly sessionEEGuidance: Map<string, { toolName: string; message: string; why: string; confidence: number }>;
262
- readonly flowReady: Promise<void> | null;
263
-
264
- // ---- Scalar getters / setters -----------------------------------------
265
- getAbortController(): AbortController | null;
266
- setAbortController(ctrl: AbortController | null): void;
267
- getSessionStartHookFired(): boolean;
268
- setSessionStartHookFired(v: boolean): void;
269
- getPlanContext(): string | null;
270
- setPlanContext(v: string | null): void;
271
- getResumeDigest(): string | null;
272
- setResumeDigest(v: string | null): void;
273
- getActiveRunId(): string | null;
274
- getPendingCwdNote(): string | null;
275
- setPendingCwdNote(v: string | null): void;
276
- setPilActive(v: boolean): void;
277
- setPilEnrichmentDelta(n: number): void;
278
- setCurrentCallId(id: string): void;
279
- setLastPromptBreakdown(
280
- b: {
281
- systemChars: number;
282
- staticPrefixChars: number;
283
- dynamicSuffixChars: number;
284
- playwrightGuidanceChars: number;
285
- messagesChars: number;
286
- messagesCount: number;
287
- toolsChars: number;
288
- toolsCount: number;
289
- } | null,
290
- ): void;
291
- setTurnUserGoalExcerpt(v: string): void;
292
- setTurnAssistantReasoning(v: string): void;
293
- appendTurnAssistantReasoning(delta: string): void;
294
- getTurnAssistantReasoning(): string;
295
- setPriorWarningIdsInSession(s: Set<string>): void;
296
- setMessages(messages: ModelMessage[]): void;
297
-
298
- // ---- Behavior delegators ----------------------------------------------
299
- requireProvider(): LegacyProvider;
300
- emitSubagentStatus(status: SubagentStatus | null): void;
301
- fireHook(
302
- input: unknown,
303
- signal?: AbortSignal,
304
- ): Promise<{
305
- blocked: boolean;
306
- blockingErrors: Array<{ command: string; stderr: string }>;
307
- preventContinuation: boolean;
308
- additionalContexts: string[];
309
- results: import("../hooks/types.js").HookResult[];
310
- eeMatches: import("../hooks/types.js").EEMatchEntry[];
311
- }>;
312
- consumeBackgroundNotifications(): Promise<string[]>;
313
- initOAuthProvider(): Promise<void>;
314
- buildRecentTurnsSummary(): string | null;
315
- estimateProjectSize(): "small" | "medium" | "large" | null;
316
- countFilesTouched(): number;
317
- respondToToolApproval(approvalId: string, approved: boolean): void;
318
- /**
319
- * Tool-loop cap askcard hook (Claude-Code-style "continue?" prompt).
320
- *
321
- * Fires when the streamText loop reaches `maxToolRounds`. Returning
322
- * `"continue"` raises the cap by `bumpBy` and lets the loop run; `"stop"`
323
- * halts gracefully (no error). When undefined the loop hard-stops as before
324
- * — preserves backward compat for batch / headless paths that have no UI to
325
- * surface the askcard.
326
- */
327
- askToolLoopContinue?: ToolLoopCapAsk;
328
- runCouncilV2(
329
- userMessage: string,
330
- opts: { skipClarification: boolean; observer?: ProcessMessageObserver; userModelMessage: ModelMessage },
331
- ): AsyncGenerator<StreamChunk, void, unknown>;
332
- processMessage(
333
- userMessage: string,
334
- observer?: ProcessMessageObserver,
335
- images?: Array<{ path: string; mediaType: string; base64: string }>,
336
- ): AsyncGenerator<StreamChunk, void, unknown>;
337
- processMessageBatchTurn(args: {
338
- userModelMessage: ModelMessage;
339
- observer?: ProcessMessageObserver;
340
- provider: LegacyProvider;
341
- subagents: ReturnType<typeof loadValidSubAgents>;
342
- system: string;
343
- runtime: ResolvedModelRuntime;
344
- modelInfo: ResolvedModelRuntime["modelInfo"];
345
- signal: AbortSignal;
346
- }): AsyncGenerator<StreamChunk, void, unknown>;
347
- }
348
-
349
- /**
350
- * MessageProcessor — extracted streaming turn loop.
351
- *
352
- * Lifecycle:
353
- * const processor = new MessageProcessor(deps);
354
- * yield* processor.run(userMessage, observer, images);
355
- *
356
- * Constructed per call (heap allocation is negligible against the streamText
357
- * cost), matching the StreamRunner / CouncilManager pattern.
358
- */
359
-
360
- /**
361
- * Max response-tool (`respond_*`) calls tolerated within a single turn before
362
- * the orchestrator finalizes early with the best answer buffered so far. A
363
- * well-behaved turn emits the response tool ONCE; a hedge-then-answer emits 2.
364
- * Beyond that is degenerate spam (session 8d8f498268ed: 80× identical
365
- * respond_general in one generation). Set to 3 so the legitimate ≤2 patterns
366
- * are never cut short.
367
- */
368
- const RESPONSE_TOOL_SPAM_CAP = 3;
369
-
370
- export class MessageProcessor {
371
- constructor(private deps: MessageProcessorDeps) {}
372
-
373
- async *run(
374
- userMessage: string,
375
- observer?: ProcessMessageObserver,
376
- images?: Array<{ path: string; mediaType: string; base64: string }>,
377
- ): AsyncGenerator<StreamChunk, void, unknown> {
378
- const deps = this.deps;
379
- // TUI-04: prefer the external AbortContext (from SIGINT handler) so that
380
- // Ctrl+C mid-tool-call triggers a single, unified abort across all I/O.
381
- // If no external context, fall back to creating a local AbortController.
382
- if (deps.externalAbortContext) {
383
- // Wrap the external signal in a local controller so existing cleanup
384
- // paths (setAbortController(null)) still work without side-effects.
385
- const ctrl = new AbortController();
386
- deps.setAbortController(ctrl);
387
- // Forward external abort to the local controller.
388
- deps.externalAbortContext.signal.addEventListener(
389
- "abort",
390
- () => {
391
- deps.getAbortController()?.abort(deps.externalAbortContext?.reason());
392
- },
393
- { once: true },
394
- );
395
- } else {
396
- deps.setAbortController(new AbortController());
397
- }
398
- const signal = deps.getAbortController()!.signal;
399
- deps.emitSubagentStatus(null);
400
-
401
- // Phase 5 Fix 1 — reset the per-session step counter at every user-turn
402
- // boundary. The original Phase 4 design kept the counter per-SESSION so a
403
- // wandering agent bursting 50 tools across pseudo-turns would still trip
404
- // the ceiling. In practice that punishes legitimate multi-turn work: turn
405
- // 1 fills the counter, turn 2 (even a deliberate continuation) is halted
406
- // almost immediately because the ceiling row may resolve smaller for the
407
- // continuation's classified task. A new user message is an explicit
408
- // human-in-the-loop signal — the user has seen results and chose to
409
- // continue. Reset the counter so each user turn gets the full budget the
410
- // matrix specifies for its own (taskType, size). Within-turn wandering
411
- // is still capped by the per-turn ceiling, which is the real concern.
412
- if (deps.session?.id) {
413
- resetSessionStep(deps.session.id);
414
- }
415
-
416
- // Phase C3: advance the cross-turn dedup turn counter so stubs can point
417
- // back to the correct prior turn.
418
- deps.crossTurnDedup?.beginTurn();
419
-
420
- // P0 native observation: turn boundary. Capture the prior batch via
421
- // resetBatch — file-revert detection (in the hook layer) reads it on
422
- // the first edit of the new turn. No language-based veto matching.
423
- try {
424
- getMistakeDetector().resetBatch();
425
- if (deps.session?.id) {
426
- fireTrajectoryEvent({
427
- ts: new Date().toISOString(),
428
- sessionId: deps.session.id,
429
- kind: "user_turn",
430
- excerpt: userMessage.slice(0, 200),
431
- vetoDetected: false,
432
- });
433
- }
434
- } catch {
435
- /* fail-open: detector state must never block the turn */
436
- }
437
-
438
- // P0 native observation: AbortSignal → fire user-veto for any in-flight
439
- // batch tools that had warnings. Listener attaches here and self-removes
440
- // after fire so it can't double-fire on later aborts in the same turn.
441
- {
442
- const aborter = () => {
443
- try {
444
- // P1 Item 3 wiring: mark current phase aborted so the next setPhase
445
- // call drains an "abandoned" outcome.
446
- phaseTracker.markAborted(
447
- deps.getAbortController()?.signal.reason ? String(deps.getAbortController()!.signal.reason) : undefined,
448
- );
449
- } catch {
450
- /* fail-open */
451
- }
452
- try {
453
- const det = getMistakeDetector();
454
- const events = det.detectAbort(
455
- deps.getAbortController()?.signal.reason ? String(deps.getAbortController()!.signal.reason) : undefined,
456
- );
457
- if (events.length === 0) return;
458
- const cwd = deps.bash.getCwd();
459
- const tenantId = getTenantIdForVeto();
460
- void buildScopeForVeto({ cwd })
461
- .then(async (scope) => {
462
- const { getDefaultEEClient } = await import("../ee/intercept.js");
463
- for (const ev of events) {
464
- void getDefaultEEClient()
465
- .posttool({
466
- toolName: ev.toolName,
467
- toolInput: ev.toolInput,
468
- outcome: { success: false, mistakeKind: ev.kind, evidence: ev.evidence },
469
- cwd,
470
- tenantId,
471
- scope,
472
- })
473
- .catch(() => {
474
- /* fire-and-forget */
475
- });
476
- }
477
- })
478
- .catch(() => {
479
- /* fire-and-forget */
480
- });
481
- } catch {
482
- /* fail-open */
483
- }
484
- };
485
- signal.addEventListener("abort", aborter, { once: true });
486
- }
487
-
488
- // Phase 4 Plan 04 (4B) — parse `--budget-rounds N` flag BEFORE PIL so the
489
- // flag never reaches the model and never biases intent classification.
490
- // The stashed override is consumed after PIL produces taskType + size.
491
- const _budgetOverride = parseBudgetOverride(userMessage);
492
- if (_budgetOverride.override !== undefined) {
493
- userMessage = _budgetOverride.cleanedPrompt;
494
- }
495
-
496
- // P0 native observation: cache turn-level intent fields for PreToolUse.
497
- deps.setTurnUserGoalExcerpt(userMessage.slice(0, 200));
498
- deps.setTurnAssistantReasoning("");
499
-
500
- // Ensure flow run is ready before processing (fail-open).
501
- await deps.flowReady?.catch(() => {});
502
-
503
- // Upgrade to OAuth-backed provider on first turn if tokens are available.
504
- await deps.initOAuthProvider().catch(() => {});
505
-
506
- if (!deps.getSessionStartHookFired()) {
507
- deps.setSessionStartHookFired(true);
508
- const isResume = deps.messages.length > 0;
509
- const sessionStartInput: SessionStartHookInput = {
510
- hook_event_name: "SessionStart",
511
- source: isResume ? "resume" : "startup",
512
- session_id: deps.session?.id,
513
- cwd: deps.bash.getCwd(),
514
- };
515
- await deps.fireHook(sessionStartInput, signal).catch(() => {});
516
- }
517
-
518
- const promptInput: UserPromptSubmitHookInput = {
519
- hook_event_name: "UserPromptSubmit",
520
- user_prompt: userMessage,
521
- session_id: deps.session?.id,
522
- cwd: deps.bash.getCwd(),
523
- };
524
- await deps.fireHook(promptInput, signal).catch(() => {});
525
-
526
- await deps.consumeBackgroundNotifications();
527
-
528
- const _debugOn = isDebugEnabled();
529
- const _debugSteps: PipelineStep[] = [];
530
- const _debugTurnId = deps.messages.filter((m) => m.role === "user").length + 1;
531
-
532
- // PIL: enrich prompt before pushing to messages (D-01, D-03, D-04)
533
- // Promise.race timeout of 200ms is inside runPipeline — fail-open guaranteed
534
- // --- PIL with discovery (interactive path) ---
535
- const pilChunkQueue: StreamChunk[] = [];
536
- const pilResponder = deps.councilManager.createQuestionResponder();
537
-
538
- const discoveryHandler: DiscoveryInteractionHandler = {
539
- askQuestion: async (question) => {
540
- pilChunkQueue.push({
541
- type: "council_question",
542
- content: question.question,
543
- councilQuestion: question,
544
- } as StreamChunk);
545
- const text = await pilResponder(question.questionId);
546
- return { questionId: question.questionId, text, kind: "choice" as const };
547
- },
548
- showAcceptance: async (card) => {
549
- const { buildAcceptanceQuestion } = await import("../pil/layer18-acceptance.js");
550
- const question = buildAcceptanceQuestion(card, crypto.randomUUID());
551
- pilChunkQueue.push({
552
- type: "council_question",
553
- content: question.question,
554
- councilQuestion: question,
555
- } as StreamChunk);
556
- const text = await pilResponder(question.questionId);
557
- return text.toLowerCase() as "accept" | "adjust" | "cancel";
558
- },
559
- };
560
-
561
- const _pilStart = Date.now();
562
- let pilCtxResolved: Awaited<ReturnType<typeof runPipeline>> | null = null;
563
- let pilDone = false;
564
-
565
- const pilTask = (async () => {
566
- try {
567
- // Build Pass 4 LLM fallback closure using the orchestrator's already-
568
- // constructed provider factory + current model. PIL stays ignorant of
569
- // provider wiring — it just receives a `classify(prompt)` callback.
570
- let llmFallback: import("../pil/llm-classify.js").LlmClassifyFn | undefined;
571
- try {
572
- const { createLlmClassifier } = await import("../pil/llm-classify.js");
573
- llmFallback = createLlmClassifier(deps.requireProvider(), deps.modelId);
574
- } catch (err) {
575
- console.error(`[pil] LLM fallback wiring failed: ${(err as Error)?.message}`);
576
- }
577
-
578
- // Model-driven clarification proposer (for discovery interview).
579
- // The actual task model (via the same provider + modelId) generates the
580
- // questions based on raw + CLI enrichment. Then discovery asks user.
581
- let clarificationProposer: import("../pil/discovery-types.js").ModelClarificationProposer | undefined;
582
- try {
583
- const { createModelClarificationProposer } = await import("../pil/discovery.js");
584
- clarificationProposer = createModelClarificationProposer(deps.requireProvider(), deps.modelId);
585
- } catch (err) {
586
- console.error(`[pil] clarification proposer wiring failed: ${(err as Error)?.message}`);
587
- }
588
-
589
- pilCtxResolved = await runPipeline(userMessage, {
590
- resumeDigest: deps.getResumeDigest(),
591
- activeRunId: deps.getActiveRunId(),
592
- sessionId: deps.session?.id ?? null,
593
- interactionHandler: discoveryHandler,
594
- llmFallback,
595
- clarificationProposer,
596
- recentTurnsSummary: deps.buildRecentTurnsSummary(),
597
- });
598
- } catch (err) {
599
- pilCtxResolved = {
600
- raw: userMessage,
601
- enriched: userMessage,
602
- taskType: null,
603
- domain: null,
604
- confidence: 0,
605
- outputStyle: null,
606
- tokenBudget: 500,
607
- metrics: null,
608
- layers: [],
609
- gsdPhase: null,
610
- activeRunId: null,
611
- intentKind: null as "task" | "chitchat" | null,
612
- fallbackReason: err instanceof Error ? `orchestrator-catch:${err.name}` : "orchestrator-catch:unknown",
613
- };
614
- } finally {
615
- pilDone = true;
616
- }
617
- })();
618
-
619
- while (!pilDone) {
620
- while (pilChunkQueue.length > 0) {
621
- yield pilChunkQueue.shift()!;
622
- }
623
- if (!pilDone) {
624
- await new Promise((resolve) => setImmediate(resolve));
625
- }
626
- }
627
- while (pilChunkQueue.length > 0) {
628
- yield pilChunkQueue.shift()!;
629
- }
630
- await pilTask;
631
-
632
- const pilCtx = pilCtxResolved!;
633
-
634
- // Phase 4 Plan 04 (4B) — resolve per-session step ceiling using
635
- // (task_type × complexitySize) matrix. Override (from --budget-rounds N
636
- // parsed earlier) wins. When the override differs from the natural
637
- // ceiling, emit info toast so the user sees the explicit cap.
638
- //
639
- // Phase 5 Fix 2 — continuation phrases ("tiếp tục" / "continue") are
640
- // classified `general/chitchat` by PIL Layer 1 Pass 0. Resolving the
641
- // ceiling from that label collapses the budget to general × small = 5,
642
- // which is wrong: the user wants the agent to RESUME the prior task,
643
- // not start a generic chitchat. When this session has a recorded
644
- // non-chitchat task row, inherit it for ceiling resolution. The Pass 0
645
- // classification itself stays general so downstream code (style /
646
- // chitchat skip / tools-empty optimization in `BUG-A guard`) reads the
647
- // correct intent; only the ceiling row is borrowed.
648
- const _pilTaskType = pilCtx.taskType ?? "general";
649
- const _pilSize = pilCtx.complexitySize?.size ?? "medium";
650
- const _sessionIdForLastTask = deps.session?.id ?? "";
651
- const _isContinuationChitchat =
652
- _pilTaskType === "general" && pilCtx.intentKind === "chitchat" && _sessionIdForLastTask !== "";
653
- const _lastTask = _isContinuationChitchat ? getSessionLastTask(_sessionIdForLastTask) : null;
654
- const _ceilingTaskType = _lastTask?.taskType ?? _pilTaskType;
655
- const _ceilingSize = _lastTask?.size ?? _pilSize;
656
- const _naturalCeiling = resolveCeiling(_ceilingTaskType, _ceilingSize);
657
- // Phase 5 Fix 4 (Option A) — make ceiling mutable so the stopWhen
658
- // closure can bump it on auto-continue checkpoints. See checkpoint
659
- // logic at dynamicStopWhen below for the bump policy.
660
- const _stepCeiling = _budgetOverride.override ?? _naturalCeiling;
661
- // Record this turn's task row for future continuation inheritance.
662
- // Only non-chitchat task turns update the slot.
663
- if (_sessionIdForLastTask && _pilTaskType !== "general" && pilCtx.intentKind === "task") {
664
- recordSessionLastTask(_sessionIdForLastTask, _pilTaskType, _pilSize);
665
- }
666
- if (_budgetOverride.override !== undefined && _budgetOverride.override !== _naturalCeiling) {
667
- try {
668
- const _ar = (globalThis as Record<string, unknown>).__muonroiAgentRuntime as
669
- | { emitEvent: (e: unknown) => void }
670
- | undefined;
671
- _ar?.emitEvent({
672
- t: "event",
673
- kind: "toast",
674
- level: "info",
675
- text: `override active: ceiling ${_budgetOverride.override}, default was ${_naturalCeiling} (task=${_ceilingTaskType}/size=${_ceilingSize})`,
676
- });
677
- } catch {
678
- /* best-effort */
679
- }
680
- }
681
- // Track whether forced-finalize is needed (set by stopWhen when the
682
- // ceiling fires). Read AFTER the streamText fullStream finishes.
683
- const _ceilingHit = false;
684
-
685
- // Cheap signal forwarded from PIL Layer 1 — true when input is greeting /
686
- // small-talk (≤10 chars + ≤2 words OR brain-classified "none"). Used to
687
- // skip the MCP tool catalog, which dominates input tokens (~20K) and is
688
- // useless for "hi" / "ok" / "thanks".
689
- const isChitchat = pilCtx.intentKind === "chitchat";
690
- let enrichedMessage = pilCtx.enriched;
691
- if (pilCtx.fallbackReason) {
692
- // Surface PIL degradation to the model so it can calibrate trust in
693
- // routing, taskType, and any injected directives. Without this the
694
- // agent has no idea the 200ms fast-path or discovery timeout fired.
695
- enrichedMessage = `[PIL fallback: ${pilCtx.fallbackReason} — classification/routing may be inaccurate or layers skipped; using raw input.]\n\n${enrichedMessage}`;
696
- }
697
- deps.setPilActive(pilCtx.taskType !== null);
698
- deps.setPilEnrichmentDelta(
699
- pilCtx.metrics?.suffixInstructionTokens ?? Math.round((enrichedMessage.length - userMessage.length) / 4),
700
- );
701
- const _pilEnrichmentDeltaSnapshot =
702
- pilCtx.metrics?.suffixInstructionTokens ?? Math.round((enrichedMessage.length - userMessage.length) / 4);
703
-
704
- // P1 Item 3 wiring: phase-boundary detection. setPhase returns a snapshot
705
- // of the prior phase iff the phase NAME just changed. We classify the
706
- // outcome (pass/fail/abandoned/null) and fire phase-outcome to the EE
707
- // server when there is a high-SNR verdict. Endpoint is feature-flagged
708
- // server-side; 404 is silently swallowed by the client wrapper.
709
- try {
710
- const drained = phaseTracker.setPhase(pilCtx.gsdPhase ?? null);
711
- if (drained && drained.principleRefs.length > 0 && deps.session?.id) {
712
- const outcome = phaseTracker.classifyOutcome(drained);
713
- if (outcome) {
714
- fireAndForgetPhaseOutcome(
715
- {
716
- sessionId: deps.session.id,
717
- phaseName: drained.phaseName,
718
- outcome,
719
- toolEventIds: drained.principleRefs,
720
- evidence: {
721
- durationMs: drained.endedAt - drained.startedAt,
722
- toolCount: drained.toolCount,
723
- cwd: deps.bash.getCwd(),
724
- ...(drained.verifyResult ? { verifyResult: drained.verifyResult } : {}),
725
- ...(drained.aborted ? { aborted: true } : {}),
726
- ...(drained.abortReason ? { abortReason: drained.abortReason } : {}),
727
- },
728
- },
729
- {
730
- ...(getCachedServerBaseUrl() ? { baseUrl: getCachedServerBaseUrl()! } : {}),
731
- ...(getCachedAuthToken() ? { authToken: getCachedAuthToken()! } : {}),
732
- },
733
- );
734
- }
735
- }
736
- } catch {
737
- /* fail-open: phase-outcome must never block a turn */
738
- }
739
-
740
- if (_debugOn) {
741
- const appliedLayers = pilCtx.layers?.filter((l) => l.applied).map((l) => l.name) ?? [];
742
- _debugSteps.push({
743
- name: "PIL Pipeline",
744
- duration_ms: Date.now() - _pilStart,
745
- input_summary: `"${userMessage.slice(0, 60)}${userMessage.length > 60 ? "..." : ""}"`,
746
- output_summary: `task=${pilCtx.taskType ?? "none"} domain=${pilCtx.domain ?? "none"} layers=[${appliedLayers.join(",")}]`,
747
- tokens_saved: _pilEnrichmentDeltaSnapshot > 0 ? _pilEnrichmentDeltaSnapshot : undefined,
748
- });
749
- }
750
-
751
- // Interaction log: PIL classification
752
- try {
753
- if (deps.session) {
754
- const pilDurationMs = Date.now() - _pilStart;
755
- // BUG-B telemetry — hash the raw user message so post-hoc queries can
756
- // detect Layer 1 classifier drift on identical inputs within a session.
757
- const { createHash } = await import("node:crypto");
758
- const _userMsgSha8 = createHash("sha1").update(userMessage).digest("hex").slice(0, 8);
759
- logInteraction(deps.session.id, "pil", {
760
- eventSubtype: pilCtx.taskType ?? "none",
761
- durationMs: pilDurationMs,
762
- data: {
763
- userMsgSha8: _userMsgSha8,
764
- userMsgPreview: userMessage.slice(0, 60),
765
- layers: pilCtx.layers?.filter((l) => l.applied).map((l) => l.name) ?? [],
766
- fullLayers: pilCtx.layers?.map((l) => ({ name: l.name, applied: l.applied, delta: l.delta })) ?? [],
767
- layerCount: pilCtx.layers?.length ?? 0,
768
- layerTimings: pilCtx.metrics?.layerTimings ?? null,
769
- domain: pilCtx.domain,
770
- confidence: pilCtx.confidence,
771
- outputStyle: pilCtx.outputStyle,
772
- intentKind: pilCtx.intentKind ?? null,
773
- mcpSkipped: isChitchat,
774
- fallbackReason: pilCtx.fallbackReason ?? null,
775
- eeMode: (await import("../ee/client-mode.js")).getCachedEEClientMode()?.mode ?? "unknown",
776
- },
777
- });
778
- logInteraction(deps.session.id, "user_message", {
779
- data: {
780
- raw_length: userMessage.length,
781
- enriched_length: enrichedMessage.length,
782
- taskType: pilCtx.taskType,
783
- intentKind: pilCtx.intentKind ?? null,
784
- confidence: pilCtx.confidence,
785
- pilActive: pilCtx.taskType !== null,
786
- },
787
- });
788
- }
789
- } catch {
790
- /* fail-open */
791
- }
792
-
793
- // ROUTE-11: Per-turn model routing via decide() — picks cheapest capable model
794
- const turnStartMs = Date.now();
795
- let turnModelId = deps.modelId;
796
- let taskHash: string | null = null;
797
- const _routeStart = Date.now();
798
- try {
799
- const { decide } = await import("../router/decide.js");
800
- const routeDecision = await decide(userMessage, {
801
- tenantId: "local",
802
- cwd: deps.bash.getCwd(),
803
- defaultModel: deps.modelId,
804
- defaultProvider: deps.providerId,
805
- pil: {
806
- domain: pilCtx.domain,
807
- taskType: pilCtx.taskType,
808
- confidence: pilCtx.confidence,
809
- gsdPhase: pilCtx.gsdPhase ?? null,
810
- activeRunId: pilCtx.activeRunId ?? null,
811
- recentTurnsSummary: deps.buildRecentTurnsSummary(),
812
- projectSize: deps.estimateProjectSize(),
813
- filesTouched: deps.countFilesTouched(),
814
- mode: deps.mode,
815
- },
816
- });
817
- if (routeDecision.model && routeDecision.model !== "HALT") {
818
- // Respect user's default model when it has a vision proxy and the
819
- // current turn (or history) has images — the proxy will convert
820
- // images to text, so there's no need to switch to a vision-capable
821
- // (and usually pricier / rate-limited) model.
822
- const defaultHasVisionProxy = needsVisionProxy(deps.modelId);
823
- const historyHasImages = deps.messages.some(
824
- (m) => Array.isArray(m.content) && (m.content as Array<{ type: string }>).some((p) => p.type === "image"),
825
- );
826
- const turnHasImages = (images?.length ?? 0) > 0;
827
- const skipVisionRoute = defaultHasVisionProxy && (turnHasImages || historyHasImages);
828
- if (!skipVisionRoute) {
829
- turnModelId = routeDecision.model;
830
- }
831
- }
832
- taskHash = routeDecision.taskHash ?? null;
833
- // Update status bar with router switch info. Also reset back to the
834
- // session default when the router does NOT switch on this turn —
835
- // otherwise the bar stays "stuck" showing the previously-routed model
836
- // (e.g. claude-sonnet-4-6) on later turns that actually run on the
837
- // user's chosen default (e.g. deepseek-v4-flash).
838
- if (turnModelId !== deps.modelId) {
839
- statusBarStore.setState({ routed_from: deps.modelId, model: turnModelId });
840
- } else {
841
- const prev = statusBarStore.getState();
842
- if (prev.routed_from || prev.model !== deps.modelId) {
843
- statusBarStore.setState({ routed_from: null, model: deps.modelId });
844
- }
845
- }
846
- if (_debugOn) {
847
- _debugSteps.push({
848
- name: "Router",
849
- duration_ms: Date.now() - _routeStart,
850
- input_summary: `default=${deps.modelId}`,
851
- output_summary: turnModelId !== deps.modelId ? `routed→${turnModelId}` : `kept ${turnModelId}`,
852
- });
853
- }
854
- } catch {
855
- // Router unavailable — use session default model (skip if provider is disabled)
856
- if (!isProviderDisabled(deps.providerId as ProviderId)) {
857
- const eeRoute = await routeModel(userMessage, {}, deps.providerId).catch(() => null);
858
- taskHash = eeRoute?.taskHash ?? null;
859
- }
860
- }
861
-
862
- // Interaction log: model routing
863
- try {
864
- if (deps.session) {
865
- logInteraction(deps.session.id, "routing", {
866
- model: turnModelId,
867
- data: {
868
- defaultModel: deps.modelId,
869
- routedModel: turnModelId,
870
- taskHash,
871
- pilTaskType: pilCtx.taskType ?? null,
872
- pilIntentKind: pilCtx.intentKind ?? null,
873
- },
874
- });
875
- }
876
- } catch {
877
- /* fail-open */
878
- }
879
-
880
- // Re-detect provider if router picked a model from a different provider
881
- const turnProviderId = detectProviderForModel(turnModelId);
882
- let turnProvider: LegacyProvider;
883
- if (turnProviderId !== deps.providerId) {
884
- // Even if the key is reachable, skip disabled providers
885
- const turnKey = !isProviderDisabled(turnProviderId as ProviderId)
886
- ? await loadKeyForProvider(turnProviderId).catch(() => null)
887
- : null;
888
- if (turnKey) {
889
- const { createProviderFactory } = await import("../providers/runtime.js");
890
- turnProvider = createProviderFactory(turnProviderId, { apiKey: turnKey }).factory;
891
- } else {
892
- // Router's provider unreachable or disabled — fall back to a non-disabled provider
893
- const fallback = await deps.councilManager.resolveNonDisabledFallback();
894
- turnModelId = fallback.modelId;
895
- turnProvider = deps.requireProvider();
896
- }
897
- } else if (isProviderDisabled(deps.providerId as ProviderId)) {
898
- // Session provider is disabled — find a non-disabled alternative
899
- const fallback = await deps.councilManager.resolveNonDisabledFallback();
900
- turnModelId = fallback.modelId;
901
- turnProvider = deps.requireProvider();
902
- } else {
903
- turnProvider = deps.requireProvider();
904
- }
905
-
906
- // E4: prepend one-shot cwd note when setCwd() changed the working directory
907
- // mid-session. Clears after injection so only the first subsequent turn sees it.
908
- const cwdNote = deps.getPendingCwdNote();
909
- deps.setPendingCwdNote(null);
910
- const messageForModel = cwdNote ? `${cwdNote}\n\n${enrichedMessage}` : enrichedMessage;
911
-
912
- let userModelMessage: ModelMessage;
913
- if (images?.length) {
914
- const parts: Array<{ type: "text"; text: string } | { type: "image"; image: string; mediaType: string }> = [
915
- { type: "text", text: messageForModel },
916
- ];
917
- for (const img of images) {
918
- parts.push({ type: "image", image: img.base64, mediaType: img.mediaType });
919
- }
920
- userModelMessage = { role: "user", content: parts };
921
- } else {
922
- userModelMessage = { role: "user", content: messageForModel };
923
- }
924
-
925
- // Vision proxy: convert images to text for models that don't support vision.
926
- // Process BOTH the current user message and any historical messages that
927
- // still carry image parts — otherwise sending the conversation back to a
928
- // text-only provider (e.g. DeepSeek) fails with "unknown variant
929
- // `image_url`" once history contains an image from a prior turn.
930
- if (needsVisionProxy(turnModelId)) {
931
- const historyHasImages = deps.messages.some(
932
- (m) => Array.isArray(m.content) && (m.content as Array<{ type: string }>).some((p) => p.type === "image"),
933
- );
934
- const turnHasImages = (images?.length ?? 0) > 0;
935
- if (turnHasImages || historyHasImages) {
936
- try {
937
- if (historyHasImages) {
938
- const historyResult = await proxyVision(deps.messages, turnModelId, signal);
939
- if (historyResult.proxied) {
940
- deps.setMessages(historyResult.messages);
941
- yield {
942
- type: "content",
943
- content: `[Vision proxy: ${historyResult.imageCount} historical image(s) → text]\n`,
944
- };
945
- }
946
- }
947
- if (turnHasImages) {
948
- const proxyResult = await proxyVision([userModelMessage], turnModelId, signal);
949
- if (proxyResult.proxied) {
950
- userModelMessage = proxyResult.messages[0];
951
- yield {
952
- type: "content",
953
- content: `[Vision proxy: ${proxyResult.imageCount} image(s) → ${turnModelId} via SiliconFlow]\n`,
954
- };
955
- }
956
- }
957
- } catch {
958
- yield { type: "content", content: "[Vision proxy: failed, images dropped]\n" };
959
- if (turnHasImages) {
960
- userModelMessage = { role: "user", content: enrichedMessage };
961
- }
962
- // Strip image parts from history as a last-resort fallback so the
963
- // request doesn't blow up at the provider serialization layer.
964
- deps.setMessages(
965
- deps.messages.map((m) => {
966
- if (!Array.isArray(m.content)) return m;
967
- const filtered = (m.content as Array<{ type: string }>).filter((p) => p.type !== "image");
968
- return { ...m, content: filtered } as typeof m;
969
- }),
970
- );
971
- }
972
- }
973
- }
974
-
975
- deps.messages.push(userModelMessage);
976
- // Phase A5 — write-ahead the user row so `recordUsage` mid-stream can
977
- // attribute usage to a real `message_seq` instead of falling back to
978
- // NULL (or to the previous turn's assistant seq for a session that has
979
- // multi-turn history). The post-stream `appendCompletedTurn(...)` path
980
- // upserts the same row to `status='completed'` via the
981
- // `ON CONFLICT(session_id, seq) DO UPDATE` clause in `appendMessages`.
982
- let userWriteAheadSeq: number | null = null;
983
- if (deps.session) {
984
- try {
985
- userWriteAheadSeq = getNextMessageSequence(deps.session.id);
986
- persistMessageWriteAhead(deps.session.id, userWriteAheadSeq, "user", JSON.stringify(userModelMessage));
987
- } catch {
988
- // Fail-open: if seq lookup throws, fall back to the legacy NULL
989
- // path. The forensics anomaly returns but the turn proceeds.
990
- userWriteAheadSeq = null;
991
- }
992
- }
993
- deps.messageSeqs.push(userWriteAheadSeq);
994
-
995
- // Inject accumulated EE session guidance as a system message so the model
996
- // is informed of past warnings before making tool decisions this turn.
997
- if (deps.sessionEEGuidance.size > 0) {
998
- const lines = Array.from(deps.sessionEEGuidance.entries()).map(([, g]) => {
999
- const pct = Math.round(g.confidence * 100);
1000
- return `- [${g.toolName}] ${g.message} (Why: ${g.why}) [${pct}%]`;
1001
- });
1002
- deps.messages.push({
1003
- role: "system",
1004
- content: `[EE Session Guidance — avoid these patterns when using tools]\n${lines.join("\n")}`,
1005
- });
1006
- deps.messageSeqs.push(null);
1007
- }
1008
-
1009
- const provider = turnProvider;
1010
- const subagents = loadValidSubAgents();
1011
- const _pilResponseTools = getResponseToolSet(pilCtx, deps.providerId);
1012
- const _hasResponseTools = Object.keys(_pilResponseTools).length > 0;
1013
- const systemParts = buildSystemPromptParts(
1014
- deps.bash.getCwd(),
1015
- deps.mode,
1016
- deps.bash.getSandboxMode(),
1017
- deps.getPlanContext(),
1018
- subagents,
1019
- deps.bash.getSandboxSettings(),
1020
- deps.providerId,
1021
- deps.getResumeDigest(),
1022
- { chitchat: isChitchat },
1023
- );
1024
- if (deps.getResumeDigest()) deps.setResumeDigest(null);
1025
- // Skip vision/playwright guidance unless the user's message has a URL
1026
- // or browser/screenshot vocabulary. ~400 tokens of routing hints
1027
- // the model only needs when it might call a browser MCP.
1028
- const _browserGuidanceNeeded =
1029
- /https?:\/\/\S+|\b(screenshot|browser|playwright|chrome|figma|canva|render|webpage|website|url|hyperlink|navigate|click|scrape)\b/i.test(
1030
- userMessage,
1031
- );
1032
- const playwrightGuidance = isChitchat || !_browserGuidanceNeeded ? "" : getVisionGuidanceForTextOnly(turnModelId);
1033
- const system = applyModelConstraints(
1034
- applyPilSuffix(
1035
- `${systemParts.staticPrefix}${playwrightGuidance}${systemParts.dynamicSuffix}`,
1036
- pilCtx,
1037
- _hasResponseTools,
1038
- ),
1039
- turnModelId,
1040
- );
1041
- let runtime = resolveModelRuntime(provider, turnModelId);
1042
- let modelInfo = runtime.modelInfo;
1043
-
1044
- // SAMR: Step-Aware Model Routing — downgrade to fast model for tool-execution
1045
- // steps after the initial reasoning step. The premium model decides WHAT to do;
1046
- // a cheaper model handles the mechanical "read results, call more tools" loop.
1047
- const stepRouterCfg = getStepRouterConfig();
1048
- const stepRouterDecision = decideStepRouting(turnModelId, deps.providerId, stepRouterCfg);
1049
- let stepRouterPhase: "phase1" | "phase2" | "done" = stepRouterDecision.phase2ModelId ? "phase1" : "done";
1050
- const phase2Runtime = stepRouterDecision.phase2ModelId
1051
- ? resolveModelRuntime(provider, stepRouterDecision.phase2ModelId)
1052
- : null;
1053
- if (stepRouterDecision.phase2ModelId && _debugOn) {
1054
- _debugSteps.push({
1055
- name: "StepRouter",
1056
- duration_ms: 0,
1057
- input_summary: `phase1=${turnModelId}`,
1058
- output_summary: stepRouterDecision.reason,
1059
- });
1060
- }
1061
-
1062
- deps.setPlanContext(null);
1063
- let attemptedOverflowRecovery = false;
1064
- // Stream-retry state: track how many transient retries have been attempted
1065
- // for the current turn. Reset to 0 on each new user turn (we're in processMessage).
1066
- let streamRetryCount = 0;
1067
- const MAX_STREAM_RETRIES = 2; // 3 total attempts = 1 first try + 2 retries
1068
- // Re-steer budget for a tool-call emitted as plain text (wrong dialect). One
1069
- // corrective retry: if the model still emits text instead of invoking the
1070
- // tool, we surface the warning and stop rather than loop. Loop-persistent so
1071
- // a model that degrades every step can't burn unbounded re-steers.
1072
- let textToolReSteerCount = 0;
1073
- const MAX_TEXT_TOOL_RESTEER = 1;
1074
- // Silent-hang guard: set true when the stall watchdog aborts a stuck stream.
1075
- // Reset before each streamText attempt; read in the stream catch to surface a
1076
- // clear toast and SKIP the transient-retry (a stalled provider just stalls
1077
- // again, wasting another full timeout of silence).
1078
- let stallTriggered = false;
1079
-
1080
- // Auto-council: route to multi-model debate when EITHER
1081
- // (a) PIL classified taskType=plan|analyze with high confidence AND the
1082
- // prompt is complex enough to justify the debate cost, OR
1083
- // (b) GSD-native tier === "heavy" (wholesale / multi-step / cross-repo work).
1084
- // After the debate finishes, runCouncilV2 records synthesis on
1085
- // councilManager.lastSynthesis; we then re-enter processMessage with the synthesis
1086
- // as the next user turn so the main loop continues with full debate context.
1087
- // Skip if this is already a council continuation turn (prevent infinite recursion).
1088
- //
1089
- // Phase 5 BUG-I (session f1a2a2a547db) — the gate previously fired on
1090
- // taskType=analyze + conf≥0.85 alone, with no complexity check. Result:
1091
- // "improve test coverage cho src/X.ts" (single-file, scoreComplexity=low,
1092
- // score=2) sank 13 minutes into council debate, then halted on pattern-loop
1093
- // after sprint 1 read 6 files. The complexity gate below bypasses council
1094
- // for low-complexity analyze prompts — they get the hot-path direct exec
1095
- // and stay productive. `plan` keeps the old behaviour (architectural
1096
- // decisions deserve debate regardless of length).
1097
- const autoCouncilTypes = new Set(["plan", "analyze"]);
1098
- const councilRoles = getRoleModels();
1099
- const configuredRoleCount = Object.values(councilRoles).filter(Boolean).length;
1100
- const heavyTier = (pilCtx as { complexityTier?: string | null }).complexityTier === "heavy";
1101
- const autoCouncilConfidence = getAutoCouncilConfidence();
1102
- const autoCouncilMinRoles = getAutoCouncilMinRoles();
1103
- const _complexityFromTrace = (pilCtx as { _intentTrace?: { complexity?: "low" | "medium" | "high" } })._intentTrace
1104
- ?.complexity;
1105
- const _complexityGatePassed =
1106
- pilCtx.taskType === "plan" || _complexityFromTrace === undefined || _complexityFromTrace !== "low";
1107
- const taskTypeMatch =
1108
- pilCtx.taskType &&
1109
- autoCouncilTypes.has(pilCtx.taskType) &&
1110
- pilCtx.confidence >= autoCouncilConfidence &&
1111
- _complexityGatePassed;
1112
- const shouldAutoCouncil =
1113
- !deps.councilManager.isContinuation &&
1114
- isAutoCouncilEnabled() &&
1115
- configuredRoleCount >= autoCouncilMinRoles &&
1116
- (taskTypeMatch || heavyTier);
1117
-
1118
- // Always log the auto-council decision (taken or skipped) with the gate
1119
- // values that decided it. Lets reports answer "why did this turn cost
1120
- // $0.30?" and "is the confidence floor tuned wrong for my prompts?".
1121
- const autoCouncilSkipReason = (() => {
1122
- if (deps.councilManager.isContinuation) return "continuation-turn";
1123
- if (!isAutoCouncilEnabled()) return "feature-disabled";
1124
- if (configuredRoleCount < autoCouncilMinRoles)
1125
- return `role-count<${autoCouncilMinRoles} (have ${configuredRoleCount})`;
1126
- if (!taskTypeMatch && !heavyTier) {
1127
- if (!pilCtx.taskType || !autoCouncilTypes.has(pilCtx.taskType))
1128
- return `taskType=${pilCtx.taskType ?? "null"} not in plan|analyze`;
1129
- if (pilCtx.confidence < autoCouncilConfidence)
1130
- return `confidence<${autoCouncilConfidence} (got ${pilCtx.confidence.toFixed(2)})`;
1131
- if (!_complexityGatePassed)
1132
- return `complexity=low + taskType=${pilCtx.taskType} (analyze needs medium+; plan bypasses gate)`;
1133
- return "no-trigger";
1134
- }
1135
- return "taken";
1136
- })();
1137
- appendDecisionLog({
1138
- ts: Date.now(),
1139
- sessionId: deps.session?.id ?? null,
1140
- kind: "auto-council",
1141
- taken: shouldAutoCouncil,
1142
- reason: autoCouncilSkipReason,
1143
- meta: {
1144
- taskType: pilCtx.taskType ?? null,
1145
- confidence: pilCtx.confidence,
1146
- complexityTier: (pilCtx as { complexityTier?: string | null }).complexityTier ?? null,
1147
- complexityScore: _complexityFromTrace ?? null,
1148
- complexityGatePassed: _complexityGatePassed,
1149
- configuredRoleCount,
1150
- autoCouncilConfidence,
1151
- autoCouncilMinRoles,
1152
- heavyTier,
1153
- isContinuation: deps.councilManager.isContinuation,
1154
- },
1155
- }).catch(() => undefined);
1156
-
1157
- if (shouldAutoCouncil) {
1158
- const reason = heavyTier
1159
- ? `complexity=heavy${pilCtx.taskType ? ` task=${pilCtx.taskType}` : ""}`
1160
- : `${pilCtx.taskType} task detected with ${(pilCtx.confidence * 100).toFixed(0)}% confidence`;
1161
- yield { type: "content", content: `\n[Auto-council triggered: ${reason}]\n` };
1162
- yield* deps.runCouncilV2(userMessage, { skipClarification: true, observer, userModelMessage });
1163
- const synthesis = deps.councilManager.lastSynthesis;
1164
- deps.councilManager.setLastSynthesis(null);
1165
- if (synthesis) {
1166
- yield { type: "content", content: "\n[Auto-continuing with council recommendations...]\n" };
1167
- deps.councilManager.setContinuation(true);
1168
- try {
1169
- yield* deps.processMessage(
1170
- `Council debate completed. Synthesis:\n\n${synthesis}\n\nProceed with the recommended action items.`,
1171
- observer,
1172
- );
1173
- } finally {
1174
- deps.councilManager.setContinuation(false);
1175
- }
1176
- }
1177
- return;
1178
- }
1179
-
1180
- if (deps.batchApi) {
1181
- try {
1182
- yield* deps.processMessageBatchTurn({
1183
- userModelMessage,
1184
- observer,
1185
- provider,
1186
- subagents,
1187
- system,
1188
- runtime,
1189
- modelInfo,
1190
- signal,
1191
- });
1192
- } finally {
1193
- if (deps.getAbortController()?.signal === signal) {
1194
- deps.setAbortController(null);
1195
- }
1196
- }
1197
- return;
1198
- }
1199
-
1200
- try {
1201
- while (true) {
1202
- // SAMR Phase 2: switch to fast model for tool-execution steps
1203
- if (stepRouterPhase === "phase2" && phase2Runtime) {
1204
- runtime = phase2Runtime;
1205
- modelInfo = runtime.modelInfo;
1206
- }
1207
-
1208
- deps.setCompactedThisTurn(false);
1209
- let assistantText = "";
1210
- // Tracks where `assistantText` was at the previous step boundary so
1211
- // `onStepFinish` can compute the text emitted within the just-finished
1212
- // step (input to the self-repetition detector).
1213
- let _assistantTextAtLastStep = 0;
1214
- let reasoningPreview = "";
1215
- let encryptedReasoningHidden = false;
1216
- let streamOk = false;
1217
- let closeMcp: (() => Promise<void>) | undefined;
1218
- let stepNumber = -1;
1219
- const activeToolCalls: ToolCall[] = [];
1220
- // Capped digest of tool outputs gathered this attempt — fuels the
1221
- // best-effort answer rescue if the stream stalls mid-turn (see
1222
- // stall-rescue.ts). Reset per attempt; only the most recent results win.
1223
- const turnToolResults: StallToolResult[] = [];
1224
- // SAMR: track whether Phase 1 produced tool calls
1225
- let phase1HadToolCalls = false;
1226
-
1227
- try {
1228
- const settings = attemptedOverflowRecovery
1229
- ? relaxCompactionSettings(deps.getCompactionSettings(modelInfo?.contextWindow))
1230
- : deps.getCompactionSettings(modelInfo?.contextWindow);
1231
- if (modelInfo?.contextWindow) {
1232
- await deps.compactForContext(
1233
- provider,
1234
- system,
1235
- modelInfo.contextWindow,
1236
- signal,
1237
- settings,
1238
- attemptedOverflowRecovery,
1239
- );
1240
- }
1241
-
1242
- // Vision-tool gate: for vision-proxy (text-only) models the registry
1243
- // adds 3 image tools (~500-700 tok) on every turn. Drop them when the
1244
- // turn has no plausible image involvement. Bias is KEEP — retained on
1245
- // any image signal, attachment, cached image, or prior-tool turn.
1246
- const includeVisionTools = visionToolsNeeded({
1247
- userMessage,
1248
- messages: deps.messages as unknown[],
1249
- cachedImageCount: listCachedImages().length,
1250
- priorTurnHadTools: (deps.messages as Array<{ role?: string }>).some((m) => m?.role === "tool"),
1251
- });
1252
- const baseToolsRaw = createBuiltinTools(deps.bash, deps.mode, {
1253
- runTask: (request, abortSignal) => deps.runTask(request, combineAbortSignals(signal, abortSignal)),
1254
- runDelegation: (request, abortSignal) =>
1255
- deps.runDelegation(request, combineAbortSignals(signal, abortSignal)),
1256
- readDelegation: (id) => deps.readDelegation(id),
1257
- listDelegations: () => deps.listDelegations(),
1258
- modelId: turnModelId,
1259
- includeVisionTools,
1260
- });
1261
- // Top-level cumulative cap state. We accumulate the raw tool set
1262
- // (base + MCP + PIL response tools) across the assembly below,
1263
- // then apply the cap once. Tier ratios are looser than the
1264
- // sub-agent cap (50%/80%) so casual single-tool turns are not
1265
- // trimmed. See sub-agent-cap.ts.
1266
- // Chitchat: drop builtin tools too (not just MCP). A 1-word greeting
1267
- // never needs bash/read_file/edit_file/grep — those schemas alone
1268
- // cost ~1.5K input tokens on this CLI. Falls back to baseTools for
1269
- // every non-chitchat turn (PIL gates conservatively).
1270
- //
1271
- // BUG-A guard — when prior turns already issued tool_calls (their
1272
- // results still live in the messages history), DROPPING tools on a
1273
- // continuation chitchat ("tiếp tục" / "continue") causes two
1274
- // failures: (1) DeepSeek goes into native DSML markup fallback
1275
- // because it sees tool-call history but no schema (visible in
1276
- // sessions 002df4014cb4 + fc19b4daee20); (2) the agent has no way
1277
- // to actually CONTINUE the prior task — the user's clear intent.
1278
- // Detect prior-tool-context and keep the base tool set in that
1279
- // case. The 1.5K token saving for true greetings (no prior tool
1280
- // history) is preserved.
1281
- const turnCaps = getProviderCapabilities(requireRuntimeProvider(runtime));
1282
- const _priorTurnHadTools = (deps.messages as Array<{ role?: string }>).some((m) => m?.role === "tool");
1283
- let rawToolSet: ToolSet = !turnCaps.supportsClientTools(runtime.modelInfo)
1284
- ? {}
1285
- : isChitchat && !_priorTurnHadTools
1286
- ? {}
1287
- : baseToolsRaw;
1288
- // MCP skip: chitchat / greeting inputs don't need 7 MCP servers'
1289
- // worth of tool schemas (~20K input tokens). PIL Layer 1 already
1290
- // gates this conservatively (≤10 chars + ≤2 words OR brain "none").
1291
- if (
1292
- deps.mode === "agent" &&
1293
- (!isChitchat || _priorTurnHadTools) &&
1294
- turnCaps.supportsClientTools(runtime.modelInfo)
1295
- ) {
1296
- // Smart MCP filter: drop OPTIONAL MCP servers whose category the
1297
- // current message gives no signal for. Browser/vision servers
1298
- // (Playwright/Chrome/Figma/Canva) skip unless the message touches a
1299
- // page; docs/web servers (context7/fetch) skip unless the message
1300
- // looks like an external lookup. Each MCP contributes 8-15 tools at
1301
- // ~150 tok each, so local code work — the majority of turns — saves
1302
- // ~13K input tokens it would otherwise pay every turn. Domain
1303
- // servers (filesystem/tools/harness) always pass through. Logic is
1304
- // a pure helper (src/mcp/smart-filter.ts) so it is unit-tested.
1305
- // Override with MUONROI_DISABLE_SMART_MCP=1.
1306
- const filteredServers = filterMcpServersByMessage(loadMcpServers(), userMessage, {
1307
- disabled: process.env.MUONROI_DISABLE_SMART_MCP === "1",
1308
- });
1309
- // MCP non-blocking: race the build against a 2500ms cap so a slow
1310
- // stdio MCP server spawn (or many optional servers) does not block
1311
- // the main turn's first token / streamText indefinitely. On timeout
1312
- // or error we fall back to builtins only (domain servers like fs/tools
1313
- // are still valuable but the optional ones can be skipped for this turn).
1314
- let mcpBundle: any = null;
1315
- try {
1316
- mcpBundle = await Promise.race([
1317
- buildMcpToolSet(filteredServers, {
1318
- onOAuthRequired: (_serverId, url) => {
1319
- const urlStr = url.toString();
1320
- import("child_process").then(({ exec }) => {
1321
- const cmd =
1322
- process.platform === "win32"
1323
- ? `start "" "${urlStr}"`
1324
- : process.platform === "darwin"
1325
- ? `open "${urlStr}"`
1326
- : `xdg-open "${urlStr}"`;
1327
- exec(cmd);
1328
- });
1329
- },
1330
- }),
1331
- new Promise((_, reject) => setTimeout(() => reject(new Error("MCP build timeout (2500ms)")), 2500)),
1332
- ]);
1333
- } catch (err) {
1334
- console.error("[MCP] buildMcpToolSet timed out or failed, proceeding with builtins only", err);
1335
- }
1336
- if (mcpBundle) {
1337
- closeMcp = mcpBundle.close;
1338
- // Drop filesystem-MCP read/write/edit tools that duplicate the
1339
- // first-class builtin file tools. Without this, models re-read the
1340
- // SAME file via both `read_file` and `mcp_filesystem__read_text_file`
1341
- // (live grok session f5dfab0ce0ca: a 772-line file read 6×), wasting
1342
- // ~150 tok/schema PLUS re-injecting whole files into context. The
1343
- // builtins are strictly better (read-before-write, LSP, CRLF match,
1344
- // dedup/read-budget wrappers). Non-duplicate fs tools are untouched.
1345
- const _builtinToolNames = new Set(Object.keys(rawToolSet));
1346
- const { tools: _dedupedMcpTools, dropped: _droppedFsMcp } = dropRedundantFsMcpTools(
1347
- mcpBundle.tools,
1348
- _builtinToolNames,
1349
- );
1350
- rawToolSet = { ...rawToolSet, ..._dedupedMcpTools };
1351
- if (_droppedFsMcp.length > 0 && deps.session) {
1352
- try {
1353
- logInteraction(deps.session.id, "routing", {
1354
- model: turnModelId,
1355
- data: { droppedRedundantFsMcp: _droppedFsMcp },
1356
- });
1357
- } catch {
1358
- /* telemetry best-effort */
1359
- }
1360
- }
1361
- if (mcpBundle.errors.length > 0) {
1362
- yield { type: "content", content: `MCP unavailable: ${mcpBundle.errors.join(" | ")}\n\n` };
1363
- }
1364
- }
1365
- }
1366
-
1367
- // PIL response tools: inject structured output tool when taskType detected
1368
- if (_hasResponseTools && turnCaps.supportsClientTools(runtime.modelInfo)) {
1369
- rawToolSet = { ...rawToolSet, ..._pilResponseTools };
1370
- captureToolSchemas(_pilResponseTools);
1371
- }
1372
-
1373
- // Apply the top-level cumulative cap once over the fully-assembled
1374
- // raw tool set. State is per-turn; each turn gets a fresh budget.
1375
- const topLevelCap = wrapToolSetWithCap(rawToolSet, {
1376
- maxCumulativeChars: getTopLevelToolBudgetChars(),
1377
- midTierRatio: 0.5,
1378
- highTierRatio: 0.8,
1379
- label: "top-level",
1380
- });
1381
- // Phase C3: layer cross-turn dedup on top of the top-level cap.
1382
- const tools: ToolSet = wrapToolSetWithReadBudget(
1383
- wrapToolSetWithDedup(topLevelCap.tools, deps.crossTurnDedup),
1384
- deps.readBudget,
1385
- );
1386
- captureToolSchemas(tools);
1387
- let responseToolCalled = false;
1388
- // A turn must surface exactly ONE final structured answer. Cheap
1389
- // models sometimes emit the response tool MORE THAN ONCE in a single
1390
- // step (session 9b1b39bf4dc6: grok emitted respond_general twice —
1391
- // a 278-char "I must read the code" hedge, then the 3782-char real
1392
- // answer — both in one step). Yielding each inline appends two
1393
- // stacked structured_response blocks and shows the hedge first.
1394
- // Instead we BUFFER the response-tool payloads and yield only the
1395
- // most complete one (longest serialized data) after the stream
1396
- // drains — robust to either ordering (hedge-then-answer or
1397
- // answer-then-summary).
1398
- let _pendingStructuredResponse: { taskType: string; data: Record<string, unknown> } | null = null;
1399
- let _pendingStructuredResponseLen = -1;
1400
- let _responseToolEmitCount = 0;
1401
-
1402
- // G3: providerOptions assembly is owned by the capability layer
1403
- // (src/providers/capabilities.ts). buildTurnProviderOptions feeds
1404
- // sessionId in so openai.promptCacheKey is derived per turn.
1405
- // The task-type-driven anthropic.thinking budget override stays
1406
- // here because it depends on PIL task context, not provider quirks.
1407
- // biome-ignore lint/suspicious/noExplicitAny: matches RuntimeResult.providerOptions shape (any) used downstream
1408
- const baseProviderOpts: any = buildTurnProviderOptions(runtime, { sessionId: deps.session?.id }) ?? {};
1409
- const providerOpts = runtime.modelInfo?.reasoning
1410
- ? {
1411
- ...baseProviderOpts,
1412
- anthropic: {
1413
- ...(baseProviderOpts.anthropic ?? {}),
1414
- thinking: {
1415
- type: "enabled" as const,
1416
- budgetTokens:
1417
- taskTypeToReasoningEffort(pilCtx.taskType) === "high"
1418
- ? 32_768
1419
- : taskTypeToReasoningEffort(pilCtx.taskType) === "medium"
1420
- ? 8_192
1421
- : 2_048,
1422
- },
1423
- },
1424
- }
1425
- : baseProviderOpts;
1426
- // Use catalog's thinkingType field instead of regex matching.
1427
- // providerOpts is loosely typed (Record<string, unknown>) after the
1428
- // g1 capability refactor — narrow with a local typed view.
1429
- const thinkingModelInfo = getModelInfo(runtime.modelId);
1430
- const providerOptsAnyView = providerOpts as {
1431
- anthropic?: { thinking?: { type?: string } };
1432
- };
1433
- if (
1434
- providerOptsAnyView.anthropic?.thinking?.type === "enabled" &&
1435
- thinkingModelInfo?.thinkingType === "adaptive"
1436
- ) {
1437
- providerOptsAnyView.anthropic.thinking = { type: "adaptive" as unknown as "enabled" };
1438
- }
1439
-
1440
- // OpenAI api-key path: `store: true` is seeded by OpenAIStrategy
1441
- // via factory.defaultProviderOptions (Phase 12.2-G4 migration).
1442
- // OAuth backend (ChatGPT Codex) overrides with `store: false` via
1443
- // the auth registry. Both flow through resolveModelRuntime →
1444
- // runtime.providerOptions → buildTurnProviderOptions and arrive
1445
- // here merged into providerOpts.openai.
1446
- // Top-level dropParam — shared with sub-agent path via shouldDropParam.
1447
- // See src/providers/runtime.ts for the central rule.
1448
- const dropParam = (p: "maxOutputTokens" | "temperature" | "topP"): boolean => shouldDropParam(runtime, p);
1449
-
1450
- // Tier-aware behavioural suffix. Cheap models (DeepSeek V4 Flash etc.)
1451
- // ignore well-worded tool descriptions but DO adopt instructions when
1452
- // surfaced in the system prompt. Smart models don't need this — gated
1453
- // by `modelInfo.tier === "fast"`. See cheap-model-playbook.ts for
1454
- // motivation + escape hatch (MUONROI_DISABLE_CHEAP_MODEL_PLAYBOOK=1).
1455
- // Fast-tier steering, front-loaded for primacy: task convergence
1456
- // workbook (anti-ramble — cuts tool-call count, the dominant
1457
- // cheap-model cost) layered UNDER the tool-use playbook so the
1458
- // CRITICAL tool rules stay at the very front. Both fixed per turn, so
1459
- // they stay inside the cached prefix.
1460
- const systemWithWorkbook = shouldInjectCheapModelWorkbook(runtime.modelInfo)
1461
- ? injectCheapModelWorkbook(system, pilCtx.taskType)
1462
- : system;
1463
- const systemWithPlaybook = shouldInjectCheapModelPlaybook(runtime.modelInfo)
1464
- ? injectCheapModelPlaybook(systemWithWorkbook)
1465
- : systemWithWorkbook;
1466
- // A2: front-load a one-line shell/env directive for fast-tier models.
1467
- // The authoritative ENVIRONMENT block already states OS/shell/cwd in
1468
- // the prompt body, but budget models underweight non-front-loaded
1469
- // rules — so echo the correct-syntax line at the very front. Derived
1470
- // from resolveShell({}) (same source as buildEnvironmentBlock) so it
1471
- // is always accurate to the actual shell the bash tool will spawn.
1472
- // Gated to fast tier, so the claude branch below still sees `system`.
1473
- const systemWithShell = shouldInjectCheapModelPlaybook(runtime.modelInfo)
1474
- ? injectCheapModelShellDirective(
1475
- systemWithPlaybook,
1476
- cheapModelShellLine(resolveShell({}).kind, process.platform),
1477
- )
1478
- : systemWithPlaybook;
1479
-
1480
- const systemForModel = runtime.modelId.startsWith("claude")
1481
- ? [
1482
- {
1483
- role: "system" as const,
1484
- content: systemParts.staticPrefix,
1485
- providerOptions: { anthropic: { cacheControl: { type: "ephemeral" as const } } },
1486
- },
1487
- {
1488
- role: "system" as const,
1489
- content: systemWithShell.slice(systemParts.staticPrefix.length),
1490
- },
1491
- ]
1492
- : systemWithShell;
1493
-
1494
- // Capture prompt-size breakdown so recordUsage can attach it to the
1495
- // cost-log entry. Without this, "system prompt is huge" is unfalsifiable.
1496
- // chars/4 ≈ tokens for English; reported as chars to keep math obvious.
1497
- const messagesChars = deps.messages.reduce((s, m) => {
1498
- const c = m.content;
1499
- if (typeof c === "string") return s + c.length;
1500
- if (Array.isArray(c)) {
1501
- for (const part of c) {
1502
- if (typeof (part as { text?: unknown }).text === "string") {
1503
- s += (part as { text: string }).text.length;
1504
- }
1505
- }
1506
- }
1507
- return s;
1508
- }, 0);
1509
- let toolsChars = 0;
1510
- let toolsCount = 0;
1511
- for (const [name, t] of Object.entries(tools)) {
1512
- toolsCount += 1;
1513
- toolsChars += name.length;
1514
- const desc = (t as { description?: string }).description;
1515
- if (typeof desc === "string") toolsChars += desc.length;
1516
- try {
1517
- // Schemas often dominate tool size on non-Anthropic providers
1518
- // (Zod-derived JSON schemas can be 2-5K chars per tool).
1519
- const params =
1520
- (t as { parameters?: unknown; inputSchema?: unknown }).parameters ??
1521
- (t as { inputSchema?: unknown }).inputSchema;
1522
- if (params) toolsChars += JSON.stringify(params).length;
1523
- } catch {
1524
- /* best-effort */
1525
- }
1526
- }
1527
- deps.setLastPromptBreakdown({
1528
- systemChars: system.length,
1529
- staticPrefixChars: systemParts.staticPrefix.length,
1530
- dynamicSuffixChars: systemParts.dynamicSuffix.length,
1531
- playwrightGuidanceChars: playwrightGuidance.length,
1532
- messagesChars,
1533
- messagesCount: deps.messages.length,
1534
- toolsChars,
1535
- toolsCount,
1536
- });
1537
-
1538
- // Task 2.6a — assign a fresh correlation ID for this top-level streamText call.
1539
- const _topCallId = crypto.randomUUID();
1540
- deps.setCurrentCallId(_topCallId);
1541
- // Capture finishReason so we can surface "round cap hit" as a visible
1542
- // toast — without this, the agent silently stops mid-flight when
1543
- // stepCountIs(maxToolRounds) fires and the user sees the TUI freeze
1544
- // (session 7dcf8fd7d6a4 hit exactly 100 rounds → looked like a crash).
1545
- let _lastFinishReason: string | null = null;
1546
- // Phase B4: compact older tool_result parts before each top-level
1547
- // step once cumulative message chars exceed the configured threshold.
1548
- // The compactor preserves system + first user verbatim and keeps the
1549
- // last N tool turns intact; older results are rewritten into short
1550
- // stubs. Symmetric to the B3 sub-agent path; reuses the same module
1551
- // with `label: "top-level"` so the stub text reflects which loop
1552
- // elided the content.
1553
- const topLevelCompactThreshold = getTopLevelCompactThresholdChars();
1554
- const topLevelCompactKeepLast = getTopLevelCompactKeepLast();
1555
- // Phase O1 — capture providerOptions SHAPE (types only) for forensics.
1556
- deps.setLastProviderOptionsShape(
1557
- Object.keys(providerOpts).length > 0 ? extractProviderOptionsShape(providerOpts) : null,
1558
- );
1559
- if (wireDebug.enabled) {
1560
- wireDebug.logRequest({
1561
- providerId: runtime.modelInfo?.provider ?? "unknown",
1562
- modelId: runtime.modelId,
1563
- messages: deps.messages as readonly unknown[],
1564
- systemChars: (systemForModel as unknown as { length?: number })?.length ?? 0,
1565
- toolNames: tools ? Object.keys(tools as Record<string, unknown>) : undefined,
1566
- providerOptions: providerOpts,
1567
- });
1568
- }
1569
- // sanitizeHistory is identity for every provider (kept as a hook
1570
- // for future provider-specific quirks). Reasoning round-trips
1571
- // natively via @ai-sdk/openai-compatible — see
1572
- // src/providers/__tests__/reasoning-roundtrip.test.ts.
1573
- const _topMessagesForCall = turnCaps.sanitizeHistory(deps.messages) as typeof deps.messages;
1574
- // Closure-mutable cap for the tool-loop askcard rescue.
1575
- // Phase 1 (SAMR) skips the dynamic cap (it's a single-step path).
1576
- // Algorithm extracted to ./tool-loop-cap.ts so it can be unit-tested.
1577
- const _baseDynamicStopWhen = createToolLoopCapPredicate({
1578
- initialCap: deps.maxToolRounds,
1579
- ask: deps.askToolLoopContinue,
1580
- // Phase 5 BUG-H — thread the resolved natural ceiling down so the
1581
- // pattern askcard can pick a context-aware default action (continue
1582
- // early in the run, stop once we're past 50% of the natural budget).
1583
- naturalCeiling: _naturalCeiling,
1584
- });
1585
- // Phase 4 Plan 04 (4B) — compose per-session ceiling alongside the
1586
- // existing cap + pattern guard. Logical OR: any condition true → halt.
1587
- // Counter is per-SESSION and increments once per stopWhen invocation
1588
- // (i.e. once per finished tool step), persisting across user turns
1589
- // so a wandering 3-turn burst still trips at the matrix limit.
1590
- const _ceilingSessionId = deps.session?.id ?? "no-session";
1591
- // Phase 5 Fix 3 — capture the actual step number when the ceiling
1592
- // trips so the halt toast can report the real value, not the
1593
- // ceiling/ceiling literal that always showed e.g. "5/5" regardless
1594
- // of how many steps the turn actually ran.
1595
- const _ceilingHitAtStep = 0;
1596
- // Phase 5 Fix 5 — matrix ceiling is now a SOFT BOUNDARY, never a
1597
- // hard halt. Phase 4's hard halt was a blunt anti-wandering
1598
- // measure that also blocked legitimate multi-step work: every
1599
- // long task (improve coverage, optimize startup, refactor) ran
1600
- // out of budget mid-flight and required the user to manually
1601
- // type "tiếp tục". Wrong philosophy — "done" must be the agent's
1602
- // call, not the counter's.
1603
- //
1604
- // What replaced the hard halt:
1605
- // - Scope-reminders (4A path, prepareStep above) inject
1606
- // "[approaching ceiling]" reminder at floor(ceiling*0.7) and
1607
- // repeat at K cadence. Past the ceiling, every step gets a
1608
- // re-anchor so the model is repeatedly nudged toward closure.
1609
- // - The dynamicStopWhen no longer checks the matrix ceiling at
1610
- // all. The only halt source is `_baseDynamicStopWhen` which
1611
- // enforces `deps.maxToolRounds` as the ULTIMATE runaway safety
1612
- // net (default raised; see CLI default).
1613
- // - 4R bash repeat detector still catches the dominant wandering
1614
- // pattern (identical command twice in a row).
1615
- // - F6 synthesis still ensures any natural stream-end without
1616
- // text gets a final summary.
1617
- //
1618
- // _ceilingHit and _ceilingHitAtStep are kept for telemetry: a
1619
- // crossing event is logged for forensics, but no action is taken.
1620
- const dynamicStopWhen = (async (state: { steps: ReadonlyArray<unknown> }) => {
1621
- // Terminal response tool: a `respond_*` call IS the model's final
1622
- // structured answer (its `execute` is identity — the payload lives
1623
- // in the tool-call args). `shouldHaltOnResponseTool` decides if the
1624
- // emission is terminal vs a premature "blind" announce:
1625
- // - response tool AFTER real tool work (read/grep/bash) → terminal,
1626
- // halt now (kills d95113d3be09 seq=27: 7 reads → 87× respond loop
1627
- // at call #1, no extra round-trip for the common case).
1628
- // - a single blind response (no prior investigation) → do NOT halt;
1629
- // give the model the step it announced it would use to read code
1630
- // (session e4a9d97a90: lone blind respond_general was force-stopped
1631
- // by the old halt-on-first rule and the agent never investigated).
1632
- // - a 2nd blind response with still no real work → narration loop,
1633
- // halt. In-step spam (80× in one generation) is bounded separately
1634
- // by RESPONSE_TOOL_SPAM_CAP — stopWhen only runs BETWEEN steps.
1635
- // Read from `state.steps` (the SDK's own per-step record) rather than
1636
- // the for-await consumer's `responseToolCalled` flag — stopWhen runs
1637
- // between steps and may evaluate before our consumer processed the
1638
- // tool-result part, so the flag would race.
1639
- const _steps = state.steps as ReadonlyArray<{ toolCalls?: ReadonlyArray<{ toolName?: string }> }>;
1640
- if (shouldHaltOnResponseTool(_steps)) return true;
1641
- const base = await _baseDynamicStopWhen(state);
1642
- if (base) return true;
1643
- const next = incSessionStep(_ceilingSessionId);
1644
- // Telemetry-only: record the first time the counter crosses
1645
- // the matrix ceiling, so post-hoc queries can correlate the
1646
- // ceiling crossing with task completion outcomes. No halt.
1647
- if (next === _stepCeiling) {
1648
- try {
1649
- if (deps.session?.id) {
1650
- logInteraction(deps.session.id, "f6_synthesis", {
1651
- data: {
1652
- outcome: "ceiling_crossed_softly",
1653
- stepAtCrossing: next,
1654
- naturalCeiling: _naturalCeiling,
1655
- taskType: _ceilingTaskType,
1656
- size: _ceilingSize,
1657
- hardCapMaxToolRounds: deps.maxToolRounds,
1658
- },
1659
- });
1660
- }
1661
- } catch {
1662
- /* telemetry only */
1663
- }
1664
- }
1665
- return false;
1666
- }) as unknown as StopCondition<typeof tools>;
1667
- // BUG-A fix — when this turn carries an empty tool set (the
1668
- // chitchat optimization at line ~1107 drops all schemas), AI SDK
1669
- // sends `tools:[], tool_choice:undefined` to the provider. DeepSeek
1670
- // V4 Flash sees prior `tool_call`/`tool_result` parts still in the
1671
- // messages history (the previous turn used 20 tools) and the
1672
- // model stays in agent-mode — but with no schema to call, it
1673
- // falls back to its NATIVE DSML markup syntax and emits that as
1674
- // plain text. AI SDK does not parse the native format, so the
1675
- // markup leaks straight to the TUI as garbage and the turn
1676
- // produces no useful output. Setting `toolChoice:"none"` is the
1677
- // canonical way to tell the model "you cannot call tools this
1678
- // turn" so it emits text-only. Verified by stream_start telemetry
1679
- // on sessions 002df4014cb4 (leak) + fc19b4daee20 (leak): both had
1680
- // toolCount=0 + toolChoice=undefined on chitchat continuation.
1681
- const _toolsAreEmpty = Object.keys(tools as Record<string, unknown>).length === 0;
1682
- const _finalToolChoice: "auto" | "none" | undefined = _toolsAreEmpty
1683
- ? "none"
1684
- : _hasResponseTools && turnCaps.supportsClientTools(runtime.modelInfo)
1685
- ? "auto"
1686
- : undefined;
1687
- // BUG-C telemetry — record tool availability + toolChoice at the
1688
- // call site so future regressions show up in telemetry not in TUI.
1689
- try {
1690
- const _toolNamesAtCall = Object.keys(tools as Record<string, unknown>);
1691
- logInteraction(deps.session?.id ?? "no-session", "stream_start", {
1692
- model: turnModelId,
1693
- data: {
1694
- toolCount: _toolNamesAtCall.length,
1695
- hasBash: _toolNamesAtCall.includes("bash"),
1696
- toolNames: _toolNamesAtCall.slice(0, 25),
1697
- toolChoice: _finalToolChoice ?? "undefined",
1698
- hasResponseTools: _hasResponseTools,
1699
- supportsClientTools: turnCaps.supportsClientTools(runtime.modelInfo),
1700
- priorTurnHadTools: (_topMessagesForCall as Array<{ role?: string }>).some((m) => m?.role === "tool"),
1701
- },
1702
- });
1703
- } catch {
1704
- /* telemetry only */
1705
- }
1706
- // Silent-hang guard: abort the stream (and surface a toast in the
1707
- // catch below) if the provider sends no chunk for too long. Re-armed
1708
- // on every chunk via stall.pet(), so it never kills an actively
1709
- // streaming call. Disposed when the stream ends or errors.
1710
- stallTriggered = false;
1711
- const stall = createStallWatchdog(getProviderStallTimeoutMs(), () => {
1712
- stallTriggered = true;
1713
- });
1714
- const result = streamText({
1715
- model: runtime.model,
1716
- system: systemForModel,
1717
- messages: _topMessagesForCall,
1718
- tools,
1719
- toolChoice: _finalToolChoice,
1720
- stopWhen: stepRouterPhase === "phase1" ? stepCountIs(1) : dynamicStopWhen,
1721
- maxRetries: 0,
1722
- abortSignal: combineAbortSignals(signal, stall.signal),
1723
- // Repair malformed tool-call JSON args before they bubble up as
1724
- // InvalidToolInputError → tool-error → repetition-detector abort.
1725
- // Conservative: only fixes the two observed Qwen-style defects.
1726
- // See src/orchestrator/tool-args-repair.ts for the transforms.
1727
- experimental_repairToolCall: repairToolCallHook,
1728
- prepareStep: ({ stepNumber: sn, messages: stepMessages }) => {
1729
- if (sn < 1) return {};
1730
- const stripped = turnCaps.sanitizeHistory(stepMessages) as typeof stepMessages;
1731
-
1732
- // Agent-controlled veto (PRESERVE) or lighter selective keep (KEEP_TOOL_IDS) for this turn's B4 compaction.
1733
- // PRESERVE_FULL_CONTEXT skips the compactor entirely (full history).
1734
- // KEEP_TOOL_IDS: id1,id2 (from prior stub " (id=...) ") protects only those specific tool results
1735
- // without the cost of a full veto. Parsed from reasoning or assistant note.
1736
- let keepToolIds: string[] = [];
1737
- const hasPreserve = stripped.some((m: any) => {
1738
- const c = m?.content;
1739
- const texts: string[] = [];
1740
- if (typeof c === "string") texts.push(c);
1741
- if (Array.isArray(c)) {
1742
- for (const p of c) if (typeof p?.text === "string") texts.push(p.text);
1743
- }
1744
- const joined = texts.join(" ");
1745
- if (joined.includes("PRESERVE_FULL_CONTEXT")) return true;
1746
- // Idea 3: parse lighter token
1747
- const mKeep = joined.match(/KEEP_TOOL_IDS\s*[:=]\s*([a-z0-9_, -]+)/i);
1748
- if (mKeep) {
1749
- keepToolIds = mKeep[1]
1750
- .split(/[,\s]+/)
1751
- .map((s) => s.trim())
1752
- .filter(Boolean);
1753
- }
1754
- return false;
1755
- });
1756
- if (hasPreserve) {
1757
- return { messages: stripped };
1758
- }
1759
-
1760
- // F2 — envelope = system prompt + JSON-Schema of every tool
1761
- // re-sent on every step. Without this the threshold check
1762
- // ignored 20-50K of fixed prompt overhead and the compactor
1763
- // sat dormant just below its limit while billed input climbed.
1764
- const envelopeChars = computeEnvelopeChars(systemForModel, tools);
1765
- // G1 + G2 — feed the model's context window so the compactor
1766
- // can pick a token-aware threshold and shrink keepLastTurns
1767
- // when the window is approaching its ceiling.
1768
- const contextWindowTokens = runtime.modelInfo?.contextWindow ?? 0;
1769
- // Idea 4: fire-and-forget persist of elided tool outputs to EE (source=tool-artifact)
1770
- // so later layer3/ee.query "tool-artifact id=xxx" or "full tool result id=..." can re-hydrate.
1771
- // Use process-level fallbacks (prepareStep closure does not directly expose outer cwd/session in this scope).
1772
- const _cwd = process.cwd();
1773
- const _sess: string | undefined = undefined; // best-effort; EE artifact still indexable by content + meta.toolCallId
1774
- const persistArtifact = (toolCallId: string, toolName: string, fullContent: string, reason: string) => {
1775
- try {
1776
- getDefaultEEClient()
1777
- .extract(
1778
- {
1779
- transcript: fullContent.slice(0, 8000),
1780
- projectPath: _cwd,
1781
- meta: {
1782
- source: "tool-artifact",
1783
- toolCallId,
1784
- toolName,
1785
- reason,
1786
- sessionId: _sess,
1787
- elidedAtStep: sn,
1788
- },
1789
- },
1790
- AbortSignal.timeout(700),
1791
- )
1792
- .catch(() => {});
1793
- } catch {
1794
- /* fail-open, no silent swallow of the decision */
1795
- }
1796
- };
1797
- const compacted = compactSubAgentMessages(stripped, {
1798
- thresholdChars: topLevelCompactThreshold,
1799
- keepLastTurns: topLevelCompactKeepLast,
1800
- label: "top-level",
1801
- envelopeChars,
1802
- contextWindowTokens,
1803
- keepToolIds: keepToolIds.length ? keepToolIds : undefined,
1804
- persistArtifact,
1805
- });
1806
- // Pre-compaction visibility: give the agent one step of notice
1807
- // before B4 actually rewrites history into stubs. This is the
1808
- // advance warning that was missing — agent can now decide to
1809
- // summarize, finish, or request preservation.
1810
- const _preCompactWarnAt = Math.floor(topLevelCompactThreshold * 0.78);
1811
- if (stripped.length > _preCompactWarnAt && compacted === stripped) {
1812
- const _cp = buildCheckpointReminder(sn, true);
1813
- const _pre = `[pre-compaction warning at step ${sn} — next step(s) will likely rewrite older tool results to stubs (threshold ${topLevelCompactThreshold}, keepLast=${topLevelCompactKeepLast}). ${_cp} Summarize or finish if possible.]`;
1814
- return { messages: attachReminderToMessages(stripped, _pre) };
1815
- }
1816
- // Phase 4A — scope reminder injection (REQ-005).
1817
- // Cadence K = 3/5/8 for small/medium/large. Soft-warn fires
1818
- // ONCE per session at floor(ceiling*0.7). Reminder lives in
1819
- // the tool_result/system channel so B3/B4 compaction cannot
1820
- // strip it (system-prompt path is unsafe at high step counts).
1821
- // Ceiling reuses the 4B (task_type × size) matrix result
1822
- // resolved above (`_stepCeiling`, `_ceilingTaskType`,
1823
- // `_ceilingSize`, `_ceilingSessionId`) so the reminder and the
1824
- // halt boundary agree on the same number.
1825
- const _scopeSize: ComplexitySize = _ceilingSize;
1826
- const _scopeK = cadenceForSize(_scopeSize);
1827
- const _scopeCeiling = Math.max(1, _stepCeiling ?? deps.maxToolRounds ?? 30);
1828
- const _scopeStep = sn;
1829
- const _shouldRemind = shouldInjectReminder(_scopeStep, _scopeK);
1830
- const _shouldWarn = shouldInjectSoftWarn(_scopeStep, _scopeCeiling, _ceilingSessionId);
1831
- // Phase 5 Fix 5 (revised) — past the natural matrix ceiling the
1832
- // orchestrator emits a STRONG re-anchor reminder, but only when
1833
- // (a) crossing the ceiling for the first time (one-shot), OR
1834
- // (b) hitting a normal cadence step (multiple of K).
1835
- // Original Phase 5 Fix 5 fired on EVERY step past ceiling, which
1836
- // on long-running sessions (e.g. step 77 / ceiling 6 in session
1837
- // 1f29e238a816) produced 70+ redundant reminders that bloated
1838
- // the tool_result channel and forced the model into a "YES still
1839
- // on scope" loop on every tool call.
1840
- const _pastNaturalCeiling = _scopeStep > _naturalCeiling;
1841
- const _justCrossedCeiling = shouldInjectCeilingCrossing(_scopeStep, _naturalCeiling, _ceilingSessionId);
1842
- const _pastCeilingAtCadence = _pastNaturalCeiling && _shouldRemind;
1843
- // Fix #8 — self-repetition one-shot. Fires when the assistant
1844
- // has opened the last 3 streamText steps with the same 4-word
1845
- // phrase (e.g. "YES still on scope" — session 1f29e238a816
1846
- // emitted 15 such bursts past ceiling). Reminder is attached
1847
- // alongside (and before) any scope reminder so the model sees
1848
- // the behavioural correction first.
1849
- const _shouldRepeatReminder = shouldInjectRepetitionReminder(_ceilingSessionId);
1850
- if (_shouldRemind || _shouldWarn || _justCrossedCeiling || _shouldRepeatReminder) {
1851
- const _baseReminder = buildScopeReminder({
1852
- step: _scopeStep,
1853
- ceiling: _scopeCeiling,
1854
- taskType: _ceilingTaskType,
1855
- size: _scopeSize,
1856
- originalPrompt: userMessage,
1857
- });
1858
- // Strong "past natural budget" prefix only applies when we
1859
- // ACTUALLY want the model to consider wrapping up — i.e. on
1860
- // the crossing event or at a cadence step past ceiling, not
1861
- // on every silent step in between.
1862
- const _useStrong = _justCrossedCeiling || _pastCeilingAtCadence;
1863
- const _scopePart =
1864
- _shouldRemind || _shouldWarn || _justCrossedCeiling
1865
- ? _useStrong
1866
- ? `[past natural budget — step ${_scopeStep}/${_naturalCeiling}] If task is COMPLETE, emit final answer NOW. If wandering, simplify the next step. ${_baseReminder}`
1867
- : _shouldWarn
1868
- ? `[approaching ceiling] ${_baseReminder}`
1869
- : _baseReminder
1870
- : null;
1871
- const _reminder = _shouldRepeatReminder
1872
- ? _scopePart
1873
- ? `${buildRepetitionReminder(_ceilingSessionId)}\n${_scopePart}`
1874
- : buildRepetitionReminder(_ceilingSessionId)
1875
- : _scopePart!;
1876
- const withReminder = attachReminderToMessages(compacted, _reminder);
1877
- return { messages: withReminder };
1878
- }
1879
- if (compacted === stripped && stripped === stepMessages) return {};
1880
- // Self-awareness note: tell the model compaction happened so it
1881
- // knows earlier context was elided and can adjust its behavior.
1882
- // Enhanced per EE anti-mù plan (docs/ee-anti-mu-compaction-plan.md Phase 2): include proactive
1883
- // "task finished?", "compacted yet?", "EE checkpoint" so agent can self-assess and avoid mù
1884
- // even when the top-level summary is not in its immediate focus (sub-agents, long loops).
1885
- const _compactNote =
1886
- compacted !== stripped
1887
- ? `[context compacted at step ${sn} — older or low-value tool results rewritten to stubs to fit budget. High-value evidence (file reads, bash, your previous responses) is kept verbatim. ${buildCheckpointReminder(sn, true)}]`
1888
- : null;
1889
- if (_compactNote) {
1890
- return { messages: attachReminderToMessages(compacted, _compactNote) };
1891
- }
1892
- return { messages: compacted };
1893
- },
1894
- ...(dropParam("temperature") ? {} : { temperature: 0.7 }),
1895
- ...(dropParam("maxOutputTokens") ? {} : { maxOutputTokens: taskTypeToMaxTokens(pilCtx.taskType) }),
1896
- ...(Object.keys(providerOpts).length > 0 ? { providerOptions: providerOpts } : {}),
1897
- experimental_onStepStart: (event: unknown) => {
1898
- stepNumber = getStepNumber(event, stepNumber + 1);
1899
- notifyObserver(observer?.onStepStart, {
1900
- stepNumber,
1901
- timestamp: Date.now(),
1902
- });
1903
- },
1904
- onStepFinish: (event: unknown) => {
1905
- const currentStep = getStepNumber(event, Math.max(stepNumber, 0));
1906
- stepNumber = Math.max(stepNumber, currentStep);
1907
- const stepUsage = getUsage(event);
1908
- notifyObserver(observer?.onStepFinish, {
1909
- stepNumber: currentStep,
1910
- timestamp: Date.now(),
1911
- finishReason: getFinishReason(event),
1912
- usage: stepUsage,
1913
- });
1914
- // Realtime status bar update per step
1915
- if (stepUsage.inputTokens || stepUsage.outputTokens) {
1916
- // O1 — thread THIS turn's providerOptions shape per step so every
1917
- // step event records it (not just step 1) and an interleaved task
1918
- // can't overwrite it. Mirrors the gate used for the call itself.
1919
- deps.recordUsage(
1920
- stepUsage,
1921
- "message",
1922
- runtime.modelId,
1923
- Object.keys(providerOpts).length > 0 ? extractProviderOptionsShape(providerOpts) : null,
1924
- );
1925
- }
1926
- // Fix #8 — feed the assistant text emitted in this step into
1927
- // the self-repetition detector. The slice covers everything
1928
- // appended to `assistantText` since the previous step boundary;
1929
- // a step with no text (pure tool call) records as empty, which
1930
- // recordAssistantBurst treats as a no-op so the current run is
1931
- // preserved across tool interludes.
1932
- const _stepText = assistantText.slice(_assistantTextAtLastStep);
1933
- _assistantTextAtLastStep = assistantText.length;
1934
- recordAssistantBurst(_ceilingSessionId, _stepText);
1935
- },
1936
- onFinish: ({ finishReason }) => {
1937
- _lastFinishReason = finishReason ?? null;
1938
- // Task 2.6b — emit llm-done (agent-mode only).
1939
- try {
1940
- const _ar = (globalThis as Record<string, unknown>).__muonroiAgentRuntime as
1941
- | { emitEvent: (e: unknown) => void }
1942
- | undefined;
1943
- _ar?.emitEvent({
1944
- t: "event",
1945
- kind: "llm-done",
1946
- correlationId: _topCallId,
1947
- totalChars: assistantText.length,
1948
- finishReason: finishReason ?? "stop",
1949
- });
1950
- } catch (err) {
1951
- console.error("[Agent:onFinish] failed to emit llm-done", err);
1952
- }
1953
- deps.setCurrentCallId("");
1954
- },
1955
- });
1956
-
1957
- let _topTokenIndex = 0;
1958
- const _wireProviderIdTop = runtime.modelInfo?.provider ?? "unknown";
1959
- for await (const part of result.fullStream) {
1960
- stall.pet(); // chunk arrived — reset the stall watchdog
1961
- if (signal.aborted) {
1962
- yield { type: "content", content: "\n\n[Cancelled]" };
1963
- break;
1964
- }
1965
-
1966
- if (wireDebug.enabled) {
1967
- wireDebug.logChunk(_wireProviderIdTop, String(part.type ?? "unknown"), {
1968
- hasText:
1969
- typeof (part as { text?: string }).text === "string"
1970
- ? (part as { text: string }).text.length
1971
- : undefined,
1972
- hasReasoning:
1973
- typeof (part as unknown as { reasoning?: string }).reasoning === "string"
1974
- ? (part as unknown as { reasoning: string }).reasoning.length
1975
- : undefined,
1976
- });
1977
- if (part.type === "error") {
1978
- wireDebug.logError(_wireProviderIdTop, (part as { error?: unknown }).error);
1979
- }
1980
- }
1981
-
1982
- switch (part.type) {
1983
- case "text-delta":
1984
- assistantText += part.text;
1985
- // Task 2.6b — emit llm-token (agent-mode only; high-volume, default-off per Phase 4).
1986
- try {
1987
- const _ar = (globalThis as Record<string, unknown>).__muonroiAgentRuntime as
1988
- | { emitEvent: (e: unknown) => void }
1989
- | undefined;
1990
- _ar?.emitEvent({
1991
- t: "event",
1992
- kind: "llm-token",
1993
- correlationId: _topCallId,
1994
- delta: part.text,
1995
- tokenIndex: _topTokenIndex++,
1996
- });
1997
- } catch {
1998
- /* best-effort */
1999
- }
2000
- yield { type: "content", content: part.text };
2001
- break;
2002
-
2003
- case "reasoning-delta":
2004
- reasoningPreview = `${reasoningPreview}${part.text}`.slice(-256);
2005
- if (containsEncryptedReasoning(reasoningPreview)) {
2006
- if (!encryptedReasoningHidden) {
2007
- encryptedReasoningHidden = true;
2008
- yield { type: "reasoning", content: "[Encrypted reasoning hidden]" };
2009
- }
2010
- break;
2011
- }
2012
- // P0 native observation: accumulate reasoning for intent context.
2013
- deps.appendTurnAssistantReasoning(part.text);
2014
- yield { type: "reasoning", content: part.text };
2015
- break;
2016
-
2017
- case "tool-call": {
2018
- const tc = toToolCall(part);
2019
- activeToolCalls.push(tc);
2020
- // SAMR: track that Phase 1 produced tool calls → transition to Phase 2
2021
- if (stepRouterPhase === "phase1") phase1HadToolCalls = true;
2022
-
2023
- // Response tool = the terminal final answer (identity execute;
2024
- // the payload lives in the call args). Buffer it (longest-wins)
2025
- // straight from the args and gate UI/DB/exec spam: cheap models
2026
- // sometimes emit the response tool MANY times in ONE generation
2027
- // (session 8d8f498268ed: 80× identical respond_general hedge in
2028
- // one step). stopWhen only halts BETWEEN steps, so it can't stop
2029
- // an in-step spam — this does. Surface only the first indicator;
2030
- // if the model spams past the cap, finalize NOW with the
2031
- // buffered answer instead of streaming out the degenerate step.
2032
- if (isResponseTool(tc.function.name)) {
2033
- _responseToolEmitCount += 1;
2034
- try {
2035
- const _payload = JSON.parse(tc.function.arguments || "{}") as Record<string, unknown>;
2036
- const _len = JSON.stringify(_payload).length;
2037
- if (_len > _pendingStructuredResponseLen) {
2038
- _pendingStructuredResponseLen = _len;
2039
- _pendingStructuredResponse = {
2040
- taskType: getResponseTaskType(tc.function.name) ?? tc.function.name,
2041
- data: _payload,
2042
- };
2043
- }
2044
- } catch {
2045
- /* keep the prior buffered payload */
2046
- }
2047
- responseToolCalled = true;
2048
- // Only the first response-tool call gets a UI indicator.
2049
- if (_responseToolEmitCount === 1) {
2050
- yield { type: "tool_calls", toolCalls: [tc] };
2051
- }
2052
- if (_responseToolEmitCount >= RESPONSE_TOOL_SPAM_CAP && _pendingStructuredResponse) {
2053
- if (deps.session) {
2054
- try {
2055
- logInteraction(deps.session.id, "f6_synthesis", {
2056
- eventSubtype: "response_tool_spam_abort",
2057
- data: { emitted: _responseToolEmitCount, keptChars: _pendingStructuredResponseLen },
2058
- });
2059
- } catch {
2060
- /* telemetry best-effort */
2061
- }
2062
- }
2063
- // Persist a clean turn (user + the single buffered answer)
2064
- // so history stays usable; the spam is dropped. Mirrors the
2065
- // tool-repetition abort: yield + done + return (do NOT await
2066
- // result.response — the stream is still spewing calls).
2067
- const _data = _pendingStructuredResponse.data as { response?: unknown };
2068
- const _answerText =
2069
- typeof _data.response === "string"
2070
- ? _data.response
2071
- : JSON.stringify(_pendingStructuredResponse.data);
2072
- try {
2073
- deps.appendCompletedTurn(userModelMessage, [
2074
- { role: "assistant", content: _answerText } as ModelMessage,
2075
- ]);
2076
- } catch (persistErr) {
2077
- console.error(
2078
- `[message-processor] response-tool-spam persist failed: ${(persistErr as Error)?.message}`,
2079
- );
2080
- }
2081
- yield {
2082
- type: "structured_response" as StreamChunk["type"],
2083
- structuredResponse: _pendingStructuredResponse,
2084
- };
2085
- yield { type: "done" };
2086
- return;
2087
- }
2088
- break; // response tools skip write-ahead/hooks/normal tool_calls yield
2089
- }
2090
-
2091
- // EE PreToolUse hook: fire intercept before tool execution.
2092
- {
2093
- const turnAssistantReasoning = deps.getTurnAssistantReasoning();
2094
- const intentContext: import("../hooks/types.js").PreToolIntentContext = {
2095
- ...(turnAssistantReasoning
2096
- ? { assistantReasoningExcerpt: turnAssistantReasoning.slice(-200) }
2097
- : {}),
2098
- ...(deps.priorWarningIdsInSession.size > 0
2099
- ? {
2100
- priorWarningIdsInSession: Array.from(deps.priorWarningIdsInSession).slice(-20),
2101
- }
2102
- : {}),
2103
- ...(pilCtx.gsdPhase ? { gsdPhase: pilCtx.gsdPhase } : {}),
2104
- ...(userMessage.slice(0, 200) ? { userGoalExcerpt: userMessage.slice(0, 200) } : {}),
2105
- };
2106
- const preInput: PreToolUseHookInput = {
2107
- hook_event_name: "PreToolUse",
2108
- tool_name: tc.function.name,
2109
- tool_input: JSON.parse(tc.function.arguments || "{}"),
2110
- session_id: deps.session?.id,
2111
- cwd: deps.bash.getCwd(),
2112
- ...(Object.keys(intentContext).length > 0 ? { intent_context: intentContext } : {}),
2113
- };
2114
- const preResult = await deps.fireHook(preInput, signal).catch(() => ({
2115
- blocked: false,
2116
- blockingErrors: [] as Array<{ command: string; stderr: string }>,
2117
- preventContinuation: false,
2118
- additionalContexts: [] as string[],
2119
- results: [] as import("../hooks/types.js").HookResult[],
2120
- eeMatches: [] as import("../hooks/types.js").EEMatchEntry[],
2121
- }));
2122
- for (const ctx of preResult.additionalContexts ?? []) {
2123
- yield { type: "content", content: `${ctx}\n` };
2124
- }
2125
- // Store structured EE matches for session guidance injection on next turn.
2126
- for (const m of preResult.eeMatches ?? []) {
2127
- deps.sessionEEGuidance.set(m.id, {
2128
- toolName: m.toolName,
2129
- message: m.message,
2130
- why: m.why,
2131
- confidence: m.confidence,
2132
- });
2133
- // Cap at 30 entries — oldest first, trim when exceeded.
2134
- if (deps.sessionEEGuidance.size > 30) {
2135
- const firstKey = deps.sessionEEGuidance.keys().next().value;
2136
- if (firstKey !== undefined) deps.sessionEEGuidance.delete(firstKey);
2137
- }
2138
- }
2139
- // P0 native observation: track which principle IDs surfaced
2140
- // this turn so the next intercept can dedup server-side.
2141
- try {
2142
- const { getLastSurfacedState } = await import("../ee/intercept.js");
2143
- const { surfacedIds } = getLastSurfacedState();
2144
- for (const id of surfacedIds) deps.priorWarningIdsInSession.add(id);
2145
- // Cap memory: keep only most-recent 100 IDs.
2146
- if (deps.priorWarningIdsInSession.size > 100) {
2147
- const arr = Array.from(deps.priorWarningIdsInSession);
2148
- deps.setPriorWarningIdsInSession(new Set(arr.slice(-100)));
2149
- }
2150
- } catch {
2151
- /* fail-open */
2152
- }
2153
- }
2154
-
2155
- // Pitfall 9: log the pending call so reconcile() can recover any
2156
- // staged .tmp files if the process is killed before tool-result.
2157
- if (deps.pendingCalls) {
2158
- const turnId = deps.session?.id ?? "anon";
2159
- const callId = stableCallId(turnId, tc.function.name, tc.function.arguments);
2160
- // Phase 0: predictStagedPaths = [] for all tools (refined in Phase 1).
2161
- void deps.pendingCalls.begin({ call_id: callId, tool_name: tc.function.name }).catch(() => {});
2162
- // Attach callId to the ToolCall so tool-result can end it.
2163
- (tc as ToolCall & { _pendingCallId?: string })._pendingCallId = callId;
2164
- }
2165
-
2166
- // Phase A4: write-ahead persistence — insert a pending row into
2167
- // tool_calls BEFORE executing the tool. If the stream throws
2168
- // mid-call (e.g. provider 5xx, abort, network drop), this row
2169
- // remains as `pending` so `usage forensics` can show the args
2170
- // the model passed. The post-stream appendMessages() path
2171
- // (INSERT OR IGNORE + UPDATE) will finalize this row to
2172
- // `completed` once the turn settles normally.
2173
- if (deps.sessionStore && deps.session) {
2174
- // Predicted assistant seq: user message + assistant message
2175
- // are appended atomically by appendCompletedTurn().
2176
- // getNextMessageSequence() returns the seq the user message
2177
- // will get; the assistant message is the next one after.
2178
- let predictedSeq = -1;
2179
- try {
2180
- predictedSeq = getNextMessageSequence(deps.session.id) + 1;
2181
- } catch {
2182
- /* fail-open — leave predictedSeq=-1; post-stream UPDATE corrects it */
2183
- }
2184
- persistToolCallWriteAhead(
2185
- deps.session.id,
2186
- predictedSeq,
2187
- tc.id,
2188
- tc.function.name,
2189
- tc.function.arguments || "{}",
2190
- );
2191
- }
2192
- notifyObserver(observer?.onToolStart, {
2193
- toolCall: tc,
2194
- timestamp: Date.now(),
2195
- });
2196
- // Interaction log: tool call start
2197
- try {
2198
- if (deps.session) {
2199
- logInteraction(deps.session.id, "tool_call", {
2200
- eventSubtype: tc.function.name,
2201
- data: {
2202
- toolCallId: tc.id,
2203
- argsPreview: tc.function.arguments.slice(0, 200),
2204
- },
2205
- });
2206
- }
2207
- } catch {
2208
- /* fail-open */
2209
- }
2210
- yield { type: "tool_calls", toolCalls: [tc] };
2211
- break;
2212
- }
2213
-
2214
- case "tool-result": {
2215
- const tc: ToolCall = {
2216
- id: part.toolCallId,
2217
- type: "function",
2218
- function: { name: part.toolName, arguments: JSON.stringify(part.input ?? {}) },
2219
- };
2220
- let tr = toToolResult(part.output);
2221
-
2222
- // Vision Bridge: proxy image-bearing tool results for text-only models (any tool, not just MCP)
2223
- try {
2224
- const bridgeResult = await bridgeMcpToolResult(
2225
- part.toolName,
2226
- tr.output,
2227
- turnModelId,
2228
- signal,
2229
- part.toolCallId,
2230
- );
2231
- if (bridgeResult.proxied) {
2232
- tr = {
2233
- ...tr,
2234
- output:
2235
- typeof bridgeResult.output === "string"
2236
- ? bridgeResult.output
2237
- : JSON.stringify(bridgeResult.output),
2238
- };
2239
- yield { type: "content", content: `[Vision Bridge: image → text for ${turnModelId}]\n` };
2240
- }
2241
- } catch (err) {
2242
- console.error("[Agent:visionBridge] failed to process image for tool result", err);
2243
- }
2244
-
2245
- // Capture into the stall-rescue digest before any further
2246
- // processing — if the stream stalls after this, these outputs
2247
- // are all we have to synthesize a final answer from.
2248
- pushStallToolResult(
2249
- turnToolResults,
2250
- part.toolName,
2251
- typeof tr.output === "string" ? tr.output : JSON.stringify(tr.output),
2252
- );
2253
-
2254
- // Pitfall 9: settle the pending call log entry.
2255
- if (deps.pendingCalls) {
2256
- const pending = activeToolCalls.find((t) => t.id === part.toolCallId);
2257
- const callId = (pending as ToolCall & { _pendingCallId?: string })?._pendingCallId;
2258
- if (callId) {
2259
- const endStatus = signal.aborted ? "aborted" : "settled";
2260
- void deps.pendingCalls.end(callId, endStatus).catch(() => {});
2261
- }
2262
- }
2263
- // EE PostToolUse hook: fire-and-forget after tool execution.
2264
- {
2265
- const postInput: PostToolUseHookInput = {
2266
- hook_event_name: "PostToolUse",
2267
- tool_name: part.toolName,
2268
- tool_input: (part.input as Record<string, unknown>) ?? {},
2269
- tool_output:
2270
- typeof tr.output === "string"
2271
- ? { text: tr.output }
2272
- : ((tr.output as unknown as Record<string, unknown>) ?? {}),
2273
- session_id: deps.session?.id,
2274
- cwd: deps.bash.getCwd(),
2275
- };
2276
- await deps.fireHook(postInput, signal).catch((err) => {
2277
- console.error("[Agent:PostToolUse hook] failed", err);
2278
- });
2279
- }
2280
-
2281
- // Response tool: yield as structured_response instead of tool_result.
2282
- // AI SDK v5 wraps tool outputs as `{type:"json", value:{...}}`; unwrap
2283
- // to expose the schema-shaped payload to the UI renderer.
2284
- if (isResponseTool(part.toolName)) {
2285
- responseToolCalled = true;
2286
- // Payload was already buffered (longest-wins) from the
2287
- // tool-CALL args above; re-buffer from the executed result as
2288
- // a fallback (unwraps the AI-SDK `{type:"json",value}` shape).
2289
- // Counting + the spam cap live in the tool-call branch.
2290
- const taskType = getResponseTaskType(part.toolName);
2291
- const rawOutput = part.output as unknown;
2292
- const unwrapped =
2293
- rawOutput && typeof rawOutput === "object" && (rawOutput as { type?: string }).type === "json"
2294
- ? ((rawOutput as { value?: unknown }).value ?? {})
2295
- : (rawOutput ?? {});
2296
- const _len = JSON.stringify(unwrapped ?? {}).length;
2297
- if (_len > _pendingStructuredResponseLen) {
2298
- _pendingStructuredResponseLen = _len;
2299
- _pendingStructuredResponse = {
2300
- taskType: taskType ?? part.toolName,
2301
- data: unwrapped as Record<string, unknown>,
2302
- };
2303
- }
2304
- notifyObserver(observer?.onToolFinish, { toolCall: tc, toolResult: tr, timestamp: Date.now() });
2305
- break;
2306
- }
2307
-
2308
- notifyObserver(observer?.onToolFinish, {
2309
- toolCall: tc,
2310
- toolResult: tr,
2311
- timestamp: Date.now(),
2312
- });
2313
- // Interaction log: tool result.
2314
- // Phase 5 BUG-J — for edit/write/update tools, persist the
2315
- // structured diff (file_path, +N/-M counts, isNew flag, and
2316
- // a bounded patch preview) so forensics queries can audit
2317
- // what actually changed in each turn without re-reading
2318
- // git history. Earlier the log only had the summary string
2319
- // ("Edited X (+1 -1)") — the patch text was lost.
2320
- try {
2321
- if (deps.session) {
2322
- const outputPreview =
2323
- typeof tr.output === "string" ? tr.output.slice(0, 200) : JSON.stringify(tr.output).slice(0, 200);
2324
- const _trWithDiff = tr as {
2325
- diff?: { filePath: string; additions: number; removals: number; patch: string; isNew: boolean };
2326
- };
2327
- const diffMeta =
2328
- _trWithDiff.diff &&
2329
- (tc.function.name === "edit_file" ||
2330
- tc.function.name === "write_file" ||
2331
- tc.function.name === "update_file")
2332
- ? {
2333
- filePath: _trWithDiff.diff.filePath,
2334
- additions: _trWithDiff.diff.additions,
2335
- removals: _trWithDiff.diff.removals,
2336
- isNew: _trWithDiff.diff.isNew,
2337
- // Cap at 4000 chars — enough to inspect small/medium
2338
- // edits without ballooning the SQLite row. Large
2339
- // refactors get truncated with a tail marker so
2340
- // readers know the patch is partial.
2341
- patchPreview:
2342
- _trWithDiff.diff.patch.length > 4000
2343
- ? _trWithDiff.diff.patch.slice(0, 4000) + "\n…[truncated]"
2344
- : _trWithDiff.diff.patch,
2345
- }
2346
- : undefined;
2347
- logInteraction(deps.session.id, "tool_result", {
2348
- eventSubtype: tc.function.name,
2349
- data: { success: tr.success, outputPreview, ...(diffMeta ? { diff: diffMeta } : {}) },
2350
- });
2351
- }
2352
- } catch {
2353
- /* fail-open */
2354
- }
2355
- yield { type: "tool_result", toolCall: tc, toolResult: tr };
2356
- // Reset tool-repetition counter on any non-error result. A
2357
- // successful call between two failures of the same shape is
2358
- // progress and should not accumulate toward the abort gate.
2359
- if (tr.success) {
2360
- recordToolRepetitionSuccess(deps.session?.id ?? null);
2361
- }
2362
- // todo_write side-effect: surface the task list to the UI via a
2363
- // dedicated chunk so the sticky checklist panel can re-render
2364
- // without parsing tool args itself. Skipped when the snapshot
2365
- // doesn't parse (malformed args) so the UI is never poisoned.
2366
- if (tc.function.name === "todo_write" && tr.success) {
2367
- const snap = snapshotFromTodoWriteArgs(tc.function.arguments);
2368
- if (snap) yield { type: "task_list_update", taskListSnapshot: snap };
2369
- }
2370
- break;
2371
- }
2372
-
2373
- case "tool-error": {
2374
- // AI SDK emits this when tool execution throws/aborts before
2375
- // producing a tool-result. Without this branch, the tool_call
2376
- // log row has no matching tool_result and the EE judge never
2377
- // sees the failure → silent ~1.6% pairing leak in prod DB.
2378
- const errPart = part as {
2379
- type: "tool-error";
2380
- toolCallId: string;
2381
- toolName: string;
2382
- input?: unknown;
2383
- error: unknown;
2384
- };
2385
- const tc: ToolCall = {
2386
- id: errPart.toolCallId,
2387
- type: "function",
2388
- function: { name: errPart.toolName, arguments: JSON.stringify(errPart.input ?? {}) },
2389
- };
2390
- const errMsg =
2391
- errPart.error instanceof Error
2392
- ? errPart.error.message
2393
- : typeof errPart.error === "string"
2394
- ? errPart.error
2395
- : JSON.stringify(errPart.error);
2396
- const tr = { success: false, output: `[tool-error] ${errMsg}` };
2397
-
2398
- // Settle pending-call ledger so we don't leak stale .tmp files.
2399
- if (deps.pendingCalls) {
2400
- const pending = activeToolCalls.find((t) => t.id === errPart.toolCallId);
2401
- const callId = (pending as ToolCall & { _pendingCallId?: string })?._pendingCallId;
2402
- if (callId) void deps.pendingCalls.end(callId, "settled").catch(() => {});
2403
- }
2404
-
2405
- // Phase A4: mark the write-ahead tool_calls row as `errored`.
2406
- // The post-stream appendMessages() path does NOT see tool-error
2407
- // parts in the assistant message content (the SDK doesn't emit
2408
- // them there), so without this explicit update the row would
2409
- // remain `pending` after a clean tool failure.
2410
- if (deps.session) {
2411
- markToolCallErrored(deps.session.id, errPart.toolCallId, errMsg);
2412
- }
2413
-
2414
- // Fire PostToolUseFailure so EE judge can record IGNORED outcome.
2415
- {
2416
- const failInput: PostToolUseFailureHookInput = {
2417
- hook_event_name: "PostToolUseFailure",
2418
- tool_name: errPart.toolName,
2419
- tool_input: (errPart.input as Record<string, unknown>) ?? {},
2420
- error: errMsg,
2421
- session_id: deps.session?.id,
2422
- cwd: deps.bash.getCwd(),
2423
- };
2424
- await deps.fireHook(failInput, signal).catch(() => {});
2425
- }
2426
-
2427
- try {
2428
- if (deps.session) {
2429
- logInteraction(deps.session.id, "tool_result", {
2430
- eventSubtype: errPart.toolName,
2431
- data: { success: false, error: errMsg.slice(0, 500), reason: "tool-error" },
2432
- });
2433
- }
2434
- } catch (logErr) {
2435
- console.error(
2436
- `[message-processor] interaction-log tool_result failed: ${(logErr as Error)?.message}`,
2437
- );
2438
- }
2439
-
2440
- notifyObserver(observer?.onToolFinish, { toolCall: tc, toolResult: tr, timestamp: Date.now() });
2441
- yield { type: "tool_result", toolCall: tc, toolResult: tr };
2442
-
2443
- // Tool-call perseveration guard. After N consecutive identical
2444
- // (toolName, args, error) triples, abort the streaming loop
2445
- // before TPM rate limits do (session 080fe2fcbf24).
2446
- const repetition = recordToolRepetitionError(
2447
- deps.session?.id ?? null,
2448
- errPart.toolName,
2449
- errPart.input,
2450
- errMsg,
2451
- );
2452
- if (repetition.shouldAbort) {
2453
- const abortMsg = buildToolRepetitionAbortMessage(errPart.toolName, repetition.runLength, errMsg);
2454
- try {
2455
- if (deps.session) {
2456
- logInteraction(deps.session.id, "error", {
2457
- eventSubtype: "tool_repetition_abort",
2458
- data: {
2459
- toolName: errPart.toolName,
2460
- runLength: repetition.runLength,
2461
- errorPreview: errMsg.slice(0, 200),
2462
- },
2463
- });
2464
- }
2465
- } catch (logErr) {
2466
- console.error(
2467
- `[message-processor] interaction-log tool_repetition_abort failed: ${(logErr as Error)?.message}`,
2468
- );
2469
- }
2470
- notifyObserver(observer?.onError, { message: abortMsg, timestamp: Date.now() });
2471
- yield { type: "error", content: abortMsg, isAuthError: false };
2472
- yield { type: "done" };
2473
- return;
2474
- }
2475
- break;
2476
- }
2477
-
2478
- case "tool-approval-request": {
2479
- const approvalPart = part as unknown as {
2480
- approvalId: string;
2481
- toolCall: { toolCallId: string; toolName: string; input: unknown };
2482
- };
2483
- const toolCallId = approvalPart.toolCall?.toolCallId ?? "";
2484
- const pendingTc = activeToolCalls.find((tc) => tc.id === toolCallId);
2485
- const tcForChunk = pendingTc ?? {
2486
- id: toolCallId,
2487
- type: "function" as const,
2488
- function: {
2489
- name: approvalPart.toolCall?.toolName ?? "paid_request",
2490
- arguments: JSON.stringify(approvalPart.toolCall?.input ?? {}),
2491
- },
2492
- };
2493
-
2494
- // Payment pre-check disabled — Stripe billing pending.
2495
- const paymentPrecheck: import("../types/index").PaymentPrecheck | undefined = undefined;
2496
-
2497
- // Plan 03-01: check permission mode before yielding approval request to UI.
2498
- // auto-edit auto-approves file ops; yolo auto-approves everything.
2499
- const toolName = approvalPart.toolCall?.toolName ?? "";
2500
- const input = approvalPart.toolCall?.input ?? {};
2501
- const context =
2502
- toolName === "bash"
2503
- ? { command: String((input as any).command ?? "") }
2504
- : toolName === "write_file" ||
2505
- toolName === "edit_file" ||
2506
- toolName === "read_file" ||
2507
- toolName === "grep"
2508
- ? { path: String((input as any).path ?? (input as any).file_path ?? "") }
2509
- : undefined;
2510
- if (!toolNeedsApproval(toolName, deps.permissionMode, context)) {
2511
- // Auto-approve: respond directly without surfacing to UI.
2512
- deps.respondToToolApproval(approvalPart.approvalId, true);
2513
- appendAudit({
2514
- kind: deps.permissionMode === "yolo" ? "yolo-override" : "permission-override",
2515
- tool: toolName,
2516
- mode: deps.permissionMode,
2517
- context,
2518
- ts: Date.now(),
2519
- });
2520
- break;
2521
- }
2522
-
2523
- yield {
2524
- type: "tool_approval_request",
2525
- approvalId: approvalPart.approvalId,
2526
- toolCall: tcForChunk,
2527
- paymentPrecheck,
2528
- };
2529
- break;
2530
- }
2531
-
2532
- case "error": {
2533
- const authError = isAuthenticationError(part.error);
2534
- const friendly = humanizeApiError(part.error, {
2535
- modelId: runtime.modelId,
2536
- providerId: runtime.modelInfo?.provider,
2537
- });
2538
- const forensics = summarizeApiErrorForLog(part.error);
2539
- notifyObserver(observer?.onError, {
2540
- message: friendly,
2541
- timestamp: Date.now(),
2542
- });
2543
- // Interaction log: error + forensics envelope so opaque
2544
- // provider 4xx ("parameter is invalid" / unknown 400s) leave
2545
- // an actionable wire-level trace without needing a repro.
2546
- try {
2547
- if (deps.session) {
2548
- logInteraction(deps.session.id, "error", {
2549
- eventSubtype: authError ? "auth" : "api",
2550
- data: {
2551
- message: friendly.slice(0, 200),
2552
- ...(forensics ? { forensics } : {}),
2553
- },
2554
- });
2555
- }
2556
- } catch (logErr) {
2557
- console.error(`[message-processor] interaction-log error failed: ${(logErr as Error)?.message}`);
2558
- }
2559
- yield {
2560
- type: "error",
2561
- content: friendly,
2562
- isAuthError: authError,
2563
- };
2564
- break;
2565
- }
2566
-
2567
- case "abort":
2568
- // A stall-watchdog abort arrives here as an "abort" stream part
2569
- // (the SDK surfaces it as a part, not a throw). Distinguish it
2570
- // from a genuine user cancel — which is caught at the top of the
2571
- // loop via `signal.aborted` — and surface it as a visible error
2572
- // instead of a benign "[Cancelled]" so a hung provider no longer
2573
- // looks like a silent freeze.
2574
- if (stallTriggered) {
2575
- stall.dispose();
2576
- // A response tool already produced the terminal structured
2577
- // answer (buffered from its call args) before the provider
2578
- // stalled on a LATER step. Surface it and finish cleanly —
2579
- // never bury the model's actual answer behind a "not
2580
- // responding" error. Root cause of the "respond_* indicator
2581
- // shows but no answer block renders" report: this stall-abort
2582
- // path returned before the post-loop structured_response yield,
2583
- // dropping the captured answer. A response tool is terminal,
2584
- // so there is nothing to rescue — just emit what we have.
2585
- if (_pendingStructuredResponse) {
2586
- if (!streamOk) {
2587
- try {
2588
- const _d = _pendingStructuredResponse.data as { response?: unknown };
2589
- const _ans =
2590
- typeof _d.response === "string"
2591
- ? _d.response
2592
- : JSON.stringify(_pendingStructuredResponse.data);
2593
- deps.appendCompletedTurn(userModelMessage, [
2594
- { role: "assistant", content: _ans } as ModelMessage,
2595
- ]);
2596
- streamOk = true;
2597
- } catch (persistErr) {
2598
- console.error(
2599
- `[message-processor] stall+response-tool persist failed: ${(persistErr as Error)?.message}`,
2600
- );
2601
- }
2602
- }
2603
- yield {
2604
- type: "structured_response" as StreamChunk["type"],
2605
- structuredResponse: _pendingStructuredResponse,
2606
- };
2607
- yield { type: "done" };
2608
- return;
2609
- }
2610
- // Best-effort answer rescue: a turn that already ran tools but
2611
- // stalled before the final synthesis would otherwise return
2612
- // ONLY "Model not responding", discarding all that work (live
2613
- // obs 2026-06-04, deepseek session 734e65cffdf6: 67 tool calls
2614
- // → user got nothing). Make ONE guarded forced-finalize call
2615
- // over the gathered tool outputs. forcedFinalize has its own
2616
- // stall timeout, so a still-dead provider just falls through.
2617
- let _rescued: string | null = null;
2618
- if (turnToolResults.length > 0) {
2619
- try {
2620
- const _userText =
2621
- typeof userModelMessage?.content === "string"
2622
- ? userModelMessage.content
2623
- : JSON.stringify(userModelMessage?.content ?? "");
2624
- _rescued = await attemptStallRescue({
2625
- baseMessages: _topMessagesForCall as unknown[],
2626
- userText: _userText.slice(0, 4000),
2627
- toolResults: turnToolResults,
2628
- system: typeof systemForModel === "string" ? systemForModel : undefined,
2629
- finalize: (a) =>
2630
- forcedFinalize({ model: runtime.model, messages: a.messages, system: a.system }),
2631
- });
2632
- } catch {
2633
- _rescued = null;
2634
- }
2635
- try {
2636
- if (deps.session) {
2637
- logInteraction(deps.session.id, "stall_rescue", {
2638
- data: {
2639
- outcome: _rescued ? "rescued" : "no_text",
2640
- toolResultCount: turnToolResults.length,
2641
- chars: _rescued?.length ?? 0,
2642
- },
2643
- });
2644
- }
2645
- } catch {
2646
- /* telemetry is best-effort */
2647
- }
2648
- }
2649
- if (_rescued) {
2650
- assistantText += (assistantText ? "\n\n" : "") + _rescued;
2651
- yield { type: "content", content: _rescued };
2652
- }
2653
- // Persist a record of the interrupted turn BEFORE returning so
2654
- // the next turn is not amnesiac. Previously this returned with
2655
- // nothing persisted → the next turn saw "no previous turn" and
2656
- // redid the work, orphaning any edits the stalled turn applied
2657
- // (live obs 2026-06-04, deepseek-v4-flash). When rescued, the
2658
- // note now carries the synthesized answer too (assistantText).
2659
- // Best-effort: never let persistence failure block surfacing.
2660
- if (!streamOk) {
2661
- try {
2662
- const _stallNote = buildInterruptedTurnNote(
2663
- assistantText,
2664
- activeToolCalls.map((c) => c.function.name),
2665
- );
2666
- deps.appendCompletedTurn(userModelMessage, [
2667
- { role: "assistant", content: _stallNote } as ModelMessage,
2668
- ]);
2669
- streamOk = true;
2670
- } catch {
2671
- /* best-effort — surface the stall regardless */
2672
- }
2673
- }
2674
- if (_rescued) {
2675
- // Recovered a best-effort answer from partial data — surface
2676
- // a soft notice instead of the scary "not responding" error.
2677
- yield {
2678
- type: "content",
2679
- content:
2680
- "\n\n[Note: the model connection stalled; the answer above is a best-effort synthesis " +
2681
- "from the tool results gathered before the stall and may be incomplete.]",
2682
- };
2683
- yield { type: "done" };
2684
- return;
2685
- }
2686
- notifyObserver(observer?.onError, { message: STALL_ERROR_MESSAGE, timestamp: Date.now() });
2687
- yield { type: "error", content: STALL_ERROR_MESSAGE, isAuthError: false };
2688
- yield { type: "done" };
2689
- return;
2690
- }
2691
- yield { type: "content", content: "\n\n[Cancelled]" };
2692
- break;
2693
- }
2694
- }
2695
- stall.dispose(); // stream drained normally — stop the stall watchdog
2696
-
2697
- // ─── SAMR Phase 1 → Phase 2 transition ─────────────────────────
2698
- // Phase 1 (premium model) produced tool calls but the SDK stopped
2699
- // before executing them (stopWhen: stepCountIs(1)). Append the
2700
- // assistant message to deps.messages and restart the loop with
2701
- // the fast execution model. Phase 2's streamText call will see
2702
- // the pending tool calls and execute them automatically.
2703
- //
2704
- // EXCEPT when Phase 1 emitted a response tool: a `respond_*` call IS
2705
- // the terminal structured answer (identity execute), not work to hand
2706
- // to Phase 2. Transitioning here would (a) skip the structured_response
2707
- // yield below — the answer never reaches the TUI — and (b) append a
2708
- // dangling assistant tool-call WITHOUT its tool-result (only assistant
2709
- // msgs are pushed), corrupting Phase 2's history. Fall through instead
2710
- // so the buffered answer is yielded + persisted on this turn.
2711
- if (stepRouterPhase === "phase1" && phase1HadToolCalls && !responseToolCalled) {
2712
- try {
2713
- const phase1Response = await result.response;
2714
- // Append only new messages (assistant message with tool calls)
2715
- const newMsgs = phase1Response.messages.slice(deps.messages.length);
2716
- for (const msg of newMsgs) {
2717
- if (msg.role === "assistant") {
2718
- deps.messages.push(msg);
2719
- }
2720
- }
2721
- } catch {
2722
- // If response extraction fails, fall through to normal completion
2723
- }
2724
- stepRouterPhase = "phase2";
2725
- continue; // Re-enter while loop with Phase 2 (fast) model
2726
- }
2727
-
2728
- // Surface the single most-complete response-tool answer buffered
2729
- // during the stream (see _pendingStructuredResponse). Yielding here —
2730
- // once, after the stream drained and after the Phase 1 transition —
2731
- // collapses any duplicate response-tool emissions in the turn into a
2732
- // single structured_response block for the UI.
2733
- if (_pendingStructuredResponse) {
2734
- yield {
2735
- type: "structured_response" as StreamChunk["type"],
2736
- structuredResponse: _pendingStructuredResponse,
2737
- };
2738
- if (_responseToolEmitCount > 1 && deps.session) {
2739
- try {
2740
- logInteraction(deps.session.id, "f6_synthesis", {
2741
- eventSubtype: "response_tool_deduped",
2742
- data: { emitted: _responseToolEmitCount, keptChars: _pendingStructuredResponseLen },
2743
- });
2744
- } catch {
2745
- /* telemetry best-effort */
2746
- }
2747
- }
2748
- }
2749
-
2750
- if (signal.aborted) {
2751
- deps.discardAbortedTurn(userModelMessage);
2752
- yield { type: "done" };
2753
- return;
2754
- }
2755
-
2756
- try {
2757
- const response = await result.response;
2758
- if (!signal.aborted) {
2759
- // Scrub oversized base64 image payloads from tool-result parts
2760
- // BEFORE persisting. The vision bridge above only modified the
2761
- // transient `tr` shown to the user — `response.messages` from
2762
- // the AI SDK still carries the full base64 (e.g. Playwright
2763
- // screenshot, ~1.5MB). Persisting that lets it accumulate and
2764
- // overflow the model's context on subsequent turns.
2765
- const scrubbed = scrubImagePayloadsInMessages(response.messages);
2766
-
2767
- // Phase 5 F6 — synthesis step when stream ended without a final
2768
- // text response. Cheap models (DeepSeek V4 Flash) frequently
2769
- // emit only tool-calls in their last step and stop, leaving the
2770
- // user staring at "Here's the summary:..." truncation that
2771
- // required a manual "tiếp tục" turn-2 to coax out. Detect that
2772
- // shape and inject ONE forcedFinalize call (same path as 4B
2773
- // ceiling-hit) so the answer arrives on turn 1.
2774
- //
2775
- // Skip when 4B ceiling already triggered its own forcedFinalize
2776
- // below — running both would double-bill and duplicate text.
2777
- let _f6SynthesisText: string | null = null;
2778
- const _f6LastMsg = scrubbed[scrubbed.length - 1] as { role?: string; content?: unknown } | undefined;
2779
- const _f6LastRole = _f6LastMsg?.role ?? "none";
2780
- let _f6Outcome:
2781
- | "skip_ceiling"
2782
- | "skip_has_text"
2783
- | "skip_response_tool"
2784
- | "fired_empty"
2785
- | "fired_text"
2786
- | "error" = "skip_ceiling";
2787
- let _f6Elapsed = 0;
2788
- let _f6ChunkChars = 0;
2789
- let _f6Error: string | null = null;
2790
- // A response tool already produced the final structured answer —
2791
- // F6 synthesis would duplicate it as prose. Skip entirely. With
2792
- // the stopWhen terminal-halt above, the turn now ends right after
2793
- // the response tool (last scrubbed message is the response
2794
- // tool-result, role "tool"), which would otherwise trip the
2795
- // _needsSynthesis "ended on a tool" branch and double-respond.
2796
- if (responseToolCalled) {
2797
- _f6Outcome = "skip_response_tool";
2798
- } else if (!_ceilingHit) {
2799
- const _needsSynthesis = (() => {
2800
- if (!_f6LastMsg) return false;
2801
- if (_f6LastMsg.role === "tool") return true;
2802
- if (_f6LastMsg.role !== "assistant") return false;
2803
- const _c = _f6LastMsg.content;
2804
- if (typeof _c === "string") return !_c.trim();
2805
- if (!Array.isArray(_c)) return false;
2806
- return !(_c as Array<Record<string, unknown>>).some(
2807
- (p) => p && p.type === "text" && typeof p.text === "string" && (p.text as string).trim().length > 0,
2808
- );
2809
- })();
2810
- if (!_needsSynthesis) {
2811
- _f6Outcome = "skip_has_text";
2812
- } else {
2813
- const _f6Start = Date.now();
2814
- try {
2815
- const _ff = await forcedFinalize({
2816
- model: runtime.model,
2817
- messages: _topMessagesForCall as unknown[],
2818
- system: typeof systemForModel === "string" ? systemForModel : undefined,
2819
- });
2820
- _f6Elapsed = Date.now() - _f6Start;
2821
- _f6ChunkChars = (_ff.text ?? "").length;
2822
- if (_ff.text.trim()) {
2823
- _f6SynthesisText = _ff.text;
2824
- assistantText += _ff.text;
2825
- yield { type: "content", content: _ff.text };
2826
- _f6Outcome = "fired_text";
2827
- } else {
2828
- _f6Outcome = "fired_empty";
2829
- }
2830
- } catch (_err) {
2831
- _f6Elapsed = Date.now() - _f6Start;
2832
- _f6Outcome = "error";
2833
- _f6Error = (_err as Error)?.message?.slice(0, 200) ?? String(_err).slice(0, 200);
2834
- }
2835
- }
2836
- }
2837
- try {
2838
- if (deps.session) {
2839
- logInteraction(deps.session.id, "f6_synthesis", {
2840
- data: {
2841
- outcome: _f6Outcome,
2842
- lastMsgRole: _f6LastRole,
2843
- elapsedMs: _f6Elapsed,
2844
- chars: _f6ChunkChars,
2845
- error: _f6Error,
2846
- ceilingHit: _ceilingHit,
2847
- scrubbedLen: scrubbed.length,
2848
- },
2849
- });
2850
- }
2851
- } catch {
2852
- /* telemetry is best-effort */
2853
- }
2854
-
2855
- // Summary-phase grounding check (Agent Operating Contract, runtime
2856
- // half). Soft-flag counts / file:line refs in the final synthesis
2857
- // that don't appear in this turn's tool outputs — possible
2858
- // hallucination. Never blocks: emits a grounding-flag event + a
2859
- // warn toast + an inline advisory footnote. Only runs when the
2860
- // turn actually produced tool output (a corpus to ground against)
2861
- // and is not chitchat. See grounding-check.ts.
2862
- if (
2863
- process.env.MUONROI_DISABLE_GROUNDING_CHECK !== "1" &&
2864
- !isChitchat &&
2865
- assistantText.trim().length > 0
2866
- ) {
2867
- try {
2868
- const _gParts: string[] = [];
2869
- let _gHadTool = false;
2870
- for (const _gm of scrubbed as Array<{ role?: string; content?: unknown }>) {
2871
- if (!_gm || _gm.role === "assistant") continue;
2872
- if (_gm.role === "tool") _gHadTool = true;
2873
- const _gc = _gm.content;
2874
- _gParts.push(typeof _gc === "string" ? _gc : JSON.stringify(_gc));
2875
- }
2876
- if (_gHadTool) {
2877
- const _claims = findUnverifiedClaims(assistantText, _gParts.join("\n"));
2878
- if (_claims.length > 0) {
2879
- const _footnote = buildGroundingFootnote(_claims);
2880
- assistantText += _footnote;
2881
- yield { type: "content", content: _footnote };
2882
- const _gar = (globalThis as Record<string, unknown>).__muonroiAgentRuntime as
2883
- | { emitEvent: (e: unknown) => void }
2884
- | undefined;
2885
- const _claimTexts = _claims.map((c) => c.text);
2886
- _gar?.emitEvent({
2887
- t: "event",
2888
- kind: "grounding-flag",
2889
- claims: _claimTexts,
2890
- count: _claims.length,
2891
- ts: Date.now(),
2892
- });
2893
- _gar?.emitEvent({
2894
- t: "event",
2895
- kind: "toast",
2896
- level: "warn",
2897
- text: `grounding: ${_claims.length} unverified claim(s) — ${_claimTexts.join(", ")}`,
2898
- });
2899
- if (deps.session) {
2900
- try {
2901
- logInteraction(deps.session.id, "grounding_flag", {
2902
- data: { claims: _claimTexts, count: _claims.length },
2903
- });
2904
- } catch {
2905
- /* telemetry is best-effort */
2906
- }
2907
- }
2908
- }
2909
- }
2910
- } catch {
2911
- /* grounding check is best-effort — never break finalize */
2912
- }
2913
- }
2914
-
2915
- const _finalMessages = sanitizeModelMessages(scrubbed) as ModelMessage[];
2916
- if (_f6SynthesisText !== null) {
2917
- _finalMessages.push({
2918
- role: "assistant",
2919
- content: _f6SynthesisText,
2920
- } as ModelMessage);
2921
- }
2922
- deps.appendCompletedTurn(userModelMessage, _finalMessages);
2923
- streamOk = true;
2924
- }
2925
- } catch (responseError: unknown) {
2926
- if (
2927
- !attemptedOverflowRecovery &&
2928
- !assistantText.trim() &&
2929
- modelInfo &&
2930
- isContextLimitError(responseError)
2931
- ) {
2932
- attemptedOverflowRecovery = true;
2933
- continue;
2934
- }
2935
- }
2936
-
2937
- if (signal.aborted) {
2938
- deps.discardAbortedTurn(userModelMessage);
2939
- yield { type: "done" };
2940
- return;
2941
- }
2942
-
2943
- // Phase 5 Fix 5 — the Phase 4 4B forced-finalize-on-ceiling-hit
2944
- // block lived here. With the matrix ceiling no longer halting the
2945
- // stream (it's pure telemetry now), _ceilingHit can never be true
2946
- // and this branch is dead. F6 synthesis above already covers the
2947
- // "stream ended with no final text" case for both natural model
2948
- // termination AND maxToolRounds halt. Keeping the comment as a
2949
- // breadcrumb for future archaeology.
2950
-
2951
- if (!streamOk && assistantText.trim()) {
2952
- deps.appendCompletedTurn(userModelMessage, [{ role: "assistant", content: assistantText }]);
2953
- }
2954
-
2955
- // Fallback: model responded in text despite tool_choice=required
2956
- // Attempt JSON extraction from assistant text → yield as structured_response
2957
- if (_hasResponseTools && !responseToolCalled && pilCtx.taskType && assistantText.trim()) {
2958
- try {
2959
- const jsonMatch = assistantText.match(/\{[\s\S]*\}/);
2960
- if (jsonMatch) {
2961
- const parsed = JSON.parse(jsonMatch[0]) as Record<string, unknown>;
2962
- if (Object.keys(parsed).length > 0) {
2963
- responseToolCalled = true;
2964
- yield {
2965
- type: "structured_response" as StreamChunk["type"],
2966
- structuredResponse: {
2967
- taskType: pilCtx.taskType,
2968
- data: parsed,
2969
- },
2970
- };
2971
- }
2972
- }
2973
- } catch {
2974
- // JSON parse failed — leave as text-fallback
2975
- }
2976
- }
2977
-
2978
- // Track PIL output mode for /optimize metrics
2979
- {
2980
- const { setLastOutputMode } = await import("../pil/store.js");
2981
- if (!_hasResponseTools) setLastOutputMode("conversational");
2982
- else if (responseToolCalled) setLastOutputMode("structured");
2983
- else setLastOutputMode("text-fallback");
2984
- }
2985
-
2986
- // ROUTE-11: Fire routeFeedback after turn completes (success path).
2987
- // Must come AFTER posttool calls (posttool fires during tool-result processing above).
2988
- // Fire-and-forget — no await. Skipped when taskHash is null (bridge absent).
2989
- {
2990
- const turnDuration = Date.now() - turnStartMs;
2991
- if (taskHash) {
2992
- const tier = taskTypeToTier(pilCtx.taskType);
2993
- void routeFeedback(
2994
- taskHash,
2995
- tier,
2996
- runtime.modelId,
2997
- "success", // Phase 6: all normal completions = 'success'
2998
- 0, // retryCount: 0 for first attempt
2999
- turnDuration,
3000
- );
3001
- }
3002
- // HTTP path: also report via router store taskHash (covers warm/cold EE routes)
3003
- const storeHash = routerStore.getState().taskHash;
3004
- if (storeHash) {
3005
- reportRouteOutcome(storeHash, "success", turnDuration);
3006
- }
3007
- }
3008
-
3009
- // Detect a tool call emitted as plain TEXT (wrong dialect) in the final
3010
- // assistant answer — the action never ran, so the turn would otherwise
3011
- // end silently with broken/half-done work (live: deepseek session
3012
- // 905d564dbde4 emitted `<read_file>` as text after a destructive edit).
3013
- // Detect regardless of how many real tool calls already succeeded: the
3014
- // common failure is the model doing a few real tools, then emitting the
3015
- // NEXT call as text and stopping (live deepseek-native, full-fix CLI: 2
3016
- // real read_file calls, then `<read_file><path>` as text → silent stop).
3017
- // An earlier `activeToolCalls.length === 0` guard suppressed exactly
3018
- // that case. Detector precision (structural invocation shape, not a bare
3019
- // mention) guards against false-firing on a normal final answer.
3020
- const _textToolCall = detectTextEmittedToolCall(assistantText);
3021
-
3022
- // Interaction log: agent response complete
3023
- try {
3024
- if (deps.session) {
3025
- const sb = statusBarStore.getState();
3026
- const turnDurationMs = Date.now() - turnStartMs;
3027
- // BUG-A telemetry — detect raw DeepSeek native tool-call markup
3028
- // leaking into assistant text. Signature is `<||DSML||` (the
3029
- // fullwidth vertical bars are NOT pipes, they're U+FF5C).
3030
- const _dsmlSig = "||DSML||";
3031
- const _dsmlMatches = assistantText.includes(_dsmlSig);
3032
- const _codeBlockBash = /```\s*bash\b/i.test(assistantText);
3033
- logInteraction(deps.session.id, "agent_response", {
3034
- model: turnModelId,
3035
- inputTokens: sb.in_tokens,
3036
- outputTokens: sb.out_tokens,
3037
- durationMs: turnDurationMs,
3038
- data: {
3039
- textLength: assistantText.length,
3040
- toolCallCount: activeToolCalls.length,
3041
- compacted: deps.getCompactedThisTurn(),
3042
- dsmlLeak: _dsmlMatches,
3043
- bashCodeBlock: _codeBlockBash,
3044
- textToolXmlLeak: _textToolCall.detected,
3045
- textToolXmlTool: _textToolCall.tool,
3046
- },
3047
- });
3048
- }
3049
- } catch {
3050
- /* fail-open */
3051
- }
3052
-
3053
- // Surface the round-cap stop so the user knows why the agent halted
3054
- // (session 7dcf8fd7d6a4 hit stepCountIs(100) silently, looked like a
3055
- // crash). AI SDK reports finishReason='tool-calls' when the step cap
3056
- // fires with tool calls still pending — distinct from 'stop' (model
3057
- // chose to end). We only warn when stepNumber ≥ cap so a model that
3058
- // legitimately terminates mid-tool-call (rare) doesn't get a false
3059
- // warning.
3060
- if (_lastFinishReason === "tool-calls" && stepNumber >= deps.maxToolRounds - 1) {
3061
- yield {
3062
- type: "content",
3063
- content:
3064
- `\n\n[Stopped: hit max-tool-rounds=${deps.maxToolRounds}. ` +
3065
- `Re-run with \`--max-tool-rounds ${deps.maxToolRounds * 2}\` to continue, ` +
3066
- "or accept the partial result above.]\n",
3067
- };
3068
- }
3069
-
3070
- // Tool-call-as-text leak: the model wrote a tool invocation as plain
3071
- // text (wrong dialect) and made NO real tool call, so the action never
3072
- // ran. Auto-recover ONCE: append a corrective message and re-run the
3073
- // turn so the model can invoke the tool properly. The just-finished
3074
- // (text-only) turn is already persisted above — the model sees its own
3075
- // mistake plus the correction. Mirrors the proven phase-switch re-entry
3076
- // (it also pushes to deps.messages then `continue`s); bounded by
3077
- // MAX_TEXT_TOOL_RESTEER so a persistently-degrading model can't loop.
3078
- if (_textToolCall.detected && streamOk && textToolReSteerCount < MAX_TEXT_TOOL_RESTEER) {
3079
- textToolReSteerCount++;
3080
- // Recover the model's INTENT from the leaked markup (DeepSeek-native
3081
- // DSML carries the tool + args) so the corrective restates the exact
3082
- // call — far more effective than a generic "use the tool" nudge.
3083
- const _parsedCalls = parseDsmlToolCalls(assistantText);
3084
- const _intent =
3085
- _parsedCalls.length > 0
3086
- ? ` You appear to have intended: ${_parsedCalls
3087
- .map(
3088
- (c) =>
3089
- `${c.name}(${Object.entries(c.args)
3090
- .map(([k, v]) => `${k}=${JSON.stringify(v)}`)
3091
- .join(", ")})`,
3092
- )
3093
- .join("; ")}. Make those exact call(s) via the tool interface now.`
3094
- : "";
3095
- deps.messages.push({
3096
- role: "user",
3097
- content:
3098
- `Your previous reply wrote a \`${_textToolCall.tool}\` tool call as XML/text. That is NOT how tools are invoked here — ` +
3099
- "writing tool calls as text does nothing, so the action did not run. " +
3100
- "Use the actual tool-calling interface (function/tool calls) to perform the action now. " +
3101
- "Do NOT output XML tags like <read_file>, <write_to_file>, <execute_command>, or <tool_call> (or DSML markup) as text." +
3102
- _intent,
3103
- });
3104
- if (deps.session) {
3105
- try {
3106
- logInteraction(deps.session.id, "text_tool_resteer", {
3107
- model: turnModelId,
3108
- data: { tool: _textToolCall.tool, attempt: textToolReSteerCount },
3109
- });
3110
- } catch {
3111
- /* telemetry best-effort */
3112
- }
3113
- }
3114
- {
3115
- const _gar = (globalThis as Record<string, unknown>).__muonroiAgentRuntime as
3116
- | { emitEvent: (e: unknown) => void }
3117
- | undefined;
3118
- _gar?.emitEvent({
3119
- t: "event",
3120
- kind: "toast",
3121
- level: "info",
3122
- text: `model wrote a ${_textToolCall.tool} tool call as text — re-steering to use the tool interface`,
3123
- });
3124
- }
3125
- await closeMcp?.().catch(() => {});
3126
- continue;
3127
- }
3128
-
3129
- // Re-steer budget exhausted (or no clean finish): surface the leak so
3130
- // the turn is not SILENTLY wasted. The "answer" above is unexecuted XML.
3131
- if (_textToolCall.detected) {
3132
- yield {
3133
- type: "content",
3134
- content:
3135
- `\n\n[⚠ The model wrote a \`${_textToolCall.tool}\` tool call as TEXT instead of invoking the tool, ` +
3136
- "so that action did NOT run and this turn made no real progress. " +
3137
- "Re-run the request (optionally with a more capable model) — the tool interface was not used.]\n",
3138
- };
3139
- const _gar = (globalThis as Record<string, unknown>).__muonroiAgentRuntime as
3140
- | { emitEvent: (e: unknown) => void }
3141
- | undefined;
3142
- _gar?.emitEvent({
3143
- t: "event",
3144
- kind: "toast",
3145
- level: "warn",
3146
- text: `model emitted a ${_textToolCall.tool} tool call as text — action not executed`,
3147
- });
3148
- }
3149
-
3150
- const stopInput: StopHookInput = {
3151
- hook_event_name: "Stop",
3152
- session_id: deps.session?.id,
3153
- cwd: deps.bash.getCwd(),
3154
- };
3155
- await deps.fireHook(stopInput, signal).catch(() => {});
3156
-
3157
- // Debug trace: emit pipeline summary
3158
- if (_debugOn) {
3159
- const sb = statusBarStore.getState();
3160
- const defaultInfo = getModelInfo(deps.modelId);
3161
- const usedInfo = getModelInfo(turnModelId);
3162
- const routerSaved =
3163
- defaultInfo && usedInfo && defaultInfo.outputPrice > usedInfo.outputPrice
3164
- ? (sb.out_tokens * (defaultInfo.outputPrice - usedInfo.outputPrice)) / 1_000_000
3165
- : 0;
3166
- const cacheSaved =
3167
- sb.cache_read_tokens > 0 && defaultInfo
3168
- ? (sb.cache_read_tokens *
3169
- (defaultInfo.inputPrice - (defaultInfo.cachedInputPrice ?? defaultInfo.inputPrice * 0.1))) /
3170
- 1_000_000
3171
- : 0;
3172
- const trace: TurnTrace = {
3173
- turn_id: _debugTurnId,
3174
- timestamp: turnStartMs,
3175
- raw_prompt: userMessage,
3176
- steps: _debugSteps,
3177
- model_requested: deps.modelId,
3178
- model_used: turnModelId,
3179
- routed: turnModelId !== deps.modelId,
3180
- input_tokens: sb.in_tokens,
3181
- output_tokens: sb.out_tokens,
3182
- cache_read_tokens: sb.cache_read_tokens,
3183
- cost_usd: sb.session_usd,
3184
- estimated_savings: {
3185
- pil_tokens_saved: _pilEnrichmentDeltaSnapshot > 0 ? _pilEnrichmentDeltaSnapshot : 0,
3186
- cache_tokens_saved: sb.cache_read_tokens,
3187
- router_cost_saved_usd: routerSaved,
3188
- total_tokens_saved:
3189
- (_pilEnrichmentDeltaSnapshot > 0 ? _pilEnrichmentDeltaSnapshot : 0) + sb.cache_read_tokens,
3190
- total_cost_saved_usd: routerSaved + cacheSaved,
3191
- },
3192
- };
3193
- recordTurnTrace(trace);
3194
-
3195
- const traceLines: string[] = [];
3196
- traceLines.push("\n┌─ Pipeline Trace ─────────────────────────");
3197
- for (const step of _debugSteps) {
3198
- const dur = step.duration_ms < 1 ? "<1ms" : `${step.duration_ms}ms`;
3199
- const saved = step.tokens_saved ? ` (saved ~${step.tokens_saved} tok)` : "";
3200
- traceLines.push(`│ ▸ ${step.name} [${dur}]${saved}`);
3201
- traceLines.push(`│ ${step.output_summary}`);
3202
- }
3203
- const routeLabel = trace.routed ? `${trace.model_requested}→${trace.model_used}` : trace.model_used;
3204
- traceLines.push(
3205
- `│ Model: ${routeLabel} | ↑${sb.in_tokens} ↓${sb.out_tokens} | $${sb.session_usd.toFixed(4)}`,
3206
- );
3207
- if (trace.estimated_savings.total_cost_saved_usd > 0) {
3208
- traceLines.push(
3209
- `│ Savings: ~${trace.estimated_savings.total_tokens_saved} tok, ~$${trace.estimated_savings.total_cost_saved_usd.toFixed(4)}`,
3210
- );
3211
- }
3212
- traceLines.push("└──────────────────────────────────────────\n");
3213
- yield { type: "content", content: traceLines.join("\n") };
3214
- }
3215
-
3216
- if (modelInfo?.contextWindow) {
3217
- await deps.postTurnCompact(provider, system, modelInfo.contextWindow, signal);
3218
- }
3219
- yield { type: "done" };
3220
- return;
3221
- } catch (err: unknown) {
3222
- if (signal.aborted) {
3223
- deps.discardAbortedTurn(userModelMessage);
3224
- // ROUTE-11: Fire routeFeedback for cancelled turns (abort path).
3225
- // Fire-and-forget — no await. Skipped when taskHash is null.
3226
- {
3227
- const turnDuration = Date.now() - turnStartMs;
3228
- if (taskHash) {
3229
- const tier = taskTypeToTier(pilCtx.taskType);
3230
- void routeFeedback(taskHash, tier, runtime.modelId, "cancelled", 0, turnDuration);
3231
- }
3232
- const storeHash = routerStore.getState().taskHash;
3233
- if (storeHash) {
3234
- reportRouteOutcome(storeHash, "cancelled", turnDuration);
3235
- }
3236
- }
3237
- yield { type: "content", content: "\n\n[Cancelled]" };
3238
- yield { type: "done" };
3239
- return;
3240
- }
3241
-
3242
- if (!attemptedOverflowRecovery && !assistantText.trim() && modelInfo && isContextLimitError(err)) {
3243
- attemptedOverflowRecovery = true;
3244
- continue;
3245
- }
3246
-
3247
- // Transient network/server error retry — up to MAX_STREAM_RETRIES extra attempts.
3248
- // Only retry when no content has flowed yet (assistantText empty) to avoid
3249
- // partial-output corruption. Honour the abort signal between retries.
3250
- // Skip retry on a stall abort: the provider is unresponsive, so a retry
3251
- // just burns another full stall timeout of silence — surface it instead.
3252
- if (!assistantText.trim() && streamRetryCount < MAX_STREAM_RETRIES && !signal.aborted && !stallTriggered) {
3253
- const { transient } = classifyStreamError(err);
3254
- if (transient) {
3255
- streamRetryCount++;
3256
- // Exponential backoff: 500 → 2000 ms with ±25% jitter
3257
- const baseMs = 500;
3258
- const expMs = Math.min(baseMs * 4 ** (streamRetryCount - 1), 8_000);
3259
- const spread = expMs * 0.25;
3260
- const nextDelayMs = Math.round(expMs + (Math.random() * 2 - 1) * spread);
3261
- const errorName = err instanceof Error ? err.name : "Error";
3262
- const errorMessage = err instanceof Error ? err.message : String(err);
3263
- // Emit harness telemetry event
3264
- try {
3265
- const _ar = (globalThis as Record<string, unknown>).__muonroiAgentRuntime as
3266
- | { emitEvent: (e: unknown) => void }
3267
- | undefined;
3268
- _ar?.emitEvent({
3269
- t: "event",
3270
- kind: "stream-retry",
3271
- attempt: streamRetryCount,
3272
- maxAttempts: MAX_STREAM_RETRIES + 1,
3273
- errorName,
3274
- errorMessage,
3275
- nextDelayMs,
3276
- });
3277
- } catch {
3278
- /* best-effort */
3279
- }
3280
- try {
3281
- if (deps.session) {
3282
- logInteraction(deps.session.id, "stream_retry", {
3283
- data: {
3284
- attempt: streamRetryCount,
3285
- maxAttempts: MAX_STREAM_RETRIES + 1,
3286
- errorName,
3287
- errorMessage: errorMessage.slice(0, 200),
3288
- nextDelayMs,
3289
- },
3290
- });
3291
- }
3292
- } catch {
3293
- /* fail-open */
3294
- }
3295
- await new Promise<void>((resolve) => setTimeout(resolve, nextDelayMs));
3296
- if (!signal.aborted) {
3297
- continue;
3298
- }
3299
- }
3300
- }
3301
-
3302
- const authError = isAuthenticationError(err);
3303
- // Stall aborts carry an opaque DOMException; show the clear stall
3304
- // message instead of the raw abort reason.
3305
- const friendly = stallTriggered
3306
- ? STALL_ERROR_MESSAGE
3307
- : humanizeApiError(err, { modelId: runtime.modelId, providerId: runtime.modelInfo?.provider });
3308
- notifyObserver(observer?.onError, {
3309
- message: friendly,
3310
- timestamp: Date.now(),
3311
- });
3312
- yield {
3313
- type: "error",
3314
- content: friendly,
3315
- isAuthError: authError,
3316
- };
3317
- if (assistantText.trim()) {
3318
- deps.appendCompletedTurn(userModelMessage, [{ role: "assistant", content: assistantText }]);
3319
- } else if (deps.session && userWriteAheadSeq != null) {
3320
- // Phase A5 — Stream threw before producing assistant text. The
3321
- // write-ahead user row is stuck at `status='pending'`. Mark it
3322
- // errored so forensics + recovery can distinguish "in-flight"
3323
- // from "crashed mid-flight".
3324
- markMessageErrored(deps.session.id, userWriteAheadSeq);
3325
- }
3326
-
3327
- // ROUTE-11: Fire routeFeedback for failed turns (error path).
3328
- // Must come AFTER posttool calls. Fire-and-forget — no await.
3329
- {
3330
- const turnDuration = Date.now() - turnStartMs;
3331
- if (taskHash) {
3332
- const tier = taskTypeToTier(pilCtx.taskType);
3333
- void routeFeedback(taskHash, tier, runtime.modelId, "fail", 0, turnDuration);
3334
- }
3335
- const storeHash = routerStore.getState().taskHash;
3336
- if (storeHash) {
3337
- reportRouteOutcome(storeHash, "fail", turnDuration);
3338
- }
3339
- }
3340
-
3341
- const stopFailureInput: StopFailureHookInput = {
3342
- hook_event_name: "StopFailure",
3343
- error: friendly,
3344
- session_id: deps.session?.id,
3345
- cwd: deps.bash.getCwd(),
3346
- };
3347
- await deps.fireHook(stopFailureInput, signal).catch(() => {});
3348
-
3349
- if (modelInfo?.contextWindow) {
3350
- await deps.postTurnCompact(provider, system, modelInfo.contextWindow, signal);
3351
- }
3352
- yield { type: "done" };
3353
- return;
3354
- } finally {
3355
- await closeMcp?.().catch(() => {});
3356
- }
3357
- }
3358
- } finally {
3359
- if (deps.getAbortController()?.signal === signal) {
3360
- deps.setAbortController(null);
3361
- }
3362
- }
3363
- }
3364
- }