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
@@ -6,15 +6,19 @@
6
6
  * is sent to the API for all providers (including DeepSeek, Gemini, etc.).
7
7
  */
8
8
  import { dynamicTool, jsonSchema } from "ai";
9
+ import { registerGsdWorkflowTools } from "../gsd/workflow-tools.js";
10
+ import { requestProactiveCompact } from "../orchestrator/compact-request.js";
9
11
  import { canonicalizeBashCommand } from "../orchestrator/tool-args-hash.js";
10
12
  import { analyzeImageFromSource, askVisionProxy, listCachedImages } from "../providers/mcp-vision-bridge.js";
11
13
  import { needsVisionProxy } from "../providers/vision-proxy.js";
14
+ import { loadMcpServers } from "../utils/settings.js";
12
15
  import { getBashRun, sliceBashOutput } from "./bash-output-cache.js";
13
- import { editFile, readFile, writeFile } from "./file.js";
16
+ import { editFile, readFile, readFiles, writeFile } from "./file.js";
14
17
  import { FileTracker } from "./file-tracker.js";
15
18
  import { analyzeGitCommand, checkPushGate, checkSensitiveStaging, commitBlockedMessage, pushBlockedMessage, recordCommandOutcome, } from "./git-safety.js";
16
19
  import { executeGrep } from "./grep.js";
17
20
  import { registerNativeMuonroiTools } from "./native-tools.js";
21
+ import { registerNativeResearchTools } from "./research.js";
18
22
  import { VISION_TOOL_NAMES } from "./vision-gate.js";
19
23
  function getSafetyApprovedMap() {
20
24
  if (!globalThis.__muonroiSafetyApproved) {
@@ -84,20 +88,38 @@ export function createBuiltinTools(bash, mode, opts) {
84
88
  // One tracker per tool registry instance — shared across read/write/edit
85
89
  // calls in the same session. Enforces "must read before edit/overwrite".
86
90
  const fileTracker = new FileTracker();
91
+ // Native research tools (fetch_url, web_search) — always available.
92
+ // These are the in-process replacements for the old external MCP research servers.
93
+ registerNativeResearchTools(tools);
87
94
  // read_file
88
95
  tools.read_file = dynamicTool({
89
- description: "Read file contents. For large files, you MUST use start_line and end_line to extract only the needed sections (e.g. specific functions). Reading full large files will quickly exhaust your context budget. Use grep or lsp first to find line numbers.",
96
+ description: "Read file contents. To read SEVERAL files, pass them ALL in one call via file_paths (array) — STRONGLY PREFERRED over issuing separate read_file calls: each extra call re-sends the whole conversation as input, so N single reads cost O(N²) tokens while one batched read costs O(N). For a large SINGLE file, use start_line/end_line to extract only the needed section (start_line/end_line apply to file_path only; file_paths reads whole files). Use grep or lsp first to find line numbers.",
90
97
  inputSchema: jsonSchema({
91
98
  type: "object",
92
99
  properties: {
93
- file_path: { type: "string", description: "Path to the file to read" },
94
- start_line: { type: "number", description: "First line to read (1-based)" },
95
- end_line: { type: "number", description: "Last line to read (1-based)" },
100
+ file_path: { type: "string", description: "Path to a single file to read (supports start_line/end_line)." },
101
+ file_paths: {
102
+ type: "array",
103
+ items: { type: "string" },
104
+ description: "Read MULTIPLE files in ONE call (preferred when you need 2+ files). Each is returned with its own header; each is capped independently so none is dropped. Best for small-to-medium files; for a large file use file_path + line range.",
105
+ },
106
+ start_line: { type: "number", description: "First line to read (1-based). Applies to file_path only." },
107
+ end_line: { type: "number", description: "Last line to read (1-based). Applies to file_path only." },
96
108
  },
97
- required: ["file_path"],
98
109
  }),
99
110
  execute: async (input) => {
100
- const result = readFile(input.file_path, bash.getCwd(), input.start_line, input.end_line, fileTracker);
111
+ const batch = Array.isArray(input.file_paths) && input.file_paths.length > 0
112
+ ? input.file_paths.filter((p) => typeof p === "string" && p.trim() !== "")
113
+ : [];
114
+ if (batch.length > 1) {
115
+ // Per-file fair-share of the output cap so the concatenated result
116
+ // stays under MAX_TOOL_OUTPUT_CHARS and every file survives (no silent
117
+ // head/tail drop of whole files). Floor keeps each file legible.
118
+ const perFileCap = Math.max(4_000, Math.floor(MAX_TOOL_OUTPUT_CHARS / batch.length));
119
+ return formatResult(readFiles(batch, bash.getCwd(), fileTracker, perFileCap));
120
+ }
121
+ const single = batch.length === 1 ? batch[0] : input.file_path;
122
+ const result = readFile(single, bash.getCwd(), input.start_line, input.end_line, fileTracker);
101
123
  return formatResult(result);
102
124
  },
103
125
  });
@@ -118,6 +140,34 @@ export function createBuiltinTools(bash, mode, opts) {
118
140
  return formatResult(result);
119
141
  },
120
142
  });
143
+ // compact — agent-initiated proactive context compaction. The model calls
144
+ // this to shed accumulated tool/conversation history mid-task (freeing
145
+ // context + resetting tool-call bloat) BEFORE it hits a tool-round limit,
146
+ // so a long task never gets interrupted. The request is queued here and
147
+ // consumed by the tool-engine's prepareStep boundary, which forces a
148
+ // compaction pass before the next LLM step, then the turn continues. A
149
+ // decisions/facts snapshot is preserved and high-value tool results stay
150
+ // rehydratable via ee_query "tool-artifact id=…". This is the proactive
151
+ // counterpart to the reactive tool-limit auto-recover.
152
+ tools.compact = dynamicTool({
153
+ description: "Proactively compress THIS turn's accumulated tool/conversation history to free context and reset tool-call bloat, then CONTINUE the task automatically. Call it after a read-heavy stretch (many read_file/grep/bash results) when context feels heavy and BEFORE you approach a tool-round limit — it prevents the 'reached tool limit' interruption entirely. The compaction runs before your next step; older tool results are summarized (a decisions/facts snapshot is kept) and remain rehydratable via ee_query \"tool-artifact id=…\". Do NOT stop after calling it — keep working toward the goal.",
154
+ inputSchema: jsonSchema({
155
+ type: "object",
156
+ properties: {
157
+ focus: {
158
+ type: "string",
159
+ description: "Short note on what to keep in mind / preserve after compaction (e.g. the current sub-task).",
160
+ },
161
+ },
162
+ }),
163
+ execute: async (input) => {
164
+ requestProactiveCompact(typeof input?.focus === "string" ? input.focus : null);
165
+ return formatResult({
166
+ success: true,
167
+ output: 'Context compaction scheduled — older tool history will be compressed before your next step; continue the task afterward. High-value results stay rehydratable via ee_query "tool-artifact id=…".',
168
+ });
169
+ },
170
+ });
121
171
  // bash — every foreground call goes through here. We track the LAST
122
172
  // canonical command + runId in SESSION-SCOPED state so we can inject a
123
173
  // reminder when the model issues another bash call that canonicalizes to
@@ -253,7 +303,20 @@ export function createBuiltinTools(bash, mode, opts) {
253
303
  }
254
304
  }
255
305
  }
256
- if (input.background) {
306
+ const isLongRunning = (c) => {
307
+ const lower = c.toLowerCase().trim();
308
+ return (/\bvite\b/.test(lower) ||
309
+ /\bnodemon\b/.test(lower) ||
310
+ /\bwebpack-dev-server\b/.test(lower) ||
311
+ /\bnext\s+dev\b/.test(lower) ||
312
+ /\bwatch\b/.test(lower) ||
313
+ /--watch\b/.test(lower) ||
314
+ /\b-w\b/.test(lower) ||
315
+ /\bdev-server\b/.test(lower) ||
316
+ /\blive-server\b/.test(lower) ||
317
+ /\bhttp-server\b/.test(lower));
318
+ };
319
+ if (input.background || isLongRunning(cmd)) {
257
320
  const result = await bash.startBackground(input.command);
258
321
  return formatResult(result);
259
322
  }
@@ -378,6 +441,9 @@ export function createBuiltinTools(bash, mode, opts) {
378
441
  });
379
442
  // Agent mode gets write/edit/task/delegate tools
380
443
  if (mode === "agent") {
444
+ // Capture delegation functions for auto-routing logic below
445
+ const runTaskFn = opts?.runTask;
446
+ const runDelegationFn = opts?.runDelegation;
381
447
  // write_file
382
448
  tools.write_file = dynamicTool({
383
449
  description: "Create a new file or overwrite an existing file with full content. SAFETY: overwriting an existing file requires you to call read_file on it first in the same session. New-file creation does not.",
@@ -390,6 +456,13 @@ export function createBuiltinTools(bash, mode, opts) {
390
456
  required: ["file_path", "content"],
391
457
  }),
392
458
  execute: async (input) => {
459
+ if (!input?.file_path?.trim() || input.content === undefined || input.content === null) {
460
+ return {
461
+ success: false,
462
+ output: 'BLOCKED (empty-write_file): write_file requires non-empty "file_path" and "content". ' +
463
+ 'Example: {"file_path":"src/foo.ts","content":"export const x = 1;\\n"}',
464
+ };
465
+ }
393
466
  const result = await writeFile(input.file_path, input.content, bash.getCwd(), fileTracker);
394
467
  return {
395
468
  success: result.success,
@@ -412,6 +485,17 @@ export function createBuiltinTools(bash, mode, opts) {
412
485
  required: ["file_path", "old_string", "new_string"],
413
486
  }),
414
487
  execute: async (input) => {
488
+ if (!input?.file_path?.trim() ||
489
+ input.old_string === undefined ||
490
+ input.old_string === null ||
491
+ input.new_string === undefined ||
492
+ input.new_string === null) {
493
+ return {
494
+ success: false,
495
+ output: "BLOCKED (empty-edit_file): edit_file requires file_path, old_string, and new_string. " +
496
+ 'Example: {"file_path":"src/foo.ts","old_string":"a","new_string":"b"}',
497
+ };
498
+ }
415
499
  const result = await editFile(input.file_path, input.old_string, input.new_string, bash.getCwd(), fileTracker);
416
500
  return {
417
501
  success: result.success,
@@ -475,9 +559,11 @@ export function createBuiltinTools(bash, mode, opts) {
475
559
  });
476
560
  // task
477
561
  if (opts?.runTask) {
478
- const runTask = opts.runTask;
479
562
  tools.task = dynamicTool({
480
- description: "Delegate a focused foreground task to a sub-agent. Types: general (edit/execute), explore (read-only research), verify (sandbox validation), computer (desktop interaction).",
563
+ description: "Delegate a FOCUSED, SHORT foreground task to a sub-agent that blocks the current turn until complete. " +
564
+ "Use ONLY for quick edit/execute/verify work (default max ~12 rounds). " +
565
+ "For long research, exploration, or anything that may take many steps (explore agent), you MUST use the 'delegate' tool instead — it runs in true background and does not block. " +
566
+ "Using task for long work will cause stalls and timeouts.",
481
567
  inputSchema: jsonSchema({
482
568
  type: "object",
483
569
  properties: {
@@ -489,13 +575,20 @@ export function createBuiltinTools(bash, mode, opts) {
489
575
  prompt: { type: "string", description: "Detailed instructions for the sub-agent" },
490
576
  maxToolRounds: {
491
577
  type: "number",
492
- description: "Optional maximum tool execution rounds (default is 12 for foreground tasks)",
578
+ description: "Optional maximum tool execution rounds. For research/explore use delegate + higher values (default 60); low values (≤20) only for task.",
493
579
  },
494
580
  },
495
581
  required: ["agent", "description", "prompt"],
496
582
  }),
497
583
  execute: async (input) => {
498
- const result = await runTask({
584
+ // Auto-route long research (explore agent or high round count) to true background delegation
585
+ // to prevent blocking the main turn and causing stall timeouts.
586
+ const isLongResearch = input.agent === "explore" || (typeof input.maxToolRounds === "number" && input.maxToolRounds > 25);
587
+ const executor = isLongResearch && runDelegationFn ? runDelegationFn : runTaskFn;
588
+ if (!executor) {
589
+ return { success: false, output: "No delegation executor available." };
590
+ }
591
+ const result = await executor({
499
592
  agent: input.agent,
500
593
  description: input.description,
501
594
  prompt: input.prompt,
@@ -530,7 +623,10 @@ export function createBuiltinTools(bash, mode, opts) {
530
623
  if (opts?.runDelegation) {
531
624
  const runDelegation = opts.runDelegation;
532
625
  tools.delegate = dynamicTool({
533
- description: "Launch a read-only background agent for longer research while you continue working.",
626
+ description: "Launch a read-only BACKGROUND research agent (usually 'explore') that runs independently in a separate process. " +
627
+ "Use this for ANY long-running research, codebase exploration, analysis, or tasks with high maxToolRounds. " +
628
+ "Main session continues working immediately. Results are delivered later via notifications or delegation_read. " +
629
+ "This is the PREFERRED tool over 'task' for explore/research to avoid blocking and timeouts.",
534
630
  inputSchema: jsonSchema({
535
631
  type: "object",
536
632
  properties: {
@@ -539,7 +635,7 @@ export function createBuiltinTools(bash, mode, opts) {
539
635
  prompt: { type: "string", description: "Detailed research instructions" },
540
636
  maxToolRounds: {
541
637
  type: "number",
542
- description: "Optional maximum tool execution rounds (default is 60 for explore delegations)",
638
+ description: "Optional maximum tool execution rounds (high values like 60+ expected for background research; do not use task for high values).",
543
639
  },
544
640
  },
545
641
  required: ["agent", "description", "prompt"],
@@ -652,7 +748,7 @@ export function createBuiltinTools(bash, mode, opts) {
652
748
  // output in-process by toolCallId. For an exact "tool-artifact id=X"
653
749
  // lookup this is the authoritative full content for THIS session and
654
750
  // works even when EE is down — the failure window long sessions hit.
655
- const { findArtifactByQuery, findArtifactOnDisk } = await import("../ee/artifact-cache.js");
751
+ const { findArtifactByQuery, findArtifactByHint, findArtifactOnDisk } = await import("../ee/artifact-cache.js");
656
752
  // Lived-experience telemetry: record where the rehydrate came from so
657
753
  // a "cảm nhận trong CLI" question (and the measure-first instrumentation)
658
754
  // sees cache vs disk vs ee vs needed-but-unavailable.
@@ -664,6 +760,15 @@ export function createBuiltinTools(bash, mode, opts) {
664
760
  recordRehydration(mem ? "cache" : "disk");
665
761
  return truncateOutput(`[tool-artifact id=${local.toolCallId} tool=${local.toolName} — rehydrated from ${src}]\n${local.content}`);
666
762
  }
763
+ // B (cheap-model anti-mù) — the exact id missed locally. Cheap models
764
+ // often pass FILE PATHS instead of the opaque toolCallId, which
765
+ // extractArtifactId can't parse. Try a path match against the local
766
+ // cache before the EE round-trip so a botched id still recovers.
767
+ const fuzzy = findArtifactByHint(query);
768
+ if (fuzzy) {
769
+ recordRehydration("cache");
770
+ return truncateOutput(`[tool-artifact id=${fuzzy.toolCallId} tool=${fuzzy.toolName} — rehydrated by path match; your id was malformed (pass the exact id from the "[… elided id=X …]" stub next time)]\n${fuzzy.content}`);
771
+ }
667
772
  // EE fallback (cross-session / post-restart) → raw /api/search exact lookup.
668
773
  const { searchEE } = await import("../ee/search.js");
669
774
  const resp = await searchEE(query, {
@@ -721,6 +826,204 @@ export function createBuiltinTools(bash, mode, opts) {
721
826
  }
722
827
  },
723
828
  });
829
+ tools.retrieve_tool_result = dynamicTool({
830
+ description: "Retrieve the full output of a previous tool call by its tool_call_id. " +
831
+ "Searches local cache, disk cache, database history (including parent sessions), and remote Experience Engine. " +
832
+ "Use this to rehydrate elided tool outputs. Optional max_chars and chunk_index allow paginated retrieval.",
833
+ inputSchema: jsonSchema({
834
+ type: "object",
835
+ properties: {
836
+ tool_call_id: { type: "string", description: "The unique ID of the tool call (e.g. 'call_123')." },
837
+ max_chars: {
838
+ type: "number",
839
+ description: "Optional character limit for the returned chunk (useful for very large outputs).",
840
+ },
841
+ chunk_index: {
842
+ type: "number",
843
+ description: "Optional chunk index if splitting the output by max_chars (0-based, default 0).",
844
+ },
845
+ },
846
+ required: ["tool_call_id"],
847
+ }),
848
+ execute: async (input) => {
849
+ const toolCallId = typeof input.tool_call_id === "string" ? input.tool_call_id.trim() : "";
850
+ if (!toolCallId) {
851
+ return "ERROR: tool_call_id is required.";
852
+ }
853
+ const maxChars = typeof input.max_chars === "number" ? input.max_chars : undefined;
854
+ const chunkIndex = typeof input.chunk_index === "number" ? input.chunk_index : 0;
855
+ let content = null;
856
+ let source = "";
857
+ // Tier 1: LRU cache
858
+ try {
859
+ const { getArtifact } = await import("../ee/artifact-cache.js");
860
+ const tier1 = getArtifact(toolCallId);
861
+ if (tier1) {
862
+ content = tier1.content;
863
+ source = "Tier 1 LRU cache";
864
+ }
865
+ }
866
+ catch (err) {
867
+ console.error(`[tools:retrieve_tool_result] Tier 1 LRU check failed: ${err.message}`);
868
+ }
869
+ // Tier 2: Disk cache
870
+ if (!content) {
871
+ try {
872
+ const { findArtifactOnDisk } = await import("../ee/artifact-cache.js");
873
+ const tier2 = await findArtifactOnDisk(`id=${toolCallId}`);
874
+ if (tier2) {
875
+ content = tier2.content;
876
+ source = "Tier 2 disk cache";
877
+ }
878
+ }
879
+ catch (err) {
880
+ console.error(`[tools:retrieve_tool_result] Tier 2 disk check failed: ${err.message}`);
881
+ }
882
+ }
883
+ // Tier 3: SQLite database
884
+ if (!content && opts?.sessionId) {
885
+ try {
886
+ const { getSessionChain } = await import("../storage/index.js");
887
+ const { getDatabase } = await import("../storage/db.js");
888
+ const chain = getSessionChain(opts.sessionId);
889
+ const db = getDatabase();
890
+ for (let i = chain.length - 1; i >= 0; i--) {
891
+ const row = db
892
+ .prepare(`
893
+ SELECT tr.output_json
894
+ FROM tool_results tr
895
+ JOIN tool_calls tc ON tc.id = tr.tool_call_row_id
896
+ WHERE tc.tool_call_id = ? AND tc.session_id = ?
897
+ LIMIT 1
898
+ `)
899
+ .get(toolCallId, chain[i]);
900
+ if (row?.output_json) {
901
+ const parsed = JSON.parse(row.output_json);
902
+ if (parsed && typeof parsed === "object") {
903
+ if ("output" in parsed && typeof parsed.output === "string") {
904
+ content = parsed.output;
905
+ }
906
+ else if ("error" in parsed && typeof parsed.error === "string") {
907
+ content = `ERROR: ${parsed.error}`;
908
+ }
909
+ else {
910
+ content = JSON.stringify(parsed);
911
+ }
912
+ }
913
+ else {
914
+ content = String(parsed);
915
+ }
916
+ source = `Tier 3 SQLite database (session ${chain[i]})`;
917
+ break;
918
+ }
919
+ }
920
+ }
921
+ catch (err) {
922
+ console.error(`[tools:retrieve_tool_result] Tier 3 DB check failed: ${err.message}`);
923
+ }
924
+ }
925
+ // Tier 4: Remote EE (behavioral collection only)
926
+ if (!content) {
927
+ try {
928
+ const { searchEE } = await import("../ee/search.js");
929
+ const resp = await searchEE(`tool-artifact id=${toolCallId}`, {
930
+ collections: ["experience-behavioral"],
931
+ limit: 1,
932
+ });
933
+ const bestHit = resp?.points?.[0];
934
+ if (bestHit?.text) {
935
+ content = bestHit.text;
936
+ source = "Tier 4 remote EE (behavioral collection)";
937
+ }
938
+ }
939
+ catch (err) {
940
+ console.error(`[tools:retrieve_tool_result] Tier 4 EE check failed: ${err.message}`);
941
+ }
942
+ }
943
+ if (content === null) {
944
+ return `ERROR: Tool result not found for tool_call_id: ${toolCallId} in any tier.`;
945
+ }
946
+ const totalLength = content.length;
947
+ if (maxChars !== undefined && maxChars > 0) {
948
+ const totalChunks = Math.ceil(totalLength / maxChars);
949
+ const start = chunkIndex * maxChars;
950
+ const end = Math.min(start + maxChars, totalLength);
951
+ if (start >= totalLength) {
952
+ return `ERROR: chunk_index ${chunkIndex} is out of bounds. Total chunks available: ${totalChunks} (max_chars: ${maxChars}, total length: ${totalLength}).`;
953
+ }
954
+ const chunk = content.slice(start, end);
955
+ return JSON.stringify({
956
+ tool_call_id: toolCallId,
957
+ source,
958
+ chunk_index: chunkIndex,
959
+ total_chunks: totalChunks,
960
+ chunk_length: chunk.length,
961
+ total_length: totalLength,
962
+ content: chunk,
963
+ }, null, 2);
964
+ }
965
+ return JSON.stringify({
966
+ tool_call_id: toolCallId,
967
+ source,
968
+ total_length: totalLength,
969
+ content,
970
+ }, null, 2);
971
+ },
972
+ });
973
+ tools.search_session_history = dynamicTool({
974
+ description: "Search the full message history across all sessions using an FTS5 MATCH expression. " +
975
+ "Useful to locate past questions, answers, and context across the session lineage.",
976
+ inputSchema: jsonSchema({
977
+ type: "object",
978
+ properties: {
979
+ query: {
980
+ type: "string",
981
+ description: "FTS5 MATCH expression query (e.g. 'compaction AND error' or 'content:Vitest').",
982
+ },
983
+ },
984
+ required: ["query"],
985
+ }),
986
+ execute: async (input) => {
987
+ const query = typeof input.query === "string" ? input.query.trim() : "";
988
+ if (!query) {
989
+ return "ERROR: query MATCH expression is required.";
990
+ }
991
+ try {
992
+ const { getDatabase } = await import("../storage/db.js");
993
+ const db = getDatabase();
994
+ // Wrap FTS search query execution in try-catch to prevent malformed FTS syntax crashes (fixing GAP-03)
995
+ const rows = db
996
+ .prepare(`
997
+ SELECT session_id, seq, role, tool_name, content, tool_args, tool_output
998
+ FROM session_history_fts
999
+ WHERE session_history_fts MATCH ?
1000
+ ORDER BY rank
1001
+ LIMIT 50
1002
+ `)
1003
+ .all(query);
1004
+ if (rows.length === 0) {
1005
+ return `No session history matched the query: "${query}"`;
1006
+ }
1007
+ const results = rows.map((row) => ({
1008
+ session_id: row.session_id,
1009
+ seq: row.seq,
1010
+ role: row.role,
1011
+ tool_name: row.tool_name ?? undefined,
1012
+ content: row.content ?? undefined,
1013
+ tool_args: row.tool_args ?? undefined,
1014
+ tool_output: row.tool_output ?? undefined,
1015
+ }));
1016
+ return JSON.stringify({
1017
+ query,
1018
+ match_count: results.length,
1019
+ results,
1020
+ }, null, 2);
1021
+ }
1022
+ catch (err) {
1023
+ return `ERROR: FTS MATCH query failed. The FTS syntax might be malformed: ${err.message}`;
1024
+ }
1025
+ },
1026
+ });
724
1027
  // Native muonroi-tools builtins — ee_health, ee_feedback, usage_forensics,
725
1028
  // lsp_query, setup_guide, selfverify_*. These run IN-PROCESS; the CLI no
726
1029
  // longer self-spawns itself as an MCP server to expose them to its own inner
@@ -728,16 +1031,25 @@ export function createBuiltinTools(bash, mode, opts) {
728
1031
  // and a seed-time bug once persisted a crashing vitest-worker command). The
729
1032
  // muonroi-tools MCP server stays only for EXTERNAL agents. See native-tools.ts.
730
1033
  registerNativeMuonroiTools(tools, { cwd: bash.getCwd() });
1034
+ registerGsdWorkflowTools(tools, {
1035
+ cwd: bash.getCwd(),
1036
+ sessionModelId: opts?.modelId ?? "unknown",
1037
+ sessionId: opts?.sessionId,
1038
+ depth: opts?.depthTier ?? "standard",
1039
+ runTask: opts?.runTask,
1040
+ runDebate: opts?.runDebate,
1041
+ });
731
1042
  }
732
1043
  // Vision proxy tools — only for text-only models (DeepSeek, etc.)
733
1044
  if (opts?.modelId && needsVisionProxy(opts.modelId)) {
734
1045
  const cwd = bash.getCwd();
735
1046
  tools.analyze_image = dynamicTool({
736
- description: "Proactively analyze an image file via the vision proxy. " +
737
- "Use this IMMEDIATELY when you encounter any image file (.png, .jpg, .gif, .webp, .svg, etc.) " +
738
- "or when the user references an image. You CANNOT see images — this tool is your eyes. " +
1047
+ description: "Inspect an image and receive a <vision-observation> block — treat the result as your direct sight. " +
1048
+ "Use IMMEDIATELY when you encounter any image file (.png, .jpg, .gif, .webp, .svg, etc.) " +
1049
+ "or when the user references an image. Do not guess visual content. " +
739
1050
  "Accepts file paths, data URIs, or base64 strings. " +
740
- "Optionally provide a question to focus the analysis.",
1051
+ "Optionally provide a question to focus the analysis (OCR, layout, specific UI element). " +
1052
+ "If details remain unclear, call ask_vision_proxy or ask the user for another screenshot.",
741
1053
  inputSchema: jsonSchema({
742
1054
  type: "object",
743
1055
  properties: {
@@ -757,9 +1069,10 @@ export function createBuiltinTools(bash, mode, opts) {
757
1069
  },
758
1070
  });
759
1071
  tools.ask_vision_proxy = dynamicTool({
760
- description: "Ask a follow-up question about a previously analyzed image, or analyze a new image with a specific question. " +
761
- "Use this when you need to clarify visual details, compare elements, check colors, read text, etc. " +
762
- "You can reference a cached image by ID, or provide a file path to analyze a new image.",
1072
+ description: "Ask a follow-up about an image you are viewing (cached ID) or analyze a new file with a specific question. " +
1073
+ "Returns a <vision-observation> respond as if you saw it yourself. " +
1074
+ "Use when any detail in a prior observation is unclear: zoom on a region, read text, compare colors, verify UI state. " +
1075
+ "Reference a cached image by ID (from list_vision_cache) or provide a file path for a new image.",
763
1076
  inputSchema: jsonSchema({
764
1077
  type: "object",
765
1078
  properties: {
@@ -854,6 +1167,131 @@ export function createBuiltinTools(bash, mode, opts) {
854
1167
  for (const name of VISION_TOOL_NAMES)
855
1168
  delete tools[name];
856
1169
  }
1170
+ // ── Agent introspection tools: help the inner agent discover capabilities ──
1171
+ // These are always added last (after all filtering) so list_tools reflects reality.
1172
+ tools.list_mcp_servers = dynamicTool({
1173
+ description: "List every MCP server in the current user config (enabled or not). Returns id, label, enabled, transport, endpoint, and recommended_native (if any). " +
1174
+ "Use this to discover exactly what MCPs you have right now. For each MCP, see if there is a preferred native replacement (e.g. fetch_url instead of legacy fetch). " +
1175
+ "Memory, playwright, figma removed from defaults. Only enabled servers contribute tools this turn.",
1176
+ inputSchema: jsonSchema({
1177
+ type: "object",
1178
+ properties: {},
1179
+ additionalProperties: false,
1180
+ }),
1181
+ execute: async () => {
1182
+ const servers = loadMcpServers();
1183
+ // Native replacement recommendations (helps agent choose better tools)
1184
+ const RECOMMENDATIONS = {
1185
+ fetch: "Prefer native fetch_url (faster, always available, no external spawn).",
1186
+ tavily: "Prefer native web_search (direct Tavily API call, same results).",
1187
+ context7: "Consider keeping for library docs, or cache important docs into Experience Engine for offline use.",
1188
+ "muonroi-docs": null, // already our own controlled service
1189
+ playwright: "Use for full browser interaction/screenshots only; fetch_url sufficient for most content needs.",
1190
+ memory: "Use native ee_query / ee_write (Experience Engine) instead.",
1191
+ figma: "Add manually only if needed; no native equivalent yet.",
1192
+ };
1193
+ const summary = servers.map((s) => {
1194
+ const rec = RECOMMENDATIONS[s.id] ?? null;
1195
+ return {
1196
+ id: s.id,
1197
+ label: s.label,
1198
+ enabled: s.enabled,
1199
+ transport: s.transport,
1200
+ endpoint: s.url || (s.command ? `${s.command} ${(s.args || []).join(" ")}` : undefined),
1201
+ recommended_native: rec,
1202
+ };
1203
+ });
1204
+ return JSON.stringify({ count: summary.length, servers: summary }, null, 2);
1205
+ },
1206
+ });
1207
+ tools.list_tools = dynamicTool({
1208
+ description: "Compact grouped summary of every tool available this turn. " +
1209
+ "native = always-on builtins (fetch_url, web_search, bash, read_file, grep, ee_query, list_mcp_servers, list_tools, ...). " +
1210
+ "mcp = tools from your enabled MCP servers (prefixed mcp_<server-id>__). " +
1211
+ "Each line: name + short description (tells you purpose and rough usage). " +
1212
+ "Call list_mcp_servers() to see your MCP sources, then this to see concrete tools + how to use them. Full parameter schemas are in the system tool list this turn.",
1213
+ inputSchema: jsonSchema({
1214
+ type: "object",
1215
+ properties: {
1216
+ category: {
1217
+ type: "string",
1218
+ enum: ["all", "native", "mcp"],
1219
+ description: "Optional filter.",
1220
+ },
1221
+ },
1222
+ additionalProperties: false,
1223
+ }),
1224
+ execute: async (input) => {
1225
+ const cat = input?.category || "all";
1226
+ const grouped = { native: [], mcp: [] };
1227
+ for (const [name, tool] of Object.entries(tools)) {
1228
+ const t = tool;
1229
+ const shortDesc = (t.description || "").split("\n")[0].slice(0, 140);
1230
+ const entry = `${name}: ${shortDesc}`;
1231
+ if (name.startsWith("mcp_")) {
1232
+ if (cat === "all" || cat === "mcp")
1233
+ grouped.mcp.push(entry);
1234
+ }
1235
+ else {
1236
+ if (cat === "all" || cat === "native")
1237
+ grouped.native.push(entry);
1238
+ }
1239
+ }
1240
+ grouped.native.sort();
1241
+ grouped.mcp.sort();
1242
+ return JSON.stringify({
1243
+ total: Object.keys(tools).length,
1244
+ native_count: grouped.native.length,
1245
+ mcp_count: grouped.mcp.length,
1246
+ ...grouped,
1247
+ note: "Native tools are always preferred. MCP tools only from servers where enabled=true (see list_mcp_servers).",
1248
+ }, null, 2);
1249
+ },
1250
+ });
1251
+ tools.describe_tool = dynamicTool({
1252
+ description: "Get detailed usage information for a specific tool by name. Returns description, full input schema (parameters), and a short usage example or note. " +
1253
+ "Call this when you need precise 'how to use' details for a tool (e.g. describe_tool with name='fetch_url' or name='mcp_context7__something'). " +
1254
+ "This complements list_tools and list_mcp_servers.",
1255
+ inputSchema: jsonSchema({
1256
+ type: "object",
1257
+ properties: {
1258
+ name: {
1259
+ type: "string",
1260
+ description: "Exact tool name (e.g. 'fetch_url', 'web_search', 'mcp_context7__search' or any from list_tools)",
1261
+ },
1262
+ },
1263
+ required: ["name"],
1264
+ additionalProperties: false,
1265
+ }),
1266
+ execute: async (input) => {
1267
+ const name = typeof input?.name === "string" ? input.name.trim() : "";
1268
+ if (!name)
1269
+ return "ERROR: name is required";
1270
+ const tool = tools[name];
1271
+ if (!tool) {
1272
+ return JSON.stringify({
1273
+ name,
1274
+ error: "Tool not found in current tool set. Use list_tools to see available names.",
1275
+ }, null, 2);
1276
+ }
1277
+ const t = tool;
1278
+ const schema = t.inputSchema || tool.parameters || null;
1279
+ // Provide a minimal example note for common tools
1280
+ const examples = {
1281
+ fetch_url: 'Example: {"url": "https://example.com/docs", "format": "markdown"}',
1282
+ web_search: 'Example: {"query": "muonroi building block best practices", "maxResults": 5}',
1283
+ list_mcp_servers: "Call with no args: {}",
1284
+ list_tools: 'Example: {"category": "native"}',
1285
+ };
1286
+ return JSON.stringify({
1287
+ name,
1288
+ description: t.description,
1289
+ inputSchema: schema,
1290
+ example: examples[name] || "See inputSchema above. Call with correct parameters.",
1291
+ note: "Use the exact parameters from inputSchema when calling this tool.",
1292
+ }, null, 2);
1293
+ },
1294
+ });
857
1295
  return tools;
858
1296
  }
859
1297
  //# sourceMappingURL=registry.js.map
@@ -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;