@machina.ai/cell-cli-core 1.20.2-rc1 → 1.25.0-rc1

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 (898) hide show
  1. package/dist/docs/AFTER_MERGE_PROMPT.md +26 -0
  2. package/dist/docs/CHANGES.md +124 -0
  3. package/dist/docs/api-proxy.md +27 -0
  4. package/dist/docs/architecture.md +80 -0
  5. package/dist/docs/assets/connected_devtools.png +0 -0
  6. package/dist/docs/assets/gemini-screenshot.png +0 -0
  7. package/dist/docs/assets/monitoring-dashboard-logs.png +0 -0
  8. package/dist/docs/assets/monitoring-dashboard-metrics.png +0 -0
  9. package/dist/docs/assets/monitoring-dashboard-overview.png +0 -0
  10. package/dist/docs/assets/release_patch.png +0 -0
  11. package/dist/docs/assets/theme-ansi-light.png +0 -0
  12. package/dist/docs/assets/theme-ansi.png +0 -0
  13. package/dist/docs/assets/theme-atom-one.png +0 -0
  14. package/dist/docs/assets/theme-ayu-light.png +0 -0
  15. package/dist/docs/assets/theme-ayu.png +0 -0
  16. package/dist/docs/assets/theme-custom.png +0 -0
  17. package/dist/docs/assets/theme-default-light.png +0 -0
  18. package/dist/docs/assets/theme-default.png +0 -0
  19. package/dist/docs/assets/theme-dracula.png +0 -0
  20. package/dist/docs/assets/theme-github-light.png +0 -0
  21. package/dist/docs/assets/theme-github.png +0 -0
  22. package/dist/docs/assets/theme-google-light.png +0 -0
  23. package/dist/docs/assets/theme-xcode-light.png +0 -0
  24. package/dist/docs/changelogs/index.md +612 -0
  25. package/dist/docs/changelogs/latest.md +153 -0
  26. package/dist/docs/changelogs/preview.md +131 -0
  27. package/dist/docs/changelogs/releases.md +1162 -0
  28. package/dist/docs/cli/authentication.md +3 -0
  29. package/dist/docs/cli/checkpointing.md +94 -0
  30. package/dist/docs/cli/commands.md +357 -0
  31. package/dist/docs/cli/custom-commands.md +315 -0
  32. package/dist/docs/cli/enterprise.md +564 -0
  33. package/dist/docs/cli/gemini-ignore.md +71 -0
  34. package/dist/docs/cli/gemini-md.md +109 -0
  35. package/dist/docs/cli/generation-settings.md +210 -0
  36. package/dist/docs/cli/headless.md +388 -0
  37. package/dist/docs/cli/index.md +63 -0
  38. package/dist/docs/cli/keyboard-shortcuts.md +136 -0
  39. package/dist/docs/cli/model-routing.md +37 -0
  40. package/dist/docs/cli/model.md +62 -0
  41. package/dist/docs/cli/sandbox.md +171 -0
  42. package/dist/docs/cli/session-management.md +158 -0
  43. package/dist/docs/cli/settings.md +148 -0
  44. package/dist/docs/cli/skills.md +188 -0
  45. package/dist/docs/cli/system-prompt.md +94 -0
  46. package/dist/docs/cli/telemetry.md +813 -0
  47. package/dist/docs/cli/themes.md +237 -0
  48. package/dist/docs/cli/token-caching.md +20 -0
  49. package/dist/docs/cli/trusted-folders.md +95 -0
  50. package/dist/docs/cli/tutorials/skills-getting-started.md +124 -0
  51. package/dist/docs/cli/tutorials.md +87 -0
  52. package/dist/docs/cli/uninstall.md +47 -0
  53. package/dist/docs/core/index.md +101 -0
  54. package/dist/docs/core/memport.md +246 -0
  55. package/dist/docs/core/policy-engine.md +268 -0
  56. package/dist/docs/core/tools-api.md +131 -0
  57. package/dist/docs/examples/proxy-script.md +83 -0
  58. package/dist/docs/extensions/extension-releasing.md +183 -0
  59. package/dist/docs/extensions/getting-started-extensions.md +244 -0
  60. package/dist/docs/extensions/index.md +343 -0
  61. package/dist/docs/faq.md +153 -0
  62. package/dist/docs/get-started/authentication.md +321 -0
  63. package/dist/docs/get-started/configuration-v1.md +890 -0
  64. package/dist/docs/get-started/configuration.md +1643 -0
  65. package/dist/docs/get-started/examples.md +218 -0
  66. package/dist/docs/get-started/gemini-3.md +101 -0
  67. package/dist/docs/get-started/index.md +71 -0
  68. package/dist/docs/get-started/installation.md +141 -0
  69. package/dist/docs/hooks/best-practices.md +856 -0
  70. package/dist/docs/hooks/index.md +723 -0
  71. package/dist/docs/hooks/reference.md +178 -0
  72. package/dist/docs/hooks/writing-hooks.md +1044 -0
  73. package/dist/docs/ide-integration/ide-companion-spec.md +267 -0
  74. package/dist/docs/ide-integration/index.md +201 -0
  75. package/dist/docs/index.md +147 -0
  76. package/dist/docs/integration-tests.md +211 -0
  77. package/dist/docs/issue-and-pr-automation.md +134 -0
  78. package/dist/docs/local-development.md +128 -0
  79. package/dist/docs/mcp_integration.md +160 -0
  80. package/dist/docs/mermaid/context.mmd +103 -0
  81. package/dist/docs/mermaid/render-path.mmd +64 -0
  82. package/dist/docs/npm.md +62 -0
  83. package/dist/docs/quota-and-pricing.md +158 -0
  84. package/dist/docs/release-confidence.md +164 -0
  85. package/dist/docs/releases.md +540 -0
  86. package/dist/docs/sidebar.json +301 -0
  87. package/dist/docs/tools/file-system.md +217 -0
  88. package/dist/docs/tools/index.md +95 -0
  89. package/dist/docs/tools/mcp-server.md +1045 -0
  90. package/dist/docs/tools/memory.md +54 -0
  91. package/dist/docs/tools/shell.md +260 -0
  92. package/dist/docs/tools/todos.md +56 -0
  93. package/dist/docs/tools/web-fetch.md +59 -0
  94. package/dist/docs/tools/web-search.md +42 -0
  95. package/dist/docs/tos-privacy.md +96 -0
  96. package/dist/docs/troubleshooting.md +162 -0
  97. package/dist/index.d.ts +1 -1
  98. package/dist/index.js +1 -1
  99. package/dist/index.js.map +1 -1
  100. package/dist/package.json +7 -4
  101. package/dist/src/agents/a2a-client-manager.d.ts +82 -0
  102. package/dist/src/agents/a2a-client-manager.js +295 -0
  103. package/dist/src/agents/a2a-client-manager.js.map +1 -0
  104. package/dist/src/agents/a2a-client-manager.test.js +281 -0
  105. package/dist/src/agents/a2a-client-manager.test.js.map +1 -0
  106. package/dist/src/agents/a2aUtils.d.ts +29 -0
  107. package/dist/src/agents/a2aUtils.js +113 -0
  108. package/dist/src/agents/a2aUtils.js.map +1 -0
  109. package/dist/src/agents/a2aUtils.test.js +147 -0
  110. package/dist/src/agents/a2aUtils.test.js.map +1 -0
  111. package/dist/src/agents/agentLoader.d.ts +68 -0
  112. package/dist/src/agents/agentLoader.js +255 -0
  113. package/dist/src/agents/agentLoader.js.map +1 -0
  114. package/dist/src/agents/agentLoader.test.js +307 -0
  115. package/dist/src/agents/agentLoader.test.js.map +1 -0
  116. package/dist/src/agents/cli-help-agent.d.ts +24 -0
  117. package/dist/src/agents/cli-help-agent.js +85 -0
  118. package/dist/src/agents/cli-help-agent.js.map +1 -0
  119. package/dist/src/agents/cli-help-agent.test.d.ts +6 -0
  120. package/dist/src/agents/cli-help-agent.test.js +65 -0
  121. package/dist/src/agents/cli-help-agent.test.js.map +1 -0
  122. package/dist/src/agents/codebase-investigator.d.ts +2 -2
  123. package/dist/src/agents/codebase-investigator.js +14 -8
  124. package/dist/src/agents/codebase-investigator.js.map +1 -1
  125. package/dist/src/agents/delegate-to-agent-tool.d.ts +19 -0
  126. package/dist/src/agents/delegate-to-agent-tool.js +122 -0
  127. package/dist/src/agents/delegate-to-agent-tool.js.map +1 -0
  128. package/dist/src/agents/delegate-to-agent-tool.test.d.ts +6 -0
  129. package/dist/src/agents/delegate-to-agent-tool.test.js +213 -0
  130. package/dist/src/agents/delegate-to-agent-tool.test.js.map +1 -0
  131. package/dist/src/agents/{executor.d.ts → local-executor.d.ts} +5 -11
  132. package/dist/src/agents/{executor.js → local-executor.js} +124 -63
  133. package/dist/src/agents/local-executor.js.map +1 -0
  134. package/dist/src/agents/local-executor.test.d.ts +6 -0
  135. package/dist/src/agents/{executor.test.js → local-executor.test.js} +136 -58
  136. package/dist/src/agents/local-executor.test.js.map +1 -0
  137. package/dist/src/agents/{invocation.d.ts → local-invocation.d.ts} +6 -7
  138. package/dist/src/agents/{invocation.js → local-invocation.js} +9 -10
  139. package/dist/src/agents/local-invocation.js.map +1 -0
  140. package/dist/src/agents/local-invocation.test.d.ts +6 -0
  141. package/dist/src/agents/{invocation.test.js → local-invocation.test.js} +29 -20
  142. package/dist/src/agents/local-invocation.test.js.map +1 -0
  143. package/dist/src/agents/registry.d.ts +37 -1
  144. package/dist/src/agents/registry.js +240 -27
  145. package/dist/src/agents/registry.js.map +1 -1
  146. package/dist/src/agents/registry.test.js +465 -30
  147. package/dist/src/agents/registry.test.js.map +1 -1
  148. package/dist/src/agents/remote-invocation.d.ts +35 -0
  149. package/dist/src/agents/remote-invocation.js +126 -0
  150. package/dist/src/agents/remote-invocation.js.map +1 -0
  151. package/dist/src/agents/remote-invocation.test.d.ts +6 -0
  152. package/dist/src/agents/remote-invocation.test.js +201 -0
  153. package/dist/src/agents/remote-invocation.test.js.map +1 -0
  154. package/dist/src/agents/subagent-tool-wrapper.d.ts +2 -2
  155. package/dist/src/agents/subagent-tool-wrapper.js +11 -6
  156. package/dist/src/agents/subagent-tool-wrapper.js.map +1 -1
  157. package/dist/src/agents/subagent-tool-wrapper.test.js +33 -19
  158. package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -1
  159. package/dist/src/agents/types.d.ts +21 -15
  160. package/dist/src/agents/types.js.map +1 -1
  161. package/dist/src/availability/errorClassification.d.ts +7 -0
  162. package/dist/src/availability/errorClassification.js +20 -0
  163. package/dist/src/availability/errorClassification.js.map +1 -0
  164. package/dist/src/availability/fallbackIntegration.test.d.ts +6 -0
  165. package/dist/src/availability/fallbackIntegration.test.js +58 -0
  166. package/dist/src/availability/fallbackIntegration.test.js.map +1 -0
  167. package/dist/src/availability/modelAvailabilityService.d.ts +3 -1
  168. package/dist/src/availability/modelAvailabilityService.js +3 -0
  169. package/dist/src/availability/modelAvailabilityService.js.map +1 -1
  170. package/dist/src/availability/modelPolicy.d.ts +8 -1
  171. package/dist/src/availability/policyCatalog.d.ts +1 -0
  172. package/dist/src/availability/policyCatalog.js +6 -7
  173. package/dist/src/availability/policyCatalog.js.map +1 -1
  174. package/dist/src/availability/policyCatalog.test.js +2 -2
  175. package/dist/src/availability/policyCatalog.test.js.map +1 -1
  176. package/dist/src/availability/policyHelpers.d.ts +34 -3
  177. package/dist/src/availability/policyHelpers.js +104 -13
  178. package/dist/src/availability/policyHelpers.js.map +1 -1
  179. package/dist/src/availability/policyHelpers.test.js +143 -13
  180. package/dist/src/availability/policyHelpers.test.js.map +1 -1
  181. package/dist/src/availability/testUtils.d.ts +10 -0
  182. package/dist/src/availability/testUtils.js +22 -0
  183. package/dist/src/availability/testUtils.js.map +1 -0
  184. package/dist/src/code_assist/experiments/client_metadata.js +2 -1
  185. package/dist/src/code_assist/experiments/client_metadata.js.map +1 -1
  186. package/dist/src/code_assist/experiments/client_metadata.test.js +7 -10
  187. package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -1
  188. package/dist/src/code_assist/experiments/experiments.d.ts +1 -1
  189. package/dist/src/code_assist/experiments/experiments.js +21 -0
  190. package/dist/src/code_assist/experiments/experiments.js.map +1 -1
  191. package/dist/src/code_assist/experiments/experiments_local.test.d.ts +6 -0
  192. package/dist/src/code_assist/experiments/experiments_local.test.js +110 -0
  193. package/dist/src/code_assist/experiments/experiments_local.test.js.map +1 -0
  194. package/dist/src/code_assist/oauth-credential-storage.js +3 -4
  195. package/dist/src/code_assist/oauth-credential-storage.js.map +1 -1
  196. package/dist/src/code_assist/oauth2.d.ts +2 -0
  197. package/dist/src/code_assist/oauth2.js +70 -14
  198. package/dist/src/code_assist/oauth2.js.map +1 -1
  199. package/dist/src/code_assist/oauth2.test.js +224 -22
  200. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  201. package/dist/src/code_assist/server.d.ts +9 -1
  202. package/dist/src/code_assist/server.js +74 -11
  203. package/dist/src/code_assist/server.js.map +1 -1
  204. package/dist/src/code_assist/server.test.js +199 -27
  205. package/dist/src/code_assist/server.test.js.map +1 -1
  206. package/dist/src/code_assist/setup.js +6 -4
  207. package/dist/src/code_assist/setup.js.map +1 -1
  208. package/dist/src/code_assist/setup.test.js +63 -0
  209. package/dist/src/code_assist/setup.test.js.map +1 -1
  210. package/dist/src/code_assist/telemetry.d.ts +14 -0
  211. package/dist/src/code_assist/telemetry.js +157 -0
  212. package/dist/src/code_assist/telemetry.js.map +1 -0
  213. package/dist/src/code_assist/telemetry.test.d.ts +6 -0
  214. package/dist/src/code_assist/telemetry.test.js +301 -0
  215. package/dist/src/code_assist/telemetry.test.js.map +1 -0
  216. package/dist/src/code_assist/types.d.ts +77 -1
  217. package/dist/src/code_assist/types.js +28 -0
  218. package/dist/src/code_assist/types.js.map +1 -1
  219. package/dist/src/commands/init.d.ts +7 -0
  220. package/dist/src/commands/init.js +53 -0
  221. package/dist/src/commands/init.js.map +1 -0
  222. package/dist/src/commands/init.test.d.ts +6 -0
  223. package/dist/src/commands/init.test.js +25 -0
  224. package/dist/src/commands/init.test.js.map +1 -0
  225. package/dist/src/commands/memory.d.ts +11 -0
  226. package/dist/src/commands/memory.js +80 -0
  227. package/dist/src/commands/memory.js.map +1 -0
  228. package/dist/src/commands/memory.test.d.ts +6 -0
  229. package/dist/src/commands/memory.test.js +155 -0
  230. package/dist/src/commands/memory.test.js.map +1 -0
  231. package/dist/src/commands/restore.d.ts +9 -0
  232. package/dist/src/commands/restore.js +46 -0
  233. package/dist/src/commands/restore.js.map +1 -0
  234. package/dist/src/commands/restore.test.d.ts +6 -0
  235. package/dist/src/commands/restore.test.js +137 -0
  236. package/dist/src/commands/restore.test.js.map +1 -0
  237. package/dist/src/commands/types.d.ts +41 -0
  238. package/dist/src/commands/types.js +7 -0
  239. package/dist/src/commands/types.js.map +1 -0
  240. package/dist/src/config/config.d.ts +145 -25
  241. package/dist/src/config/config.js +370 -132
  242. package/dist/src/config/config.js.map +1 -1
  243. package/dist/src/config/config.test.js +416 -50
  244. package/dist/src/config/config.test.js.map +1 -1
  245. package/dist/src/config/defaultModelConfigs.js +21 -0
  246. package/dist/src/config/defaultModelConfigs.js.map +1 -1
  247. package/dist/src/config/flashFallback.test.js +11 -35
  248. package/dist/src/config/flashFallback.test.js.map +1 -1
  249. package/dist/src/config/models.d.ts +36 -15
  250. package/dist/src/config/models.js +89 -28
  251. package/dist/src/config/models.js.map +1 -1
  252. package/dist/src/config/models.test.js +107 -77
  253. package/dist/src/config/models.test.js.map +1 -1
  254. package/dist/src/config/storage.d.ts +5 -0
  255. package/dist/src/config/storage.js +17 -2
  256. package/dist/src/config/storage.js.map +1 -1
  257. package/dist/src/config/storage.test.js +16 -0
  258. package/dist/src/config/storage.test.js.map +1 -1
  259. package/dist/src/confirmation-bus/message-bus.js +3 -1
  260. package/dist/src/confirmation-bus/message-bus.js.map +1 -1
  261. package/dist/src/confirmation-bus/types.d.ts +4 -0
  262. package/dist/src/core/baseLlmClient.d.ts +3 -1
  263. package/dist/src/core/baseLlmClient.js +60 -22
  264. package/dist/src/core/baseLlmClient.js.map +1 -1
  265. package/dist/src/core/baseLlmClient.test.js +177 -7
  266. package/dist/src/core/baseLlmClient.test.js.map +1 -1
  267. package/dist/src/core/client.d.ts +7 -1
  268. package/dist/src/core/client.js +261 -96
  269. package/dist/src/core/client.js.map +1 -1
  270. package/dist/src/core/client.test.js +397 -67
  271. package/dist/src/core/client.test.js.map +1 -1
  272. package/dist/src/core/clientHookTriggers.js +2 -2
  273. package/dist/src/core/clientHookTriggers.js.map +1 -1
  274. package/dist/src/core/contentGenerator.js +6 -4
  275. package/dist/src/core/contentGenerator.js.map +1 -1
  276. package/dist/src/core/contentGenerator.test.js +24 -23
  277. package/dist/src/core/contentGenerator.test.js.map +1 -1
  278. package/dist/src/core/coreToolHookTriggers.d.ts +9 -5
  279. package/dist/src/core/coreToolHookTriggers.js +119 -21
  280. package/dist/src/core/coreToolHookTriggers.js.map +1 -1
  281. package/dist/src/core/coreToolHookTriggers.test.d.ts +6 -0
  282. package/dist/src/core/coreToolHookTriggers.test.js +191 -0
  283. package/dist/src/core/coreToolHookTriggers.test.js.map +1 -0
  284. package/dist/src/core/coreToolScheduler.d.ts +7 -93
  285. package/dist/src/core/coreToolScheduler.js +139 -333
  286. package/dist/src/core/coreToolScheduler.js.map +1 -1
  287. package/dist/src/core/coreToolScheduler.test.js +304 -348
  288. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  289. package/dist/src/core/geminiChat.d.ts +26 -1
  290. package/dist/src/core/geminiChat.js +144 -80
  291. package/dist/src/core/geminiChat.js.map +1 -1
  292. package/dist/src/core/geminiChat.test.js +334 -253
  293. package/dist/src/core/geminiChat.test.js.map +1 -1
  294. package/dist/src/core/geminiChatHookTriggers.d.ts +8 -4
  295. package/dist/src/core/geminiChatHookTriggers.js +34 -12
  296. package/dist/src/core/geminiChatHookTriggers.js.map +1 -1
  297. package/dist/src/core/geminiChatHookTriggers.test.d.ts +6 -0
  298. package/dist/src/core/geminiChatHookTriggers.test.js +153 -0
  299. package/dist/src/core/geminiChatHookTriggers.test.js.map +1 -0
  300. package/dist/src/core/geminiChat_network_retry.test.d.ts +6 -0
  301. package/dist/src/core/geminiChat_network_retry.test.js +196 -0
  302. package/dist/src/core/geminiChat_network_retry.test.js.map +1 -0
  303. package/dist/src/core/logger.js.map +1 -1
  304. package/dist/src/core/loggingContentGenerator.js +19 -2
  305. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  306. package/dist/src/core/loggingContentGenerator.test.js +30 -0
  307. package/dist/src/core/loggingContentGenerator.test.js.map +1 -1
  308. package/dist/src/core/nonInteractiveToolExecutor.test.js +7 -8
  309. package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
  310. package/dist/src/core/prompts.js +48 -22
  311. package/dist/src/core/prompts.js.map +1 -1
  312. package/dist/src/core/prompts.test.js +66 -11
  313. package/dist/src/core/prompts.test.js.map +1 -1
  314. package/dist/src/core/tokenLimits.js +6 -12
  315. package/dist/src/core/tokenLimits.js.map +1 -1
  316. package/dist/src/core/tokenLimits.test.js +8 -4
  317. package/dist/src/core/tokenLimits.test.js.map +1 -1
  318. package/dist/src/core/turn.d.ts +21 -21
  319. package/dist/src/core/turn.js +32 -22
  320. package/dist/src/core/turn.js.map +1 -1
  321. package/dist/src/core/turn.test.js +79 -5
  322. package/dist/src/core/turn.test.js.map +1 -1
  323. package/dist/src/fallback/handler.js +55 -120
  324. package/dist/src/fallback/handler.js.map +1 -1
  325. package/dist/src/fallback/handler.test.js +115 -288
  326. package/dist/src/fallback/handler.test.js.map +1 -1
  327. package/dist/src/generated/git-commit.d.ts +3 -3
  328. package/dist/src/generated/git-commit.js +3 -3
  329. package/dist/src/hooks/hookAggregator.js +7 -0
  330. package/dist/src/hooks/hookAggregator.js.map +1 -1
  331. package/dist/src/hooks/hookEventHandler.d.ts +9 -5
  332. package/dist/src/hooks/hookEventHandler.js +120 -16
  333. package/dist/src/hooks/hookEventHandler.js.map +1 -1
  334. package/dist/src/hooks/hookEventHandler.test.js +231 -9
  335. package/dist/src/hooks/hookEventHandler.test.js.map +1 -1
  336. package/dist/src/hooks/hookPlanner.d.ts +1 -5
  337. package/dist/src/hooks/hookPlanner.js +2 -7
  338. package/dist/src/hooks/hookPlanner.js.map +1 -1
  339. package/dist/src/hooks/hookPlanner.test.js +62 -2
  340. package/dist/src/hooks/hookPlanner.test.js.map +1 -1
  341. package/dist/src/hooks/hookRegistry.d.ts +6 -18
  342. package/dist/src/hooks/hookRegistry.js +49 -35
  343. package/dist/src/hooks/hookRegistry.js.map +1 -1
  344. package/dist/src/hooks/hookRegistry.test.js +167 -8
  345. package/dist/src/hooks/hookRegistry.test.js.map +1 -1
  346. package/dist/src/hooks/hookRunner.d.ts +5 -3
  347. package/dist/src/hooks/hookRunner.js +68 -18
  348. package/dist/src/hooks/hookRunner.js.map +1 -1
  349. package/dist/src/hooks/hookRunner.test.js +173 -36
  350. package/dist/src/hooks/hookRunner.test.js.map +1 -1
  351. package/dist/src/hooks/hookSystem.d.ts +10 -6
  352. package/dist/src/hooks/hookSystem.js +36 -16
  353. package/dist/src/hooks/hookSystem.js.map +1 -1
  354. package/dist/src/hooks/hookSystem.test.js +123 -18
  355. package/dist/src/hooks/hookSystem.test.js.map +1 -1
  356. package/dist/src/hooks/hookTranslator.js +2 -1
  357. package/dist/src/hooks/hookTranslator.js.map +1 -1
  358. package/dist/src/hooks/index.d.ts +2 -1
  359. package/dist/src/hooks/index.js +1 -0
  360. package/dist/src/hooks/index.js.map +1 -1
  361. package/dist/src/hooks/trustedHooks.d.ts +28 -0
  362. package/dist/src/hooks/trustedHooks.js +90 -0
  363. package/dist/src/hooks/trustedHooks.js.map +1 -0
  364. package/dist/src/hooks/trustedHooks.test.d.ts +6 -0
  365. package/dist/src/hooks/trustedHooks.test.js +154 -0
  366. package/dist/src/hooks/trustedHooks.test.js.map +1 -0
  367. package/dist/src/hooks/types.d.ts +42 -11
  368. package/dist/src/hooks/types.js +31 -42
  369. package/dist/src/hooks/types.js.map +1 -1
  370. package/dist/src/hooks/types.test.js +9 -52
  371. package/dist/src/hooks/types.test.js.map +1 -1
  372. package/dist/src/ide/detect-ide.d.ts +4 -0
  373. package/dist/src/ide/detect-ide.js +7 -2
  374. package/dist/src/ide/detect-ide.js.map +1 -1
  375. package/dist/src/ide/detect-ide.test.js +42 -1
  376. package/dist/src/ide/detect-ide.test.js.map +1 -1
  377. package/dist/src/ide/ide-client.js +6 -1
  378. package/dist/src/ide/ide-client.js.map +1 -1
  379. package/dist/src/ide/ide-installer.js +2 -2
  380. package/dist/src/ide/ide-installer.js.map +1 -1
  381. package/dist/src/ide/ide-installer.test.js +12 -3
  382. package/dist/src/ide/ide-installer.test.js.map +1 -1
  383. package/dist/src/index.d.ts +23 -1
  384. package/dist/src/index.js +25 -2
  385. package/dist/src/index.js.map +1 -1
  386. package/dist/src/mcp/oauth-provider.js +7 -3
  387. package/dist/src/mcp/oauth-provider.js.map +1 -1
  388. package/dist/src/mcp/oauth-provider.test.js +4 -1
  389. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  390. package/dist/src/mcp/oauth-utils.d.ts +8 -1
  391. package/dist/src/mcp/oauth-utils.js +31 -2
  392. package/dist/src/mcp/oauth-utils.js.map +1 -1
  393. package/dist/src/mcp/oauth-utils.test.js +42 -0
  394. package/dist/src/mcp/oauth-utils.test.js.map +1 -1
  395. package/dist/src/mcp/token-storage/file-token-storage.js +2 -2
  396. package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -1
  397. package/dist/src/mcp/token-storage/keychain-token-storage.js +1 -1
  398. package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
  399. package/dist/src/output/json-formatter.d.ts +2 -2
  400. package/dist/src/output/json-formatter.js +6 -3
  401. package/dist/src/output/json-formatter.js.map +1 -1
  402. package/dist/src/output/json-formatter.test.js +37 -9
  403. package/dist/src/output/json-formatter.test.js.map +1 -1
  404. package/dist/src/output/stream-json-formatter.js +6 -0
  405. package/dist/src/output/stream-json-formatter.js.map +1 -1
  406. package/dist/src/output/stream-json-formatter.test.js +98 -100
  407. package/dist/src/output/stream-json-formatter.test.js.map +1 -1
  408. package/dist/src/output/types.d.ts +3 -0
  409. package/dist/src/output/types.js.map +1 -1
  410. package/dist/src/policy/config.js +140 -15
  411. package/dist/src/policy/config.js.map +1 -1
  412. package/dist/src/policy/config.test.js +24 -2
  413. package/dist/src/policy/config.test.js.map +1 -1
  414. package/dist/src/policy/persistence.test.d.ts +6 -0
  415. package/dist/src/policy/persistence.test.js +154 -0
  416. package/dist/src/policy/persistence.test.js.map +1 -0
  417. package/dist/src/policy/policies/agent.toml +31 -0
  418. package/dist/src/policy/policies/write.toml +5 -0
  419. package/dist/src/policy/policies/yolo.toml +1 -0
  420. package/dist/src/policy/policy-engine.d.ts +14 -1
  421. package/dist/src/policy/policy-engine.js +165 -7
  422. package/dist/src/policy/policy-engine.js.map +1 -1
  423. package/dist/src/policy/policy-engine.test.js +315 -3
  424. package/dist/src/policy/policy-engine.test.js.map +1 -1
  425. package/dist/src/policy/policy-updater.test.d.ts +6 -0
  426. package/dist/src/policy/policy-updater.test.js +116 -0
  427. package/dist/src/policy/policy-updater.test.js.map +1 -0
  428. package/dist/src/policy/shell-safety.test.d.ts +6 -0
  429. package/dist/src/policy/shell-safety.test.js +438 -0
  430. package/dist/src/policy/shell-safety.test.js.map +1 -0
  431. package/dist/src/policy/toml-loader.d.ts +3 -5
  432. package/dist/src/policy/toml-loader.js +43 -60
  433. package/dist/src/policy/toml-loader.js.map +1 -1
  434. package/dist/src/policy/toml-loader.test.js +41 -7
  435. package/dist/src/policy/toml-loader.test.js.map +1 -1
  436. package/dist/src/policy/types.d.ts +25 -0
  437. package/dist/src/policy/utils.d.ts +21 -0
  438. package/dist/src/policy/utils.js +45 -0
  439. package/dist/src/policy/utils.js.map +1 -0
  440. package/dist/src/policy/utils.test.d.ts +6 -0
  441. package/dist/src/policy/utils.test.js +92 -0
  442. package/dist/src/policy/utils.test.js.map +1 -0
  443. package/dist/src/resources/resource-registry.d.ts +30 -0
  444. package/dist/src/resources/resource-registry.js +57 -0
  445. package/dist/src/resources/resource-registry.js.map +1 -0
  446. package/dist/src/resources/resource-registry.test.d.ts +6 -0
  447. package/dist/src/resources/resource-registry.test.js +54 -0
  448. package/dist/src/resources/resource-registry.test.js.map +1 -0
  449. package/dist/src/routing/modelRouterService.js +0 -15
  450. package/dist/src/routing/modelRouterService.js.map +1 -1
  451. package/dist/src/routing/modelRouterService.test.js +0 -62
  452. package/dist/src/routing/modelRouterService.test.js.map +1 -1
  453. package/dist/src/routing/routingStrategy.d.ts +2 -0
  454. package/dist/src/routing/strategies/classifierStrategy.js +10 -21
  455. package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
  456. package/dist/src/routing/strategies/classifierStrategy.test.js +18 -1
  457. package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -1
  458. package/dist/src/routing/strategies/compositeStrategy.js +4 -2
  459. package/dist/src/routing/strategies/compositeStrategy.js.map +1 -1
  460. package/dist/src/routing/strategies/compositeStrategy.test.js +11 -10
  461. package/dist/src/routing/strategies/compositeStrategy.test.js.map +1 -1
  462. package/dist/src/routing/strategies/fallbackStrategy.d.ts +1 -1
  463. package/dist/src/routing/strategies/fallbackStrategy.js +21 -13
  464. package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -1
  465. package/dist/src/routing/strategies/fallbackStrategy.test.js +76 -39
  466. package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -1
  467. package/dist/src/routing/strategies/overrideStrategy.d.ts +1 -1
  468. package/dist/src/routing/strategies/overrideStrategy.js +5 -4
  469. package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
  470. package/dist/src/routing/strategies/overrideStrategy.test.js +14 -0
  471. package/dist/src/routing/strategies/overrideStrategy.test.js.map +1 -1
  472. package/dist/src/safety/checker-runner.js +17 -6
  473. package/dist/src/safety/checker-runner.js.map +1 -1
  474. package/dist/src/scheduler/tool-executor.d.ts +22 -0
  475. package/dist/src/scheduler/tool-executor.js +198 -0
  476. package/dist/src/scheduler/tool-executor.js.map +1 -0
  477. package/dist/src/scheduler/tool-executor.test.d.ts +6 -0
  478. package/dist/src/scheduler/tool-executor.test.js +231 -0
  479. package/dist/src/scheduler/tool-executor.test.js.map +1 -0
  480. package/dist/src/scheduler/tool-modifier.d.ts +23 -0
  481. package/dist/src/scheduler/tool-modifier.js +50 -0
  482. package/dist/src/scheduler/tool-modifier.js.map +1 -0
  483. package/dist/src/scheduler/tool-modifier.test.d.ts +6 -0
  484. package/dist/src/scheduler/tool-modifier.test.js +159 -0
  485. package/dist/src/scheduler/tool-modifier.test.js.map +1 -0
  486. package/dist/src/scheduler/types.d.ts +95 -0
  487. package/dist/src/scheduler/types.js +7 -0
  488. package/dist/src/scheduler/types.js.map +1 -0
  489. package/dist/src/services/chatCompressionService.js +8 -1
  490. package/dist/src/services/chatCompressionService.js.map +1 -1
  491. package/dist/src/services/chatCompressionService.test.js +3 -0
  492. package/dist/src/services/chatCompressionService.test.js.map +1 -1
  493. package/dist/src/services/chatRecordingService.d.ts +21 -1
  494. package/dist/src/services/chatRecordingService.js +57 -2
  495. package/dist/src/services/chatRecordingService.js.map +1 -1
  496. package/dist/src/services/chatRecordingService.test.js +43 -0
  497. package/dist/src/services/chatRecordingService.test.js.map +1 -1
  498. package/dist/src/services/contextManager.d.ts +5 -11
  499. package/dist/src/services/contextManager.js +20 -17
  500. package/dist/src/services/contextManager.js.map +1 -1
  501. package/dist/src/services/contextManager.test.js +40 -41
  502. package/dist/src/services/contextManager.test.js.map +1 -1
  503. package/dist/src/services/environmentSanitization.d.ts +15 -0
  504. package/dist/src/services/environmentSanitization.js +142 -0
  505. package/dist/src/services/environmentSanitization.js.map +1 -0
  506. package/dist/src/services/environmentSanitization.test.d.ts +6 -0
  507. package/dist/src/services/environmentSanitization.test.js +284 -0
  508. package/dist/src/services/environmentSanitization.test.js.map +1 -0
  509. package/dist/src/services/fileSystemService.d.ts +0 -9
  510. package/dist/src/services/fileSystemService.js +0 -11
  511. package/dist/src/services/fileSystemService.js.map +1 -1
  512. package/dist/src/services/gitService.js +15 -1
  513. package/dist/src/services/gitService.js.map +1 -1
  514. package/dist/src/services/gitService.test.js +56 -2
  515. package/dist/src/services/gitService.test.js.map +1 -1
  516. package/dist/src/services/loopDetectionService.js +4 -3
  517. package/dist/src/services/loopDetectionService.js.map +1 -1
  518. package/dist/src/services/loopDetectionService.test.js +14 -8
  519. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  520. package/dist/src/services/modelConfig.golden.test.js +32 -0
  521. package/dist/src/services/modelConfig.golden.test.js.map +1 -1
  522. package/dist/src/services/modelConfig.integration.test.js +3 -3
  523. package/dist/src/services/modelConfig.integration.test.js.map +1 -1
  524. package/dist/src/services/modelConfigService.d.ts +41 -4
  525. package/dist/src/services/modelConfigService.js +135 -75
  526. package/dist/src/services/modelConfigService.js.map +1 -1
  527. package/dist/src/services/modelConfigService.test.js +226 -0
  528. package/dist/src/services/modelConfigService.test.js.map +1 -1
  529. package/dist/src/services/modelConfigServiceTestUtils.d.ts +10 -0
  530. package/dist/src/services/modelConfigServiceTestUtils.js +17 -0
  531. package/dist/src/services/modelConfigServiceTestUtils.js.map +1 -0
  532. package/dist/src/services/sessionSummaryService.d.ts +28 -0
  533. package/dist/src/services/sessionSummaryService.js +131 -0
  534. package/dist/src/services/sessionSummaryService.js.map +1 -0
  535. package/dist/src/services/sessionSummaryService.test.d.ts +6 -0
  536. package/dist/src/services/sessionSummaryService.test.js +785 -0
  537. package/dist/src/services/sessionSummaryService.test.js.map +1 -0
  538. package/dist/src/services/sessionSummaryUtils.d.ts +16 -0
  539. package/dist/src/services/sessionSummaryUtils.js +129 -0
  540. package/dist/src/services/sessionSummaryUtils.js.map +1 -0
  541. package/dist/src/services/sessionSummaryUtils.test.d.ts +6 -0
  542. package/dist/src/services/sessionSummaryUtils.test.js +137 -0
  543. package/dist/src/services/sessionSummaryUtils.test.js.map +1 -0
  544. package/dist/src/services/shellExecutionService.d.ts +2 -0
  545. package/dist/src/services/shellExecutionService.js +34 -72
  546. package/dist/src/services/shellExecutionService.js.map +1 -1
  547. package/dist/src/services/shellExecutionService.test.js +114 -8
  548. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  549. package/dist/src/services/test-data/resolved-aliases-retry.golden.json +238 -0
  550. package/dist/src/services/test-data/resolved-aliases.golden.json +16 -0
  551. package/dist/src/skills/skillLoader.d.ts +31 -0
  552. package/dist/src/skills/skillLoader.js +77 -0
  553. package/dist/src/skills/skillLoader.js.map +1 -0
  554. package/dist/src/skills/skillLoader.test.d.ts +6 -0
  555. package/dist/src/skills/skillLoader.test.js +75 -0
  556. package/dist/src/skills/skillLoader.test.js.map +1 -0
  557. package/dist/src/skills/skillManager.d.ts +69 -0
  558. package/dist/src/skills/skillManager.js +127 -0
  559. package/dist/src/skills/skillManager.js.map +1 -0
  560. package/dist/src/skills/skillManager.test.d.ts +6 -0
  561. package/dist/src/skills/skillManager.test.js +210 -0
  562. package/dist/src/skills/skillManager.test.js.map +1 -0
  563. package/dist/src/telemetry/activity-detector.test.js.map +1 -1
  564. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +19 -9
  565. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +261 -164
  566. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  567. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +223 -27
  568. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  569. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +12 -3
  570. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +26 -5
  571. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  572. package/dist/src/telemetry/config.js +2 -0
  573. package/dist/src/telemetry/config.js.map +1 -1
  574. package/dist/src/telemetry/config.test.js +25 -0
  575. package/dist/src/telemetry/config.test.js.map +1 -1
  576. package/dist/src/telemetry/gcp-exporters.d.ts +4 -3
  577. package/dist/src/telemetry/gcp-exporters.js +8 -4
  578. package/dist/src/telemetry/gcp-exporters.js.map +1 -1
  579. package/dist/src/telemetry/index.d.ts +1 -1
  580. package/dist/src/telemetry/index.js +1 -1
  581. package/dist/src/telemetry/index.js.map +1 -1
  582. package/dist/src/telemetry/loggers.d.ts +4 -3
  583. package/dist/src/telemetry/loggers.js +351 -340
  584. package/dist/src/telemetry/loggers.js.map +1 -1
  585. package/dist/src/telemetry/loggers.test.circular.js +1 -0
  586. package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
  587. package/dist/src/telemetry/loggers.test.js +71 -15
  588. package/dist/src/telemetry/loggers.test.js.map +1 -1
  589. package/dist/src/telemetry/metrics.test.js.map +1 -1
  590. package/dist/src/telemetry/sdk.d.ts +9 -2
  591. package/dist/src/telemetry/sdk.js +142 -17
  592. package/dist/src/telemetry/sdk.js.map +1 -1
  593. package/dist/src/telemetry/sdk.test.js +130 -28
  594. package/dist/src/telemetry/sdk.test.js.map +1 -1
  595. package/dist/src/telemetry/startupProfiler.js +26 -3
  596. package/dist/src/telemetry/startupProfiler.js.map +1 -1
  597. package/dist/src/telemetry/startupProfiler.test.js +49 -7
  598. package/dist/src/telemetry/startupProfiler.test.js.map +1 -1
  599. package/dist/src/telemetry/telemetry.test.js +10 -3
  600. package/dist/src/telemetry/telemetry.test.js.map +1 -1
  601. package/dist/src/telemetry/trace.js.map +1 -1
  602. package/dist/src/telemetry/types.d.ts +37 -12
  603. package/dist/src/telemetry/types.js +61 -20
  604. package/dist/src/telemetry/types.js.map +1 -1
  605. package/dist/src/telemetry/uiTelemetry.d.ts +1 -0
  606. package/dist/src/telemetry/uiTelemetry.js +2 -0
  607. package/dist/src/telemetry/uiTelemetry.js.map +1 -1
  608. package/dist/src/telemetry/uiTelemetry.test.js +4 -0
  609. package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
  610. package/dist/src/test-utils/mock-message-bus.d.ts +1 -0
  611. package/dist/src/test-utils/mock-message-bus.js +29 -0
  612. package/dist/src/test-utils/mock-message-bus.js.map +1 -1
  613. package/dist/src/test-utils/mock-tool.d.ts +5 -3
  614. package/dist/src/test-utils/mock-tool.js +11 -10
  615. package/dist/src/test-utils/mock-tool.js.map +1 -1
  616. package/dist/src/tools/activate-skill.d.ts +27 -0
  617. package/dist/src/tools/activate-skill.js +133 -0
  618. package/dist/src/tools/activate-skill.js.map +1 -0
  619. package/dist/src/tools/activate-skill.test.d.ts +6 -0
  620. package/dist/src/tools/activate-skill.test.js +113 -0
  621. package/dist/src/tools/activate-skill.test.js.map +1 -0
  622. package/dist/src/tools/confirmation-policy.test.d.ts +6 -0
  623. package/dist/src/tools/confirmation-policy.test.js +143 -0
  624. package/dist/src/tools/confirmation-policy.test.js.map +1 -0
  625. package/dist/src/tools/edit.d.ts +27 -5
  626. package/dist/src/tools/edit.js +460 -136
  627. package/dist/src/tools/edit.js.map +1 -1
  628. package/dist/src/tools/edit.test.js +292 -526
  629. package/dist/src/tools/edit.test.js.map +1 -1
  630. package/dist/src/tools/get-internal-docs.d.ts +27 -0
  631. package/dist/src/tools/get-internal-docs.js +122 -0
  632. package/dist/src/tools/get-internal-docs.js.map +1 -0
  633. package/dist/src/tools/get-internal-docs.test.d.ts +6 -0
  634. package/dist/src/tools/get-internal-docs.test.js +57 -0
  635. package/dist/src/tools/get-internal-docs.test.js.map +1 -0
  636. package/dist/src/tools/glob.d.ts +2 -2
  637. package/dist/src/tools/glob.js +1 -1
  638. package/dist/src/tools/glob.js.map +1 -1
  639. package/dist/src/tools/glob.test.js +2 -1
  640. package/dist/src/tools/glob.test.js.map +1 -1
  641. package/dist/src/tools/grep.d.ts +2 -2
  642. package/dist/src/tools/grep.js +1 -1
  643. package/dist/src/tools/grep.js.map +1 -1
  644. package/dist/src/tools/grep.test.js +5 -4
  645. package/dist/src/tools/grep.test.js.map +1 -1
  646. package/dist/src/tools/ls.d.ts +2 -2
  647. package/dist/src/tools/ls.js +2 -2
  648. package/dist/src/tools/ls.js.map +1 -1
  649. package/dist/src/tools/ls.test.js +2 -1
  650. package/dist/src/tools/ls.test.js.map +1 -1
  651. package/dist/src/tools/mcp-client-manager.d.ts +2 -1
  652. package/dist/src/tools/mcp-client-manager.js +32 -9
  653. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  654. package/dist/src/tools/mcp-client-manager.test.js +41 -10
  655. package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
  656. package/dist/src/tools/mcp-client.d.ts +43 -6
  657. package/dist/src/tools/mcp-client.js +443 -176
  658. package/dist/src/tools/mcp-client.js.map +1 -1
  659. package/dist/src/tools/mcp-client.test.js +664 -39
  660. package/dist/src/tools/mcp-client.test.js.map +1 -1
  661. package/dist/src/tools/mcp-tool.d.ts +20 -5
  662. package/dist/src/tools/mcp-tool.js +21 -8
  663. package/dist/src/tools/mcp-tool.js.map +1 -1
  664. package/dist/src/tools/mcp-tool.test.js +35 -5
  665. package/dist/src/tools/mcp-tool.test.js.map +1 -1
  666. package/dist/src/tools/memoryTool.d.ts +3 -3
  667. package/dist/src/tools/memoryTool.js +3 -4
  668. package/dist/src/tools/memoryTool.js.map +1 -1
  669. package/dist/src/tools/memoryTool.test.js +5 -2
  670. package/dist/src/tools/memoryTool.test.js.map +1 -1
  671. package/dist/src/tools/message-bus-integration.test.js +10 -37
  672. package/dist/src/tools/message-bus-integration.test.js.map +1 -1
  673. package/dist/src/tools/modifiable-tool.js.map +1 -1
  674. package/dist/src/tools/modifiable-tool.test.js +22 -13
  675. package/dist/src/tools/modifiable-tool.test.js.map +1 -1
  676. package/dist/src/tools/read-file.d.ts +2 -2
  677. package/dist/src/tools/read-file.js +2 -2
  678. package/dist/src/tools/read-file.js.map +1 -1
  679. package/dist/src/tools/read-file.test.js +3 -2
  680. package/dist/src/tools/read-file.test.js.map +1 -1
  681. package/dist/src/tools/read-many-files.d.ts +2 -2
  682. package/dist/src/tools/read-many-files.js +7 -6
  683. package/dist/src/tools/read-many-files.js.map +1 -1
  684. package/dist/src/tools/read-many-files.test.js +4 -3
  685. package/dist/src/tools/read-many-files.test.js.map +1 -1
  686. package/dist/src/tools/ripGrep.d.ts +3 -2
  687. package/dist/src/tools/ripGrep.js +18 -7
  688. package/dist/src/tools/ripGrep.js.map +1 -1
  689. package/dist/src/tools/ripGrep.test.js +60 -4
  690. package/dist/src/tools/ripGrep.test.js.map +1 -1
  691. package/dist/src/tools/shell.d.ts +5 -7
  692. package/dist/src/tools/shell.js +35 -49
  693. package/dist/src/tools/shell.js.map +1 -1
  694. package/dist/src/tools/shell.test.js +36 -59
  695. package/dist/src/tools/shell.test.js.map +1 -1
  696. package/dist/src/tools/tool-error.d.ts +6 -1
  697. package/dist/src/tools/tool-error.js +6 -0
  698. package/dist/src/tools/tool-error.js.map +1 -1
  699. package/dist/src/tools/tool-names.d.ts +17 -0
  700. package/dist/src/tools/tool-names.js +59 -0
  701. package/dist/src/tools/tool-names.js.map +1 -1
  702. package/dist/src/tools/tool-names.test.d.ts +6 -0
  703. package/dist/src/tools/tool-names.test.js +43 -0
  704. package/dist/src/tools/tool-names.test.js.map +1 -0
  705. package/dist/src/tools/tool-registry.d.ts +11 -7
  706. package/dist/src/tools/tool-registry.js +15 -10
  707. package/dist/src/tools/tool-registry.js.map +1 -1
  708. package/dist/src/tools/tool-registry.test.js +16 -11
  709. package/dist/src/tools/tool-registry.test.js.map +1 -1
  710. package/dist/src/tools/tools.d.ts +27 -6
  711. package/dist/src/tools/tools.js +44 -25
  712. package/dist/src/tools/tools.js.map +1 -1
  713. package/dist/src/tools/tools.test.js +3 -1
  714. package/dist/src/tools/tools.test.js.map +1 -1
  715. package/dist/src/tools/web-fetch.d.ts +2 -2
  716. package/dist/src/tools/web-fetch.js +21 -8
  717. package/dist/src/tools/web-fetch.js.map +1 -1
  718. package/dist/src/tools/web-fetch.test.js +18 -19
  719. package/dist/src/tools/web-fetch.test.js.map +1 -1
  720. package/dist/src/tools/web-search.d.ts +2 -2
  721. package/dist/src/tools/web-search.js +5 -5
  722. package/dist/src/tools/web-search.js.map +1 -1
  723. package/dist/src/tools/web-search.test.js +2 -1
  724. package/dist/src/tools/web-search.test.js.map +1 -1
  725. package/dist/src/tools/write-file.d.ts +2 -2
  726. package/dist/src/tools/write-file.js +14 -6
  727. package/dist/src/tools/write-file.js.map +1 -1
  728. package/dist/src/tools/write-file.test.js +49 -7
  729. package/dist/src/tools/write-file.test.js.map +1 -1
  730. package/dist/src/tools/write-todos.d.ts +2 -2
  731. package/dist/src/tools/write-todos.js +5 -4
  732. package/dist/src/tools/write-todos.js.map +1 -1
  733. package/dist/src/tools/write-todos.test.js +2 -1
  734. package/dist/src/tools/write-todos.test.js.map +1 -1
  735. package/dist/src/utils/apiConversionUtils.d.ts +12 -0
  736. package/dist/src/utils/apiConversionUtils.js +46 -0
  737. package/dist/src/utils/apiConversionUtils.js.map +1 -0
  738. package/dist/src/utils/apiConversionUtils.test.d.ts +6 -0
  739. package/dist/src/utils/apiConversionUtils.test.js +150 -0
  740. package/dist/src/utils/apiConversionUtils.test.js.map +1 -0
  741. package/dist/src/utils/bfsFileSearch.d.ts +8 -0
  742. package/dist/src/utils/bfsFileSearch.js +63 -23
  743. package/dist/src/utils/bfsFileSearch.js.map +1 -1
  744. package/dist/src/utils/bfsFileSearch.test.js +65 -1
  745. package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
  746. package/dist/src/utils/checkpointUtils.d.ts +82 -0
  747. package/dist/src/utils/checkpointUtils.js +117 -0
  748. package/dist/src/utils/checkpointUtils.js.map +1 -0
  749. package/dist/src/utils/checkpointUtils.test.d.ts +6 -0
  750. package/dist/src/utils/checkpointUtils.test.js +229 -0
  751. package/dist/src/utils/checkpointUtils.test.js.map +1 -0
  752. package/dist/src/utils/debugLogger.d.ts +3 -0
  753. package/dist/src/utils/debugLogger.js +28 -0
  754. package/dist/src/utils/debugLogger.js.map +1 -1
  755. package/dist/src/utils/editCorrector.d.ts +3 -3
  756. package/dist/src/utils/editCorrector.js +27 -10
  757. package/dist/src/utils/editCorrector.js.map +1 -1
  758. package/dist/src/utils/editCorrector.test.js +27 -23
  759. package/dist/src/utils/editCorrector.test.js.map +1 -1
  760. package/dist/src/utils/editor.d.ts +10 -1
  761. package/dist/src/utils/editor.js +48 -19
  762. package/dist/src/utils/editor.js.map +1 -1
  763. package/dist/src/utils/editor.test.js +27 -4
  764. package/dist/src/utils/editor.test.js.map +1 -1
  765. package/dist/src/utils/environmentContext.d.ts +1 -0
  766. package/dist/src/utils/environmentContext.js +4 -0
  767. package/dist/src/utils/environmentContext.js.map +1 -1
  768. package/dist/src/utils/environmentContext.test.js +2 -0
  769. package/dist/src/utils/environmentContext.test.js.map +1 -1
  770. package/dist/src/utils/errorReporting.d.ts +1 -1
  771. package/dist/src/utils/errorReporting.js +13 -12
  772. package/dist/src/utils/errorReporting.js.map +1 -1
  773. package/dist/src/utils/errorReporting.test.js +17 -14
  774. package/dist/src/utils/errorReporting.test.js.map +1 -1
  775. package/dist/src/utils/errors.d.ts +8 -0
  776. package/dist/src/utils/errors.js +39 -2
  777. package/dist/src/utils/errors.js.map +1 -1
  778. package/dist/src/utils/errors.test.d.ts +6 -0
  779. package/dist/src/utils/errors.test.js +155 -0
  780. package/dist/src/utils/errors.test.js.map +1 -0
  781. package/dist/src/utils/events.d.ts +71 -19
  782. package/dist/src/utils/events.js +35 -9
  783. package/dist/src/utils/events.js.map +1 -1
  784. package/dist/src/utils/events.test.js +25 -0
  785. package/dist/src/utils/events.test.js.map +1 -1
  786. package/dist/src/utils/extensionLoader.d.ts +2 -2
  787. package/dist/src/utils/extensionLoader.js +5 -6
  788. package/dist/src/utils/extensionLoader.js.map +1 -1
  789. package/dist/src/utils/extensionLoader.test.js +11 -0
  790. package/dist/src/utils/extensionLoader.test.js.map +1 -1
  791. package/dist/src/utils/fetch.d.ts +1 -1
  792. package/dist/src/utils/fetch.js +3 -3
  793. package/dist/src/utils/fetch.js.map +1 -1
  794. package/dist/src/utils/fileDiffUtils.d.ts +18 -0
  795. package/dist/src/utils/fileDiffUtils.js +37 -0
  796. package/dist/src/utils/fileDiffUtils.js.map +1 -0
  797. package/dist/src/utils/fileDiffUtils.test.d.ts +6 -0
  798. package/dist/src/utils/fileDiffUtils.test.js +84 -0
  799. package/dist/src/utils/fileDiffUtils.test.js.map +1 -0
  800. package/dist/src/utils/fileUtils.d.ts +4 -0
  801. package/dist/src/utils/fileUtils.js +53 -0
  802. package/dist/src/utils/fileUtils.js.map +1 -1
  803. package/dist/src/utils/fileUtils.test.js +127 -1
  804. package/dist/src/utils/fileUtils.test.js.map +1 -1
  805. package/dist/src/utils/filesearch/crawlCache.js.map +1 -1
  806. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  807. package/dist/src/utils/flashFallback.test.js +1 -1
  808. package/dist/src/utils/flashFallback.test.js.map +1 -1
  809. package/dist/src/utils/geminiIgnoreParser.d.ts +11 -0
  810. package/dist/src/utils/geminiIgnoreParser.js +20 -0
  811. package/dist/src/utils/geminiIgnoreParser.js.map +1 -1
  812. package/dist/src/utils/geminiIgnoreParser.test.js +48 -0
  813. package/dist/src/utils/geminiIgnoreParser.test.js.map +1 -1
  814. package/dist/src/utils/generateContentResponseUtilities.d.ts +3 -1
  815. package/dist/src/utils/generateContentResponseUtilities.js +106 -0
  816. package/dist/src/utils/generateContentResponseUtilities.js.map +1 -1
  817. package/dist/src/utils/generateContentResponseUtilities.test.js +279 -2
  818. package/dist/src/utils/generateContentResponseUtilities.test.js.map +1 -1
  819. package/dist/src/utils/getFolderStructure.js +7 -2
  820. package/dist/src/utils/getFolderStructure.js.map +1 -1
  821. package/dist/src/utils/gitIgnoreParser.js +9 -10
  822. package/dist/src/utils/gitIgnoreParser.js.map +1 -1
  823. package/dist/src/utils/googleErrors.js +31 -18
  824. package/dist/src/utils/googleErrors.js.map +1 -1
  825. package/dist/src/utils/googleErrors.test.js +10 -2
  826. package/dist/src/utils/googleErrors.test.js.map +1 -1
  827. package/dist/src/utils/googleQuotaErrors.d.ts +3 -3
  828. package/dist/src/utils/googleQuotaErrors.js +32 -6
  829. package/dist/src/utils/googleQuotaErrors.js.map +1 -1
  830. package/dist/src/utils/googleQuotaErrors.test.js +94 -2
  831. package/dist/src/utils/googleQuotaErrors.test.js.map +1 -1
  832. package/dist/src/utils/installationManager.test.js +11 -3
  833. package/dist/src/utils/installationManager.test.js.map +1 -1
  834. package/dist/src/utils/memoryDiscovery.js +3 -4
  835. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  836. package/dist/src/utils/memoryDiscovery.test.js +12 -1
  837. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  838. package/dist/src/utils/nextSpeakerChecker.test.js +4 -0
  839. package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
  840. package/dist/src/utils/partUtils.js +1 -1
  841. package/dist/src/utils/partUtils.js.map +1 -1
  842. package/dist/src/utils/pathCorrector.js +12 -2
  843. package/dist/src/utils/pathCorrector.js.map +1 -1
  844. package/dist/src/utils/pathCorrector.test.js +6 -2
  845. package/dist/src/utils/pathCorrector.test.js.map +1 -1
  846. package/dist/src/utils/paths.d.ts +10 -0
  847. package/dist/src/utils/paths.js +20 -1
  848. package/dist/src/utils/paths.js.map +1 -1
  849. package/dist/src/utils/retry.d.ts +12 -0
  850. package/dist/src/utils/retry.js +70 -17
  851. package/dist/src/utils/retry.js.map +1 -1
  852. package/dist/src/utils/retry.test.js +181 -21
  853. package/dist/src/utils/retry.test.js.map +1 -1
  854. package/dist/src/utils/shell-utils.d.ts +16 -47
  855. package/dist/src/utils/shell-utils.js +98 -194
  856. package/dist/src/utils/shell-utils.js.map +1 -1
  857. package/dist/src/utils/shell-utils.test.js +99 -288
  858. package/dist/src/utils/shell-utils.test.js.map +1 -1
  859. package/dist/src/utils/summarizer.test.js +3 -2
  860. package/dist/src/utils/summarizer.test.js.map +1 -1
  861. package/dist/src/utils/terminal.d.ts +4 -0
  862. package/dist/src/utils/terminal.js +12 -0
  863. package/dist/src/utils/terminal.js.map +1 -1
  864. package/dist/src/utils/terminalSerializer.test.js +17 -0
  865. package/dist/src/utils/terminalSerializer.test.js.map +1 -1
  866. package/dist/src/utils/tokenCalculation.js +20 -5
  867. package/dist/src/utils/tokenCalculation.js.map +1 -1
  868. package/dist/src/utils/tokenCalculation.test.js +11 -2
  869. package/dist/src/utils/tokenCalculation.test.js.map +1 -1
  870. package/dist/src/utils/tool-utils.d.ts +9 -0
  871. package/dist/src/utils/tool-utils.js +29 -0
  872. package/dist/src/utils/tool-utils.js.map +1 -1
  873. package/dist/src/utils/tool-utils.test.js +17 -2
  874. package/dist/src/utils/tool-utils.test.js.map +1 -1
  875. package/dist/src/utils/userAccountManager.test.js +5 -5
  876. package/dist/src/utils/userAccountManager.test.js.map +1 -1
  877. package/dist/src/utils/version.d.ts +6 -0
  878. package/dist/src/utils/version.js +15 -0
  879. package/dist/src/utils/version.js.map +1 -0
  880. package/dist/src/utils/version.test.d.ts +6 -0
  881. package/dist/src/utils/version.test.js +39 -0
  882. package/dist/src/utils/version.test.js.map +1 -0
  883. package/dist/src/utils/workspaceContext.test.js +1 -1
  884. package/dist/src/utils/workspaceContext.test.js.map +1 -1
  885. package/dist/tsconfig.tsbuildinfo +1 -1
  886. package/package.json +8 -6
  887. package/dist/src/agents/executor.js.map +0 -1
  888. package/dist/src/agents/executor.test.js.map +0 -1
  889. package/dist/src/agents/invocation.js.map +0 -1
  890. package/dist/src/agents/invocation.test.js.map +0 -1
  891. package/dist/src/tools/smart-edit.d.ts +0 -78
  892. package/dist/src/tools/smart-edit.js +0 -717
  893. package/dist/src/tools/smart-edit.js.map +0 -1
  894. package/dist/src/tools/smart-edit.test.js +0 -592
  895. package/dist/src/tools/smart-edit.test.js.map +0 -1
  896. /package/dist/src/agents/{executor.test.d.ts → a2a-client-manager.test.d.ts} +0 -0
  897. /package/dist/src/agents/{invocation.test.d.ts → a2aUtils.test.d.ts} +0 -0
  898. /package/dist/src/{tools/smart-edit.test.d.ts → agents/agentLoader.test.d.ts} +0 -0
@@ -7,19 +7,25 @@ import { GoogleAuth } from 'google-auth-library';
7
7
  import * as ClientLib from '@modelcontextprotocol/sdk/client/index.js';
8
8
  import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
9
9
  import * as SdkClientStdioLib from '@modelcontextprotocol/sdk/client/stdio.js';
10
- import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
10
+ import { StreamableHTTPClientTransport, StreamableHTTPError, } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
11
11
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
12
12
  import { AuthProviderType } from '../config/config.js';
13
13
  import { GoogleCredentialProvider } from '../mcp/google-auth-provider.js';
14
14
  import { MCPOAuthProvider } from '../mcp/oauth-provider.js';
15
15
  import { MCPOAuthTokenStorage } from '../mcp/oauth-token-storage.js';
16
16
  import { OAuthUtils } from '../mcp/oauth-utils.js';
17
+ import { ToolListChangedNotificationSchema } from '@modelcontextprotocol/sdk/types.js';
17
18
  import { WorkspaceContext } from '../utils/workspaceContext.js';
18
19
  import { connectToMcpServer, createTransport, hasNetworkTransport, isEnabled, McpClient, populateMcpServerCommand, } from './mcp-client.js';
19
20
  import * as fs from 'node:fs';
20
21
  import * as os from 'node:os';
21
22
  import * as path from 'node:path';
22
23
  import { coreEvents } from '../utils/events.js';
24
+ const EMPTY_CONFIG = {
25
+ enableEnvironmentVariableRedaction: true,
26
+ allowedEnvironmentVariables: [],
27
+ blockedEnvironmentVariables: [],
28
+ };
23
29
  const mockAuthProviderKeycloak = vi.hoisted(() => vi.fn().mockImplementation(() => ({
24
30
  getToken: vi.fn().mockResolvedValue('test-agent-token'),
25
31
  })));
@@ -60,6 +66,7 @@ describe('mcp-client', () => {
60
66
  getStatus: vi.fn(),
61
67
  registerCapabilities: vi.fn(),
62
68
  setRequestHandler: vi.fn(),
69
+ setNotificationHandler: vi.fn(),
63
70
  getServerCapabilities: vi.fn().mockReturnValue({ tools: {} }),
64
71
  listTools: vi.fn().mockResolvedValue({
65
72
  tools: [
@@ -84,12 +91,20 @@ describe('mcp-client', () => {
84
91
  sortTools: vi.fn(),
85
92
  getMessageBus: vi.fn().mockReturnValue(undefined),
86
93
  };
94
+ const promptRegistry = {
95
+ registerPrompt: vi.fn(),
96
+ removePromptsByServer: vi.fn(),
97
+ };
98
+ const resourceRegistry = {
99
+ setResourcesForServer: vi.fn(),
100
+ removeResourcesByServer: vi.fn(),
101
+ };
87
102
  const client = new McpClient('test-server', {
88
103
  command: 'test-command',
89
- }, mockedToolRegistry, {}, workspaceContext, false);
104
+ }, mockedToolRegistry, promptRegistry, resourceRegistry, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
90
105
  await client.connect();
91
106
  await client.discover({});
92
- expect(mockedClient.listTools).toHaveBeenCalledWith({});
107
+ expect(mockedClient.listTools).toHaveBeenCalledWith({}, { timeout: 600000 });
93
108
  });
94
109
  it('should not skip tools even if a parameter is missing a type', async () => {
95
110
  const consoleWarnSpy = vi
@@ -102,6 +117,7 @@ describe('mcp-client', () => {
102
117
  getStatus: vi.fn(),
103
118
  registerCapabilities: vi.fn(),
104
119
  setRequestHandler: vi.fn(),
120
+ setNotificationHandler: vi.fn(),
105
121
  getServerCapabilities: vi.fn().mockReturnValue({ tools: {} }),
106
122
  listTools: vi.fn().mockResolvedValue({
107
123
  tools: [
@@ -137,9 +153,17 @@ describe('mcp-client', () => {
137
153
  sortTools: vi.fn(),
138
154
  getMessageBus: vi.fn().mockReturnValue(undefined),
139
155
  };
156
+ const promptRegistry = {
157
+ registerPrompt: vi.fn(),
158
+ removePromptsByServer: vi.fn(),
159
+ };
160
+ const resourceRegistry = {
161
+ setResourcesForServer: vi.fn(),
162
+ removeResourcesByServer: vi.fn(),
163
+ };
140
164
  const client = new McpClient('test-server', {
141
165
  command: 'test-command',
142
- }, mockedToolRegistry, {}, workspaceContext, false);
166
+ }, mockedToolRegistry, promptRegistry, resourceRegistry, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
143
167
  await client.connect();
144
168
  await client.discover({});
145
169
  expect(mockedToolRegistry.registerTool).toHaveBeenCalledTimes(2);
@@ -154,6 +178,7 @@ describe('mcp-client', () => {
154
178
  getStatus: vi.fn(),
155
179
  registerCapabilities: vi.fn(),
156
180
  setRequestHandler: vi.fn(),
181
+ setNotificationHandler: vi.fn(),
157
182
  getServerCapabilities: vi.fn().mockReturnValue({ prompts: {} }),
158
183
  listTools: vi.fn().mockResolvedValue({ tools: [] }),
159
184
  listPrompts: vi.fn().mockRejectedValue(new Error('Test error')),
@@ -165,11 +190,19 @@ describe('mcp-client', () => {
165
190
  registerTool: vi.fn(),
166
191
  getMessageBus: vi.fn().mockReturnValue(undefined),
167
192
  };
193
+ const promptRegistry = {
194
+ registerPrompt: vi.fn(),
195
+ removePromptsByServer: vi.fn(),
196
+ };
197
+ const resourceRegistry = {
198
+ setResourcesForServer: vi.fn(),
199
+ removeResourcesByServer: vi.fn(),
200
+ };
168
201
  const client = new McpClient('test-server', {
169
202
  command: 'test-command',
170
- }, mockedToolRegistry, {}, workspaceContext, false);
203
+ }, mockedToolRegistry, promptRegistry, resourceRegistry, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
171
204
  await client.connect();
172
- await expect(client.discover({})).rejects.toThrow('No prompts or tools found on the server.');
205
+ await expect(client.discover({})).rejects.toThrow('No prompts, tools, or resources found on the server.');
173
206
  expect(coreEvents.emitFeedback).toHaveBeenCalledWith('error', `Error discovering prompts from test-server: Test error`, expect.any(Error));
174
207
  });
175
208
  it('should not discover tools if server does not support them', async () => {
@@ -180,6 +213,7 @@ describe('mcp-client', () => {
180
213
  getStatus: vi.fn(),
181
214
  registerCapabilities: vi.fn(),
182
215
  setRequestHandler: vi.fn(),
216
+ setNotificationHandler: vi.fn(),
183
217
  getServerCapabilities: vi.fn().mockReturnValue({ prompts: {} }),
184
218
  listPrompts: vi.fn().mockResolvedValue({ prompts: [] }),
185
219
  request: vi.fn().mockResolvedValue({}),
@@ -191,11 +225,19 @@ describe('mcp-client', () => {
191
225
  sortTools: vi.fn(),
192
226
  getMessageBus: vi.fn().mockReturnValue(undefined),
193
227
  };
228
+ const promptRegistry = {
229
+ registerPrompt: vi.fn(),
230
+ removePromptsByServer: vi.fn(),
231
+ };
232
+ const resourceRegistry = {
233
+ setResourcesForServer: vi.fn(),
234
+ removeResourcesByServer: vi.fn(),
235
+ };
194
236
  const client = new McpClient('test-server', {
195
237
  command: 'test-command',
196
- }, mockedToolRegistry, {}, workspaceContext, false);
238
+ }, mockedToolRegistry, promptRegistry, resourceRegistry, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
197
239
  await client.connect();
198
- await expect(client.discover({})).rejects.toThrow('No prompts or tools found on the server.');
240
+ await expect(client.discover({})).rejects.toThrow('No prompts, tools, or resources found on the server.');
199
241
  });
200
242
  it('should discover tools if server supports them', async () => {
201
243
  const mockedClient = {
@@ -205,6 +247,7 @@ describe('mcp-client', () => {
205
247
  getStatus: vi.fn(),
206
248
  registerCapabilities: vi.fn(),
207
249
  setRequestHandler: vi.fn(),
250
+ setNotificationHandler: vi.fn(),
208
251
  getServerCapabilities: vi.fn().mockReturnValue({ tools: {} }),
209
252
  listTools: vi.fn().mockResolvedValue({
210
253
  tools: [
@@ -225,9 +268,17 @@ describe('mcp-client', () => {
225
268
  sortTools: vi.fn(),
226
269
  getMessageBus: vi.fn().mockReturnValue(undefined),
227
270
  };
271
+ const promptRegistry = {
272
+ registerPrompt: vi.fn(),
273
+ removePromptsByServer: vi.fn(),
274
+ };
275
+ const resourceRegistry = {
276
+ setResourcesForServer: vi.fn(),
277
+ removeResourcesByServer: vi.fn(),
278
+ };
228
279
  const client = new McpClient('test-server', {
229
280
  command: 'test-command',
230
- }, mockedToolRegistry, {}, workspaceContext, false);
281
+ }, mockedToolRegistry, promptRegistry, resourceRegistry, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
231
282
  await client.connect();
232
283
  await client.discover({});
233
284
  expect(mockedToolRegistry.registerTool).toHaveBeenCalledOnce();
@@ -240,6 +291,7 @@ describe('mcp-client', () => {
240
291
  getStatus: vi.fn(),
241
292
  registerCapabilities: vi.fn(),
242
293
  setRequestHandler: vi.fn(),
294
+ setNotificationHandler: vi.fn(),
243
295
  getServerCapabilities: vi.fn().mockReturnValue({ tools: {} }),
244
296
  listTools: vi.fn().mockResolvedValue({
245
297
  tools: [
@@ -275,9 +327,17 @@ describe('mcp-client', () => {
275
327
  sortTools: vi.fn(),
276
328
  getMessageBus: vi.fn().mockReturnValue(undefined),
277
329
  };
330
+ const promptRegistry = {
331
+ registerPrompt: vi.fn(),
332
+ removePromptsByServer: vi.fn(),
333
+ };
334
+ const resourceRegistry = {
335
+ setResourcesForServer: vi.fn(),
336
+ removeResourcesByServer: vi.fn(),
337
+ };
278
338
  const client = new McpClient('test-server', {
279
339
  command: 'test-command',
280
- }, mockedToolRegistry, {}, workspaceContext, false);
340
+ }, mockedToolRegistry, promptRegistry, resourceRegistry, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
281
341
  await client.connect();
282
342
  await client.discover({});
283
343
  expect(mockedToolRegistry.registerTool).toHaveBeenCalledOnce();
@@ -298,6 +358,126 @@ describe('mcp-client', () => {
298
358
  },
299
359
  });
300
360
  });
361
+ it('should discover resources when a server only exposes resources', async () => {
362
+ const mockedClient = {
363
+ connect: vi.fn(),
364
+ discover: vi.fn(),
365
+ disconnect: vi.fn(),
366
+ getStatus: vi.fn(),
367
+ registerCapabilities: vi.fn(),
368
+ setRequestHandler: vi.fn(),
369
+ setNotificationHandler: vi.fn(),
370
+ getServerCapabilities: vi.fn().mockReturnValue({ resources: {} }),
371
+ request: vi.fn().mockImplementation(({ method }) => {
372
+ if (method === 'resources/list') {
373
+ return Promise.resolve({
374
+ resources: [
375
+ {
376
+ uri: 'file:///tmp/resource.txt',
377
+ name: 'resource',
378
+ description: 'Test Resource',
379
+ mimeType: 'text/plain',
380
+ },
381
+ ],
382
+ });
383
+ }
384
+ return Promise.resolve({ prompts: [] });
385
+ }),
386
+ };
387
+ vi.mocked(ClientLib.Client).mockReturnValue(mockedClient);
388
+ vi.spyOn(SdkClientStdioLib, 'StdioClientTransport').mockReturnValue({});
389
+ const mockedToolRegistry = {
390
+ registerTool: vi.fn(),
391
+ sortTools: vi.fn(),
392
+ getMessageBus: vi.fn().mockReturnValue(undefined),
393
+ };
394
+ const promptRegistry = {
395
+ registerPrompt: vi.fn(),
396
+ removePromptsByServer: vi.fn(),
397
+ };
398
+ const resourceRegistry = {
399
+ setResourcesForServer: vi.fn(),
400
+ removeResourcesByServer: vi.fn(),
401
+ };
402
+ const client = new McpClient('test-server', {
403
+ command: 'test-command',
404
+ }, mockedToolRegistry, promptRegistry, resourceRegistry, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
405
+ await client.connect();
406
+ await client.discover({});
407
+ expect(resourceRegistry.setResourcesForServer).toHaveBeenCalledWith('test-server', [
408
+ expect.objectContaining({
409
+ uri: 'file:///tmp/resource.txt',
410
+ name: 'resource',
411
+ }),
412
+ ]);
413
+ });
414
+ it('refreshes registry when resource list change notification is received', async () => {
415
+ let listCallCount = 0;
416
+ let resourceListHandler;
417
+ const mockedClient = {
418
+ connect: vi.fn(),
419
+ discover: vi.fn(),
420
+ disconnect: vi.fn(),
421
+ getStatus: vi.fn(),
422
+ registerCapabilities: vi.fn(),
423
+ setRequestHandler: vi.fn(),
424
+ setNotificationHandler: vi.fn((_, handler) => {
425
+ resourceListHandler = handler;
426
+ }),
427
+ getServerCapabilities: vi
428
+ .fn()
429
+ .mockReturnValue({ resources: { listChanged: true } }),
430
+ request: vi.fn().mockImplementation(({ method }) => {
431
+ if (method === 'resources/list') {
432
+ listCallCount += 1;
433
+ if (listCallCount === 1) {
434
+ return Promise.resolve({
435
+ resources: [
436
+ {
437
+ uri: 'file:///tmp/one.txt',
438
+ },
439
+ ],
440
+ });
441
+ }
442
+ return Promise.resolve({
443
+ resources: [
444
+ {
445
+ uri: 'file:///tmp/two.txt',
446
+ },
447
+ ],
448
+ });
449
+ }
450
+ return Promise.resolve({ prompts: [] });
451
+ }),
452
+ };
453
+ vi.mocked(ClientLib.Client).mockReturnValue(mockedClient);
454
+ vi.spyOn(SdkClientStdioLib, 'StdioClientTransport').mockReturnValue({});
455
+ const mockedToolRegistry = {
456
+ registerTool: vi.fn(),
457
+ sortTools: vi.fn(),
458
+ getMessageBus: vi.fn().mockReturnValue(undefined),
459
+ };
460
+ const promptRegistry = {
461
+ registerPrompt: vi.fn(),
462
+ removePromptsByServer: vi.fn(),
463
+ };
464
+ const resourceRegistry = {
465
+ setResourcesForServer: vi.fn(),
466
+ removeResourcesByServer: vi.fn(),
467
+ };
468
+ const client = new McpClient('test-server', {
469
+ command: 'test-command',
470
+ }, mockedToolRegistry, promptRegistry, resourceRegistry, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
471
+ await client.connect();
472
+ await client.discover({});
473
+ expect(mockedClient.setNotificationHandler).toHaveBeenCalledOnce();
474
+ expect(resourceListHandler).toBeDefined();
475
+ await resourceListHandler?.({
476
+ method: 'notifications/resources/list_changed',
477
+ });
478
+ expect(resourceRegistry.setResourcesForServer).toHaveBeenLastCalledWith('test-server', [expect.objectContaining({ uri: 'file:///tmp/two.txt' })]);
479
+ expect(coreEvents.emitFeedback).toHaveBeenCalledWith('info', 'Resources updated for server: test-server');
480
+ });
301
481
  it('should remove tools and prompts on disconnect', async () => {
302
482
  const mockedClient = {
303
483
  connect: vi.fn(),
@@ -305,6 +485,7 @@ describe('mcp-client', () => {
305
485
  getStatus: vi.fn(),
306
486
  registerCapabilities: vi.fn(),
307
487
  setRequestHandler: vi.fn(),
488
+ setNotificationHandler: vi.fn(),
308
489
  getServerCapabilities: vi
309
490
  .fn()
310
491
  .mockReturnValue({ tools: {}, prompts: {} }),
@@ -336,9 +517,13 @@ describe('mcp-client', () => {
336
517
  unregisterPrompt: vi.fn(),
337
518
  removePromptsByServer: vi.fn(),
338
519
  };
520
+ const resourceRegistry = {
521
+ setResourcesForServer: vi.fn(),
522
+ removeResourcesByServer: vi.fn(),
523
+ };
339
524
  const client = new McpClient('test-server', {
340
525
  command: 'test-command',
341
- }, mockedToolRegistry, mockedPromptRegistry, workspaceContext, false);
526
+ }, mockedToolRegistry, mockedPromptRegistry, resourceRegistry, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
342
527
  await client.connect();
343
528
  await client.discover({});
344
529
  expect(mockedToolRegistry.registerTool).toHaveBeenCalledOnce();
@@ -347,6 +532,251 @@ describe('mcp-client', () => {
347
532
  expect(mockedClient.close).toHaveBeenCalledOnce();
348
533
  expect(mockedToolRegistry.removeMcpToolsByServer).toHaveBeenCalledOnce();
349
534
  expect(mockedPromptRegistry.removePromptsByServer).toHaveBeenCalledOnce();
535
+ expect(resourceRegistry.removeResourcesByServer).toHaveBeenCalledOnce();
536
+ });
537
+ });
538
+ describe('Dynamic Tool Updates', () => {
539
+ it('should set up notification handler if server supports tool list changes', async () => {
540
+ const mockedClient = {
541
+ connect: vi.fn(),
542
+ getStatus: vi.fn(),
543
+ registerCapabilities: vi.fn(),
544
+ setRequestHandler: vi.fn(),
545
+ // Capability enables the listener
546
+ getServerCapabilities: vi
547
+ .fn()
548
+ .mockReturnValue({ tools: { listChanged: true } }),
549
+ setNotificationHandler: vi.fn(),
550
+ listTools: vi.fn().mockResolvedValue({ tools: [] }),
551
+ listPrompts: vi.fn().mockResolvedValue({ prompts: [] }),
552
+ request: vi.fn().mockResolvedValue({}),
553
+ };
554
+ vi.mocked(ClientLib.Client).mockReturnValue(mockedClient);
555
+ vi.spyOn(SdkClientStdioLib, 'StdioClientTransport').mockReturnValue({});
556
+ const client = new McpClient('test-server', { command: 'test-command' }, {}, {}, {}, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
557
+ await client.connect();
558
+ expect(mockedClient.setNotificationHandler).toHaveBeenCalledWith(ToolListChangedNotificationSchema, expect.any(Function));
559
+ });
560
+ it('should NOT set up notification handler if server lacks capability', async () => {
561
+ const mockedClient = {
562
+ connect: vi.fn(),
563
+ getServerCapabilities: vi.fn().mockReturnValue({ tools: {} }), // No listChanged
564
+ setNotificationHandler: vi.fn(),
565
+ request: vi.fn().mockResolvedValue({}),
566
+ registerCapabilities: vi.fn().mockResolvedValue({}),
567
+ setRequestHandler: vi.fn().mockResolvedValue({}),
568
+ };
569
+ vi.mocked(ClientLib.Client).mockReturnValue(mockedClient);
570
+ vi.spyOn(SdkClientStdioLib, 'StdioClientTransport').mockReturnValue({});
571
+ const client = new McpClient('test-server', { command: 'test-command' }, {}, {}, {}, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
572
+ await client.connect();
573
+ expect(mockedClient.setNotificationHandler).not.toHaveBeenCalled();
574
+ });
575
+ it('should refresh tools and notify manager when notification is received', async () => {
576
+ // Setup mocks
577
+ const mockedClient = {
578
+ connect: vi.fn(),
579
+ getServerCapabilities: vi
580
+ .fn()
581
+ .mockReturnValue({ tools: { listChanged: true } }),
582
+ setNotificationHandler: vi.fn(),
583
+ listTools: vi.fn().mockResolvedValue({
584
+ tools: [
585
+ {
586
+ name: 'newTool',
587
+ inputSchema: { type: 'object', properties: {} },
588
+ },
589
+ ],
590
+ }),
591
+ listPrompts: vi.fn().mockResolvedValue({ prompts: [] }),
592
+ request: vi.fn().mockResolvedValue({}),
593
+ registerCapabilities: vi.fn().mockResolvedValue({}),
594
+ setRequestHandler: vi.fn().mockResolvedValue({}),
595
+ };
596
+ vi.mocked(ClientLib.Client).mockReturnValue(mockedClient);
597
+ vi.spyOn(SdkClientStdioLib, 'StdioClientTransport').mockReturnValue({});
598
+ const mockedToolRegistry = {
599
+ removeMcpToolsByServer: vi.fn(),
600
+ registerTool: vi.fn(),
601
+ sortTools: vi.fn(),
602
+ getMessageBus: vi.fn().mockReturnValue(undefined),
603
+ };
604
+ const onToolsUpdatedSpy = vi.fn().mockResolvedValue(undefined);
605
+ // Initialize client with onToolsUpdated callback
606
+ const client = new McpClient('test-server', { command: 'test-command' }, mockedToolRegistry, {}, {}, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false, onToolsUpdatedSpy);
607
+ // 1. Connect (sets up listener)
608
+ await client.connect();
609
+ // 2. Extract the callback passed to setNotificationHandler
610
+ const notificationCallback = mockedClient.setNotificationHandler.mock.calls[0][1];
611
+ // 3. Trigger the notification manually
612
+ await notificationCallback();
613
+ // 4. Assertions
614
+ // It should clear old tools
615
+ expect(mockedToolRegistry.removeMcpToolsByServer).toHaveBeenCalledWith('test-server');
616
+ // It should fetch new tools (listTools called inside discoverTools)
617
+ expect(mockedClient.listTools).toHaveBeenCalled();
618
+ // It should register the new tool
619
+ expect(mockedToolRegistry.registerTool).toHaveBeenCalled();
620
+ // It should notify the manager
621
+ expect(onToolsUpdatedSpy).toHaveBeenCalled();
622
+ // It should emit feedback event
623
+ expect(coreEvents.emitFeedback).toHaveBeenCalledWith('info', 'Tools updated for server: test-server');
624
+ });
625
+ it('should handle errors during tool refresh gracefully', async () => {
626
+ const mockedClient = {
627
+ connect: vi.fn(),
628
+ getServerCapabilities: vi
629
+ .fn()
630
+ .mockReturnValue({ tools: { listChanged: true } }),
631
+ setNotificationHandler: vi.fn(),
632
+ // Simulate error during discovery
633
+ listTools: vi.fn().mockRejectedValue(new Error('Network blip')),
634
+ request: vi.fn().mockResolvedValue({}),
635
+ registerCapabilities: vi.fn().mockResolvedValue({}),
636
+ setRequestHandler: vi.fn().mockResolvedValue({}),
637
+ };
638
+ vi.mocked(ClientLib.Client).mockReturnValue(mockedClient);
639
+ vi.spyOn(SdkClientStdioLib, 'StdioClientTransport').mockReturnValue({});
640
+ const mockedToolRegistry = {
641
+ removeMcpToolsByServer: vi.fn(),
642
+ getMessageBus: vi.fn().mockReturnValue(undefined),
643
+ };
644
+ const client = new McpClient('test-server', { command: 'test-command' }, mockedToolRegistry, {}, {}, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
645
+ await client.connect();
646
+ const notificationCallback = mockedClient.setNotificationHandler.mock.calls[0][1];
647
+ // Trigger notification - should fail internally but catch the error
648
+ await notificationCallback();
649
+ // Should try to remove tools
650
+ expect(mockedToolRegistry.removeMcpToolsByServer).toHaveBeenCalled();
651
+ // Should NOT emit success feedback
652
+ expect(coreEvents.emitFeedback).not.toHaveBeenCalledWith('info', expect.stringContaining('Tools updated'));
653
+ });
654
+ it('should handle concurrent updates from multiple servers', async () => {
655
+ const createMockSdkClient = (toolName) => ({
656
+ connect: vi.fn(),
657
+ getServerCapabilities: vi
658
+ .fn()
659
+ .mockReturnValue({ tools: { listChanged: true } }),
660
+ setNotificationHandler: vi.fn(),
661
+ listTools: vi.fn().mockResolvedValue({
662
+ tools: [
663
+ {
664
+ name: toolName,
665
+ inputSchema: { type: 'object', properties: {} },
666
+ },
667
+ ],
668
+ }),
669
+ listPrompts: vi.fn().mockResolvedValue({ prompts: [] }),
670
+ request: vi.fn().mockResolvedValue({}),
671
+ registerCapabilities: vi.fn().mockResolvedValue({}),
672
+ setRequestHandler: vi.fn().mockResolvedValue({}),
673
+ });
674
+ const mockClientA = createMockSdkClient('tool-from-A');
675
+ const mockClientB = createMockSdkClient('tool-from-B');
676
+ vi.mocked(ClientLib.Client)
677
+ .mockReturnValueOnce(mockClientA)
678
+ .mockReturnValueOnce(mockClientB);
679
+ vi.spyOn(SdkClientStdioLib, 'StdioClientTransport').mockReturnValue({});
680
+ const mockedToolRegistry = {
681
+ removeMcpToolsByServer: vi.fn(),
682
+ registerTool: vi.fn(),
683
+ sortTools: vi.fn(),
684
+ getMessageBus: vi.fn().mockReturnValue(undefined),
685
+ };
686
+ const onToolsUpdatedSpy = vi.fn().mockResolvedValue(undefined);
687
+ const clientA = new McpClient('server-A', { command: 'cmd-a' }, mockedToolRegistry, {}, {}, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false, onToolsUpdatedSpy);
688
+ const clientB = new McpClient('server-B', { command: 'cmd-b' }, mockedToolRegistry, {}, {}, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false, onToolsUpdatedSpy);
689
+ await clientA.connect();
690
+ await clientB.connect();
691
+ const handlerA = mockClientA.setNotificationHandler.mock.calls[0][1];
692
+ const handlerB = mockClientB.setNotificationHandler.mock.calls[0][1];
693
+ // Trigger burst updates simultaneously
694
+ await Promise.all([handlerA(), handlerB()]);
695
+ expect(mockedToolRegistry.removeMcpToolsByServer).toHaveBeenCalledWith('server-A');
696
+ expect(mockedToolRegistry.removeMcpToolsByServer).toHaveBeenCalledWith('server-B');
697
+ // Verify fetching happened on both clients
698
+ expect(mockClientA.listTools).toHaveBeenCalled();
699
+ expect(mockClientB.listTools).toHaveBeenCalled();
700
+ // Verify tools from both servers were registered (2 total calls)
701
+ expect(mockedToolRegistry.registerTool).toHaveBeenCalledTimes(2);
702
+ // Verify the update callback was triggered for both
703
+ expect(onToolsUpdatedSpy).toHaveBeenCalledTimes(2);
704
+ });
705
+ it('should abort discovery and log error if timeout is exceeded during refresh', async () => {
706
+ vi.useFakeTimers();
707
+ const mockedClient = {
708
+ connect: vi.fn(),
709
+ getServerCapabilities: vi
710
+ .fn()
711
+ .mockReturnValue({ tools: { listChanged: true } }),
712
+ setNotificationHandler: vi.fn(),
713
+ // Mock listTools to simulate a long running process that respects the abort signal
714
+ listTools: vi.fn().mockImplementation(async (params, options) => new Promise((resolve, reject) => {
715
+ if (options?.signal?.aborted) {
716
+ return reject(new Error('Operation aborted'));
717
+ }
718
+ options?.signal?.addEventListener('abort', () => {
719
+ reject(new Error('Operation aborted'));
720
+ });
721
+ // Intentionally do not resolve immediately to simulate lag
722
+ })),
723
+ listPrompts: vi.fn().mockResolvedValue({ prompts: [] }),
724
+ request: vi.fn().mockResolvedValue({}),
725
+ registerCapabilities: vi.fn().mockResolvedValue({}),
726
+ setRequestHandler: vi.fn().mockResolvedValue({}),
727
+ };
728
+ vi.mocked(ClientLib.Client).mockReturnValue(mockedClient);
729
+ vi.spyOn(SdkClientStdioLib, 'StdioClientTransport').mockReturnValue({});
730
+ const mockedToolRegistry = {
731
+ removeMcpToolsByServer: vi.fn(),
732
+ registerTool: vi.fn(),
733
+ sortTools: vi.fn(),
734
+ getMessageBus: vi.fn().mockReturnValue(undefined),
735
+ };
736
+ const client = new McpClient('test-server',
737
+ // Set a short timeout
738
+ { command: 'test-command', timeout: 100 }, mockedToolRegistry, {}, {}, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false);
739
+ await client.connect();
740
+ const notificationCallback = mockedClient.setNotificationHandler.mock.calls[0][1];
741
+ const refreshPromise = notificationCallback();
742
+ vi.advanceTimersByTime(150);
743
+ await refreshPromise;
744
+ expect(mockedClient.listTools).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({
745
+ signal: expect.any(AbortSignal),
746
+ }));
747
+ expect(mockedToolRegistry.registerTool).not.toHaveBeenCalled();
748
+ vi.useRealTimers();
749
+ });
750
+ it('should pass abort signal to onToolsUpdated callback', async () => {
751
+ const mockedClient = {
752
+ connect: vi.fn(),
753
+ getServerCapabilities: vi
754
+ .fn()
755
+ .mockReturnValue({ tools: { listChanged: true } }),
756
+ setNotificationHandler: vi.fn(),
757
+ listTools: vi.fn().mockResolvedValue({ tools: [] }),
758
+ listPrompts: vi.fn().mockResolvedValue({ prompts: [] }),
759
+ request: vi.fn().mockResolvedValue({}),
760
+ registerCapabilities: vi.fn().mockResolvedValue({}),
761
+ setRequestHandler: vi.fn().mockResolvedValue({}),
762
+ };
763
+ vi.mocked(ClientLib.Client).mockReturnValue(mockedClient);
764
+ vi.spyOn(SdkClientStdioLib, 'StdioClientTransport').mockReturnValue({});
765
+ const mockedToolRegistry = {
766
+ removeMcpToolsByServer: vi.fn(),
767
+ registerTool: vi.fn(),
768
+ sortTools: vi.fn(),
769
+ getMessageBus: vi.fn().mockReturnValue(undefined),
770
+ };
771
+ const onToolsUpdatedSpy = vi.fn().mockResolvedValue(undefined);
772
+ const client = new McpClient('test-server', { command: 'test-command' }, mockedToolRegistry, {}, {}, workspaceContext, { sanitizationConfig: EMPTY_CONFIG }, false, onToolsUpdatedSpy);
773
+ await client.connect();
774
+ const notificationCallback = mockedClient.setNotificationHandler.mock.calls[0][1];
775
+ await notificationCallback();
776
+ expect(onToolsUpdatedSpy).toHaveBeenCalledWith(expect.any(AbortSignal));
777
+ // Verify the signal passed was not aborted (happy path)
778
+ const signal = onToolsUpdatedSpy.mock.calls[0][0];
779
+ expect(signal.aborted).toBe(false);
350
780
  });
351
781
  });
352
782
  describe('appendMcpServerCommand', () => {
@@ -373,42 +803,122 @@ describe('mcp-client', () => {
373
803
  it('without headers', async () => {
374
804
  const transport = await createTransport('test-server', {
375
805
  httpUrl: 'http://test-server',
376
- }, false);
806
+ }, false, EMPTY_CONFIG);
377
807
  expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
378
- expect(transport).toHaveProperty('_url', new URL('http://test-server/'));
808
+ expect(transport).toMatchObject({
809
+ _url: new URL('http://test-server'),
810
+ _requestInit: { headers: {} },
811
+ });
379
812
  });
380
813
  it('with headers', async () => {
381
- // We need this to be an any type because we dig into its private state.
382
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
383
814
  const transport = await createTransport('test-server', {
384
815
  httpUrl: 'http://test-server',
385
816
  headers: { Authorization: 'derp' },
386
- }, false);
817
+ }, false, EMPTY_CONFIG);
387
818
  expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
388
- expect(transport).toHaveProperty('_url', new URL('http://test-server/'));
389
- const authHeader = transport._requestInit?.headers?.['Authorization'];
390
- expect(authHeader).toBe('derp');
819
+ expect(transport).toMatchObject({
820
+ _url: new URL('http://test-server'),
821
+ _requestInit: {
822
+ headers: { Authorization: 'derp' },
823
+ },
824
+ });
391
825
  });
392
826
  });
393
827
  describe('should connect via url', () => {
394
828
  it('without headers', async () => {
395
829
  const transport = await createTransport('test-server', {
396
830
  url: 'http://test-server',
397
- }, false);
398
- expect(transport).toBeInstanceOf(SSEClientTransport);
399
- expect(transport).toHaveProperty('_url', new URL('http://test-server/'));
831
+ }, false, EMPTY_CONFIG);
832
+ expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
833
+ expect(transport).toMatchObject({
834
+ _url: new URL('http://test-server'),
835
+ _requestInit: { headers: {} },
836
+ });
400
837
  });
401
838
  it('with headers', async () => {
402
- // We need this to be an any type because we dig into its private state.
403
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
404
839
  const transport = await createTransport('test-server', {
405
840
  url: 'http://test-server',
406
841
  headers: { Authorization: 'derp' },
407
- }, false);
842
+ }, false, EMPTY_CONFIG);
843
+ expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
844
+ expect(transport).toMatchObject({
845
+ _url: new URL('http://test-server'),
846
+ _requestInit: {
847
+ headers: { Authorization: 'derp' },
848
+ },
849
+ });
850
+ });
851
+ it('with type="http" creates StreamableHTTPClientTransport', async () => {
852
+ const transport = await createTransport('test-server', {
853
+ url: 'http://test-server',
854
+ type: 'http',
855
+ }, false, EMPTY_CONFIG);
856
+ expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
857
+ expect(transport).toMatchObject({
858
+ _url: new URL('http://test-server'),
859
+ _requestInit: { headers: {} },
860
+ });
861
+ });
862
+ it('with type="sse" creates SSEClientTransport', async () => {
863
+ const transport = await createTransport('test-server', {
864
+ url: 'http://test-server',
865
+ type: 'sse',
866
+ }, false, EMPTY_CONFIG);
408
867
  expect(transport).toBeInstanceOf(SSEClientTransport);
409
- expect(transport).toHaveProperty('_url', new URL('http://test-server/'));
410
- const authHeader = transport._requestInit?.headers?.['Authorization'];
411
- expect(authHeader).toBe('derp');
868
+ expect(transport).toMatchObject({
869
+ _url: new URL('http://test-server'),
870
+ _requestInit: { headers: {} },
871
+ });
872
+ });
873
+ it('without type defaults to StreamableHTTPClientTransport', async () => {
874
+ const transport = await createTransport('test-server', {
875
+ url: 'http://test-server',
876
+ }, false, EMPTY_CONFIG);
877
+ expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
878
+ expect(transport).toMatchObject({
879
+ _url: new URL('http://test-server'),
880
+ _requestInit: { headers: {} },
881
+ });
882
+ });
883
+ it('with type="http" and headers applies headers correctly', async () => {
884
+ const transport = await createTransport('test-server', {
885
+ url: 'http://test-server',
886
+ type: 'http',
887
+ headers: { Authorization: 'Bearer token' },
888
+ }, false, EMPTY_CONFIG);
889
+ expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
890
+ expect(transport).toMatchObject({
891
+ _url: new URL('http://test-server'),
892
+ _requestInit: {
893
+ headers: { Authorization: 'Bearer token' },
894
+ },
895
+ });
896
+ });
897
+ it('with type="sse" and headers applies headers correctly', async () => {
898
+ const transport = await createTransport('test-server', {
899
+ url: 'http://test-server',
900
+ type: 'sse',
901
+ headers: { 'X-API-Key': 'key123' },
902
+ }, false, EMPTY_CONFIG);
903
+ expect(transport).toBeInstanceOf(SSEClientTransport);
904
+ expect(transport).toMatchObject({
905
+ _url: new URL('http://test-server'),
906
+ _requestInit: {
907
+ headers: { 'X-API-Key': 'key123' },
908
+ },
909
+ });
910
+ });
911
+ it('httpUrl takes priority over url when both are present', async () => {
912
+ const transport = await createTransport('test-server', {
913
+ httpUrl: 'http://test-server-http',
914
+ url: 'http://test-server-url',
915
+ }, false, EMPTY_CONFIG);
916
+ // httpUrl should take priority and create HTTP transport
917
+ expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
918
+ expect(transport).toMatchObject({
919
+ _url: new URL('http://test-server-http'),
920
+ _requestInit: { headers: {} },
921
+ });
412
922
  });
413
923
  });
414
924
  it('should connect via command', async () => {
@@ -420,12 +930,12 @@ describe('mcp-client', () => {
420
930
  args: ['--foo', 'bar'],
421
931
  env: { FOO: 'bar' },
422
932
  cwd: 'test/cwd',
423
- }, false);
933
+ }, false, EMPTY_CONFIG);
424
934
  expect(mockedTransport).toHaveBeenCalledWith({
425
935
  command: 'test-command',
426
936
  args: ['--foo', 'bar'],
427
937
  cwd: 'test/cwd',
428
- env: { ...process.env, FOO: 'bar' },
938
+ env: expect.objectContaining({ FOO: 'bar' }),
429
939
  stderr: 'pipe',
430
940
  });
431
941
  });
@@ -448,7 +958,7 @@ describe('mcp-client', () => {
448
958
  headers: {
449
959
  'X-Goog-User-Project': 'myproject',
450
960
  },
451
- }, false);
961
+ }, false, EMPTY_CONFIG);
452
962
  expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
453
963
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
454
964
  const authProvider = transport._authProvider;
@@ -468,7 +978,7 @@ describe('mcp-client', () => {
468
978
  oauth: {
469
979
  scopes: ['scope1'],
470
980
  },
471
- }, false);
981
+ }, false, EMPTY_CONFIG);
472
982
  expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
473
983
  expect(mockGetRequestHeaders).toHaveBeenCalled();
474
984
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -489,7 +999,7 @@ describe('mcp-client', () => {
489
999
  headers: {
490
1000
  'X-Goog-User-Project': 'config-project',
491
1001
  },
492
- }, false);
1002
+ }, false, EMPTY_CONFIG);
493
1003
  expect(transport).toBeInstanceOf(StreamableHTTPClientTransport);
494
1004
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
495
1005
  const headers = transport._requestInit?.headers;
@@ -498,11 +1008,12 @@ describe('mcp-client', () => {
498
1008
  it('should use GoogleCredentialProvider with SSE transport', async () => {
499
1009
  const transport = await createTransport('test-server', {
500
1010
  url: 'http://test.googleapis.com',
1011
+ type: 'sse',
501
1012
  authProviderType: AuthProviderType.GOOGLE_CREDENTIALS,
502
1013
  oauth: {
503
1014
  scopes: ['scope1'],
504
1015
  },
505
- }, false);
1016
+ }, false, EMPTY_CONFIG);
506
1017
  expect(transport).toBeInstanceOf(SSEClientTransport);
507
1018
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
508
1019
  const authProvider = transport._authProvider;
@@ -514,7 +1025,7 @@ describe('mcp-client', () => {
514
1025
  oauth: {
515
1026
  scopes: ['scope1'],
516
1027
  },
517
- }, false)).rejects.toThrow('URL must be provided in the config for Google Credentials provider');
1028
+ }, false, EMPTY_CONFIG)).rejects.toThrow('URL must be provided in the config for Google Credentials provider');
518
1029
  });
519
1030
  });
520
1031
  });
@@ -620,7 +1131,7 @@ describe('connectToMcpServer with OAuth', () => {
620
1131
  const authUrl = 'http://auth.example.com/auth';
621
1132
  const tokenUrl = 'http://auth.example.com/token';
622
1133
  const wwwAuthHeader = `Bearer realm="test", resource_metadata="http://test-server.com/.well-known/oauth-protected-resource"`;
623
- vi.mocked(mockedClient.connect).mockRejectedValueOnce(new Error(`401 Unauthorized\nwww-authenticate: ${wwwAuthHeader}`));
1134
+ vi.mocked(mockedClient.connect).mockRejectedValueOnce(new StreamableHTTPError(401, `Unauthorized\nwww-authenticate: ${wwwAuthHeader}`));
624
1135
  vi.mocked(OAuthUtils.discoverOAuthConfig).mockResolvedValue({
625
1136
  authorizationUrl: authUrl,
626
1137
  tokenUrl,
@@ -633,7 +1144,7 @@ describe('connectToMcpServer with OAuth', () => {
633
1144
  capturedTransport = transport;
634
1145
  return Promise.resolve();
635
1146
  });
636
- const client = await connectToMcpServer('test-server', { httpUrl: serverUrl }, false, workspaceContext);
1147
+ const client = await connectToMcpServer('test-server', { httpUrl: serverUrl, oauth: { enabled: true } }, false, workspaceContext, EMPTY_CONFIG);
637
1148
  expect(client).toBe(mockedClient);
638
1149
  expect(mockedClient.connect).toHaveBeenCalledTimes(2);
639
1150
  expect(mockAuthProvider.authenticate).toHaveBeenCalledOnce();
@@ -644,7 +1155,7 @@ describe('connectToMcpServer with OAuth', () => {
644
1155
  const serverUrl = 'http://test-server.com';
645
1156
  const authUrl = 'http://auth.example.com/auth';
646
1157
  const tokenUrl = 'http://auth.example.com/token';
647
- vi.mocked(mockedClient.connect).mockRejectedValueOnce(new Error('401 Unauthorized'));
1158
+ vi.mocked(mockedClient.connect).mockRejectedValueOnce(new StreamableHTTPError(401, 'Unauthorized'));
648
1159
  vi.mocked(OAuthUtils.discoverOAuthConfig).mockResolvedValue({
649
1160
  authorizationUrl: authUrl,
650
1161
  tokenUrl,
@@ -658,7 +1169,7 @@ describe('connectToMcpServer with OAuth', () => {
658
1169
  capturedTransport = transport;
659
1170
  return Promise.resolve();
660
1171
  });
661
- const client = await connectToMcpServer('test-server', { httpUrl: serverUrl }, false, workspaceContext);
1172
+ const client = await connectToMcpServer('test-server', { httpUrl: serverUrl, oauth: { enabled: true } }, false, workspaceContext, EMPTY_CONFIG);
662
1173
  expect(client).toBe(mockedClient);
663
1174
  expect(mockedClient.connect).toHaveBeenCalledTimes(2);
664
1175
  expect(mockAuthProvider.authenticate).toHaveBeenCalledOnce();
@@ -667,4 +1178,118 @@ describe('connectToMcpServer with OAuth', () => {
667
1178
  expect(authHeader).toBe('Bearer test-access-token-from-discovery');
668
1179
  });
669
1180
  });
1181
+ describe('connectToMcpServer - HTTP→SSE fallback', () => {
1182
+ let mockedClient;
1183
+ let workspaceContext;
1184
+ let testWorkspace;
1185
+ beforeEach(() => {
1186
+ mockedClient = {
1187
+ connect: vi.fn(),
1188
+ close: vi.fn(),
1189
+ registerCapabilities: vi.fn(),
1190
+ setRequestHandler: vi.fn(),
1191
+ onclose: vi.fn(),
1192
+ notification: vi.fn(),
1193
+ };
1194
+ vi.mocked(ClientLib.Client).mockImplementation(() => mockedClient);
1195
+ testWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), 'gemini-agent-test-'));
1196
+ workspaceContext = new WorkspaceContext(testWorkspace);
1197
+ vi.spyOn(console, 'log').mockImplementation(() => { });
1198
+ vi.spyOn(console, 'warn').mockImplementation(() => { });
1199
+ vi.spyOn(console, 'error').mockImplementation(() => { });
1200
+ });
1201
+ afterEach(() => {
1202
+ vi.clearAllMocks();
1203
+ });
1204
+ it('should NOT trigger fallback when type="http" is explicit', async () => {
1205
+ vi.mocked(mockedClient.connect).mockRejectedValueOnce(new Error('Connection failed'));
1206
+ await expect(connectToMcpServer('test-server', { url: 'http://test-server', type: 'http' }, false, workspaceContext, EMPTY_CONFIG)).rejects.toThrow('Connection failed');
1207
+ // Should only try once (no fallback)
1208
+ expect(mockedClient.connect).toHaveBeenCalledTimes(1);
1209
+ });
1210
+ it('should NOT trigger fallback when type="sse" is explicit', async () => {
1211
+ vi.mocked(mockedClient.connect).mockRejectedValueOnce(new Error('Connection failed'));
1212
+ await expect(connectToMcpServer('test-server', { url: 'http://test-server', type: 'sse' }, false, workspaceContext, EMPTY_CONFIG)).rejects.toThrow('Connection failed');
1213
+ // Should only try once (no fallback)
1214
+ expect(mockedClient.connect).toHaveBeenCalledTimes(1);
1215
+ });
1216
+ it('should trigger fallback when url provided without type and HTTP fails', async () => {
1217
+ vi.mocked(mockedClient.connect)
1218
+ .mockRejectedValueOnce(new StreamableHTTPError(500, 'Server error'))
1219
+ .mockResolvedValueOnce(undefined);
1220
+ const client = await connectToMcpServer('test-server', { url: 'http://test-server' }, false, workspaceContext, EMPTY_CONFIG);
1221
+ expect(client).toBe(mockedClient);
1222
+ // First HTTP attempt fails, second SSE attempt succeeds
1223
+ expect(mockedClient.connect).toHaveBeenCalledTimes(2);
1224
+ });
1225
+ it('should throw original HTTP error when both HTTP and SSE fail (non-401)', async () => {
1226
+ const httpError = new StreamableHTTPError(500, 'Server error');
1227
+ const sseError = new Error('SSE connection failed');
1228
+ vi.mocked(mockedClient.connect)
1229
+ .mockRejectedValueOnce(httpError)
1230
+ .mockRejectedValueOnce(sseError);
1231
+ await expect(connectToMcpServer('test-server', { url: 'http://test-server' }, false, workspaceContext, EMPTY_CONFIG)).rejects.toThrow('Server error');
1232
+ expect(mockedClient.connect).toHaveBeenCalledTimes(2);
1233
+ });
1234
+ it('should handle HTTP 404 followed by SSE success', async () => {
1235
+ vi.mocked(mockedClient.connect)
1236
+ .mockRejectedValueOnce(new StreamableHTTPError(404, 'Not Found'))
1237
+ .mockResolvedValueOnce(undefined);
1238
+ const client = await connectToMcpServer('test-server', { url: 'http://test-server' }, false, workspaceContext, EMPTY_CONFIG);
1239
+ expect(client).toBe(mockedClient);
1240
+ expect(mockedClient.connect).toHaveBeenCalledTimes(2);
1241
+ });
1242
+ });
1243
+ describe('connectToMcpServer - OAuth with transport fallback', () => {
1244
+ let mockedClient;
1245
+ let workspaceContext;
1246
+ let testWorkspace;
1247
+ let mockAuthProvider;
1248
+ let mockTokenStorage;
1249
+ beforeEach(() => {
1250
+ mockedClient = {
1251
+ connect: vi.fn(),
1252
+ close: vi.fn(),
1253
+ registerCapabilities: vi.fn(),
1254
+ setRequestHandler: vi.fn(),
1255
+ onclose: vi.fn(),
1256
+ notification: vi.fn(),
1257
+ };
1258
+ vi.mocked(ClientLib.Client).mockImplementation(() => mockedClient);
1259
+ testWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), 'gemini-agent-test-'));
1260
+ workspaceContext = new WorkspaceContext(testWorkspace);
1261
+ vi.spyOn(console, 'log').mockImplementation(() => { });
1262
+ vi.spyOn(console, 'warn').mockImplementation(() => { });
1263
+ vi.spyOn(console, 'error').mockImplementation(() => { });
1264
+ mockTokenStorage = {
1265
+ getCredentials: vi.fn().mockResolvedValue({ clientId: 'test-client' }),
1266
+ };
1267
+ vi.mocked(MCPOAuthTokenStorage).mockReturnValue(mockTokenStorage);
1268
+ mockAuthProvider = {
1269
+ authenticate: vi.fn().mockResolvedValue(undefined),
1270
+ getValidToken: vi.fn().mockResolvedValue('test-access-token'),
1271
+ tokenStorage: mockTokenStorage,
1272
+ };
1273
+ vi.mocked(MCPOAuthProvider).mockReturnValue(mockAuthProvider);
1274
+ vi.mocked(OAuthUtils.discoverOAuthConfig).mockResolvedValue({
1275
+ authorizationUrl: 'http://auth.example.com/auth',
1276
+ tokenUrl: 'http://auth.example.com/token',
1277
+ scopes: ['test-scope'],
1278
+ });
1279
+ });
1280
+ afterEach(() => {
1281
+ vi.clearAllMocks();
1282
+ });
1283
+ it('should handle HTTP 404 → SSE 401 → OAuth → SSE+OAuth succeeds', async () => {
1284
+ // Tests that OAuth flow works when SSE (not HTTP) requires auth
1285
+ vi.mocked(mockedClient.connect)
1286
+ .mockRejectedValueOnce(new StreamableHTTPError(404, 'Not Found'))
1287
+ .mockRejectedValueOnce(new StreamableHTTPError(401, 'Unauthorized'))
1288
+ .mockResolvedValueOnce(undefined);
1289
+ const client = await connectToMcpServer('test-server', { url: 'http://test-server', oauth: { enabled: true } }, false, workspaceContext, EMPTY_CONFIG);
1290
+ expect(client).toBe(mockedClient);
1291
+ expect(mockedClient.connect).toHaveBeenCalledTimes(3);
1292
+ expect(mockAuthProvider.authenticate).toHaveBeenCalledOnce();
1293
+ });
1294
+ });
670
1295
  //# sourceMappingURL=mcp-client.test.js.map