muonroi-cli 1.8.4 → 1.8.5

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 (458) 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-tee.d.ts +48 -0
  5. package/dist/packages/agent-harness-core/src/event-tee.js +77 -0
  6. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +11 -0
  7. package/dist/packages/agent-harness-core/src/mcp-server.js +87 -15
  8. package/dist/packages/agent-harness-core/src/protocol.d.ts +66 -2
  9. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  10. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  11. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  12. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  13. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  14. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  15. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  16. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  17. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  18. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  19. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  20. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  21. package/dist/src/agent-harness/mock-model.d.ts +28 -0
  22. package/dist/src/agent-harness/mock-model.js +63 -1
  23. package/dist/src/agent-harness/test-spawn.js +31 -0
  24. package/dist/src/cli/config/screen-providers.js +1 -1
  25. package/dist/src/cli/cost-forensics.d.ts +10 -0
  26. package/dist/src/cli/cost-forensics.js +18 -3
  27. package/dist/src/cli/keys-bundle.d.ts +1 -1
  28. package/dist/src/cli/keys-bundle.js +1 -1
  29. package/dist/src/cli/keys.d.ts +2 -2
  30. package/dist/src/cli/keys.js +19 -81
  31. package/dist/src/council/clarifier.d.ts +28 -2
  32. package/dist/src/council/clarifier.js +81 -15
  33. package/dist/src/council/context.js +49 -15
  34. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  35. package/dist/src/council/debate-checkpoint.js +176 -0
  36. package/dist/src/council/debate-planner.js +51 -3
  37. package/dist/src/council/debate-summary.d.ts +25 -0
  38. package/dist/src/council/debate-summary.js +85 -0
  39. package/dist/src/council/debate.d.ts +169 -2
  40. package/dist/src/council/debate.js +1210 -134
  41. package/dist/src/council/index.d.ts +85 -1
  42. package/dist/src/council/index.js +634 -196
  43. package/dist/src/council/leader.d.ts +26 -0
  44. package/dist/src/council/leader.js +150 -9
  45. package/dist/src/council/llm.d.ts +32 -0
  46. package/dist/src/council/llm.js +231 -38
  47. package/dist/src/council/panel-select.d.ts +30 -0
  48. package/dist/src/council/panel-select.js +72 -0
  49. package/dist/src/council/planner.js +23 -0
  50. package/dist/src/council/preflight.d.ts +7 -0
  51. package/dist/src/council/preflight.js +14 -2
  52. package/dist/src/council/prompts.d.ts +30 -3
  53. package/dist/src/council/prompts.js +234 -64
  54. package/dist/src/council/stance-recall.d.ts +42 -0
  55. package/dist/src/council/stance-recall.js +57 -0
  56. package/dist/src/council/strip-think.d.ts +17 -0
  57. package/dist/src/council/strip-think.js +33 -0
  58. package/dist/src/council/types.d.ts +128 -0
  59. package/dist/src/ee/artifact-cache.d.ts +16 -0
  60. package/dist/src/ee/artifact-cache.js +32 -0
  61. package/dist/src/ee/auth.d.ts +1 -0
  62. package/dist/src/ee/auth.js +15 -2
  63. package/dist/src/ee/bridge.d.ts +10 -0
  64. package/dist/src/ee/bridge.js +58 -0
  65. package/dist/src/ee/client.js +81 -18
  66. package/dist/src/ee/export-transcripts.d.ts +1 -0
  67. package/dist/src/ee/export-transcripts.js +8 -10
  68. package/dist/src/ee/extract-session.js +29 -0
  69. package/dist/src/ee/extract-style.d.ts +58 -0
  70. package/dist/src/ee/extract-style.js +270 -0
  71. package/dist/src/ee/recall-ledger.d.ts +9 -0
  72. package/dist/src/ee/recall-ledger.js +3 -0
  73. package/dist/src/ee/scope.d.ts +1 -0
  74. package/dist/src/ee/scope.js +26 -1
  75. package/dist/src/ee/search.d.ts +7 -0
  76. package/dist/src/ee/search.js +24 -0
  77. package/dist/src/ee/transcript-emit.js +2 -0
  78. package/dist/src/ee/types.d.ts +22 -0
  79. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  80. package/dist/src/ee/who-am-i-brain.js +220 -0
  81. package/dist/src/ee/who-am-i.d.ts +10 -3
  82. package/dist/src/ee/who-am-i.js +12 -0
  83. package/dist/src/ee/workflow-event.d.ts +48 -0
  84. package/dist/src/ee/workflow-event.js +81 -0
  85. package/dist/src/flow/compaction/compress.d.ts +3 -3
  86. package/dist/src/flow/compaction/compress.js +45 -8
  87. package/dist/src/flow/compaction/extract.d.ts +4 -7
  88. package/dist/src/flow/compaction/extract.js +50 -10
  89. package/dist/src/flow/compaction/index.d.ts +13 -1
  90. package/dist/src/flow/compaction/index.js +70 -3
  91. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  92. package/dist/src/flow/compaction/input-guard.js +43 -0
  93. package/dist/src/flow/fold-planning.d.ts +36 -0
  94. package/dist/src/flow/fold-planning.js +83 -0
  95. package/dist/src/flow/hierarchy.d.ts +146 -0
  96. package/dist/src/flow/hierarchy.js +427 -0
  97. package/dist/src/flow/index.d.ts +1 -0
  98. package/dist/src/flow/index.js +2 -0
  99. package/dist/src/flow/run-artifacts.d.ts +102 -0
  100. package/dist/src/flow/run-artifacts.js +208 -0
  101. package/dist/src/generated/version.d.ts +1 -1
  102. package/dist/src/generated/version.js +1 -1
  103. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  104. package/dist/src/gsd/assessment-schema.js +134 -0
  105. package/dist/src/gsd/capability-registry.d.ts +45 -0
  106. package/dist/src/gsd/capability-registry.js +337 -0
  107. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  108. package/dist/src/gsd/complexity-assessor.js +152 -0
  109. package/dist/src/gsd/config-bridge.d.ts +7 -0
  110. package/dist/src/gsd/config-bridge.js +114 -0
  111. package/dist/src/gsd/config-loader.d.ts +27 -0
  112. package/dist/src/gsd/config-loader.js +50 -0
  113. package/dist/src/gsd/council-context.d.ts +44 -0
  114. package/dist/src/gsd/council-context.js +114 -0
  115. package/dist/src/gsd/ee-closure.d.ts +28 -0
  116. package/dist/src/gsd/ee-closure.js +49 -0
  117. package/dist/src/gsd/flags.d.ts +55 -0
  118. package/dist/src/gsd/flags.js +83 -0
  119. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  120. package/dist/src/gsd/gsd-dispatch.js +131 -0
  121. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  122. package/dist/src/gsd/gsd-runtime.js +37 -0
  123. package/dist/src/gsd/host-adapter.d.ts +11 -0
  124. package/dist/src/gsd/host-adapter.js +29 -0
  125. package/dist/src/gsd/index.d.ts +24 -1
  126. package/dist/src/gsd/index.js +27 -0
  127. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  128. package/dist/src/gsd/loop-host-contract.js +39 -0
  129. package/dist/src/gsd/loop-host.d.ts +69 -0
  130. package/dist/src/gsd/loop-host.js +245 -0
  131. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  132. package/dist/src/gsd/loop-resolver.js +79 -0
  133. package/dist/src/gsd/model-tier.d.ts +13 -0
  134. package/dist/src/gsd/model-tier.js +45 -0
  135. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  136. package/dist/src/gsd/mutation-gate.js +41 -0
  137. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  138. package/dist/src/gsd/native-roadmap.js +343 -0
  139. package/dist/src/gsd/native-state.d.ts +47 -0
  140. package/dist/src/gsd/native-state.js +220 -0
  141. package/dist/src/gsd/paths.d.ts +23 -0
  142. package/dist/src/gsd/paths.js +66 -0
  143. package/dist/src/gsd/phase-dag.d.ts +12 -0
  144. package/dist/src/gsd/phase-dag.js +94 -0
  145. package/dist/src/gsd/phase-sync.d.ts +42 -0
  146. package/dist/src/gsd/phase-sync.js +321 -0
  147. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  148. package/dist/src/gsd/pil-gate-context.js +64 -0
  149. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  150. package/dist/src/gsd/pil-gate-critic.js +74 -0
  151. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  152. package/dist/src/gsd/plan-council-prompts.js +79 -0
  153. package/dist/src/gsd/plan-council.d.ts +44 -0
  154. package/dist/src/gsd/plan-council.js +251 -0
  155. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  156. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  157. package/dist/src/gsd/product-workspace.d.ts +13 -0
  158. package/dist/src/gsd/product-workspace.js +124 -0
  159. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  160. package/dist/src/gsd/ship-bridge.js +65 -0
  161. package/dist/src/gsd/state-document.d.ts +40 -0
  162. package/dist/src/gsd/state-document.js +163 -0
  163. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  164. package/dist/src/gsd/verdict-schema.js +144 -0
  165. package/dist/src/gsd/verify-context.d.ts +22 -0
  166. package/dist/src/gsd/verify-context.js +27 -0
  167. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  168. package/dist/src/gsd/verify-council-prompts.js +85 -0
  169. package/dist/src/gsd/verify-council.d.ts +25 -0
  170. package/dist/src/gsd/verify-council.js +119 -0
  171. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  172. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  173. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  174. package/dist/src/gsd/workflow-engine.js +207 -0
  175. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  176. package/dist/src/gsd/workflow-tools.js +277 -0
  177. package/dist/src/hooks/index.js +1 -1
  178. package/dist/src/index.js +44 -11
  179. package/dist/src/maintain/pr-builder.js +23 -13
  180. package/dist/src/mcp/auto-setup.js +57 -32
  181. package/dist/src/mcp/client-pool.js +1 -1
  182. package/dist/src/mcp/ee-tools.js +1 -0
  183. package/dist/src/mcp/research-onboarding.js +8 -7
  184. package/dist/src/mcp/runtime.js +34 -2
  185. package/dist/src/models/catalog-client.d.ts +87 -0
  186. package/dist/src/models/catalog-client.js +105 -38
  187. package/dist/src/models/catalog.json +528 -265
  188. package/dist/src/models/registry.d.ts +22 -7
  189. package/dist/src/models/registry.js +73 -10
  190. package/dist/src/ops/doctor.js +1 -1
  191. package/dist/src/orchestrator/auto-commit.js +1 -1
  192. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  193. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  194. package/dist/src/orchestrator/cache-prefix.js +83 -0
  195. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  196. package/dist/src/orchestrator/compact-request.js +41 -0
  197. package/dist/src/orchestrator/compaction.d.ts +10 -0
  198. package/dist/src/orchestrator/compaction.js +27 -7
  199. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  200. package/dist/src/orchestrator/council-manager.js +65 -24
  201. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  202. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  203. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  204. package/dist/src/orchestrator/error-utils.js +132 -24
  205. package/dist/src/orchestrator/grounding-check.js +39 -1
  206. package/dist/src/orchestrator/message-processor.js +242 -33
  207. package/dist/src/orchestrator/orchestrator.d.ts +39 -3
  208. package/dist/src/orchestrator/orchestrator.js +651 -102
  209. package/dist/src/orchestrator/preprocessor.js +1 -1
  210. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  211. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  212. package/dist/src/orchestrator/prompts.js +17 -17
  213. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  214. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  215. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  216. package/dist/src/orchestrator/retry-classifier.js +46 -2
  217. package/dist/src/orchestrator/safety-intercept.d.ts +45 -0
  218. package/dist/src/orchestrator/safety-intercept.js +55 -0
  219. package/dist/src/orchestrator/scope-reminder.js +1 -1
  220. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  221. package/dist/src/orchestrator/session-experience.js +2 -1
  222. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  223. package/dist/src/orchestrator/should-run-gate.js +18 -0
  224. package/dist/src/orchestrator/stall-watchdog.d.ts +24 -3
  225. package/dist/src/orchestrator/stall-watchdog.js +47 -13
  226. package/dist/src/orchestrator/stream-runner.js +62 -29
  227. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  228. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  229. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  230. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  231. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  232. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  233. package/dist/src/orchestrator/tool-engine.d.ts +22 -0
  234. package/dist/src/orchestrator/tool-engine.js +620 -56
  235. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  236. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  237. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  238. package/dist/src/orchestrator/turn-watchdog.d.ts +37 -0
  239. package/dist/src/orchestrator/turn-watchdog.js +55 -0
  240. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  241. package/dist/src/pil/agent-operating-contract.js +1 -1
  242. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  243. package/dist/src/pil/cheap-model-playbook.js +5 -1
  244. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  245. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  246. package/dist/src/pil/discovery-types.d.ts +1 -0
  247. package/dist/src/pil/discovery.js +16 -11
  248. package/dist/src/pil/layer1-intent.d.ts +18 -6
  249. package/dist/src/pil/layer1-intent.js +66 -757
  250. package/dist/src/pil/layer15-context-scan.js +15 -1
  251. package/dist/src/pil/layer3-ee-injection.js +23 -8
  252. package/dist/src/pil/layer4-gsd.js +69 -16
  253. package/dist/src/pil/layer5-context.js +7 -3
  254. package/dist/src/pil/layer6-output.d.ts +23 -0
  255. package/dist/src/pil/layer6-output.js +5 -1
  256. package/dist/src/pil/llm-classify.d.ts +33 -2
  257. package/dist/src/pil/llm-classify.js +123 -131
  258. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  259. package/dist/src/pil/native-capabilities-workbook.js +1 -0
  260. package/dist/src/pil/pipeline.js +34 -2
  261. package/dist/src/pil/response-tools.js +5 -3
  262. package/dist/src/pil/schema.d.ts +1 -0
  263. package/dist/src/pil/schema.js +2 -0
  264. package/dist/src/pil/types.d.ts +18 -0
  265. package/dist/src/playbook/directives.d.ts +4 -0
  266. package/dist/src/playbook/directives.js +17 -5
  267. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  268. package/dist/src/product-loop/backlog-builder.js +30 -6
  269. package/dist/src/product-loop/discovery-context-format.js +3 -1
  270. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  271. package/dist/src/product-loop/discovery-interview.js +32 -3
  272. package/dist/src/product-loop/discovery-schema.js +5 -1
  273. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  274. package/dist/src/product-loop/ideal-trace.js +64 -0
  275. package/dist/src/product-loop/index.d.ts +13 -1
  276. package/dist/src/product-loop/index.js +333 -52
  277. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  278. package/dist/src/product-loop/loop-driver.js +310 -99
  279. package/dist/src/product-loop/phase-plan.d.ts +5 -0
  280. package/dist/src/product-loop/phase-plan.js +39 -2
  281. package/dist/src/product-loop/phase-runner.js +9 -1
  282. package/dist/src/product-loop/sprint-runner.d.ts +111 -0
  283. package/dist/src/product-loop/sprint-runner.js +559 -16
  284. package/dist/src/product-loop/types.d.ts +36 -5
  285. package/dist/src/providers/adapter.d.ts +1 -1
  286. package/dist/src/providers/adapter.js +3 -4
  287. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  288. package/dist/src/providers/auth/browser-flow.js +1 -1
  289. package/dist/src/providers/auth/openai-oauth.js +1 -1
  290. package/dist/src/providers/auth/registry.js +0 -34
  291. package/dist/src/providers/auth/token-store.js +4 -1
  292. package/dist/src/providers/auth/types.d.ts +1 -1
  293. package/dist/src/providers/auth/types.js +1 -1
  294. package/dist/src/providers/capabilities.d.ts +24 -5
  295. package/dist/src/providers/capabilities.js +42 -24
  296. package/dist/src/providers/endpoints.d.ts +2 -2
  297. package/dist/src/providers/endpoints.js +11 -10
  298. package/dist/src/providers/keychain.d.ts +1 -1
  299. package/dist/src/providers/keychain.js +7 -9
  300. package/dist/src/providers/mcp-vision-bridge.js +56 -146
  301. package/dist/src/providers/openai-compatible.js +8 -1
  302. package/dist/src/providers/pricing.d.ts +2 -2
  303. package/dist/src/providers/pricing.js +3 -13
  304. package/dist/src/providers/runtime.d.ts +27 -2
  305. package/dist/src/providers/runtime.js +78 -15
  306. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  307. package/dist/src/providers/strategies/base.strategy.js +24 -1
  308. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  309. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  310. package/dist/src/providers/strategies/registry.js +4 -4
  311. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  312. package/dist/src/providers/strategies/thinking-mode.js +280 -1
  313. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  314. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  315. package/dist/src/providers/types.d.ts +5 -6
  316. package/dist/src/providers/types.js +2 -2
  317. package/dist/src/providers/vision-backend.d.ts +47 -0
  318. package/dist/src/providers/vision-backend.js +258 -0
  319. package/dist/src/providers/vision-proxy.d.ts +22 -9
  320. package/dist/src/providers/vision-proxy.js +63 -132
  321. package/dist/src/providers/wire-debug.js +95 -0
  322. package/dist/src/router/decide.d.ts +13 -0
  323. package/dist/src/router/decide.js +138 -36
  324. package/dist/src/router/peak-hour.d.ts +38 -0
  325. package/dist/src/router/peak-hour.js +107 -0
  326. package/dist/src/router/step-router.js +3 -2
  327. package/dist/src/router/warm.js +4 -5
  328. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  329. package/dist/src/scaffold/continuation-prompt.js +26 -0
  330. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  331. package/dist/src/scaffold/point-to-existing.js +25 -0
  332. package/dist/src/self-qa/agentic-loop.js +3 -3
  333. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  334. package/dist/src/{ui/state → state}/active-run.js +21 -0
  335. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  336. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  337. package/dist/src/state/turn-trace.d.ts +43 -0
  338. package/dist/src/state/turn-trace.js +32 -0
  339. package/dist/src/storage/db.js +2 -1
  340. package/dist/src/storage/index.d.ts +1 -1
  341. package/dist/src/storage/index.js +1 -1
  342. package/dist/src/storage/interaction-log.d.ts +1 -1
  343. package/dist/src/storage/migrations.js +71 -1
  344. package/dist/src/storage/sessions.d.ts +28 -10
  345. package/dist/src/storage/sessions.js +78 -21
  346. package/dist/src/storage/transcript-view.js +1 -1
  347. package/dist/src/storage/transcript.d.ts +51 -0
  348. package/dist/src/storage/transcript.js +284 -13
  349. package/dist/src/tools/file.d.ts +15 -0
  350. package/dist/src/tools/file.js +32 -0
  351. package/dist/src/tools/native-tools.js +5 -0
  352. package/dist/src/tools/registry.d.ts +3 -0
  353. package/dist/src/tools/registry.js +460 -22
  354. package/dist/src/tools/research.d.ts +29 -0
  355. package/dist/src/tools/research.js +233 -0
  356. package/dist/src/types/index.d.ts +118 -3
  357. package/dist/src/ui/app.js +0 -0
  358. package/dist/src/ui/cards/product-status-card.js +1 -1
  359. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  360. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  361. package/dist/src/ui/components/context-rail.d.ts +26 -0
  362. package/dist/src/ui/components/context-rail.js +33 -0
  363. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  364. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  365. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  366. package/dist/src/ui/components/council-debate-pill.js +34 -0
  367. package/dist/src/ui/components/council-info-card.js +2 -2
  368. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  369. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  370. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  371. package/dist/src/ui/components/council-message-bubble.js +16 -15
  372. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  373. package/dist/src/ui/components/council-phase-timeline.js +49 -15
  374. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  375. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  376. package/dist/src/ui/components/council-question-card.js +12 -12
  377. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  378. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  379. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  380. package/dist/src/ui/components/council-round-group.js +88 -0
  381. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  382. package/dist/src/ui/components/council-status-list.js +36 -24
  383. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  384. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  385. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  386. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  387. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  388. package/dist/src/ui/components/prompt-box.js +18 -16
  389. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  390. package/dist/src/ui/components/session-tree-card.js +46 -0
  391. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  392. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  393. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  394. package/dist/src/ui/components/task-list-panel.js +22 -2
  395. package/dist/src/ui/containers/modals-layer.d.ts +2 -1
  396. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  397. package/dist/src/ui/mcp-modal.js +2 -4
  398. package/dist/src/ui/modals/api-key-modal.js +1 -1
  399. package/dist/src/ui/modals/connect-modal.js +4 -3
  400. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  401. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  402. package/dist/src/ui/picker-providers.d.ts +1 -1
  403. package/dist/src/ui/picker-providers.js +1 -1
  404. package/dist/src/ui/primitives/index.d.ts +1 -0
  405. package/dist/src/ui/primitives/index.js +2 -0
  406. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  407. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  408. package/dist/src/ui/slash/compact.js +5 -7
  409. package/dist/src/ui/slash/cost.js +1 -1
  410. package/dist/src/ui/slash/council.js +19 -1
  411. package/dist/src/ui/slash/debug.d.ts +3 -31
  412. package/dist/src/ui/slash/debug.js +9 -20
  413. package/dist/src/ui/slash/ideal.d.ts +6 -2
  414. package/dist/src/ui/slash/ideal.js +97 -7
  415. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  416. package/dist/src/ui/slash/menu-items.js +12 -18
  417. package/dist/src/ui/slash/registry.d.ts +2 -0
  418. package/dist/src/ui/slash/registry.js +4 -0
  419. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  420. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  421. package/dist/src/ui/status-bar/index.d.ts +1 -1
  422. package/dist/src/ui/status-bar/index.js +7 -3
  423. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  424. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  425. package/dist/src/ui/theme.d.ts +1 -0
  426. package/dist/src/ui/theme.js +2 -0
  427. package/dist/src/ui/types.d.ts +7 -0
  428. package/dist/src/ui/use-app-logic.js +0 -0
  429. package/dist/src/ui/utils/format.d.ts +14 -0
  430. package/dist/src/ui/utils/format.js +23 -3
  431. package/dist/src/usage/downgrade.js +2 -2
  432. package/dist/src/usage/product-ledger.js +2 -2
  433. package/dist/src/utils/install-manager.js +2 -1
  434. package/dist/src/utils/logger.js +2 -2
  435. package/dist/src/utils/permission-mode.js +5 -3
  436. package/dist/src/utils/redactor.js +1 -1
  437. package/dist/src/utils/settings.d.ts +153 -5
  438. package/dist/src/utils/settings.js +233 -29
  439. package/dist/src/utils/visible-retry.d.ts +11 -0
  440. package/dist/src/utils/visible-retry.js +10 -1
  441. package/dist/src/verify/entrypoint.d.ts +1 -1
  442. package/dist/src/verify/entrypoint.js +1 -1
  443. package/dist/src/verify/recipes.d.ts +13 -0
  444. package/dist/src/verify/recipes.js +15 -0
  445. package/package.json +135 -132
  446. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  447. package/dist/src/providers/auth/gcloud.js +0 -102
  448. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  449. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  450. package/dist/src/providers/gemini.d.ts +0 -11
  451. package/dist/src/providers/gemini.js +0 -45
  452. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  453. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  454. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  455. package/dist/src/providers/strategies/google.strategy.js +0 -174
  456. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  457. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  458. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -11,10 +11,11 @@
11
11
  // original orchestrator.ts (see commit history), only `this.xxx` → `this.deps.xxx()`
12
12
  // transposition where the field/method originally lived on Agent.
13
13
  import { generateText, stepCountIs } from "ai";
14
- import { getModelByTier, getModelsForProvider } from "../models/registry.js";
14
+ import { getModelsForProvider } from "../models/registry.js";
15
15
  import { loadKeyForProvider } from "../providers/keychain.js";
16
- import { createProviderFactory, detectProviderForModel, resolveModelRuntime, shouldDropParam, } from "../providers/runtime.js";
16
+ import { createProviderFactory, detectProviderForModel, resolveModelRuntime, resolveTemperatureParam, shouldDropParam, } from "../providers/runtime.js";
17
17
  import { ALL_PROVIDER_IDS } from "../providers/types.js";
18
+ import { getRoutedModelByTier } from "../router/peak-hour.js";
18
19
  import { appendSystemMessage } from "../storage/index.js";
19
20
  import { createBuiltinTools } from "../tools/registry.js";
20
21
  import { isProviderDisabled } from "../utils/settings.js";
@@ -35,6 +36,12 @@ export class CouncilManager {
35
36
  deps;
36
37
  // ---- Mutable state (was Agent private fields) ----
37
38
  _lastSynthesis = null;
39
+ /**
40
+ * Post-debate action the user chose on the last runCouncilV2 (e.g.
41
+ * "continue_session", "save_exit"). Relayed to the auto-council caller
42
+ * (tool-engine) so it can honor the choice instead of always continuing.
43
+ */
44
+ _lastPostDebateAction = null;
38
45
  _isContinuation = false;
39
46
  _questionResolvers = new Map();
40
47
  _preflightResolvers = new Map();
@@ -52,6 +59,12 @@ export class CouncilManager {
52
59
  setLastSynthesis(v) {
53
60
  this._lastSynthesis = v;
54
61
  }
62
+ get lastPostDebateAction() {
63
+ return this._lastPostDebateAction;
64
+ }
65
+ setLastPostDebateAction(v) {
66
+ this._lastPostDebateAction = v;
67
+ }
55
68
  get isContinuation() {
56
69
  return this._isContinuation;
57
70
  }
@@ -62,7 +75,7 @@ export class CouncilManager {
62
75
  this.stats = { calls: 0, startMs: startMs ?? 0 };
63
76
  }
64
77
  // ---- Public responder API (delegated from Agent.respondToCouncilQuestion etc) ----
65
- respondToQuestion(questionId, answer) {
78
+ respondToQuestion(questionId, answer, questionText) {
66
79
  if (process.env.MUONROI_DEBUG_LEADER === "1") {
67
80
  process.stderr.write(`[responder] respondToCouncilQuestion: ${JSON.stringify({
68
81
  questionId,
@@ -75,6 +88,14 @@ export class CouncilManager {
75
88
  if (resolver) {
76
89
  resolver(answer);
77
90
  this._questionResolvers.delete(questionId);
91
+ if (questionText) {
92
+ import("../gsd/phase-sync.js")
93
+ .then(({ appendClarificationToContext }) => {
94
+ const cwd = this.deps.getBash().getCwd();
95
+ appendClarificationToContext(cwd, questionText, answer);
96
+ })
97
+ .catch(() => { });
98
+ }
78
99
  }
79
100
  else {
80
101
  // Headless auto-answer: response arrived before the generator registered
@@ -135,7 +156,7 @@ export class CouncilManager {
135
156
  system,
136
157
  prompt,
137
158
  ...(shouldDropParam(runtime, "maxOutputTokens") ? {} : { maxOutputTokens: maxTokens }),
138
- ...(shouldDropParam(runtime, "temperature") ? {} : { temperature: 0.7 }),
159
+ ...resolveTemperatureParam(runtime, 0.7),
139
160
  ...(runtime.providerOptions ? { providerOptions: runtime.providerOptions } : {}),
140
161
  });
141
162
  this.stats.calls++;
@@ -153,7 +174,8 @@ export class CouncilManager {
153
174
  const runtime = resolveModelRuntime(provider, modelId);
154
175
  // Build tool set with bash, grep, read_file for codebase research
155
176
  const researchTools = createBuiltinTools(this.deps.getBash(), this.deps.getMode(), {
156
- // research phase intentionally has no runTask/runDelegation handlers
177
+ // research phase intentionally has no runTask/runDelegation handlers
178
+ sessionId: this.deps.getSessionId() ?? undefined,
157
179
  });
158
180
  const systemPrompt = `You are a research specialist. Your job is to gather FACTS about the topic below.\n\n` +
159
181
  `## Instructions\n` +
@@ -182,7 +204,7 @@ export class CouncilManager {
182
204
  tools: researchTools,
183
205
  stopWhen: stepCountIs(10),
184
206
  ...(shouldDropParam(runtime, "maxOutputTokens") ? {} : { maxOutputTokens: 4096 }),
185
- ...(shouldDropParam(runtime, "temperature") ? {} : { temperature: 0.3 }),
207
+ ...resolveTemperatureParam(runtime, 0.3),
186
208
  ...(runtime.providerOptions ? { providerOptions: runtime.providerOptions } : {}),
187
209
  ...(signal ? { abortSignal: signal } : {}),
188
210
  });
@@ -251,8 +273,9 @@ export class CouncilManager {
251
273
  }
252
274
  /**
253
275
  * Build conversation context for council discussion from current session messages.
254
- * Extracts: compaction summary, recent user messages, key decisions.
255
- * Limited to ~3000 tokens to avoid excessive cost.
276
+ * Extracts: compaction summary, recent conversation (user + analytical assistant),
277
+ * key decisions/outcomes/plans.
278
+ * Limited to ~8000 tokens (~32K chars) to balance depth vs cost.
256
279
  */
257
280
  buildContext() {
258
281
  const messages = this.deps.getMessages();
@@ -267,34 +290,52 @@ export class CouncilManager {
267
290
  }
268
291
  }
269
292
  }
270
- // 2. Recent user messages (last 3-5 user turns)
271
- const userMessages = [];
272
- for (let i = messages.length - 1; i >= 0 && userMessages.length < 5; i--) {
293
+ // 2. Recent conversation turns — user + analytical assistant messages.
294
+ // Previously only captured user messages, losing assistant analysis,
295
+ // code changes, and decisions made during the session.
296
+ const conversationTurns = [];
297
+ for (let i = messages.length - 1; i >= 0 && conversationTurns.length < 8; i--) {
273
298
  const msg = messages[i];
274
299
  if (msg.role === "user") {
275
300
  const text = typeof msg.content === "string" ? msg.content : extractUserContent(msg.content);
276
301
  if (text.trim()) {
277
- userMessages.unshift(`- ${text.slice(0, 2000).trim()}`);
302
+ conversationTurns.unshift(`[User] ${text.slice(0, 3000).trim()}`);
303
+ }
304
+ }
305
+ else if (msg.role === "assistant") {
306
+ const text = typeof msg.content === "string" ? msg.content : extractUserContent(msg.content);
307
+ // Only include analytical assistant turns (≥80 chars of text — excludes pure tool-call results)
308
+ if (text.trim().length >= 80) {
309
+ conversationTurns.unshift(`[Assistant] ${text.slice(0, 1500).trim()}`);
278
310
  }
279
311
  }
280
312
  }
281
- if (userMessages.length > 0) {
282
- parts.push(`## Recent User Messages\n${userMessages.join("\n")}`);
313
+ if (conversationTurns.length > 0) {
314
+ parts.push(`## Recent Conversation\n${conversationTurns.join("\n\n")}`);
283
315
  }
284
- // 3. Key decisions from council memory if available
285
- const councilMemories = [];
316
+ // 3. Key decisions from system messages (task outcomes, council results, plans, etc.)
317
+ const decisionMsgs = [];
286
318
  for (const msg of messages) {
287
- if (msg.role === "system" && typeof msg.content === "string" && msg.content.includes("[Council Memory]")) {
288
- councilMemories.push(msg.content);
319
+ if (msg.role !== "system" || typeof msg.content !== "string")
320
+ continue;
321
+ const c = msg.content;
322
+ if (c.includes("[Council Memory]") ||
323
+ c.includes("[Council Decision]") ||
324
+ c.includes("[Council Action Items]") ||
325
+ c.includes("[Council Plan Update]") ||
326
+ c.includes("[Decision]") ||
327
+ c.includes("[Task Completed]") ||
328
+ c.includes("[NEEDS HUMAN REVIEW]")) {
329
+ decisionMsgs.push(c);
289
330
  }
290
331
  }
291
- if (councilMemories.length > 0) {
292
- parts.push(`## Previous Council Outcomes\n${councilMemories.slice(-2).join("\n\n")}`);
332
+ if (decisionMsgs.length > 0) {
333
+ parts.push(`## Key Decisions\n${decisionMsgs.slice(-4).join("\n\n")}`);
293
334
  }
294
335
  const combined = parts.join("\n\n---\n\n");
295
- // Rough token estimate: char/4
296
- if (combined.length > 12000) {
297
- return `${combined.slice(0, 12000)}\n\n[... context truncated to fit token budget]`;
336
+ // ~8K token budget (char/4 ≈ token count; cap raised from original 12K chars)
337
+ if (combined.length > 32000) {
338
+ return `${combined.slice(0, 32000)}\n\n[... context truncated to fit token budget]`;
298
339
  }
299
340
  return combined;
300
341
  }
@@ -414,7 +455,7 @@ export class CouncilManager {
414
455
  if (!isProviderDisabled(p)) {
415
456
  const key = await loadKeyForProvider(p).catch(() => null);
416
457
  if (key) {
417
- const m = getModelByTier("balanced", p);
458
+ const m = getRoutedModelByTier("balanced", p);
418
459
  // Guard: getModelByTier may return a model from a different provider
419
460
  // when the preferred provider has no model for the requested tier.
420
461
  if (m && m.provider === p)
@@ -32,6 +32,12 @@ export interface CrossTurnDedupEntry {
32
32
  firstSeenTurn: number;
33
33
  /** Tool name that originally produced the content (for the stub). */
34
34
  firstSeenToolName: string;
35
+ /**
36
+ * Number of SAME-TURN repeat calls seen for this content (0 until the first
37
+ * in-turn re-call). Used to re-serve content once before hard-stopping a
38
+ * loop — see the same-turn branch of maybeDedup.
39
+ */
40
+ sameTurnRepeats: number;
35
41
  }
36
42
  export interface CrossTurnDedupStats {
37
43
  /** Total dedup hits across the lifetime of this instance. */
@@ -75,10 +75,30 @@ export class CrossTurnDedup {
75
75
  const hash = shortHash(raw);
76
76
  const existing = this.cache.get(hash);
77
77
  if (existing) {
78
- this.hits += 1;
79
78
  // Refresh LRU position so frequently-reused outputs survive eviction.
80
79
  this.cache.delete(hash);
81
80
  this.cache.set(hash, existing);
81
+ const thisTurn = this.currentTurn || 1;
82
+ const sameTurnLoop = existing.firstSeenTurn === thisTurn;
83
+ if (sameTurnLoop) {
84
+ // O1/O2 fix — a re-call of identical content WITHIN the same turn is a
85
+ // model loop, not genuine cross-turn reuse. A cheap model (kimi /
86
+ // deepseek) that re-issues the same read usually did so because it did
87
+ // NOT retain the earlier result; a bare "reuse" stub then triggers a
88
+ // WORSE fallback — it re-reads each file singly, inflating fresh input
89
+ // (measured: batch read → stub → stub → 4 single reads). Re-serve the
90
+ // content ONCE (passthrough) to satisfy the loop, then hard-stop on any
91
+ // further in-turn repeat so an infinite loop stays bounded.
92
+ existing.sameTurnRepeats += 1;
93
+ if (existing.sameTurnRepeats === 1)
94
+ return null;
95
+ this.hits += 1;
96
+ return `[${existing.firstSeenToolName} already returned this EXACT result ${existing.sameTurnRepeats + 1}× this turn — it is unchanged and already in the context above. STOP re-calling it; answer from the result you already have.]`;
97
+ }
98
+ // Genuine cross-turn reuse (C3): the user prompted again and the agent
99
+ // re-ran an identical read. The model is not looping, so the short stub
100
+ // is the right, token-saving behavior.
101
+ this.hits += 1;
82
102
  // G3 — short marker. Old format was ~110 chars; this is ~45.
83
103
  return `[dup of ${existing.firstSeenToolName} from turn ${existing.firstSeenTurn} — reuse]`;
84
104
  }
@@ -87,6 +107,7 @@ export class CrossTurnDedup {
87
107
  content: raw,
88
108
  firstSeenTurn: this.currentTurn || 1,
89
109
  firstSeenToolName: toolName,
110
+ sameTurnRepeats: 0,
90
111
  });
91
112
  this.inserts += 1;
92
113
  while (this.cache.size > this.maxEntries) {
@@ -27,6 +27,35 @@ export interface ApiErrorForensics {
27
27
  urlHost: string | undefined;
28
28
  responseBodyTrunc: string | undefined;
29
29
  requestParamKeys: string[] | undefined;
30
+ /** Field-key signature per distinct assistant message shape (PII-safe).
31
+ * Diagnoses Z.ai 1210 / SiliconFlow 20015 "invalid parameter" rejections
32
+ * where the culprit is a missing/extra field on assistant turns in a
33
+ * multi-step tool loop (e.g. reasoning_content present on some turns but
34
+ * absent on tool-only turns). */
35
+ assistantFieldKeys: string[] | undefined;
36
+ /** Per-assistant-message char counts (PII-safe — lengths only, no text).
37
+ * Distinguishes the "uniform shape but still rejected" failure mode:
38
+ * H1 cumulative reasoning budget exceeded vs H2 empty reasoning_content
39
+ * string vs H3 oversized text/tool payload. Set when messages are present. */
40
+ assistantReasoningLens: number[] | undefined;
41
+ /** Total reasoning_content chars across assistant messages. */
42
+ totalReasoningChars: number | undefined;
43
+ /** Values of scalar SDK-config params (reasoning_effort, verbosity,
44
+ * tool_choice, response_format, max_tokens, temperature, top_p,
45
+ * frequency_penalty, presence_penalty, seed, stop, parallel_tool_calls).
46
+ * PII-safe (generation config, not prompt content) — pinpoints WHICH
47
+ * param value a provider rejects when the error is generic (Z.ai 1210,
48
+ * SiliconFlow 20015). */
49
+ configParamValues: Record<string, unknown> | undefined;
50
+ /** Per-assistant tool_calls counts (from assistant messages in the request
51
+ * that failed). Captures H3 for Z.ai 1210: a single assistant response
52
+ * emitting many parallel tool_calls (e.g. 8 or 12) → the follow-up request
53
+ * carrying that many role:tool results gets rejected by the coding endpoint
54
+ * with generic 1210. */
55
+ assistantToolCallCounts: number[] | undefined;
56
+ /** Count of role:"tool" messages in the failing request body. Complements
57
+ * assistantToolCallCounts to show the round-trip payload size for H3. */
58
+ toolMessageCount: number | undefined;
30
59
  isRetryable: boolean | undefined;
31
60
  }
32
61
  export declare function summarizeApiErrorForLog(error: unknown): ApiErrorForensics | null;
@@ -1,16 +1,16 @@
1
1
  import { APICallError } from "@ai-sdk/provider";
2
2
  const STATUS_MESSAGES = {
3
- 400: "The request was invalid. This may be caused by an unsupported parameter or model.",
4
- 401: "Authentication failed. Your API key may be invalid or expired.",
5
- 403: "Access denied. Your API key does not have permission for this request.",
6
- 404: "The requested model or endpoint was not found. Check your model name and base URL.",
7
- 408: "The request timed out. Please try again.",
8
- 422: "The request could not be processed. Check your message format or parameters.",
9
- 429: "Rate limit exceeded. Please wait a moment and try again.",
10
- 500: "The API server encountered an internal error. Please try again later.",
11
- 502: "The API server is temporarily unavailable. Please try again later.",
12
- 503: "The API service is temporarily overloaded. Please try again later.",
13
- 529: "The API service is overloaded. Please try again later.",
3
+ 400: "The provider rejected this request as invalid usually a parameter or model it doesn't support. Try switching models with `-m <model>`, or simplify the request and retry.",
4
+ 401: "The provider didn't accept your API key — it may be missing, invalid, or expired. Run `keys login <provider>` to set a fresh key, then try again.",
5
+ 403: "Your API key works, but it isn't allowed to make this request. Check your plan or key permissions on the provider's dashboard, or switch models with `-m <model>`.",
6
+ 404: "The provider couldn't find that model or endpoint. Double-check the model name (see `models list`) and your base URL, then try again.",
7
+ 408: "The request took too long and timed out. This is usually temporary — just try again.",
8
+ 422: "The provider understood the request but couldn't process it. Check your message format and parameters, then retry — switching models with `-m <model>` can also help.",
9
+ 429: "You're sending requests faster than the provider allows right now. Wait a moment and try again, or switch to another model with `-m <model>`.",
10
+ 500: "Something went wrong on the provider's servers — not on your end. Give it a moment and try again later.",
11
+ 502: "The provider's servers are temporarily unreachable. This usually clears up on its own — try again in a minute.",
12
+ 503: "The provider is overloaded right now. Give it a minute and retry, or switch models with `-m <model>` in the meantime.",
13
+ 529: "The provider is overloaded right now. Give it a minute and retry, or switch models with `-m <model>` in the meantime.",
14
14
  };
15
15
  export function isContextLimitError(error) {
16
16
  const message = error instanceof Error ? error.message : String(error);
@@ -48,14 +48,45 @@ function routingSuffix(error, ctx) {
48
48
  if (status === undefined && /insufficient balance|out of (balance|credit)/i.test(message)) {
49
49
  status = 402;
50
50
  }
51
- if (status === undefined || !ROUTING_STATUSES.has(status))
51
+ const rawMsg = (error instanceof Error ? error.message : String(error)).toLowerCase();
52
+ const isConsoleGo = rawMsg.includes("console go") || ctx?.providerId === "opencode-go";
53
+ const isRateLimitMsg = /rate limit|rate-limited|429|too many requests/i.test(rawMsg);
54
+ // If we have model context and it's a routing error (by status or by message content)
55
+ if (!ctx?.modelId)
56
+ return "";
57
+ if (!(status !== undefined && ROUTING_STATUSES.has(status)) && !isRateLimitMsg && !isConsoleGo)
52
58
  return "";
53
59
  const where = `routed to model "${ctx.modelId}"${ctx.providerId ? ` via provider "${ctx.providerId}"` : ""}`;
54
- const hint = status === 402
55
- ? "out of balance/credit top up the provider account, or switch model with `-m <model>`."
56
- : status === 401 || status === 403
57
- ? "not authenticated for this provider — run `keys login <provider>` (or set its API key), or switch model with `-m <model>`."
58
- : "rate-limitedwait and retry, or switch model with `-m <model>`.";
60
+ // A generic "invalid request" rejection — NOT a rate limit. Console Go can
61
+ // silently re-route (e.g. deepseek-v4-flash a kimi coding backend) and then
62
+ // reject a long tool-loop payload with a bare 400 invalid_request. Retrying
63
+ // as-is never helps (isRetryable:false), so the hint must NOT say "wait and
64
+ // retry" — it must point at the real levers (switch model / shorten payload).
65
+ const isInvalidRequest = status === 400 || status === 422;
66
+ let hint;
67
+ if (isConsoleGo && (isRateLimitMsg || status === 429)) {
68
+ hint =
69
+ "the Console Go proxy hit its own burst rate limit — this is separate from your web 'Rolling Usage' %, so the dashboard can look fine while the proxy still throttles. Wait a moment, use native DeepSeek with `-m deepseek-v4-flash`, or switch provider.";
70
+ }
71
+ else if (status === 402) {
72
+ hint =
73
+ "this provider account is out of balance or credit. Top it up on the provider's site, or switch to another model with `-m <model>`.";
74
+ }
75
+ else if (status === 401 || status === 403) {
76
+ hint =
77
+ "you're not authenticated for this provider. Run `keys login <provider>` (or set its API key), or switch to another model with `-m <model>`.";
78
+ }
79
+ else if (isInvalidRequest) {
80
+ hint =
81
+ "the provider rejected this request as invalid — often a param or backend model it doesn't support, or a tool-loop payload the routed model can't accept (some gateways re-route to a different backend than the one you picked). Switch models with `-m <model>` or shorten/simplify the request; retrying it unchanged won't help.";
82
+ }
83
+ else if (isRateLimitMsg || status === 429) {
84
+ hint = "the provider is rate-limiting you. Wait a moment and retry, or switch to another model with `-m <model>`.";
85
+ }
86
+ else {
87
+ hint =
88
+ "the routed model or provider couldn't complete this request. Switch to another model with `-m <model>`, or try again.";
89
+ }
59
90
  return ` [${where}] — ${hint}`;
60
91
  }
61
92
  export function humanizeApiError(error, ctx) {
@@ -63,7 +94,7 @@ export function humanizeApiError(error, ctx) {
63
94
  }
64
95
  function humanizeApiErrorBase(error) {
65
96
  if (isMalformedFunctionNameError(error)) {
66
- return "Model emitted a malformed tool call (function.name missing). Skipping this turn — please retry or rephrase.";
97
+ return "The model produced a malformed tool call (its function name was missing), so this turn was skipped. Just send your request again rephrasing slightly often helps.";
67
98
  }
68
99
  if (APICallError.isInstance(error)) {
69
100
  const detail = extractResponseDetail(error.responseBody);
@@ -75,7 +106,8 @@ function humanizeApiErrorBase(error) {
75
106
  // For 5xx prefer the canned "retry later" message + the status code; keep a
76
107
  // body detail only when it actually adds information.
77
108
  if (status && status >= 500) {
78
- const canned = STATUS_MESSAGES[status] ?? "The API server returned an error. Please try again later.";
109
+ const canned = STATUS_MESSAGES[status] ??
110
+ "The provider's servers returned an error — not something you did. Wait a bit and try again.";
79
111
  if (!detail || isOpaqueDetail(detail))
80
112
  return `${canned} (HTTP ${status})`;
81
113
  return `${detail} (HTTP ${status})`;
@@ -93,9 +125,9 @@ function humanizeApiErrorBase(error) {
93
125
  const toolMatch = raw.match(/Tool\s+"?(\w+)"?\s+(?:is\s+)?not\s+found/i) ?? raw.match(/tool\s+(\w+)/i);
94
126
  const toolName = toolMatch?.[1] ?? "that tool";
95
127
  if (toolName === "search_web") {
96
- return `"search_web" is not available. Use bash with curl for web requests, or delegate to an explore agent for research.`;
128
+ return `"search_web" isn't available here. For web requests, use bash with curl instead, or hand the research off to an explore agent.`;
97
129
  }
98
- return `Tool "${toolName}" is not available. Check the TOOLS list in the system prompt for supported tools.`;
130
+ return `Tool "${toolName}" isn't available in this session. Check the TOOLS list in the system prompt to see which tools you can use.`;
99
131
  }
100
132
  return stripped;
101
133
  }
@@ -135,9 +167,50 @@ export function summarizeApiErrorForLog(error) {
135
167
  catch {
136
168
  urlHost = undefined;
137
169
  }
138
- let requestParamKeys;
139
- if (error.requestBodyValues && typeof error.requestBodyValues === "object") {
140
- requestParamKeys = Object.keys(error.requestBodyValues).sort();
170
+ const bodyValues = error.requestBodyValues && typeof error.requestBodyValues === "object"
171
+ ? error.requestBodyValues
172
+ : undefined;
173
+ const requestParamKeys = bodyValues ? Object.keys(bodyValues).sort() : undefined;
174
+ // Collect the distinct field-key signature across assistant wire messages.
175
+ // Only key NAMES are persisted — values may contain secrets/PII.
176
+ let assistantFieldKeys;
177
+ let assistantReasoningLens;
178
+ let assistantToolCallCounts;
179
+ let totalReasoningChars = 0;
180
+ let toolMessageCount = 0;
181
+ if (bodyValues && Array.isArray(bodyValues.messages)) {
182
+ const signatures = new Set();
183
+ const rcLens = [];
184
+ const tcLens = [];
185
+ for (const m of bodyValues.messages) {
186
+ const msg = m;
187
+ if (msg?.role === "tool") {
188
+ toolMessageCount++;
189
+ continue;
190
+ }
191
+ if (msg?.role !== "assistant")
192
+ continue;
193
+ const sig = Object.keys(msg ?? {})
194
+ .sort()
195
+ .join(",");
196
+ signatures.add(sig);
197
+ const rc = msg?.reasoning_content;
198
+ if (typeof rc === "string") {
199
+ rcLens.push(rc.length);
200
+ totalReasoningChars += rc.length;
201
+ }
202
+ else {
203
+ rcLens.push(-1); // marker: reasoning_content missing/non-string on this turn
204
+ }
205
+ const tcs = Array.isArray(msg?.tool_calls) ? msg.tool_calls.length : 0;
206
+ tcLens.push(tcs);
207
+ }
208
+ if (signatures.size > 0)
209
+ assistantFieldKeys = [...signatures].sort();
210
+ if (rcLens.length > 0)
211
+ assistantReasoningLens = rcLens;
212
+ if (tcLens.length > 0)
213
+ assistantToolCallCounts = tcLens;
141
214
  }
142
215
  const body = typeof error.responseBody === "string" ? error.responseBody : undefined;
143
216
  const responseBodyTrunc = body && body.length > RESPONSE_BODY_CAP ? `${body.slice(0, RESPONSE_BODY_CAP)}…[truncated]` : body;
@@ -146,8 +219,43 @@ export function summarizeApiErrorForLog(error) {
146
219
  urlHost,
147
220
  responseBodyTrunc,
148
221
  requestParamKeys,
222
+ assistantFieldKeys,
223
+ assistantReasoningLens,
224
+ totalReasoningChars: assistantReasoningLens ? totalReasoningChars : undefined,
225
+ configParamValues: bodyValues ? extractConfigParamValues(bodyValues) : undefined,
226
+ assistantToolCallCounts,
227
+ toolMessageCount: bodyValues && Array.isArray(bodyValues.messages) ? toolMessageCount : undefined,
149
228
  isRetryable: error.isRetryable,
150
229
  };
151
230
  }
231
+ /**
232
+ * Scalar SDK-config params whose VALUES are PII-safe (generation config, not
233
+ * user prompt content). See `ApiErrorForensics.configParamValues`.
234
+ * Includes parallel_tool_calls because Z.ai GLM coding endpoint rejects
235
+ * high-parallelism tool call batches (observed 8-12 in one assistant turn)
236
+ * with generic 1210; capturing the value helps confirm if SDK overrode it.
237
+ */
238
+ const CONFIG_PARAM_KEYS = [
239
+ "reasoning_effort",
240
+ "verbosity",
241
+ "tool_choice",
242
+ "response_format",
243
+ "max_tokens",
244
+ "temperature",
245
+ "top_p",
246
+ "frequency_penalty",
247
+ "presence_penalty",
248
+ "seed",
249
+ "stop",
250
+ "parallel_tool_calls",
251
+ ];
252
+ function extractConfigParamValues(body) {
253
+ const out = {};
254
+ for (const k of CONFIG_PARAM_KEYS) {
255
+ if (k in body)
256
+ out[k] = body[k] ?? null;
257
+ }
258
+ return out;
259
+ }
152
260
  export { extractResponseDetail, STATUS_MESSAGES };
153
261
  //# sourceMappingURL=error-utils.js.map
@@ -41,6 +41,30 @@ const COUNT_RE = new RegExp(`\\b(\\d{1,3}(?:,\\d{3})+|\\d{2,})\\b(?:\\s+(?:\\w+\
41
41
  const NOUN_SEP_NUM_RE = new RegExp(`\\b(?:${COUNT_NOUN})\\b[^.\\n:=]{0,40}?[:=]\\s*(\\d{1,3}(?:,\\d{3})+|\\d{2,})\\b`, "gi");
42
42
  // filename.ext:line — basename only (the char class excludes "/").
43
43
  const FILELINE_RE = /\b([\w.-]+\.[a-z]{1,5}):(\d+)\b/gi;
44
+ // read_file emits a header `[<path>: lines A-B of TOTAL]` (src/tools/file.ts:75).
45
+ // TOTAL is always the FULL file length (not the slice end B), so it is the
46
+ // ground truth for "does line N exist in this file". Path may use "/" or "\";
47
+ // the basename char class excludes both, so it captures just "planner.ts".
48
+ const READ_HEADER_RE = /([\w.-]+\.[a-z]{1,5}):\s*lines\s+\d+-\d+\s+of\s+(\d+)/gi;
49
+ /**
50
+ * Map basename → largest known full-file line count, parsed from read_file
51
+ * headers in the corpus. Used to catch a file:line that names a REAL (read)
52
+ * file but a FABRICATED line number beyond the file's length — the failure the
53
+ * basename-only check misses.
54
+ */
55
+ function parseReadLineCounts(corpus) {
56
+ const totals = new Map();
57
+ for (const m of corpus.matchAll(READ_HEADER_RE)) {
58
+ const base = m[1].toLowerCase();
59
+ const total = Number.parseInt(m[2], 10);
60
+ if (!Number.isFinite(total))
61
+ continue;
62
+ const prev = totals.get(base);
63
+ if (prev === undefined || total > prev)
64
+ totals.set(base, total);
65
+ }
66
+ return totals;
67
+ }
44
68
  // Hedge markers immediately before a number mean it is an estimate, not a fact.
45
69
  const HEDGE_RE = /(~|≈|\babout\b|\bapprox(?:imately)?\b|\broughly\b|\baround\b|\bnearly\b|\best\.?\b)\s*$/i;
46
70
  function stripCommas(s) {
@@ -56,6 +80,7 @@ export function findUnverifiedClaims(finalText, corpus) {
56
80
  return [];
57
81
  const corpusNorm = stripCommas(corpus).toLowerCase();
58
82
  const corpusLower = corpus.toLowerCase();
83
+ const readTotals = parseReadLineCounts(corpus);
59
84
  const out = [];
60
85
  const seen = new Set();
61
86
  const push = (claim) => {
@@ -103,8 +128,21 @@ export function findUnverifiedClaims(finalText, corpus) {
103
128
  if (idx > 0 && finalText[idx - 1] === "/")
104
129
  continue;
105
130
  const basename = m[1];
131
+ const lineNo = Number.parseInt(m[2], 10);
132
+ const knownTotal = readTotals.get(basename.toLowerCase());
133
+ // Provably-fabricated line: the file WAS read this turn (header parsed), but
134
+ // the cited line exceeds its real length. Deterministic — flag even though
135
+ // the basename appears in the corpus (the basename check below would pass).
136
+ if (knownTotal !== undefined && Number.isFinite(lineNo) && lineNo > knownTotal) {
137
+ push({
138
+ kind: "fileline",
139
+ value: `${basename}:${m[2]}`,
140
+ text: `${basename}:${m[2]} (file has ${knownTotal} lines)`,
141
+ });
142
+ continue;
143
+ }
106
144
  if (corpusLower.includes(basename.toLowerCase()))
107
- continue; // file was read/grepped → verified
145
+ continue; // file was read/grepped & in-bounds → verified
108
146
  push({ kind: "fileline", value: `${basename}:${m[2]}`, text: `${basename}:${m[2]}` });
109
147
  }
110
148
  return out.slice(0, MAX_CLAIMS);