muonroi-cli 1.7.2 → 1.8.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 (322) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +122 -122
  3. package/dist/packages/agent-harness-core/src/event-filter.js +1 -0
  4. package/dist/packages/agent-harness-core/src/event-redact.js +8 -0
  5. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +16 -0
  6. package/dist/packages/agent-harness-core/src/mcp-server.js +88 -10
  7. package/dist/packages/agent-harness-core/src/protocol.d.ts +15 -0
  8. package/dist/packages/agent-harness-core/src/selector.js +2 -2
  9. package/dist/packages/agent-harness-core/src/transports/sidechannel.js +1 -1
  10. package/dist/packages/agent-harness-opentui/src/agent-mode.js +1 -1
  11. package/dist/packages/agent-harness-opentui/src/install.js +1 -1
  12. package/dist/src/__test-stubs__/vitest-setup.js +4 -0
  13. package/dist/src/agent-harness/__tests__/mock-model.spec.js +54 -0
  14. package/dist/src/agent-harness/mock-model.d.ts +1 -1
  15. package/dist/src/agent-harness/mock-model.js +32 -3
  16. package/dist/src/agent-harness/test-spawn.js +3 -1
  17. package/dist/src/chat/chat-keychain.js +9 -1
  18. package/dist/src/cli/cost-forensics.js +12 -12
  19. package/dist/src/cli/keys.d.ts +2 -2
  20. package/dist/src/cli/keys.js +107 -28
  21. package/dist/src/cli/usage-report.js +2 -2
  22. package/dist/src/council/__tests__/abort-threading.test.d.ts +1 -0
  23. package/dist/src/council/__tests__/abort-threading.test.js +193 -0
  24. package/dist/src/council/__tests__/clarification-prompt.test.js +21 -1
  25. package/dist/src/council/__tests__/council-turn-length-emit.test.d.ts +1 -0
  26. package/dist/src/council/__tests__/council-turn-length-emit.test.js +130 -0
  27. package/dist/src/council/__tests__/debate-round-budget.test.d.ts +1 -0
  28. package/dist/src/council/__tests__/debate-round-budget.test.js +45 -0
  29. package/dist/src/council/__tests__/evaluator-metrics.test.js +3 -0
  30. package/dist/src/council/__tests__/post-debate-recommendation.test.d.ts +1 -0
  31. package/dist/src/council/__tests__/post-debate-recommendation.test.js +58 -0
  32. package/dist/src/council/__tests__/research-tools.test.js +4 -0
  33. package/dist/src/council/__tests__/round-tools.test.js +6 -0
  34. package/dist/src/council/clarifier-question-cap.test.d.ts +12 -0
  35. package/dist/src/council/clarifier-question-cap.test.js +73 -0
  36. package/dist/src/council/clarifier.d.ts +29 -1
  37. package/dist/src/council/clarifier.js +64 -1
  38. package/dist/src/council/debate-planner.d.ts +2 -1
  39. package/dist/src/council/debate-planner.js +5 -3
  40. package/dist/src/council/debate.d.ts +9 -0
  41. package/dist/src/council/debate.js +88 -8
  42. package/dist/src/council/index.d.ts +46 -1
  43. package/dist/src/council/index.js +125 -19
  44. package/dist/src/council/llm.js +41 -13
  45. package/dist/src/council/prompts.js +56 -21
  46. package/dist/src/council/types.d.ts +14 -1
  47. package/dist/src/ee/__tests__/export-transcripts.test.js +1 -1
  48. package/dist/src/ee/bridge.d.ts +3 -1
  49. package/dist/src/ee/bridge.js +9 -3
  50. package/dist/src/ee/bridge.test.js +1 -2
  51. package/dist/src/ee/client.js +15 -2
  52. package/dist/src/ee/recall-ledger.d.ts +20 -0
  53. package/dist/src/ee/recall-ledger.js +40 -1
  54. package/dist/src/ee/search.d.ts +25 -0
  55. package/dist/src/ee/search.js +73 -0
  56. package/dist/src/ee/types.d.ts +15 -1
  57. package/dist/src/ee/who-am-i.d.ts +41 -0
  58. package/dist/src/ee/who-am-i.js +143 -0
  59. package/dist/src/ee/who-am-i.test.d.ts +1 -0
  60. package/dist/src/ee/who-am-i.test.js +101 -0
  61. package/dist/src/generated/version.d.ts +1 -1
  62. package/dist/src/generated/version.js +1 -1
  63. package/dist/src/headless/council-answers.js +1 -0
  64. package/dist/src/headless/output.d.ts +30 -1
  65. package/dist/src/headless/output.js +180 -0
  66. package/dist/src/headless/output.test.js +61 -1
  67. package/dist/src/hooks/index.js +48 -2
  68. package/dist/src/index.d.ts +2 -0
  69. package/dist/src/index.js +55 -60
  70. package/dist/src/lsp/client-normalize.test.d.ts +12 -0
  71. package/dist/src/lsp/client-normalize.test.js +34 -0
  72. package/dist/src/lsp/client.d.ts +1 -0
  73. package/dist/src/lsp/client.js +10 -2
  74. package/dist/src/lsp/manager.d.ts +1 -1
  75. package/dist/src/lsp/manager.js +2 -2
  76. package/dist/src/lsp/manager.test.js +2 -2
  77. package/dist/src/lsp/runtime.d.ts +1 -1
  78. package/dist/src/lsp/runtime.js +2 -2
  79. package/dist/src/maintain/__tests__/gh-create-pr.test.js +7 -3
  80. package/dist/src/maintain/__tests__/pr-builder.test.js +7 -3
  81. package/dist/src/mcp/__tests__/client-pool.spec.js +3 -3
  82. package/dist/src/mcp/__tests__/ee-tools.test.js +42 -14
  83. package/dist/src/mcp/__tests__/forensics-tools.test.js +3 -3
  84. package/dist/src/mcp/__tests__/lsp-tools.test.js +4 -4
  85. package/dist/src/mcp/client-pool.d.ts +1 -1
  86. package/dist/src/mcp/client-pool.js +25 -9
  87. package/dist/src/mcp/ee-tools.d.ts +10 -0
  88. package/dist/src/mcp/ee-tools.js +34 -0
  89. package/dist/src/mcp/oauth-callback.js +2 -2
  90. package/dist/src/mcp/parse-headers.test.js +14 -14
  91. package/dist/src/mcp/self-verify-jobs.js +1 -3
  92. package/dist/src/mcp/setup-guide-text.js +74 -74
  93. package/dist/src/mcp/smoke.test.js +43 -43
  94. package/dist/src/models/catalog-gemini.test.js +12 -10
  95. package/dist/src/models/catalog.json +106 -38
  96. package/dist/src/ops/doctor.js +7 -7
  97. package/dist/src/orchestrator/__tests__/auto-commit.test.d.ts +1 -0
  98. package/dist/src/orchestrator/__tests__/auto-commit.test.js +142 -0
  99. package/dist/src/orchestrator/__tests__/batch-turn-runner.test.js +2 -0
  100. package/dist/src/orchestrator/__tests__/delegations.test.d.ts +1 -0
  101. package/dist/src/orchestrator/__tests__/delegations.test.js +96 -0
  102. package/dist/src/orchestrator/__tests__/message-processor.test.js +1 -0
  103. package/dist/src/orchestrator/__tests__/stream-runner.test.js +29 -0
  104. package/dist/src/orchestrator/agent.test.js +5 -2
  105. package/dist/src/orchestrator/auto-commit.d.ts +110 -0
  106. package/dist/src/orchestrator/auto-commit.js +364 -0
  107. package/dist/src/orchestrator/batch-turn-runner.d.ts +3 -2
  108. package/dist/src/orchestrator/batch-turn-runner.js +2 -1
  109. package/dist/src/orchestrator/compaction-proposer-prompt.d.ts +8 -0
  110. package/dist/src/orchestrator/compaction-proposer-prompt.js +43 -0
  111. package/dist/src/orchestrator/compaction.d.ts +22 -0
  112. package/dist/src/orchestrator/compaction.js +42 -0
  113. package/dist/src/orchestrator/delegations.d.ts +1 -0
  114. package/dist/src/orchestrator/delegations.js +41 -0
  115. package/dist/src/orchestrator/error-utils.js +27 -2
  116. package/dist/src/orchestrator/message-processor.d.ts +21 -5
  117. package/dist/src/orchestrator/message-processor.js +219 -2573
  118. package/dist/src/orchestrator/orchestrator.d.ts +8 -2
  119. package/dist/src/orchestrator/orchestrator.js +187 -34
  120. package/dist/src/orchestrator/preprocessor.d.ts +13 -0
  121. package/dist/src/orchestrator/preprocessor.js +145 -0
  122. package/dist/src/orchestrator/prompts.d.ts +8 -0
  123. package/dist/src/orchestrator/prompts.js +76 -60
  124. package/dist/src/orchestrator/safety-askcard.d.ts +66 -0
  125. package/dist/src/orchestrator/safety-askcard.js +74 -0
  126. package/dist/src/orchestrator/sandbox.test.js +8 -5
  127. package/dist/src/orchestrator/scope-ceiling.js +1 -1
  128. package/dist/src/orchestrator/stall-watchdog.d.ts +47 -0
  129. package/dist/src/orchestrator/stall-watchdog.js +23 -0
  130. package/dist/src/orchestrator/stall-watchdog.test.js +36 -1
  131. package/dist/src/orchestrator/stream-runner.js +52 -30
  132. package/dist/src/orchestrator/sub-agent-model-tier.js +1 -1
  133. package/dist/src/orchestrator/subagent-compactor.d.ts +14 -0
  134. package/dist/src/orchestrator/subagent-compactor.js +83 -10
  135. package/dist/src/orchestrator/subagent-compactor.spec.js +132 -0
  136. package/dist/src/orchestrator/text-tool-call-detector.d.ts +9 -5
  137. package/dist/src/orchestrator/text-tool-call-detector.js +16 -12
  138. package/dist/src/orchestrator/text-tool-call-detector.test.js +66 -8
  139. package/dist/src/orchestrator/tool-args-repair.js +1 -1
  140. package/dist/src/orchestrator/tool-engine.d.ts +151 -0
  141. package/dist/src/orchestrator/tool-engine.js +3079 -0
  142. package/dist/src/orchestrator/turn-runner-deps.d.ts +1 -0
  143. package/dist/src/pil/__tests__/discovery-types.test.js +15 -4
  144. package/dist/src/pil/__tests__/discovery.test.js +89 -145
  145. package/dist/src/pil/__tests__/dual-run.test.js +2 -0
  146. package/dist/src/pil/__tests__/layer1-intent-trace.test.js +3 -0
  147. package/dist/src/pil/__tests__/layer1-intent.test.js +3 -0
  148. package/dist/src/pil/__tests__/layer16-clarity.test.js +35 -32
  149. package/dist/src/pil/__tests__/layer18-acceptance.test.js +1 -78
  150. package/dist/src/pil/__tests__/layer2_5-ponytail.test.d.ts +1 -0
  151. package/dist/src/pil/__tests__/layer2_5-ponytail.test.js +53 -0
  152. package/dist/src/pil/__tests__/layer3-ee-injection.test.js +67 -4
  153. package/dist/src/pil/__tests__/layer3-injected-chunk.test.js +14 -2
  154. package/dist/src/pil/__tests__/layer4-gsd.test.js +30 -0
  155. package/dist/src/pil/__tests__/layer5-context.test.js +39 -1
  156. package/dist/src/pil/__tests__/layer6-output.test.js +30 -2
  157. package/dist/src/pil/__tests__/orchestrator-integration.test.js +3 -1
  158. package/dist/src/pil/__tests__/pipeline.test.js +11 -8
  159. package/dist/src/pil/__tests__/response-tools.test.js +52 -0
  160. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  161. package/dist/src/pil/agent-operating-contract.js +5 -3
  162. package/dist/src/pil/agent-operating-contract.test.js +2 -2
  163. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  164. package/dist/src/pil/cheap-model-playbook.js +1 -1
  165. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  166. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  167. package/dist/src/pil/config.d.ts +20 -0
  168. package/dist/src/pil/config.js +35 -0
  169. package/dist/src/pil/discovery-types.d.ts +32 -9
  170. package/dist/src/pil/discovery.d.ts +3 -3
  171. package/dist/src/pil/discovery.js +138 -244
  172. package/dist/src/pil/index.d.ts +1 -1
  173. package/dist/src/pil/index.js +1 -1
  174. package/dist/src/pil/layer1-intent.d.ts +9 -1
  175. package/dist/src/pil/layer1-intent.js +99 -44
  176. package/dist/src/pil/layer1-intent.test.js +112 -2
  177. package/dist/src/pil/layer15-context-scan.js +1 -1
  178. package/dist/src/pil/layer16-clarity.d.ts +21 -25
  179. package/dist/src/pil/layer16-clarity.js +52 -88
  180. package/dist/src/pil/layer18-acceptance.d.ts +13 -3
  181. package/dist/src/pil/layer18-acceptance.js +1 -75
  182. package/dist/src/pil/layer2-personality.js +7 -8
  183. package/dist/src/pil/layer2_5-ponytail.d.ts +2 -0
  184. package/dist/src/pil/layer2_5-ponytail.js +41 -0
  185. package/dist/src/pil/layer3-ee-injection.js +180 -14
  186. package/dist/src/pil/layer4-gsd.js +22 -8
  187. package/dist/src/pil/layer5-context.d.ts +1 -0
  188. package/dist/src/pil/layer5-context.js +26 -11
  189. package/dist/src/pil/layer6-output.js +23 -5
  190. package/dist/src/pil/llm-classify.js +3 -3
  191. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  192. package/dist/src/pil/native-capabilities-workbook.js +4 -3
  193. package/dist/src/pil/pipeline.js +15 -1
  194. package/dist/src/pil/response-tools.d.ts +16 -0
  195. package/dist/src/pil/response-tools.js +41 -0
  196. package/dist/src/pil/schema.d.ts +8 -0
  197. package/dist/src/pil/schema.js +24 -3
  198. package/dist/src/pil/task-tier-map.js +7 -7
  199. package/dist/src/pil/types.d.ts +9 -3
  200. package/dist/src/product-loop/__tests__/discovery-interview.test.js +103 -1
  201. package/dist/src/product-loop/__tests__/gather-selectable-alts.test.js +34 -0
  202. package/dist/src/product-loop/__tests__/sprint-self-verify.test.js +12 -12
  203. package/dist/src/product-loop/discovery-interview.d.ts +20 -0
  204. package/dist/src/product-loop/discovery-interview.js +121 -7
  205. package/dist/src/product-loop/done-gate.js +3 -3
  206. package/dist/src/product-loop/gather.js +19 -5
  207. package/dist/src/product-loop/loop-driver.js +20 -20
  208. package/dist/src/product-loop/progress-snapshot.js +4 -4
  209. package/dist/src/product-loop/sprint-self-verify.js +2 -2
  210. package/dist/src/providers/__tests__/reasoning-roundtrip.test.js +12 -0
  211. package/dist/src/providers/auth/__tests__/gemini-oauth.test.d.ts +1 -5
  212. package/dist/src/providers/auth/__tests__/gemini-oauth.test.js +1 -5
  213. package/dist/src/providers/auth/gcloud.d.ts +28 -0
  214. package/dist/src/providers/auth/gcloud.js +102 -0
  215. package/dist/src/providers/auth/gemini-oauth.d.ts +46 -19
  216. package/dist/src/providers/auth/gemini-oauth.js +292 -105
  217. package/dist/src/providers/auth/grok-oauth.d.ts +1 -1
  218. package/dist/src/providers/auth/grok-oauth.js +1 -1
  219. package/dist/src/providers/auth/registry.js +28 -6
  220. package/dist/src/providers/gemini.d.ts +1 -1
  221. package/dist/src/providers/gemini.js +10 -3
  222. package/dist/src/providers/keychain.d.ts +2 -2
  223. package/dist/src/providers/keychain.js +20 -2
  224. package/dist/src/providers/mcp-vision-bridge.js +48 -48
  225. package/dist/src/providers/openai.js +5 -1
  226. package/dist/src/providers/runtime.d.ts +1 -1
  227. package/dist/src/providers/runtime.js +11 -2
  228. package/dist/src/providers/siliconflow-sse-repair.js +1 -1
  229. package/dist/src/providers/strategies/google.strategy.d.ts +9 -2
  230. package/dist/src/providers/strategies/google.strategy.js +159 -9
  231. package/dist/src/providers/strategies/thinking-mode.js +19 -6
  232. package/dist/src/providers/types.d.ts +1 -1
  233. package/dist/src/reporter/index.js +1 -1
  234. package/dist/src/router/decide.test.js +40 -8
  235. package/dist/src/router/step-router.d.ts +20 -0
  236. package/dist/src/router/step-router.js +73 -0
  237. package/dist/src/scaffold/bb-ecosystem-apply.js +47 -47
  238. package/dist/src/scaffold/bb-quality-gate.js +5 -5
  239. package/dist/src/scaffold/continuation-prompt.js +60 -60
  240. package/dist/src/scaffold/init-new.js +453 -453
  241. package/dist/src/self-qa/__tests__/scenario-planner.test.js +3 -3
  242. package/dist/src/self-qa/agentic-loop.js +19 -19
  243. package/dist/src/self-qa/orchestrator.js +5 -5
  244. package/dist/src/self-qa/scenario-planner.js +1 -1
  245. package/dist/src/self-qa/spec-emitter.js +4 -4
  246. package/dist/src/storage/__tests__/migrations.test.js +2 -2
  247. package/dist/src/storage/index.d.ts +1 -1
  248. package/dist/src/storage/index.js +1 -1
  249. package/dist/src/storage/interaction-log.js +5 -5
  250. package/dist/src/storage/migrations.js +122 -122
  251. package/dist/src/storage/session-experience-store.js +4 -4
  252. package/dist/src/storage/sessions.js +43 -43
  253. package/dist/src/storage/transcript-view.js +7 -1
  254. package/dist/src/storage/transcript.d.ts +1 -0
  255. package/dist/src/storage/transcript.js +55 -0
  256. package/dist/src/storage/ui-interaction-log.d.ts +17 -0
  257. package/dist/src/storage/usage.js +14 -14
  258. package/dist/src/storage/workspaces.js +12 -12
  259. package/dist/src/tools/__tests__/native-tools.test.js +6 -0
  260. package/dist/src/tools/bash.d.ts +36 -23
  261. package/dist/src/tools/bash.js +59 -301
  262. package/dist/src/tools/bash.test.js +2 -257
  263. package/dist/src/tools/file-tracker.d.ts +5 -0
  264. package/dist/src/tools/file-tracker.js +14 -0
  265. package/dist/src/tools/file.js +2 -0
  266. package/dist/src/tools/git-safety.d.ts +38 -1
  267. package/dist/src/tools/git-safety.js +94 -4
  268. package/dist/src/tools/git-safety.test.js +45 -1
  269. package/dist/src/tools/native-tools.d.ts +1 -1
  270. package/dist/src/tools/native-tools.js +56 -0
  271. package/dist/src/tools/registry-bash-empty-command.test.js +4 -3
  272. package/dist/src/tools/registry-git-safety.test.js +17 -6
  273. package/dist/src/tools/registry.d.ts +5 -0
  274. package/dist/src/tools/registry.js +185 -11
  275. package/dist/src/types/index.d.ts +7 -1
  276. package/dist/src/ui/app.d.ts +1 -0
  277. package/dist/src/ui/app.js +0 -0
  278. package/dist/src/ui/components/council-question-card.js +1 -0
  279. package/dist/src/ui/components/message-view.js +37 -3
  280. package/dist/src/ui/components/structured-response-view.js +7 -0
  281. package/dist/src/ui/components/task-list-panel.js +3 -12
  282. package/dist/src/ui/containers/chat-feed.d.ts +40 -0
  283. package/dist/src/ui/containers/chat-feed.js +66 -0
  284. package/dist/src/ui/containers/modals-layer.d.ts +87 -0
  285. package/dist/src/ui/containers/modals-layer.js +18 -0
  286. package/dist/src/ui/slash/__tests__/menu-parity.test.d.ts +1 -0
  287. package/dist/src/ui/slash/__tests__/menu-parity.test.js +1 -0
  288. package/dist/src/ui/slash/__tests__/ponytail.test.d.ts +1 -0
  289. package/dist/src/ui/slash/__tests__/ponytail.test.js +37 -0
  290. package/dist/src/ui/slash/council-inspect.js +4 -4
  291. package/dist/src/ui/slash/export.js +16 -1
  292. package/dist/src/ui/slash/menu-items.js +1 -0
  293. package/dist/src/ui/slash/ponytail.d.ts +2 -0
  294. package/dist/src/ui/slash/ponytail.js +19 -0
  295. package/dist/src/ui/status-bar/store.js +0 -1
  296. package/dist/src/ui/status-bar/store.test.js +2 -2
  297. package/dist/src/ui/use-app-logic.d.ts +26 -0
  298. package/dist/src/ui/use-app-logic.js +0 -0
  299. package/dist/src/ui/utils/relaunch.js +1 -1
  300. package/dist/src/ui/utils/text.d.ts +11 -0
  301. package/dist/src/ui/utils/text.js +21 -1
  302. package/dist/src/ui/utils/text.test.js +25 -1
  303. package/dist/src/ui/utils/tools.js +3 -1
  304. package/dist/src/usage/cost-log.js +2 -2
  305. package/dist/src/usage/estimator.d.ts +14 -0
  306. package/dist/src/usage/estimator.js +22 -0
  307. package/dist/src/utils/__tests__/compaction-caps.test.d.ts +21 -0
  308. package/dist/src/utils/__tests__/compaction-caps.test.js +187 -0
  309. package/dist/src/utils/__tests__/llm-deadline-abort.test.d.ts +1 -0
  310. package/dist/src/utils/__tests__/llm-deadline-abort.test.js +33 -0
  311. package/dist/src/utils/clipboard-image.js +23 -23
  312. package/dist/src/utils/llm-deadline.d.ts +9 -1
  313. package/dist/src/utils/llm-deadline.js +31 -2
  314. package/dist/src/utils/permission-mode.d.ts +33 -0
  315. package/dist/src/utils/permission-mode.js +164 -3
  316. package/dist/src/utils/permission-mode.test.js +92 -1
  317. package/dist/src/utils/settings.d.ts +27 -31
  318. package/dist/src/utils/settings.js +100 -109
  319. package/dist/src/utils/side-question.js +2 -2
  320. package/dist/src/utils/skills.js +3 -3
  321. package/dist/src/verify/__tests__/coverage-parsers.test.js +30 -30
  322. package/package.json +1 -1
@@ -39,10 +39,32 @@ describe("detectTextEmittedToolCall", () => {
39
39
  expect(detectTextEmittedToolCall('<invoke name="read_file"><parameter name="path">a</parameter></invoke>').detected).toBe(true);
40
40
  expect(detectTextEmittedToolCall("<function_calls>...").detected).toBe(true);
41
41
  });
42
- it("detects the DeepSeek-native DSML leak (||DSML||invoke …) and extracts the tool name", () => {
42
+ it("detects the DeepSeek-native DSML leak (invoke …) and extracts the tool name", () => {
43
43
  // Live: storyflow_ui explore-A/B, deepseek T3 (session 799f0508e830) emitted
44
44
  // this as text and made no real tool call → empty, silent turn. The generic
45
45
  // <invoke matcher misses it because `<` is followed by the U+FF5C sentinel.
46
+ const text = `<│tool_calls>
47
+ <│invoke name="read_file">
48
+ <│parameter name="file_path" string="true">src/app/foo.html</│parameter>
49
+ </│invoke>
50
+ </│tool_calls>`;
51
+ const r = detectTextEmittedToolCall(text);
52
+ expect(r.detected).toBe(true);
53
+ expect(r.tool).toBe("read_file");
54
+ });
55
+ it("detects the newer DeepSeek DSML format with │ DSML │ sentinel (2026-06-23+ leak)", () => {
56
+ // Newer DSML format where the model inserts "DSML" text between bars:
57
+ // <│ DSML │invoke name="read_file">...</│ DSML │invoke>
58
+ const text = `<│tool_calls>
59
+ <│ DSML │invoke name="read_file">
60
+ <│ DSML │parameter name="file_path" string="true">D:\\sources\\Core\\muonroi-cli\\biome.json</│ DSML │parameter>
61
+ </│ DSML │invoke>
62
+ </│tool_calls>`;
63
+ const r = detectTextEmittedToolCall(text);
64
+ expect(r.detected).toBe(true);
65
+ expect(r.tool).toBe("read_file");
66
+ });
67
+ it("detects the double-bar DeepSeek DSML format with || sentinel", () => {
46
68
  const text = `<||DSML||tool_calls>
47
69
  <||DSML||invoke name="read_file">
48
70
  <||DSML||parameter name="file_path" string="true">src/app/foo.html</||DSML||parameter>
@@ -52,6 +74,24 @@ describe("detectTextEmittedToolCall", () => {
52
74
  expect(r.detected).toBe(true);
53
75
  expect(r.tool).toBe("read_file");
54
76
  });
77
+ it("parses double-bar DSML blocks with || DSML || sentinel format", () => {
78
+ const text = `<||DSML||invoke name="read_file">
79
+ <||DSML||parameter name="file_path" string="true">src/app/foo.html</||DSML||parameter>
80
+ </||DSML||invoke>`;
81
+ const calls = parseDsmlToolCalls(text);
82
+ expect(calls).toHaveLength(1);
83
+ expect(calls[0].name).toBe("read_file");
84
+ expect(calls[0].args.file_path).toBe("src/app/foo.html");
85
+ });
86
+ it("parses DSML blocks with │ DSML │ sentinel format", () => {
87
+ const text = `<│ DSML │invoke name="read_file">
88
+ <│ DSML │parameter name="file_path" string="true">src/app.ts</│ DSML │parameter>
89
+ </│ DSML │invoke>`;
90
+ const calls = parseDsmlToolCalls(text);
91
+ expect(calls).toHaveLength(1);
92
+ expect(calls[0].name).toBe("read_file");
93
+ expect(calls[0].args.file_path).toBe("src/app.ts");
94
+ });
55
95
  it("does NOT fire on a bare inline mention of a tool name (no invocation shape)", () => {
56
96
  // Precision: a prose mention must not be flagged — it would wrongly mark a
57
97
  // legitimate final answer as a broken tool call.
@@ -60,12 +100,12 @@ describe("detectTextEmittedToolCall", () => {
60
100
  expect(detectTextEmittedToolCall("I edited the file and ran the tests; everything passes.").detected).toBe(false);
61
101
  });
62
102
  it("parseDsmlToolCalls extracts name + args from the DSML block (for targeted re-steer)", () => {
63
- const text = `<||DSML||tool_calls>
64
- <||DSML||invoke name="read_file">
65
- <||DSML||parameter name="file_path" string="true">src/app/foo.html</||DSML||parameter>
66
- <||DSML||parameter name="start_line" string="false">25</||DSML||parameter>
67
- </||DSML||invoke>
68
- </||DSML||tool_calls>`;
103
+ const text = `<│tool_calls>
104
+ <│invoke name="read_file">
105
+ <│parameter name="file_path" string="true">src/app/foo.html</│parameter>
106
+ <│parameter name="start_line" string="false">25</│parameter>
107
+ </│invoke>
108
+ </│tool_calls>`;
69
109
  const calls = parseDsmlToolCalls(text);
70
110
  expect(calls).toHaveLength(1);
71
111
  expect(calls[0].name).toBe("read_file");
@@ -73,7 +113,7 @@ describe("detectTextEmittedToolCall", () => {
73
113
  expect(calls[0].args.start_line).toBe("25");
74
114
  });
75
115
  it("parseDsmlToolCalls handles multiple invoke blocks and returns [] for non-DSML text", () => {
76
- const text = `<||DSML||invoke name="read_file"><||DSML||parameter name="file_path">a.ts</||DSML||parameter></||DSML||invoke><||DSML||invoke name="edit_file"><||DSML||parameter name="path">b.ts</||DSML||parameter></||DSML||invoke>`;
116
+ const text = `<│invoke name="read_file"><│parameter name="file_path">a.ts</│parameter></│invoke><│invoke name="edit_file"><│parameter name="path">b.ts</│parameter></│invoke>`;
77
117
  const calls = parseDsmlToolCalls(text);
78
118
  expect(calls.map((c) => c.name)).toEqual(["read_file", "edit_file"]);
79
119
  expect(parseDsmlToolCalls("just a normal answer")).toEqual([]);
@@ -85,5 +125,23 @@ describe("detectTextEmittedToolCall", () => {
85
125
  // Angular template with self-closing/nested tags must not match a tool tag.
86
126
  expect(detectTextEmittedToolCall('<span *ngIf="!story.cover" class="placeholder">{{ title }}</span>').detected).toBe(false);
87
127
  });
128
+ it("detects and parses Gemini-style ASCII DSML leak with spaces and standard pipes", () => {
129
+ const text = `Tôi cần xác nhận ecosystem có những extension gì trước khi sửa - không đoán, phải đọc source thật.
130
+
131
+ < | | DSML | | tool_calls>
132
+ < | | DSML | | invoke name="mcp_filesystem__search_files">
133
+ < | | DSML | | parameter name="pattern" string="true">Serilog</ | | DSML | | parameter>
134
+ < | | DSML | | parameter name="path" string="true">D:\\sources\\Core\\muonroi-building-block\\src</ | | DSML | | parameter>
135
+ </ | | DSML | | invoke>
136
+ </ | | DSML | | tool_calls>`;
137
+ const r = detectTextEmittedToolCall(text);
138
+ expect(r.detected).toBe(true);
139
+ expect(r.tool).toBe("mcp_filesystem__search_files");
140
+ const calls = parseDsmlToolCalls(text);
141
+ expect(calls).toHaveLength(1);
142
+ expect(calls[0].name).toBe("mcp_filesystem__search_files");
143
+ expect(calls[0].args.pattern).toBe("Serilog");
144
+ expect(calls[0].args.path).toBe("D:\\sources\\Core\\muonroi-building-block\\src");
145
+ });
88
146
  });
89
147
  //# sourceMappingURL=text-tool-call-detector.test.js.map
@@ -180,7 +180,7 @@ function insertMissingCloseQuote(s) {
180
180
  const prefix = out.slice(0, m.index);
181
181
  if (!isInsideOpenString(prefix))
182
182
  continue;
183
- result += out.slice(lastIndex, m.index) + m[1] + '"' + m[2] + m[3];
183
+ result += `${out.slice(lastIndex, m.index) + m[1]}"${m[2]}${m[3]}`;
184
184
  lastIndex = m.index + m[0].length;
185
185
  matched = true;
186
186
  }
@@ -0,0 +1,151 @@
1
+ import { type ModelMessage } from "ai";
2
+ import { getModelInfo } from "../models/registry.js";
3
+ import { type resolveModelRuntime } from "../providers/runtime.js";
4
+ import type { ProviderId } from "../providers/types.js";
5
+ import { type SessionStore } from "../storage/index.js";
6
+ import type { SessionInfo, StreamChunk, SubagentStatus } from "../types/index.js";
7
+ import { type PermissionMode } from "../utils/permission-mode.js";
8
+ import type { AbortContext } from "./abort.js";
9
+ import type { LegacyProvider, ProcessMessageObserver } from "./agent-options.js";
10
+ import type { CouncilManager } from "./council-manager.js";
11
+ import type { CrossTurnDedup } from "./cross-turn-dedup.js";
12
+ import type { PendingCallsLog } from "./pending-calls.js";
13
+ import type { ReadPathBudget } from "./read-path-budget.js";
14
+ import type { SafetyOverrideAskInfo, SafetyOverrideVerdict } from "./safety-askcard.js";
15
+ import { type ToolLoopCapAsk } from "./tool-loop-cap.js";
16
+ import type { TurnRunnerDepsBase } from "./turn-runner-deps.js";
17
+ /**
18
+ * Dependency surface the MessageProcessor needs to reach back into Agent
19
+ * state without holding a circular reference. Properties expose array
20
+ * references (mutating push() must affect the same array the Agent reads on
21
+ * subsequent turns). Method callbacks delegate to Agent private methods.
22
+ */
23
+ export interface MessageProcessorDeps extends TurnRunnerDepsBase {
24
+ /** Live messageSeqs array (mutated by push; parallel to messages). */
25
+ readonly messageSeqs: Array<number | null>;
26
+ /** Session bookkeeping. */
27
+ readonly session: SessionInfo | null;
28
+ readonly sessionStore: SessionStore | null;
29
+ readonly modelId: string;
30
+ readonly providerId: ProviderId;
31
+ readonly batchApi: boolean;
32
+ readonly permissionMode: PermissionMode;
33
+ readonly externalAbortContext: AbortContext | null;
34
+ readonly pendingCalls: PendingCallsLog | null;
35
+ readonly councilManager: CouncilManager;
36
+ readonly crossTurnDedup: CrossTurnDedup | null;
37
+ readonly readBudget: ReadPathBudget | null;
38
+ readonly priorWarningIdsInSession: Set<string>;
39
+ readonly sessionEEGuidance: Map<string, {
40
+ toolName: string;
41
+ message: string;
42
+ why: string;
43
+ confidence: number;
44
+ }>;
45
+ readonly flowReady: Promise<void> | null;
46
+ getAbortController(): AbortController | null;
47
+ setAbortController(ctrl: AbortController | null): void;
48
+ getSessionStartHookFired(): boolean;
49
+ setSessionStartHookFired(v: boolean): void;
50
+ getPlanContext(): string | null;
51
+ setPlanContext(v: string | null): void;
52
+ getResumeDigest(): string | null;
53
+ setResumeDigest(v: string | null): void;
54
+ getActiveRunId(): string | null;
55
+ getPendingCwdNote(): string | null;
56
+ setPendingCwdNote(v: string | null): void;
57
+ setPilActive(v: boolean): void;
58
+ setPilEnrichmentDelta(n: number): void;
59
+ setCurrentCallId(id: string): void;
60
+ setLastPromptBreakdown(b: {
61
+ systemChars: number;
62
+ staticPrefixChars: number;
63
+ dynamicSuffixChars: number;
64
+ playwrightGuidanceChars: number;
65
+ messagesChars: number;
66
+ messagesCount: number;
67
+ toolsChars: number;
68
+ toolsCount: number;
69
+ } | null): void;
70
+ setTurnUserGoalExcerpt(v: string): void;
71
+ setTurnAssistantReasoning(v: string): void;
72
+ appendTurnAssistantReasoning(delta: string): void;
73
+ getTurnAssistantReasoning(): string;
74
+ setPriorWarningIdsInSession(s: Set<string>): void;
75
+ setMessages(messages: ModelMessage[]): void;
76
+ requireProvider(): LegacyProvider;
77
+ emitSubagentStatus(status: SubagentStatus | null): void;
78
+ fireHook(input: unknown, signal?: AbortSignal): Promise<{
79
+ blocked: boolean;
80
+ blockingErrors: Array<{
81
+ command: string;
82
+ stderr: string;
83
+ }>;
84
+ preventContinuation: boolean;
85
+ additionalContexts: string[];
86
+ results: import("../hooks/types.js").HookResult[];
87
+ eeMatches: import("../hooks/types.js").EEMatchEntry[];
88
+ }>;
89
+ consumeBackgroundNotifications(): Promise<string[]>;
90
+ initOAuthProvider(): Promise<void>;
91
+ buildRecentTurnsSummary(): string | null;
92
+ estimateProjectSize(): "small" | "medium" | "large" | null;
93
+ countFilesTouched(): number;
94
+ respondToToolApproval(approvalId: string, approved: boolean): void;
95
+ /**
96
+ * Tool-loop cap askcard hook (Claude-Code-style "continue?" prompt).
97
+ *
98
+ * Fires when the streamText loop reaches `maxToolRounds`. Returning
99
+ * `"continue"` raises the cap by `bumpBy` and lets the loop run; `"stop"`
100
+ * halts gracefully (no error). When undefined the loop hard-stops as before
101
+ * — preserves backward compat for batch / headless paths that have no UI to
102
+ * surface the askcard.
103
+ */
104
+ /**
105
+ * Live-queue steering drain (UI-provided). Returns and CLEARS any messages
106
+ * the user typed while this turn is streaming, so prepareStep can inject them
107
+ * mid-turn. Undefined / returns [] → no steering (legacy deferred queue).
108
+ */
109
+ drainSteerMessages?: () => {
110
+ text: string;
111
+ }[];
112
+ appendMidTurnMessages?: (msgs: ModelMessage[]) => void;
113
+ askToolLoopContinue?: ToolLoopCapAsk;
114
+ /** Safety override handler — invoked when a tool call is blocked by the safety filter. */
115
+ askSafetyOverride?: (info: SafetyOverrideAskInfo) => Promise<SafetyOverrideVerdict>;
116
+ runCouncilV2(userMessage: string, opts: {
117
+ skipClarification: boolean;
118
+ observer?: ProcessMessageObserver;
119
+ userModelMessage: ModelMessage;
120
+ }): AsyncGenerator<StreamChunk, void, unknown>;
121
+ processMessage(userMessage: string, observer?: ProcessMessageObserver, images?: Array<{
122
+ path: string;
123
+ mediaType: string;
124
+ base64: string;
125
+ }>): AsyncGenerator<StreamChunk, void, unknown>;
126
+ processMessageBatchTurn(args: {
127
+ userModelMessage: ModelMessage;
128
+ userEnrichedMessage: ModelMessage;
129
+ observer?: ProcessMessageObserver;
130
+ provider: LegacyProvider;
131
+ subagents: unknown[];
132
+ system: string;
133
+ runtime: ReturnType<typeof resolveModelRuntime>;
134
+ modelInfo: ReturnType<typeof getModelInfo>;
135
+ signal: AbortSignal;
136
+ }): AsyncGenerator<StreamChunk, void, unknown>;
137
+ }
138
+ /**
139
+ * Rewrites tool-result parts in the AI SDK's final response history if the
140
+ * user manually approved a safety-blocked command. This ensures the model sees
141
+ * its own retry context accurately (as a success) rather than a repeated block
142
+ * message, avoiding infinite retry loops or hallucinated failures.
143
+ */
144
+ export declare function rewriteSafetyApprovedToolResults<T extends {
145
+ role: string;
146
+ content?: any;
147
+ }>(messages: T[]): T[];
148
+ export interface ToolEngineArgs {
149
+ [key: string]: any;
150
+ }
151
+ export declare function executeToolEngine(args: ToolEngineArgs): AsyncGenerator<StreamChunk, void, unknown>;