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
@@ -70,36 +70,63 @@ export function shouldContinueAfterMidLoopStall(s) {
70
70
  export function stallRepromptBackoffMs(attempt) {
71
71
  return Math.min(500 * 2 ** (Math.max(1, attempt) - 1), 4_000);
72
72
  }
73
- export function createStallWatchdog(timeoutMs, onFire) {
73
+ export function createStallWatchdog(timeoutMs, onFire, progressOpts) {
74
74
  const controller = new AbortController();
75
75
  let firedFlag = false;
76
76
  let timer = null;
77
77
  const enabled = Number.isFinite(timeoutMs) && timeoutMs > 0;
78
+ const progressTimeoutMs = progressOpts?.progressTimeoutMs ?? 0;
79
+ const progressEnabled = Number.isFinite(progressTimeoutMs) && progressTimeoutMs > 0;
80
+ let progressTimer = null;
81
+ const fire = (onSpecificFire) => {
82
+ if (firedFlag)
83
+ return;
84
+ firedFlag = true;
85
+ // Stop the OTHER timer so it can't also fire after the abort (e.g. the
86
+ // any-activity stall timer that was armed just before the progress timer
87
+ // tripped — otherwise both onFire callbacks would run).
88
+ clearBoth();
89
+ // DOMException(TimeoutError) mirrors AbortSignal.timeout() semantics so
90
+ // downstream isAbortError-style checks treat it as an abort.
91
+ controller.abort(new DOMException(STALL_ABORT_REASON, "TimeoutError"));
92
+ try {
93
+ onSpecificFire?.();
94
+ }
95
+ catch {
96
+ /* callback must not break the watchdog */
97
+ }
98
+ };
78
99
  const arm = () => {
79
100
  if (!enabled)
80
101
  return;
81
- timer = setTimeout(() => {
82
- firedFlag = true;
83
- // DOMException(TimeoutError) mirrors AbortSignal.timeout() semantics so
84
- // downstream isAbortError-style checks treat it as an abort.
85
- controller.abort(new DOMException(STALL_ABORT_REASON, "TimeoutError"));
86
- try {
87
- onFire?.();
88
- }
89
- catch {
90
- /* callback must not break the watchdog */
91
- }
92
- }, timeoutMs);
102
+ timer = setTimeout(() => fire(onFire), timeoutMs);
93
103
  // Don't keep the event loop alive solely for the watchdog (Node).
94
104
  timer.unref?.();
95
105
  };
106
+ const armProgress = () => {
107
+ if (!progressEnabled)
108
+ return;
109
+ progressTimer = setTimeout(() => fire(progressOpts?.onProgressFire), progressTimeoutMs);
110
+ progressTimer.unref?.();
111
+ };
96
112
  const clear = () => {
97
113
  if (timer) {
98
114
  clearTimeout(timer);
99
115
  timer = null;
100
116
  }
101
117
  };
118
+ const clearProgress = () => {
119
+ if (progressTimer) {
120
+ clearTimeout(progressTimer);
121
+ progressTimer = null;
122
+ }
123
+ };
124
+ function clearBoth() {
125
+ clear();
126
+ clearProgress();
127
+ }
102
128
  arm();
129
+ armProgress();
103
130
  return {
104
131
  signal: controller.signal,
105
132
  pet() {
@@ -108,8 +135,15 @@ export function createStallWatchdog(timeoutMs, onFire) {
108
135
  clear();
109
136
  arm();
110
137
  },
138
+ petProgress() {
139
+ if (!progressEnabled || firedFlag)
140
+ return;
141
+ clearProgress();
142
+ armProgress();
143
+ },
111
144
  dispose() {
112
145
  clear();
146
+ clearProgress();
113
147
  },
114
148
  fired() {
115
149
  return firedFlag;
@@ -25,7 +25,7 @@
25
25
  // - C1 (DeepSeek cache split read) — onFinish normalization
26
26
  // - C3 (cross-turn dedup wrap) — wrapToolSetWithDedup
27
27
  // - F1 (sub-agent cumulative cap) — wrapToolSetWithCap
28
- // - siliconflow reasoning-strip — taskCaps.sanitizeHistory
28
+ // - reasoning-strip (provider quirk) — taskCaps.sanitizeHistory
29
29
  import { stepCountIs, streamText } from "ai";
30
30
  import { recordArtifact } from "../ee/artifact-cache.js";
31
31
  import { getDefaultEEClient } from "../ee/intercept.js";
@@ -36,14 +36,14 @@ import { injectCheapModelWorkbook, shouldInjectCheapModelWorkbook, subagentTaskT
36
36
  import { getProviderCapabilities } from "../providers/capabilities.js";
37
37
  import { getVisionGuidanceForTextOnly } from "../providers/mcp-vision-bridge.js";
38
38
  import { captureToolSchemas } from "../providers/patch-zod-schema.js";
39
- import { buildTurnProviderOptions, requireRuntimeProvider, resolveModelRuntime, shouldDropParam, } from "../providers/runtime.js";
39
+ import { buildTurnProviderOptions, requireRuntimeProvider, resolveModelRuntime, resolveTemperatureParam, shouldDropParam, } from "../providers/runtime.js";
40
40
  import { needsVisionProxy } from "../providers/vision-proxy.js";
41
41
  import { wireDebug } from "../providers/wire-debug.js";
42
+ import { statusBarStore } from "../state/status-bar-store.js";
42
43
  import { BashTool } from "../tools/bash.js";
43
44
  import { createBuiltinTools } from "../tools/registry.js";
44
- import { statusBarStore } from "../ui/status-bar/store.js";
45
45
  import { openUrl } from "../utils/open-url.js";
46
- import { getCurrentShellSettings, getProviderStallTimeoutMs, getSubAgentBudgetChars, getSubAgentCompactKeepLast, getSubAgentCompactThresholdChars, loadMcpServers, loadValidSubAgents, } from "../utils/settings.js";
46
+ import { getCurrentShellSettings, getProviderProgressTimeoutMs, getProviderStallTimeoutMs, getSubAgentBudgetChars, getSubAgentCompactKeepLast, getSubAgentCompactThresholdChars, loadMcpServers, loadValidSubAgents, } from "../utils/settings.js";
47
47
  import { resolveShell } from "../utils/shell.js";
48
48
  import { prepareVerifySandbox } from "../verify/entrypoint.js";
49
49
  import { asNumber } from "./batch-utils.js";
@@ -58,7 +58,7 @@ import { attachReminderToMessages, buildScopeReminder, cadenceForSize, shouldInj
58
58
  import { recordCompaction, recordElision } from "./session-experience.js";
59
59
  import { createStallWatchdog, STALL_ERROR_MESSAGE } from "./stall-watchdog.js";
60
60
  import { wrapToolSetWithCap } from "./sub-agent-cap.js";
61
- import { compactSubAgentMessages, applyAnthropicPromptCaching } from "./subagent-compactor.js";
61
+ import { applyAnthropicPromptCaching, compactSubAgentMessages } from "./subagent-compactor.js";
62
62
  import { combineAbortSignals, firstLine, formatSubagentActivity } from "./tool-utils.js";
63
63
  /**
64
64
  * StreamRunner — extracted sub-agent stream lifecycle.
@@ -137,23 +137,36 @@ export class StreamRunner {
137
137
  });
138
138
  // Resolve child model early so we can pass modelId to createBuiltinTools
139
139
  // (needed for vision-proxy tools: analyze_image / ask_vision_proxy).
140
- const childModelId = normalizeModelId(isVision
141
- ? VISION_MODEL
142
- : isComputer
143
- ? COMPUTER_MODEL
144
- : custom
145
- ? custom.model
146
- : this.deps.resolveModelForTask(isExplore ? "explore" : isVerify || isVerifyDetect || isVerifyManifest ? "verify" : "general"));
140
+ const childModelId = normalizeModelId(request.modelId
141
+ ? request.modelId
142
+ : isVision
143
+ ? VISION_MODEL
144
+ : isComputer
145
+ ? COMPUTER_MODEL
146
+ : custom
147
+ ? custom.model
148
+ : this.deps.resolveModelForTask(isExplore ? "explore" : isVerify || isVerifyDetect || isVerifyManifest ? "verify" : "general"));
147
149
  // Mirror the file-local `createTools` wrapper from orchestrator.ts —
148
150
  // pass modelId so registry can inject analyze_image/ask_vision_proxy for
149
151
  // text-only child models (needsVisionProxy).
150
- const childBaseToolsRaw = createBuiltinTools(childBash, childMode, { modelId: childModelId });
152
+ const childBaseToolsRaw = createBuiltinTools(childBash, childMode, {
153
+ modelId: childModelId,
154
+ sessionId: this.deps.getSessionId(),
155
+ });
151
156
  // Wrap with the cumulative cap so the sub-agent's tool loop cannot
152
157
  // accumulate unbounded tool_result tokens. See sub-agent-cap.ts for the
153
158
  // tiered compression schedule. The cap is per-invocation; each sub-agent
154
159
  // gets a fresh budget.
155
160
  const subAgentCapBudget = getSubAgentBudgetChars();
156
- const subAgentCap = wrapToolSetWithCap(childBaseToolsRaw, { maxCumulativeChars: subAgentCapBudget });
161
+ const subAgentCap = wrapToolSetWithCap(childBaseToolsRaw, {
162
+ maxCumulativeChars: subAgentCapBudget,
163
+ // Opt-out toggle (default ON). The cap dedups identical tool outputs by
164
+ // content hash; set MUONROI_SUBAGENT_CAP_DEDUP=0 to disable. Used by the
165
+ // B3 compaction E2E, where the harness re-processes each tool result and
166
+ // the self-dedup would otherwise collapse distinct reads into pointer
167
+ // stubs before cumulative history can grow enough to trigger compaction.
168
+ dedupRepeatOutputs: process.env.MUONROI_SUBAGENT_CAP_DEDUP !== "0",
169
+ });
157
170
  // Phase C3: layer cross-turn dedup ON TOP of the per-invocation cap. The
158
171
  // cap sees raw output (for accurate cumulative accounting); dedup sees
159
172
  // the already-trimmed output that will actually reach the model.
@@ -255,7 +268,7 @@ export class StreamRunner {
255
268
  void signal;
256
269
  const childMessages = [{ role: "user", content: childPrompt }];
257
270
  // The main agent manages its sub-agents, so don't apply an arbitrary hard limit.
258
- const maxSteps = request.maxToolRounds ?? (this.deps.getMaxToolRounds() * 2);
271
+ const maxSteps = request.maxToolRounds ?? this.deps.getMaxToolRounds() * 2;
259
272
  // F1 parity — derive per-turn providerOptions so the sub-agent OpenAI calls
260
273
  // carry a stable session-derived promptCacheKey (every tool round routes to
261
274
  // the same cache node, keeping the unchanging prefix cached). The top-level
@@ -328,7 +341,6 @@ export class StreamRunner {
328
341
  // already strips it via `dropParam`, the sub-agent path was missing
329
342
  // the same guard, causing G1: "Task failed: No output generated.").
330
343
  const childDropMaxOutput = shouldDropParam(childRuntime, "maxOutputTokens");
331
- const childDropTemperature = shouldDropParam(childRuntime, "temperature");
332
344
  // Phase B3: compact older tool_results out of the running message history
333
345
  // before each AI SDK step. First step (stepNumber === 0) has no history
334
346
  // worth compacting; later steps are where cumulative input balloons.
@@ -346,8 +358,8 @@ export class StreamRunner {
346
358
  providerOptions: childProviderOptions,
347
359
  });
348
360
  }
349
- // SiliconFlow DeepSeek thinking-mode rejects assistant history with
350
- // `reasoning` parts (HTTP 400 code 20015). The siliconflow capability
361
+ // Some DeepSeek thinking-mode endpoints reject assistant history with
362
+ // `reasoning` parts (HTTP 400 code 20015). A provider capability
351
363
  // override strips them; every other provider's capability is identity.
352
364
  const subMessagesForCall = taskCaps.sanitizeHistory(childMessages);
353
365
  // Phase 4 Plan 04 (4B) — mirror top-level scope-ceiling integration.
@@ -377,8 +389,26 @@ export class StreamRunner {
377
389
  // and is re-armed by stall.pet() on every chunk. Cheap models (which run
378
390
  // mostly as sub-agents via SAMR) hit this most.
379
391
  let stallTriggered = false;
392
+ // Second timer (progressTimeoutMs) is the no-forward-progress guard: the
393
+ // stall timer re-arms on EVERY chunk — including a reasoning model's
394
+ // `reasoning-delta` chunks — so a sub-agent stuck in an endless
395
+ // chain-of-thought keeps petting it and it never fires (observed live
396
+ // 2026-07-10: a deepseek-v4-flash sprint sub-agent churned reasoning for
397
+ // 30+ min, 1.4M input tokens, ZERO text/tool output; the 2-min stall
398
+ // watchdog never tripped). The progress timer is reset ONLY by
399
+ // stall.petProgress() on real output (text-delta / tool-call), so a runaway
400
+ // reasoning loop is aborted while a legitimately long reasoning burst that
401
+ // DOES eventually emit output survives. Both timers abort the same signal
402
+ // and set stallTriggered, so the existing surface-and-return path handles it.
380
403
  const stall = createStallWatchdog(getProviderStallTimeoutMs(), () => {
381
404
  stallTriggered = true;
405
+ }, {
406
+ progressTimeoutMs: getProviderProgressTimeoutMs(),
407
+ onProgressFire: () => {
408
+ stallTriggered = true;
409
+ console.error(`[stream-runner] sub-agent aborted: no text/tool output for ${getProviderProgressTimeoutMs()}ms ` +
410
+ `(runaway reasoning / no forward progress) model=${childRuntime.modelId}`);
411
+ },
382
412
  });
383
413
  const result = streamText({
384
414
  model: childRuntime.model,
@@ -396,11 +426,11 @@ export class StreamRunner {
396
426
  prepareStep: ({ messages, stepNumber }) => {
397
427
  if (stepNumber < 1)
398
428
  return undefined;
399
- // SiliconFlow internal multi-step loop: AI-SDK accumulates streamed
400
- // reasoning parts into in-flight assistant history and re-POSTs them
401
- // on the next step within the same streamText call — orchestrator-
402
- // level strip at call setup never sees this. Strip per step too via
403
- // the capability hook (identity for non-siliconflow providers).
429
+ // Internal multi-step loop: AI-SDK accumulates streamed reasoning
430
+ // parts into in-flight assistant history and re-POSTs them on the
431
+ // next step within the same streamText call — orchestrator-level
432
+ // strip at call setup never sees this. Strip per step too via the
433
+ // capability hook (identity for providers without the quirk).
404
434
  const stripped = taskCaps.sanitizeHistory(messages);
405
435
  // G1 + G2 — pass the sub-agent's model context window so the
406
436
  // compactor can use a token-aware threshold and shrink the keep
@@ -428,17 +458,16 @@ export class StreamRunner {
428
458
  break;
429
459
  }
430
460
  }
431
- // Idea 4 persist for sub-agent elisions (best-effort; may lack full session but EE can still index the artifact content).
432
- const persistSubArtifact = (toolCallId, toolName, fullContent, reason) => {
461
+ const persistSubArtifact = (toolCallId, toolName, fullContent, reason, summary) => {
433
462
  // Local-first durable cache so ee_query rehydrates even when EE is down.
434
463
  recordArtifact(toolCallId, toolName, fullContent);
435
- recordElision(toolCallId, toolName, fullContent.length, stepNumber);
464
+ recordElision(toolCallId, toolName, fullContent.length, stepNumber, summary);
436
465
  try {
437
466
  getDefaultEEClient()
438
467
  .extract({
439
468
  transcript: fullContent.slice(0, 4000),
440
469
  projectPath: process.cwd(),
441
- meta: { source: "tool-artifact", toolCallId, toolName, reason },
470
+ meta: { source: "tool-artifact", toolCallId, toolName, reason, summary },
442
471
  }, AbortSignal.timeout(600))
443
472
  .catch(() => { });
444
473
  }
@@ -494,7 +523,7 @@ export class StreamRunner {
494
523
  return undefined;
495
524
  return { messages: finalMessages };
496
525
  },
497
- ...(childDropTemperature ? {} : { temperature: isExplore ? 0.2 : 0.5 }),
526
+ ...resolveTemperatureParam(childRuntime, isExplore ? 0.2 : 0.5),
498
527
  ...(childDropMaxOutput ? {} : { maxOutputTokens: Math.min(this.deps.getMaxTokens(), 8_192) }),
499
528
  ...(childProviderOptions ? { providerOptions: childProviderOptions } : {}),
500
529
  onFinish: ({ totalUsage, finishReason }) => {
@@ -557,6 +586,7 @@ export class StreamRunner {
557
586
  });
558
587
  }
559
588
  if (part.type === "text-delta") {
589
+ stall.petProgress(); // real forward progress — reset the no-progress guard
560
590
  textDeltaCount++;
561
591
  assistantText += part.text;
562
592
  // Task 2.6b — emit llm-token (agent-mode only; high-volume, default-off per Phase 4).
@@ -576,6 +606,7 @@ export class StreamRunner {
576
606
  continue;
577
607
  }
578
608
  if (part.type === "tool-call") {
609
+ stall.petProgress(); // real forward progress — reset the no-progress guard
579
610
  toolCallCount++;
580
611
  lastActivity = formatSubagentActivity(part.toolName, part.input);
581
612
  onActivity?.(lastActivity);
@@ -653,7 +684,9 @@ export class StreamRunner {
653
684
  ...priorMessages,
654
685
  {
655
686
  role: "user",
656
- content: "You've reached your investigation budget and have not written your findings yet. Stop now — do NOT call any more tools. Write your final synthesis FOR THE PARENT AGENT: lead with the answer to the delegated task, cite the concrete file:line behind each claim, then note any gaps or the recommended next step. Be concise; the parent only ingests this message.",
687
+ content: "You've reached your tool execution budget (max steps) for this turn and have not written your final answer yet. Stop now — do NOT call any more tools.\n\n" +
688
+ "Option A: If you have enough findings, write your final synthesis FOR THE PARENT AGENT: lead with the answer to the delegated task, cite the concrete file:line behind each claim, then note any gaps or the recommended next step. Be concise; the parent only ingests this message.\n\n" +
689
+ "Option B: If you need to continue working but are blocked by this limit, you can request the system to compact the context and start a fresh turn. To do this, reply with EXACTLY this format and nothing else:\n/compact <instructions on what to focus on after compaction>",
657
690
  },
658
691
  ],
659
692
  tools: {},
@@ -18,7 +18,19 @@
18
18
  * returns a fresh wrapper with its own counters. Don't share across
19
19
  * sub-agent runs.
20
20
  *
21
- * Tiers (default 120_000 chars cumulative ~30k tokens):
21
+ * BUDGET SOURCE — do not read the 120_000 below as "the sub-agent budget".
22
+ * DEFAULT_MAX_CUMULATIVE_CHARS (120_000) is only the fallback used when
23
+ * wrapToolSetWithCap() is called WITHOUT maxCumulativeChars. The wired
24
+ * budgets come from settings, not this constant:
25
+ * - sub-agent (`task`) turns: getSubAgentBudgetChars() → default 240_000
26
+ * (settings.ts), passed at stream-runner.ts.
27
+ * - top-level orchestrator turn: getTopLevelToolBudgetChars() → default
28
+ * 400_000, wired at tool-engine.ts with looser 0.5/0.8 tier ratios.
29
+ * See docs/agent-harness/CONTEXT-CONTROL-LAYERS.md for how this cap relates
30
+ * to the other four context-control layers (compactor, rotation, reactive
31
+ * sub-session, top-level cap).
32
+ *
33
+ * Tiers (percentages of whichever budget is in effect, NOT of 120_000):
22
34
  * < 30% → pass through (A1's 32KB per-call cap already applied)
23
35
  * 30-70% → truncate each new result to 8_000 chars head/tail
24
36
  * 70-100% → truncate to 2_000 chars head + "[budget low, finalize work]" note
@@ -18,13 +18,28 @@
18
18
  * returns a fresh wrapper with its own counters. Don't share across
19
19
  * sub-agent runs.
20
20
  *
21
- * Tiers (default 120_000 chars cumulative ~30k tokens):
21
+ * BUDGET SOURCE — do not read the 120_000 below as "the sub-agent budget".
22
+ * DEFAULT_MAX_CUMULATIVE_CHARS (120_000) is only the fallback used when
23
+ * wrapToolSetWithCap() is called WITHOUT maxCumulativeChars. The wired
24
+ * budgets come from settings, not this constant:
25
+ * - sub-agent (`task`) turns: getSubAgentBudgetChars() → default 240_000
26
+ * (settings.ts), passed at stream-runner.ts.
27
+ * - top-level orchestrator turn: getTopLevelToolBudgetChars() → default
28
+ * 400_000, wired at tool-engine.ts with looser 0.5/0.8 tier ratios.
29
+ * See docs/agent-harness/CONTEXT-CONTROL-LAYERS.md for how this cap relates
30
+ * to the other four context-control layers (compactor, rotation, reactive
31
+ * sub-session, top-level cap).
32
+ *
33
+ * Tiers (percentages of whichever budget is in effect, NOT of 120_000):
22
34
  * < 30% → pass through (A1's 32KB per-call cap already applied)
23
35
  * 30-70% → truncate each new result to 8_000 chars head/tail
24
36
  * 70-100% → truncate to 2_000 chars head + "[budget low, finalize work]" note
25
37
  * ≥ 100% → return error stub that signals the agent to stop expanding scope
26
38
  */
27
39
  import { createHash } from "node:crypto";
40
+ // Fallback ONLY — used when wrapToolSetWithCap gets no maxCumulativeChars.
41
+ // Real wired budgets are 240_000 (sub-agent) / 400_000 (top-level) from
42
+ // settings; see the header note. Keep this in sync only as the no-arg floor.
28
43
  const DEFAULT_MAX_CUMULATIVE_CHARS = 120_000;
29
44
  const DEFAULT_DEDUP_MIN_CHARS = 500;
30
45
  const DEFAULT_MID_TIER_RATIO = 0.3;
@@ -9,5 +9,17 @@ export type TierLookup = (tier: "fast" | "balanced" | "premium", preferProvider?
9
9
  * Resolve the model id for a task kind on a given provider. Walks the tier
10
10
  * preference list, accepting only same-provider matches, and falls back to
11
11
  * `fallbackModelId` (the parent model) when nothing matches.
12
+ *
13
+ * `opts.parentTier` (the top-level / parent model's tier) acts as a ceiling:
14
+ * a delegated sub-task never runs on a HIGHER tier than the parent. Without
15
+ * this cap, a `verify` sub-agent (prefs `["premium","balanced"]`) spawned from
16
+ * a flash (fast) parent silently promotes to premium — e.g. on a DeepSeek-only
17
+ * setup (no balanced model) every verify sub-agent lands on deepseek-v4-pro.
18
+ * The parent already did the hard thinking; the sub-task should not exceed it.
19
+ *
20
+ * The cap is skipped when `parentTier` is omitted (preserves legacy behavior
21
+ * for callers that have not been threaded yet).
12
22
  */
13
- export declare function resolveModelForTask(task: ModelTaskKind, providerId: string, fallbackModelId: string, lookup?: TierLookup): string;
23
+ export declare function resolveModelForTask(task: ModelTaskKind, providerId: string, fallbackModelId: string, lookup?: TierLookup, opts?: {
24
+ parentTier?: "fast" | "balanced" | "premium";
25
+ }): string;
@@ -16,7 +16,7 @@
16
16
  * - verify : validation/verification → premium first; rigor matters
17
17
  * more than cost here, so we do NOT downgrade by default.
18
18
  */
19
- import { getModelByTier } from "../models/registry.js";
19
+ import { getRoutedModelByTier } from "../router/peak-hour.js";
20
20
  export const TASK_TIER_PREFS = {
21
21
  compact: ["fast", "balanced"],
22
22
  title: ["fast", "balanced"],
@@ -29,13 +29,27 @@ export const TASK_TIER_PREFS = {
29
29
  // exists to perform. Mirrors council `verify` role preference.
30
30
  verify: ["premium", "balanced"],
31
31
  };
32
+ const TIER_RANK = { fast: 0, balanced: 1, premium: 2 };
32
33
  /**
33
34
  * Resolve the model id for a task kind on a given provider. Walks the tier
34
35
  * preference list, accepting only same-provider matches, and falls back to
35
36
  * `fallbackModelId` (the parent model) when nothing matches.
37
+ *
38
+ * `opts.parentTier` (the top-level / parent model's tier) acts as a ceiling:
39
+ * a delegated sub-task never runs on a HIGHER tier than the parent. Without
40
+ * this cap, a `verify` sub-agent (prefs `["premium","balanced"]`) spawned from
41
+ * a flash (fast) parent silently promotes to premium — e.g. on a DeepSeek-only
42
+ * setup (no balanced model) every verify sub-agent lands on deepseek-v4-pro.
43
+ * The parent already did the hard thinking; the sub-task should not exceed it.
44
+ *
45
+ * The cap is skipped when `parentTier` is omitted (preserves legacy behavior
46
+ * for callers that have not been threaded yet).
36
47
  */
37
- export function resolveModelForTask(task, providerId, fallbackModelId, lookup = getModelByTier) {
48
+ export function resolveModelForTask(task, providerId, fallbackModelId, lookup = getRoutedModelByTier, opts) {
49
+ const ceilingRank = opts?.parentTier ? TIER_RANK[opts.parentTier] : undefined;
38
50
  for (const tier of TASK_TIER_PREFS[task] ?? ["balanced"]) {
51
+ if (ceilingRank !== undefined && TIER_RANK[tier] > ceilingRank)
52
+ continue;
39
53
  const m = lookup(tier, providerId);
40
54
  if (m?.provider === providerId)
41
55
  return m.id;
@@ -95,7 +95,7 @@ export interface SubAgentCompactorOptions {
95
95
  * stub (full raw content available here). Fire-and-forget EE persist under
96
96
  * source:"tool-artifact" so layer3/ee.query can later fetch "full tool result id=xxx".
97
97
  */
98
- persistArtifact?: (toolCallId: string, toolName: string, fullContent: string, reason: string) => void;
98
+ persistArtifact?: (toolCallId: string, toolName: string, fullContent: string, reason: string, summary?: string) => void;
99
99
  /**
100
100
  * T1.1 — strip reasoning parts from old assistant turns (older than
101
101
  * keepLastTurns). Reasoning tokens (CoT / <think>) from prior turns are
@@ -104,6 +104,18 @@ export interface SubAgentCompactorOptions {
104
104
  * models, false otherwise.
105
105
  */
106
106
  stripOldReasoning?: boolean;
107
+ /**
108
+ * O2 — max cumulative chars of the verbatim tail (the last keepLastTurns
109
+ * turns). The G2 shrink is FILL-ratio based, so on a large-context model a
110
+ * read-heavy tail (five 8-30k tool results) stays verbatim at only ~50%
111
+ * fill — pinning every tool round at 60-80k input (measured: July-8 message
112
+ * calls, 83 in the 60-80k bucket = 44% of message-fresh). When set, keepLast
113
+ * is reduced further (floor 2) until the kept tail fits this budget,
114
+ * regardless of fill ratio. High-value results (isHighValueToolResult) are
115
+ * still kept verbatim independently, so only bulk dumps get stubbed.
116
+ * Undefined = off (sub-agent path unchanged).
117
+ */
118
+ tailBudgetChars?: number;
107
119
  }
108
120
  /**
109
121
  * G1 — coarse char→token conversion. The real ratio is provider/tokenizer
@@ -136,6 +148,7 @@ export declare const HIGH_VALUE_MCP_PREFIXES: readonly ["mcp_muonroi-docs__"];
136
148
  */
137
149
  export declare function isHighValueToolResult(toolName: string, preview: string, explicitKeepIds?: Set<string>, toolCallId?: string): boolean;
138
150
  export declare function cumulativeMessageChars(messages: ReadonlyArray<ModelMessage>): number;
151
+ export declare function buildSlimContext(msgs: ModelMessage[]): ModelMessage[];
139
152
  /**
140
153
  * Compact a sub-agent message array in place-like fashion. The input is never
141
154
  * mutated. When compaction actually elides something a NEW array is returned.
@@ -148,6 +161,45 @@ export declare function cumulativeMessageChars(messages: ReadonlyArray<ModelMess
148
161
  * step.
149
162
  */
150
163
  export declare function compactSubAgentMessages(messages: ReadonlyArray<ModelMessage>, opts?: SubAgentCompactorOptions): ModelMessage[];
164
+ /**
165
+ * O3 — compaction hysteresis state, threaded across `prepareStep` calls within
166
+ * a single top-level turn. `frozenCompacted` is the compacted history captured
167
+ * at the last real compaction; `frozenStrippedLen` is the message count of the
168
+ * (un-compacted) history at that moment, so the append delta can be recovered.
169
+ */
170
+ export interface CompactionHysteresisState {
171
+ frozenCompacted: ModelMessage[] | null;
172
+ frozenStrippedLen: number;
173
+ lastCompactTriggerChars: number;
174
+ }
175
+ export declare function initCompactionHysteresisState(): CompactionHysteresisState;
176
+ /**
177
+ * Decide whether to hold the frozen compacted prefix or (re)compact.
178
+ *
179
+ * Re-running the compactor on every step slides the keepLast boundary forward
180
+ * one tool result per step, flipping that result verbatim→stub and breaking the
181
+ * provider prompt-cache prefix at its position — measured as 63% of a real
182
+ * session's FRESH input (session 1afb2728e67a). Between compactions we instead
183
+ * reuse the frozen compacted prefix and append only the messages added since
184
+ * (history is append-only within a turn), keeping the cached prefix byte-stable
185
+ * until cumulative size grows past `lastCompactTriggerChars * hysteresis`.
186
+ *
187
+ * Pure: returns the next state rather than mutating. `hysteresis <= 1.0`
188
+ * disables the freeze (legacy per-step compaction). The delta slice uses the
189
+ * ORIGINAL (pre-compaction) length, so it is correct whether or not the
190
+ * compactor preserves message count.
191
+ */
192
+ export declare function applyCompactionHysteresis(args: {
193
+ stripped: ModelMessage[];
194
+ currChars: number;
195
+ hysteresis: number;
196
+ state: CompactionHysteresisState;
197
+ runCompaction: () => ModelMessage[];
198
+ }): {
199
+ compacted: ModelMessage[];
200
+ didRecompact: boolean;
201
+ state: CompactionHysteresisState;
202
+ };
151
203
  /**
152
204
  * Injects Anthropic prompt caching (cacheControl) into the last message's content
153
205
  * block(s) if the model is Claude (starts with 'claude').