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
@@ -6,15 +6,20 @@
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";
11
+ import { requestCouncilConvene } from "../orchestrator/council-request.js";
9
12
  import { canonicalizeBashCommand } from "../orchestrator/tool-args-hash.js";
10
13
  import { analyzeImageFromSource, askVisionProxy, listCachedImages } from "../providers/mcp-vision-bridge.js";
11
14
  import { needsVisionProxy } from "../providers/vision-proxy.js";
15
+ import { loadMcpServers } from "../utils/settings.js";
12
16
  import { getBashRun, sliceBashOutput } from "./bash-output-cache.js";
13
- import { editFile, readFile, writeFile } from "./file.js";
17
+ import { editFile, readFile, readFiles, writeFile } from "./file.js";
14
18
  import { FileTracker } from "./file-tracker.js";
15
- import { analyzeGitCommand, checkPushGate, checkSensitiveStaging, commitBlockedMessage, pushBlockedMessage, recordCommandOutcome, } from "./git-safety.js";
19
+ import { analyzeGitCommand, checkDestructiveOp, checkPushGate, checkSensitiveStaging, commitBlockedMessage, pushBlockedMessage, recordCommandOutcome, } from "./git-safety.js";
16
20
  import { executeGrep } from "./grep.js";
17
21
  import { registerNativeMuonroiTools } from "./native-tools.js";
22
+ import { registerNativeResearchTools } from "./research.js";
18
23
  import { VISION_TOOL_NAMES } from "./vision-gate.js";
19
24
  function getSafetyApprovedMap() {
20
25
  if (!globalThis.__muonroiSafetyApproved) {
@@ -84,20 +89,38 @@ export function createBuiltinTools(bash, mode, opts) {
84
89
  // One tracker per tool registry instance — shared across read/write/edit
85
90
  // calls in the same session. Enforces "must read before edit/overwrite".
86
91
  const fileTracker = new FileTracker();
92
+ // Native research tools (fetch_url, web_search) — always available.
93
+ // These are the in-process replacements for the old external MCP research servers.
94
+ registerNativeResearchTools(tools);
87
95
  // read_file
88
96
  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.",
97
+ 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
98
  inputSchema: jsonSchema({
91
99
  type: "object",
92
100
  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)" },
101
+ file_path: { type: "string", description: "Path to a single file to read (supports start_line/end_line)." },
102
+ file_paths: {
103
+ type: "array",
104
+ items: { type: "string" },
105
+ 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.",
106
+ },
107
+ start_line: { type: "number", description: "First line to read (1-based). Applies to file_path only." },
108
+ end_line: { type: "number", description: "Last line to read (1-based). Applies to file_path only." },
96
109
  },
97
- required: ["file_path"],
98
110
  }),
99
111
  execute: async (input) => {
100
- const result = readFile(input.file_path, bash.getCwd(), input.start_line, input.end_line, fileTracker);
112
+ const batch = Array.isArray(input.file_paths) && input.file_paths.length > 0
113
+ ? input.file_paths.filter((p) => typeof p === "string" && p.trim() !== "")
114
+ : [];
115
+ if (batch.length > 1) {
116
+ // Per-file fair-share of the output cap so the concatenated result
117
+ // stays under MAX_TOOL_OUTPUT_CHARS and every file survives (no silent
118
+ // head/tail drop of whole files). Floor keeps each file legible.
119
+ const perFileCap = Math.max(4_000, Math.floor(MAX_TOOL_OUTPUT_CHARS / batch.length));
120
+ return formatResult(readFiles(batch, bash.getCwd(), fileTracker, perFileCap));
121
+ }
122
+ const single = batch.length === 1 ? batch[0] : input.file_path;
123
+ const result = readFile(single, bash.getCwd(), input.start_line, input.end_line, fileTracker);
101
124
  return formatResult(result);
102
125
  },
103
126
  });
@@ -118,6 +141,137 @@ export function createBuiltinTools(bash, mode, opts) {
118
141
  return formatResult(result);
119
142
  },
120
143
  });
144
+ // compact — agent-initiated proactive context compaction. The model calls
145
+ // this to shed accumulated tool/conversation history mid-task (freeing
146
+ // context + resetting tool-call bloat) BEFORE it hits a tool-round limit,
147
+ // so a long task never gets interrupted. The request is queued here and
148
+ // consumed by the tool-engine's prepareStep boundary, which forces a
149
+ // compaction pass before the next LLM step, then the turn continues. A
150
+ // decisions/facts snapshot is preserved and high-value tool results stay
151
+ // rehydratable via ee_query "tool-artifact id=…". This is the proactive
152
+ // counterpart to the reactive tool-limit auto-recover.
153
+ tools.compact = dynamicTool({
154
+ 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.",
155
+ inputSchema: jsonSchema({
156
+ type: "object",
157
+ properties: {
158
+ focus: {
159
+ type: "string",
160
+ description: "Short note on what to keep in mind / preserve after compaction (e.g. the current sub-task).",
161
+ },
162
+ },
163
+ }),
164
+ execute: async (input) => {
165
+ requestProactiveCompact(typeof input?.focus === "string" ? input.focus : null);
166
+ return formatResult({
167
+ success: true,
168
+ 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=…".',
169
+ });
170
+ },
171
+ });
172
+ // convene_council — agent-initiated multi-model council. The model calls this
173
+ // when THIS request genuinely warrants a cross-provider debate (conflicting
174
+ // design tradeoffs, high-stakes decision). The request is queued here; the
175
+ // tool-engine consumes it from the outer restart loop, runs runCouncilV2 with
176
+ // convenePath:true (which suppresses ALL hardcoded post-debate decision
177
+ // surface — no card, no continuation), splices the synthesis into THIS tool's
178
+ // tool_result, and restarts the step so the model reads the conclusion as the
179
+ // result and continues. Registered only when the council is usable so the
180
+ // model never calls a council that cannot convene.
181
+ if (opts?.councilConfigured) {
182
+ tools.convene_council = dynamicTool({
183
+ description: "Convene the multi-model council to debate THIS request. Use ONLY when the task has genuinely conflicting design tradeoffs, needs a cross-provider/second-opinion review, or is a high-stakes architecture/analysis decision where a single model's view is insufficient. It runs a real multi-role debate across several models and returns a synthesized conclusion AS THIS TOOL'S RESULT. Do NOT use it for routine or low-ambiguity work — it is expensive. After calling, read the returned conclusion and continue; nothing is auto-decided for you.",
184
+ inputSchema: jsonSchema({
185
+ type: "object",
186
+ properties: {
187
+ reason: {
188
+ type: "string",
189
+ description: "Why this task needs a multi-model debate (the specific tradeoff or decision at stake).",
190
+ },
191
+ },
192
+ }),
193
+ execute: async (input, execOpts) => {
194
+ const reason = input && typeof input === "object" && typeof input.reason === "string"
195
+ ? input.reason
196
+ : null;
197
+ requestCouncilConvene(reason, execOpts?.toolCallId ?? null);
198
+ return formatResult({
199
+ success: true,
200
+ output: "Council convening — the multi-model debate runs now and its conclusion replaces this result before your next step. Read the conclusion, then continue.",
201
+ });
202
+ },
203
+ });
204
+ }
205
+ // ask_user — agent-initiated question to the human. The model calls this from
206
+ // its OWN judgment (e.g. after a convene_council conclusion, when it wants a
207
+ // go/no-go before implementing). The CLI does NOT synthesise options or decide
208
+ // the branch: question, options, and default all come from the model's input.
209
+ // execute() BLOCKS until the human answers; the answer becomes the tool result.
210
+ // Registered only when a UI answerer is wired (opts.askUser present).
211
+ if (opts?.askUser) {
212
+ const askUser = opts.askUser;
213
+ tools.ask_user = dynamicTool({
214
+ description: "Ask the human user a question and receive their answer AS THIS TOOL'S RESULT. Use when you need a decision, confirmation (e.g. 'proceed with implementation?'), or missing detail that only the user can provide — typically in an interactive discussion, or after a convene_council conclusion when you want a go/no-go before building. Supply the exact `question` and, optionally, `options` the user picks from (omit for a free-text answer). This BLOCKS until the user responds. Nothing is auto-decided: read their answer and continue from your own judgment. Do NOT use it to narrate or for rhetorical questions — only when you genuinely need input to proceed.",
215
+ inputSchema: jsonSchema({
216
+ type: "object",
217
+ properties: {
218
+ question: {
219
+ type: "string",
220
+ description: "The exact question to put to the user.",
221
+ },
222
+ context: {
223
+ type: "string",
224
+ description: "Optional short context shown under the question.",
225
+ },
226
+ options: {
227
+ type: "array",
228
+ description: "Optional choices the user picks from. Omit for a free-text answer. These are YOUR options — the CLI adds none.",
229
+ items: {
230
+ type: "object",
231
+ properties: {
232
+ label: { type: "string", description: "The choice shown to the user." },
233
+ description: { type: "string", description: "Optional one-line explanation of the choice." },
234
+ value: { type: "string", description: "Optional value returned when picked (defaults to the label)." },
235
+ },
236
+ required: ["label"],
237
+ },
238
+ },
239
+ defaultIndex: {
240
+ type: "number",
241
+ description: "Optional index into options for the pre-selected choice (defaults to 0 = first).",
242
+ },
243
+ },
244
+ required: ["question"],
245
+ }),
246
+ execute: async (input) => {
247
+ const obj = (input && typeof input === "object" ? input : {});
248
+ const question = typeof obj.question === "string" ? obj.question : "";
249
+ if (question.trim().length === 0) {
250
+ return formatResult({
251
+ success: false,
252
+ output: "ask_user requires a non-empty `question`.",
253
+ });
254
+ }
255
+ const rawOptions = Array.isArray(obj.options) ? obj.options : [];
256
+ const options = rawOptions
257
+ .filter((o) => !!o && typeof o === "object")
258
+ .map((o) => ({
259
+ label: typeof o.label === "string" ? o.label : String(o.label ?? ""),
260
+ description: typeof o.description === "string" ? o.description : undefined,
261
+ value: typeof o.value === "string" ? o.value : undefined,
262
+ }))
263
+ .filter((o) => o.label.length > 0);
264
+ const info = {
265
+ question,
266
+ context: typeof obj.context === "string" ? obj.context : undefined,
267
+ options: options.length > 0 ? options : undefined,
268
+ defaultIndex: typeof obj.defaultIndex === "number" ? obj.defaultIndex : undefined,
269
+ };
270
+ const answer = await askUser(info);
271
+ return formatResult({ success: true, output: answer });
272
+ },
273
+ });
274
+ }
121
275
  // bash — every foreground call goes through here. We track the LAST
122
276
  // canonical command + runId in SESSION-SCOPED state so we can inject a
123
277
  // reminder when the model issues another bash call that canonicalizes to
@@ -215,6 +369,17 @@ export function createBuiltinTools(bash, mode, opts) {
215
369
  // motivation (session 18285908637a). gitSafetyKey is STABLE per process
216
370
  // (or the real sessionId) — unlike repeatKey, whose anon fallback changes
217
371
  // on every registry rebuild and would silently drop the gate across turns.
372
+ // Destructive-op guard (pre-execution, any permission mode): block a
373
+ // command that would irreversibly discard uncommitted work (git
374
+ // checkout --/restore/reset --hard/clean, git stash drop/clear, or rm of
375
+ // a tracked file) when there is actually work at risk. Routed as
376
+ // `destructive-revert` so the tool-engine shows the safety askcard
377
+ // interactively and hard-blocks headless (autonomous sub-agents) — the
378
+ // fix for the /ideal plan-adherence agent silently reverting user files.
379
+ const destructive = checkDestructiveOp(cmd, bash.getCwd());
380
+ if (destructive.blocked) {
381
+ return _prefixBlock("destructive-revert", destructive.message);
382
+ }
218
383
  const gitShape = analyzeGitCommand(cmd);
219
384
  // Hard-block broad staging when sensitive files are present.
220
385
  // This runs PRE-EXECUTION (before bash.execute) regardless of permission mode.
@@ -253,7 +418,20 @@ export function createBuiltinTools(bash, mode, opts) {
253
418
  }
254
419
  }
255
420
  }
256
- if (input.background) {
421
+ const isLongRunning = (c) => {
422
+ const lower = c.toLowerCase().trim();
423
+ return (/\bvite\b/.test(lower) ||
424
+ /\bnodemon\b/.test(lower) ||
425
+ /\bwebpack-dev-server\b/.test(lower) ||
426
+ /\bnext\s+dev\b/.test(lower) ||
427
+ /\bwatch\b/.test(lower) ||
428
+ /--watch\b/.test(lower) ||
429
+ /\b-w\b/.test(lower) ||
430
+ /\bdev-server\b/.test(lower) ||
431
+ /\blive-server\b/.test(lower) ||
432
+ /\bhttp-server\b/.test(lower));
433
+ };
434
+ if (input.background || isLongRunning(cmd)) {
257
435
  const result = await bash.startBackground(input.command);
258
436
  return formatResult(result);
259
437
  }
@@ -378,6 +556,9 @@ export function createBuiltinTools(bash, mode, opts) {
378
556
  });
379
557
  // Agent mode gets write/edit/task/delegate tools
380
558
  if (mode === "agent") {
559
+ // Capture delegation functions for auto-routing logic below
560
+ const runTaskFn = opts?.runTask;
561
+ const runDelegationFn = opts?.runDelegation;
381
562
  // write_file
382
563
  tools.write_file = dynamicTool({
383
564
  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 +571,13 @@ export function createBuiltinTools(bash, mode, opts) {
390
571
  required: ["file_path", "content"],
391
572
  }),
392
573
  execute: async (input) => {
574
+ if (!input?.file_path?.trim() || input.content === undefined || input.content === null) {
575
+ return {
576
+ success: false,
577
+ output: 'BLOCKED (empty-write_file): write_file requires non-empty "file_path" and "content". ' +
578
+ 'Example: {"file_path":"src/foo.ts","content":"export const x = 1;\\n"}',
579
+ };
580
+ }
393
581
  const result = await writeFile(input.file_path, input.content, bash.getCwd(), fileTracker);
394
582
  return {
395
583
  success: result.success,
@@ -412,6 +600,17 @@ export function createBuiltinTools(bash, mode, opts) {
412
600
  required: ["file_path", "old_string", "new_string"],
413
601
  }),
414
602
  execute: async (input) => {
603
+ if (!input?.file_path?.trim() ||
604
+ input.old_string === undefined ||
605
+ input.old_string === null ||
606
+ input.new_string === undefined ||
607
+ input.new_string === null) {
608
+ return {
609
+ success: false,
610
+ output: "BLOCKED (empty-edit_file): edit_file requires file_path, old_string, and new_string. " +
611
+ 'Example: {"file_path":"src/foo.ts","old_string":"a","new_string":"b"}',
612
+ };
613
+ }
415
614
  const result = await editFile(input.file_path, input.old_string, input.new_string, bash.getCwd(), fileTracker);
416
615
  return {
417
616
  success: result.success,
@@ -475,9 +674,11 @@ export function createBuiltinTools(bash, mode, opts) {
475
674
  });
476
675
  // task
477
676
  if (opts?.runTask) {
478
- const runTask = opts.runTask;
479
677
  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).",
678
+ description: "Delegate a FOCUSED, SHORT foreground task to a sub-agent that blocks the current turn until complete. " +
679
+ "Use ONLY for quick edit/execute/verify work (default max ~12 rounds). " +
680
+ "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. " +
681
+ "Using task for long work will cause stalls and timeouts.",
481
682
  inputSchema: jsonSchema({
482
683
  type: "object",
483
684
  properties: {
@@ -489,13 +690,20 @@ export function createBuiltinTools(bash, mode, opts) {
489
690
  prompt: { type: "string", description: "Detailed instructions for the sub-agent" },
490
691
  maxToolRounds: {
491
692
  type: "number",
492
- description: "Optional maximum tool execution rounds (default is 12 for foreground tasks)",
693
+ description: "Optional maximum tool execution rounds. For research/explore use delegate + higher values (default 60); low values (≤20) only for task.",
493
694
  },
494
695
  },
495
696
  required: ["agent", "description", "prompt"],
496
697
  }),
497
698
  execute: async (input) => {
498
- const result = await runTask({
699
+ // Auto-route long research (explore agent or high round count) to true background delegation
700
+ // to prevent blocking the main turn and causing stall timeouts.
701
+ const isLongResearch = input.agent === "explore" || (typeof input.maxToolRounds === "number" && input.maxToolRounds > 25);
702
+ const executor = isLongResearch && runDelegationFn ? runDelegationFn : runTaskFn;
703
+ if (!executor) {
704
+ return { success: false, output: "No delegation executor available." };
705
+ }
706
+ const result = await executor({
499
707
  agent: input.agent,
500
708
  description: input.description,
501
709
  prompt: input.prompt,
@@ -530,7 +738,10 @@ export function createBuiltinTools(bash, mode, opts) {
530
738
  if (opts?.runDelegation) {
531
739
  const runDelegation = opts.runDelegation;
532
740
  tools.delegate = dynamicTool({
533
- description: "Launch a read-only background agent for longer research while you continue working.",
741
+ description: "Launch a read-only BACKGROUND research agent (usually 'explore') that runs independently in a separate process. " +
742
+ "Use this for ANY long-running research, codebase exploration, analysis, or tasks with high maxToolRounds. " +
743
+ "Main session continues working immediately. Results are delivered later via notifications or delegation_read. " +
744
+ "This is the PREFERRED tool over 'task' for explore/research to avoid blocking and timeouts.",
534
745
  inputSchema: jsonSchema({
535
746
  type: "object",
536
747
  properties: {
@@ -539,7 +750,7 @@ export function createBuiltinTools(bash, mode, opts) {
539
750
  prompt: { type: "string", description: "Detailed research instructions" },
540
751
  maxToolRounds: {
541
752
  type: "number",
542
- description: "Optional maximum tool execution rounds (default is 60 for explore delegations)",
753
+ description: "Optional maximum tool execution rounds (high values like 60+ expected for background research; do not use task for high values).",
543
754
  },
544
755
  },
545
756
  required: ["agent", "description", "prompt"],
@@ -652,7 +863,7 @@ export function createBuiltinTools(bash, mode, opts) {
652
863
  // output in-process by toolCallId. For an exact "tool-artifact id=X"
653
864
  // lookup this is the authoritative full content for THIS session and
654
865
  // works even when EE is down — the failure window long sessions hit.
655
- const { findArtifactByQuery, findArtifactOnDisk } = await import("../ee/artifact-cache.js");
866
+ const { findArtifactByQuery, findArtifactByHint, findArtifactOnDisk } = await import("../ee/artifact-cache.js");
656
867
  // Lived-experience telemetry: record where the rehydrate came from so
657
868
  // a "cảm nhận trong CLI" question (and the measure-first instrumentation)
658
869
  // sees cache vs disk vs ee vs needed-but-unavailable.
@@ -664,6 +875,15 @@ export function createBuiltinTools(bash, mode, opts) {
664
875
  recordRehydration(mem ? "cache" : "disk");
665
876
  return truncateOutput(`[tool-artifact id=${local.toolCallId} tool=${local.toolName} — rehydrated from ${src}]\n${local.content}`);
666
877
  }
878
+ // B (cheap-model anti-mù) — the exact id missed locally. Cheap models
879
+ // often pass FILE PATHS instead of the opaque toolCallId, which
880
+ // extractArtifactId can't parse. Try a path match against the local
881
+ // cache before the EE round-trip so a botched id still recovers.
882
+ const fuzzy = findArtifactByHint(query);
883
+ if (fuzzy) {
884
+ recordRehydration("cache");
885
+ 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}`);
886
+ }
667
887
  // EE fallback (cross-session / post-restart) → raw /api/search exact lookup.
668
888
  const { searchEE } = await import("../ee/search.js");
669
889
  const resp = await searchEE(query, {
@@ -721,6 +941,204 @@ export function createBuiltinTools(bash, mode, opts) {
721
941
  }
722
942
  },
723
943
  });
944
+ tools.retrieve_tool_result = dynamicTool({
945
+ description: "Retrieve the full output of a previous tool call by its tool_call_id. " +
946
+ "Searches local cache, disk cache, database history (including parent sessions), and remote Experience Engine. " +
947
+ "Use this to rehydrate elided tool outputs. Optional max_chars and chunk_index allow paginated retrieval.",
948
+ inputSchema: jsonSchema({
949
+ type: "object",
950
+ properties: {
951
+ tool_call_id: { type: "string", description: "The unique ID of the tool call (e.g. 'call_123')." },
952
+ max_chars: {
953
+ type: "number",
954
+ description: "Optional character limit for the returned chunk (useful for very large outputs).",
955
+ },
956
+ chunk_index: {
957
+ type: "number",
958
+ description: "Optional chunk index if splitting the output by max_chars (0-based, default 0).",
959
+ },
960
+ },
961
+ required: ["tool_call_id"],
962
+ }),
963
+ execute: async (input) => {
964
+ const toolCallId = typeof input.tool_call_id === "string" ? input.tool_call_id.trim() : "";
965
+ if (!toolCallId) {
966
+ return "ERROR: tool_call_id is required.";
967
+ }
968
+ const maxChars = typeof input.max_chars === "number" ? input.max_chars : undefined;
969
+ const chunkIndex = typeof input.chunk_index === "number" ? input.chunk_index : 0;
970
+ let content = null;
971
+ let source = "";
972
+ // Tier 1: LRU cache
973
+ try {
974
+ const { getArtifact } = await import("../ee/artifact-cache.js");
975
+ const tier1 = getArtifact(toolCallId);
976
+ if (tier1) {
977
+ content = tier1.content;
978
+ source = "Tier 1 LRU cache";
979
+ }
980
+ }
981
+ catch (err) {
982
+ console.error(`[tools:retrieve_tool_result] Tier 1 LRU check failed: ${err.message}`);
983
+ }
984
+ // Tier 2: Disk cache
985
+ if (!content) {
986
+ try {
987
+ const { findArtifactOnDisk } = await import("../ee/artifact-cache.js");
988
+ const tier2 = await findArtifactOnDisk(`id=${toolCallId}`);
989
+ if (tier2) {
990
+ content = tier2.content;
991
+ source = "Tier 2 disk cache";
992
+ }
993
+ }
994
+ catch (err) {
995
+ console.error(`[tools:retrieve_tool_result] Tier 2 disk check failed: ${err.message}`);
996
+ }
997
+ }
998
+ // Tier 3: SQLite database
999
+ if (!content && opts?.sessionId) {
1000
+ try {
1001
+ const { getSessionChain } = await import("../storage/index.js");
1002
+ const { getDatabase } = await import("../storage/db.js");
1003
+ const chain = getSessionChain(opts.sessionId);
1004
+ const db = getDatabase();
1005
+ for (let i = chain.length - 1; i >= 0; i--) {
1006
+ const row = db
1007
+ .prepare(`
1008
+ SELECT tr.output_json
1009
+ FROM tool_results tr
1010
+ JOIN tool_calls tc ON tc.id = tr.tool_call_row_id
1011
+ WHERE tc.tool_call_id = ? AND tc.session_id = ?
1012
+ LIMIT 1
1013
+ `)
1014
+ .get(toolCallId, chain[i]);
1015
+ if (row?.output_json) {
1016
+ const parsed = JSON.parse(row.output_json);
1017
+ if (parsed && typeof parsed === "object") {
1018
+ if ("output" in parsed && typeof parsed.output === "string") {
1019
+ content = parsed.output;
1020
+ }
1021
+ else if ("error" in parsed && typeof parsed.error === "string") {
1022
+ content = `ERROR: ${parsed.error}`;
1023
+ }
1024
+ else {
1025
+ content = JSON.stringify(parsed);
1026
+ }
1027
+ }
1028
+ else {
1029
+ content = String(parsed);
1030
+ }
1031
+ source = `Tier 3 SQLite database (session ${chain[i]})`;
1032
+ break;
1033
+ }
1034
+ }
1035
+ }
1036
+ catch (err) {
1037
+ console.error(`[tools:retrieve_tool_result] Tier 3 DB check failed: ${err.message}`);
1038
+ }
1039
+ }
1040
+ // Tier 4: Remote EE (behavioral collection only)
1041
+ if (!content) {
1042
+ try {
1043
+ const { searchEE } = await import("../ee/search.js");
1044
+ const resp = await searchEE(`tool-artifact id=${toolCallId}`, {
1045
+ collections: ["experience-behavioral"],
1046
+ limit: 1,
1047
+ });
1048
+ const bestHit = resp?.points?.[0];
1049
+ if (bestHit?.text) {
1050
+ content = bestHit.text;
1051
+ source = "Tier 4 remote EE (behavioral collection)";
1052
+ }
1053
+ }
1054
+ catch (err) {
1055
+ console.error(`[tools:retrieve_tool_result] Tier 4 EE check failed: ${err.message}`);
1056
+ }
1057
+ }
1058
+ if (content === null) {
1059
+ return `ERROR: Tool result not found for tool_call_id: ${toolCallId} in any tier.`;
1060
+ }
1061
+ const totalLength = content.length;
1062
+ if (maxChars !== undefined && maxChars > 0) {
1063
+ const totalChunks = Math.ceil(totalLength / maxChars);
1064
+ const start = chunkIndex * maxChars;
1065
+ const end = Math.min(start + maxChars, totalLength);
1066
+ if (start >= totalLength) {
1067
+ return `ERROR: chunk_index ${chunkIndex} is out of bounds. Total chunks available: ${totalChunks} (max_chars: ${maxChars}, total length: ${totalLength}).`;
1068
+ }
1069
+ const chunk = content.slice(start, end);
1070
+ return JSON.stringify({
1071
+ tool_call_id: toolCallId,
1072
+ source,
1073
+ chunk_index: chunkIndex,
1074
+ total_chunks: totalChunks,
1075
+ chunk_length: chunk.length,
1076
+ total_length: totalLength,
1077
+ content: chunk,
1078
+ }, null, 2);
1079
+ }
1080
+ return JSON.stringify({
1081
+ tool_call_id: toolCallId,
1082
+ source,
1083
+ total_length: totalLength,
1084
+ content,
1085
+ }, null, 2);
1086
+ },
1087
+ });
1088
+ tools.search_session_history = dynamicTool({
1089
+ description: "Search the full message history across all sessions using an FTS5 MATCH expression. " +
1090
+ "Useful to locate past questions, answers, and context across the session lineage.",
1091
+ inputSchema: jsonSchema({
1092
+ type: "object",
1093
+ properties: {
1094
+ query: {
1095
+ type: "string",
1096
+ description: "FTS5 MATCH expression query (e.g. 'compaction AND error' or 'content:Vitest').",
1097
+ },
1098
+ },
1099
+ required: ["query"],
1100
+ }),
1101
+ execute: async (input) => {
1102
+ const query = typeof input.query === "string" ? input.query.trim() : "";
1103
+ if (!query) {
1104
+ return "ERROR: query MATCH expression is required.";
1105
+ }
1106
+ try {
1107
+ const { getDatabase } = await import("../storage/db.js");
1108
+ const db = getDatabase();
1109
+ // Wrap FTS search query execution in try-catch to prevent malformed FTS syntax crashes (fixing GAP-03)
1110
+ const rows = db
1111
+ .prepare(`
1112
+ SELECT session_id, seq, role, tool_name, content, tool_args, tool_output
1113
+ FROM session_history_fts
1114
+ WHERE session_history_fts MATCH ?
1115
+ ORDER BY rank
1116
+ LIMIT 50
1117
+ `)
1118
+ .all(query);
1119
+ if (rows.length === 0) {
1120
+ return `No session history matched the query: "${query}"`;
1121
+ }
1122
+ const results = rows.map((row) => ({
1123
+ session_id: row.session_id,
1124
+ seq: row.seq,
1125
+ role: row.role,
1126
+ tool_name: row.tool_name ?? undefined,
1127
+ content: row.content ?? undefined,
1128
+ tool_args: row.tool_args ?? undefined,
1129
+ tool_output: row.tool_output ?? undefined,
1130
+ }));
1131
+ return JSON.stringify({
1132
+ query,
1133
+ match_count: results.length,
1134
+ results,
1135
+ }, null, 2);
1136
+ }
1137
+ catch (err) {
1138
+ return `ERROR: FTS MATCH query failed. The FTS syntax might be malformed: ${err.message}`;
1139
+ }
1140
+ },
1141
+ });
724
1142
  // Native muonroi-tools builtins — ee_health, ee_feedback, usage_forensics,
725
1143
  // lsp_query, setup_guide, selfverify_*. These run IN-PROCESS; the CLI no
726
1144
  // longer self-spawns itself as an MCP server to expose them to its own inner
@@ -728,16 +1146,25 @@ export function createBuiltinTools(bash, mode, opts) {
728
1146
  // and a seed-time bug once persisted a crashing vitest-worker command). The
729
1147
  // muonroi-tools MCP server stays only for EXTERNAL agents. See native-tools.ts.
730
1148
  registerNativeMuonroiTools(tools, { cwd: bash.getCwd() });
1149
+ registerGsdWorkflowTools(tools, {
1150
+ cwd: bash.getCwd(),
1151
+ sessionModelId: opts?.modelId ?? "unknown",
1152
+ sessionId: opts?.sessionId,
1153
+ depth: opts?.depthTier ?? "standard",
1154
+ runTask: opts?.runTask,
1155
+ runDebate: opts?.runDebate,
1156
+ });
731
1157
  }
732
1158
  // Vision proxy tools — only for text-only models (DeepSeek, etc.)
733
1159
  if (opts?.modelId && needsVisionProxy(opts.modelId)) {
734
1160
  const cwd = bash.getCwd();
735
1161
  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. " +
1162
+ description: "Inspect an image and receive a <vision-observation> block — treat the result as your direct sight. " +
1163
+ "Use IMMEDIATELY when you encounter any image file (.png, .jpg, .gif, .webp, .svg, etc.) " +
1164
+ "or when the user references an image. Do not guess visual content. " +
739
1165
  "Accepts file paths, data URIs, or base64 strings. " +
740
- "Optionally provide a question to focus the analysis.",
1166
+ "Optionally provide a question to focus the analysis (OCR, layout, specific UI element). " +
1167
+ "If details remain unclear, call ask_vision_proxy or ask the user for another screenshot.",
741
1168
  inputSchema: jsonSchema({
742
1169
  type: "object",
743
1170
  properties: {
@@ -757,9 +1184,10 @@ export function createBuiltinTools(bash, mode, opts) {
757
1184
  },
758
1185
  });
759
1186
  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.",
1187
+ description: "Ask a follow-up about an image you are viewing (cached ID) or analyze a new file with a specific question. " +
1188
+ "Returns a <vision-observation> respond as if you saw it yourself. " +
1189
+ "Use when any detail in a prior observation is unclear: zoom on a region, read text, compare colors, verify UI state. " +
1190
+ "Reference a cached image by ID (from list_vision_cache) or provide a file path for a new image.",
763
1191
  inputSchema: jsonSchema({
764
1192
  type: "object",
765
1193
  properties: {
@@ -854,6 +1282,131 @@ export function createBuiltinTools(bash, mode, opts) {
854
1282
  for (const name of VISION_TOOL_NAMES)
855
1283
  delete tools[name];
856
1284
  }
1285
+ // ── Agent introspection tools: help the inner agent discover capabilities ──
1286
+ // These are always added last (after all filtering) so list_tools reflects reality.
1287
+ tools.list_mcp_servers = dynamicTool({
1288
+ description: "List every MCP server in the current user config (enabled or not). Returns id, label, enabled, transport, endpoint, and recommended_native (if any). " +
1289
+ "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). " +
1290
+ "Memory, playwright, figma removed from defaults. Only enabled servers contribute tools this turn.",
1291
+ inputSchema: jsonSchema({
1292
+ type: "object",
1293
+ properties: {},
1294
+ additionalProperties: false,
1295
+ }),
1296
+ execute: async () => {
1297
+ const servers = loadMcpServers();
1298
+ // Native replacement recommendations (helps agent choose better tools)
1299
+ const RECOMMENDATIONS = {
1300
+ fetch: "Prefer native fetch_url (faster, always available, no external spawn).",
1301
+ tavily: "Prefer native web_search (direct Tavily API call, same results).",
1302
+ context7: "Consider keeping for library docs, or cache important docs into Experience Engine for offline use.",
1303
+ "muonroi-docs": null, // already our own controlled service
1304
+ playwright: "Use for full browser interaction/screenshots only; fetch_url sufficient for most content needs.",
1305
+ memory: "Use native ee_query / ee_write (Experience Engine) instead.",
1306
+ figma: "Add manually only if needed; no native equivalent yet.",
1307
+ };
1308
+ const summary = servers.map((s) => {
1309
+ const rec = RECOMMENDATIONS[s.id] ?? null;
1310
+ return {
1311
+ id: s.id,
1312
+ label: s.label,
1313
+ enabled: s.enabled,
1314
+ transport: s.transport,
1315
+ endpoint: s.url || (s.command ? `${s.command} ${(s.args || []).join(" ")}` : undefined),
1316
+ recommended_native: rec,
1317
+ };
1318
+ });
1319
+ return JSON.stringify({ count: summary.length, servers: summary }, null, 2);
1320
+ },
1321
+ });
1322
+ tools.list_tools = dynamicTool({
1323
+ description: "Compact grouped summary of every tool available this turn. " +
1324
+ "native = always-on builtins (fetch_url, web_search, bash, read_file, grep, ee_query, list_mcp_servers, list_tools, ...). " +
1325
+ "mcp = tools from your enabled MCP servers (prefixed mcp_<server-id>__). " +
1326
+ "Each line: name + short description (tells you purpose and rough usage). " +
1327
+ "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.",
1328
+ inputSchema: jsonSchema({
1329
+ type: "object",
1330
+ properties: {
1331
+ category: {
1332
+ type: "string",
1333
+ enum: ["all", "native", "mcp"],
1334
+ description: "Optional filter.",
1335
+ },
1336
+ },
1337
+ additionalProperties: false,
1338
+ }),
1339
+ execute: async (input) => {
1340
+ const cat = input?.category || "all";
1341
+ const grouped = { native: [], mcp: [] };
1342
+ for (const [name, tool] of Object.entries(tools)) {
1343
+ const t = tool;
1344
+ const shortDesc = (t.description || "").split("\n")[0].slice(0, 140);
1345
+ const entry = `${name}: ${shortDesc}`;
1346
+ if (name.startsWith("mcp_")) {
1347
+ if (cat === "all" || cat === "mcp")
1348
+ grouped.mcp.push(entry);
1349
+ }
1350
+ else {
1351
+ if (cat === "all" || cat === "native")
1352
+ grouped.native.push(entry);
1353
+ }
1354
+ }
1355
+ grouped.native.sort();
1356
+ grouped.mcp.sort();
1357
+ return JSON.stringify({
1358
+ total: Object.keys(tools).length,
1359
+ native_count: grouped.native.length,
1360
+ mcp_count: grouped.mcp.length,
1361
+ ...grouped,
1362
+ note: "Native tools are always preferred. MCP tools only from servers where enabled=true (see list_mcp_servers).",
1363
+ }, null, 2);
1364
+ },
1365
+ });
1366
+ tools.describe_tool = dynamicTool({
1367
+ description: "Get detailed usage information for a specific tool by name. Returns description, full input schema (parameters), and a short usage example or note. " +
1368
+ "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'). " +
1369
+ "This complements list_tools and list_mcp_servers.",
1370
+ inputSchema: jsonSchema({
1371
+ type: "object",
1372
+ properties: {
1373
+ name: {
1374
+ type: "string",
1375
+ description: "Exact tool name (e.g. 'fetch_url', 'web_search', 'mcp_context7__search' or any from list_tools)",
1376
+ },
1377
+ },
1378
+ required: ["name"],
1379
+ additionalProperties: false,
1380
+ }),
1381
+ execute: async (input) => {
1382
+ const name = typeof input?.name === "string" ? input.name.trim() : "";
1383
+ if (!name)
1384
+ return "ERROR: name is required";
1385
+ const tool = tools[name];
1386
+ if (!tool) {
1387
+ return JSON.stringify({
1388
+ name,
1389
+ error: "Tool not found in current tool set. Use list_tools to see available names.",
1390
+ }, null, 2);
1391
+ }
1392
+ const t = tool;
1393
+ const schema = t.inputSchema || tool.parameters || null;
1394
+ // Provide a minimal example note for common tools
1395
+ const examples = {
1396
+ fetch_url: 'Example: {"url": "https://example.com/docs", "format": "markdown"}',
1397
+ web_search: 'Example: {"query": "muonroi building block best practices", "maxResults": 5}',
1398
+ list_mcp_servers: "Call with no args: {}",
1399
+ list_tools: 'Example: {"category": "native"}',
1400
+ };
1401
+ return JSON.stringify({
1402
+ name,
1403
+ description: t.description,
1404
+ inputSchema: schema,
1405
+ example: examples[name] || "See inputSchema above. Call with correct parameters.",
1406
+ note: "Use the exact parameters from inputSchema when calling this tool.",
1407
+ }, null, 2);
1408
+ },
1409
+ });
857
1410
  return tools;
858
1411
  }
859
1412
  //# sourceMappingURL=registry.js.map