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
@@ -13,6 +13,24 @@
13
13
  * 3. Register the singleton in `strategies/registry.ts`.
14
14
  * 4. Add the ProviderId to `src/providers/types.ts` if not already present.
15
15
  */
16
+ /**
17
+ * Catalog ids for models reached through the OpenCode Go (Console Go) gateway
18
+ * carry an `opencode/` routing prefix (e.g. `opencode/deepseek-v4-flash`). That
19
+ * prefix is a *routing* marker, not part of the wire model name any upstream
20
+ * accepts — the gateway itself strips it before forwarding (see
21
+ * OpenCodeGoStrategy.createFactory). When a task sub-model resolved from that
22
+ * catalog id is run through a DIFFERENT provider's factory (e.g. the compaction
23
+ * proposer reusing the parent's native DeepSeek factory), the raw prefixed id
24
+ * would otherwise be POSTed to api.deepseek.com and rejected with HTTP 400
25
+ * "The supported API model names are deepseek-v4-pro or deepseek-v4-flash, but
26
+ * you passed opencode/deepseek-v4-flash". Stripping here — the single chokepoint
27
+ * every provider's resolve() flows through — makes the wire name always native.
28
+ * The returned `modelId` keeps the catalog id so usage/pricing attribution is
29
+ * unchanged; only the id handed to factory() is normalized.
30
+ */
31
+ export function toWireModelId(modelId) {
32
+ return modelId.startsWith("opencode/") ? modelId.slice("opencode/".length) : modelId;
33
+ }
16
34
  /**
17
35
  * Shared base — most providers want the same `resolve` body. Subclasses
18
36
  * override only when truly different.
@@ -21,7 +39,12 @@ export class BaseProviderStrategy {
21
39
  resolve(opts) {
22
40
  const { factory, modelId, modelInfo, reasoningEffort } = opts;
23
41
  const useResponsesApi = this.capabilities.usesResponsesAPI(modelInfo);
24
- const model = useResponsesApi && factory.responses ? factory.responses(modelId) : factory(modelId);
42
+ // Normalize the wire model name (strip the `opencode/` routing prefix) so a
43
+ // native provider factory never receives a gateway-routed id. See
44
+ // toWireModelId above. `modelId` (catalog id) is still returned below for
45
+ // attribution — only the id passed to factory() is normalized.
46
+ const wireModelId = toWireModelId(modelId);
47
+ const model = useResponsesApi && factory.responses ? factory.responses(wireModelId) : factory(wireModelId);
25
48
  const providerOptions = this.capabilities.buildProviderOptions({
26
49
  model: modelInfo,
27
50
  reasoningEffort,
@@ -1,13 +1,13 @@
1
1
  /**
2
- * src/providers/strategies/siliconflow.strategy.ts
2
+ * src/providers/strategies/opencode-go.strategy.ts
3
3
  *
4
- * Phase 12.2-G4 — SiliconFlow strategy via `@ai-sdk/openai-compatible`.
4
+ * OpenCode Go strategy via `@ai-sdk/openai-compatible`.
5
5
  */
6
6
  import { type ProviderCapabilities } from "../capabilities.js";
7
7
  import type { ProviderFactory } from "../runtime.js";
8
8
  import type { ProviderId } from "../types.js";
9
9
  import { BaseProviderStrategy, type CreateFactoryOpts } from "./base.strategy.js";
10
- export declare class SiliconflowStrategy extends BaseProviderStrategy {
10
+ export declare class OpenCodeGoStrategy extends BaseProviderStrategy {
11
11
  readonly id: ProviderId;
12
12
  readonly capabilities: ProviderCapabilities;
13
13
  createFactory(opts: CreateFactoryOpts): ProviderFactory;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * src/providers/strategies/opencode-go.strategy.ts
3
+ *
4
+ * OpenCode Go strategy via `@ai-sdk/openai-compatible`.
5
+ */
6
+ import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
7
+ import { getProviderCapabilities } from "../capabilities.js";
8
+ import { OPENAI_COMPATIBLE_BASE_URLS } from "../endpoints.js";
9
+ import { BaseProviderStrategy } from "./base.strategy.js";
10
+ import { backfillReasoningContent, sanitizeToolCallArguments, splitParallelToolCalls, transformThinkingModeBody, transformZaiThinkingBody, } from "./thinking-mode.js";
11
+ export class OpenCodeGoStrategy extends BaseProviderStrategy {
12
+ id = "opencode-go";
13
+ capabilities = getProviderCapabilities("opencode-go");
14
+ createFactory(opts) {
15
+ const p = createOpenAICompatible({
16
+ name: this.id,
17
+ baseURL: opts.baseURL ?? OPENAI_COMPATIBLE_BASE_URLS["opencode-go"],
18
+ apiKey: opts.apiKey ?? (opts.headers ? "oauth" : undefined),
19
+ ...(opts.headers ? { headers: opts.headers } : {}),
20
+ // DeepSeek models (common via opencode-go) do not support full json_schema,
21
+ // only json_object. Prevent AI SDK from sending unsupported schema.
22
+ supportsStructuredOutputs: false,
23
+ // Apply thinking-mode transform for deepseek models routed via opencode-go (e.g. deepseek-v4-flash).
24
+ // The opencode Console Go backend forwards to DeepSeek, which requires reasoning_content
25
+ // roundtrips (like direct DeepSeek). Without it, histories with tool calls produce
26
+ // "Upstream request failed" / invalid_request_error (observed in session 53f3c3ea4ae8).
27
+ // Inspect body.model (after possible prefix) to apply only when appropriate.
28
+ transformRequestBody: (body) => {
29
+ const modelInBody = body?.model || "";
30
+ const isDeepseekModel = modelInBody.includes("deepseek") || modelInBody.includes("v4-flash");
31
+ const isGlmModel = modelInBody.includes("glm");
32
+ let out = body;
33
+ if (isDeepseekModel) {
34
+ out = transformThinkingModeBody(body);
35
+ }
36
+ else if (isGlmModel) {
37
+ // For GLM models via opencode-go, use zai-style sanitization (reasoning backfill + tool shape).
38
+ out = transformZaiThinkingBody(body);
39
+ }
40
+ else {
41
+ // Other reasoning-capable models via Console Go (e.g. kimi-k2.7-code).
42
+ // Verified 2026-07-02 (session 53f3c3ea4ae8): kimi histories arrive
43
+ // MIXED — some assistant turns carry reasoning_content, some do not —
44
+ // and Console Go rejects the request (400 "Upstream request failed").
45
+ // Apply the same mixed-history reasoning backfill Z.ai uses.
46
+ out = { ...body };
47
+ if (Array.isArray(out.messages)) {
48
+ out.messages = backfillReasoningContent(out.messages, { onlyIfMixed: true });
49
+ }
50
+ }
51
+ // H3 REAL FIX — Console Go's upstream (kimi / deepseek / glm) rejects a
52
+ // follow-up whose history has an assistant turn with a batch of parallel
53
+ // tool_calls (observed 5/6 for kimi, up to 17 for glm). parallel_tool_calls
54
+ // below is ignored by the model, so split any multi-tool-call assistant
55
+ // turn into sequential single-call turns. No-op unless the failing
56
+ // pattern is present, so successful requests are untouched.
57
+ if (Array.isArray(out.messages)) {
58
+ out.messages = splitParallelToolCalls(out.messages);
59
+ // Repair empty/truncated tool_call arguments ("unexpected end of JSON
60
+ // input" 1210 sub-cause) before they reach the Console Go upstream.
61
+ out.messages = sanitizeToolCallArguments(out.messages);
62
+ }
63
+ // Additional sanitization for opencode-go (proxy can be sensitive):
64
+ // Force no parallel to avoid large tool result batches causing upstream failures.
65
+ // Drop null response_format.
66
+ out.parallel_tool_calls = false;
67
+ if ("response_format" in out) {
68
+ const rf = out.response_format;
69
+ if (rf == null || (typeof rf === "object" && Object.keys(rf).length === 0)) {
70
+ delete out.response_format;
71
+ }
72
+ }
73
+ return out;
74
+ },
75
+ });
76
+ return (modelId) => {
77
+ // Strip 'opencode/' prefix if present
78
+ const cleanId = modelId.startsWith("opencode/") ? modelId.slice(9) : modelId;
79
+ return p(cleanId);
80
+ };
81
+ }
82
+ }
83
+ //# sourceMappingURL=opencode-go.strategy.js.map
@@ -6,19 +6,19 @@
6
6
  */
7
7
  import { AnthropicStrategy } from "./anthropic.strategy.js";
8
8
  import { DeepSeekStrategy } from "./deepseek.strategy.js";
9
- import { GoogleStrategy } from "./google.strategy.js";
10
9
  import { OllamaStrategy } from "./ollama.strategy.js";
11
10
  import { OpenAIStrategy } from "./openai.strategy.js";
12
- import { SiliconflowStrategy } from "./siliconflow.strategy.js";
11
+ import { OpenCodeGoStrategy } from "./opencode-go.strategy.js";
13
12
  import { XAIStrategy } from "./xai.strategy.js";
13
+ import { ZaiStrategy } from "./zai.strategy.js";
14
14
  const STRATEGIES = {
15
15
  anthropic: new AnthropicStrategy(),
16
16
  openai: new OpenAIStrategy(),
17
- google: new GoogleStrategy(),
18
17
  deepseek: new DeepSeekStrategy(),
19
- siliconflow: new SiliconflowStrategy(),
20
18
  xai: new XAIStrategy(),
21
19
  ollama: new OllamaStrategy(),
20
+ zai: new ZaiStrategy(),
21
+ "opencode-go": new OpenCodeGoStrategy(),
22
22
  };
23
23
  /**
24
24
  * Returns the strategy singleton for a given provider id. Throws on unknown
@@ -28,8 +28,117 @@
28
28
  * https://api-docs.deepseek.com/guides/thinking_mode
29
29
  */
30
30
  export declare function shouldDisableThinking(): boolean;
31
+ interface WireMessage {
32
+ role?: unknown;
33
+ content?: unknown;
34
+ reasoning_content?: unknown;
35
+ tool_calls?: unknown;
36
+ [k: string]: unknown;
37
+ }
38
+ /**
39
+ * Backfill `reasoning_content: ""` onto any assistant message that lacks a
40
+ * (non-empty/present) one, so SiliconFlow's thinking-mode validator never
41
+ * sees a reasoning-less assistant turn. Assistant turns that already carry a
42
+ * real `reasoning_content` are left untouched.
43
+ *
44
+ * `opts.onlyIfMixed` (used by Z.ai): skip the backfill entirely when NO
45
+ * assistant message in the history carries a `reasoning_content` field. This
46
+ * guards non-thinking models (glm-4.5-air, glm-4.6v-flash) from having an
47
+ * unknown `reasoning_content` field injected — which would itself trigger
48
+ * Z.ai's 1210. Once any one assistant turn carries reasoning (i.e. the
49
+ * conversation is in thinking mode — confirmed by the model's own emission),
50
+ * the backfill brings every other assistant turn up to the same shape.
51
+ */
52
+ export declare function backfillReasoningContent(messages: WireMessage[], opts?: {
53
+ onlyIfMixed?: boolean;
54
+ }): WireMessage[];
55
+ /**
56
+ * Split assistant messages that carry MORE THAN ONE `tool_calls` entry into a
57
+ * sequence of single-tool-call assistant turns, each immediately followed by
58
+ * its matching `role:"tool"` result. Identity (returns the same array by
59
+ * reference) when no assistant message has >1 tool_calls.
60
+ *
61
+ * WHY (verified from live sessions c0dcf9153803 / c1f5ca294496 and the
62
+ * llm-wire.log forensics on 2026-07-02): both the Z.ai GLM coding endpoint
63
+ * (HTTP 400 / code 1210 "Invalid API parameter") and the opencode Console Go
64
+ * proxy (HTTP 400 invalid_request_error "Upstream request failed") REJECT a
65
+ * follow-up request whose history contains an assistant turn that emitted a
66
+ * large batch of parallel tool_calls (observed 5, 6, 8, 12, and 17 in a single
67
+ * assistant message). Forcing `parallel_tool_calls:false` does NOT prevent
68
+ * this — the model ignores the flag and still emits batches, and the flag has
69
+ * no effect on assistant turns already in the history. The only reliable fix
70
+ * is to reshape the echoed-back history so no single assistant turn presents
71
+ * more than one tool_call.
72
+ *
73
+ * Safety: because this is a no-op unless an assistant turn has >1 tool_calls,
74
+ * it can only ever alter requests that match the known-failing pattern —
75
+ * requests that already succeed (≤1 tool_call per turn) are returned
76
+ * untouched.
77
+ *
78
+ * `reasoning_content` (when present) is kept on the FIRST split turn only and
79
+ * blanked to "" on the rest, so a single reasoning segment is not duplicated
80
+ * across the synthesized turns. Assistant `content` is likewise kept on the
81
+ * first and blanked on the rest.
82
+ */
83
+ export declare function splitParallelToolCalls(messages: WireMessage[]): WireMessage[];
31
84
  /**
32
85
  * The shared `transformRequestBody` for deepseek + siliconflow. Runs on the
33
86
  * fully-serialized wire body right before fetch.
34
87
  */
35
88
  export declare function transformThinkingModeBody<T extends Record<string, unknown>>(body: T): T;
89
+ /**
90
+ * Should the Z.ai thinking-disable escape hatch fire? Off by default — Z.ai
91
+ * GLM coding-plan endpoints (`api.z.ai/api/coding/paas/v4`) auto-enable
92
+ * thinking for reasoning-capable models (glm-4.7, glm-5.x), and we want the
93
+ * reasoning_content round-trip to succeed. Set `MUONROI_ZAI_DISABLE_THINKING=1`
94
+ * to mirror DeepSeek's fallback B (disable thinking entirely).
95
+ */
96
+ export declare function shouldDisableZaiThinking(): boolean;
97
+ /** True once a provider param-reject has flipped the session into degraded mode. */
98
+ export declare function isProviderThinkingDegraded(): boolean;
99
+ /** Latch degraded mode on (idempotent). Called by the retry classifier. */
100
+ export declare function markProviderThinkingDegrade(): void;
101
+ /** Test-only reset so the module latch doesn't leak across cases. */
102
+ export declare function _resetProviderThinkingDegrade(): void;
103
+ /**
104
+ * Ensure every assistant `tool_calls[].function.arguments` is a valid JSON
105
+ * STRING. GLM's coding endpoint returns a generic 1210 with the underlying
106
+ * detail "error parsing parameters: unexpected end of JSON input" when an
107
+ * assistant turn echoes back a tool call whose `arguments` is empty, missing,
108
+ * or truncated (verified failure mode reported by crush #1237 and opencode
109
+ * users — a big parallel-tool-call batch clamped by max_tokens truncates the
110
+ * last call's arguments mid-string). Repairs are conservative: a value that
111
+ * already parses as JSON is left untouched; only empty/missing/unparseable
112
+ * arguments are replaced with `"{}"`, and a stray object is re-stringified.
113
+ * No-op (returns input by reference) when nothing needs repair.
114
+ */
115
+ export declare function sanitizeToolCallArguments(messages: WireMessage[]): WireMessage[];
116
+ /**
117
+ * Z.ai's `transformRequestBody`. Mirrors `transformThinkingModeBody` but with
118
+ * one critical difference: the reasoning_content backfill is GATED on
119
+ * `onlyIfMixed` — it only fires once at least one assistant message in the
120
+ * history already carries reasoning_content. This protects non-thinking Z.ai
121
+ * models (glm-4.5-air, glm-4.6v-flash) which would otherwise reject the
122
+ * injected field with HTTP 400 / code 1210.
123
+ *
124
+ * Verified failure: session c0dcf9153803 — GLM-4.7 on the Z.ai coding
125
+ * endpoint. First 4 assistant turns succeeded; on the 5th streamText call
126
+ * (after 6 tool rounds, where intermediate assistant steps carried tool_calls
127
+ * WITHOUT reasoning), Z.ai rejected the whole request with code 1210
128
+ * "Invalid API parameter". Same class of bug as SiliconFlow 20015 (see
129
+ * `transformThinkingModeBody` above), but Z.ai also hosts non-thinking models
130
+ * on the same strategy, so the backfill must stay conditional.
131
+ *
132
+ * H3 mitigation (added after c7c4a6487847 + 94827f75a69e + c94360bac00f + c1f5ca294496):
133
+ * GLM coding endpoint rejects the request (often as generic 1210) when the
134
+ * history contains assistant turns with multiple tool_calls (even after forcing
135
+ * parallel_tool_calls:false — model still emitted batches of 2-5). The reject
136
+ * frequently manifests as stall timeout because the provider stops emitting
137
+ * chunks. We do extra sanitization here:
138
+ * - force parallel_tool_calls:false
139
+ * - drop response_format when null/empty (combo with tools is fragile)
140
+ * - clamp max_tokens > 4096 down to 4096 (higher values seen in 1210s)
141
+ * Trade-off: more sequential tool use + slightly lower token budget.
142
+ */
143
+ export declare function transformZaiThinkingBody<T extends Record<string, unknown>>(body: T): T;
144
+ export {};
@@ -36,8 +36,21 @@ export function shouldDisableThinking() {
36
36
  * (non-empty/present) one, so SiliconFlow's thinking-mode validator never
37
37
  * sees a reasoning-less assistant turn. Assistant turns that already carry a
38
38
  * real `reasoning_content` are left untouched.
39
+ *
40
+ * `opts.onlyIfMixed` (used by Z.ai): skip the backfill entirely when NO
41
+ * assistant message in the history carries a `reasoning_content` field. This
42
+ * guards non-thinking models (glm-4.5-air, glm-4.6v-flash) from having an
43
+ * unknown `reasoning_content` field injected — which would itself trigger
44
+ * Z.ai's 1210. Once any one assistant turn carries reasoning (i.e. the
45
+ * conversation is in thinking mode — confirmed by the model's own emission),
46
+ * the backfill brings every other assistant turn up to the same shape.
39
47
  */
40
- function backfillReasoningContent(messages) {
48
+ export function backfillReasoningContent(messages, opts = {}) {
49
+ if (opts.onlyIfMixed) {
50
+ const hasAnyReasoning = messages.some((m) => m?.role === "assistant" && typeof m.reasoning_content === "string");
51
+ if (!hasAnyReasoning)
52
+ return messages;
53
+ }
41
54
  let mutated = false;
42
55
  const next = messages.map((m) => {
43
56
  if (m?.role !== "assistant")
@@ -63,6 +76,75 @@ function backfillReasoningContent(messages) {
63
76
  });
64
77
  return mutated ? next : messages;
65
78
  }
79
+ /**
80
+ * Split assistant messages that carry MORE THAN ONE `tool_calls` entry into a
81
+ * sequence of single-tool-call assistant turns, each immediately followed by
82
+ * its matching `role:"tool"` result. Identity (returns the same array by
83
+ * reference) when no assistant message has >1 tool_calls.
84
+ *
85
+ * WHY (verified from live sessions c0dcf9153803 / c1f5ca294496 and the
86
+ * llm-wire.log forensics on 2026-07-02): both the Z.ai GLM coding endpoint
87
+ * (HTTP 400 / code 1210 "Invalid API parameter") and the opencode Console Go
88
+ * proxy (HTTP 400 invalid_request_error "Upstream request failed") REJECT a
89
+ * follow-up request whose history contains an assistant turn that emitted a
90
+ * large batch of parallel tool_calls (observed 5, 6, 8, 12, and 17 in a single
91
+ * assistant message). Forcing `parallel_tool_calls:false` does NOT prevent
92
+ * this — the model ignores the flag and still emits batches, and the flag has
93
+ * no effect on assistant turns already in the history. The only reliable fix
94
+ * is to reshape the echoed-back history so no single assistant turn presents
95
+ * more than one tool_call.
96
+ *
97
+ * Safety: because this is a no-op unless an assistant turn has >1 tool_calls,
98
+ * it can only ever alter requests that match the known-failing pattern —
99
+ * requests that already succeed (≤1 tool_call per turn) are returned
100
+ * untouched.
101
+ *
102
+ * `reasoning_content` (when present) is kept on the FIRST split turn only and
103
+ * blanked to "" on the rest, so a single reasoning segment is not duplicated
104
+ * across the synthesized turns. Assistant `content` is likewise kept on the
105
+ * first and blanked on the rest.
106
+ */
107
+ export function splitParallelToolCalls(messages) {
108
+ const needsSplit = messages.some((m) => m?.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 1);
109
+ if (!needsSplit)
110
+ return messages;
111
+ const out = [];
112
+ for (let i = 0; i < messages.length; i++) {
113
+ const m = messages[i];
114
+ const toolCalls = m?.role === "assistant" && Array.isArray(m.tool_calls) ? m.tool_calls : null;
115
+ if (!toolCalls || toolCalls.length <= 1) {
116
+ out.push(m);
117
+ continue;
118
+ }
119
+ // Collect the contiguous block of role:"tool" results that follows this
120
+ // assistant turn, keyed by tool_call_id, so each split can carry its own.
121
+ const resultsById = new Map();
122
+ let j = i + 1;
123
+ while (j < messages.length && messages[j]?.role === "tool") {
124
+ const id = messages[j].tool_call_id;
125
+ if (typeof id === "string")
126
+ resultsById.set(id, messages[j]);
127
+ j++;
128
+ }
129
+ for (let k = 0; k < toolCalls.length; k++) {
130
+ const tc = toolCalls[k];
131
+ const single = { ...m, tool_calls: [tc] };
132
+ if (k > 0) {
133
+ // Avoid duplicating reasoning/content across the synthesized turns.
134
+ if (typeof m.reasoning_content === "string")
135
+ single.reasoning_content = "";
136
+ single.content = "";
137
+ }
138
+ out.push(single);
139
+ const res = typeof tc.id === "string" ? resultsById.get(tc.id) : undefined;
140
+ if (res)
141
+ out.push(res);
142
+ }
143
+ // Skip past the consumed tool-result block.
144
+ i = j - 1;
145
+ }
146
+ return out;
147
+ }
66
148
  /**
67
149
  * The shared `transformRequestBody` for deepseek + siliconflow. Runs on the
68
150
  * fully-serialized wire body right before fetch.
@@ -83,4 +165,201 @@ export function transformThinkingModeBody(body) {
83
165
  return body;
84
166
  return { ...body, messages: patched };
85
167
  }
168
+ /**
169
+ * Should the Z.ai thinking-disable escape hatch fire? Off by default — Z.ai
170
+ * GLM coding-plan endpoints (`api.z.ai/api/coding/paas/v4`) auto-enable
171
+ * thinking for reasoning-capable models (glm-4.7, glm-5.x), and we want the
172
+ * reasoning_content round-trip to succeed. Set `MUONROI_ZAI_DISABLE_THINKING=1`
173
+ * to mirror DeepSeek's fallback B (disable thinking entirely).
174
+ */
175
+ export function shouldDisableZaiThinking() {
176
+ const v = process.env.MUONROI_ZAI_DISABLE_THINKING;
177
+ if (v !== undefined && (v === "1" || v.toLowerCase() === "true"))
178
+ return true;
179
+ // One-shot runtime degrade: once a zai/opencode coding endpoint has rejected a
180
+ // request with a generic param error (1210 / "Upstream request failed"), we
181
+ // flip thinking OFF for the remainder of the session so the retry (and every
182
+ // subsequent call) sends the simpler, validator-safe shape. See
183
+ // markProviderThinkingDegrade / retry-classifier.ts.
184
+ return _thinkingDegraded;
185
+ }
186
+ /**
187
+ * Runtime "degrade" latch. Set once a z.ai / opencode-go coding endpoint
188
+ * rejects a request with a generic, spec-undocumented param error (code 1210
189
+ * "Invalid API parameter" / Console Go "Upstream request failed"). Because
190
+ * z.ai does NOT document the exact constraint (verified 2026-07-02 against
191
+ * docs.z.ai/api-reference/api-code — 1210 is an intentionally generic bucket),
192
+ * a fully preventive client fix is impossible. The pragmatic guard is: give the
193
+ * request exactly one retry with a degraded-but-valid body (thinking disabled →
194
+ * no reasoning_content round-trip requirement; parallel tool_calls already
195
+ * split). retry-classifier.ts drives the one-shot semantics.
196
+ */
197
+ let _thinkingDegraded = false;
198
+ /** True once a provider param-reject has flipped the session into degraded mode. */
199
+ export function isProviderThinkingDegraded() {
200
+ return _thinkingDegraded;
201
+ }
202
+ /** Latch degraded mode on (idempotent). Called by the retry classifier. */
203
+ export function markProviderThinkingDegrade() {
204
+ _thinkingDegraded = true;
205
+ }
206
+ /** Test-only reset so the module latch doesn't leak across cases. */
207
+ export function _resetProviderThinkingDegrade() {
208
+ _thinkingDegraded = false;
209
+ }
210
+ /**
211
+ * Ensure every assistant `tool_calls[].function.arguments` is a valid JSON
212
+ * STRING. GLM's coding endpoint returns a generic 1210 with the underlying
213
+ * detail "error parsing parameters: unexpected end of JSON input" when an
214
+ * assistant turn echoes back a tool call whose `arguments` is empty, missing,
215
+ * or truncated (verified failure mode reported by crush #1237 and opencode
216
+ * users — a big parallel-tool-call batch clamped by max_tokens truncates the
217
+ * last call's arguments mid-string). Repairs are conservative: a value that
218
+ * already parses as JSON is left untouched; only empty/missing/unparseable
219
+ * arguments are replaced with `"{}"`, and a stray object is re-stringified.
220
+ * No-op (returns input by reference) when nothing needs repair.
221
+ */
222
+ export function sanitizeToolCallArguments(messages) {
223
+ let mutated = false;
224
+ const next = messages.map((m) => {
225
+ if (m?.role !== "assistant")
226
+ return m;
227
+ const calls = m.tool_calls;
228
+ if (!Array.isArray(calls) || calls.length === 0)
229
+ return m;
230
+ let callsChanged = false;
231
+ const newCalls = calls.map((c) => {
232
+ const call = c;
233
+ const fn = call?.function;
234
+ if (!fn || typeof fn !== "object")
235
+ return c;
236
+ const args = fn.arguments;
237
+ let repaired;
238
+ if (typeof args === "string") {
239
+ const trimmed = args.trim();
240
+ if (trimmed === "") {
241
+ repaired = "{}";
242
+ }
243
+ else {
244
+ try {
245
+ JSON.parse(trimmed);
246
+ }
247
+ catch {
248
+ repaired = "{}";
249
+ }
250
+ }
251
+ }
252
+ else if (args === undefined || args === null) {
253
+ repaired = "{}";
254
+ }
255
+ else if (typeof args === "object") {
256
+ // Wire shape should be a string; re-stringify a stray object.
257
+ try {
258
+ repaired = JSON.stringify(args);
259
+ }
260
+ catch {
261
+ repaired = "{}";
262
+ }
263
+ }
264
+ if (repaired === undefined)
265
+ return c;
266
+ callsChanged = true;
267
+ return { ...call, function: { ...fn, arguments: repaired } };
268
+ });
269
+ if (!callsChanged)
270
+ return m;
271
+ mutated = true;
272
+ return { ...m, tool_calls: newCalls };
273
+ });
274
+ return mutated ? next : messages;
275
+ }
276
+ /**
277
+ * Z.ai's `transformRequestBody`. Mirrors `transformThinkingModeBody` but with
278
+ * one critical difference: the reasoning_content backfill is GATED on
279
+ * `onlyIfMixed` — it only fires once at least one assistant message in the
280
+ * history already carries reasoning_content. This protects non-thinking Z.ai
281
+ * models (glm-4.5-air, glm-4.6v-flash) which would otherwise reject the
282
+ * injected field with HTTP 400 / code 1210.
283
+ *
284
+ * Verified failure: session c0dcf9153803 — GLM-4.7 on the Z.ai coding
285
+ * endpoint. First 4 assistant turns succeeded; on the 5th streamText call
286
+ * (after 6 tool rounds, where intermediate assistant steps carried tool_calls
287
+ * WITHOUT reasoning), Z.ai rejected the whole request with code 1210
288
+ * "Invalid API parameter". Same class of bug as SiliconFlow 20015 (see
289
+ * `transformThinkingModeBody` above), but Z.ai also hosts non-thinking models
290
+ * on the same strategy, so the backfill must stay conditional.
291
+ *
292
+ * H3 mitigation (added after c7c4a6487847 + 94827f75a69e + c94360bac00f + c1f5ca294496):
293
+ * GLM coding endpoint rejects the request (often as generic 1210) when the
294
+ * history contains assistant turns with multiple tool_calls (even after forcing
295
+ * parallel_tool_calls:false — model still emitted batches of 2-5). The reject
296
+ * frequently manifests as stall timeout because the provider stops emitting
297
+ * chunks. We do extra sanitization here:
298
+ * - force parallel_tool_calls:false
299
+ * - drop response_format when null/empty (combo with tools is fragile)
300
+ * - clamp max_tokens > 4096 down to 4096 (higher values seen in 1210s)
301
+ * Trade-off: more sequential tool use + slightly lower token budget.
302
+ */
303
+ export function transformZaiThinkingBody(body) {
304
+ const out = { ...body };
305
+ if (shouldDisableZaiThinking()) {
306
+ out.thinking = { type: "disabled" };
307
+ }
308
+ else {
309
+ const messages = body.messages;
310
+ if (Array.isArray(messages)) {
311
+ let patched = backfillReasoningContent(messages, { onlyIfMixed: true });
312
+ // Extra hardening inspired by opencode + observed Z.ai GLM behavior:
313
+ // Assistant messages that only contain tool_calls sometimes arrive with
314
+ // content: null. The coding endpoint can be strict about this shape
315
+ // when reasoning_content is also present.
316
+ patched = patched.map((m) => {
317
+ if (m?.role !== "assistant")
318
+ return m;
319
+ const mm = m;
320
+ const hasToolCalls = Array.isArray(mm.tool_calls) && mm.tool_calls.length > 0;
321
+ if (hasToolCalls && (mm.content === null || mm.content === undefined)) {
322
+ return { ...mm, content: "" };
323
+ }
324
+ return m;
325
+ });
326
+ // H3 REAL FIX (parallel_tool_calls:false proven ineffective — the model
327
+ // ignores it and still emits 8-17 tool_calls; the coding endpoint then
328
+ // 1210s on the echo-back). Split multi-tool-call assistant turns so no
329
+ // single assistant message ever presents >1 tool_call to Z.ai.
330
+ patched = splitParallelToolCalls(patched);
331
+ // Guard the "unexpected end of JSON input" 1210 sub-cause: ensure every
332
+ // echoed tool_call carries valid JSON arguments (empty/truncated → "{}").
333
+ patched = sanitizeToolCallArguments(patched);
334
+ if (patched !== messages) {
335
+ out.messages = patched;
336
+ }
337
+ }
338
+ }
339
+ // H3 mitigation (Z.ai coding 1210 on 8-17 parallel tool_calls, still seen
340
+ // with smaller batches in c1f5ca294496 even after the flag):
341
+ // Always force parallel_tool_calls:false. Kept as belt-and-suspenders even
342
+ // though the split above is the actual lever (the model ignores this flag).
343
+ out.parallel_tool_calls = false;
344
+ // Z.ai coding endpoint is known to return generic 1210 for certain param
345
+ // combinations when tools are present (observed across many sessions).
346
+ // - response_format (even when null) combined with tools has been implicated.
347
+ // - Higher max_tokens (e.g. 8192) appeared in failing requests.
348
+ // Clean these here so they never reach the wire for zai.
349
+ if ("response_format" in out) {
350
+ const rf = out.response_format;
351
+ if (rf == null || (typeof rf === "object" && Object.keys(rf).length === 0)) {
352
+ delete out.response_format;
353
+ }
354
+ }
355
+ if (typeof out.max_tokens === "number" && out.max_tokens > 4096) {
356
+ out.max_tokens = 4096;
357
+ }
358
+ // Also normalize possible camelCase variant the SDK might emit
359
+ if ("parallelToolCalls" in out) {
360
+ out.parallel_tool_calls = out.parallelToolCalls;
361
+ delete out.parallelToolCalls;
362
+ }
363
+ return out;
364
+ }
86
365
  //# sourceMappingURL=thinking-mode.js.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * src/providers/strategies/zai.strategy.ts
3
+ *
4
+ * Z.ai strategy via `@ai-sdk/openai-compatible`.
5
+ */
6
+ import { type ProviderCapabilities } from "../capabilities.js";
7
+ import type { ProviderFactory } from "../runtime.js";
8
+ import type { ProviderId } from "../types.js";
9
+ import { BaseProviderStrategy, type CreateFactoryOpts } from "./base.strategy.js";
10
+ export declare class ZaiStrategy extends BaseProviderStrategy {
11
+ readonly id: ProviderId;
12
+ readonly capabilities: ProviderCapabilities;
13
+ createFactory(opts: CreateFactoryOpts): ProviderFactory;
14
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * src/providers/strategies/zai.strategy.ts
3
+ *
4
+ * Z.ai strategy via `@ai-sdk/openai-compatible`.
5
+ */
6
+ import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
7
+ import { getProviderCapabilities } from "../capabilities.js";
8
+ import { OPENAI_COMPATIBLE_BASE_URLS } from "../endpoints.js";
9
+ import { BaseProviderStrategy } from "./base.strategy.js";
10
+ import { transformZaiThinkingBody } from "./thinking-mode.js";
11
+ export class ZaiStrategy extends BaseProviderStrategy {
12
+ id = "zai";
13
+ capabilities = getProviderCapabilities("zai");
14
+ createFactory(opts) {
15
+ const p = createOpenAICompatible({
16
+ name: this.id,
17
+ baseURL: opts.baseURL ?? OPENAI_COMPATIBLE_BASE_URLS.zai,
18
+ apiKey: opts.apiKey ?? (opts.headers ? "oauth" : undefined),
19
+ ...(opts.headers ? { headers: opts.headers } : {}),
20
+ // Many Z.ai users (especially Coding Plan) hit 1210 / empty responses
21
+ // when using the wrong baseURL or when the SDK sends extra fields.
22
+ // Default is the coding/paas/v4 endpoint (matching opencode recommendations).
23
+ // Users can override via --base-url or provider config for the standard paas.
24
+ // Z.ai coding endpoint (api.z.ai/api/coding/paas/v4) auto-enables
25
+ // thinking for GLM-4.7 / GLM-5.x. In a multi-step tool loop some
26
+ // intermediate assistant turns carry tool_calls WITHOUT reasoning, so
27
+ // @ai-sdk/openai-compatible serializes them without a reasoning_content
28
+ // key → Z.ai rejects the whole request with HTTP 400 / code 1210
29
+ // "Invalid API parameter".
30
+ //
31
+ // We follow patterns seen in other mature clients (e.g. opencode) for
32
+ // robust GLM coding plan usage:
33
+ // - Conditional reasoning_content backfill (onlyIfMixed)
34
+ // - Force parallel_tool_calls: false (model still sometimes batches 2-5)
35
+ // - Drop null response_format (fragile with tools)
36
+ // - Clamp max_tokens, normalize tool-only assistant content shape
37
+ //
38
+ // See transformZaiThinkingBody for the full sanitization.
39
+ transformRequestBody: (body) => transformZaiThinkingBody(body),
40
+ });
41
+ return (modelId) => p(modelId);
42
+ }
43
+ }
44
+ //# sourceMappingURL=zai.strategy.js.map