@office-ai/aioncli-core 0.18.7 → 0.24.0-preview.1

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