muonroi-cli 1.8.4 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (562) hide show
  1. package/LICENSE +17 -5
  2. package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
  3. package/dist/packages/agent-harness-core/src/driver.js +46 -0
  4. package/dist/packages/agent-harness-core/src/event-filter.js +11 -0
  5. package/dist/packages/agent-harness-core/src/event-redact.js +7 -0
  6. package/dist/packages/agent-harness-core/src/event-tee.d.ts +64 -0
  7. package/dist/packages/agent-harness-core/src/event-tee.js +104 -0
  8. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +25 -0
  9. package/dist/packages/agent-harness-core/src/mcp-server.js +169 -21
  10. package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
  11. package/dist/packages/agent-harness-core/src/protocol.d.ts +90 -4
  12. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  13. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  14. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  15. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  16. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  17. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  18. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  19. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  20. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  21. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  22. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  23. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  24. package/dist/src/agent-harness/mock-model.d.ts +38 -0
  25. package/dist/src/agent-harness/mock-model.js +69 -3
  26. package/dist/src/agent-harness/test-spawn.js +31 -0
  27. package/dist/src/chat/chat-keychain.d.ts +7 -12
  28. package/dist/src/chat/chat-keychain.js +19 -86
  29. package/dist/src/cli/config/screen-providers.js +1 -1
  30. package/dist/src/cli/cost-forensics.d.ts +10 -0
  31. package/dist/src/cli/cost-forensics.js +18 -3
  32. package/dist/src/cli/keys-bundle.d.ts +1 -1
  33. package/dist/src/cli/keys-bundle.js +1 -1
  34. package/dist/src/cli/keys.d.ts +10 -47
  35. package/dist/src/cli/keys.js +31 -399
  36. package/dist/src/council/clarifier.d.ts +31 -3
  37. package/dist/src/council/clarifier.js +220 -32
  38. package/dist/src/council/context.js +49 -15
  39. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  40. package/dist/src/council/debate-checkpoint.js +176 -0
  41. package/dist/src/council/debate-planner.js +54 -5
  42. package/dist/src/council/debate-summary.d.ts +25 -0
  43. package/dist/src/council/debate-summary.js +85 -0
  44. package/dist/src/council/debate.d.ts +169 -2
  45. package/dist/src/council/debate.js +1265 -135
  46. package/dist/src/council/index.d.ts +108 -1
  47. package/dist/src/council/index.js +670 -197
  48. package/dist/src/council/leader.d.ts +26 -0
  49. package/dist/src/council/leader.js +150 -9
  50. package/dist/src/council/llm.d.ts +94 -0
  51. package/dist/src/council/llm.js +348 -55
  52. package/dist/src/council/panel-select.d.ts +30 -0
  53. package/dist/src/council/panel-select.js +82 -0
  54. package/dist/src/council/planner.js +40 -0
  55. package/dist/src/council/preflight.d.ts +17 -0
  56. package/dist/src/council/preflight.js +50 -2
  57. package/dist/src/council/prompts.d.ts +39 -4
  58. package/dist/src/council/prompts.js +256 -69
  59. package/dist/src/council/stance-recall.d.ts +42 -0
  60. package/dist/src/council/stance-recall.js +57 -0
  61. package/dist/src/council/strip-think.d.ts +17 -0
  62. package/dist/src/council/strip-think.js +33 -0
  63. package/dist/src/council/types.d.ts +138 -0
  64. package/dist/src/ee/artifact-cache.d.ts +16 -0
  65. package/dist/src/ee/artifact-cache.js +32 -0
  66. package/dist/src/ee/auth.d.ts +20 -0
  67. package/dist/src/ee/auth.js +54 -2
  68. package/dist/src/ee/bridge.d.ts +10 -0
  69. package/dist/src/ee/bridge.js +58 -0
  70. package/dist/src/ee/client.js +109 -21
  71. package/dist/src/ee/ee-onboarding.js +6 -26
  72. package/dist/src/ee/export-transcripts.d.ts +1 -0
  73. package/dist/src/ee/export-transcripts.js +8 -10
  74. package/dist/src/ee/extract-session.js +29 -0
  75. package/dist/src/ee/extract-style.d.ts +58 -0
  76. package/dist/src/ee/extract-style.js +270 -0
  77. package/dist/src/ee/recall-ledger.d.ts +9 -0
  78. package/dist/src/ee/recall-ledger.js +3 -0
  79. package/dist/src/ee/scope.d.ts +1 -0
  80. package/dist/src/ee/scope.js +26 -1
  81. package/dist/src/ee/search.d.ts +7 -0
  82. package/dist/src/ee/search.js +24 -0
  83. package/dist/src/ee/transcript-emit.js +2 -0
  84. package/dist/src/ee/types.d.ts +22 -0
  85. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  86. package/dist/src/ee/who-am-i-brain.js +220 -0
  87. package/dist/src/ee/who-am-i.d.ts +10 -3
  88. package/dist/src/ee/who-am-i.js +12 -0
  89. package/dist/src/ee/workflow-event.d.ts +48 -0
  90. package/dist/src/ee/workflow-event.js +81 -0
  91. package/dist/src/flow/compaction/compress.d.ts +3 -3
  92. package/dist/src/flow/compaction/compress.js +58 -8
  93. package/dist/src/flow/compaction/extract.d.ts +4 -7
  94. package/dist/src/flow/compaction/extract.js +50 -10
  95. package/dist/src/flow/compaction/index.d.ts +14 -1
  96. package/dist/src/flow/compaction/index.js +96 -3
  97. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  98. package/dist/src/flow/compaction/input-guard.js +43 -0
  99. package/dist/src/flow/compaction/progress.d.ts +35 -0
  100. package/dist/src/flow/compaction/progress.js +35 -0
  101. package/dist/src/flow/fold-planning.d.ts +36 -0
  102. package/dist/src/flow/fold-planning.js +83 -0
  103. package/dist/src/flow/hierarchy.d.ts +146 -0
  104. package/dist/src/flow/hierarchy.js +427 -0
  105. package/dist/src/flow/index.d.ts +1 -0
  106. package/dist/src/flow/index.js +2 -0
  107. package/dist/src/flow/run-artifacts.d.ts +102 -0
  108. package/dist/src/flow/run-artifacts.js +208 -0
  109. package/dist/src/generated/version.d.ts +1 -1
  110. package/dist/src/generated/version.js +1 -1
  111. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  112. package/dist/src/gsd/assessment-schema.js +134 -0
  113. package/dist/src/gsd/capability-registry.d.ts +45 -0
  114. package/dist/src/gsd/capability-registry.js +337 -0
  115. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  116. package/dist/src/gsd/complexity-assessor.js +152 -0
  117. package/dist/src/gsd/config-bridge.d.ts +7 -0
  118. package/dist/src/gsd/config-bridge.js +114 -0
  119. package/dist/src/gsd/config-loader.d.ts +27 -0
  120. package/dist/src/gsd/config-loader.js +50 -0
  121. package/dist/src/gsd/council-context.d.ts +44 -0
  122. package/dist/src/gsd/council-context.js +114 -0
  123. package/dist/src/gsd/ee-closure.d.ts +28 -0
  124. package/dist/src/gsd/ee-closure.js +49 -0
  125. package/dist/src/gsd/flags.d.ts +66 -0
  126. package/dist/src/gsd/flags.js +102 -0
  127. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  128. package/dist/src/gsd/gsd-dispatch.js +131 -0
  129. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  130. package/dist/src/gsd/gsd-runtime.js +37 -0
  131. package/dist/src/gsd/host-adapter.d.ts +11 -0
  132. package/dist/src/gsd/host-adapter.js +29 -0
  133. package/dist/src/gsd/index.d.ts +24 -1
  134. package/dist/src/gsd/index.js +27 -0
  135. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  136. package/dist/src/gsd/loop-host-contract.js +39 -0
  137. package/dist/src/gsd/loop-host.d.ts +69 -0
  138. package/dist/src/gsd/loop-host.js +245 -0
  139. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  140. package/dist/src/gsd/loop-resolver.js +79 -0
  141. package/dist/src/gsd/model-tier.d.ts +13 -0
  142. package/dist/src/gsd/model-tier.js +45 -0
  143. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  144. package/dist/src/gsd/mutation-gate.js +41 -0
  145. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  146. package/dist/src/gsd/native-roadmap.js +343 -0
  147. package/dist/src/gsd/native-state.d.ts +47 -0
  148. package/dist/src/gsd/native-state.js +220 -0
  149. package/dist/src/gsd/paths.d.ts +23 -0
  150. package/dist/src/gsd/paths.js +66 -0
  151. package/dist/src/gsd/phase-dag.d.ts +12 -0
  152. package/dist/src/gsd/phase-dag.js +94 -0
  153. package/dist/src/gsd/phase-sync.d.ts +42 -0
  154. package/dist/src/gsd/phase-sync.js +321 -0
  155. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  156. package/dist/src/gsd/pil-gate-context.js +64 -0
  157. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  158. package/dist/src/gsd/pil-gate-critic.js +74 -0
  159. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  160. package/dist/src/gsd/plan-council-prompts.js +79 -0
  161. package/dist/src/gsd/plan-council.d.ts +44 -0
  162. package/dist/src/gsd/plan-council.js +283 -0
  163. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  164. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  165. package/dist/src/gsd/product-workspace.d.ts +13 -0
  166. package/dist/src/gsd/product-workspace.js +124 -0
  167. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  168. package/dist/src/gsd/ship-bridge.js +65 -0
  169. package/dist/src/gsd/state-document.d.ts +40 -0
  170. package/dist/src/gsd/state-document.js +163 -0
  171. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  172. package/dist/src/gsd/verdict-schema.js +144 -0
  173. package/dist/src/gsd/verify-context.d.ts +22 -0
  174. package/dist/src/gsd/verify-context.js +27 -0
  175. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  176. package/dist/src/gsd/verify-council-prompts.js +85 -0
  177. package/dist/src/gsd/verify-council.d.ts +25 -0
  178. package/dist/src/gsd/verify-council.js +119 -0
  179. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  180. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  181. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  182. package/dist/src/gsd/workflow-engine.js +207 -0
  183. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  184. package/dist/src/gsd/workflow-tools.js +277 -0
  185. package/dist/src/headless/council-answers.js +4 -0
  186. package/dist/src/hooks/index.js +1 -1
  187. package/dist/src/index.js +172 -270
  188. package/dist/src/lsp/builtins.js +3 -1
  189. package/dist/src/lsp/manager.d.ts +5 -1
  190. package/dist/src/lsp/manager.js +249 -3
  191. package/dist/src/lsp/npm-cache.d.ts +11 -1
  192. package/dist/src/lsp/npm-cache.js +17 -1
  193. package/dist/src/lsp/runtime.d.ts +6 -1
  194. package/dist/src/lsp/runtime.js +17 -1
  195. package/dist/src/lsp/types.d.ts +83 -1
  196. package/dist/src/lsp/types.js +10 -0
  197. package/dist/src/maintain/pr-builder.js +23 -13
  198. package/dist/src/mcp/auto-setup.js +57 -32
  199. package/dist/src/mcp/client-pool.js +44 -16
  200. package/dist/src/mcp/lsp-tools.d.ts +5 -1
  201. package/dist/src/mcp/lsp-tools.js +93 -2
  202. package/dist/src/mcp/mcp-keychain.d.ts +3 -5
  203. package/dist/src/mcp/mcp-keychain.js +9 -49
  204. package/dist/src/mcp/research-onboarding.js +8 -7
  205. package/dist/src/mcp/runtime.js +34 -2
  206. package/dist/src/mcp/setup-guide-text.d.ts +1 -1
  207. package/dist/src/mcp/setup-guide-text.js +22 -2
  208. package/dist/src/mcp/tools-server.d.ts +10 -0
  209. package/dist/src/mcp/tools-server.js +10 -2
  210. package/dist/src/models/catalog-client.d.ts +87 -0
  211. package/dist/src/models/catalog-client.js +105 -38
  212. package/dist/src/models/catalog.json +528 -265
  213. package/dist/src/models/registry.d.ts +22 -7
  214. package/dist/src/models/registry.js +73 -10
  215. package/dist/src/ops/doctor.js +1 -1
  216. package/dist/src/orchestrator/ask-user.d.ts +61 -0
  217. package/dist/src/orchestrator/ask-user.js +65 -0
  218. package/dist/src/orchestrator/auto-commit.js +1 -1
  219. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  220. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  221. package/dist/src/orchestrator/cache-prefix.js +83 -0
  222. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  223. package/dist/src/orchestrator/compact-request.js +41 -0
  224. package/dist/src/orchestrator/compaction.d.ts +12 -3
  225. package/dist/src/orchestrator/compaction.js +35 -15
  226. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  227. package/dist/src/orchestrator/council-manager.js +74 -32
  228. package/dist/src/orchestrator/council-request.d.ts +49 -0
  229. package/dist/src/orchestrator/council-request.js +62 -0
  230. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  231. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  232. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  233. package/dist/src/orchestrator/error-utils.js +132 -24
  234. package/dist/src/orchestrator/grounding-check.js +39 -1
  235. package/dist/src/orchestrator/interactive-pause.d.ts +26 -0
  236. package/dist/src/orchestrator/interactive-pause.js +36 -0
  237. package/dist/src/orchestrator/message-processor.d.ts +4 -0
  238. package/dist/src/orchestrator/message-processor.js +268 -41
  239. package/dist/src/orchestrator/orchestrator.d.ts +64 -3
  240. package/dist/src/orchestrator/orchestrator.js +823 -120
  241. package/dist/src/orchestrator/preprocessor.js +3 -3
  242. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  243. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  244. package/dist/src/orchestrator/prompts.js +17 -17
  245. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  246. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  247. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  248. package/dist/src/orchestrator/retry-classifier.js +46 -2
  249. package/dist/src/orchestrator/safety-askcard.d.ts +1 -1
  250. package/dist/src/orchestrator/safety-askcard.js +5 -2
  251. package/dist/src/orchestrator/safety-intercept.d.ts +50 -0
  252. package/dist/src/orchestrator/safety-intercept.js +62 -0
  253. package/dist/src/orchestrator/scope-reminder.js +1 -1
  254. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  255. package/dist/src/orchestrator/session-experience.js +2 -1
  256. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  257. package/dist/src/orchestrator/should-run-gate.js +18 -0
  258. package/dist/src/orchestrator/stall-watchdog.d.ts +31 -3
  259. package/dist/src/orchestrator/stall-watchdog.js +65 -10
  260. package/dist/src/orchestrator/stream-runner.d.ts +13 -3
  261. package/dist/src/orchestrator/stream-runner.js +115 -49
  262. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  263. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  264. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  265. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  266. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  267. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  268. package/dist/src/orchestrator/tool-engine.d.ts +41 -0
  269. package/dist/src/orchestrator/tool-engine.js +846 -66
  270. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  271. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  272. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  273. package/dist/src/orchestrator/turn-watchdog.d.ts +44 -0
  274. package/dist/src/orchestrator/turn-watchdog.js +84 -0
  275. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  276. package/dist/src/pil/agent-operating-contract.js +6 -4
  277. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  278. package/dist/src/pil/cheap-model-playbook.js +5 -1
  279. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  280. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  281. package/dist/src/pil/discovery-types.d.ts +1 -0
  282. package/dist/src/pil/discovery.d.ts +1 -1
  283. package/dist/src/pil/discovery.js +18 -13
  284. package/dist/src/pil/layer1-intent.d.ts +18 -6
  285. package/dist/src/pil/layer1-intent.js +66 -757
  286. package/dist/src/pil/layer15-context-scan.js +15 -1
  287. package/dist/src/pil/layer1_5-complexity-size.d.ts +7 -0
  288. package/dist/src/pil/layer1_5-complexity-size.js +31 -5
  289. package/dist/src/pil/layer3-ee-injection.js +23 -8
  290. package/dist/src/pil/layer4-gsd.js +69 -16
  291. package/dist/src/pil/layer5-context.js +7 -3
  292. package/dist/src/pil/layer6-output.d.ts +23 -0
  293. package/dist/src/pil/layer6-output.js +5 -1
  294. package/dist/src/pil/llm-classify.d.ts +111 -5
  295. package/dist/src/pil/llm-classify.js +421 -189
  296. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  297. package/dist/src/pil/native-capabilities-workbook.js +8 -0
  298. package/dist/src/pil/pipeline.js +36 -2
  299. package/dist/src/pil/repo-grounding-probe.d.ts +15 -0
  300. package/dist/src/pil/repo-grounding-probe.js +136 -0
  301. package/dist/src/pil/repo-structure-hints.d.ts +7 -0
  302. package/dist/src/pil/repo-structure-hints.js +45 -0
  303. package/dist/src/pil/response-tools.js +5 -3
  304. package/dist/src/pil/schema.d.ts +1 -0
  305. package/dist/src/pil/schema.js +2 -0
  306. package/dist/src/pil/types.d.ts +18 -0
  307. package/dist/src/playbook/directives.d.ts +4 -0
  308. package/dist/src/playbook/directives.js +17 -5
  309. package/dist/src/product-loop/artifact-io.js +4 -0
  310. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  311. package/dist/src/product-loop/backlog-builder.js +30 -6
  312. package/dist/src/product-loop/criteria-seed.d.ts +51 -0
  313. package/dist/src/product-loop/criteria-seed.js +200 -0
  314. package/dist/src/product-loop/discovery-context-format.js +3 -1
  315. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  316. package/dist/src/product-loop/discovery-interview.d.ts +9 -0
  317. package/dist/src/product-loop/discovery-interview.js +60 -12
  318. package/dist/src/product-loop/discovery-recommender.js +2 -1
  319. package/dist/src/product-loop/discovery-schema.js +19 -2
  320. package/dist/src/product-loop/discovery-triage.d.ts +23 -0
  321. package/dist/src/product-loop/discovery-triage.js +109 -0
  322. package/dist/src/product-loop/gather.js +150 -2
  323. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  324. package/dist/src/product-loop/ideal-trace.js +64 -0
  325. package/dist/src/product-loop/index.d.ts +13 -1
  326. package/dist/src/product-loop/index.js +340 -52
  327. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  328. package/dist/src/product-loop/loop-driver.js +330 -106
  329. package/dist/src/product-loop/phase-plan.d.ts +21 -0
  330. package/dist/src/product-loop/phase-plan.js +81 -6
  331. package/dist/src/product-loop/phase-rituals.d.ts +3 -0
  332. package/dist/src/product-loop/phase-rituals.js +8 -3
  333. package/dist/src/product-loop/phase-runner.js +39 -12
  334. package/dist/src/product-loop/plan-adherence-review.d.ts +26 -0
  335. package/dist/src/product-loop/plan-adherence-review.js +144 -0
  336. package/dist/src/product-loop/sprint-runner.d.ts +173 -0
  337. package/dist/src/product-loop/sprint-runner.js +863 -19
  338. package/dist/src/product-loop/types.d.ts +61 -5
  339. package/dist/src/providers/adapter.d.ts +1 -1
  340. package/dist/src/providers/adapter.js +3 -4
  341. package/dist/src/providers/anthropic.d.ts +9 -8
  342. package/dist/src/providers/anthropic.js +13 -47
  343. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  344. package/dist/src/providers/auth/browser-flow.js +1 -1
  345. package/dist/src/providers/auth/grok-oauth.d.ts +1 -0
  346. package/dist/src/providers/auth/grok-oauth.js +30 -5
  347. package/dist/src/providers/auth/openai-oauth.d.ts +1 -0
  348. package/dist/src/providers/auth/openai-oauth.js +15 -1
  349. package/dist/src/providers/auth/registry.js +0 -34
  350. package/dist/src/providers/auth/token-store.d.ts +9 -9
  351. package/dist/src/providers/auth/token-store.js +8 -67
  352. package/dist/src/providers/auth/types.d.ts +9 -1
  353. package/dist/src/providers/auth/types.js +1 -1
  354. package/dist/src/providers/capabilities.d.ts +24 -5
  355. package/dist/src/providers/capabilities.js +42 -24
  356. package/dist/src/providers/endpoints.d.ts +2 -2
  357. package/dist/src/providers/endpoints.js +11 -10
  358. package/dist/src/providers/env-store.d.ts +17 -0
  359. package/dist/src/providers/env-store.js +228 -0
  360. package/dist/src/providers/keychain.d.ts +22 -18
  361. package/dist/src/providers/keychain.js +127 -140
  362. package/dist/src/providers/mcp-vision-bridge.js +56 -146
  363. package/dist/src/providers/openai-compatible.js +8 -1
  364. package/dist/src/providers/pricing.d.ts +2 -2
  365. package/dist/src/providers/pricing.js +3 -13
  366. package/dist/src/providers/runtime.d.ts +43 -3
  367. package/dist/src/providers/runtime.js +88 -14
  368. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  369. package/dist/src/providers/strategies/base.strategy.js +24 -1
  370. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  371. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  372. package/dist/src/providers/strategies/registry.js +4 -4
  373. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  374. package/dist/src/providers/strategies/thinking-mode.js +288 -1
  375. package/dist/src/providers/strategies/xai.strategy.js +27 -0
  376. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  377. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  378. package/dist/src/providers/types.d.ts +5 -6
  379. package/dist/src/providers/types.js +2 -2
  380. package/dist/src/providers/vision-backend.d.ts +47 -0
  381. package/dist/src/providers/vision-backend.js +258 -0
  382. package/dist/src/providers/vision-proxy.d.ts +22 -9
  383. package/dist/src/providers/vision-proxy.js +63 -132
  384. package/dist/src/providers/warm.d.ts +65 -0
  385. package/dist/src/providers/warm.js +145 -0
  386. package/dist/src/providers/wire-debug.js +95 -0
  387. package/dist/src/router/decide.d.ts +13 -0
  388. package/dist/src/router/decide.js +138 -36
  389. package/dist/src/router/peak-hour.d.ts +38 -0
  390. package/dist/src/router/peak-hour.js +107 -0
  391. package/dist/src/router/step-router.js +3 -2
  392. package/dist/src/router/warm.js +4 -5
  393. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  394. package/dist/src/scaffold/continuation-prompt.js +26 -0
  395. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  396. package/dist/src/scaffold/point-to-existing.js +25 -0
  397. package/dist/src/self-qa/agentic-loop.js +6 -5
  398. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  399. package/dist/src/{ui/state → state}/active-run.js +21 -0
  400. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  401. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  402. package/dist/src/state/turn-trace.d.ts +43 -0
  403. package/dist/src/state/turn-trace.js +32 -0
  404. package/dist/src/storage/db.js +2 -1
  405. package/dist/src/storage/index.d.ts +1 -1
  406. package/dist/src/storage/index.js +1 -1
  407. package/dist/src/storage/interaction-log.d.ts +1 -1
  408. package/dist/src/storage/migrations.js +71 -1
  409. package/dist/src/storage/sessions.d.ts +28 -10
  410. package/dist/src/storage/sessions.js +78 -21
  411. package/dist/src/storage/transcript-view.js +1 -1
  412. package/dist/src/storage/transcript.d.ts +51 -0
  413. package/dist/src/storage/transcript.js +340 -15
  414. package/dist/src/tools/file.d.ts +15 -0
  415. package/dist/src/tools/file.js +32 -0
  416. package/dist/src/tools/git-safety.d.ts +19 -0
  417. package/dist/src/tools/git-safety.js +168 -0
  418. package/dist/src/tools/native-tools.d.ts +1 -1
  419. package/dist/src/tools/native-tools.js +81 -1
  420. package/dist/src/tools/registry.d.ts +20 -0
  421. package/dist/src/tools/registry.js +576 -23
  422. package/dist/src/tools/research.d.ts +29 -0
  423. package/dist/src/tools/research.js +233 -0
  424. package/dist/src/types/index.d.ts +147 -4
  425. package/dist/src/ui/app.js +0 -0
  426. package/dist/src/ui/cards/product-status-card.js +1 -1
  427. package/dist/src/ui/components/agent-rail-activities.d.ts +26 -0
  428. package/dist/src/ui/components/agent-rail-activities.js +47 -0
  429. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  430. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  431. package/dist/src/ui/components/compact-progress-card.d.ts +24 -0
  432. package/dist/src/ui/components/compact-progress-card.js +42 -0
  433. package/dist/src/ui/components/context-rail.d.ts +26 -0
  434. package/dist/src/ui/components/context-rail.js +33 -0
  435. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  436. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  437. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  438. package/dist/src/ui/components/council-debate-pill.js +34 -0
  439. package/dist/src/ui/components/council-info-card.js +2 -2
  440. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  441. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  442. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  443. package/dist/src/ui/components/council-message-bubble.js +16 -15
  444. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  445. package/dist/src/ui/components/council-phase-timeline.js +66 -17
  446. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  447. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  448. package/dist/src/ui/components/council-question-card.js +13 -12
  449. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  450. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  451. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  452. package/dist/src/ui/components/council-round-group.js +88 -0
  453. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  454. package/dist/src/ui/components/council-status-list.js +36 -24
  455. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  456. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  457. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  458. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  459. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  460. package/dist/src/ui/components/message-view.d.ts +15 -0
  461. package/dist/src/ui/components/message-view.js +50 -1
  462. package/dist/src/ui/components/prompt-box.js +18 -16
  463. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  464. package/dist/src/ui/components/session-tree-card.js +46 -0
  465. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  466. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  467. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  468. package/dist/src/ui/components/task-list-panel.js +22 -2
  469. package/dist/src/ui/components/tool-group.d.ts +15 -3
  470. package/dist/src/ui/components/tool-group.js +69 -11
  471. package/dist/src/ui/containers/modals-layer.d.ts +4 -2
  472. package/dist/src/ui/containers/modals-layer.js +2 -2
  473. package/dist/src/ui/council-harness-event.d.ts +57 -0
  474. package/dist/src/ui/council-harness-event.js +46 -0
  475. package/dist/src/ui/heartbeat-debug.d.ts +29 -0
  476. package/dist/src/ui/heartbeat-debug.js +45 -0
  477. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  478. package/dist/src/ui/mcp-modal.js +2 -4
  479. package/dist/src/ui/modals/api-key-modal.js +1 -1
  480. package/dist/src/ui/modals/connect-modal.js +4 -3
  481. package/dist/src/ui/modals/model-picker-modal.d.ts +8 -18
  482. package/dist/src/ui/modals/model-picker-modal.js +8 -10
  483. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  484. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  485. package/dist/src/ui/picker-providers.d.ts +1 -1
  486. package/dist/src/ui/picker-providers.js +1 -1
  487. package/dist/src/ui/primitives/index.d.ts +1 -0
  488. package/dist/src/ui/primitives/index.js +2 -0
  489. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  490. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  491. package/dist/src/ui/slash/compact.js +5 -7
  492. package/dist/src/ui/slash/cost.js +1 -1
  493. package/dist/src/ui/slash/council.js +19 -1
  494. package/dist/src/ui/slash/debug.d.ts +3 -31
  495. package/dist/src/ui/slash/debug.js +9 -20
  496. package/dist/src/ui/slash/ee.js +81 -0
  497. package/dist/src/ui/slash/ideal.d.ts +6 -2
  498. package/dist/src/ui/slash/ideal.js +97 -7
  499. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  500. package/dist/src/ui/slash/menu-items.js +23 -20
  501. package/dist/src/ui/slash/registry.d.ts +2 -0
  502. package/dist/src/ui/slash/registry.js +4 -0
  503. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  504. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  505. package/dist/src/ui/status-bar/index.d.ts +1 -1
  506. package/dist/src/ui/status-bar/index.js +7 -3
  507. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  508. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  509. package/dist/src/ui/theme.d.ts +1 -0
  510. package/dist/src/ui/theme.js +2 -0
  511. package/dist/src/ui/types.d.ts +7 -0
  512. package/dist/src/ui/use-app-logic.js +0 -0
  513. package/dist/src/ui/utils/agent-activities.d.ts +39 -0
  514. package/dist/src/ui/utils/agent-activities.js +96 -0
  515. package/dist/src/ui/utils/format.d.ts +14 -0
  516. package/dist/src/ui/utils/format.js +23 -3
  517. package/dist/src/ui/utils/group-tool-entries.d.ts +26 -0
  518. package/dist/src/ui/utils/group-tool-entries.js +111 -0
  519. package/dist/src/ui/utils/tool-summary.d.ts +21 -0
  520. package/dist/src/ui/utils/tool-summary.js +91 -0
  521. package/dist/src/usage/downgrade.js +2 -2
  522. package/dist/src/usage/product-ledger.js +2 -2
  523. package/dist/src/utils/event-loop-monitor.d.ts +85 -0
  524. package/dist/src/utils/event-loop-monitor.js +107 -0
  525. package/dist/src/utils/install-manager.js +2 -1
  526. package/dist/src/utils/llm-deadline.d.ts +14 -0
  527. package/dist/src/utils/llm-deadline.js +19 -0
  528. package/dist/src/utils/logger.js +2 -2
  529. package/dist/src/utils/loop-profiler.d.ts +102 -0
  530. package/dist/src/utils/loop-profiler.js +202 -0
  531. package/dist/src/utils/permission-mode.js +5 -3
  532. package/dist/src/utils/redactor.js +1 -1
  533. package/dist/src/utils/settings.d.ts +180 -5
  534. package/dist/src/utils/settings.js +271 -31
  535. package/dist/src/utils/side-question.d.ts +1 -2
  536. package/dist/src/utils/side-question.js +2 -2
  537. package/dist/src/utils/visible-retry.d.ts +11 -0
  538. package/dist/src/utils/visible-retry.js +10 -1
  539. package/dist/src/verify/entrypoint.d.ts +1 -1
  540. package/dist/src/verify/entrypoint.js +52 -17
  541. package/dist/src/verify/orchestrator.d.ts +1 -1
  542. package/dist/src/verify/orchestrator.js +20 -3
  543. package/dist/src/verify/recipes.d.ts +13 -0
  544. package/dist/src/verify/recipes.js +15 -0
  545. package/package.json +134 -132
  546. package/dist/src/cli/bw-vault.d.ts +0 -55
  547. package/dist/src/cli/bw-vault.js +0 -133
  548. package/dist/src/mcp/ee-tools.d.ts +0 -46
  549. package/dist/src/mcp/ee-tools.js +0 -193
  550. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  551. package/dist/src/providers/auth/gcloud.js +0 -102
  552. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  553. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  554. package/dist/src/providers/gemini.d.ts +0 -11
  555. package/dist/src/providers/gemini.js +0 -45
  556. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  557. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  558. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  559. package/dist/src/providers/strategies/google.strategy.js +0 -174
  560. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  561. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  562. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -0,0 +1,29 @@
1
+ /**
2
+ * src/tools/research.ts
3
+ *
4
+ * Native research tools for the inner agent.
5
+ *
6
+ * These replace the previous external MCP servers (fetch, tavily, and eventually
7
+ * context7 / muonroi-docs) so that web/docs lookup and search are:
8
+ * - Always available without spawn / warmup / "Connection closed"
9
+ * - Subject to the same permission, capping, redaction and cost rules as other builtins
10
+ * - Fast and reliable on first turn
11
+ *
12
+ * memory and playwright were removed from defaults (see auto-setup.ts).
13
+ * Full browser automation (playwright) can still be added manually if needed.
14
+ */
15
+ import { type ToolSet } from "ai";
16
+ export interface FetchUrlOptions {
17
+ format?: "markdown" | "text" | "html";
18
+ /** Max characters to return (soft cap) */
19
+ maxChars?: number;
20
+ }
21
+ export declare function fetchUrl(url: string, opts?: FetchUrlOptions): Promise<string>;
22
+ export interface WebSearchOptions {
23
+ maxResults?: number;
24
+ /** Optional override; otherwise loaded from keychain or TAVILY_API_KEY */
25
+ apiKey?: string;
26
+ }
27
+ export declare function webSearch(query: string, opts?: WebSearchOptions): Promise<string>;
28
+ /** Register the native research tools into the provided ToolSet. */
29
+ export declare function registerNativeResearchTools(tools: ToolSet): ToolSet;
@@ -0,0 +1,233 @@
1
+ /**
2
+ * src/tools/research.ts
3
+ *
4
+ * Native research tools for the inner agent.
5
+ *
6
+ * These replace the previous external MCP servers (fetch, tavily, and eventually
7
+ * context7 / muonroi-docs) so that web/docs lookup and search are:
8
+ * - Always available without spawn / warmup / "Connection closed"
9
+ * - Subject to the same permission, capping, redaction and cost rules as other builtins
10
+ * - Fast and reliable on first turn
11
+ *
12
+ * memory and playwright were removed from defaults (see auto-setup.ts).
13
+ * Full browser automation (playwright) can still be added manually if needed.
14
+ */
15
+ import { dynamicTool, jsonSchema } from "ai";
16
+ import TurndownService from "turndown";
17
+ import { getMcpKey } from "../mcp/mcp-keychain.js";
18
+ const turndown = new TurndownService({
19
+ headingStyle: "atx",
20
+ codeBlockStyle: "fenced",
21
+ bulletListMarker: "-",
22
+ });
23
+ // Basic cleanup for HTML before turndown (remove scripts, styles, etc.)
24
+ function sanitizeForMarkdown(html) {
25
+ return html
26
+ .replace(/<script[\s\S]*?<\/script>/gi, "")
27
+ .replace(/<style[\s\S]*?<\/style>/gi, "")
28
+ .replace(/<noscript[\s\S]*?<\/noscript>/gi, "")
29
+ .replace(/<!--[\s\S]*?-->/g, "");
30
+ }
31
+ function extractTitle(html) {
32
+ const m = html.match(/<title[^>]*>([^<]+)<\/title>/i);
33
+ return m ? m[1].trim() : undefined;
34
+ }
35
+ export async function fetchUrl(url, opts = {}) {
36
+ const { format = "markdown", maxChars = 12000 } = opts;
37
+ const controller = new AbortController();
38
+ const timeout = setTimeout(() => controller.abort(), 15000);
39
+ try {
40
+ const res = await fetch(url, {
41
+ signal: controller.signal,
42
+ headers: {
43
+ "User-Agent": "muonroi-cli/1.0 (+https://github.com/muonroi/muonroi-cli)",
44
+ Accept: "text/html,application/xhtml+xml,application/json,text/plain,*/*",
45
+ },
46
+ redirect: "follow",
47
+ });
48
+ if (!res.ok) {
49
+ return `ERROR fetch_failed: HTTP ${res.status} ${res.statusText} for ${url}`;
50
+ }
51
+ const contentType = res.headers.get("content-type") || "";
52
+ let body = await res.text();
53
+ if (format === "html") {
54
+ return body.length > maxChars ? body.slice(0, maxChars) + "\n... [truncated]" : body;
55
+ }
56
+ if (contentType.includes("application/json")) {
57
+ try {
58
+ const obj = JSON.parse(body);
59
+ body = JSON.stringify(obj, null, 2);
60
+ }
61
+ catch { }
62
+ return body.length > maxChars ? body.slice(0, maxChars) + "\n... [truncated]" : body;
63
+ }
64
+ // Treat as HTML or plain text
65
+ const isHtml = /<\/?[a-z][\s\S]*>/i.test(body) || contentType.includes("html");
66
+ if (format === "text") {
67
+ // Very lightweight text extraction
68
+ const text = isHtml
69
+ ? body
70
+ .replace(/<[^>]+>/g, " ")
71
+ .replace(/\s+/g, " ")
72
+ .trim()
73
+ : body;
74
+ return text.length > maxChars ? text.slice(0, maxChars) + "\n... [truncated]" : text;
75
+ }
76
+ // markdown (default)
77
+ if (isHtml) {
78
+ const cleaned = sanitizeForMarkdown(body);
79
+ const title = extractTitle(body);
80
+ let md = turndown.turndown(cleaned);
81
+ if (title && !md.startsWith("# ")) {
82
+ md = `# ${title}\n\n${md}`;
83
+ }
84
+ if (md.length > maxChars) {
85
+ md = md.slice(0, maxChars) + "\n\n... [truncated — use more specific URL or smaller scope]";
86
+ }
87
+ // Add source
88
+ return `${md}\n\n_Source: ${url}_`;
89
+ }
90
+ // Plain text → code block or just return
91
+ const out = body.length > maxChars ? body.slice(0, maxChars) + "\n... [truncated]" : body;
92
+ return `\`\`\`\n${out}\n\`\`\`\n\n_Source: ${url}_`;
93
+ }
94
+ catch (err) {
95
+ if (err?.name === "AbortError") {
96
+ return `ERROR fetch_timeout: timed out after 15s fetching ${url}`;
97
+ }
98
+ return `ERROR fetch_error: ${err instanceof Error ? err.message : String(err)}`;
99
+ }
100
+ finally {
101
+ clearTimeout(timeout);
102
+ }
103
+ }
104
+ export async function webSearch(query, opts = {}) {
105
+ const maxResults = Math.max(1, Math.min(opts.maxResults ?? 8, 20));
106
+ let key = opts.apiKey;
107
+ if (!key) {
108
+ key = (await getMcpKey("tavily")) || process.env.TAVILY_API_KEY || "";
109
+ }
110
+ if (!key || key.length < 10) {
111
+ return ("ERROR no_tavily_key: Tavily API key is required for web_search. " +
112
+ "Run `muonroi-cli mcp setup-research` or set TAVILY_API_KEY. " +
113
+ "You can also use `fetch_url` for direct URLs.");
114
+ }
115
+ const controller = new AbortController();
116
+ const timeout = setTimeout(() => controller.abort(), 12000);
117
+ try {
118
+ const res = await fetch("https://api.tavily.com/search", {
119
+ method: "POST",
120
+ signal: controller.signal,
121
+ headers: {
122
+ "Content-Type": "application/json",
123
+ },
124
+ body: JSON.stringify({
125
+ api_key: key,
126
+ query,
127
+ max_results: maxResults,
128
+ include_answer: true,
129
+ include_raw_content: false,
130
+ search_depth: "basic",
131
+ }),
132
+ });
133
+ if (!res.ok) {
134
+ const text = await res.text().catch(() => "");
135
+ return `ERROR tavily_http_${res.status}: ${text.slice(0, 300)}`;
136
+ }
137
+ const data = await res.json();
138
+ const lines = [];
139
+ if (data.answer) {
140
+ lines.push("**Answer summary:**");
141
+ lines.push(data.answer);
142
+ lines.push("");
143
+ }
144
+ const results = Array.isArray(data.results) ? data.results : [];
145
+ if (results.length === 0) {
146
+ return "No web results found.";
147
+ }
148
+ lines.push(`**Web results** (top ${Math.min(results.length, maxResults)}):\n`);
149
+ for (const r of results.slice(0, maxResults)) {
150
+ const title = r.title || r.url;
151
+ const url = r.url;
152
+ const content = (r.content || r.raw_content || "").trim().slice(0, 600);
153
+ lines.push(`- **${title}**`);
154
+ lines.push(` ${url}`);
155
+ if (content)
156
+ lines.push(` ${content.replace(/\s+/g, " ")}`);
157
+ lines.push("");
158
+ }
159
+ if (data.query) {
160
+ lines.push(`_Query: ${data.query}_`);
161
+ }
162
+ return lines.join("\n");
163
+ }
164
+ catch (err) {
165
+ if (err?.name === "AbortError") {
166
+ return "ERROR web_search_timeout: Tavily request timed out.";
167
+ }
168
+ return `ERROR web_search_failed: ${err instanceof Error ? err.message : String(err)}`;
169
+ }
170
+ finally {
171
+ clearTimeout(timeout);
172
+ }
173
+ }
174
+ /** Register the native research tools into the provided ToolSet. */
175
+ export function registerNativeResearchTools(tools) {
176
+ tools.fetch_url = dynamicTool({
177
+ description: "Fetch a URL and return clean, readable content as markdown (default), plain text, or raw HTML. " +
178
+ "Ideal for documentation, articles, GitHub, blog posts, raw files, and any public web page. " +
179
+ "Use this for most 'read this URL' needs instead of external MCP fetch.",
180
+ inputSchema: jsonSchema({
181
+ type: "object",
182
+ properties: {
183
+ url: { type: "string", description: "The full http(s) URL to fetch" },
184
+ format: {
185
+ type: "string",
186
+ enum: ["markdown", "text", "html"],
187
+ description: "Output format. Default: markdown (best for agents)",
188
+ },
189
+ maxChars: {
190
+ type: "number",
191
+ description: "Maximum characters to return (500-30000). Default ~12000.",
192
+ },
193
+ },
194
+ required: ["url"],
195
+ additionalProperties: false,
196
+ }),
197
+ execute: async (input) => {
198
+ const url = String(input?.url || "").trim();
199
+ if (!url || !/^https?:\/\//i.test(url)) {
200
+ return "ERROR invalid_url: fetch_url requires a full http(s):// URL";
201
+ }
202
+ const format = (["markdown", "text", "html"].includes(input?.format) ? input.format : "markdown");
203
+ const maxChars = typeof input?.maxChars === "number" ? input.maxChars : undefined;
204
+ return fetchUrl(url, { format, maxChars });
205
+ },
206
+ });
207
+ tools.web_search = dynamicTool({
208
+ description: "Search the live web using Tavily (LLM-optimized search with summaries). " +
209
+ "Returns titles, URLs, and content snippets. Requires a Tavily API key (free tier available). " +
210
+ "Use together with fetch_url when you need deeper content from specific results.",
211
+ inputSchema: jsonSchema({
212
+ type: "object",
213
+ properties: {
214
+ query: { type: "string", description: "Search query (natural language is fine)" },
215
+ maxResults: {
216
+ type: "number",
217
+ description: "How many results to return (1-20). Default 8.",
218
+ },
219
+ },
220
+ required: ["query"],
221
+ additionalProperties: false,
222
+ }),
223
+ execute: async (input) => {
224
+ const query = String(input?.query || "").trim();
225
+ if (!query)
226
+ return "ERROR invalid_query: web_search requires a non-empty query";
227
+ const maxResults = typeof input?.maxResults === "number" ? input.maxResults : undefined;
228
+ return webSearch(query, { maxResults });
229
+ },
230
+ });
231
+ return tools;
232
+ }
233
+ //# sourceMappingURL=research.js.map
@@ -34,6 +34,8 @@ export interface TaskRequest {
34
34
  description: string;
35
35
  prompt: string;
36
36
  maxToolRounds?: number;
37
+ /** When set, bypasses parent-tier cap and uses this model for the sub-agent. */
38
+ modelId?: string;
37
39
  }
38
40
  export interface TaskRun {
39
41
  agent: string;
@@ -192,6 +194,13 @@ export interface ToolGroup {
192
194
  items: ToolGroupItem[];
193
195
  startedAt: number;
194
196
  finishedAt?: number;
197
+ /**
198
+ * True when this group was rebuilt from a persisted transcript rather than
199
+ * observed live (see ui/utils/group-tool-entries.ts). Its timestamps come
200
+ * from entry write-time, so the elapsed span is NOT a real measurement and
201
+ * must not be displayed as one.
202
+ */
203
+ restored?: boolean;
195
204
  inputTokens?: number;
196
205
  outputTokens?: number;
197
206
  }
@@ -223,7 +232,7 @@ export interface StructuredResponse {
223
232
  taskType: string;
224
233
  data: Record<string, unknown>;
225
234
  }
226
- export type CouncilQuestionPhase = "clarify" | "preflight" | "plan-confirm" | "post-debate" | "pil-interview" | "pil-acceptance" | "tool-loop-cap" | "safety-override";
235
+ export type CouncilQuestionPhase = "clarify" | "preflight" | "plan-confirm" | "post-debate" | "pil-interview" | "pil-acceptance" | "tool-loop-cap" | "safety-override" | "ask-user";
227
236
  export type CouncilOptionKind = "choice" | "freetext" | "chat";
228
237
  export interface CouncilQuestionOption {
229
238
  label: string;
@@ -246,7 +255,7 @@ export interface CouncilQuestionData {
246
255
  options?: CouncilQuestionOption[];
247
256
  defaultIndex?: number;
248
257
  }
249
- export type CouncilStatusPhase = "clarify" | "plan_debate" | "research" | "opening" | "exchange" | "evaluate" | "synthesis" | "summary";
258
+ export type CouncilStatusPhase = "clarify" | "panel_select" | "plan_debate" | "research" | "opening" | "exchange" | "evaluate" | "synthesis" | "summary";
250
259
  export type CouncilStatusState = "start" | "tick" | "done" | "error";
251
260
  export interface CouncilStatusData {
252
261
  statusId: string;
@@ -256,12 +265,25 @@ export interface CouncilStatusData {
256
265
  detail?: string;
257
266
  role?: string;
258
267
  elapsedMs?: number;
268
+ /** Client-side first-seen stamp (upsertStatus), back-dated by the emitted elapsedMs. Drives live-ticking elapsed. */
269
+ startedAt?: number;
259
270
  tokensIn?: number;
260
271
  tokensOut?: number;
272
+ /**
273
+ * Push-based stream liveness (additive, optional). `elapsedMs` alone cannot
274
+ * prove a council call is alive: the tick generator only advances when the
275
+ * CONSUMER pulls, so a round awaiting its pairs via Promise.all freezes it.
276
+ * These two come from the token stream itself — `streamedChars` counts text +
277
+ * reasoning deltas since the phase began, and `lastDeltaAgeMs` is the age of
278
+ * the most recent delta. Growing chars / small age = SLOW BUT ALIVE; static
279
+ * chars + growing age = genuinely STUCK.
280
+ */
281
+ streamedChars?: number;
282
+ lastDeltaAgeMs?: number;
261
283
  errorMessage?: string;
262
284
  }
263
285
  /** High-level lifecycle event for a council phase. Drives the phase timeline UI. */
264
- export type CouncilPhaseKind = "clarification" | "clarification_round" | "preflight" | "debate_plan" | "research" | "opening" | "round" | "evaluation" | "mid_research" | "summary" | "synthesis" | "action_plan"
286
+ export type CouncilPhaseKind = "clarification" | "clarification_round" | "preflight" | "debate_plan" | "research" | "opening" | "round" | "evaluation" | "mid_research" | "grounding_verify" | "summary" | "synthesis" | "action_plan"
265
287
  /**
266
288
  * Sprint stage emitted by sprint-runner — one of planning/implementation/
267
289
  * verification/judgment. label distinguishes the stage. Used so the user
@@ -333,6 +355,84 @@ export interface CouncilInfoCard {
333
355
  title: string;
334
356
  sections: CouncilInfoCardSection[];
335
357
  }
358
+ /**
359
+ * Incremental council metadata for the context rail (P3). Emitted as one or more
360
+ * `council_meta` chunks — the leader/panel/researchMode/costAware fields come
361
+ * from the council entrypoint, the round budget/ceiling from inside runDebate
362
+ * (locals invisible to the entrypoint). The UI upsert-merges each patch into a
363
+ * single `councilMeta` object, so any subset of fields may be present.
364
+ */
365
+ /**
366
+ * One debate round's lifecycle record for the round-grouped transcript (P5/P6).
367
+ * Emitted as `council_round` chunks: a `running` record at round start, then a
368
+ * `done` record (guaranteed on every loop exit) carrying the outcome. The UI
369
+ * upsert-merges by `round` (running → done overwrite).
370
+ */
371
+ export interface CouncilRoundRecord {
372
+ round: number;
373
+ state: "running" | "done";
374
+ /** This round's focus, carried from the prior round's `nextRoundFocus`. */
375
+ topic?: string;
376
+ /** Role labels of the participants active this round. */
377
+ participants: string[];
378
+ /** Number of debate pairs exchanged this round. */
379
+ pairCount: number;
380
+ /** True when this round is beyond the leader's original planned budget. */
381
+ emergent: boolean;
382
+ /** Leader-evaluated criteria met / total (absent until the round is done). */
383
+ criteriaMet?: number;
384
+ criteriaTotal?: number;
385
+ /** Leader's one-sentence decision reason. */
386
+ leaderReason?: string;
387
+ /** What the leader / engine decided at the end of this round. */
388
+ leaderDecision?: "continue" | "stop" | "extend" | "aborted" | "circuit-break" | "eval-unavailable";
389
+ /** Topic the leader set for the NEXT round (drives the overview). */
390
+ nextRoundFocus?: string;
391
+ /**
392
+ * B5 — the leader's pre-round DIRECTIVE for this round (goal + criteria still
393
+ * unmet going in). Captured on the round record so it survives into the
394
+ * post-debate conclusion card, not only the ephemeral live directive bubble —
395
+ * otherwise a user who looks away during the debate never sees the leader
396
+ * conduct the round. Present only when the conductor is on + criteria pinned.
397
+ */
398
+ directive?: string;
399
+ }
400
+ /**
401
+ * Incremental council metadata for the context rail (P3). Emitted as one or more
402
+ * `council_meta` chunks — the leader/panel/researchMode/costAware fields come
403
+ * from the council entrypoint, the round budget/ceiling from inside runDebate
404
+ * (locals invisible to the entrypoint). The UI upsert-merges each patch into a
405
+ * single `councilMeta` object, so any subset of fields may be present.
406
+ */
407
+ export interface CouncilMetaPatch {
408
+ /** The debate topic / question under discussion (shown at the top of the rail). */
409
+ topic?: string;
410
+ /** Leader model id driving the debate. */
411
+ leader?: string;
412
+ /** Panel member role labels. */
413
+ panel?: string[];
414
+ /** Planned round budget resolved for this debate. */
415
+ roundBudget?: number;
416
+ /** Hard ceiling rounds may extend to (emergent rounds). */
417
+ roundCeiling?: number;
418
+ /** Research mode enabled for this debate. */
419
+ researchMode?: boolean;
420
+ /** Cost-aware budgeting active. */
421
+ costAware?: boolean;
422
+ /**
423
+ * The pinned outcome criteria the debate is graded against (the user-owned
424
+ * `ClarifiedSpec.successCriteria`). Emitted once after clarify so the rail can
425
+ * show the OUTCOME the debate is chasing — fixes "criteria met là gì tôi không
426
+ * biết". Stable for the whole debate.
427
+ */
428
+ successCriteria?: string[];
429
+ /**
430
+ * Per-criterion met status, index-aligned to `successCriteria`. Upsert-merged
431
+ * and refreshed after each round's leader evaluation so the rail shows live
432
+ * ✓/○ against the pinned criteria. Length matches `successCriteria`.
433
+ */
434
+ criteriaMet?: boolean[];
435
+ }
336
436
  export interface CouncilMessage {
337
437
  kind: CouncilMessageKind;
338
438
  speaker: {
@@ -343,6 +443,7 @@ export interface CouncilMessage {
343
443
  role: string;
344
444
  };
345
445
  round?: number;
446
+ phase?: "directive" | "verdict";
346
447
  text: string;
347
448
  toolCalls?: {
348
449
  name: string;
@@ -350,9 +451,19 @@ export interface CouncilMessage {
350
451
  attempts?: number;
351
452
  failureReason?: string;
352
453
  runId?: string;
454
+ /**
455
+ * Wall-clock of THIS speaker's LLM call, including retries.
456
+ *
457
+ * Without it the only timed council rows are `debate_complete` (the whole
458
+ * debate, measured at 87s..1128s) and `council_summary` — aggregates that
459
+ * cannot say WHICH model burned the time, so every latency diagnosis is
460
+ * guesswork. Persisted to `interaction_logs.duration_ms` alongside the
461
+ * `speakerModel` this row already carries, making the bottleneck queryable.
462
+ */
463
+ durationMs?: number;
353
464
  }
354
465
  export interface StreamChunk {
355
- type: "content" | "tool_calls" | "tool_result" | "tool_approval_request" | "council_question" | "council_preflight" | "council_status" | "council_phase" | "council_message" | "council_info_card" | "done" | "error" | "reasoning" | "structured_response" | "product_status_card" | "experience_warning" | "experience_injected" | "push_notification" | "halt" | "task_list_update";
466
+ type: "content" | "tool_calls" | "tool_result" | "tool_approval_request" | "council_question" | "council_preflight" | "council_status" | "council_phase" | "council_message" | "council_info_card" | "council_meta" | "council_round" | "done" | "error" | "reasoning" | "structured_response" | "product_status_card" | "experience_warning" | "experience_injected" | "push_notification" | "halt" | "toast" | "task_list_update";
356
467
  content?: string;
357
468
  toolCalls?: ToolCall[];
358
469
  toolCall?: ToolCall;
@@ -367,12 +478,21 @@ export interface StreamChunk {
367
478
  councilPhase?: CouncilPhaseEvent;
368
479
  councilMessage?: CouncilMessage;
369
480
  councilInfoCard?: CouncilInfoCard;
481
+ councilMeta?: CouncilMetaPatch;
482
+ councilRound?: CouncilRoundRecord;
370
483
  productStatusCard?: import("../product-loop/types.js").ProductStatusCardData;
371
484
  /** Populated when type === "halt". Contains structured recovery options. */
372
485
  haltChunk?: import("../product-loop/types.js").HaltChunk;
373
486
  experienceWarning?: ExperienceWarningData;
374
487
  experienceInjected?: ExperienceInjectedData;
375
488
  taskListSnapshot?: TaskListSnapshot;
489
+ /**
490
+ * Populated when type === "toast". A transient, ephemeral notice (e.g.
491
+ * "initializing sub-session…") that the UI shows briefly then auto-dismisses
492
+ * — it is NOT appended to the persisted assistant message. `content` holds
493
+ * the text; `toastLevel` selects the style (defaults to "info").
494
+ */
495
+ toastLevel?: "info" | "warn" | "error";
376
496
  }
377
497
  export type TaskListItemStatus = "pending" | "in_progress" | "completed";
378
498
  export interface TaskListItem {
@@ -413,13 +533,28 @@ export interface ModelInfo {
413
533
  multiAgent?: boolean;
414
534
  supportsClientTools?: boolean;
415
535
  supportsMaxOutputTokens?: boolean;
536
+ /**
537
+ * When set, the provider rejects any temperature other than this exact value
538
+ * (e.g. Moonshot/Kimi: "only 1 is allowed for this model"). Callers must send
539
+ * this value verbatim rather than their preferred temperature — see
540
+ * `resolveTemperature` in src/providers/capabilities.ts.
541
+ */
542
+ fixedTemperature?: number;
416
543
  defaultReasoningEffort?: ReasoningEffort;
417
544
  supportsReasoningEffort?: boolean;
418
545
  thinkingType?: "enabled" | "adaptive";
419
546
  supportsVision?: boolean;
547
+ /** When false, excluded from getModelByTier / automatic compaction routing. Default: routable. */
548
+ tierRouting?: boolean;
549
+ /** Extra tiers this model may satisfy in getModelByTier (primary tier remains `tier`). */
550
+ routingTiers?: ModelTier[];
551
+ roles?: string[];
552
+ /** Part E — model has native online web research (its own web_search/browsing). */
553
+ nativeWebResearch?: boolean;
420
554
  }
421
555
  export type AgentMode = "agent" | "plan" | "ask";
422
556
  export type SessionStatus = "active" | "completed" | "archived" | "abandoned";
557
+ export type SessionKind = "conversation" | "rotation" | "subagent";
423
558
  export type UsageSource = "message" | "title" | "task" | "delegation" | "council" | "other";
424
559
  export interface WorkspaceInfo {
425
560
  id: string;
@@ -441,6 +576,14 @@ export interface SessionInfo {
441
576
  createdAt: Date;
442
577
  updatedAt: Date;
443
578
  }
579
+ /**
580
+ * One row in the `/sessions` resume picker: a whole conversation tree collapsed
581
+ * to a single entry. `id`/`title`/`createdAt` describe the tree root; `resumeId`
582
+ * is the latest leaf to relaunch; `model`/`updatedAt`/`status` describe that leaf.
583
+ */
584
+ export interface ResumeEntry extends SessionInfo {
585
+ resumeId: string;
586
+ }
444
587
  export interface UsageEvent {
445
588
  id: number;
446
589
  sessionId: string;
Binary file
@@ -49,7 +49,7 @@ export function ProductStatusCard({ data, theme: t }) {
49
49
  const costSpark = data.costHistory?.length
50
50
  ? sparkline(data.costHistory.map((h) => (data.costCap > 0 ? h.cumulativeUsd / data.costCap : 0)))
51
51
  : "";
52
- return (_jsx(Semantic, { id: "ideal-status", role: "region", name: "Ideal status", children: _jsxs("box", { flexDirection: "column", paddingLeft: 2, paddingTop: 0, flexShrink: 0, children: [_jsx("box", { children: _jsx("text", { fg: t.accent, children: `▶ Product Loop · ${data.currentStage}` }) }), _jsx(Semantic, { id: `ideal-phase-sprint`, role: "listitem", name: "Sprint", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Sprint: " }), _jsx("text", { fg: t.text, children: `${data.sprintN}/${data.totalSprints} ` }), _jsx("text", { fg: t.accent, children: bar(sprintPct) }), _jsx("text", { fg: t.textDim, children: ` ${sprintPct.toFixed(0)}%` })] }) }), _jsx(Semantic, { id: `ideal-phase-cost`, role: "listitem", name: "Cost", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Cost: " }), _jsx("text", { fg: t.text, children: `$${data.costSpent.toFixed(2)}/$${data.costCap.toFixed(2)} ` }), _jsx("text", { fg: costColor, children: bar(costPct) }), _jsx("text", { fg: t.textDim, children: ` ${costPct.toFixed(0)}%` })] }) }), costSpark && (_jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Burn: " }), _jsx("text", { fg: costColor, children: costSpark }), _jsx("text", { fg: t.textDim, children: ` (per-sprint)` })] })), _jsx(Semantic, { id: `ideal-phase-criteria`, role: "listitem", name: "Criteria", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Criteria: " }), _jsx("text", { fg: t.planOptionCheck, children: `✓ ${data.criteriaMet}` }), _jsx("text", { fg: t.text, children: " " }), _jsx("text", { fg: t.accent, children: `◐ ${data.criteriaPartial}` }), _jsx("text", { fg: t.text, children: " " }), _jsx("text", { fg: t.diffRemovedFg, children: `✗ ${data.criteriaUnmet}` }), _jsx("text", { fg: t.textDim, children: ` (of ${totalCriteria})` })] }) }), criteriaSpark && (_jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Trend: " }), _jsx("text", { fg: t.planOptionCheck, children: criteriaSpark }), _jsx("text", { fg: t.textDim, children: ` met-ratio per sprint` })] }))] }) }));
52
+ return (_jsx(Semantic, { id: "ideal-status", role: "region", name: "Ideal status", children: _jsxs("box", { flexDirection: "column", paddingLeft: 2, paddingTop: 0, flexShrink: 0, children: [_jsx("box", { children: _jsx("text", { fg: t.accent, children: `▶ Product Loop · ${data.currentStage}` }) }), _jsx(Semantic, { id: `ideal-phase-sprint`, role: "listitem", name: "Sprint", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Sprint: " }), _jsx("text", { fg: t.text, children: `${data.sprintN}/${data.totalSprints} ` }), _jsx("text", { fg: t.accent, children: bar(sprintPct) }), _jsx("text", { fg: t.textDim, children: ` ${sprintPct.toFixed(0)}%` })] }) }), _jsx(Semantic, { id: `ideal-phase-cost`, role: "listitem", name: "Cost", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Cost: " }), _jsx("text", { fg: t.text, children: `$${data.costSpent.toFixed(2)}/$${data.costCap.toFixed(2)} ` }), _jsx("text", { fg: costColor, children: bar(costPct) }), _jsx("text", { fg: t.textDim, children: ` ${costPct.toFixed(0)}%` })] }) }), costSpark && (_jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Burn: " }), _jsx("text", { fg: costColor, children: costSpark }), _jsx("text", { fg: t.textDim, children: ` spend per sprint` })] })), _jsx(Semantic, { id: `ideal-phase-criteria`, role: "listitem", name: "Criteria", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Criteria: " }), _jsx("text", { fg: t.planOptionCheck, children: `✓ ${data.criteriaMet}` }), _jsx("text", { fg: t.text, children: " " }), _jsx("text", { fg: t.accent, children: `◐ ${data.criteriaPartial}` }), _jsx("text", { fg: t.text, children: " " }), _jsx("text", { fg: t.diffRemovedFg, children: `✗ ${data.criteriaUnmet}` }), _jsx("text", { fg: t.textDim, children: ` (of ${totalCriteria})` })] }) }), criteriaSpark && (_jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Trend: " }), _jsx("text", { fg: t.planOptionCheck, children: criteriaSpark }), _jsx("text", { fg: t.textDim, children: ` criteria met per sprint` })] }))] }) }));
53
53
  }
54
54
  export default ProductStatusCard;
55
55
  //# sourceMappingURL=product-status-card.js.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * src/ui/components/agent-rail-activities.tsx
3
+ *
4
+ * Rail block listing every sub-agent / background job this session spawned.
5
+ *
6
+ * Before this, a spawned agent was visible only as a transient line in the
7
+ * transcript: it scrolled away, and once done there was nowhere to see WHAT it
8
+ * was asked or what it returned. The rail keeps the roster on screen, and a row
9
+ * opens to show the prompt and the result.
10
+ *
11
+ * Selection is by click (OpenTUI onMouseDown per row, same as
12
+ * council-rail-rounds.tsx) — clicking the open row closes it again.
13
+ */
14
+ import type { AgentActivity } from "../utils/agent-activities.js";
15
+ import type { Theme } from "../theme.js";
16
+ /** Row prefix naming what was spawned: the agent type, or "shell" for a job. */
17
+ export declare function activityPrefix(a: AgentActivity): string;
18
+ export interface AgentRailActivitiesProps {
19
+ activities: AgentActivity[];
20
+ /** Tool-call id of the open row, or null when all are collapsed. */
21
+ selected: string | null;
22
+ onSelect: (id: string | null) => void;
23
+ width: number;
24
+ t: Theme;
25
+ }
26
+ export declare function AgentRailActivities({ activities, selected, onSelect, width, t }: AgentRailActivitiesProps): import("react").ReactNode;
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
2
+ /**
3
+ * src/ui/components/agent-rail-activities.tsx
4
+ *
5
+ * Rail block listing every sub-agent / background job this session spawned.
6
+ *
7
+ * Before this, a spawned agent was visible only as a transient line in the
8
+ * transcript: it scrolled away, and once done there was nowhere to see WHAT it
9
+ * was asked or what it returned. The rail keeps the roster on screen, and a row
10
+ * opens to show the prompt and the result.
11
+ *
12
+ * Selection is by click (OpenTUI onMouseDown per row, same as
13
+ * council-rail-rounds.tsx) — clicking the open row closes it again.
14
+ */
15
+ import { ListItem, Region } from "../primitives/semantic-primitives.js";
16
+ import { trunc } from "../utils/text.js";
17
+ /** Characters of detail shown when a row is open. Keeps the rail scrollable. */
18
+ const DETAIL_LIMIT = 600;
19
+ const GLYPH = { running: "▸", done: "✓", failed: "✗" };
20
+ function statusColor(status, t) {
21
+ if (status === "failed")
22
+ return t.diffRemovedFg;
23
+ if (status === "done")
24
+ return t.diffAddedFg;
25
+ return t.accent;
26
+ }
27
+ /** Row prefix naming what was spawned: the agent type, or "shell" for a job. */
28
+ export function activityPrefix(a) {
29
+ if (a.kind === "background")
30
+ return "shell";
31
+ return a.agent || (a.kind === "delegate" ? "delegate" : "sub-agent");
32
+ }
33
+ export function AgentRailActivities({ activities, selected, onSelect, width, t }) {
34
+ if (activities.length === 0)
35
+ return null;
36
+ const running = activities.filter((a) => a.status === "running").length;
37
+ return (_jsx(Region, { id: "agent-rail-activities", name: "Agents", value: `${activities.length}`, props: {
38
+ count: activities.length,
39
+ running,
40
+ selected: selected ?? "",
41
+ ids: activities.map((a) => a.id).join(","),
42
+ }, children: _jsxs("box", { flexDirection: "column", flexShrink: 0, children: [_jsx("text", { fg: t.textMuted, attributes: 1, children: running > 0 ? `Agents (${running} running)` : "Agents" }), activities.map((a) => {
43
+ const isOpen = selected === a.id;
44
+ return (_jsx(ListItem, { id: `rail-agent-${a.id}`, name: `${activityPrefix(a)} ${a.label}`, state: a.status, selected: isOpen || undefined, children: _jsxs("box", { flexDirection: "column", flexShrink: 0, children: [_jsx("box", { flexDirection: "row", onMouseDown: () => onSelect(isOpen ? null : a.id), children: _jsxs("text", { children: [_jsx("span", { style: { fg: statusColor(a.status, t) }, children: `${GLYPH[a.status]} ` }), _jsx("span", { style: { fg: t.textMuted }, children: `${activityPrefix(a)} ` }), _jsx("span", { style: { fg: t.text }, children: trunc(a.label, Math.max(8, width - 12)) })] }) }), isOpen && (_jsx("box", { paddingLeft: 2, flexDirection: "column", children: _jsx("text", { fg: t.textDim, children: a.detail.trim() ? trunc(a.detail, DETAIL_LIMIT) : "(no output yet)" }) }))] }) }, a.id));
45
+ })] }) }));
46
+ }
47
+ //# sourceMappingURL=agent-rail-activities.js.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Render-time guard for council message bodies.
3
+ *
4
+ * Root cause it defends against (live-diagnosed 2026-07-08, run mrbj8v6w81a3):
5
+ * a single round-1 debate turn whose body contained a very long whitespace-free
6
+ * run (an import graph / path list / blob a Flash-tier model dumped over a
7
+ * 1286-file repo). `CouncilMessageBubble` hands the raw body to a single
8
+ * OpenTUI `<text>` node with NO length or line-length bound. OpenTUI's word-wrap
9
+ * on such a mega-line pegs the main thread at 100% CPU — and because render and
10
+ * the product-loop share one JS thread, the entire `/ideal` run hard-freezes
11
+ * (render + input + debate logic all starve). Every muonroi-owned text function
12
+ * on the path (`truncateCodeBlocks`, `renderMarkdown`, `parseInline`,
13
+ * `tokenize`) was benchmarked fast on 80–130KB adversarial input, so the block
14
+ * lives in the terminal's layout of an unbounded body.
15
+ *
16
+ * This function bounds BOTH failure axes before the body reaches `<text>`:
17
+ * 1. total length — cap at `maxChars`, append a muted pointer to /export.
18
+ * 2. line length — hard-break any whitespace-free run longer than the
19
+ * terminal width so the wrapper always has a break opportunity (turns a
20
+ * pathological O(n²) single-line wrap into linear per-segment wrapping).
21
+ *
22
+ * Pure + side-effect free — safe to unit-test without a terminal.
23
+ */
24
+ /** Default ceiling on a rendered bubble body. Well above any real prose turn
25
+ * (~2–4KB) but far below the 100KB+ blobs that trigger the layout hang. */
26
+ export declare const MAX_BUBBLE_BODY_CHARS = 12000;
27
+ export declare function capBubbleBody(text: string, terminalCols: number, maxChars?: number): string;