muonroi-cli 1.8.4 → 1.9.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 (562) hide show
  1. package/LICENSE +17 -5
  2. package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
  3. package/dist/packages/agent-harness-core/src/driver.js +46 -0
  4. package/dist/packages/agent-harness-core/src/event-filter.js +11 -0
  5. package/dist/packages/agent-harness-core/src/event-redact.js +7 -0
  6. package/dist/packages/agent-harness-core/src/event-tee.d.ts +64 -0
  7. package/dist/packages/agent-harness-core/src/event-tee.js +104 -0
  8. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +25 -0
  9. package/dist/packages/agent-harness-core/src/mcp-server.js +169 -21
  10. package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
  11. package/dist/packages/agent-harness-core/src/protocol.d.ts +90 -4
  12. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  13. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  14. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  15. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  16. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  17. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  18. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  19. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  20. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  21. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  22. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  23. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  24. package/dist/src/agent-harness/mock-model.d.ts +38 -0
  25. package/dist/src/agent-harness/mock-model.js +69 -3
  26. package/dist/src/agent-harness/test-spawn.js +31 -0
  27. package/dist/src/chat/chat-keychain.d.ts +7 -12
  28. package/dist/src/chat/chat-keychain.js +19 -86
  29. package/dist/src/cli/config/screen-providers.js +1 -1
  30. package/dist/src/cli/cost-forensics.d.ts +10 -0
  31. package/dist/src/cli/cost-forensics.js +18 -3
  32. package/dist/src/cli/keys-bundle.d.ts +1 -1
  33. package/dist/src/cli/keys-bundle.js +1 -1
  34. package/dist/src/cli/keys.d.ts +10 -47
  35. package/dist/src/cli/keys.js +31 -399
  36. package/dist/src/council/clarifier.d.ts +31 -3
  37. package/dist/src/council/clarifier.js +220 -32
  38. package/dist/src/council/context.js +49 -15
  39. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  40. package/dist/src/council/debate-checkpoint.js +176 -0
  41. package/dist/src/council/debate-planner.js +54 -5
  42. package/dist/src/council/debate-summary.d.ts +25 -0
  43. package/dist/src/council/debate-summary.js +85 -0
  44. package/dist/src/council/debate.d.ts +169 -2
  45. package/dist/src/council/debate.js +1265 -135
  46. package/dist/src/council/index.d.ts +108 -1
  47. package/dist/src/council/index.js +670 -197
  48. package/dist/src/council/leader.d.ts +26 -0
  49. package/dist/src/council/leader.js +150 -9
  50. package/dist/src/council/llm.d.ts +94 -0
  51. package/dist/src/council/llm.js +348 -55
  52. package/dist/src/council/panel-select.d.ts +30 -0
  53. package/dist/src/council/panel-select.js +82 -0
  54. package/dist/src/council/planner.js +40 -0
  55. package/dist/src/council/preflight.d.ts +17 -0
  56. package/dist/src/council/preflight.js +50 -2
  57. package/dist/src/council/prompts.d.ts +39 -4
  58. package/dist/src/council/prompts.js +256 -69
  59. package/dist/src/council/stance-recall.d.ts +42 -0
  60. package/dist/src/council/stance-recall.js +57 -0
  61. package/dist/src/council/strip-think.d.ts +17 -0
  62. package/dist/src/council/strip-think.js +33 -0
  63. package/dist/src/council/types.d.ts +138 -0
  64. package/dist/src/ee/artifact-cache.d.ts +16 -0
  65. package/dist/src/ee/artifact-cache.js +32 -0
  66. package/dist/src/ee/auth.d.ts +20 -0
  67. package/dist/src/ee/auth.js +54 -2
  68. package/dist/src/ee/bridge.d.ts +10 -0
  69. package/dist/src/ee/bridge.js +58 -0
  70. package/dist/src/ee/client.js +109 -21
  71. package/dist/src/ee/ee-onboarding.js +6 -26
  72. package/dist/src/ee/export-transcripts.d.ts +1 -0
  73. package/dist/src/ee/export-transcripts.js +8 -10
  74. package/dist/src/ee/extract-session.js +29 -0
  75. package/dist/src/ee/extract-style.d.ts +58 -0
  76. package/dist/src/ee/extract-style.js +270 -0
  77. package/dist/src/ee/recall-ledger.d.ts +9 -0
  78. package/dist/src/ee/recall-ledger.js +3 -0
  79. package/dist/src/ee/scope.d.ts +1 -0
  80. package/dist/src/ee/scope.js +26 -1
  81. package/dist/src/ee/search.d.ts +7 -0
  82. package/dist/src/ee/search.js +24 -0
  83. package/dist/src/ee/transcript-emit.js +2 -0
  84. package/dist/src/ee/types.d.ts +22 -0
  85. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  86. package/dist/src/ee/who-am-i-brain.js +220 -0
  87. package/dist/src/ee/who-am-i.d.ts +10 -3
  88. package/dist/src/ee/who-am-i.js +12 -0
  89. package/dist/src/ee/workflow-event.d.ts +48 -0
  90. package/dist/src/ee/workflow-event.js +81 -0
  91. package/dist/src/flow/compaction/compress.d.ts +3 -3
  92. package/dist/src/flow/compaction/compress.js +58 -8
  93. package/dist/src/flow/compaction/extract.d.ts +4 -7
  94. package/dist/src/flow/compaction/extract.js +50 -10
  95. package/dist/src/flow/compaction/index.d.ts +14 -1
  96. package/dist/src/flow/compaction/index.js +96 -3
  97. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  98. package/dist/src/flow/compaction/input-guard.js +43 -0
  99. package/dist/src/flow/compaction/progress.d.ts +35 -0
  100. package/dist/src/flow/compaction/progress.js +35 -0
  101. package/dist/src/flow/fold-planning.d.ts +36 -0
  102. package/dist/src/flow/fold-planning.js +83 -0
  103. package/dist/src/flow/hierarchy.d.ts +146 -0
  104. package/dist/src/flow/hierarchy.js +427 -0
  105. package/dist/src/flow/index.d.ts +1 -0
  106. package/dist/src/flow/index.js +2 -0
  107. package/dist/src/flow/run-artifacts.d.ts +102 -0
  108. package/dist/src/flow/run-artifacts.js +208 -0
  109. package/dist/src/generated/version.d.ts +1 -1
  110. package/dist/src/generated/version.js +1 -1
  111. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  112. package/dist/src/gsd/assessment-schema.js +134 -0
  113. package/dist/src/gsd/capability-registry.d.ts +45 -0
  114. package/dist/src/gsd/capability-registry.js +337 -0
  115. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  116. package/dist/src/gsd/complexity-assessor.js +152 -0
  117. package/dist/src/gsd/config-bridge.d.ts +7 -0
  118. package/dist/src/gsd/config-bridge.js +114 -0
  119. package/dist/src/gsd/config-loader.d.ts +27 -0
  120. package/dist/src/gsd/config-loader.js +50 -0
  121. package/dist/src/gsd/council-context.d.ts +44 -0
  122. package/dist/src/gsd/council-context.js +114 -0
  123. package/dist/src/gsd/ee-closure.d.ts +28 -0
  124. package/dist/src/gsd/ee-closure.js +49 -0
  125. package/dist/src/gsd/flags.d.ts +66 -0
  126. package/dist/src/gsd/flags.js +102 -0
  127. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  128. package/dist/src/gsd/gsd-dispatch.js +131 -0
  129. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  130. package/dist/src/gsd/gsd-runtime.js +37 -0
  131. package/dist/src/gsd/host-adapter.d.ts +11 -0
  132. package/dist/src/gsd/host-adapter.js +29 -0
  133. package/dist/src/gsd/index.d.ts +24 -1
  134. package/dist/src/gsd/index.js +27 -0
  135. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  136. package/dist/src/gsd/loop-host-contract.js +39 -0
  137. package/dist/src/gsd/loop-host.d.ts +69 -0
  138. package/dist/src/gsd/loop-host.js +245 -0
  139. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  140. package/dist/src/gsd/loop-resolver.js +79 -0
  141. package/dist/src/gsd/model-tier.d.ts +13 -0
  142. package/dist/src/gsd/model-tier.js +45 -0
  143. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  144. package/dist/src/gsd/mutation-gate.js +41 -0
  145. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  146. package/dist/src/gsd/native-roadmap.js +343 -0
  147. package/dist/src/gsd/native-state.d.ts +47 -0
  148. package/dist/src/gsd/native-state.js +220 -0
  149. package/dist/src/gsd/paths.d.ts +23 -0
  150. package/dist/src/gsd/paths.js +66 -0
  151. package/dist/src/gsd/phase-dag.d.ts +12 -0
  152. package/dist/src/gsd/phase-dag.js +94 -0
  153. package/dist/src/gsd/phase-sync.d.ts +42 -0
  154. package/dist/src/gsd/phase-sync.js +321 -0
  155. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  156. package/dist/src/gsd/pil-gate-context.js +64 -0
  157. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  158. package/dist/src/gsd/pil-gate-critic.js +74 -0
  159. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  160. package/dist/src/gsd/plan-council-prompts.js +79 -0
  161. package/dist/src/gsd/plan-council.d.ts +44 -0
  162. package/dist/src/gsd/plan-council.js +283 -0
  163. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  164. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  165. package/dist/src/gsd/product-workspace.d.ts +13 -0
  166. package/dist/src/gsd/product-workspace.js +124 -0
  167. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  168. package/dist/src/gsd/ship-bridge.js +65 -0
  169. package/dist/src/gsd/state-document.d.ts +40 -0
  170. package/dist/src/gsd/state-document.js +163 -0
  171. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  172. package/dist/src/gsd/verdict-schema.js +144 -0
  173. package/dist/src/gsd/verify-context.d.ts +22 -0
  174. package/dist/src/gsd/verify-context.js +27 -0
  175. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  176. package/dist/src/gsd/verify-council-prompts.js +85 -0
  177. package/dist/src/gsd/verify-council.d.ts +25 -0
  178. package/dist/src/gsd/verify-council.js +119 -0
  179. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  180. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  181. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  182. package/dist/src/gsd/workflow-engine.js +207 -0
  183. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  184. package/dist/src/gsd/workflow-tools.js +277 -0
  185. package/dist/src/headless/council-answers.js +4 -0
  186. package/dist/src/hooks/index.js +1 -1
  187. package/dist/src/index.js +172 -270
  188. package/dist/src/lsp/builtins.js +3 -1
  189. package/dist/src/lsp/manager.d.ts +5 -1
  190. package/dist/src/lsp/manager.js +249 -3
  191. package/dist/src/lsp/npm-cache.d.ts +11 -1
  192. package/dist/src/lsp/npm-cache.js +17 -1
  193. package/dist/src/lsp/runtime.d.ts +6 -1
  194. package/dist/src/lsp/runtime.js +17 -1
  195. package/dist/src/lsp/types.d.ts +83 -1
  196. package/dist/src/lsp/types.js +10 -0
  197. package/dist/src/maintain/pr-builder.js +23 -13
  198. package/dist/src/mcp/auto-setup.js +57 -32
  199. package/dist/src/mcp/client-pool.js +44 -16
  200. package/dist/src/mcp/lsp-tools.d.ts +5 -1
  201. package/dist/src/mcp/lsp-tools.js +93 -2
  202. package/dist/src/mcp/mcp-keychain.d.ts +3 -5
  203. package/dist/src/mcp/mcp-keychain.js +9 -49
  204. package/dist/src/mcp/research-onboarding.js +8 -7
  205. package/dist/src/mcp/runtime.js +34 -2
  206. package/dist/src/mcp/setup-guide-text.d.ts +1 -1
  207. package/dist/src/mcp/setup-guide-text.js +22 -2
  208. package/dist/src/mcp/tools-server.d.ts +10 -0
  209. package/dist/src/mcp/tools-server.js +10 -2
  210. package/dist/src/models/catalog-client.d.ts +87 -0
  211. package/dist/src/models/catalog-client.js +105 -38
  212. package/dist/src/models/catalog.json +528 -265
  213. package/dist/src/models/registry.d.ts +22 -7
  214. package/dist/src/models/registry.js +73 -10
  215. package/dist/src/ops/doctor.js +1 -1
  216. package/dist/src/orchestrator/ask-user.d.ts +61 -0
  217. package/dist/src/orchestrator/ask-user.js +65 -0
  218. package/dist/src/orchestrator/auto-commit.js +1 -1
  219. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  220. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  221. package/dist/src/orchestrator/cache-prefix.js +83 -0
  222. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  223. package/dist/src/orchestrator/compact-request.js +41 -0
  224. package/dist/src/orchestrator/compaction.d.ts +12 -3
  225. package/dist/src/orchestrator/compaction.js +35 -15
  226. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  227. package/dist/src/orchestrator/council-manager.js +74 -32
  228. package/dist/src/orchestrator/council-request.d.ts +49 -0
  229. package/dist/src/orchestrator/council-request.js +62 -0
  230. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  231. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  232. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  233. package/dist/src/orchestrator/error-utils.js +132 -24
  234. package/dist/src/orchestrator/grounding-check.js +39 -1
  235. package/dist/src/orchestrator/interactive-pause.d.ts +26 -0
  236. package/dist/src/orchestrator/interactive-pause.js +36 -0
  237. package/dist/src/orchestrator/message-processor.d.ts +4 -0
  238. package/dist/src/orchestrator/message-processor.js +268 -41
  239. package/dist/src/orchestrator/orchestrator.d.ts +64 -3
  240. package/dist/src/orchestrator/orchestrator.js +823 -120
  241. package/dist/src/orchestrator/preprocessor.js +3 -3
  242. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  243. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  244. package/dist/src/orchestrator/prompts.js +17 -17
  245. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  246. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  247. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  248. package/dist/src/orchestrator/retry-classifier.js +46 -2
  249. package/dist/src/orchestrator/safety-askcard.d.ts +1 -1
  250. package/dist/src/orchestrator/safety-askcard.js +5 -2
  251. package/dist/src/orchestrator/safety-intercept.d.ts +50 -0
  252. package/dist/src/orchestrator/safety-intercept.js +62 -0
  253. package/dist/src/orchestrator/scope-reminder.js +1 -1
  254. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  255. package/dist/src/orchestrator/session-experience.js +2 -1
  256. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  257. package/dist/src/orchestrator/should-run-gate.js +18 -0
  258. package/dist/src/orchestrator/stall-watchdog.d.ts +31 -3
  259. package/dist/src/orchestrator/stall-watchdog.js +65 -10
  260. package/dist/src/orchestrator/stream-runner.d.ts +13 -3
  261. package/dist/src/orchestrator/stream-runner.js +115 -49
  262. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  263. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  264. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  265. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  266. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  267. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  268. package/dist/src/orchestrator/tool-engine.d.ts +41 -0
  269. package/dist/src/orchestrator/tool-engine.js +846 -66
  270. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  271. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  272. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  273. package/dist/src/orchestrator/turn-watchdog.d.ts +44 -0
  274. package/dist/src/orchestrator/turn-watchdog.js +84 -0
  275. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  276. package/dist/src/pil/agent-operating-contract.js +6 -4
  277. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  278. package/dist/src/pil/cheap-model-playbook.js +5 -1
  279. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  280. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  281. package/dist/src/pil/discovery-types.d.ts +1 -0
  282. package/dist/src/pil/discovery.d.ts +1 -1
  283. package/dist/src/pil/discovery.js +18 -13
  284. package/dist/src/pil/layer1-intent.d.ts +18 -6
  285. package/dist/src/pil/layer1-intent.js +66 -757
  286. package/dist/src/pil/layer15-context-scan.js +15 -1
  287. package/dist/src/pil/layer1_5-complexity-size.d.ts +7 -0
  288. package/dist/src/pil/layer1_5-complexity-size.js +31 -5
  289. package/dist/src/pil/layer3-ee-injection.js +23 -8
  290. package/dist/src/pil/layer4-gsd.js +69 -16
  291. package/dist/src/pil/layer5-context.js +7 -3
  292. package/dist/src/pil/layer6-output.d.ts +23 -0
  293. package/dist/src/pil/layer6-output.js +5 -1
  294. package/dist/src/pil/llm-classify.d.ts +111 -5
  295. package/dist/src/pil/llm-classify.js +421 -189
  296. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  297. package/dist/src/pil/native-capabilities-workbook.js +8 -0
  298. package/dist/src/pil/pipeline.js +36 -2
  299. package/dist/src/pil/repo-grounding-probe.d.ts +15 -0
  300. package/dist/src/pil/repo-grounding-probe.js +136 -0
  301. package/dist/src/pil/repo-structure-hints.d.ts +7 -0
  302. package/dist/src/pil/repo-structure-hints.js +45 -0
  303. package/dist/src/pil/response-tools.js +5 -3
  304. package/dist/src/pil/schema.d.ts +1 -0
  305. package/dist/src/pil/schema.js +2 -0
  306. package/dist/src/pil/types.d.ts +18 -0
  307. package/dist/src/playbook/directives.d.ts +4 -0
  308. package/dist/src/playbook/directives.js +17 -5
  309. package/dist/src/product-loop/artifact-io.js +4 -0
  310. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  311. package/dist/src/product-loop/backlog-builder.js +30 -6
  312. package/dist/src/product-loop/criteria-seed.d.ts +51 -0
  313. package/dist/src/product-loop/criteria-seed.js +200 -0
  314. package/dist/src/product-loop/discovery-context-format.js +3 -1
  315. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  316. package/dist/src/product-loop/discovery-interview.d.ts +9 -0
  317. package/dist/src/product-loop/discovery-interview.js +60 -12
  318. package/dist/src/product-loop/discovery-recommender.js +2 -1
  319. package/dist/src/product-loop/discovery-schema.js +19 -2
  320. package/dist/src/product-loop/discovery-triage.d.ts +23 -0
  321. package/dist/src/product-loop/discovery-triage.js +109 -0
  322. package/dist/src/product-loop/gather.js +150 -2
  323. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  324. package/dist/src/product-loop/ideal-trace.js +64 -0
  325. package/dist/src/product-loop/index.d.ts +13 -1
  326. package/dist/src/product-loop/index.js +340 -52
  327. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  328. package/dist/src/product-loop/loop-driver.js +330 -106
  329. package/dist/src/product-loop/phase-plan.d.ts +21 -0
  330. package/dist/src/product-loop/phase-plan.js +81 -6
  331. package/dist/src/product-loop/phase-rituals.d.ts +3 -0
  332. package/dist/src/product-loop/phase-rituals.js +8 -3
  333. package/dist/src/product-loop/phase-runner.js +39 -12
  334. package/dist/src/product-loop/plan-adherence-review.d.ts +26 -0
  335. package/dist/src/product-loop/plan-adherence-review.js +144 -0
  336. package/dist/src/product-loop/sprint-runner.d.ts +173 -0
  337. package/dist/src/product-loop/sprint-runner.js +863 -19
  338. package/dist/src/product-loop/types.d.ts +61 -5
  339. package/dist/src/providers/adapter.d.ts +1 -1
  340. package/dist/src/providers/adapter.js +3 -4
  341. package/dist/src/providers/anthropic.d.ts +9 -8
  342. package/dist/src/providers/anthropic.js +13 -47
  343. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  344. package/dist/src/providers/auth/browser-flow.js +1 -1
  345. package/dist/src/providers/auth/grok-oauth.d.ts +1 -0
  346. package/dist/src/providers/auth/grok-oauth.js +30 -5
  347. package/dist/src/providers/auth/openai-oauth.d.ts +1 -0
  348. package/dist/src/providers/auth/openai-oauth.js +15 -1
  349. package/dist/src/providers/auth/registry.js +0 -34
  350. package/dist/src/providers/auth/token-store.d.ts +9 -9
  351. package/dist/src/providers/auth/token-store.js +8 -67
  352. package/dist/src/providers/auth/types.d.ts +9 -1
  353. package/dist/src/providers/auth/types.js +1 -1
  354. package/dist/src/providers/capabilities.d.ts +24 -5
  355. package/dist/src/providers/capabilities.js +42 -24
  356. package/dist/src/providers/endpoints.d.ts +2 -2
  357. package/dist/src/providers/endpoints.js +11 -10
  358. package/dist/src/providers/env-store.d.ts +17 -0
  359. package/dist/src/providers/env-store.js +228 -0
  360. package/dist/src/providers/keychain.d.ts +22 -18
  361. package/dist/src/providers/keychain.js +127 -140
  362. package/dist/src/providers/mcp-vision-bridge.js +56 -146
  363. package/dist/src/providers/openai-compatible.js +8 -1
  364. package/dist/src/providers/pricing.d.ts +2 -2
  365. package/dist/src/providers/pricing.js +3 -13
  366. package/dist/src/providers/runtime.d.ts +43 -3
  367. package/dist/src/providers/runtime.js +88 -14
  368. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  369. package/dist/src/providers/strategies/base.strategy.js +24 -1
  370. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  371. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  372. package/dist/src/providers/strategies/registry.js +4 -4
  373. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  374. package/dist/src/providers/strategies/thinking-mode.js +288 -1
  375. package/dist/src/providers/strategies/xai.strategy.js +27 -0
  376. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  377. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  378. package/dist/src/providers/types.d.ts +5 -6
  379. package/dist/src/providers/types.js +2 -2
  380. package/dist/src/providers/vision-backend.d.ts +47 -0
  381. package/dist/src/providers/vision-backend.js +258 -0
  382. package/dist/src/providers/vision-proxy.d.ts +22 -9
  383. package/dist/src/providers/vision-proxy.js +63 -132
  384. package/dist/src/providers/warm.d.ts +65 -0
  385. package/dist/src/providers/warm.js +145 -0
  386. package/dist/src/providers/wire-debug.js +95 -0
  387. package/dist/src/router/decide.d.ts +13 -0
  388. package/dist/src/router/decide.js +138 -36
  389. package/dist/src/router/peak-hour.d.ts +38 -0
  390. package/dist/src/router/peak-hour.js +107 -0
  391. package/dist/src/router/step-router.js +3 -2
  392. package/dist/src/router/warm.js +4 -5
  393. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  394. package/dist/src/scaffold/continuation-prompt.js +26 -0
  395. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  396. package/dist/src/scaffold/point-to-existing.js +25 -0
  397. package/dist/src/self-qa/agentic-loop.js +6 -5
  398. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  399. package/dist/src/{ui/state → state}/active-run.js +21 -0
  400. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  401. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  402. package/dist/src/state/turn-trace.d.ts +43 -0
  403. package/dist/src/state/turn-trace.js +32 -0
  404. package/dist/src/storage/db.js +2 -1
  405. package/dist/src/storage/index.d.ts +1 -1
  406. package/dist/src/storage/index.js +1 -1
  407. package/dist/src/storage/interaction-log.d.ts +1 -1
  408. package/dist/src/storage/migrations.js +71 -1
  409. package/dist/src/storage/sessions.d.ts +28 -10
  410. package/dist/src/storage/sessions.js +78 -21
  411. package/dist/src/storage/transcript-view.js +1 -1
  412. package/dist/src/storage/transcript.d.ts +51 -0
  413. package/dist/src/storage/transcript.js +340 -15
  414. package/dist/src/tools/file.d.ts +15 -0
  415. package/dist/src/tools/file.js +32 -0
  416. package/dist/src/tools/git-safety.d.ts +19 -0
  417. package/dist/src/tools/git-safety.js +168 -0
  418. package/dist/src/tools/native-tools.d.ts +1 -1
  419. package/dist/src/tools/native-tools.js +81 -1
  420. package/dist/src/tools/registry.d.ts +20 -0
  421. package/dist/src/tools/registry.js +576 -23
  422. package/dist/src/tools/research.d.ts +29 -0
  423. package/dist/src/tools/research.js +233 -0
  424. package/dist/src/types/index.d.ts +147 -4
  425. package/dist/src/ui/app.js +0 -0
  426. package/dist/src/ui/cards/product-status-card.js +1 -1
  427. package/dist/src/ui/components/agent-rail-activities.d.ts +26 -0
  428. package/dist/src/ui/components/agent-rail-activities.js +47 -0
  429. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  430. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  431. package/dist/src/ui/components/compact-progress-card.d.ts +24 -0
  432. package/dist/src/ui/components/compact-progress-card.js +42 -0
  433. package/dist/src/ui/components/context-rail.d.ts +26 -0
  434. package/dist/src/ui/components/context-rail.js +33 -0
  435. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  436. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  437. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  438. package/dist/src/ui/components/council-debate-pill.js +34 -0
  439. package/dist/src/ui/components/council-info-card.js +2 -2
  440. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  441. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  442. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  443. package/dist/src/ui/components/council-message-bubble.js +16 -15
  444. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  445. package/dist/src/ui/components/council-phase-timeline.js +66 -17
  446. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  447. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  448. package/dist/src/ui/components/council-question-card.js +13 -12
  449. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  450. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  451. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  452. package/dist/src/ui/components/council-round-group.js +88 -0
  453. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  454. package/dist/src/ui/components/council-status-list.js +36 -24
  455. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  456. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  457. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  458. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  459. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  460. package/dist/src/ui/components/message-view.d.ts +15 -0
  461. package/dist/src/ui/components/message-view.js +50 -1
  462. package/dist/src/ui/components/prompt-box.js +18 -16
  463. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  464. package/dist/src/ui/components/session-tree-card.js +46 -0
  465. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  466. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  467. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  468. package/dist/src/ui/components/task-list-panel.js +22 -2
  469. package/dist/src/ui/components/tool-group.d.ts +15 -3
  470. package/dist/src/ui/components/tool-group.js +69 -11
  471. package/dist/src/ui/containers/modals-layer.d.ts +4 -2
  472. package/dist/src/ui/containers/modals-layer.js +2 -2
  473. package/dist/src/ui/council-harness-event.d.ts +57 -0
  474. package/dist/src/ui/council-harness-event.js +46 -0
  475. package/dist/src/ui/heartbeat-debug.d.ts +29 -0
  476. package/dist/src/ui/heartbeat-debug.js +45 -0
  477. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  478. package/dist/src/ui/mcp-modal.js +2 -4
  479. package/dist/src/ui/modals/api-key-modal.js +1 -1
  480. package/dist/src/ui/modals/connect-modal.js +4 -3
  481. package/dist/src/ui/modals/model-picker-modal.d.ts +8 -18
  482. package/dist/src/ui/modals/model-picker-modal.js +8 -10
  483. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  484. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  485. package/dist/src/ui/picker-providers.d.ts +1 -1
  486. package/dist/src/ui/picker-providers.js +1 -1
  487. package/dist/src/ui/primitives/index.d.ts +1 -0
  488. package/dist/src/ui/primitives/index.js +2 -0
  489. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  490. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  491. package/dist/src/ui/slash/compact.js +5 -7
  492. package/dist/src/ui/slash/cost.js +1 -1
  493. package/dist/src/ui/slash/council.js +19 -1
  494. package/dist/src/ui/slash/debug.d.ts +3 -31
  495. package/dist/src/ui/slash/debug.js +9 -20
  496. package/dist/src/ui/slash/ee.js +81 -0
  497. package/dist/src/ui/slash/ideal.d.ts +6 -2
  498. package/dist/src/ui/slash/ideal.js +97 -7
  499. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  500. package/dist/src/ui/slash/menu-items.js +23 -20
  501. package/dist/src/ui/slash/registry.d.ts +2 -0
  502. package/dist/src/ui/slash/registry.js +4 -0
  503. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  504. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  505. package/dist/src/ui/status-bar/index.d.ts +1 -1
  506. package/dist/src/ui/status-bar/index.js +7 -3
  507. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  508. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  509. package/dist/src/ui/theme.d.ts +1 -0
  510. package/dist/src/ui/theme.js +2 -0
  511. package/dist/src/ui/types.d.ts +7 -0
  512. package/dist/src/ui/use-app-logic.js +0 -0
  513. package/dist/src/ui/utils/agent-activities.d.ts +39 -0
  514. package/dist/src/ui/utils/agent-activities.js +96 -0
  515. package/dist/src/ui/utils/format.d.ts +14 -0
  516. package/dist/src/ui/utils/format.js +23 -3
  517. package/dist/src/ui/utils/group-tool-entries.d.ts +26 -0
  518. package/dist/src/ui/utils/group-tool-entries.js +111 -0
  519. package/dist/src/ui/utils/tool-summary.d.ts +21 -0
  520. package/dist/src/ui/utils/tool-summary.js +91 -0
  521. package/dist/src/usage/downgrade.js +2 -2
  522. package/dist/src/usage/product-ledger.js +2 -2
  523. package/dist/src/utils/event-loop-monitor.d.ts +85 -0
  524. package/dist/src/utils/event-loop-monitor.js +107 -0
  525. package/dist/src/utils/install-manager.js +2 -1
  526. package/dist/src/utils/llm-deadline.d.ts +14 -0
  527. package/dist/src/utils/llm-deadline.js +19 -0
  528. package/dist/src/utils/logger.js +2 -2
  529. package/dist/src/utils/loop-profiler.d.ts +102 -0
  530. package/dist/src/utils/loop-profiler.js +202 -0
  531. package/dist/src/utils/permission-mode.js +5 -3
  532. package/dist/src/utils/redactor.js +1 -1
  533. package/dist/src/utils/settings.d.ts +180 -5
  534. package/dist/src/utils/settings.js +271 -31
  535. package/dist/src/utils/side-question.d.ts +1 -2
  536. package/dist/src/utils/side-question.js +2 -2
  537. package/dist/src/utils/visible-retry.d.ts +11 -0
  538. package/dist/src/utils/visible-retry.js +10 -1
  539. package/dist/src/verify/entrypoint.d.ts +1 -1
  540. package/dist/src/verify/entrypoint.js +52 -17
  541. package/dist/src/verify/orchestrator.d.ts +1 -1
  542. package/dist/src/verify/orchestrator.js +20 -3
  543. package/dist/src/verify/recipes.d.ts +13 -0
  544. package/dist/src/verify/recipes.js +15 -0
  545. package/package.json +134 -132
  546. package/dist/src/cli/bw-vault.d.ts +0 -55
  547. package/dist/src/cli/bw-vault.js +0 -133
  548. package/dist/src/mcp/ee-tools.d.ts +0 -46
  549. package/dist/src/mcp/ee-tools.js +0 -193
  550. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  551. package/dist/src/providers/auth/gcloud.js +0 -102
  552. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  553. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  554. package/dist/src/providers/gemini.d.ts +0 -11
  555. package/dist/src/providers/gemini.js +0 -45
  556. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  557. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  558. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  559. package/dist/src/providers/strategies/google.strategy.js +0 -174
  560. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  561. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  562. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -1,20 +1,31 @@
1
1
  import * as fs from "node:fs";
2
- import { generateText, stepCountIs } from "ai";
2
+ import { generateText, stepCountIs, streamText } from "ai";
3
3
  import { getDefaultEEClient } from "../ee/intercept.js";
4
4
  import { emitMatches } from "../ee/render.js";
5
+ import { getMcpKey } from "../mcp/mcp-keychain.js";
5
6
  import { buildMcpToolSet } from "../mcp/runtime.js";
6
- import { getProviderCapabilities } from "../providers/capabilities.js";
7
+ import { getModelInfo } from "../models/registry.js";
8
+ import { getProviderCapabilities, resolveTemperature } from "../providers/capabilities.js";
7
9
  import { loadKeyForProvider, ProviderKeyMissingError } from "../providers/keychain.js";
8
- import { createProviderFactoryAsync, detectProviderForModel, resolveModelRuntime } from "../providers/runtime.js";
10
+ import { createProviderFactoryAsync, detectProviderForModel, resolveModelRuntime, shouldDropParam, } from "../providers/runtime.js";
11
+ import { wireDebug } from "../providers/wire-debug.js";
12
+ import { statusBarStore } from "../state/status-bar-store.js";
13
+ import { recordUsageEvent } from "../storage/index.js";
9
14
  import { createBuiltinTools as createTools } from "../tools/registry.js";
10
15
  import { appendCostLog } from "../usage/cost-log.js";
11
16
  import { projectCostUSD } from "../usage/estimator.js";
12
17
  import { withDeadlineRace, withTimeoutSignal } from "../utils/llm-deadline.js";
18
+ import { logger } from "../utils/logger.js";
13
19
  import { loadMcpServers } from "../utils/settings.js";
14
20
  import { withVisibleRetry } from "../utils/visible-retry.js";
15
21
  import { buildResearchSystemPrompt } from "./prompts.js";
22
+ import { stripThinkBlocks } from "./strip-think.js";
16
23
  /**
17
- * Resolve a provider factory for a council sub-call, OAuth-aware.
24
+ * Register a provider factory for a council sub-call, OAuth-aware.
25
+ *
26
+ * A council roster routes stances to providers the session itself never built,
27
+ * so their factory must exist in the registry before `resolveModelRuntime` can
28
+ * derive it from the model id.
18
29
  *
19
30
  * The council reachability gate (`isProviderReachable` in leader.ts) counts
20
31
  * OAuth-authenticated providers as usable (via `getConfiguredProviders`), so a
@@ -27,7 +38,7 @@ import { buildResearchSystemPrompt } from "./prompts.js";
27
38
  * refreshes the stored OAuth bearer token. Only the expected missing-key case
28
39
  * is swallowed; unexpected errors propagate.
29
40
  */
30
- async function resolveCouncilFactory(providerId) {
41
+ async function ensureCouncilFactory(providerId) {
31
42
  let apiKey;
32
43
  try {
33
44
  apiKey = await loadKeyForProvider(providerId);
@@ -37,8 +48,7 @@ async function resolveCouncilFactory(providerId) {
37
48
  throw err;
38
49
  // OAuth-only provider — createProviderFactoryAsync injects the bearer token.
39
50
  }
40
- const { factory } = await createProviderFactoryAsync(providerId, apiKey ? { apiKey } : {});
41
- return factory;
51
+ await createProviderFactoryAsync(providerId, apiKey ? { apiKey } : {});
42
52
  }
43
53
  function getDebugLogPath() {
44
54
  const p = process.env.MUONROI_COUNCIL_DEBUG_LOG;
@@ -186,6 +196,62 @@ function logCouncilCost(args) {
186
196
  }).catch(() => undefined);
187
197
  return usage;
188
198
  }
199
+ /**
200
+ * Record a council LLM call into the `usage_events` table with source="council".
201
+ *
202
+ * This is the SINGLE source of truth for council usage accounting: it fires from
203
+ * inside every council generate/debate/research call so ALL council entry points
204
+ * (the /council slash path, auto-council, and every /ideal phase — clarifier,
205
+ * research, generate, sprint) land in usage_events. Before this existed, only
206
+ * the loop-driver's `runDebate` call site externally wrapped usage recording, so
207
+ * `runCouncilV2` (/council + auto-council) and the non-debate /ideal phases never
208
+ * recorded — their token cost was invisible to session totals, the StatusBar,
209
+ * `usage forensics`, and the cost caps (root cause of session f24c28b6dcb3:
210
+ * council ran but produced 0 source="council" usage_events).
211
+ *
212
+ * Best-effort: a null sessionId (no chat session FK) or a DB failure must never
213
+ * break the council run, but per the No-Silent-Catch rule we log the failure.
214
+ */
215
+ export function recordCouncilUsage(sessionId, modelId, usage) {
216
+ if (!sessionId)
217
+ return;
218
+ try {
219
+ recordUsageEvent(sessionId, "council", modelId, {
220
+ inputTokens: usage.inputTokens,
221
+ outputTokens: usage.outputTokens,
222
+ cacheReadTokens: usage.cachedInputTokens,
223
+ });
224
+ // Mirror council billing into the live StatusBar so cache-hit% / tokens /
225
+ // cost reflect the WHOLE session (council calls have ~0 cache; excluding
226
+ // them overstated the message-only cache ratio — session f24c28b6dcb3).
227
+ // ONLY the five cumulative billing counters — NEVER ctx_tokens/ctx_pct/
228
+ // model/provider, which describe the current MAIN-conversation call and
229
+ // would be clobbered by a small council sub-call.
230
+ const totalInput = usage.inputTokens;
231
+ const output = usage.outputTokens;
232
+ const cacheRead = usage.cachedInputTokens;
233
+ const info = getModelInfo(modelId);
234
+ const priceIn = info?.inputPrice ?? 0;
235
+ const priceCached = info?.cachedInputPrice ?? priceIn * 0.1;
236
+ const priceOut = info?.outputPrice ?? 0;
237
+ const nonCachedInput = Math.max(0, totalInput - cacheRead);
238
+ const turnCostMicros = nonCachedInput * priceIn + cacheRead * priceCached + output * priceOut;
239
+ const prev = statusBarStore.getState();
240
+ statusBarStore.setState({
241
+ in_tokens: prev.in_tokens + totalInput,
242
+ out_tokens: prev.out_tokens + output,
243
+ cache_read_tokens: (prev.cache_read_tokens ?? 0) + cacheRead,
244
+ session_usd: prev.session_usd + turnCostMicros / 1_000_000,
245
+ });
246
+ }
247
+ catch (err) {
248
+ logger.error("storage", "recordUsageEvent(council) failed — token cost not accounted", {
249
+ sessionId,
250
+ modelId,
251
+ message: err instanceof Error ? err.message : String(err),
252
+ });
253
+ }
254
+ }
189
255
  function getMockLlm() {
190
256
  // biome-ignore lint/suspicious/noExplicitAny: intentionally untyped global access
191
257
  return globalThis.__muonroiMockLlm ?? null;
@@ -209,6 +275,154 @@ const COUNCIL_LLM_TIMEOUT_MS = (() => {
209
275
  // withTimeoutSignal + withDeadlineRace moved to ../utils/llm-deadline.js so all
210
276
  // pre-flight LLM call sites (council, debate-planner, scope-ceiling) share one
211
277
  // implementation. Imported at the top of this file.
278
+ /**
279
+ * Run a single-shot LLM call over the STREAMING transport and collect the full
280
+ * result, returning a `generateText`-shaped object ({ text, usage, finishReason,
281
+ * reasoningText }).
282
+ *
283
+ * Why stream a one-shot generate? The OpenAI codex/oauth endpoint
284
+ * (chatgpt.com/backend-api/codex/responses, used by gpt-5.*-codex subscription
285
+ * auth) HARD-REJECTS non-streaming requests with 400 `{"detail":"Stream must be
286
+ * set to true"}`. `generateText` issues a non-stream POST, so every council
287
+ * sub-task that ran through it (leader round evaluation, clarify, spec
288
+ * synthesis, running summary) failed on a codex session — surfacing to the user
289
+ * as the opaque "Decision: evaluation unavailable" round card (diagnosed from
290
+ * session 8191ecaee149: gpt-5.4-mini → codex/responses → "Stream must be set to
291
+ * true"). The panel debate never hit this because it streams. Streaming is the
292
+ * universal transport (every provider + the whole TUI already use it), so
293
+ * collecting a streamed result fixes codex without special-casing it.
294
+ *
295
+ * A provider `error` part is re-thrown so the caller's retry / cross-provider
296
+ * fallback treats it as a failure exactly as a thrown `generateText` did.
297
+ *
298
+ * Also used by `debate()` (the panel pair turns) with the tiny verification
299
+ * toolset: pass `tools`/`stopWhen`/`prepareStep` and the collected `toolCalls`
300
+ * (toolName + input + matched result) come back in the same shape the old
301
+ * `generateText` result exposed. A debater on the codex/oauth endpoint hit the
302
+ * exact same non-stream 400 as the eval path — streaming fixes it uniformly.
303
+ */
304
+ /**
305
+ * Spread for the `maxOutputTokens` param, omitted when the resolved runtime
306
+ * rejects it. The ChatGPT Codex OAuth endpoint (chatgpt.com/backend-api/codex/
307
+ * responses) 400s with `{"detail":"Unsupported parameter: max_output_tokens"}`
308
+ * on EVERY council sub-call (clarify / debate / research) — every council
309
+ * generate on a Codex-OAuth session was failing wholesale. Mirrors the
310
+ * orchestrator + classify paths, which already gate this param via
311
+ * `shouldDropParam`.
312
+ */
313
+ function maxOutSpread(runtime, n) {
314
+ return shouldDropParam(runtime, "maxOutputTokens") ? {} : { maxOutputTokens: n };
315
+ }
316
+ /**
317
+ * Push-based stream liveness — module-level because the only readers
318
+ * (`tracedAsync` wrappers in debate.ts) sit OUTSIDE the `CouncilLLM` interface
319
+ * and cannot reach the in-flight `collectStreamText` any other way.
320
+ *
321
+ * Why it exists. `tracedAsync`'s 1s tick only materializes when the CONSUMER
322
+ * pulls `.next()`; a round that awaits its pairs via `Promise.all` stops
323
+ * pumping the tick generator, so `elapsedMs` FREEZES and a slow-but-alive run
324
+ * is indistinguishable from a hung one (observed: tick frozen at 33142ms for
325
+ * 8+ minutes while status was still "tick"). Token deltas are PUSHED here as
326
+ * they arrive, so liveness survives any back-pressure on the generator.
327
+ */
328
+ let councilStreamedCharsTotal = 0;
329
+ let councilLastDeltaAt = 0;
330
+ /** Record `chars` of streamed output (text OR reasoning) against the live window. */
331
+ export function noteCouncilStreamDelta(chars) {
332
+ if (chars <= 0)
333
+ return;
334
+ councilStreamedCharsTotal += chars;
335
+ councilLastDeltaAt = Date.now();
336
+ }
337
+ /**
338
+ * Open a liveness window and return a reader for it.
339
+ *
340
+ * `streamedChars` counts only what streamed SINCE the window opened, and
341
+ * `lastDeltaAgeMs` is measured from the window's own start until the first
342
+ * delta lands — so a cold stall reads as an age growing from 0, never as a
343
+ * bogus epoch-sized number. Reasoning-delta counts toward both: a reasoning
344
+ * model emits reasoning tokens for minutes before any text, and that is
345
+ * exactly the window an operator must not mistake for a hang.
346
+ */
347
+ export function councilStreamLivenessReader() {
348
+ const baseChars = councilStreamedCharsTotal;
349
+ const windowStart = Date.now();
350
+ return () => ({
351
+ streamedChars: councilStreamedCharsTotal - baseChars,
352
+ lastDeltaAgeMs: Date.now() - (councilLastDeltaAt > windowStart ? councilLastDeltaAt : windowStart),
353
+ });
354
+ }
355
+ async function collectStreamText(args) {
356
+ const hasTools = !!args.tools && Object.keys(args.tools).length > 0;
357
+ const result = streamText({
358
+ model: args.model,
359
+ system: args.system,
360
+ prompt: args.prompt,
361
+ ...(args.maxOutputTokens === undefined ? {} : { maxOutputTokens: args.maxOutputTokens }),
362
+ maxRetries: 0,
363
+ ...(args.temperature === undefined ? {} : { temperature: args.temperature }),
364
+ ...(args.providerOptions ? { providerOptions: args.providerOptions } : {}),
365
+ ...(hasTools ? { tools: args.tools, stopWhen: args.stopWhen, prepareStep: args.prepareStep } : {}),
366
+ abortSignal: args.abortSignal,
367
+ });
368
+ let text = "";
369
+ let reasoningText = "";
370
+ let usage;
371
+ let finishReason;
372
+ const toolCalls = [];
373
+ const byId = new Map();
374
+ for await (const part of result.fullStream) {
375
+ switch (part.type) {
376
+ case "text-delta": {
377
+ const d = part.text ?? "";
378
+ text += d;
379
+ args.onDelta?.(d.length);
380
+ break;
381
+ }
382
+ case "reasoning-delta": {
383
+ // Reasoning deltas count as liveness: a reasoning model streams these
384
+ // for minutes before its first text-delta, and that silent-on-text
385
+ // window is precisely what gets misread as a hang.
386
+ const d = part.text ?? "";
387
+ reasoningText += d;
388
+ args.onDelta?.(d.length);
389
+ break;
390
+ }
391
+ case "tool-call": {
392
+ const p = part;
393
+ const tc = { toolName: p.toolName, input: p.input };
394
+ byId.set(p.toolCallId, tc);
395
+ toolCalls.push(tc);
396
+ break;
397
+ }
398
+ case "tool-result": {
399
+ const p = part;
400
+ const tc = byId.get(p.toolCallId);
401
+ if (tc)
402
+ tc.result = p.output;
403
+ break;
404
+ }
405
+ case "finish":
406
+ usage = part.totalUsage ?? part.usage;
407
+ finishReason = part.finishReason;
408
+ break;
409
+ case "error": {
410
+ const raw = part.error;
411
+ throw raw instanceof Error ? raw : new Error(String(raw));
412
+ }
413
+ default:
414
+ break;
415
+ }
416
+ }
417
+ return { text, usage, finishReason, reasoningText: reasoningText || undefined, toolCalls };
418
+ }
419
+ /**
420
+ * Test-only handle on the private stream collector, so `onDelta` (the liveness
421
+ * signal that tells a slow reasoning call from a hung one) is directly
422
+ * assertable without standing up a full council run. Not for production use.
423
+ * @internal
424
+ */
425
+ export const __testCollectStreamText = collectStreamText;
212
426
  export function createCouncilLLM(bash, mode, sessionId, stats) {
213
427
  return {
214
428
  async generate(modelId, system, prompt, maxTokens = 4096, onUsage, signal) {
@@ -216,11 +430,11 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
216
430
  if (mock) {
217
431
  stats.calls++;
218
432
  const result = await mock.complete({ prompt });
219
- return result.text;
433
+ return stripThinkBlocks(result.text);
220
434
  }
221
435
  const providerId = detectProviderForModel(modelId);
222
- const factory = await resolveCouncilFactory(providerId);
223
- const runtime = resolveModelRuntime(factory, modelId);
436
+ await ensureCouncilFactory(providerId);
437
+ const runtime = resolveModelRuntime(modelId);
224
438
  const t0 = Date.now();
225
439
  // Combine the user-abort signal (when threaded from runCouncil) with the
226
440
  // per-call wall-clock deadline. Without the parent signal, an Esc/Ctrl-C
@@ -228,19 +442,25 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
228
442
  // eval) was a no-op — the call ran to completion or hit the 5-min timeout.
229
443
  const { signal: timedSignal, cleanup: cleanupTimeout } = withTimeoutSignal(signal, COUNCIL_LLM_TIMEOUT_MS);
230
444
  try {
231
- const result = await withDeadlineRace(() => withVisibleRetry(() => generateText({
445
+ const result = await withDeadlineRace(() => withVisibleRetry(() =>
446
+ // Stream + collect (NOT generateText). The codex/oauth endpoint
447
+ // 400s on non-stream requests ("Stream must be set to true"),
448
+ // which nulled every council eval/clarify/synthesis on a codex
449
+ // session → the opaque "evaluation unavailable" card. See
450
+ // collectStreamText's doc for the full diagnosis.
451
+ collectStreamText({
232
452
  model: runtime.model,
233
453
  system,
234
454
  prompt,
235
- maxOutputTokens: maxTokens,
236
- temperature: 0.7,
237
- // Visible retry (src/utils/visible-retry.ts) replaces SDK's silent
238
- // exponential backoff (2,4,8,16,32s). When SiliconFlow rate-limits
239
- // with 429, user now sees "[retry] rate-limited (429) waiting Xs
240
- // before attempt N/6" instead of a 62s blank window that looks hung.
241
- maxRetries: 0,
242
- ...(runtime.providerOptions ? { providerOptions: runtime.providerOptions } : {}),
455
+ ...maxOutSpread(runtime, maxTokens),
456
+ // Never hardcode temperature: some upstreams (Moonshot/Kimi via
457
+ // opencode-go) reject any value but their pinned one, which
458
+ // failed every clarify/spec call on a Kimi session. resolveTemperature
459
+ // omits the field or clamps to the model's fixed value.
460
+ temperature: resolveTemperature(providerId, runtime.modelInfo, 0.7),
461
+ providerOptions: runtime.providerOptions,
243
462
  abortSignal: timedSignal,
463
+ onDelta: noteCouncilStreamDelta,
244
464
  }), { label: "council.generate" }), COUNCIL_LLM_TIMEOUT_MS + 5_000, "council.generate", signal);
245
465
  cleanupTimeout();
246
466
  stats.calls++;
@@ -255,6 +475,7 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
255
475
  durationMs: durMs,
256
476
  });
257
477
  onUsage?.(callUsage);
478
+ recordCouncilUsage(sessionId, modelId, callUsage);
258
479
  writeDebugRecord({
259
480
  ts: new Date().toISOString(),
260
481
  kind: "generate",
@@ -273,10 +494,16 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
273
494
  finishReason: result.finishReason,
274
495
  usage: result.usage,
275
496
  });
276
- return result.text;
497
+ return stripThinkBlocks(result.text);
277
498
  }
278
499
  catch (err) {
279
500
  cleanupTimeout();
501
+ // Capture the provider-side detail (status code + response body +
502
+ // request param shape) that `err.message` alone drops — a generic
503
+ // "Bad Request" on the council path was previously undiagnosable
504
+ // because collectStreamText re-throws only the message. PII-safe,
505
+ // no-op unless MUONROI_DEBUG_LLM_WIRE=1. (No-Silent-Catch.)
506
+ wireDebug.logError(providerId, err);
280
507
  writeDebugRecord({
281
508
  ts: new Date().toISOString(),
282
509
  kind: "generate",
@@ -300,11 +527,11 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
300
527
  if (mock) {
301
528
  stats.calls++;
302
529
  const result = await mock.complete({ prompt });
303
- return { text: result.text, toolCalls: [] };
530
+ return { text: stripThinkBlocks(result.text), toolCalls: [] };
304
531
  }
305
532
  const providerId = detectProviderForModel(modelId);
306
- const factory = await resolveCouncilFactory(providerId);
307
- const runtime = resolveModelRuntime(factory, modelId);
533
+ await ensureCouncilFactory(providerId);
534
+ const runtime = resolveModelRuntime(modelId);
308
535
  // Verification tools — re-introduced after the no-tools fix (session
309
536
  // a7a5690d2049). The original failure was stepCountIs(4) + full toolset
310
537
  // letting reasoning models exhaust steps on exploratory tool chains and
@@ -335,13 +562,16 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
335
562
  }
336
563
  }
337
564
  }
338
- catch {
339
- /* MCP optional — debate continues with builtins only */
565
+ catch (err) {
566
+ // MCP is optional here — debate continues with builtins only — but a
567
+ // silent swallow hid which server failed and why. (No-Silent-Catch.)
568
+ console.error(`[council/llm] debate MCP tool discovery failed, continuing with builtins only: ${err instanceof Error ? err.message : String(err)}`, { modelId, provider: providerId });
340
569
  }
341
570
  verificationTools = wrapToolsWithEeCheck(filtered, sessionId ?? "council-debate");
342
571
  }
343
- catch {
344
- /* fail-open: no tools */
572
+ catch (err) {
573
+ // fail-open: the debate turn still runs, just without verification tools.
574
+ console.error(`[council/llm] debate verification toolset build failed, running without tools: ${err instanceof Error ? err.message : String(err)}`, { modelId, provider: providerId });
345
575
  }
346
576
  }
347
577
  // sanitizeHistory is identity for every provider (kept as a hook for
@@ -351,10 +581,30 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
351
581
  const t0 = Date.now();
352
582
  const { signal: timedSignal, cleanup: cleanupTimeout } = withTimeoutSignal(signal, COUNCIL_LLM_TIMEOUT_MS);
353
583
  try {
354
- const result = await withDeadlineRace(() => withVisibleRetry(() => generateText({
584
+ const result = await withDeadlineRace(() => withVisibleRetry(() =>
585
+ // Stream + collect (NOT generateText). A debater on the codex/oauth
586
+ // endpoint hits the same non-stream 400 ("Stream must be set to
587
+ // true") that nulled the eval path; streaming is uniform across
588
+ // providers. Tools (when the tier + circuit breaker allow) ride
589
+ // through with stepCountIs(2) + the same sanitizeHistory prepareStep.
590
+ collectStreamText({
355
591
  model: runtime.model,
356
592
  system,
357
593
  prompt,
594
+ // Reasoning models (deepseek-v4-*, anthropic thinking) consume part
595
+ // of this budget on reasoning_tokens before producing user-visible
596
+ // text. E2E showed 2048 caused finishReason=length on 3KB debate
597
+ // prompts. 6144 leaves ~4000 tokens for text after typical reasoning
598
+ // overhead and avoids cuts mid-thought.
599
+ ...maxOutSpread(runtime, 6144),
600
+ // See generate(): capability-aware temperature (omit / clamp).
601
+ temperature: resolveTemperature(providerId, runtime.modelInfo, 0.7),
602
+ providerOptions: runtime.providerOptions,
603
+ abortSignal: timedSignal,
604
+ // Push liveness for the round wrapper: a debate turn on a
605
+ // reasoning model runs near the 5-min ceiling, and the tick
606
+ // generator is not being pumped while Promise.all awaits.
607
+ onDelta: noteCouncilStreamDelta,
358
608
  ...(verificationTools && Object.keys(verificationTools).length > 0
359
609
  ? {
360
610
  tools: verificationTools,
@@ -367,20 +617,6 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
367
617
  },
368
618
  }
369
619
  : {}),
370
- // Reasoning models (deepseek-v4-*, anthropic thinking) consume part
371
- // of this budget on reasoning_tokens before producing user-visible
372
- // text. E2E showed 2048 caused finishReason=length on 3KB debate
373
- // prompts. 6144 leaves ~4000 tokens for text after typical reasoning
374
- // overhead and avoids cuts mid-thought.
375
- maxOutputTokens: 6144,
376
- temperature: 0.7,
377
- // Visible retry (src/utils/visible-retry.ts) replaces SDK's silent
378
- // exponential backoff (2,4,8,16,32s). When SiliconFlow rate-limits
379
- // with 429, user now sees "[retry] rate-limited (429) — waiting Xs
380
- // before attempt N/6" instead of a 62s blank window that looks hung.
381
- maxRetries: 0,
382
- ...(runtime.providerOptions ? { providerOptions: runtime.providerOptions } : {}),
383
- abortSignal: timedSignal,
384
620
  }), { label: "council.debate" }), COUNCIL_LLM_TIMEOUT_MS + 5_000, "council.debate", signal);
385
621
  cleanupTimeout();
386
622
  stats.calls++;
@@ -402,6 +638,7 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
402
638
  stepCount: toolCalls.length,
403
639
  });
404
640
  onUsage?.(debateUsage);
641
+ recordCouncilUsage(sessionId, modelId, debateUsage);
405
642
  writeDebugRecord({
406
643
  ts: new Date().toISOString(),
407
644
  kind: "debate",
@@ -423,7 +660,7 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
423
660
  usage: result.usage,
424
661
  });
425
662
  return {
426
- text: result.text,
663
+ text: stripThinkBlocks(result.text),
427
664
  toolCalls: toolCalls,
428
665
  };
429
666
  }
@@ -456,11 +693,11 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
456
693
  if (mock) {
457
694
  stats.calls++;
458
695
  const result = await mock.complete({ prompt: topic });
459
- return result.text;
696
+ return stripThinkBlocks(result.text);
460
697
  }
461
698
  const providerId = detectProviderForModel(modelId);
462
- const factory = await resolveCouncilFactory(providerId);
463
- const runtime = resolveModelRuntime(factory, modelId);
699
+ await ensureCouncilFactory(providerId);
700
+ const runtime = resolveModelRuntime(modelId);
464
701
  const builtinTools = createTools(bash, mode);
465
702
  // CQ-03: Lazy MCP bundle per research call — fail-open so builtins remain available
466
703
  let mcpBundle = null;
@@ -476,12 +713,21 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
476
713
  const hasUrl = /https?:\/\/\S+/.test(topic);
477
714
  const internetFirst = options?.internetFirst === true;
478
715
  const systemPrompt = buildResearchSystemPrompt(hasUrl, internetFirst);
479
- // Warn early if internet-first mode is requested but no internet/browser tools are loaded.
480
- const internetToolAvailable = Object.keys(allTools).some((n) => /tavily|web[_-]?fetch|web[_-]?search|playwright|chrome|context7|firecrawl|exa/i.test(n));
716
+ // Warn early if internet-first mode is requested but no *working* web
717
+ // research capability exists. The builtin `web_search`/`fetch_url` tools
718
+ // are ALWAYS registered, so the old tool-NAME check was always true — even
719
+ // when `web_search` will just return `ERROR no_tavily_key`, so the warning
720
+ // never fired and internet-first research failed silently. Gate on real
721
+ // capability: a Tavily key, or an MCP search/browser tool actually loaded
722
+ // (builtins alone don't count — open-ended search needs the key).
723
+ const hasTavilyKey = ((await getMcpKey("tavily")) || process.env.TAVILY_API_KEY || "").trim().length >= 10;
724
+ const mcpSearchTool = Object.keys(mcpBundle?.tools ?? {}).some((n) => /tavily|web[_-]?search|web[_-]?fetch|playwright|chrome|context7|firecrawl|exa|browser/i.test(n));
725
+ const internetToolAvailable = hasTavilyKey || mcpSearchTool;
481
726
  const internetGapWarning = internetFirst && !internetToolAvailable
482
- ? `\n\n## Research Gap\n- Internet-first mode requested but no browser/search tool ` +
483
- `(tavily, web-fetch, playwright, chrome-devtools, context7) is available. ` +
484
- `Findings will be limited to what the model already knows.`
727
+ ? `\n\n## Research Gap\n- Internet-first mode requested but no working web-search capability ` +
728
+ `(a Tavily API key or an MCP search/browser tool) is available. ` +
729
+ `\`fetch_url\` still works for explicit URLs, but open-ended search is unavailable — ` +
730
+ `findings will be limited to what the model already knows.`
485
731
  : "";
486
732
  const userPrompt = conversationContext
487
733
  ? `## Context\n${conversationContext}\n\n---\n\n## Research Topic\n${topic}\n\nInvestigate and report findings.`
@@ -507,8 +753,12 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
507
753
  const stripped = researchCaps.sanitizeHistory(messages);
508
754
  return stripped === messages ? {} : { messages: stripped };
509
755
  },
510
- maxOutputTokens: 4096,
511
- temperature: 0.3,
756
+ ...maxOutSpread(runtime, 4096),
757
+ // See generate(): capability-aware temperature (omit / clamp).
758
+ ...(() => {
759
+ const t = resolveTemperature(providerId, runtime.modelInfo, 0.3);
760
+ return t === undefined ? {} : { temperature: t };
761
+ })(),
512
762
  // Visible retry (src/utils/visible-retry.ts) replaces SDK's silent
513
763
  // exponential backoff (2,4,8,16,32s). When SiliconFlow rate-limits
514
764
  // with 429, user now sees "[retry] rate-limited (429) — waiting Xs
@@ -530,6 +780,7 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
530
780
  stepCount: (result.toolCalls ?? []).length,
531
781
  });
532
782
  onUsage?.(researchUsage);
783
+ recordCouncilUsage(sessionId, modelId, researchUsage);
533
784
  writeDebugRecord({
534
785
  ts: new Date().toISOString(),
535
786
  kind: "research",
@@ -558,7 +809,7 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
558
809
  // CQ-04: When URL present, verify at least one browser tool was invoked
559
810
  if (hasUrl) {
560
811
  // Use result.toolCalls (flat array across all steps) — more reliably typed than steps[].toolCalls
561
- const browserUsed = researchToolCalls.some((tc) => tc.toolName.includes("playwright") || tc.toolName.includes("chrome"));
812
+ const browserUsed = researchToolCalls.some((tc) => tc.toolName.includes("playwright") || tc.toolName.includes("chrome") || tc.toolName === "fetch_url");
562
813
  if (!browserUsed) {
563
814
  stats.calls++;
564
815
  return (result.text +
@@ -568,7 +819,7 @@ export function createCouncilLLM(bash, mode, sessionId, stats) {
568
819
  }
569
820
  }
570
821
  stats.calls++;
571
- return result.text + internetGapWarning;
822
+ return stripThinkBlocks(result.text) + internetGapWarning;
572
823
  }
573
824
  catch (err) {
574
825
  cleanupTimeout();
@@ -691,6 +942,33 @@ export async function* tracedGenerate(llm, args) {
691
942
  };
692
943
  return resultText;
693
944
  }
945
+ /**
946
+ * Run {@link tracedGenerate} across a list of models, returning the first
947
+ * non-empty completion. A model that throws (e.g. a flaky proxy returning
948
+ * "Upstream request failed") or yields only whitespace advances to the next
949
+ * candidate; fallback attempts are labelled so the timeline shows the retry.
950
+ * Returns null when every candidate fails — the caller decides the degraded
951
+ * fallback (e.g. a single-criterion spec). Dedupes the model list in order.
952
+ */
953
+ export async function* tracedGenerateWithFallback(llm, args) {
954
+ const seen = new Set();
955
+ const models = args.models.filter((m) => m && !seen.has(m) && (seen.add(m), true));
956
+ for (let i = 0; i < models.length; i++) {
957
+ try {
958
+ const raw = yield* tracedGenerate(llm, {
959
+ ...args,
960
+ modelId: models[i],
961
+ label: i > 0 ? `${args.label} (fallback: ${models[i]})` : args.label,
962
+ });
963
+ if (raw?.trim())
964
+ return raw;
965
+ }
966
+ catch {
967
+ /* try the next candidate */
968
+ }
969
+ }
970
+ return null;
971
+ }
694
972
  /**
695
973
  * Generic version of {@link tracedGenerate} for arbitrary async work
696
974
  * (e.g. `llm.research`, `Promise.all` over multiple model calls).
@@ -701,6 +979,19 @@ export async function* tracedAsync(fn, args) {
701
979
  : `status-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
702
980
  const start = Date.now();
703
981
  const tickInterval = args.tickIntervalMs ?? 1000;
982
+ /** Never let a liveness read break the heartbeat it is meant to enrich. */
983
+ const livenessFields = () => {
984
+ if (!args.liveness)
985
+ return {};
986
+ try {
987
+ const l = args.liveness();
988
+ return { streamedChars: l.streamedChars, lastDeltaAgeMs: l.lastDeltaAgeMs };
989
+ }
990
+ catch (err) {
991
+ console.error(`[council/llm] tracedAsync liveness read failed: ${err instanceof Error ? err.message : String(err)}`, { phase: args.phase, label: args.label });
992
+ return {};
993
+ }
994
+ };
704
995
  yield {
705
996
  type: "council_status",
706
997
  councilStatus: {
@@ -746,6 +1037,7 @@ export async function* tracedAsync(fn, args) {
746
1037
  detail: args.detail,
747
1038
  role: args.role,
748
1039
  elapsedMs: Date.now() - start,
1040
+ ...livenessFields(),
749
1041
  },
750
1042
  };
751
1043
  }
@@ -777,6 +1069,7 @@ export async function* tracedAsync(fn, args) {
777
1069
  detail: args.detail,
778
1070
  role: args.role,
779
1071
  elapsedMs: Date.now() - start,
1072
+ ...livenessFields(),
780
1073
  },
781
1074
  };
782
1075
  return result;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * src/council/panel-select.ts
3
+ *
4
+ * U3 — task-aware debate panel selection. Instead of a fixed capability roster
5
+ * (resolveParticipants picks by tier, blind to the prompt), the leader reads the
6
+ * task and CHOOSES which reachable models should debate it. Fail-open: any parse
7
+ * / provider failure returns null and the caller keeps the default roster. The
8
+ * internal implement/verify/research routing slots are assigned here purely for
9
+ * downstream compatibility — they are never surfaced to the user (the UI shows
10
+ * the task-adaptive persona / model, per U1.1).
11
+ */
12
+ import type { StreamChunk } from "../types/index.js";
13
+ import type { ModelRole } from "../utils/settings.js";
14
+ import type { CouncilCandidate } from "./leader.js";
15
+ import type { CouncilLLM } from "./types.js";
16
+ /**
17
+ * Ask the leader to select a task-appropriate debate panel from `pool`.
18
+ * Returns a roster (models mapped onto internal routing roles) or null when the
19
+ * leader is unavailable / returns an unusable selection — the caller then keeps
20
+ * its default roster.
21
+ */
22
+ export declare function selectTaskAwarePanel(opts: {
23
+ topic: string;
24
+ pool: CouncilCandidate[];
25
+ leaderModelId: string;
26
+ llm: CouncilLLM;
27
+ }): AsyncGenerator<StreamChunk, Array<{
28
+ role: ModelRole;
29
+ model: string;
30
+ }> | null, unknown>;