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
@@ -1,22 +1,37 @@
1
+ import type { ProviderId } from "../providers/types.js";
1
2
  import type { ModelInfo, ReasoningEffort } from "../types/index.js";
3
+ import type { CatalogCouncilRouting, CatalogProviderPeakHour, CatalogVisionProxyRouting } from "./catalog-client.js";
2
4
  export declare let MODELS: ModelInfo[];
3
5
  export declare let isLoading: boolean;
6
+ export declare let SWITCH_PROVIDER_ORDER: readonly ProviderId[];
4
7
  /**
5
- * Load models from centralized catalog (CP endpoint with static fallback).
6
- * Called once at boot. No provider API keys needed.
8
+ * Load models + routing policies from centralized catalog (API with static fallback).
7
9
  */
8
10
  export declare function loadCatalog(): Promise<void>;
11
+ export declare function getProviderPeakHourRule(providerId: string): CatalogProviderPeakHour | undefined;
12
+ /** Catalog-defined default council lineup (multi-provider debate slots). */
13
+ export declare function getCatalogCouncilRouting(): CatalogCouncilRouting | undefined;
14
+ export declare function getVisionProxyRouting(): CatalogVisionProxyRouting | undefined;
9
15
  export declare function getModelIds(): string[];
10
16
  export declare function getModelInfo(idOrAlias: string): ModelInfo | undefined;
11
17
  export declare function normalizeModelId(idOrAlias: string): string;
12
18
  export declare function getEffectiveReasoningEffort(modelId: string, requestedEffort: ReasoningEffort | undefined): ReasoningEffort | undefined;
19
+ /** Returns true if the resolved model has built-in reasoning / extended thinking. */
20
+ export declare function isReasoningModel(modelId: string): boolean;
13
21
  export declare function getSupportedReasoningEfforts(modelId: string): ReasoningEffort[];
14
- /**
15
- * Pick the first model matching a tier for a given provider.
16
- * If no match for provider+tier, returns first model of that tier from any provider.
17
- * Returns undefined if no models in that tier exist.
18
- */
19
22
  export declare function getModelByTier(tier: "fast" | "balanced" | "premium", preferProvider?: string): ModelInfo | undefined;
20
23
  export declare function getModelsForProvider(providerId: string): ModelInfo[];
24
+ /**
25
+ * Part E — does this model have NATIVE online web research (its own
26
+ * web_search/browsing/Live-Search)? Missing flag → false (safe default per the
27
+ * Kill #6 rule: never infer web capability from the provider).
28
+ */
29
+ export declare function modelHasNativeWebResearch(idOrAlias: string): boolean;
30
+ /**
31
+ * First catalog model with native web research (optionally constrained to a set
32
+ * of reachable model ids). Used by the council research phase to route the
33
+ * Researcher stance to a web-capable model. Returns undefined when none exist.
34
+ */
35
+ export declare function getWebResearchModel(reachableIds?: ReadonlySet<string>): ModelInfo | undefined;
21
36
  export declare function getFirstCatalogModel(): ModelInfo;
22
37
  export declare function getFirstCatalogProvider(): string;
@@ -1,19 +1,33 @@
1
- import { catalogModelToModelInfo, fetchCatalog } from "./catalog-client.js";
1
+ import { catalogModelToModelInfo, fetchCatalogDocument } from "./catalog-client.js";
2
2
  const ALL_REASONING_EFFORTS = ["low", "medium", "high", "xhigh"];
3
+ const DEFAULT_SWITCH_PROVIDER_ORDER = ["deepseek", "zai", "opencode-go", "xai"];
3
4
  // ---------------------------------------------------------------------------
4
5
  // Centralized model registry — populated by loadCatalog() at boot
5
6
  // ---------------------------------------------------------------------------
6
7
  export let MODELS = [];
7
8
  export let isLoading = true;
9
+ export let SWITCH_PROVIDER_ORDER = DEFAULT_SWITCH_PROVIDER_ORDER;
10
+ const providerPeakHourRules = new Map();
11
+ let catalogCouncilRouting;
12
+ let catalogVisionProxyRouting;
8
13
  /**
9
- * Load models from centralized catalog (CP endpoint with static fallback).
10
- * Called once at boot. No provider API keys needed.
14
+ * Load models + routing policies from centralized catalog (API with static fallback).
11
15
  */
12
16
  export async function loadCatalog() {
13
17
  isLoading = true;
14
18
  try {
15
- const catalog = await fetchCatalog();
16
- MODELS = catalog.map(catalogModelToModelInfo);
19
+ const doc = await fetchCatalogDocument();
20
+ MODELS = doc.models.map(catalogModelToModelInfo);
21
+ SWITCH_PROVIDER_ORDER = doc.routing?.switch_provider_order ?? [
22
+ ...DEFAULT_SWITCH_PROVIDER_ORDER,
23
+ ];
24
+ providerPeakHourRules.clear();
25
+ for (const [providerId, policy] of Object.entries(doc.provider_policies ?? {})) {
26
+ if (policy.peak_hour)
27
+ providerPeakHourRules.set(providerId, policy.peak_hour);
28
+ }
29
+ catalogCouncilRouting = doc.routing?.council;
30
+ catalogVisionProxyRouting = doc.routing?.vision_proxy;
17
31
  }
18
32
  catch {
19
33
  // On total failure, MODELS stays empty — callers must handle
@@ -22,6 +36,16 @@ export async function loadCatalog() {
22
36
  isLoading = false;
23
37
  }
24
38
  }
39
+ export function getProviderPeakHourRule(providerId) {
40
+ return providerPeakHourRules.get(providerId);
41
+ }
42
+ /** Catalog-defined default council lineup (multi-provider debate slots). */
43
+ export function getCatalogCouncilRouting() {
44
+ return catalogCouncilRouting;
45
+ }
46
+ export function getVisionProxyRouting() {
47
+ return catalogVisionProxyRouting;
48
+ }
25
49
  // ---------------------------------------------------------------------------
26
50
  // Lookup helpers
27
51
  // ---------------------------------------------------------------------------
@@ -29,7 +53,22 @@ export function getModelIds() {
29
53
  return MODELS.map((m) => m.id);
30
54
  }
31
55
  export function getModelInfo(idOrAlias) {
32
- return MODELS.find((m) => m.id === idOrAlias || m.aliases?.includes(idOrAlias));
56
+ const direct = MODELS.find((m) => m.id === idOrAlias || m.aliases?.includes(idOrAlias));
57
+ if (direct)
58
+ return direct;
59
+ // Gateway-prefix fallback: some routers/persisted configs prefix the model
60
+ // id with the gateway they came through (e.g. "opencode/deepseek-v4-flash",
61
+ // "deepseek-ai/DeepSeek-V4-Flash"). The native provider API rejects the
62
+ // prefixed form. Retry with the last path segment so the canonical catalog
63
+ // entry (and its provider) still resolves instead of leaking a dead id to
64
+ // runtime. Only matches when the stripped segment is a real catalog id/alias,
65
+ // so a non-catalog id still returns undefined (no false positives).
66
+ const slash = idOrAlias.lastIndexOf("/");
67
+ if (slash >= 0 && slash < idOrAlias.length - 1) {
68
+ const tail = idOrAlias.slice(slash + 1);
69
+ return MODELS.find((m) => m.id === tail || m.aliases?.includes(tail));
70
+ }
71
+ return undefined;
33
72
  }
34
73
  export function normalizeModelId(idOrAlias) {
35
74
  const m = getModelInfo(idOrAlias);
@@ -43,6 +82,10 @@ export function getEffectiveReasoningEffort(modelId, requestedEffort) {
43
82
  return undefined;
44
83
  return requestedEffort;
45
84
  }
85
+ /** Returns true if the resolved model has built-in reasoning / extended thinking. */
86
+ export function isReasoningModel(modelId) {
87
+ return getModelInfo(modelId)?.reasoning ?? false;
88
+ }
46
89
  export function getSupportedReasoningEfforts(modelId) {
47
90
  const info = getModelInfo(modelId);
48
91
  if (!info?.reasoning)
@@ -54,17 +97,37 @@ export function getSupportedReasoningEfforts(modelId) {
54
97
  * If no match for provider+tier, returns first model of that tier from any provider.
55
98
  * Returns undefined if no models in that tier exist.
56
99
  */
100
+ function isTierRoutable(m) {
101
+ return m.tierRouting !== false;
102
+ }
103
+ function matchesTier(m, tier) {
104
+ return m.tier === tier || m.routingTiers?.includes(tier) === true;
105
+ }
57
106
  export function getModelByTier(tier, preferProvider) {
58
107
  if (preferProvider) {
59
- const providerMatch = MODELS.find((m) => m.tier === tier && m.provider === preferProvider);
60
- if (providerMatch)
61
- return providerMatch;
108
+ return MODELS.find((m) => matchesTier(m, tier) && m.provider === preferProvider && isTierRoutable(m));
62
109
  }
63
- return MODELS.find((m) => m.tier === tier);
110
+ return MODELS.find((m) => matchesTier(m, tier) && isTierRoutable(m));
64
111
  }
65
112
  export function getModelsForProvider(providerId) {
66
113
  return MODELS.filter((m) => m.provider === providerId);
67
114
  }
115
+ /**
116
+ * Part E — does this model have NATIVE online web research (its own
117
+ * web_search/browsing/Live-Search)? Missing flag → false (safe default per the
118
+ * Kill #6 rule: never infer web capability from the provider).
119
+ */
120
+ export function modelHasNativeWebResearch(idOrAlias) {
121
+ return getModelInfo(idOrAlias)?.nativeWebResearch === true;
122
+ }
123
+ /**
124
+ * First catalog model with native web research (optionally constrained to a set
125
+ * of reachable model ids). Used by the council research phase to route the
126
+ * Researcher stance to a web-capable model. Returns undefined when none exist.
127
+ */
128
+ export function getWebResearchModel(reachableIds) {
129
+ return MODELS.find((m) => m.nativeWebResearch === true && isTierRoutable(m) && (!reachableIds || reachableIds.has(m.id)));
130
+ }
68
131
  export function getFirstCatalogModel() {
69
132
  const m = MODELS.find(() => true);
70
133
  if (!m)
@@ -132,7 +132,7 @@ async function checkEEDetailed() {
132
132
  // that contradicts a live ee_query working. See VERIFY F9.
133
133
  if (!serverOk) {
134
134
  const hint = result.mode === "thin-client"
135
- ? "Hint: check VPS 72.61.127.154:8082 is reachable; verify ~/.experience/config.json serverBaseUrl + serverReadAuthToken"
135
+ ? "Hint: check VPS experience.muonroi.com is reachable; verify ~/.experience/config.json serverBaseUrl + serverReadAuthToken"
136
136
  : "Hint: start EE locally or configure thin-client in ~/.experience/config.json";
137
137
  return {
138
138
  name: "ee.health",
@@ -21,9 +21,9 @@
21
21
  * cannot inject shell commands.
22
22
  */
23
23
  import { execFile } from "node:child_process";
24
- import { logger } from "../utils/logger.js";
25
24
  import { resolve } from "node:path";
26
25
  import { promisify } from "node:util";
26
+ import { logger } from "../utils/logger.js";
27
27
  const pexecFile = promisify(execFile);
28
28
  /** Attribution line every auto-commit message ends with (mirrors the prompt rule). */
29
29
  export const AUTO_COMMIT_ATTRIBUTION = "Coding by - Muonroi-CLI";
@@ -133,7 +133,7 @@ export class BatchTurnRunner {
133
133
  const batchRequestId = `turn-${Date.now()}-${stepNumber}`;
134
134
  // Phase O1 — capture providerOptions SHAPE for batch path too.
135
135
  deps.setLastProviderOptionsShape(extractProviderOptionsShape(runtime.providerOptions));
136
- const _messagesForCall = deps.messages.map((m) => (m === args.userModelMessage ? args.userEnrichedMessage : m));
136
+ const _messagesForCall = deps.messages.map((m) => m === args.userModelMessage ? args.userEnrichedMessage : m);
137
137
  await addBatchRequests({
138
138
  ...deps.getBatchClientOptions(signal),
139
139
  batchId: batch.batch_id,
@@ -145,7 +145,7 @@ export class BatchTurnRunner {
145
145
  modelId: runtime.modelId,
146
146
  system,
147
147
  messages: [..._messagesForCall, ...turnMessages],
148
- temperature: 0.7,
148
+ temperature: runtime.modelInfo?.fixedTemperature ?? 0.7,
149
149
  maxOutputTokens: !batchCaps.acceptsParam("maxOutputTokens", runtime.modelInfo)
150
150
  ? undefined
151
151
  : deps.maxTokens,
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Non-Claude prompt-cache prefix stability (Task 3).
3
+ *
4
+ * On non-Claude providers (DeepSeek / GLM / other OpenAI-compatible backends)
5
+ * the whole system prompt is sent as a single string. Any per-turn-varying
6
+ * content that sits AFTER the byte-stable `staticPrefix` but BEFORE the
7
+ * conversation — the `dynamicSuffix` (plan / resume / cwd), the PIL output
8
+ * suffix, and the live MCP capability roster — shifts the cached prefix and
9
+ * forces a full cache miss on PIL-active turns. Measured: `pil_active=1` ⟺
10
+ * `cache_read=0` on 12/12 calls (session `47a774d272da`).
11
+ *
12
+ * Fix (variant b): split the assembled system string at the END of
13
+ * `staticPrefix`. The front stays as the `system` string; the dynamic tail is
14
+ * relocated into the trailing user message (see `foldDynamicTailIntoUserMessage`)
15
+ * rather than emitted as a mid-conversation system-role message, because
16
+ * OpenAI-compatible providers do not reliably accept a non-leading system role.
17
+ *
18
+ * IMPORTANT fast-tier caveat: for fast-tier models the cheap-model workbook /
19
+ * playbook / shell directive are front-loaded BEFORE `staticPrefix` for primacy,
20
+ * and the workbook's task addendum covaries with `taskType` (== `pil_active`).
21
+ * That portion still shifts the prefix and is a deliberate primacy design, so
22
+ * this split does NOT relocate it — the front is fully byte-stable only for
23
+ * non-fast-tier non-Claude models (the expensive-model path, which is where the
24
+ * cache payoff is per the plan). See task-3-report.md for the residual analysis.
25
+ *
26
+ * The Claude path keeps its own two-block cache split upstream and MUST NOT be
27
+ * routed through this helper.
28
+ */
29
+ export interface FrontTailSplit {
30
+ /** The byte-stable front to send as the `system` string. */
31
+ front: string;
32
+ /** The per-turn-dynamic tail to relocate into the trailing user message. */
33
+ dynamicTail: string;
34
+ }
35
+ /**
36
+ * Split an assembled non-Claude system string into a byte-stable front and a
37
+ * per-turn-dynamic tail, cutting at the end of `staticPrefix`.
38
+ *
39
+ * Uses the established provider-family detection (`modelId.startsWith("claude")`)
40
+ * so the Claude branch is a no-op guard. If `staticPrefix` cannot be located in
41
+ * `systemWithCaps` (unexpected), returns the whole string as `front` with an
42
+ * empty tail so no instruction content is ever dropped.
43
+ */
44
+ export declare function splitFrontAndDynamicTail(params: {
45
+ modelId: string;
46
+ systemWithCaps: string;
47
+ staticPrefix: string;
48
+ }): FrontTailSplit;
49
+ /**
50
+ * `assembleFrontSystem` — thin convenience wrapper returning only the byte-stable
51
+ * front (the value sent as the `system` string). Named to match the plan's
52
+ * invariant-test contract.
53
+ */
54
+ export declare function assembleFrontSystem(params: {
55
+ modelId: string;
56
+ systemWithCaps: string;
57
+ staticPrefix: string;
58
+ }): string;
59
+ /**
60
+ * Fold a relocated dynamic tail into a user message's content. Handles both
61
+ * string content and structured (array-of-parts) content. Returns the message
62
+ * unchanged when the tail is empty. Never mutates the input.
63
+ */
64
+ export declare function foldDynamicTailIntoUserMessage<T extends {
65
+ role: unknown;
66
+ content: unknown;
67
+ }>(msg: T, dynamicTail: string): T;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Non-Claude prompt-cache prefix stability (Task 3).
3
+ *
4
+ * On non-Claude providers (DeepSeek / GLM / other OpenAI-compatible backends)
5
+ * the whole system prompt is sent as a single string. Any per-turn-varying
6
+ * content that sits AFTER the byte-stable `staticPrefix` but BEFORE the
7
+ * conversation — the `dynamicSuffix` (plan / resume / cwd), the PIL output
8
+ * suffix, and the live MCP capability roster — shifts the cached prefix and
9
+ * forces a full cache miss on PIL-active turns. Measured: `pil_active=1` ⟺
10
+ * `cache_read=0` on 12/12 calls (session `47a774d272da`).
11
+ *
12
+ * Fix (variant b): split the assembled system string at the END of
13
+ * `staticPrefix`. The front stays as the `system` string; the dynamic tail is
14
+ * relocated into the trailing user message (see `foldDynamicTailIntoUserMessage`)
15
+ * rather than emitted as a mid-conversation system-role message, because
16
+ * OpenAI-compatible providers do not reliably accept a non-leading system role.
17
+ *
18
+ * IMPORTANT fast-tier caveat: for fast-tier models the cheap-model workbook /
19
+ * playbook / shell directive are front-loaded BEFORE `staticPrefix` for primacy,
20
+ * and the workbook's task addendum covaries with `taskType` (== `pil_active`).
21
+ * That portion still shifts the prefix and is a deliberate primacy design, so
22
+ * this split does NOT relocate it — the front is fully byte-stable only for
23
+ * non-fast-tier non-Claude models (the expensive-model path, which is where the
24
+ * cache payoff is per the plan). See task-3-report.md for the residual analysis.
25
+ *
26
+ * The Claude path keeps its own two-block cache split upstream and MUST NOT be
27
+ * routed through this helper.
28
+ */
29
+ /**
30
+ * Split an assembled non-Claude system string into a byte-stable front and a
31
+ * per-turn-dynamic tail, cutting at the end of `staticPrefix`.
32
+ *
33
+ * Uses the established provider-family detection (`modelId.startsWith("claude")`)
34
+ * so the Claude branch is a no-op guard. If `staticPrefix` cannot be located in
35
+ * `systemWithCaps` (unexpected), returns the whole string as `front` with an
36
+ * empty tail so no instruction content is ever dropped.
37
+ */
38
+ export function splitFrontAndDynamicTail(params) {
39
+ const { modelId, systemWithCaps, staticPrefix } = params;
40
+ // Claude is handled by its own two-block ephemeral-cache split — never here.
41
+ if (modelId.startsWith("claude") || staticPrefix.length === 0) {
42
+ return { front: systemWithCaps, dynamicTail: "" };
43
+ }
44
+ const anchor = systemWithCaps.indexOf(staticPrefix);
45
+ if (anchor < 0) {
46
+ // staticPrefix not found — do not risk relocating (and possibly dropping)
47
+ // content we cannot precisely locate. Keep the original single string.
48
+ return { front: systemWithCaps, dynamicTail: "" };
49
+ }
50
+ const splitAt = anchor + staticPrefix.length;
51
+ return {
52
+ front: systemWithCaps.slice(0, splitAt),
53
+ dynamicTail: systemWithCaps.slice(splitAt),
54
+ };
55
+ }
56
+ /**
57
+ * `assembleFrontSystem` — thin convenience wrapper returning only the byte-stable
58
+ * front (the value sent as the `system` string). Named to match the plan's
59
+ * invariant-test contract.
60
+ */
61
+ export function assembleFrontSystem(params) {
62
+ return splitFrontAndDynamicTail(params).front;
63
+ }
64
+ /**
65
+ * Fold a relocated dynamic tail into a user message's content. Handles both
66
+ * string content and structured (array-of-parts) content. Returns the message
67
+ * unchanged when the tail is empty. Never mutates the input.
68
+ */
69
+ export function foldDynamicTailIntoUserMessage(msg, dynamicTail) {
70
+ if (dynamicTail.trim().length === 0)
71
+ return msg;
72
+ const block = `\n\n---\n[Session context — working directory, task guidance, and available tools]\n${dynamicTail.trim()}`;
73
+ const content = msg.content;
74
+ if (typeof content === "string") {
75
+ return { ...msg, content: `${content}${block}` };
76
+ }
77
+ if (Array.isArray(content)) {
78
+ return { ...msg, content: [...content, { type: "text", text: block }] };
79
+ }
80
+ // Unknown content shape — do not risk corrupting it; leave unchanged.
81
+ return msg;
82
+ }
83
+ //# sourceMappingURL=cache-prefix.js.map
@@ -0,0 +1,32 @@
1
+ /**
2
+ * src/orchestrator/compact-request.ts
3
+ *
4
+ * Process-global one-shot channel for an AGENT-initiated proactive compaction.
5
+ *
6
+ * The `compact` tool (src/tools/registry.ts) sets a pending request when the
7
+ * model decides to free context mid-task; the tool-engine `prepareStep`
8
+ * boundary consumes it exactly once and forces a compaction of the accumulated
9
+ * tool/conversation history BEFORE the next LLM step, then continues the turn.
10
+ * This is the proactive counterpart to the reactive tool-limit auto-recover
11
+ * (tool-limit-auto-recover.ts): the agent no longer has to hit a round cap to
12
+ * shed context — it can ask for a clean history the moment it judges the turn
13
+ * has gone read-heavy, avoiding the interruption entirely.
14
+ *
15
+ * Single-active-turn assumption: the TUI streams one turn at a time, so a
16
+ * process-global slot is sufficient and cannot cross-talk between concurrent
17
+ * user turns. A nested sub-session runs within its parent's turn and consumes
18
+ * the flag on its own next step — worst case a harmless extra compaction, never
19
+ * data loss (compaction is snapshot + rehydratable via ee_query).
20
+ */
21
+ export interface ProactiveCompactRequestState {
22
+ /** Optional focus note the model wants preserved in mind after compaction. */
23
+ instructions: string | null;
24
+ }
25
+ /** Queue a proactive compaction to run before the next tool-loop step. */
26
+ export declare function requestProactiveCompact(instructions?: string | null): void;
27
+ /** True when a proactive compaction is queued (non-consuming peek). */
28
+ export declare function hasPendingProactiveCompact(): boolean;
29
+ /** Consume the pending request exactly once (returns null when none queued). */
30
+ export declare function consumeProactiveCompact(): ProactiveCompactRequestState | null;
31
+ /** Test hook — clear any queued request. */
32
+ export declare function __resetProactiveCompactForTests(): void;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * src/orchestrator/compact-request.ts
3
+ *
4
+ * Process-global one-shot channel for an AGENT-initiated proactive compaction.
5
+ *
6
+ * The `compact` tool (src/tools/registry.ts) sets a pending request when the
7
+ * model decides to free context mid-task; the tool-engine `prepareStep`
8
+ * boundary consumes it exactly once and forces a compaction of the accumulated
9
+ * tool/conversation history BEFORE the next LLM step, then continues the turn.
10
+ * This is the proactive counterpart to the reactive tool-limit auto-recover
11
+ * (tool-limit-auto-recover.ts): the agent no longer has to hit a round cap to
12
+ * shed context — it can ask for a clean history the moment it judges the turn
13
+ * has gone read-heavy, avoiding the interruption entirely.
14
+ *
15
+ * Single-active-turn assumption: the TUI streams one turn at a time, so a
16
+ * process-global slot is sufficient and cannot cross-talk between concurrent
17
+ * user turns. A nested sub-session runs within its parent's turn and consumes
18
+ * the flag on its own next step — worst case a harmless extra compaction, never
19
+ * data loss (compaction is snapshot + rehydratable via ee_query).
20
+ */
21
+ let pending = null;
22
+ /** Queue a proactive compaction to run before the next tool-loop step. */
23
+ export function requestProactiveCompact(instructions) {
24
+ const trimmed = typeof instructions === "string" ? instructions.trim() : "";
25
+ pending = { instructions: trimmed.length > 0 ? trimmed : null };
26
+ }
27
+ /** True when a proactive compaction is queued (non-consuming peek). */
28
+ export function hasPendingProactiveCompact() {
29
+ return pending !== null;
30
+ }
31
+ /** Consume the pending request exactly once (returns null when none queued). */
32
+ export function consumeProactiveCompact() {
33
+ const p = pending;
34
+ pending = null;
35
+ return p;
36
+ }
37
+ /** Test hook — clear any queued request. */
38
+ export function __resetProactiveCompactForTests() {
39
+ pending = null;
40
+ }
41
+ //# sourceMappingURL=compact-request.js.map
@@ -56,6 +56,16 @@ export declare function getCompactionSummaryText(message: ModelMessage | undefin
56
56
  export declare function estimateMessageTokens(message: ModelMessage): number;
57
57
  export declare function estimateConversationTokens(systemPrompt: string, messages: ModelMessage[], inFlightText?: string): number;
58
58
  export declare function shouldCompactContext(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean;
59
+ /**
60
+ * Cross-turn anti-thrash guard: true when a post-turn compaction should be
61
+ * SKIPPED because too few new tokens have accumulated since the last
62
+ * compaction's `tokensAfter` — i.e. the cache-reset cost would not be
63
+ * amortized (observed: session ff932f8568e8 re-compacted after only ~14K
64
+ * new tokens against a 20K floor).
65
+ *
66
+ * `lastAfter === null` means no prior compaction this session — never skip.
67
+ */
68
+ export declare function isCompactionThrash(tokens: number, lastAfter: number | null, minNew: number): boolean;
59
69
  export declare function findCutPoint(messages: ModelMessage[], startIndex: number, keepRecentTokens: number): CutPointResult;
60
70
  export declare function prepareCompaction(messages: ModelMessage[], systemPrompt: string, settings: CompactionSettings): PreparedCompaction | null;
61
71
  export declare function relaxCompactionSettings(settings: CompactionSettings): CompactionSettings;
@@ -1,7 +1,8 @@
1
1
  import { generateText } from "ai";
2
2
  import { isMetaAnalysisPrompt } from "../pil/layer6-output.js";
3
3
  import { getProviderCapabilities } from "../providers/capabilities.js";
4
- import { requireRuntimeProvider, resolveModelRuntime } from "../providers/runtime.js";
4
+ import { requireRuntimeProvider, resolveModelRuntime, resolveTemperatureParam } from "../providers/runtime.js";
5
+ import { logger } from "../utils/logger.js";
5
6
  import { COMPACT_PROPOSER_SYSTEM_PROMPT } from "./compaction-proposer-prompt.js";
6
7
  import { containsEncryptedReasoning } from "./reasoning.js";
7
8
  import { countTokens } from "./token-counter.js";
@@ -21,28 +22,35 @@ export async function proposeCompaction(provider, modelId, messages, signal) {
21
22
  prompt: `Current conversation messages:\n\n${serialized}\n\nDecide if compaction is needed and what to keep/drop/summarize. Return strict JSON.`,
22
23
  abortSignal: signal,
23
24
  maxRetries: 1,
24
- temperature: 0.1,
25
+ ...resolveTemperatureParam(runtime, 0.1),
25
26
  ...(!compactCaps.acceptsParam("maxOutputTokens", runtime.modelInfo) ? {} : { maxOutputTokens: 2048 }),
26
27
  ...(runtime.providerOptions ? { providerOptions: runtime.providerOptions } : {}),
27
28
  });
28
29
  const text = result.text.trim();
29
- // Attempt to parse top-level JSON object. The model might wrap in markdown fences strip those.
30
- const jsonStr = text.replace(/^```(?:json)?\s*|\s*```$/gi, "").trim();
31
- const parsed = JSON.parse(jsonStr);
30
+ // Attempt to parse JSON object robustly, even if the model wraps it in conversational text or markdown fences.
31
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
32
+ if (!jsonMatch) {
33
+ logger.warn("orchestrator", "Failed to extract JSON from proposer output", { text });
34
+ return null;
35
+ }
36
+ const parsed = JSON.parse(jsonMatch[0]);
32
37
  // Validate shape
33
38
  if (typeof parsed.shouldCompact !== "boolean" || !Array.isArray(parsed.actions)) {
39
+ logger.warn("orchestrator", "Invalid JSON shape from proposer", { parsed });
34
40
  return null;
35
41
  }
36
42
  // Validate each action
37
43
  for (const action of parsed.actions) {
38
44
  if (typeof action.messageIndex !== "number" || !["keep", "drop", "summarize"].includes(action.action)) {
45
+ logger.warn("orchestrator", "Invalid action shape from proposer", { action });
39
46
  return null;
40
47
  }
41
48
  }
42
49
  return parsed;
43
50
  }
44
- catch {
51
+ catch (err) {
45
52
  // Proposer failure is non-fatal — caller falls back to heuristic or no-compact
53
+ logger.warn("orchestrator", "Proposer failure", { error: err });
46
54
  return null;
47
55
  }
48
56
  }
@@ -347,6 +355,18 @@ export function estimateConversationTokens(systemPrompt, messages, inFlightText
347
355
  export function shouldCompactContext(contextTokens, contextWindow, settings) {
348
356
  return contextTokens > contextWindow - settings.reserveTokens;
349
357
  }
358
+ /**
359
+ * Cross-turn anti-thrash guard: true when a post-turn compaction should be
360
+ * SKIPPED because too few new tokens have accumulated since the last
361
+ * compaction's `tokensAfter` — i.e. the cache-reset cost would not be
362
+ * amortized (observed: session ff932f8568e8 re-compacted after only ~14K
363
+ * new tokens against a 20K floor).
364
+ *
365
+ * `lastAfter === null` means no prior compaction this session — never skip.
366
+ */
367
+ export function isCompactionThrash(tokens, lastAfter, minNew) {
368
+ return lastAfter !== null && tokens - lastAfter < minNew;
369
+ }
350
370
  function isValidCutPoint(message) {
351
371
  return message.role !== "tool";
352
372
  }
@@ -523,7 +543,7 @@ async function summarizeConversation(provider, modelId, messages, reserveTokens,
523
543
  prompt: promptParts.filter(Boolean).join("\n\n"),
524
544
  abortSignal: signal,
525
545
  maxRetries: 0,
526
- temperature: 0.2,
546
+ ...resolveTemperatureParam(runtime, 0.2),
527
547
  ...(!compactCaps.acceptsParam("maxOutputTokens", runtime.modelInfo) ? {} : { maxOutputTokens: effectiveMax }),
528
548
  ...(runtime.providerOptions ? { providerOptions: runtime.providerOptions } : {}),
529
549
  });
@@ -36,6 +36,12 @@ export interface CouncilManagerDeps {
36
36
  export declare class CouncilManager {
37
37
  private deps;
38
38
  private _lastSynthesis;
39
+ /**
40
+ * Post-debate action the user chose on the last runCouncilV2 (e.g.
41
+ * "continue_session", "save_exit"). Relayed to the auto-council caller
42
+ * (tool-engine) so it can honor the choice instead of always continuing.
43
+ */
44
+ private _lastPostDebateAction;
39
45
  private _isContinuation;
40
46
  private _questionResolvers;
41
47
  private _preflightResolvers;
@@ -49,10 +55,12 @@ export declare class CouncilManager {
49
55
  constructor(deps: CouncilManagerDeps);
50
56
  get lastSynthesis(): string | null;
51
57
  setLastSynthesis(v: string | null): void;
58
+ get lastPostDebateAction(): string | null;
59
+ setLastPostDebateAction(v: string | null): void;
52
60
  get isContinuation(): boolean;
53
61
  setContinuation(v: boolean): void;
54
62
  resetStats(startMs?: number): void;
55
- respondToQuestion(questionId: string, answer: string): void;
63
+ respondToQuestion(questionId: string, answer: string, questionText?: string): void;
56
64
  respondToPreflight(preflightId: string, approved: boolean): void;
57
65
  createQuestionResponder(): (questionId: string) => Promise<string>;
58
66
  createPreflightResponder(): (preflightId: string) => Promise<boolean>;
@@ -84,8 +92,9 @@ export declare class CouncilManager {
84
92
  generateRoundSummary(exchangeLogs: Map<string, string[]>, topic: string, round: number, modelId: string): Promise<string>;
85
93
  /**
86
94
  * Build conversation context for council discussion from current session messages.
87
- * Extracts: compaction summary, recent user messages, key decisions.
88
- * Limited to ~3000 tokens to avoid excessive cost.
95
+ * Extracts: compaction summary, recent conversation (user + analytical assistant),
96
+ * key decisions/outcomes/plans.
97
+ * Limited to ~8000 tokens (~32K chars) to balance depth vs cost.
89
98
  */
90
99
  buildContext(): string;
91
100
  parseOutcome(synthesisText: string, _topic: string): CouncilOutcome | null;