muonroi-cli 1.8.4 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (562) hide show
  1. package/LICENSE +17 -5
  2. package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
  3. package/dist/packages/agent-harness-core/src/driver.js +46 -0
  4. package/dist/packages/agent-harness-core/src/event-filter.js +11 -0
  5. package/dist/packages/agent-harness-core/src/event-redact.js +7 -0
  6. package/dist/packages/agent-harness-core/src/event-tee.d.ts +64 -0
  7. package/dist/packages/agent-harness-core/src/event-tee.js +104 -0
  8. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +25 -0
  9. package/dist/packages/agent-harness-core/src/mcp-server.js +169 -21
  10. package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
  11. package/dist/packages/agent-harness-core/src/protocol.d.ts +90 -4
  12. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  13. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  14. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  15. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  16. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  17. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  18. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  19. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  20. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  21. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  22. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  23. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  24. package/dist/src/agent-harness/mock-model.d.ts +38 -0
  25. package/dist/src/agent-harness/mock-model.js +69 -3
  26. package/dist/src/agent-harness/test-spawn.js +31 -0
  27. package/dist/src/chat/chat-keychain.d.ts +7 -12
  28. package/dist/src/chat/chat-keychain.js +19 -86
  29. package/dist/src/cli/config/screen-providers.js +1 -1
  30. package/dist/src/cli/cost-forensics.d.ts +10 -0
  31. package/dist/src/cli/cost-forensics.js +18 -3
  32. package/dist/src/cli/keys-bundle.d.ts +1 -1
  33. package/dist/src/cli/keys-bundle.js +1 -1
  34. package/dist/src/cli/keys.d.ts +10 -47
  35. package/dist/src/cli/keys.js +31 -399
  36. package/dist/src/council/clarifier.d.ts +31 -3
  37. package/dist/src/council/clarifier.js +220 -32
  38. package/dist/src/council/context.js +49 -15
  39. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  40. package/dist/src/council/debate-checkpoint.js +176 -0
  41. package/dist/src/council/debate-planner.js +54 -5
  42. package/dist/src/council/debate-summary.d.ts +25 -0
  43. package/dist/src/council/debate-summary.js +85 -0
  44. package/dist/src/council/debate.d.ts +169 -2
  45. package/dist/src/council/debate.js +1265 -135
  46. package/dist/src/council/index.d.ts +108 -1
  47. package/dist/src/council/index.js +670 -197
  48. package/dist/src/council/leader.d.ts +26 -0
  49. package/dist/src/council/leader.js +150 -9
  50. package/dist/src/council/llm.d.ts +94 -0
  51. package/dist/src/council/llm.js +348 -55
  52. package/dist/src/council/panel-select.d.ts +30 -0
  53. package/dist/src/council/panel-select.js +82 -0
  54. package/dist/src/council/planner.js +40 -0
  55. package/dist/src/council/preflight.d.ts +17 -0
  56. package/dist/src/council/preflight.js +50 -2
  57. package/dist/src/council/prompts.d.ts +39 -4
  58. package/dist/src/council/prompts.js +256 -69
  59. package/dist/src/council/stance-recall.d.ts +42 -0
  60. package/dist/src/council/stance-recall.js +57 -0
  61. package/dist/src/council/strip-think.d.ts +17 -0
  62. package/dist/src/council/strip-think.js +33 -0
  63. package/dist/src/council/types.d.ts +138 -0
  64. package/dist/src/ee/artifact-cache.d.ts +16 -0
  65. package/dist/src/ee/artifact-cache.js +32 -0
  66. package/dist/src/ee/auth.d.ts +20 -0
  67. package/dist/src/ee/auth.js +54 -2
  68. package/dist/src/ee/bridge.d.ts +10 -0
  69. package/dist/src/ee/bridge.js +58 -0
  70. package/dist/src/ee/client.js +109 -21
  71. package/dist/src/ee/ee-onboarding.js +6 -26
  72. package/dist/src/ee/export-transcripts.d.ts +1 -0
  73. package/dist/src/ee/export-transcripts.js +8 -10
  74. package/dist/src/ee/extract-session.js +29 -0
  75. package/dist/src/ee/extract-style.d.ts +58 -0
  76. package/dist/src/ee/extract-style.js +270 -0
  77. package/dist/src/ee/recall-ledger.d.ts +9 -0
  78. package/dist/src/ee/recall-ledger.js +3 -0
  79. package/dist/src/ee/scope.d.ts +1 -0
  80. package/dist/src/ee/scope.js +26 -1
  81. package/dist/src/ee/search.d.ts +7 -0
  82. package/dist/src/ee/search.js +24 -0
  83. package/dist/src/ee/transcript-emit.js +2 -0
  84. package/dist/src/ee/types.d.ts +22 -0
  85. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  86. package/dist/src/ee/who-am-i-brain.js +220 -0
  87. package/dist/src/ee/who-am-i.d.ts +10 -3
  88. package/dist/src/ee/who-am-i.js +12 -0
  89. package/dist/src/ee/workflow-event.d.ts +48 -0
  90. package/dist/src/ee/workflow-event.js +81 -0
  91. package/dist/src/flow/compaction/compress.d.ts +3 -3
  92. package/dist/src/flow/compaction/compress.js +58 -8
  93. package/dist/src/flow/compaction/extract.d.ts +4 -7
  94. package/dist/src/flow/compaction/extract.js +50 -10
  95. package/dist/src/flow/compaction/index.d.ts +14 -1
  96. package/dist/src/flow/compaction/index.js +96 -3
  97. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  98. package/dist/src/flow/compaction/input-guard.js +43 -0
  99. package/dist/src/flow/compaction/progress.d.ts +35 -0
  100. package/dist/src/flow/compaction/progress.js +35 -0
  101. package/dist/src/flow/fold-planning.d.ts +36 -0
  102. package/dist/src/flow/fold-planning.js +83 -0
  103. package/dist/src/flow/hierarchy.d.ts +146 -0
  104. package/dist/src/flow/hierarchy.js +427 -0
  105. package/dist/src/flow/index.d.ts +1 -0
  106. package/dist/src/flow/index.js +2 -0
  107. package/dist/src/flow/run-artifacts.d.ts +102 -0
  108. package/dist/src/flow/run-artifacts.js +208 -0
  109. package/dist/src/generated/version.d.ts +1 -1
  110. package/dist/src/generated/version.js +1 -1
  111. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  112. package/dist/src/gsd/assessment-schema.js +134 -0
  113. package/dist/src/gsd/capability-registry.d.ts +45 -0
  114. package/dist/src/gsd/capability-registry.js +337 -0
  115. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  116. package/dist/src/gsd/complexity-assessor.js +152 -0
  117. package/dist/src/gsd/config-bridge.d.ts +7 -0
  118. package/dist/src/gsd/config-bridge.js +114 -0
  119. package/dist/src/gsd/config-loader.d.ts +27 -0
  120. package/dist/src/gsd/config-loader.js +50 -0
  121. package/dist/src/gsd/council-context.d.ts +44 -0
  122. package/dist/src/gsd/council-context.js +114 -0
  123. package/dist/src/gsd/ee-closure.d.ts +28 -0
  124. package/dist/src/gsd/ee-closure.js +49 -0
  125. package/dist/src/gsd/flags.d.ts +66 -0
  126. package/dist/src/gsd/flags.js +102 -0
  127. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  128. package/dist/src/gsd/gsd-dispatch.js +131 -0
  129. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  130. package/dist/src/gsd/gsd-runtime.js +37 -0
  131. package/dist/src/gsd/host-adapter.d.ts +11 -0
  132. package/dist/src/gsd/host-adapter.js +29 -0
  133. package/dist/src/gsd/index.d.ts +24 -1
  134. package/dist/src/gsd/index.js +27 -0
  135. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  136. package/dist/src/gsd/loop-host-contract.js +39 -0
  137. package/dist/src/gsd/loop-host.d.ts +69 -0
  138. package/dist/src/gsd/loop-host.js +245 -0
  139. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  140. package/dist/src/gsd/loop-resolver.js +79 -0
  141. package/dist/src/gsd/model-tier.d.ts +13 -0
  142. package/dist/src/gsd/model-tier.js +45 -0
  143. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  144. package/dist/src/gsd/mutation-gate.js +41 -0
  145. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  146. package/dist/src/gsd/native-roadmap.js +343 -0
  147. package/dist/src/gsd/native-state.d.ts +47 -0
  148. package/dist/src/gsd/native-state.js +220 -0
  149. package/dist/src/gsd/paths.d.ts +23 -0
  150. package/dist/src/gsd/paths.js +66 -0
  151. package/dist/src/gsd/phase-dag.d.ts +12 -0
  152. package/dist/src/gsd/phase-dag.js +94 -0
  153. package/dist/src/gsd/phase-sync.d.ts +42 -0
  154. package/dist/src/gsd/phase-sync.js +321 -0
  155. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  156. package/dist/src/gsd/pil-gate-context.js +64 -0
  157. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  158. package/dist/src/gsd/pil-gate-critic.js +74 -0
  159. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  160. package/dist/src/gsd/plan-council-prompts.js +79 -0
  161. package/dist/src/gsd/plan-council.d.ts +44 -0
  162. package/dist/src/gsd/plan-council.js +283 -0
  163. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  164. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  165. package/dist/src/gsd/product-workspace.d.ts +13 -0
  166. package/dist/src/gsd/product-workspace.js +124 -0
  167. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  168. package/dist/src/gsd/ship-bridge.js +65 -0
  169. package/dist/src/gsd/state-document.d.ts +40 -0
  170. package/dist/src/gsd/state-document.js +163 -0
  171. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  172. package/dist/src/gsd/verdict-schema.js +144 -0
  173. package/dist/src/gsd/verify-context.d.ts +22 -0
  174. package/dist/src/gsd/verify-context.js +27 -0
  175. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  176. package/dist/src/gsd/verify-council-prompts.js +85 -0
  177. package/dist/src/gsd/verify-council.d.ts +25 -0
  178. package/dist/src/gsd/verify-council.js +119 -0
  179. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  180. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  181. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  182. package/dist/src/gsd/workflow-engine.js +207 -0
  183. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  184. package/dist/src/gsd/workflow-tools.js +277 -0
  185. package/dist/src/headless/council-answers.js +4 -0
  186. package/dist/src/hooks/index.js +1 -1
  187. package/dist/src/index.js +172 -270
  188. package/dist/src/lsp/builtins.js +3 -1
  189. package/dist/src/lsp/manager.d.ts +5 -1
  190. package/dist/src/lsp/manager.js +249 -3
  191. package/dist/src/lsp/npm-cache.d.ts +11 -1
  192. package/dist/src/lsp/npm-cache.js +17 -1
  193. package/dist/src/lsp/runtime.d.ts +6 -1
  194. package/dist/src/lsp/runtime.js +17 -1
  195. package/dist/src/lsp/types.d.ts +83 -1
  196. package/dist/src/lsp/types.js +10 -0
  197. package/dist/src/maintain/pr-builder.js +23 -13
  198. package/dist/src/mcp/auto-setup.js +57 -32
  199. package/dist/src/mcp/client-pool.js +44 -16
  200. package/dist/src/mcp/lsp-tools.d.ts +5 -1
  201. package/dist/src/mcp/lsp-tools.js +93 -2
  202. package/dist/src/mcp/mcp-keychain.d.ts +3 -5
  203. package/dist/src/mcp/mcp-keychain.js +9 -49
  204. package/dist/src/mcp/research-onboarding.js +8 -7
  205. package/dist/src/mcp/runtime.js +34 -2
  206. package/dist/src/mcp/setup-guide-text.d.ts +1 -1
  207. package/dist/src/mcp/setup-guide-text.js +22 -2
  208. package/dist/src/mcp/tools-server.d.ts +10 -0
  209. package/dist/src/mcp/tools-server.js +10 -2
  210. package/dist/src/models/catalog-client.d.ts +87 -0
  211. package/dist/src/models/catalog-client.js +105 -38
  212. package/dist/src/models/catalog.json +528 -265
  213. package/dist/src/models/registry.d.ts +22 -7
  214. package/dist/src/models/registry.js +73 -10
  215. package/dist/src/ops/doctor.js +1 -1
  216. package/dist/src/orchestrator/ask-user.d.ts +61 -0
  217. package/dist/src/orchestrator/ask-user.js +65 -0
  218. package/dist/src/orchestrator/auto-commit.js +1 -1
  219. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  220. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  221. package/dist/src/orchestrator/cache-prefix.js +83 -0
  222. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  223. package/dist/src/orchestrator/compact-request.js +41 -0
  224. package/dist/src/orchestrator/compaction.d.ts +12 -3
  225. package/dist/src/orchestrator/compaction.js +35 -15
  226. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  227. package/dist/src/orchestrator/council-manager.js +74 -32
  228. package/dist/src/orchestrator/council-request.d.ts +49 -0
  229. package/dist/src/orchestrator/council-request.js +62 -0
  230. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  231. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  232. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  233. package/dist/src/orchestrator/error-utils.js +132 -24
  234. package/dist/src/orchestrator/grounding-check.js +39 -1
  235. package/dist/src/orchestrator/interactive-pause.d.ts +26 -0
  236. package/dist/src/orchestrator/interactive-pause.js +36 -0
  237. package/dist/src/orchestrator/message-processor.d.ts +4 -0
  238. package/dist/src/orchestrator/message-processor.js +268 -41
  239. package/dist/src/orchestrator/orchestrator.d.ts +64 -3
  240. package/dist/src/orchestrator/orchestrator.js +823 -120
  241. package/dist/src/orchestrator/preprocessor.js +3 -3
  242. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  243. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  244. package/dist/src/orchestrator/prompts.js +17 -17
  245. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  246. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  247. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  248. package/dist/src/orchestrator/retry-classifier.js +46 -2
  249. package/dist/src/orchestrator/safety-askcard.d.ts +1 -1
  250. package/dist/src/orchestrator/safety-askcard.js +5 -2
  251. package/dist/src/orchestrator/safety-intercept.d.ts +50 -0
  252. package/dist/src/orchestrator/safety-intercept.js +62 -0
  253. package/dist/src/orchestrator/scope-reminder.js +1 -1
  254. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  255. package/dist/src/orchestrator/session-experience.js +2 -1
  256. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  257. package/dist/src/orchestrator/should-run-gate.js +18 -0
  258. package/dist/src/orchestrator/stall-watchdog.d.ts +31 -3
  259. package/dist/src/orchestrator/stall-watchdog.js +65 -10
  260. package/dist/src/orchestrator/stream-runner.d.ts +13 -3
  261. package/dist/src/orchestrator/stream-runner.js +115 -49
  262. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  263. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  264. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  265. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  266. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  267. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  268. package/dist/src/orchestrator/tool-engine.d.ts +41 -0
  269. package/dist/src/orchestrator/tool-engine.js +846 -66
  270. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  271. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  272. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  273. package/dist/src/orchestrator/turn-watchdog.d.ts +44 -0
  274. package/dist/src/orchestrator/turn-watchdog.js +84 -0
  275. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  276. package/dist/src/pil/agent-operating-contract.js +6 -4
  277. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  278. package/dist/src/pil/cheap-model-playbook.js +5 -1
  279. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  280. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  281. package/dist/src/pil/discovery-types.d.ts +1 -0
  282. package/dist/src/pil/discovery.d.ts +1 -1
  283. package/dist/src/pil/discovery.js +18 -13
  284. package/dist/src/pil/layer1-intent.d.ts +18 -6
  285. package/dist/src/pil/layer1-intent.js +66 -757
  286. package/dist/src/pil/layer15-context-scan.js +15 -1
  287. package/dist/src/pil/layer1_5-complexity-size.d.ts +7 -0
  288. package/dist/src/pil/layer1_5-complexity-size.js +31 -5
  289. package/dist/src/pil/layer3-ee-injection.js +23 -8
  290. package/dist/src/pil/layer4-gsd.js +69 -16
  291. package/dist/src/pil/layer5-context.js +7 -3
  292. package/dist/src/pil/layer6-output.d.ts +23 -0
  293. package/dist/src/pil/layer6-output.js +5 -1
  294. package/dist/src/pil/llm-classify.d.ts +111 -5
  295. package/dist/src/pil/llm-classify.js +421 -189
  296. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  297. package/dist/src/pil/native-capabilities-workbook.js +8 -0
  298. package/dist/src/pil/pipeline.js +36 -2
  299. package/dist/src/pil/repo-grounding-probe.d.ts +15 -0
  300. package/dist/src/pil/repo-grounding-probe.js +136 -0
  301. package/dist/src/pil/repo-structure-hints.d.ts +7 -0
  302. package/dist/src/pil/repo-structure-hints.js +45 -0
  303. package/dist/src/pil/response-tools.js +5 -3
  304. package/dist/src/pil/schema.d.ts +1 -0
  305. package/dist/src/pil/schema.js +2 -0
  306. package/dist/src/pil/types.d.ts +18 -0
  307. package/dist/src/playbook/directives.d.ts +4 -0
  308. package/dist/src/playbook/directives.js +17 -5
  309. package/dist/src/product-loop/artifact-io.js +4 -0
  310. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  311. package/dist/src/product-loop/backlog-builder.js +30 -6
  312. package/dist/src/product-loop/criteria-seed.d.ts +51 -0
  313. package/dist/src/product-loop/criteria-seed.js +200 -0
  314. package/dist/src/product-loop/discovery-context-format.js +3 -1
  315. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  316. package/dist/src/product-loop/discovery-interview.d.ts +9 -0
  317. package/dist/src/product-loop/discovery-interview.js +60 -12
  318. package/dist/src/product-loop/discovery-recommender.js +2 -1
  319. package/dist/src/product-loop/discovery-schema.js +19 -2
  320. package/dist/src/product-loop/discovery-triage.d.ts +23 -0
  321. package/dist/src/product-loop/discovery-triage.js +109 -0
  322. package/dist/src/product-loop/gather.js +150 -2
  323. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  324. package/dist/src/product-loop/ideal-trace.js +64 -0
  325. package/dist/src/product-loop/index.d.ts +13 -1
  326. package/dist/src/product-loop/index.js +340 -52
  327. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  328. package/dist/src/product-loop/loop-driver.js +330 -106
  329. package/dist/src/product-loop/phase-plan.d.ts +21 -0
  330. package/dist/src/product-loop/phase-plan.js +81 -6
  331. package/dist/src/product-loop/phase-rituals.d.ts +3 -0
  332. package/dist/src/product-loop/phase-rituals.js +8 -3
  333. package/dist/src/product-loop/phase-runner.js +39 -12
  334. package/dist/src/product-loop/plan-adherence-review.d.ts +26 -0
  335. package/dist/src/product-loop/plan-adherence-review.js +144 -0
  336. package/dist/src/product-loop/sprint-runner.d.ts +173 -0
  337. package/dist/src/product-loop/sprint-runner.js +863 -19
  338. package/dist/src/product-loop/types.d.ts +61 -5
  339. package/dist/src/providers/adapter.d.ts +1 -1
  340. package/dist/src/providers/adapter.js +3 -4
  341. package/dist/src/providers/anthropic.d.ts +9 -8
  342. package/dist/src/providers/anthropic.js +13 -47
  343. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  344. package/dist/src/providers/auth/browser-flow.js +1 -1
  345. package/dist/src/providers/auth/grok-oauth.d.ts +1 -0
  346. package/dist/src/providers/auth/grok-oauth.js +30 -5
  347. package/dist/src/providers/auth/openai-oauth.d.ts +1 -0
  348. package/dist/src/providers/auth/openai-oauth.js +15 -1
  349. package/dist/src/providers/auth/registry.js +0 -34
  350. package/dist/src/providers/auth/token-store.d.ts +9 -9
  351. package/dist/src/providers/auth/token-store.js +8 -67
  352. package/dist/src/providers/auth/types.d.ts +9 -1
  353. package/dist/src/providers/auth/types.js +1 -1
  354. package/dist/src/providers/capabilities.d.ts +24 -5
  355. package/dist/src/providers/capabilities.js +42 -24
  356. package/dist/src/providers/endpoints.d.ts +2 -2
  357. package/dist/src/providers/endpoints.js +11 -10
  358. package/dist/src/providers/env-store.d.ts +17 -0
  359. package/dist/src/providers/env-store.js +228 -0
  360. package/dist/src/providers/keychain.d.ts +22 -18
  361. package/dist/src/providers/keychain.js +127 -140
  362. package/dist/src/providers/mcp-vision-bridge.js +56 -146
  363. package/dist/src/providers/openai-compatible.js +8 -1
  364. package/dist/src/providers/pricing.d.ts +2 -2
  365. package/dist/src/providers/pricing.js +3 -13
  366. package/dist/src/providers/runtime.d.ts +43 -3
  367. package/dist/src/providers/runtime.js +88 -14
  368. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  369. package/dist/src/providers/strategies/base.strategy.js +24 -1
  370. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  371. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  372. package/dist/src/providers/strategies/registry.js +4 -4
  373. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  374. package/dist/src/providers/strategies/thinking-mode.js +288 -1
  375. package/dist/src/providers/strategies/xai.strategy.js +27 -0
  376. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  377. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  378. package/dist/src/providers/types.d.ts +5 -6
  379. package/dist/src/providers/types.js +2 -2
  380. package/dist/src/providers/vision-backend.d.ts +47 -0
  381. package/dist/src/providers/vision-backend.js +258 -0
  382. package/dist/src/providers/vision-proxy.d.ts +22 -9
  383. package/dist/src/providers/vision-proxy.js +63 -132
  384. package/dist/src/providers/warm.d.ts +65 -0
  385. package/dist/src/providers/warm.js +145 -0
  386. package/dist/src/providers/wire-debug.js +95 -0
  387. package/dist/src/router/decide.d.ts +13 -0
  388. package/dist/src/router/decide.js +138 -36
  389. package/dist/src/router/peak-hour.d.ts +38 -0
  390. package/dist/src/router/peak-hour.js +107 -0
  391. package/dist/src/router/step-router.js +3 -2
  392. package/dist/src/router/warm.js +4 -5
  393. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  394. package/dist/src/scaffold/continuation-prompt.js +26 -0
  395. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  396. package/dist/src/scaffold/point-to-existing.js +25 -0
  397. package/dist/src/self-qa/agentic-loop.js +6 -5
  398. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  399. package/dist/src/{ui/state → state}/active-run.js +21 -0
  400. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  401. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  402. package/dist/src/state/turn-trace.d.ts +43 -0
  403. package/dist/src/state/turn-trace.js +32 -0
  404. package/dist/src/storage/db.js +2 -1
  405. package/dist/src/storage/index.d.ts +1 -1
  406. package/dist/src/storage/index.js +1 -1
  407. package/dist/src/storage/interaction-log.d.ts +1 -1
  408. package/dist/src/storage/migrations.js +71 -1
  409. package/dist/src/storage/sessions.d.ts +28 -10
  410. package/dist/src/storage/sessions.js +78 -21
  411. package/dist/src/storage/transcript-view.js +1 -1
  412. package/dist/src/storage/transcript.d.ts +51 -0
  413. package/dist/src/storage/transcript.js +340 -15
  414. package/dist/src/tools/file.d.ts +15 -0
  415. package/dist/src/tools/file.js +32 -0
  416. package/dist/src/tools/git-safety.d.ts +19 -0
  417. package/dist/src/tools/git-safety.js +168 -0
  418. package/dist/src/tools/native-tools.d.ts +1 -1
  419. package/dist/src/tools/native-tools.js +81 -1
  420. package/dist/src/tools/registry.d.ts +20 -0
  421. package/dist/src/tools/registry.js +576 -23
  422. package/dist/src/tools/research.d.ts +29 -0
  423. package/dist/src/tools/research.js +233 -0
  424. package/dist/src/types/index.d.ts +147 -4
  425. package/dist/src/ui/app.js +0 -0
  426. package/dist/src/ui/cards/product-status-card.js +1 -1
  427. package/dist/src/ui/components/agent-rail-activities.d.ts +26 -0
  428. package/dist/src/ui/components/agent-rail-activities.js +47 -0
  429. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  430. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  431. package/dist/src/ui/components/compact-progress-card.d.ts +24 -0
  432. package/dist/src/ui/components/compact-progress-card.js +42 -0
  433. package/dist/src/ui/components/context-rail.d.ts +26 -0
  434. package/dist/src/ui/components/context-rail.js +33 -0
  435. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  436. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  437. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  438. package/dist/src/ui/components/council-debate-pill.js +34 -0
  439. package/dist/src/ui/components/council-info-card.js +2 -2
  440. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  441. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  442. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  443. package/dist/src/ui/components/council-message-bubble.js +16 -15
  444. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  445. package/dist/src/ui/components/council-phase-timeline.js +66 -17
  446. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  447. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  448. package/dist/src/ui/components/council-question-card.js +13 -12
  449. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  450. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  451. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  452. package/dist/src/ui/components/council-round-group.js +88 -0
  453. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  454. package/dist/src/ui/components/council-status-list.js +36 -24
  455. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  456. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  457. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  458. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  459. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  460. package/dist/src/ui/components/message-view.d.ts +15 -0
  461. package/dist/src/ui/components/message-view.js +50 -1
  462. package/dist/src/ui/components/prompt-box.js +18 -16
  463. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  464. package/dist/src/ui/components/session-tree-card.js +46 -0
  465. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  466. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  467. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  468. package/dist/src/ui/components/task-list-panel.js +22 -2
  469. package/dist/src/ui/components/tool-group.d.ts +15 -3
  470. package/dist/src/ui/components/tool-group.js +69 -11
  471. package/dist/src/ui/containers/modals-layer.d.ts +4 -2
  472. package/dist/src/ui/containers/modals-layer.js +2 -2
  473. package/dist/src/ui/council-harness-event.d.ts +57 -0
  474. package/dist/src/ui/council-harness-event.js +46 -0
  475. package/dist/src/ui/heartbeat-debug.d.ts +29 -0
  476. package/dist/src/ui/heartbeat-debug.js +45 -0
  477. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  478. package/dist/src/ui/mcp-modal.js +2 -4
  479. package/dist/src/ui/modals/api-key-modal.js +1 -1
  480. package/dist/src/ui/modals/connect-modal.js +4 -3
  481. package/dist/src/ui/modals/model-picker-modal.d.ts +8 -18
  482. package/dist/src/ui/modals/model-picker-modal.js +8 -10
  483. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  484. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  485. package/dist/src/ui/picker-providers.d.ts +1 -1
  486. package/dist/src/ui/picker-providers.js +1 -1
  487. package/dist/src/ui/primitives/index.d.ts +1 -0
  488. package/dist/src/ui/primitives/index.js +2 -0
  489. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  490. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  491. package/dist/src/ui/slash/compact.js +5 -7
  492. package/dist/src/ui/slash/cost.js +1 -1
  493. package/dist/src/ui/slash/council.js +19 -1
  494. package/dist/src/ui/slash/debug.d.ts +3 -31
  495. package/dist/src/ui/slash/debug.js +9 -20
  496. package/dist/src/ui/slash/ee.js +81 -0
  497. package/dist/src/ui/slash/ideal.d.ts +6 -2
  498. package/dist/src/ui/slash/ideal.js +97 -7
  499. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  500. package/dist/src/ui/slash/menu-items.js +23 -20
  501. package/dist/src/ui/slash/registry.d.ts +2 -0
  502. package/dist/src/ui/slash/registry.js +4 -0
  503. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  504. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  505. package/dist/src/ui/status-bar/index.d.ts +1 -1
  506. package/dist/src/ui/status-bar/index.js +7 -3
  507. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  508. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  509. package/dist/src/ui/theme.d.ts +1 -0
  510. package/dist/src/ui/theme.js +2 -0
  511. package/dist/src/ui/types.d.ts +7 -0
  512. package/dist/src/ui/use-app-logic.js +0 -0
  513. package/dist/src/ui/utils/agent-activities.d.ts +39 -0
  514. package/dist/src/ui/utils/agent-activities.js +96 -0
  515. package/dist/src/ui/utils/format.d.ts +14 -0
  516. package/dist/src/ui/utils/format.js +23 -3
  517. package/dist/src/ui/utils/group-tool-entries.d.ts +26 -0
  518. package/dist/src/ui/utils/group-tool-entries.js +111 -0
  519. package/dist/src/ui/utils/tool-summary.d.ts +21 -0
  520. package/dist/src/ui/utils/tool-summary.js +91 -0
  521. package/dist/src/usage/downgrade.js +2 -2
  522. package/dist/src/usage/product-ledger.js +2 -2
  523. package/dist/src/utils/event-loop-monitor.d.ts +85 -0
  524. package/dist/src/utils/event-loop-monitor.js +107 -0
  525. package/dist/src/utils/install-manager.js +2 -1
  526. package/dist/src/utils/llm-deadline.d.ts +14 -0
  527. package/dist/src/utils/llm-deadline.js +19 -0
  528. package/dist/src/utils/logger.js +2 -2
  529. package/dist/src/utils/loop-profiler.d.ts +102 -0
  530. package/dist/src/utils/loop-profiler.js +202 -0
  531. package/dist/src/utils/permission-mode.js +5 -3
  532. package/dist/src/utils/redactor.js +1 -1
  533. package/dist/src/utils/settings.d.ts +180 -5
  534. package/dist/src/utils/settings.js +271 -31
  535. package/dist/src/utils/side-question.d.ts +1 -2
  536. package/dist/src/utils/side-question.js +2 -2
  537. package/dist/src/utils/visible-retry.d.ts +11 -0
  538. package/dist/src/utils/visible-retry.js +10 -1
  539. package/dist/src/verify/entrypoint.d.ts +1 -1
  540. package/dist/src/verify/entrypoint.js +52 -17
  541. package/dist/src/verify/orchestrator.d.ts +1 -1
  542. package/dist/src/verify/orchestrator.js +20 -3
  543. package/dist/src/verify/recipes.d.ts +13 -0
  544. package/dist/src/verify/recipes.js +15 -0
  545. package/package.json +134 -132
  546. package/dist/src/cli/bw-vault.d.ts +0 -55
  547. package/dist/src/cli/bw-vault.js +0 -133
  548. package/dist/src/mcp/ee-tools.d.ts +0 -46
  549. package/dist/src/mcp/ee-tools.js +0 -193
  550. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  551. package/dist/src/providers/auth/gcloud.js +0 -102
  552. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  553. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  554. package/dist/src/providers/gemini.d.ts +0 -11
  555. package/dist/src/providers/gemini.js +0 -45
  556. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  557. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  558. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  559. package/dist/src/providers/strategies/google.strategy.js +0 -174
  560. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  561. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  562. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -32,6 +32,10 @@ export interface IterationState {
32
32
  criteriaMet: number;
33
33
  criteriaPartial: number;
34
34
  criteriaUnmet: number;
35
+ /** Total criteria evaluated this sprint. Optional for back-compat with older
36
+ * persisted iterations; when present it fixes the phase-runner exit ratio + the
37
+ * sprint-review "met X/Y" count that previously read undefined. */
38
+ totalCriteria?: number;
35
39
  costUsd: number;
36
40
  lastVerifyResult: string;
37
41
  /** Alias of costUsd kept for circuit-breaker history adapters (CB-1 reads actualCost). */
@@ -40,6 +44,16 @@ export interface IterationState {
40
44
  score?: number;
41
45
  crashed?: boolean;
42
46
  retryOf?: number;
47
+ /**
48
+ * Carry-over focus for the NEXT sprint when this one did not satisfy the
49
+ * done-gate: the failed-condition focus (feedback-routing) plus any plan
50
+ * deviations that survived the adherence review. The phase-runner adapter
51
+ * threads this into the next sprint's `carryOver` so each iteration continues
52
+ * the specific unmet / risky parts instead of restarting blind — the mechanism
53
+ * behind "spawn to continue the risk parts → finished product after N sprints".
54
+ * Absent when the sprint passed.
55
+ */
56
+ nextFocus?: string;
43
57
  }
44
58
  export interface DoneVerdict {
45
59
  pass: boolean;
@@ -128,6 +142,18 @@ export interface DriverContext {
128
142
  * without it; sprint-runner enforces presence at call time.
129
143
  */
130
144
  processMessageFn?: (message: string) => AsyncGenerator<import("../types/index.js").StreamChunk, void, unknown>;
145
+ /**
146
+ * Bridge into the orchestrator's ISOLATED task-runner (Agent.runTaskRequest →
147
+ * StreamRunner). Unlike processMessageFn — which appends to the shared
148
+ * top-level context and therefore inherits the (large) council-debate history —
149
+ * each call here runs in a FRESH, budget-capped (getSubAgentBudgetChars) child
150
+ * context with independent in-loop compaction, and returns a compact ToolResult
151
+ * summary instead of streaming into the parent. Sprint-runner uses this for the
152
+ * implement stage so the impl never inherits the debate context (which caused a
153
+ * live ctx-overflow wedge). Optional: legacy/test drivers omit it → sprint-runner
154
+ * falls back to processMessageFn.
155
+ */
156
+ runIsolatedTask?: (request: import("../types/index.js").TaskRequest) => Promise<import("../types/index.js").ToolResult>;
131
157
  /**
132
158
  * Optional bridge for verify-recipe detection. Mirrors `Orchestrator.detectVerifyRecipe`.
133
159
  * If absent, sprint-runner uses a deterministic fallback based on the inferVerifyProjectProfile
@@ -185,7 +211,7 @@ export type ProductTypeT = "saas" | "internal-tool" | "consumer-app" | "b2b-plat
185
211
  export type PlatformT = "web" | "mobile-ios" | "mobile-android" | "desktop-win" | "desktop-mac" | "desktop-linux" | "cli";
186
212
  export type ScaleT = "1-100" | "100-1k" | "1k-100k" | "100k-1M" | "1M+";
187
213
  export type BackendArchT = "monolith" | "modular-monolith" | "microservices" | "serverless" | "none";
188
- export type DbModeT = "greenfield" | "existing-schema" | "migrate-from";
214
+ export type DbModeT = "none" | "greenfield" | "existing-schema" | "migrate-from";
189
215
  export type FeLibraryT = "shadcn" | "radix" | "headlessui" | "none";
190
216
  export interface AudienceCtx {
191
217
  persona: string;
@@ -266,6 +292,17 @@ export interface ProjectContext {
266
292
  idea: string;
267
293
  detection: ExistingProjectSignals;
268
294
  context: DiscoveryContext;
295
+ /**
296
+ * Agent-driven interview output. When the gather phase runs the unified
297
+ * clarifier (the same LLM-generates-its-own-questions engine `/council`
298
+ * uses — see runGatherPhase), it produces a rich `ClarifiedSpec` directly
299
+ * instead of the fixed-question `DiscoveryContext`. Stashed here (plain data,
300
+ * JSON round-trips through project-context.md) so `clarifiedSpecFromContext`
301
+ * can return the real LLM-synthesized successCriteria/constraints/scope
302
+ * verbatim rather than re-deriving a thin 2-item spec from persona+scale.
303
+ * Absent on the legacy fixed-question path (MUONROI_IDEAL_AGENT_INTERVIEW=0).
304
+ */
305
+ clarified?: import("../council/types.js").ClarifiedSpec;
269
306
  recommendations: {
270
307
  byField: Record<string, RecommendationEntry>;
271
308
  constraints: {
@@ -353,8 +390,12 @@ export interface PhaseDigestEntry {
353
390
  * The UI (Task 5.2) wires each id to a concrete handler.
354
391
  */
355
392
  export interface RecoveryOption {
356
- /** Stable key. Used by the UI to wire actions. */
357
- id: "init_new" | "point_to_existing" | "continue_as_council";
393
+ /**
394
+ * Stable key. Used by the UI to wire actions.
395
+ * - CB-3 halt (no recipe): init_new | point_to_existing | continue_as_council
396
+ * - Sprint break (A): resume | retry | skip_verify | abort
397
+ */
398
+ id: "init_new" | "point_to_existing" | "continue_as_council" | "resume" | "retry" | "skip_verify" | "abort";
358
399
  /** Label shown in the recovery card. */
359
400
  label: string;
360
401
  /** One-line user-facing description of what choosing this does. */
@@ -367,10 +408,22 @@ export interface RecoveryOption {
367
408
  */
368
409
  export interface HaltChunk {
369
410
  type: "halt";
370
- /** CB-3 emits "no_recipe" / "zero_coverage"; product-loop emits "budget_exhausted" when --budget-tokens trips. */
371
- reason: "no_recipe" | "zero_coverage" | "budget_exhausted";
411
+ /**
412
+ * CB-3 emits "no_recipe" / "zero_coverage"; product-loop emits
413
+ * "budget_exhausted" when --budget-tokens trips; "sprint_failed" (A) when a
414
+ * sprint breaks mid-run (thrown implement/verify error, cap breach, etc.).
415
+ */
416
+ reason: "no_recipe" | "zero_coverage" | "budget_exhausted" | "sprint_failed";
372
417
  /** Optional human-readable detail rendered alongside the recovery card. */
373
418
  detail?: string;
419
+ /**
420
+ * A — the run this halt belongs to. Lets the recovery card auto-wire
421
+ * Resume/Retry/Abort to `/ideal <action> <runId>` without the user knowing
422
+ * (or typing) the runId. Set on "sprint_failed" halts.
423
+ */
424
+ runId?: string;
425
+ /** A — the sprint number that broke, for the "Sprint N failed" card title. */
426
+ sprintN?: number;
374
427
  /** Actionable choices. UI renders these as buttons / list items. */
375
428
  recovery_options: RecoveryOption[];
376
429
  }
@@ -393,6 +446,9 @@ export interface RunPhasesOptions {
393
446
  }) => Promise<Omit<CustomerDecision, "seq" | "timestampUtc" | "phaseId" | "sprintN">>;
394
447
  suppressPush?: boolean;
395
448
  backoffDelays?: number[];
449
+ /** Project repo cwd — hosts `.planning/` when MUONROI_GSD_NATIVE=1 */
450
+ projectCwd?: string;
451
+ idea?: string;
396
452
  }
397
453
  export type BacklogItemStatus = "backlog" | "in_sprint" | "in_progress" | "done" | "blocked";
398
454
  export type MvpPriority = "v1" | "v2" | "later";
@@ -45,7 +45,7 @@ export declare function createAdapter(id: ProviderId, config: ProviderConfig): A
45
45
  * Dispatch is registry-driven — no `if (id === "openai")` branching. To add
46
46
  * OAuth for a new provider (Anthropic, etc.):
47
47
  * 1. Register the provider in `providers/auth/registry.ts`.
48
- * 2. Ensure its adapter honors `config.oauthHeaders` (see openai.ts/anthropic.ts/gemini.ts).
48
+ * 2. Ensure its adapter honors `config.oauthHeaders` (see openai.ts/anthropic.ts).
49
49
  *
50
50
  * Behavior per provider:
51
51
  * - OAuth tokens present (auto-refreshed) → adapter built with Bearer headers,
@@ -32,7 +32,6 @@
32
32
  import { createAnthropicAdapter } from "./anthropic.js";
33
33
  import { getOAuthProviderConfig } from "./auth/registry.js";
34
34
  import { apiBaseFor } from "./endpoints.js";
35
- import { createGeminiAdapter } from "./gemini.js";
36
35
  import { createOllamaAdapter } from "./ollama.js";
37
36
  import { createOpenAIAdapter } from "./openai.js";
38
37
  import { createOpenAICompatibleAdapter } from "./openai-compatible.js";
@@ -55,11 +54,11 @@ const ADAPTER_FACTORIES = {
55
54
  anthropic: (config) => createAnthropicAdapter(config),
56
55
  // Synchronous path: API-key only (no OAuth auto-load). Use createAdapterAsync for OAuth.
57
56
  openai: (config) => createOpenAIAdapter(config),
58
- google: (config) => createGeminiAdapter(config),
59
57
  deepseek: (config) => createOpenAICompatibleAdapter({ ...config, id: "deepseek" }),
60
- siliconflow: (config) => createOpenAICompatibleAdapter({ ...config, id: "siliconflow" }),
61
58
  xai: (config) => createOpenAICompatibleAdapter({ ...config, id: "xai", baseURL: config.baseURL ?? apiBaseFor("xai") }),
62
59
  ollama: (config) => createOllamaAdapter(config),
60
+ zai: (config) => createOpenAICompatibleAdapter({ ...config, id: "zai", baseURL: config.baseURL ?? apiBaseFor("zai") }),
61
+ "opencode-go": (config) => createOpenAICompatibleAdapter({ ...config, id: "opencode-go" }),
63
62
  };
64
63
  /**
65
64
  * Create an Adapter for the given provider.
@@ -86,7 +85,7 @@ export function createAdapter(id, config) {
86
85
  * Dispatch is registry-driven — no `if (id === "openai")` branching. To add
87
86
  * OAuth for a new provider (Anthropic, etc.):
88
87
  * 1. Register the provider in `providers/auth/registry.ts`.
89
- * 2. Ensure its adapter honors `config.oauthHeaders` (see openai.ts/anthropic.ts/gemini.ts).
88
+ * 2. Ensure its adapter honors `config.oauthHeaders` (see openai.ts/anthropic.ts).
90
89
  *
91
90
  * Behavior per provider:
92
91
  * - OAuth tokens present (auto-refreshed) → adapter built with Bearer headers,
@@ -2,16 +2,15 @@
2
2
  * src/providers/anthropic.ts
3
3
  *
4
4
  * Anthropic-only provider shell for Phase 0.
5
- * Implements TUI-02 (stub conversation), PROV-03 (BYOK keychain), PROV-07 (log redaction).
5
+ * Implements TUI-02 (stub conversation), PROV-03 (BYOK), PROV-07 (log redaction).
6
6
  *
7
- * Key loading priority:
8
- * 1. OS keychain via keytar (service="muonroi-cli", account="anthropic") — B-2: dynamic import
9
- * 2. ANTHROPIC_API_KEY env var fallback with redacted warning
10
- * 3. AnthropicKeyMissingError — user-facing error with remediation instructions
7
+ * Key loading:
8
+ * 1. ANTHROPIC_API_KEY env var (the env-store loads ~/.muonroi-cli/.env into
9
+ * process.env at startup; the real OS env also applies)
10
+ * 2. AnthropicKeyMissingError — user-facing error with remediation instructions
11
11
  *
12
12
  * Security invariants:
13
13
  * - redactor.enrollSecret(key) is called BEFORE any log line that might contain the key.
14
- * - keytar is loaded via dynamic import() so a missing/broken native module cannot crash boot.
15
14
  * - Keys shorter than 20 characters are rejected early.
16
15
  *
17
16
  * Streaming (AI SDK v6 with @ai-sdk/anthropic):
@@ -32,13 +31,15 @@ export declare class AnthropicKeyMissingError extends Error {
32
31
  constructor();
33
32
  }
34
33
  /**
35
- * Load the Anthropic API key from the OS keychain first, then env var fallback.
34
+ * Load the Anthropic API key from the environment (the env-store loads
35
+ * `~/.muonroi-cli/.env` into process.env at startup; the real OS env also
36
+ * applies).
36
37
  *
37
38
  * Security contract:
38
39
  * - redactor.enrollSecret(key) is called BEFORE any subsequent log line.
39
40
  * - Keys < 20 chars are rejected (T-00.05-05: truncated key guard).
40
41
  *
41
- * @throws {AnthropicKeyMissingError} when both keychain and env var are absent.
42
+ * @throws {AnthropicKeyMissingError} when no ANTHROPIC_API_KEY is present.
42
43
  */
43
44
  export declare function loadAnthropicKey(): Promise<string>;
44
45
  /**
@@ -2,16 +2,15 @@
2
2
  * src/providers/anthropic.ts
3
3
  *
4
4
  * Anthropic-only provider shell for Phase 0.
5
- * Implements TUI-02 (stub conversation), PROV-03 (BYOK keychain), PROV-07 (log redaction).
5
+ * Implements TUI-02 (stub conversation), PROV-03 (BYOK), PROV-07 (log redaction).
6
6
  *
7
- * Key loading priority:
8
- * 1. OS keychain via keytar (service="muonroi-cli", account="anthropic") — B-2: dynamic import
9
- * 2. ANTHROPIC_API_KEY env var fallback with redacted warning
10
- * 3. AnthropicKeyMissingError — user-facing error with remediation instructions
7
+ * Key loading:
8
+ * 1. ANTHROPIC_API_KEY env var (the env-store loads ~/.muonroi-cli/.env into
9
+ * process.env at startup; the real OS env also applies)
10
+ * 2. AnthropicKeyMissingError — user-facing error with remediation instructions
11
11
  *
12
12
  * Security invariants:
13
13
  * - redactor.enrollSecret(key) is called BEFORE any log line that might contain the key.
14
- * - keytar is loaded via dynamic import() so a missing/broken native module cannot crash boot.
15
14
  * - Keys shorter than 20 characters are rejected early.
16
15
  *
17
16
  * Streaming (AI SDK v6 with @ai-sdk/anthropic):
@@ -43,58 +42,25 @@ export class AnthropicKeyMissingError extends Error {
43
42
  this.name = "AnthropicKeyMissingError";
44
43
  }
45
44
  }
45
+ // ---------------------------------------------------------------------------
46
+ // Key loader
47
+ // ---------------------------------------------------------------------------
46
48
  /**
47
- * Dynamic keytar loader B-2 mitigation.
48
- * A missing or broken keytar native module (common on minimal Linux environments)
49
- * must NOT crash process boot. The env-var fallback path is always available.
50
- */
51
- async function loadKeytar() {
52
- try {
53
- // keytar exports named functions directly (no default export)
54
- const mod = await import("keytar");
55
- return mod;
56
- }
57
- catch {
58
- return null;
59
- }
60
- }
61
- /**
62
- * Load the Anthropic API key from the OS keychain first, then env var fallback.
49
+ * Load the Anthropic API key from the environment (the env-store loads
50
+ * `~/.muonroi-cli/.env` into process.env at startup; the real OS env also
51
+ * applies).
63
52
  *
64
53
  * Security contract:
65
54
  * - redactor.enrollSecret(key) is called BEFORE any subsequent log line.
66
55
  * - Keys < 20 chars are rejected (T-00.05-05: truncated key guard).
67
56
  *
68
- * @throws {AnthropicKeyMissingError} when both keychain and env var are absent.
57
+ * @throws {AnthropicKeyMissingError} when no ANTHROPIC_API_KEY is present.
69
58
  */
70
59
  export async function loadAnthropicKey() {
71
- // --- Primary: OS keychain via dynamic import (B-2) ---
72
- const keytarMod = await loadKeytar();
73
- if (keytarMod) {
74
- try {
75
- const key = await keytarMod.getPassword("muonroi-cli", "anthropic");
76
- if (key && key.length >= 20) {
77
- // Enroll BEFORE any log that might emit the key
78
- redactor.enrollSecret(key);
79
- return key;
80
- }
81
- }
82
- catch (err) {
83
- // keytar present but backend unavailable (e.g. Linux without libsecret/dbus)
84
- console.warn("[muonroi-cli] keytar backend unavailable, falling back to env var:", redactor.redactError(err));
85
- }
86
- }
87
- else {
88
- console.warn("[muonroi-cli] keytar module not installed — using env-var path. " +
89
- "Install keytar to enable OS keychain key storage.");
90
- }
91
- // --- Fallback: ANTHROPIC_API_KEY environment variable ---
92
60
  const envKey = process.env.ANTHROPIC_API_KEY;
93
61
  if (envKey && envKey.length >= 20) {
94
- // Enroll BEFORE the warning that mentions we're using env path
62
+ // Enroll BEFORE any log that might mention the key path.
95
63
  redactor.enrollSecret(envKey);
96
- console.warn("[muonroi-cli] Using ANTHROPIC_API_KEY from environment. " +
97
- "Prefer storing the key in your OS keychain (Phase 1 `muonroi-cli login` helper).");
98
64
  return envKey;
99
65
  }
100
66
  throw new AnthropicKeyMissingError();
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Generic helpers for Authorization Code + PKCE browser-redirect OAuth flows.
5
5
  * Usable for any provider that supports the standard OAuth 2.0 browser-redirect
6
- * grant (e.g. Google Gemini). Not for device-code flows (see device-flow.ts).
6
+ * grant. Not for device-code flows (see device-flow.ts).
7
7
  *
8
8
  * Re-exports generatePKCE from device-flow.ts so callers need only one import.
9
9
  */
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Generic helpers for Authorization Code + PKCE browser-redirect OAuth flows.
5
5
  * Usable for any provider that supports the standard OAuth 2.0 browser-redirect
6
- * grant (e.g. Google Gemini). Not for device-code flows (see device-flow.ts).
6
+ * grant. Not for device-code flows (see device-flow.ts).
7
7
  *
8
8
  * Re-exports generatePKCE from device-flow.ts so callers need only one import.
9
9
  */
@@ -49,6 +49,7 @@ export declare class GrokOAuthProvider implements ProviderOAuth {
49
49
  });
50
50
  login(opts?: {
51
51
  onUserCode?: (code: string, url: string) => void;
52
+ signal?: AbortSignal;
52
53
  }): Promise<OAuthTokens>;
53
54
  refresh(tokens: OAuthTokens): Promise<OAuthTokens>;
54
55
  revoke(tokens: OAuthTokens): Promise<void>;
@@ -114,6 +114,7 @@ export class GrokOAuthProvider {
114
114
  const state = randomBytes(16).toString("base64url");
115
115
  const nonce = randomBytes(16).toString("base64url");
116
116
  let callbackServer;
117
+ let manualPasteRl;
117
118
  let authCode;
118
119
  let receivedState = "";
119
120
  try {
@@ -125,6 +126,19 @@ export class GrokOAuthProvider {
125
126
  const loginTimeout = setTimeout(() => {
126
127
  reject(new Error("OAuth browser callback timed out"));
127
128
  }, CALLBACK_TIMEOUT_MS);
129
+ // Cancelling must END the flow, not just abandon it: the `finally`
130
+ // below is what closes the loopback server (and the readline), and an
131
+ // abandoned server holds its port for the full callback timeout, so the
132
+ // next sign-in cannot bind.
133
+ const onAbort = () => {
134
+ clearTimeout(loginTimeout);
135
+ reject(new OAuthLoginError("xai", "Sign-in cancelled."));
136
+ };
137
+ if (opts.signal?.aborted) {
138
+ onAbort();
139
+ return;
140
+ }
141
+ opts.signal?.addEventListener("abort", onAbort, { once: true });
128
142
  this.callbackServerFn({
129
143
  onCode: (code, s) => {
130
144
  receivedState = s;
@@ -146,15 +160,23 @@ export class GrokOAuthProvider {
146
160
  });
147
161
  opts.onUserCode?.(authorizeUrl, authorizeUrl);
148
162
  this.openBrowserFn(authorizeUrl);
149
- // Simple manual token/code input fallback (when redirect fails and xAI page shows a code)
150
- if (process.stdin.isTTY) {
151
- const rl = readline.createInterface({ input: process.stdin });
163
+ // Manual code-paste fallback (xAI's page sometimes shows a code
164
+ // instead of redirecting to the loopback URI).
165
+ //
166
+ // CLI only. `isRaw` means another consumer already owns stdin —
167
+ // inside the TUI that is OpenTUI's key handler. Attaching a readline
168
+ // there stole every keystroke, and on the normal HTTP-callback path
169
+ // it was never closed, so the TUI kept receiving nothing: Esc did
170
+ // not dismiss the provider dialog and only restarting the session
171
+ // recovered it. The console.log pair also printed into the TUI's
172
+ // alternate screen. Both are correct for `keys login`, wrong here.
173
+ if (process.stdin.isTTY && !process.stdin.isRaw) {
174
+ manualPasteRl = readline.createInterface({ input: process.stdin });
152
175
  console.log(' If the xAI page shows a code ("Could not establish connection") instead of redirecting,');
153
176
  console.log(" copy the code and paste it here then press Enter:");
154
- rl.on("line", (line) => {
177
+ manualPasteRl.on("line", (line) => {
155
178
  const c = line.trim();
156
179
  if (c.length > 30) {
157
- rl.close();
158
180
  clearTimeout(loginTimeout);
159
181
  resolve(c);
160
182
  }
@@ -174,6 +196,9 @@ export class GrokOAuthProvider {
174
196
  }
175
197
  finally {
176
198
  callbackServer?.close();
199
+ // Unconditional: the old code only closed this when the user actually
200
+ // pasted a code, so the normal HTTP-callback path left stdin captured.
201
+ manualPasteRl?.close();
177
202
  }
178
203
  if (receivedState && receivedState !== state) {
179
204
  throw new OAuthLoginError("xai", "OAuth state mismatch — possible CSRF, aborting.");
@@ -50,6 +50,7 @@ export declare class OpenAIOAuthProvider implements ProviderOAuth {
50
50
  });
51
51
  login(opts?: {
52
52
  onUserCode?: (code: string, url: string) => void;
53
+ signal?: AbortSignal;
53
54
  }): Promise<OAuthTokens>;
54
55
  refresh(tokens: OAuthTokens): Promise<OAuthTokens>;
55
56
  revoke(tokens: OAuthTokens): Promise<void>;
@@ -117,6 +117,20 @@ export class OpenAIOAuthProvider {
117
117
  const loginTimeout = setTimeout(() => {
118
118
  reject(new Error("OAuth browser callback timed out"));
119
119
  }, CALLBACK_TIMEOUT_MS);
120
+ // Cancelling used to abandon this promise rather than end it: the
121
+ // loopback server then held its port for the full CALLBACK_TIMEOUT_MS
122
+ // (5 min) across only two ports, so the next sign-in could not bind and
123
+ // the user had to restart the CLI. Rejecting here runs the `finally`
124
+ // below, which closes the server and frees the port immediately.
125
+ const onAbort = () => {
126
+ clearTimeout(loginTimeout);
127
+ reject(new OAuthLoginError("openai", "Sign-in cancelled."));
128
+ };
129
+ if (opts.signal?.aborted) {
130
+ onAbort();
131
+ return;
132
+ }
133
+ opts.signal?.addEventListener("abort", onAbort, { once: true });
120
134
  const tryPorts = async () => {
121
135
  let bindError;
122
136
  for (const port of CODEX_PORTS) {
@@ -321,7 +335,7 @@ function extractIdTokenClaim(idToken, key) {
321
335
  }
322
336
  function buildOpenAIAuthorizeUrl(opts) {
323
337
  // Build the query string by hand — generic helpers like buildAuthorizeUrl()
324
- // inject Google-specific params (access_type=offline, prompt=consent) that
338
+ // inject extra params (access_type=offline, prompt=consent) that
325
339
  // OpenAI's auth backend rejects with "Authentication Error".
326
340
  const params = new URLSearchParams({
327
341
  response_type: "code",
@@ -50,40 +50,6 @@ export async function loadOAuthRegistry() {
50
50
  catch {
51
51
  /* openai-oauth unavailable */
52
52
  }
53
- try {
54
- const { agyOAuth, loadAgyTokensWithRefresh, loadCustomOAuthTokens } = await import("./gemini-oauth.js");
55
- const { loadGcloudToken } = await import("./gcloud.js");
56
- r.google = {
57
- provider: agyOAuth,
58
- displayName: "Agy",
59
- // baseURL intentionally left undefined for the google provider.
60
- // When OAuth tokens are present, the custom fetch-based provider in
61
- // google.strategy.ts (Approach A) uses the user-specified baseURL from
62
- // settings, or falls back to generativelanguage.googleapis.com/v1beta.
63
- // The old hardcoded cloudcode-pa.googleapis.com endpoint is dead.
64
- //
65
- // Token loading chain (Approach B + C):
66
- // 1. Custom OAuth client from env vars MUONROI_GOOGLE_CLIENT_ID/SECRET
67
- // or settings providers.google.oauthClientId/oauthClientSecret
68
- // 2. gcloud ADC (~/.config/gcloud/application_default_credentials.json)
69
- // 3. Agy OAuth tokens from ~/.gemini/oauth_creds.json (legacy)
70
- loadTokensWithRefresh: async () => {
71
- // Approach C: try custom OAuth client first (user-registered GCP client)
72
- const custom = await loadCustomOAuthTokens().catch(() => null);
73
- if (custom)
74
- return custom;
75
- // Approach B: try gcloud ADC (works immediately after gcloud auth login)
76
- const gcloud = await loadGcloudToken().catch(() => null);
77
- if (gcloud)
78
- return gcloud;
79
- // Legacy fallback: Agy tokens from ~/.gemini/oauth_creds.json
80
- return loadAgyTokensWithRefresh();
81
- },
82
- };
83
- }
84
- catch {
85
- /* agy-oauth unavailable */
86
- }
87
53
  try {
88
54
  const { grokOAuth, loadGrokTokensWithRefresh } = await import("./grok-oauth.js");
89
55
  r.xai = {
@@ -2,10 +2,8 @@
2
2
  * src/providers/auth/token-store.ts
3
3
  *
4
4
  * Persistent store for provider OAuth tokens.
5
- * Primary: OS keychain via keytar (same loader as keychain.ts).
6
- * Account key: `oauth:<provider>`, service: "muonroi-cli".
7
- * Value: JSON-serialized OAuthTokens.
8
- * Fallback: ~/.muonroi-cli/auth/<provider>.json, mode 0600.
5
+ * Storage: ~/.muonroi-cli/auth/<provider>.json, mode 0600 (JSON-serialized
6
+ * OAuthTokens). The OS keychain (keytar) has been removed.
9
7
  *
10
8
  * All token fields are enrolled in the redactor immediately after load.
11
9
  */
@@ -14,15 +12,17 @@ import type { OAuthTokens } from "./types.js";
14
12
  * Enroll all token secrets so they are scrubbed from logs.
15
13
  */
16
14
  export declare function enrollTokensInRedactor(tokens: OAuthTokens): void;
15
+ /**
16
+ * Persist OAuth tokens for a provider to ~/.muonroi-cli/auth/<provider>.json
17
+ * (mode 0600).
18
+ */
17
19
  export declare function saveTokens(provider: string, tokens: OAuthTokens): Promise<void>;
18
20
  /**
19
- * Load OAuth tokens for a provider.
20
- * Returns null if no tokens are stored.
21
- * Enrolled in redactor on load.
21
+ * Load OAuth tokens for a provider from the 0600 file store.
22
+ * Returns null if no tokens are stored. Enrolled in redactor on load.
22
23
  */
23
24
  export declare function loadTokens(provider: string): Promise<OAuthTokens | null>;
24
25
  /**
25
- * Delete stored OAuth tokens for a provider.
26
- * Attempts both keychain and file removal (either may or may not exist).
26
+ * Delete stored OAuth tokens for a provider (removes the 0600 file).
27
27
  */
28
28
  export declare function deleteTokens(provider: string): Promise<void>;
@@ -2,10 +2,8 @@
2
2
  * src/providers/auth/token-store.ts
3
3
  *
4
4
  * Persistent store for provider OAuth tokens.
5
- * Primary: OS keychain via keytar (same loader as keychain.ts).
6
- * Account key: `oauth:<provider>`, service: "muonroi-cli".
7
- * Value: JSON-serialized OAuthTokens.
8
- * Fallback: ~/.muonroi-cli/auth/<provider>.json, mode 0600.
5
+ * Storage: ~/.muonroi-cli/auth/<provider>.json, mode 0600 (JSON-serialized
6
+ * OAuthTokens). The OS keychain (keytar) has been removed.
9
7
  *
10
8
  * All token fields are enrolled in the redactor immediately after load.
11
9
  */
@@ -13,10 +11,6 @@ import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
13
11
  import * as os from "node:os";
14
12
  import * as path from "node:path";
15
13
  import { redactor } from "../../utils/redactor.js";
16
- const KEYCHAIN_SERVICE = "muonroi-cli";
17
- function oauthAccount(provider) {
18
- return `oauth:${provider}`;
19
- }
20
14
  /**
21
15
  * Override for tests — set process.env.MUONROI_AUTH_DIR to point at a temp dir.
22
16
  */
@@ -38,68 +32,24 @@ export function enrollTokensInRedactor(tokens) {
38
32
  if (tokens.idToken)
39
33
  redactor.enrollSecret(tokens.idToken);
40
34
  }
41
- async function loadKeytar() {
42
- try {
43
- return (await import("keytar"));
44
- }
45
- catch {
46
- return null;
47
- }
48
- }
49
35
  // ---------------------------------------------------------------------------
50
36
  // Public API
51
37
  // ---------------------------------------------------------------------------
52
38
  /**
53
- * Persist OAuth tokens for a provider.
54
- * Tries keychain first; falls back to filesystem (0600).
39
+ * Persist OAuth tokens for a provider to ~/.muonroi-cli/auth/<provider>.json
40
+ * (mode 0600).
55
41
  */
56
- // Windows Credential Manager's stub rejects credentials larger than ~2.5 KiB
57
- // with "The stub received bad data" — OAuth blobs routinely exceed that, so
58
- // for anything over this threshold we skip keytar and go straight to the
59
- // file fallback (mode 0600).
60
- const KEYCHAIN_BLOB_LIMIT_BYTES = 2000;
61
42
  export async function saveTokens(provider, tokens) {
62
43
  enrollTokensInRedactor(tokens);
63
44
  const json = JSON.stringify(tokens);
64
- // Try keytar only for payloads small enough that Credential Manager will
65
- // accept them. For larger blobs, write to the 0600 file fallback directly.
66
- if (json.length <= KEYCHAIN_BLOB_LIMIT_BYTES) {
67
- const kt = await loadKeytar();
68
- if (kt) {
69
- try {
70
- await kt.setPassword(KEYCHAIN_SERVICE, oauthAccount(provider), json);
71
- return;
72
- }
73
- catch {
74
- // fall through to file
75
- }
76
- }
77
- }
78
45
  await mkdir(fallbackDir(), { recursive: true });
79
46
  await writeFile(fallbackPath(provider), json, { mode: 0o600, encoding: "utf8" });
80
47
  }
81
48
  /**
82
- * Load OAuth tokens for a provider.
83
- * Returns null if no tokens are stored.
84
- * Enrolled in redactor on load.
49
+ * Load OAuth tokens for a provider from the 0600 file store.
50
+ * Returns null if no tokens are stored. Enrolled in redactor on load.
85
51
  */
86
52
  export async function loadTokens(provider) {
87
- // Try keychain first
88
- const kt = await loadKeytar();
89
- if (kt) {
90
- try {
91
- const raw = await kt.getPassword(KEYCHAIN_SERVICE, oauthAccount(provider));
92
- if (raw) {
93
- const tokens = JSON.parse(raw);
94
- enrollTokensInRedactor(tokens);
95
- return tokens;
96
- }
97
- }
98
- catch {
99
- // fall through to file
100
- }
101
- }
102
- // Try file fallback
103
53
  try {
104
54
  const raw = await readFile(fallbackPath(provider), "utf8");
105
55
  const tokens = JSON.parse(raw);
@@ -107,23 +57,14 @@ export async function loadTokens(provider) {
107
57
  return tokens;
108
58
  }
109
59
  catch {
60
+ // Missing/unreadable file → no tokens stored.
110
61
  return null;
111
62
  }
112
63
  }
113
64
  /**
114
- * Delete stored OAuth tokens for a provider.
115
- * Attempts both keychain and file removal (either may or may not exist).
65
+ * Delete stored OAuth tokens for a provider (removes the 0600 file).
116
66
  */
117
67
  export async function deleteTokens(provider) {
118
- const kt = await loadKeytar();
119
- if (kt) {
120
- try {
121
- await kt.deletePassword(KEYCHAIN_SERVICE, oauthAccount(provider));
122
- }
123
- catch {
124
- // ignore
125
- }
126
- }
127
68
  try {
128
69
  await unlink(fallbackPath(provider));
129
70
  }