@code-yeongyu/senpi 2026.8.11-2 → 2026.8.11-4

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 (262) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/dist/cli-main.d.ts +1 -1
  3. package/dist/cli-main.d.ts.map +1 -1
  4. package/dist/cli-main.js +1 -0
  5. package/dist/cli-main.js.map +1 -1
  6. package/dist/cli.d.ts +1 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +1 -0
  9. package/dist/cli.js.map +1 -1
  10. package/dist/core/agent-session.d.ts +8 -2
  11. package/dist/core/agent-session.d.ts.map +1 -1
  12. package/dist/core/agent-session.js +63 -7
  13. package/dist/core/agent-session.js.map +1 -1
  14. package/dist/core/extensions/builtin/claude-sdk-oauth/availability.d.ts +2 -0
  15. package/dist/core/extensions/builtin/claude-sdk-oauth/availability.d.ts.map +1 -0
  16. package/dist/core/extensions/builtin/claude-sdk-oauth/availability.js +24 -0
  17. package/dist/core/extensions/builtin/claude-sdk-oauth/availability.js.map +1 -0
  18. package/dist/core/extensions/builtin/claude-sdk-oauth/index.d.ts +4 -0
  19. package/dist/core/extensions/builtin/claude-sdk-oauth/index.d.ts.map +1 -1
  20. package/dist/core/extensions/builtin/claude-sdk-oauth/index.js +5 -2
  21. package/dist/core/extensions/builtin/claude-sdk-oauth/index.js.map +1 -1
  22. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.d.ts +6 -1
  23. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.d.ts.map +1 -1
  24. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.js +16 -0
  25. package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.js.map +1 -1
  26. package/dist/core/extensions/builtin/goal/transitions.js +2 -1
  27. package/dist/core/extensions/builtin/goal/transitions.js.map +1 -1
  28. package/dist/core/extensions/builtin/imagegen/auth.d.ts +45 -0
  29. package/dist/core/extensions/builtin/imagegen/auth.d.ts.map +1 -0
  30. package/dist/core/extensions/builtin/imagegen/auth.js +137 -0
  31. package/dist/core/extensions/builtin/imagegen/auth.js.map +1 -0
  32. package/dist/core/extensions/builtin/imagegen/index.d.ts +5 -0
  33. package/dist/core/extensions/builtin/imagegen/index.d.ts.map +1 -0
  34. package/dist/core/extensions/builtin/imagegen/index.js +46 -0
  35. package/dist/core/extensions/builtin/imagegen/index.js.map +1 -0
  36. package/dist/core/extensions/builtin/imagegen/paths.d.ts +26 -0
  37. package/dist/core/extensions/builtin/imagegen/paths.d.ts.map +1 -0
  38. package/dist/core/extensions/builtin/imagegen/paths.js +52 -0
  39. package/dist/core/extensions/builtin/imagegen/paths.js.map +1 -0
  40. package/dist/core/extensions/builtin/imagegen/skill/SKILL.md +67 -0
  41. package/dist/core/extensions/builtin/imagegen/state.d.ts +26 -0
  42. package/dist/core/extensions/builtin/imagegen/state.d.ts.map +1 -0
  43. package/dist/core/extensions/builtin/imagegen/state.js +35 -0
  44. package/dist/core/extensions/builtin/imagegen/state.js.map +1 -0
  45. package/dist/core/extensions/builtin/imagegen/tool.d.ts +31 -0
  46. package/dist/core/extensions/builtin/imagegen/tool.d.ts.map +1 -0
  47. package/dist/core/extensions/builtin/imagegen/tool.js +174 -0
  48. package/dist/core/extensions/builtin/imagegen/tool.js.map +1 -0
  49. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  50. package/dist/core/extensions/builtin/index.js +9 -1
  51. package/dist/core/extensions/builtin/index.js.map +1 -1
  52. package/dist/core/extensions/builtin/mcp/control-inventory.d.ts +14 -0
  53. package/dist/core/extensions/builtin/mcp/control-inventory.d.ts.map +1 -0
  54. package/dist/core/extensions/builtin/mcp/control-inventory.js +22 -0
  55. package/dist/core/extensions/builtin/mcp/control-inventory.js.map +1 -0
  56. package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts +2 -44
  57. package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts.map +1 -1
  58. package/dist/core/extensions/builtin/mcp/expose/native-search.js +3 -97
  59. package/dist/core/extensions/builtin/mcp/expose/native-search.js.map +1 -1
  60. package/dist/core/extensions/builtin/mcp/expose/proxy.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/mcp/expose/proxy.js +15 -4
  62. package/dist/core/extensions/builtin/mcp/expose/proxy.js.map +1 -1
  63. package/dist/core/extensions/builtin/mcp/expose/session.d.ts +2 -1
  64. package/dist/core/extensions/builtin/mcp/expose/session.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/mcp/expose/session.js +2 -2
  66. package/dist/core/extensions/builtin/mcp/expose/session.js.map +1 -1
  67. package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts +13 -11
  68. package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts.map +1 -1
  69. package/dist/core/extensions/builtin/mcp/expose/tier-b.js +58 -59
  70. package/dist/core/extensions/builtin/mcp/expose/tier-b.js.map +1 -1
  71. package/dist/core/extensions/builtin/mcp/index.d.ts.map +1 -1
  72. package/dist/core/extensions/builtin/mcp/index.js +28 -36
  73. package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
  74. package/dist/core/extensions/builtin/mcp/service-register.d.ts +2 -1
  75. package/dist/core/extensions/builtin/mcp/service-register.d.ts.map +1 -1
  76. package/dist/core/extensions/builtin/mcp/service-register.js +2 -2
  77. package/dist/core/extensions/builtin/mcp/service-register.js.map +1 -1
  78. package/dist/core/extensions/builtin/mcp/service-types.d.ts +4 -0
  79. package/dist/core/extensions/builtin/mcp/service-types.d.ts.map +1 -1
  80. package/dist/core/extensions/builtin/mcp/service-types.js.map +1 -1
  81. package/dist/core/extensions/builtin/mcp/service.d.ts +6 -11
  82. package/dist/core/extensions/builtin/mcp/service.d.ts.map +1 -1
  83. package/dist/core/extensions/builtin/mcp/service.js +79 -41
  84. package/dist/core/extensions/builtin/mcp/service.js.map +1 -1
  85. package/dist/core/extensions/builtin/mcp/wrap.d.ts +2 -0
  86. package/dist/core/extensions/builtin/mcp/wrap.d.ts.map +1 -1
  87. package/dist/core/extensions/builtin/mcp/wrap.js +3 -0
  88. package/dist/core/extensions/builtin/mcp/wrap.js.map +1 -1
  89. package/dist/core/extensions/builtin/openai-image-gen/externalize.d.ts +27 -0
  90. package/dist/core/extensions/builtin/openai-image-gen/externalize.d.ts.map +1 -0
  91. package/dist/core/extensions/builtin/openai-image-gen/externalize.js +133 -0
  92. package/dist/core/extensions/builtin/openai-image-gen/externalize.js.map +1 -0
  93. package/dist/core/extensions/builtin/openai-image-gen/gate.d.ts +21 -0
  94. package/dist/core/extensions/builtin/openai-image-gen/gate.d.ts.map +1 -0
  95. package/dist/core/extensions/builtin/openai-image-gen/gate.js +63 -0
  96. package/dist/core/extensions/builtin/openai-image-gen/gate.js.map +1 -0
  97. package/dist/core/extensions/builtin/openai-image-gen/index.d.ts +14 -0
  98. package/dist/core/extensions/builtin/openai-image-gen/index.d.ts.map +1 -0
  99. package/dist/core/extensions/builtin/openai-image-gen/index.js +77 -0
  100. package/dist/core/extensions/builtin/openai-image-gen/index.js.map +1 -0
  101. package/dist/core/extensions/builtin/openai-image-gen/inject.d.ts +15 -0
  102. package/dist/core/extensions/builtin/openai-image-gen/inject.d.ts.map +1 -0
  103. package/dist/core/extensions/builtin/openai-image-gen/inject.js +42 -0
  104. package/dist/core/extensions/builtin/openai-image-gen/inject.js.map +1 -0
  105. package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts.map +1 -1
  106. package/dist/core/extensions/builtin/terminal/monitor-notify.js +8 -1
  107. package/dist/core/extensions/builtin/terminal/monitor-notify.js.map +1 -1
  108. package/dist/core/extensions/builtin/terminal/notify.d.ts +3 -1
  109. package/dist/core/extensions/builtin/terminal/notify.d.ts.map +1 -1
  110. package/dist/core/extensions/builtin/terminal/notify.js +4 -1
  111. package/dist/core/extensions/builtin/terminal/notify.js.map +1 -1
  112. package/dist/core/extensions/builtin/tool-search/engine/bm25.d.ts +22 -0
  113. package/dist/core/extensions/builtin/tool-search/engine/bm25.d.ts.map +1 -0
  114. package/dist/core/extensions/builtin/{mcp/expose → tool-search/engine}/bm25.js +16 -31
  115. package/dist/core/extensions/builtin/tool-search/engine/bm25.js.map +1 -0
  116. package/dist/core/extensions/builtin/tool-search/engine/document.d.ts +14 -0
  117. package/dist/core/extensions/builtin/tool-search/engine/document.d.ts.map +1 -0
  118. package/dist/core/extensions/builtin/tool-search/engine/document.js +2 -0
  119. package/dist/core/extensions/builtin/tool-search/engine/document.js.map +1 -0
  120. package/dist/core/extensions/builtin/tool-search/engine/marker.d.ts +55 -0
  121. package/dist/core/extensions/builtin/tool-search/engine/marker.d.ts.map +1 -0
  122. package/dist/core/extensions/builtin/tool-search/engine/marker.js +189 -0
  123. package/dist/core/extensions/builtin/tool-search/engine/marker.js.map +1 -0
  124. package/dist/core/extensions/builtin/tool-search/index.d.ts +7 -0
  125. package/dist/core/extensions/builtin/tool-search/index.d.ts.map +1 -0
  126. package/dist/core/extensions/builtin/tool-search/index.js +71 -0
  127. package/dist/core/extensions/builtin/tool-search/index.js.map +1 -0
  128. package/dist/core/extensions/builtin/tool-search/native-search.d.ts +52 -0
  129. package/dist/core/extensions/builtin/tool-search/native-search.d.ts.map +1 -0
  130. package/dist/core/extensions/builtin/tool-search/native-search.js +116 -0
  131. package/dist/core/extensions/builtin/tool-search/native-search.js.map +1 -0
  132. package/dist/core/extensions/builtin/tool-search/service.d.ts +38 -0
  133. package/dist/core/extensions/builtin/tool-search/service.d.ts.map +1 -0
  134. package/dist/core/extensions/builtin/tool-search/service.js +200 -0
  135. package/dist/core/extensions/builtin/tool-search/service.js.map +1 -0
  136. package/dist/core/extensions/builtin/tool-search/tool.d.ts +21 -0
  137. package/dist/core/extensions/builtin/tool-search/tool.d.ts.map +1 -0
  138. package/dist/core/extensions/builtin/tool-search/tool.js +95 -0
  139. package/dist/core/extensions/builtin/tool-search/tool.js.map +1 -0
  140. package/dist/core/extensions/loader.d.ts.map +1 -1
  141. package/dist/core/extensions/loader.js +3 -0
  142. package/dist/core/extensions/loader.js.map +1 -1
  143. package/dist/core/extensions/types.d.ts +44 -4
  144. package/dist/core/extensions/types.d.ts.map +1 -1
  145. package/dist/core/extensions/types.js +11 -0
  146. package/dist/core/extensions/types.js.map +1 -1
  147. package/dist/core/provider-composer.d.ts +10 -1
  148. package/dist/core/provider-composer.d.ts.map +1 -1
  149. package/dist/core/provider-composer.js +9 -0
  150. package/dist/core/provider-composer.js.map +1 -1
  151. package/dist/core/resource-loader.d.ts.map +1 -1
  152. package/dist/core/resource-loader.js +17 -5
  153. package/dist/core/resource-loader.js.map +1 -1
  154. package/dist/modes/provider-native-rendering.d.ts.map +1 -1
  155. package/dist/modes/provider-native-rendering.js +33 -0
  156. package/dist/modes/provider-native-rendering.js.map +1 -1
  157. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  158. package/dist/modes/rpc/connection-handler.js +130 -4
  159. package/dist/modes/rpc/connection-handler.js.map +1 -1
  160. package/dist/modes/rpc/rpc-types.d.ts +31 -0
  161. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  162. package/dist/modes/rpc/rpc-types.js.map +1 -1
  163. package/dist/senpi +1 -0
  164. package/dist/valid-cwd.d.ts +2 -0
  165. package/dist/valid-cwd.d.ts.map +1 -0
  166. package/dist/valid-cwd.js +14 -0
  167. package/dist/valid-cwd.js.map +1 -0
  168. package/docs/environment-variables.md +7 -0
  169. package/docs/extensions.md +50 -13
  170. package/docs/mcp.md +2 -0
  171. package/docs/rpc.md +54 -0
  172. package/docs/skills.md +8 -0
  173. package/examples/extensions/searchable-tools.ts +49 -0
  174. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +29 -0
  175. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  176. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/kernel.ts +14 -1
  177. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/kernel.ts +14 -1
  178. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/runtime-asset.ts +31 -0
  179. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  180. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +5 -1
  181. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  182. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +4 -1
  183. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  184. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +2 -0
  185. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  186. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +9 -0
  187. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
  188. package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
  189. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  190. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  191. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +7 -3
  192. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  193. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.d.ts +8 -0
  194. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.d.ts.map +1 -0
  195. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.js +222 -0
  196. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.js.map +1 -0
  197. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.d.ts +3 -0
  198. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.d.ts.map +1 -0
  199. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.js +10 -0
  200. package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.js.map +1 -0
  201. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts.map +1 -1
  202. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js +113 -4
  203. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js.map +1 -1
  204. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  205. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +1 -0
  206. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  207. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.d.ts +5 -0
  208. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.d.ts.map +1 -1
  209. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js +2 -1
  210. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js.map +1 -1
  211. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +10 -0
  212. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
  213. package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
  214. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +32 -0
  215. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  216. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +32 -0
  217. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  218. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
  219. package/node_modules/@earendil-works/pi-ai/dist/models.js +36 -13
  220. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  221. package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.d.ts +2 -0
  222. package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.d.ts.map +1 -1
  223. package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.js.map +1 -1
  224. package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
  225. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +2 -1
  226. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
  227. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  228. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  229. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
  230. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
  231. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  232. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  233. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  234. package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.d.ts +1 -0
  235. package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.d.ts.map +1 -1
  236. package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.js +18 -0
  237. package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.js.map +1 -1
  238. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.d.ts +3 -0
  239. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.d.ts.map +1 -0
  240. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.js +16 -0
  241. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.js.map +1 -0
  242. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +1 -1
  243. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  244. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  245. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  246. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +7 -0
  247. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  248. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  249. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  250. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  251. package/package.json +9 -9
  252. package/dist/core/extensions/builtin/mcp/expose/bm25.d.ts +0 -30
  253. package/dist/core/extensions/builtin/mcp/expose/bm25.d.ts.map +0 -1
  254. package/dist/core/extensions/builtin/mcp/expose/bm25.js.map +0 -1
  255. package/dist/core/extensions/builtin/mcp/expose/lazy-activate.d.ts +0 -15
  256. package/dist/core/extensions/builtin/mcp/expose/lazy-activate.d.ts.map +0 -1
  257. package/dist/core/extensions/builtin/mcp/expose/lazy-activate.js +0 -33
  258. package/dist/core/extensions/builtin/mcp/expose/lazy-activate.js.map +0 -1
  259. package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts +0 -43
  260. package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts.map +0 -1
  261. package/dist/core/extensions/builtin/mcp/expose/tool-search.js +0 -125
  262. package/dist/core/extensions/builtin/mcp/expose/tool-search.js.map +0 -1
@@ -1,98 +1,4 @@
1
- // Native provider tool-search adapters (todo 33 — Anthropic half).
2
- //
3
- // Gated on the todo-29 spike verdict: Anthropic Messages is GO-pure-extension —
4
- // server_tool_use / tool_search_tool_result blocks round-trip pi-ai's
5
- // parse->persist->re-serialise cycle untouched (native-search-spike.md), so this
6
- // adapter injects request-side fields via the extension before_provider_request
7
- // event ONLY (the sole ExtensionAPI payload surface) with no pi-ai change.
8
- //
9
- // It injects Anthropic's native `tool_search_tool_bm25_20251119` tool and marks
10
- // deferrable MCP tools `defer_loading:true`, honouring the API HARD RULES, and
11
- // auto-falls-back to local Tier-B on a 400. The OpenAI half is deferred
12
- // (spike = GO-with-ai-seam; see native-search-spike.md).
13
- export const ANTHROPIC_TOOL_SEARCH_TYPE = "tool_search_tool_bm25_20251119";
14
- export const ANTHROPIC_TOOL_SEARCH_NAME = "tool_search";
15
- /** Anthropic caps a request at 10k tools; beyond that native search is invalid. */
16
- export const ANTHROPIC_MAX_TOOLS = 10000;
17
- function isRecord(value) {
18
- return typeof value === "object" && value !== null;
19
- }
20
- /**
21
- * Pure payload transform. Adds exactly one native tool-search tool (idempotent)
22
- * and sets `defer_loading:true` on eligible MCP tools, enforcing the HARD RULES:
23
- * never defer the search tool, never combine defer_loading with cache_control
24
- * (400), keep >=1 non-deferred tool (the native search tool guarantees this),
25
- * and skip entirely above the 10k tool cap.
26
- */
27
- export function addAnthropicNativeToolSearch(api, payload, config) {
28
- if (api !== "anthropic-messages" || !isRecord(payload))
29
- return payload;
30
- const tools = Array.isArray(payload.tools) ? payload.tools : [];
31
- if (tools.length > ANTHROPIC_MAX_TOOLS)
32
- return payload;
33
- const deferred = tools.map((tool) => maybeDefer(tool, config));
34
- const hasSearchTool = deferred.some((tool) => isRecord(tool) && tool.type === ANTHROPIC_TOOL_SEARCH_TYPE);
35
- const nextTools = hasSearchTool
36
- ? deferred
37
- : [...deferred, { type: ANTHROPIC_TOOL_SEARCH_TYPE, name: ANTHROPIC_TOOL_SEARCH_NAME }];
38
- return { ...payload, tools: nextTools };
39
- }
40
- function maybeDefer(tool, config) {
41
- if (!isRecord(tool))
42
- return tool;
43
- const name = typeof tool.name === "string" ? tool.name : undefined;
44
- if (name === undefined)
45
- return tool; // server/native tools are type-based, never deferred
46
- if (name === config.searchToolName)
47
- return tool; // never defer the search tool
48
- if (!config.isDeferrable(name))
49
- return tool; // non-MCP tools untouched
50
- if ("cache_control" in tool)
51
- return tool; // never defer_loading + cache_control (400)
52
- if (tool.defer_loading === true)
53
- return tool; // idempotent
54
- return { ...tool, defer_loading: true };
55
- }
56
- /** `tool_reference` blocks emitted inside a tool_result so the API expands the
57
- * referenced (deferred) tools — the cache-prefix-safe custom-search path. */
58
- export function buildToolReferenceBlocks(names) {
59
- return names.map((name) => ({ type: "tool_reference", name }));
60
- }
61
- /**
62
- * Stateful adapter driving the before_provider_request injection and the
63
- * after_provider_response 400 detector. Once a 400 lands on a request we
64
- * injected, native search is disabled for the rest of the session and the
65
- * extension falls back to local Tier-B (which is always registered).
66
- */
67
- export class AnthropicNativeToolSearchAdapter {
68
- #disabled = false;
69
- #injectedLastRequest = false;
70
- #fallbackReason = null;
71
- #deps;
72
- constructor(deps) {
73
- this.#deps = deps;
74
- }
75
- applyBeforeRequest(api, payload) {
76
- this.#injectedLastRequest = false;
77
- if (this.#disabled || !this.#deps.enabled())
78
- return payload;
79
- const next = addAnthropicNativeToolSearch(api, payload, this.#deps);
80
- this.#injectedLastRequest = next !== payload;
81
- return next;
82
- }
83
- noteResponseStatus(status) {
84
- if (status !== 400 || !this.#injectedLastRequest || this.#disabled)
85
- return;
86
- this.#disabled = true;
87
- this.#fallbackReason =
88
- "Anthropic returned 400 for native tool-search; disabled it and fell back to local tool_search for this session.";
89
- this.#deps.onFallback?.(this.#fallbackReason);
90
- }
91
- get disabled() {
92
- return this.#disabled;
93
- }
94
- get fallbackReason() {
95
- return this.#fallbackReason;
96
- }
97
- }
1
+ // Compatibility re-export. Native Anthropic tool-search ownership moved to the
2
+ // shared tool-search builtin; MCP now contributes only its setting gate.
3
+ export { ANTHROPIC_MAX_TOOLS, ANTHROPIC_TOOL_SEARCH_NAME, ANTHROPIC_TOOL_SEARCH_TYPE, AnthropicNativeToolSearchAdapter, addAnthropicNativeToolSearch, buildToolReferenceBlocks, } from "../../tool-search/native-search.js";
98
4
  //# sourceMappingURL=native-search.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"native-search.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/native-search.ts"],"names":[],"mappings":"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","sourcesContent":["// Native provider tool-search adapters (todo 33 — Anthropic half).\n//\n// Gated on the todo-29 spike verdict: Anthropic Messages is GO-pure-extension —\n// server_tool_use / tool_search_tool_result blocks round-trip pi-ai's\n// parse->persist->re-serialise cycle untouched (native-search-spike.md), so this\n// adapter injects request-side fields via the extension before_provider_request\n// event ONLY (the sole ExtensionAPI payload surface) with no pi-ai change.\n//\n// It injects Anthropic's native `tool_search_tool_bm25_20251119` tool and marks\n// deferrable MCP tools `defer_loading:true`, honouring the API HARD RULES, and\n// auto-falls-back to local Tier-B on a 400. The OpenAI half is deferred\n// (spike = GO-with-ai-seam; see native-search-spike.md).\n\nexport const ANTHROPIC_TOOL_SEARCH_TYPE = \"tool_search_tool_bm25_20251119\";\nexport const ANTHROPIC_TOOL_SEARCH_NAME = \"tool_search\";\n/** Anthropic caps a request at 10k tools; beyond that native search is invalid. */\nexport const ANTHROPIC_MAX_TOOLS = 10000;\n\nexport interface AnthropicNativeInjectionConfig {\n\t/** Never defer this tool (our custom tool_search), and it is non-deferrable. */\n\treadonly searchToolName?: string;\n\t/** True for MCP catalog tools eligible for deferral. */\n\treadonly isDeferrable: (toolName: string) => boolean;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\n/**\n * Pure payload transform. Adds exactly one native tool-search tool (idempotent)\n * and sets `defer_loading:true` on eligible MCP tools, enforcing the HARD RULES:\n * never defer the search tool, never combine defer_loading with cache_control\n * (400), keep >=1 non-deferred tool (the native search tool guarantees this),\n * and skip entirely above the 10k tool cap.\n */\nexport function addAnthropicNativeToolSearch(\n\tapi: string | undefined,\n\tpayload: unknown,\n\tconfig: AnthropicNativeInjectionConfig,\n): unknown {\n\tif (api !== \"anthropic-messages\" || !isRecord(payload)) return payload;\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : [];\n\tif (tools.length > ANTHROPIC_MAX_TOOLS) return payload;\n\tconst deferred = tools.map((tool) => maybeDefer(tool, config));\n\tconst hasSearchTool = deferred.some((tool) => isRecord(tool) && tool.type === ANTHROPIC_TOOL_SEARCH_TYPE);\n\tconst nextTools = hasSearchTool\n\t\t? deferred\n\t\t: [...deferred, { type: ANTHROPIC_TOOL_SEARCH_TYPE, name: ANTHROPIC_TOOL_SEARCH_NAME }];\n\treturn { ...payload, tools: nextTools };\n}\n\nfunction maybeDefer(tool: unknown, config: AnthropicNativeInjectionConfig): unknown {\n\tif (!isRecord(tool)) return tool;\n\tconst name = typeof tool.name === \"string\" ? tool.name : undefined;\n\tif (name === undefined) return tool; // server/native tools are type-based, never deferred\n\tif (name === config.searchToolName) return tool; // never defer the search tool\n\tif (!config.isDeferrable(name)) return tool; // non-MCP tools untouched\n\tif (\"cache_control\" in tool) return tool; // never defer_loading + cache_control (400)\n\tif (tool.defer_loading === true) return tool; // idempotent\n\treturn { ...tool, defer_loading: true };\n}\n\n/** `tool_reference` blocks emitted inside a tool_result so the API expands the\n * referenced (deferred) tools — the cache-prefix-safe custom-search path. */\nexport function buildToolReferenceBlocks(names: readonly string[]): { type: \"tool_reference\"; name: string }[] {\n\treturn names.map((name) => ({ type: \"tool_reference\", name }));\n}\n\nexport interface AnthropicNativeAdapterDeps extends AnthropicNativeInjectionConfig {\n\t/** Resolved config gate (nativeToolSearch auto|true AND provider supports). */\n\tenabled(): boolean;\n\t/** Invoked once when a 400 forces the local-search fallback. */\n\tonFallback?(reason: string): void;\n}\n\n/**\n * Stateful adapter driving the before_provider_request injection and the\n * after_provider_response 400 detector. Once a 400 lands on a request we\n * injected, native search is disabled for the rest of the session and the\n * extension falls back to local Tier-B (which is always registered).\n */\nexport class AnthropicNativeToolSearchAdapter {\n\t#disabled = false;\n\t#injectedLastRequest = false;\n\t#fallbackReason: string | null = null;\n\treadonly #deps: AnthropicNativeAdapterDeps;\n\n\tconstructor(deps: AnthropicNativeAdapterDeps) {\n\t\tthis.#deps = deps;\n\t}\n\n\tapplyBeforeRequest(api: string | undefined, payload: unknown): unknown {\n\t\tthis.#injectedLastRequest = false;\n\t\tif (this.#disabled || !this.#deps.enabled()) return payload;\n\t\tconst next = addAnthropicNativeToolSearch(api, payload, this.#deps);\n\t\tthis.#injectedLastRequest = next !== payload;\n\t\treturn next;\n\t}\n\n\tnoteResponseStatus(status: number): void {\n\t\tif (status !== 400 || !this.#injectedLastRequest || this.#disabled) return;\n\t\tthis.#disabled = true;\n\t\tthis.#fallbackReason =\n\t\t\t\"Anthropic returned 400 for native tool-search; disabled it and fell back to local tool_search for this session.\";\n\t\tthis.#deps.onFallback?.(this.#fallbackReason);\n\t}\n\n\tget disabled(): boolean {\n\t\treturn this.#disabled;\n\t}\n\n\tget fallbackReason(): string | null {\n\t\treturn this.#fallbackReason;\n\t}\n}\n"]}
1
+ {"version":3,"file":"native-search.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/native-search.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,yEAAyE;AAOzE,OAAO,EACN,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,EAC1B,gCAAgC,EAChC,4BAA4B,EAC5B,wBAAwB,GACxB,MAAM,oCAAoC,CAAC","sourcesContent":["// Compatibility re-export. Native Anthropic tool-search ownership moved to the\n// shared tool-search builtin; MCP now contributes only its setting gate.\n\nexport type {\n\tAnthropicNativeAdapterDeps,\n\tAnthropicNativeInjectionConfig,\n\tNativeToolDefinition,\n} from \"../../tool-search/native-search.ts\";\nexport {\n\tANTHROPIC_MAX_TOOLS,\n\tANTHROPIC_TOOL_SEARCH_NAME,\n\tANTHROPIC_TOOL_SEARCH_TYPE,\n\tAnthropicNativeToolSearchAdapter,\n\taddAnthropicNativeToolSearch,\n\tbuildToolReferenceBlocks,\n} from \"../../tool-search/native-search.ts\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/proxy.ts"],"names":[],"mappings":"AAaA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EAA0B,KAAK,cAAc,EAAsB,MAAM,eAAe,CAAC;AAEhG,QAAA,MAAM,YAAY;;;;;EAWhB,CAAC;AAIH,KAAK,YAAY,GAAG,cAAc,CAAC,OAAO,YAAY,EAAE,cAAc,GAAG,SAAS,EAAE,OAAO,CAAC,CAAC;AAE7F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,mBAAmB,EAAE,GAAG,YAAY,CA2DxG"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/proxy.ts"],"names":[],"mappings":"AAaA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAA0B,KAAK,cAAc,EAAsB,MAAM,eAAe,CAAC;AAEhG,QAAA,MAAM,YAAY;;;;;EAWhB,CAAC;AAIH,KAAK,YAAY,GAAG,cAAc,CAAC,OAAO,YAAY,EAAE,cAAc,GAAG,SAAS,EAAE,OAAO,CAAC,CAAC;AAE7F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,mBAAmB,EAAE,GAAG,YAAY,CAqExG"}
@@ -10,7 +10,8 @@
10
10
  // self-correct; unknown tool names get nearest-match suggestions.
11
11
  import { Text } from "@earendil-works/pi-tui";
12
12
  import { Type } from "typebox";
13
- import { buildBm25Index } from "./bm25.js";
13
+ import { buildBm25Index } from "../../tool-search/engine/bm25.js";
14
+ import { deriveMcpRegistrationId } from "../../tool-search/engine/marker.js";
14
15
  import { executeMcpCatalogEntry, mapMcpCatalogNames } from "./register.js";
15
16
  const ParamsSchema = Type.Object({
16
17
  op: Type.Union([Type.Literal("search"), Type.Literal("describe"), Type.Literal("call")], {
@@ -25,7 +26,17 @@ const ParamsSchema = Type.Object({
25
26
  export function createMcpProxyTool(server, entries) {
26
27
  const named = mapMcpCatalogNames(entries);
27
28
  const byTool = new Map(named.map(({ entry }) => [entry.tool, entry]));
28
- const index = buildBm25Index(named.map(({ entry, name }) => ({ description: entry.description, name, server, toolName: entry.tool })));
29
+ const index = buildBm25Index(named.map(({ entry, name }) => ({
30
+ name,
31
+ label: entry.tool,
32
+ aliases: [entry.tool],
33
+ description: entry.description,
34
+ keywords: [],
35
+ source: "mcp",
36
+ group: server,
37
+ ownerLabel: server,
38
+ registrationId: deriveMcpRegistrationId(server, entry.tool),
39
+ })));
29
40
  const name = named[0]?.name.split("_").slice(0, 2).join("_") ?? `mcp_${server}`;
30
41
  return {
31
42
  name,
@@ -40,7 +51,7 @@ export function createMcpProxyTool(server, entries) {
40
51
  const body = matches.length === 0
41
52
  ? `No '${server}' tools matched. Try broader keywords or op:"describe" with an exact tool name.`
42
53
  : matches
43
- .map((match) => `- ${match.doc.toolName} — ${match.doc.description ?? "(no description)"}`)
54
+ .map((match) => `- ${match.doc.label} — ${match.doc.description ?? "(no description)"}`)
44
55
  .join("\n");
45
56
  return textResult(server, `Tools on '${server}':\n${body}`);
46
57
  }
@@ -79,7 +90,7 @@ function textResult(server, text) {
79
90
  }
80
91
  function unknownToolText(server, tool, index) {
81
92
  const nearest = tool === undefined ? [] : index.search(tool, 3, {});
82
- const hint = nearest.length === 0 ? "" : ` Nearest matches: ${nearest.map((match) => match.doc.toolName).join(", ")}.`;
93
+ const hint = nearest.length === 0 ? "" : ` Nearest matches: ${nearest.map((match) => match.doc.label).join(", ")}.`;
83
94
  return `Unknown tool '${tool ?? "(missing)"}' on '${server}'.${hint} Use op:"search" to list tools.`;
84
95
  }
85
96
  function firstLine(text) {
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/proxy.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AACzE,4EAA4E;AAC5E,wEAAwE;AACxE,2EAA2E;AAC3E,8EAA8E;AAC9E,6EAA6E;AAC7E,kEAAkE;AAGlE,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAuB,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEhG,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC;IAChC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE;QACxF,WAAW,EAAE,4FAA4F;KACzG,CAAC;IACF,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC,CAAC;IACtG,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,2CAA2C,EAAE,CAAC,CAAC;IAC9F,IAAI,EAAE,IAAI,CAAC,QAAQ,CAClB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,iFAAiF;KAC9F,CAAC,CACF;CACD,CAAC,CAAC;AAMH,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,OAAuC;IACzF,MAAM,KAAK,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAU,CAAC,CAAC,CAAC;IAC/E,MAAM,KAAK,GAAG,cAAc,CAC3B,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CACxG,CAAC;IACF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,MAAM,EAAE,CAAC;IAChF,OAAO;QACN,IAAI;QACJ,KAAK,EAAE,iBAAiB,MAAM,EAAE;QAChC,WAAW,EAAE,mBAAmB,MAAM,iBAAiB,OAAO,CAAC,MAAM,mOAAmO;QACxS,aAAa,EAAE,iBAAiB,MAAM,kEAAkE;QACxG,UAAU,EAAE,YAAY;QACxB,aAAa,EAAE,UAAU;QACzB,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,MAAc,EAAE,MAAM,EAAE,QAAQ;YAC1D,IAAI,MAAM,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;gBACzD,MAAM,IAAI,GACT,OAAO,CAAC,MAAM,KAAK,CAAC;oBACnB,CAAC,CAAC,OAAO,MAAM,iFAAiF;oBAChG,CAAC,CAAC,OAAO;yBACN,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,QAAQ,MAAM,KAAK,CAAC,GAAG,CAAC,WAAW,IAAI,kBAAkB,EAAE,CAAC;yBAC1F,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChB,OAAO,UAAU,CAAC,MAAM,EAAE,aAAa,MAAM,OAAO,IAAI,EAAE,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9E,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,UAAU,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YACxE,CAAC;YACD,IAAI,MAAM,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;gBAC9B,OAAO,UAAU,CAChB,MAAM,EACN,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,WAAW,IAAI,kBAAkB,kCAAkC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CACxI,CAAC;YACH,CAAC;YACD,IAAI,IAA6B,CAAC;YAClC,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;gBACxD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC5E,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;gBACnD,CAAC;gBACD,IAAI,GAAG,MAAiC,CAAC;YAC1C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,OAAO,UAAU,CAChB,MAAM,EACN,qBAAqB,KAAK,CAAC,IAAI,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,yGAAyG,KAAK,CAAC,IAAI,uCAAuC,CACrP,CAAC;YACH,CAAC;YACD,OAAO,MAAM,sBAAsB,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACpE,CAAC;QACD,UAAU,CAAC,IAAI,EAAE,KAAK;YACrB,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YAC7E,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACjG,CAAC;QACD,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK;YAClC,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC;YACvG,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACtD,CAAC;KACD,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,MAAc,EAAE,IAAY;IAC/C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC;AAC5G,CAAC;AAED,SAAS,eAAe,CAAC,MAAc,EAAE,IAAwB,EAAE,KAAwC;IAC1G,MAAM,OAAO,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACpE,MAAM,IAAI,GACT,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAC3G,OAAO,iBAAiB,IAAI,IAAI,WAAW,SAAS,MAAM,KAAK,IAAI,iCAAiC,CAAC;AACtG,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["// Tier-C proxy mode (todo 38): per-server OPT-IN (`exposure:\"proxy\"`).\n//\n// The whole server catalog hides behind ONE always-active `mcp_<server>`\n// gateway tool with three ops: search (BM25 over this server's catalog),\n// describe (schema + description for one tool), call (tool + args as a JSON\n// STRING). The JSON-string args deliberately trade provider strict-mode\n// validation for a ~200-token footprint (SPEC §5: -27.3pp GSM8K structured\n// output under proxy) — which is why auto NEVER selects this mode. Errors are\n// returned as guiding text (never thrown for user mistakes) so the model can\n// self-correct; unknown tool names get nearest-match suggestions.\n\nimport type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport { Text } from \"@earendil-works/pi-tui\";\nimport { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../../../types.ts\";\nimport type { McpToolCatalogEntry } from \"../catalog.ts\";\nimport { buildBm25Index } from \"./bm25.ts\";\nimport { executeMcpCatalogEntry, type McpToolDetails, mapMcpCatalogNames } from \"./register.ts\";\n\nconst ParamsSchema = Type.Object({\n\top: Type.Union([Type.Literal(\"search\"), Type.Literal(\"describe\"), Type.Literal(\"call\")], {\n\t\tdescription: \"search: rank tools by capability; describe: full schema for one tool; call: invoke a tool.\",\n\t}),\n\tquery: Type.Optional(Type.String({ description: \"search: capability description to rank tools by.\" })),\n\ttool: Type.Optional(Type.String({ description: \"describe/call: the server-side tool name.\" })),\n\targs: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: 'call: tool arguments as a JSON object STRING, e.g. \"{\\\\\"path\\\\\": \\\\\"a.txt\\\\\"}\".',\n\t\t}),\n\t),\n});\ntype Params = Static<typeof ParamsSchema>;\n\ntype ProxyResult = AgentToolResult<McpToolDetails | undefined>;\ntype McpProxyTool = ToolDefinition<typeof ParamsSchema, McpToolDetails | undefined, unknown>;\n\nexport function createMcpProxyTool(server: string, entries: readonly McpToolCatalogEntry[]): McpProxyTool {\n\tconst named = mapMcpCatalogNames(entries);\n\tconst byTool = new Map(named.map(({ entry }) => [entry.tool, entry] as const));\n\tconst index = buildBm25Index(\n\t\tnamed.map(({ entry, name }) => ({ description: entry.description, name, server, toolName: entry.tool })),\n\t);\n\tconst name = named[0]?.name.split(\"_\").slice(0, 2).join(\"_\") ?? `mcp_${server}`;\n\treturn {\n\t\tname,\n\t\tlabel: `MCP proxy for ${server}`,\n\t\tdescription: `Gateway to the '${server}' MCP server (${entries.length} tools). Use op:\"search\" with a query to find tools, op:\"describe\" with a tool name for its schema, then op:\"call\" with tool + args (args is a JSON object STRING — no strict validation, so match the described schema exactly).`,\n\t\tpromptSnippet: `Proxy for the ${server} MCP server: search -> describe -> call (args as a JSON string).`,\n\t\tparameters: ParamsSchema,\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params: Params, signal, onUpdate): Promise<ProxyResult> {\n\t\t\tif (params.op === \"search\") {\n\t\t\t\tconst matches = index.search(params.query ?? \"\", 10, {});\n\t\t\t\tconst body =\n\t\t\t\t\tmatches.length === 0\n\t\t\t\t\t\t? `No '${server}' tools matched. Try broader keywords or op:\"describe\" with an exact tool name.`\n\t\t\t\t\t\t: matches\n\t\t\t\t\t\t\t\t.map((match) => `- ${match.doc.toolName} — ${match.doc.description ?? \"(no description)\"}`)\n\t\t\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\treturn textResult(server, `Tools on '${server}':\\n${body}`);\n\t\t\t}\n\t\t\tconst entry = params.tool === undefined ? undefined : byTool.get(params.tool);\n\t\t\tif (entry === undefined) {\n\t\t\t\treturn textResult(server, unknownToolText(server, params.tool, index));\n\t\t\t}\n\t\t\tif (params.op === \"describe\") {\n\t\t\t\treturn textResult(\n\t\t\t\t\tserver,\n\t\t\t\t\t`${entry.tool}: ${entry.description ?? \"(no description)\"}\\nInput schema (JSON Schema):\\n${JSON.stringify(entry.schema ?? {}, null, 2)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tlet args: Record<string, unknown>;\n\t\t\ttry {\n\t\t\t\tconst parsed: unknown = JSON.parse(params.args ?? \"{}\");\n\t\t\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\t\t\tthrow new Error(\"args must encode a JSON object\");\n\t\t\t\t}\n\t\t\t\targs = parsed as Record<string, unknown>;\n\t\t\t} catch (error) {\n\t\t\t\treturn textResult(\n\t\t\t\t\tserver,\n\t\t\t\t\t`Invalid args for '${entry.tool}': ${error instanceof Error ? error.message : String(error)}. Pass args as a JSON object STRING matching the schema from op:\"describe\", e.g. {\"op\":\"call\",\"tool\":\"${entry.tool}\",\"args\":\"{\\\\\"key\\\\\": \\\\\"value\\\\\"}\"}.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn await executeMcpCatalogEntry(entry, args, signal, onUpdate);\n\t\t},\n\t\trenderCall(args, theme) {\n\t\t\tconst detail = args.op === \"search\" ? (args.query ?? \"\") : (args.tool ?? \"\");\n\t\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(`${name} ${args.op} ${detail}`.trim())), 0, 0);\n\t\t},\n\t\trenderResult(result, options, theme) {\n\t\t\tconst title = options.isPartial ? `${name}: running` : `${name}: ${result.details?.preview ?? \"done\"}`;\n\t\t\treturn new Text(theme.fg(\"toolOutput\", title), 0, 0);\n\t\t},\n\t};\n}\n\nfunction textResult(server: string, text: string): ProxyResult {\n\treturn { content: [{ type: \"text\", text }], details: { preview: firstLine(text), server, tool: \"proxy\" } };\n}\n\nfunction unknownToolText(server: string, tool: string | undefined, index: ReturnType<typeof buildBm25Index>): string {\n\tconst nearest = tool === undefined ? [] : index.search(tool, 3, {});\n\tconst hint =\n\t\tnearest.length === 0 ? \"\" : ` Nearest matches: ${nearest.map((match) => match.doc.toolName).join(\", \")}.`;\n\treturn `Unknown tool '${tool ?? \"(missing)\"}' on '${server}'.${hint} Use op:\"search\" to list tools.`;\n}\n\nfunction firstLine(text: string): string {\n\treturn text.split(\"\\n\", 1)[0].slice(0, 80);\n}\n"]}
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/proxy.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AACzE,4EAA4E;AAC5E,wEAAwE;AACxE,2EAA2E;AAC3E,8EAA8E;AAC9E,6EAA6E;AAC7E,kEAAkE;AAGlE,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,OAAO,EAAE,sBAAsB,EAAuB,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEhG,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC;IAChC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE;QACxF,WAAW,EAAE,4FAA4F;KACzG,CAAC;IACF,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC,CAAC;IACtG,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,2CAA2C,EAAE,CAAC,CAAC;IAC9F,IAAI,EAAE,IAAI,CAAC,QAAQ,CAClB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,iFAAiF;KAC9F,CAAC,CACF;CACD,CAAC,CAAC;AAMH,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,OAAuC;IACzF,MAAM,KAAK,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAU,CAAC,CAAC,CAAC;IAC/E,MAAM,KAAK,GAAG,cAAc,CAC3B,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/B,IAAI;QACJ,KAAK,EAAE,KAAK,CAAC,IAAI;QACjB,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;QACrB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,KAAc;QACtB,KAAK,EAAE,MAAM;QACb,UAAU,EAAE,MAAM;QAClB,cAAc,EAAE,uBAAuB,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;KAC3D,CAAC,CAAC,CACH,CAAC;IACF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,MAAM,EAAE,CAAC;IAChF,OAAO;QACN,IAAI;QACJ,KAAK,EAAE,iBAAiB,MAAM,EAAE;QAChC,WAAW,EAAE,mBAAmB,MAAM,iBAAiB,OAAO,CAAC,MAAM,mOAAmO;QACxS,aAAa,EAAE,iBAAiB,MAAM,kEAAkE;QACxG,UAAU,EAAE,YAAY;QACxB,aAAa,EAAE,UAAU;QACzB,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,MAAc,EAAE,MAAM,EAAE,QAAQ;YAC1D,IAAI,MAAM,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;gBACzD,MAAM,IAAI,GACT,OAAO,CAAC,MAAM,KAAK,CAAC;oBACnB,CAAC,CAAC,OAAO,MAAM,iFAAiF;oBAChG,CAAC,CAAC,OAAO;yBACN,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,KAAK,CAAC,GAAG,CAAC,WAAW,IAAI,kBAAkB,EAAE,CAAC;yBACvF,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChB,OAAO,UAAU,CAAC,MAAM,EAAE,aAAa,MAAM,OAAO,IAAI,EAAE,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9E,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,UAAU,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YACxE,CAAC;YACD,IAAI,MAAM,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;gBAC9B,OAAO,UAAU,CAChB,MAAM,EACN,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,WAAW,IAAI,kBAAkB,kCAAkC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CACxI,CAAC;YACH,CAAC;YACD,IAAI,IAA6B,CAAC;YAClC,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;gBACxD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC5E,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;gBACnD,CAAC;gBACD,IAAI,GAAG,MAAiC,CAAC;YAC1C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,OAAO,UAAU,CAChB,MAAM,EACN,qBAAqB,KAAK,CAAC,IAAI,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,yGAAyG,KAAK,CAAC,IAAI,uCAAuC,CACrP,CAAC;YACH,CAAC;YACD,OAAO,MAAM,sBAAsB,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACpE,CAAC;QACD,UAAU,CAAC,IAAI,EAAE,KAAK;YACrB,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YAC7E,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACjG,CAAC;QACD,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK;YAClC,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC;YACvG,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACtD,CAAC;KACD,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,MAAc,EAAE,IAAY;IAC/C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC;AAC5G,CAAC;AAED,SAAS,eAAe,CAAC,MAAc,EAAE,IAAwB,EAAE,KAAwC;IAC1G,MAAM,OAAO,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IACpH,OAAO,iBAAiB,IAAI,IAAI,WAAW,SAAS,MAAM,KAAK,IAAI,iCAAiC,CAAC;AACtG,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["// Tier-C proxy mode (todo 38): per-server OPT-IN (`exposure:\"proxy\"`).\n//\n// The whole server catalog hides behind ONE always-active `mcp_<server>`\n// gateway tool with three ops: search (BM25 over this server's catalog),\n// describe (schema + description for one tool), call (tool + args as a JSON\n// STRING). The JSON-string args deliberately trade provider strict-mode\n// validation for a ~200-token footprint (SPEC §5: -27.3pp GSM8K structured\n// output under proxy) — which is why auto NEVER selects this mode. Errors are\n// returned as guiding text (never thrown for user mistakes) so the model can\n// self-correct; unknown tool names get nearest-match suggestions.\n\nimport type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport { Text } from \"@earendil-works/pi-tui\";\nimport { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../../../types.ts\";\nimport { buildBm25Index } from \"../../tool-search/engine/bm25.ts\";\nimport { deriveMcpRegistrationId } from \"../../tool-search/engine/marker.ts\";\nimport type { McpToolCatalogEntry } from \"../catalog.ts\";\nimport { executeMcpCatalogEntry, type McpToolDetails, mapMcpCatalogNames } from \"./register.ts\";\n\nconst ParamsSchema = Type.Object({\n\top: Type.Union([Type.Literal(\"search\"), Type.Literal(\"describe\"), Type.Literal(\"call\")], {\n\t\tdescription: \"search: rank tools by capability; describe: full schema for one tool; call: invoke a tool.\",\n\t}),\n\tquery: Type.Optional(Type.String({ description: \"search: capability description to rank tools by.\" })),\n\ttool: Type.Optional(Type.String({ description: \"describe/call: the server-side tool name.\" })),\n\targs: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: 'call: tool arguments as a JSON object STRING, e.g. \"{\\\\\"path\\\\\": \\\\\"a.txt\\\\\"}\".',\n\t\t}),\n\t),\n});\ntype Params = Static<typeof ParamsSchema>;\n\ntype ProxyResult = AgentToolResult<McpToolDetails | undefined>;\ntype McpProxyTool = ToolDefinition<typeof ParamsSchema, McpToolDetails | undefined, unknown>;\n\nexport function createMcpProxyTool(server: string, entries: readonly McpToolCatalogEntry[]): McpProxyTool {\n\tconst named = mapMcpCatalogNames(entries);\n\tconst byTool = new Map(named.map(({ entry }) => [entry.tool, entry] as const));\n\tconst index = buildBm25Index(\n\t\tnamed.map(({ entry, name }) => ({\n\t\t\tname,\n\t\t\tlabel: entry.tool,\n\t\t\taliases: [entry.tool],\n\t\t\tdescription: entry.description,\n\t\t\tkeywords: [],\n\t\t\tsource: \"mcp\" as const,\n\t\t\tgroup: server,\n\t\t\townerLabel: server,\n\t\t\tregistrationId: deriveMcpRegistrationId(server, entry.tool),\n\t\t})),\n\t);\n\tconst name = named[0]?.name.split(\"_\").slice(0, 2).join(\"_\") ?? `mcp_${server}`;\n\treturn {\n\t\tname,\n\t\tlabel: `MCP proxy for ${server}`,\n\t\tdescription: `Gateway to the '${server}' MCP server (${entries.length} tools). Use op:\"search\" with a query to find tools, op:\"describe\" with a tool name for its schema, then op:\"call\" with tool + args (args is a JSON object STRING — no strict validation, so match the described schema exactly).`,\n\t\tpromptSnippet: `Proxy for the ${server} MCP server: search -> describe -> call (args as a JSON string).`,\n\t\tparameters: ParamsSchema,\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params: Params, signal, onUpdate): Promise<ProxyResult> {\n\t\t\tif (params.op === \"search\") {\n\t\t\t\tconst matches = index.search(params.query ?? \"\", 10, {});\n\t\t\t\tconst body =\n\t\t\t\t\tmatches.length === 0\n\t\t\t\t\t\t? `No '${server}' tools matched. Try broader keywords or op:\"describe\" with an exact tool name.`\n\t\t\t\t\t\t: matches\n\t\t\t\t\t\t\t\t.map((match) => `- ${match.doc.label} — ${match.doc.description ?? \"(no description)\"}`)\n\t\t\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\treturn textResult(server, `Tools on '${server}':\\n${body}`);\n\t\t\t}\n\t\t\tconst entry = params.tool === undefined ? undefined : byTool.get(params.tool);\n\t\t\tif (entry === undefined) {\n\t\t\t\treturn textResult(server, unknownToolText(server, params.tool, index));\n\t\t\t}\n\t\t\tif (params.op === \"describe\") {\n\t\t\t\treturn textResult(\n\t\t\t\t\tserver,\n\t\t\t\t\t`${entry.tool}: ${entry.description ?? \"(no description)\"}\\nInput schema (JSON Schema):\\n${JSON.stringify(entry.schema ?? {}, null, 2)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tlet args: Record<string, unknown>;\n\t\t\ttry {\n\t\t\t\tconst parsed: unknown = JSON.parse(params.args ?? \"{}\");\n\t\t\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\t\t\tthrow new Error(\"args must encode a JSON object\");\n\t\t\t\t}\n\t\t\t\targs = parsed as Record<string, unknown>;\n\t\t\t} catch (error) {\n\t\t\t\treturn textResult(\n\t\t\t\t\tserver,\n\t\t\t\t\t`Invalid args for '${entry.tool}': ${error instanceof Error ? error.message : String(error)}. Pass args as a JSON object STRING matching the schema from op:\"describe\", e.g. {\"op\":\"call\",\"tool\":\"${entry.tool}\",\"args\":\"{\\\\\"key\\\\\": \\\\\"value\\\\\"}\"}.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn await executeMcpCatalogEntry(entry, args, signal, onUpdate);\n\t\t},\n\t\trenderCall(args, theme) {\n\t\t\tconst detail = args.op === \"search\" ? (args.query ?? \"\") : (args.tool ?? \"\");\n\t\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(`${name} ${args.op} ${detail}`.trim())), 0, 0);\n\t\t},\n\t\trenderResult(result, options, theme) {\n\t\t\tconst title = options.isPartial ? `${name}: running` : `${name}: ${result.details?.preview ?? \"done\"}`;\n\t\t\treturn new Text(theme.fg(\"toolOutput\", title), 0, 0);\n\t\t},\n\t};\n}\n\nfunction textResult(server: string, text: string): ProxyResult {\n\treturn { content: [{ type: \"text\", text }], details: { preview: firstLine(text), server, tool: \"proxy\" } };\n}\n\nfunction unknownToolText(server: string, tool: string | undefined, index: ReturnType<typeof buildBm25Index>): string {\n\tconst nearest = tool === undefined ? [] : index.search(tool, 3, {});\n\tconst hint = nearest.length === 0 ? \"\" : ` Nearest matches: ${nearest.map((match) => match.doc.label).join(\", \")}.`;\n\treturn `Unknown tool '${tool ?? \"(missing)\"}' on '${server}'.${hint} Use op:\"search\" to list tools.`;\n}\n\nfunction firstLine(text: string): string {\n\treturn text.split(\"\\n\", 1)[0].slice(0, 80);\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import type { ExtensionAPI } from "../../../types.ts";
2
+ import type { ToolSearchService } from "../../tool-search/service.ts";
2
3
  import type { McpCachedServerCatalog } from "../catalog-cache.ts";
3
4
  import type { ResolvedMcpConfig } from "../config-schema.ts";
4
5
  import type { ServerConnection } from "../connection.ts";
@@ -22,5 +23,5 @@ export interface McpDirectRegistrationEntry {
22
23
  readonly ensureFresh?: () => Promise<void>;
23
24
  readonly ensureCachedToolConnected?: () => Promise<void>;
24
25
  }
25
- export declare function registerDirectMcpTools(pi: Pick<ExtensionAPI, "getActiveTools" | "setActiveTools" | "registerTool">, config: ResolvedMcpConfig, entries: Iterable<McpDirectRegistrationEntry>, options?: McpCatalogRegistrationOptions): Promise<McpSessionRegistration | undefined>;
26
+ export declare function registerDirectMcpTools(pi: Pick<ExtensionAPI, "getActiveTools" | "setActiveTools" | "registerTool">, config: ResolvedMcpConfig, entries: Iterable<McpDirectRegistrationEntry>, toolSearchService: ToolSearchService, options?: McpCatalogRegistrationOptions): Promise<McpSessionRegistration | undefined>;
26
27
  //# sourceMappingURL=session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAA0B,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEjF,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,KAAK,oBAAoB,EAAyB,MAAM,aAAa,CAAC;AAE/E,MAAM,MAAM,sBAAsB,GAAG,oBAAoB,GAAG;IAC3D,eAAe,EAAE,iBAAiB,EAAE,CAAC;IACrC,aAAa,EAAE,eAAe,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,aAAa,CAAC,EAAE,sBAAsB,CAAC;IAChD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,QAAQ,CAAC,yBAAyB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED,wBAAsB,sBAAsB,CAC3C,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,cAAc,CAAC,EAC5E,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,QAAQ,CAAC,0BAA0B,CAAC,EAC7C,OAAO,GAAE,6BAAkC,GACzC,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC,CA8E7C"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAA0B,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEjF,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,KAAK,oBAAoB,EAAyB,MAAM,aAAa,CAAC;AAE/E,MAAM,MAAM,sBAAsB,GAAG,oBAAoB,GAAG;IAC3D,eAAe,EAAE,iBAAiB,EAAE,CAAC;IACrC,aAAa,EAAE,eAAe,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,aAAa,CAAC,EAAE,sBAAsB,CAAC;IAChD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,QAAQ,CAAC,yBAAyB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED,wBAAsB,sBAAsB,CAC3C,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,cAAc,CAAC,EAC5E,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,QAAQ,CAAC,0BAA0B,CAAC,EAC7C,iBAAiB,EAAE,iBAAiB,EACpC,OAAO,GAAE,6BAAkC,GACzC,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC,CA+E7C"}
@@ -3,7 +3,7 @@ import { createMcpLogger } from "../log.js";
3
3
  import { createMcpResourceTools } from "../resources.js";
4
4
  import { computeMcpExposurePolicy } from "./policy.js";
5
5
  import { registerMcpTierBTools } from "./tier-b.js";
6
- export async function registerDirectMcpTools(pi, config, entries, options = {}) {
6
+ export async function registerDirectMcpTools(pi, config, entries, toolSearchService, options = {}) {
7
7
  const registeredEntries = [];
8
8
  const activeEntries = [];
9
9
  let searchMode = false;
@@ -69,7 +69,7 @@ export async function registerDirectMcpTools(pi, config, entries, options = {})
69
69
  return undefined;
70
70
  }
71
71
  const utilityTools = resourceServers.length > 0 ? createMcpResourceTools(() => resourceServers) : [];
72
- const registration = registerMcpTierBTools(pi, { activeEntries, proxyGateways, registeredEntries, searchMode, settings: config.settings, utilityTools }, (message) => createMcpLogger("service").warn(message));
72
+ const registration = registerMcpTierBTools(pi, { activeEntries, proxyGateways, registeredEntries, searchMode, settings: config.settings, utilityTools }, toolSearchService, (message) => createMcpLogger("service").warn(message));
73
73
  return { ...registration, promptServers, resourceServers };
74
74
  }
75
75
  //# sourceMappingURL=session.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/session.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionAPI } from \"../../../types.ts\";\nimport { cachedToolsToCatalogEntries, collectToolCatalog, type McpToolCatalogEntry } from \"../catalog.ts\";\nimport type { McpCachedServerCatalog } from \"../catalog-cache.ts\";\nimport type { ResolvedMcpConfig } from \"../config-schema.ts\";\nimport type { ServerConnection } from \"../connection.ts\";\nimport type { McpOutputArtifacts } from \"../guard/output-guard.ts\";\nimport { createMcpLogger, type McpLogger } from \"../log.ts\";\nimport type { McpPromptServer } from \"../prompts.ts\";\nimport { createMcpResourceTools, type McpResourceServer } from \"../resources.ts\";\nimport { computeMcpExposurePolicy } from \"./policy.ts\";\nimport type { McpCatalogRegistrationOptions } from \"./register.ts\";\nimport { type McpTierBRegistration, registerMcpTierBTools } from \"./tier-b.ts\";\n\nexport type McpSessionRegistration = McpTierBRegistration & {\n\tresourceServers: McpResourceServer[];\n\tpromptServers: McpPromptServer[];\n};\n\nexport interface McpDirectRegistrationEntry {\n\treadonly name: string;\n\treadonly connection: ServerConnection;\n\treadonly logger: McpLogger;\n\treadonly agentDir?: string;\n\treadonly artifacts?: McpOutputArtifacts;\n\treadonly cachedCatalog?: McpCachedServerCatalog;\n\treadonly ensureFresh?: () => Promise<void>;\n\treadonly ensureCachedToolConnected?: () => Promise<void>;\n}\n\nexport async function registerDirectMcpTools(\n\tpi: Pick<ExtensionAPI, \"getActiveTools\" | \"setActiveTools\" | \"registerTool\">,\n\tconfig: ResolvedMcpConfig,\n\tentries: Iterable<McpDirectRegistrationEntry>,\n\toptions: McpCatalogRegistrationOptions = {},\n): Promise<McpSessionRegistration | undefined> {\n\tconst registeredEntries: McpToolCatalogEntry[] = [];\n\tconst activeEntries: McpToolCatalogEntry[] = [];\n\tlet searchMode = false;\n\tconst proxyGateways: { server: string; entries: McpToolCatalogEntry[] }[] = [];\n\tconst resourceServers: McpResourceServer[] = [];\n\tconst promptServers: McpPromptServer[] = [];\n\tfor (const entry of entries) {\n\t\tconst server = config.servers[entry.name];\n\t\tif (server?.config === undefined) continue;\n\t\tconst catalog =\n\t\t\tentry.cachedCatalog === undefined\n\t\t\t\t? entry.connection.state === \"connected\"\n\t\t\t\t\t? await collectToolCatalog(entry.name, entry.connection, server.config, {\n\t\t\t\t\t\t\tagentDir: entry.agentDir,\n\t\t\t\t\t\t\tartifacts: entry.artifacts,\n\t\t\t\t\t\t\tensureFresh: entry.ensureFresh,\n\t\t\t\t\t\t\toutputGuard: config.settings.outputGuard,\n\t\t\t\t\t\t})\n\t\t\t\t\t: []\n\t\t\t\t: cachedToolsToCatalogEntries(\n\t\t\t\t\t\tentry.name,\n\t\t\t\t\t\tentry.cachedCatalog,\n\t\t\t\t\t\tentry.connection,\n\t\t\t\t\t\tserver.config.requestTimeoutMs,\n\t\t\t\t\t\tentry.ensureCachedToolConnected ?? (() => entry.connection.connect().then(() => undefined)),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tagentDir: entry.agentDir,\n\t\t\t\t\t\t\tartifacts: entry.artifacts,\n\t\t\t\t\t\t\tensureFresh: entry.ensureFresh,\n\t\t\t\t\t\t\toutputGuard: config.settings.outputGuard,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\tconst cachedPrompts = entry.cachedCatalog?.prompts ?? [];\n\t\tif (cachedPrompts.length > 0) {\n\t\t\tpromptServers.push({\n\t\t\t\tconnection: entry.connection,\n\t\t\t\tprompts: cachedPrompts,\n\t\t\t\trequestTimeoutMs: server.config.requestTimeoutMs,\n\t\t\t\tserver: entry.name,\n\t\t\t});\n\t\t}\n\t\tconst cachedResources = entry.cachedCatalog?.resources ?? [];\n\t\tif (cachedResources.length > 0) {\n\t\t\tresourceServers.push({\n\t\t\t\tagentDir: entry.agentDir,\n\t\t\t\tartifacts: entry.artifacts,\n\t\t\t\tconnection: entry.connection,\n\t\t\t\toutputGuard: config.settings.outputGuard,\n\t\t\t\trequestTimeoutMs: server.config.requestTimeoutMs,\n\t\t\t\tresources: cachedResources,\n\t\t\t\tserver: entry.name,\n\t\t\t});\n\t\t}\n\t\tconst policy = computeMcpExposurePolicy(catalog, server.config, config.settings);\n\t\tfor (const warning of policy.warnings) entry.logger.warn(warning);\n\t\tif (policy.mode === \"search\") searchMode = true;\n\t\tif (policy.mode === \"proxy\") proxyGateways.push({ entries: [...policy.filteredEntries], server: entry.name });\n\t\tregisteredEntries.push(...policy.registeredEntries);\n\t\tactiveEntries.push(...policy.activeEntries);\n\t}\n\t// Skip touching the active set only when there is genuinely nothing to do.\n\tif (\n\t\tregisteredEntries.length === 0 &&\n\t\tactiveEntries.length === 0 &&\n\t\t!searchMode &&\n\t\tproxyGateways.length === 0 &&\n\t\toptions.refreshActiveSetWhenEmpty !== true\n\t) {\n\t\treturn undefined;\n\t}\n\tconst utilityTools = resourceServers.length > 0 ? createMcpResourceTools(() => resourceServers) : [];\n\tconst registration = registerMcpTierBTools(\n\t\tpi,\n\t\t{ activeEntries, proxyGateways, registeredEntries, searchMode, settings: config.settings, utilityTools },\n\t\t(message) => createMcpLogger(\"service\").warn(message),\n\t);\n\treturn { ...registration, promptServers, resourceServers };\n}\n"]}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/session.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionAPI } from \"../../../types.ts\";\nimport type { ToolSearchService } from \"../../tool-search/service.ts\";\nimport { cachedToolsToCatalogEntries, collectToolCatalog, type McpToolCatalogEntry } from \"../catalog.ts\";\nimport type { McpCachedServerCatalog } from \"../catalog-cache.ts\";\nimport type { ResolvedMcpConfig } from \"../config-schema.ts\";\nimport type { ServerConnection } from \"../connection.ts\";\nimport type { McpOutputArtifacts } from \"../guard/output-guard.ts\";\nimport { createMcpLogger, type McpLogger } from \"../log.ts\";\nimport type { McpPromptServer } from \"../prompts.ts\";\nimport { createMcpResourceTools, type McpResourceServer } from \"../resources.ts\";\nimport { computeMcpExposurePolicy } from \"./policy.ts\";\nimport type { McpCatalogRegistrationOptions } from \"./register.ts\";\nimport { type McpTierBRegistration, registerMcpTierBTools } from \"./tier-b.ts\";\n\nexport type McpSessionRegistration = McpTierBRegistration & {\n\tresourceServers: McpResourceServer[];\n\tpromptServers: McpPromptServer[];\n};\n\nexport interface McpDirectRegistrationEntry {\n\treadonly name: string;\n\treadonly connection: ServerConnection;\n\treadonly logger: McpLogger;\n\treadonly agentDir?: string;\n\treadonly artifacts?: McpOutputArtifacts;\n\treadonly cachedCatalog?: McpCachedServerCatalog;\n\treadonly ensureFresh?: () => Promise<void>;\n\treadonly ensureCachedToolConnected?: () => Promise<void>;\n}\n\nexport async function registerDirectMcpTools(\n\tpi: Pick<ExtensionAPI, \"getActiveTools\" | \"setActiveTools\" | \"registerTool\">,\n\tconfig: ResolvedMcpConfig,\n\tentries: Iterable<McpDirectRegistrationEntry>,\n\ttoolSearchService: ToolSearchService,\n\toptions: McpCatalogRegistrationOptions = {},\n): Promise<McpSessionRegistration | undefined> {\n\tconst registeredEntries: McpToolCatalogEntry[] = [];\n\tconst activeEntries: McpToolCatalogEntry[] = [];\n\tlet searchMode = false;\n\tconst proxyGateways: { server: string; entries: McpToolCatalogEntry[] }[] = [];\n\tconst resourceServers: McpResourceServer[] = [];\n\tconst promptServers: McpPromptServer[] = [];\n\tfor (const entry of entries) {\n\t\tconst server = config.servers[entry.name];\n\t\tif (server?.config === undefined) continue;\n\t\tconst catalog =\n\t\t\tentry.cachedCatalog === undefined\n\t\t\t\t? entry.connection.state === \"connected\"\n\t\t\t\t\t? await collectToolCatalog(entry.name, entry.connection, server.config, {\n\t\t\t\t\t\t\tagentDir: entry.agentDir,\n\t\t\t\t\t\t\tartifacts: entry.artifacts,\n\t\t\t\t\t\t\tensureFresh: entry.ensureFresh,\n\t\t\t\t\t\t\toutputGuard: config.settings.outputGuard,\n\t\t\t\t\t\t})\n\t\t\t\t\t: []\n\t\t\t\t: cachedToolsToCatalogEntries(\n\t\t\t\t\t\tentry.name,\n\t\t\t\t\t\tentry.cachedCatalog,\n\t\t\t\t\t\tentry.connection,\n\t\t\t\t\t\tserver.config.requestTimeoutMs,\n\t\t\t\t\t\tentry.ensureCachedToolConnected ?? (() => entry.connection.connect().then(() => undefined)),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tagentDir: entry.agentDir,\n\t\t\t\t\t\t\tartifacts: entry.artifacts,\n\t\t\t\t\t\t\tensureFresh: entry.ensureFresh,\n\t\t\t\t\t\t\toutputGuard: config.settings.outputGuard,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\tconst cachedPrompts = entry.cachedCatalog?.prompts ?? [];\n\t\tif (cachedPrompts.length > 0) {\n\t\t\tpromptServers.push({\n\t\t\t\tconnection: entry.connection,\n\t\t\t\tprompts: cachedPrompts,\n\t\t\t\trequestTimeoutMs: server.config.requestTimeoutMs,\n\t\t\t\tserver: entry.name,\n\t\t\t});\n\t\t}\n\t\tconst cachedResources = entry.cachedCatalog?.resources ?? [];\n\t\tif (cachedResources.length > 0) {\n\t\t\tresourceServers.push({\n\t\t\t\tagentDir: entry.agentDir,\n\t\t\t\tartifacts: entry.artifacts,\n\t\t\t\tconnection: entry.connection,\n\t\t\t\toutputGuard: config.settings.outputGuard,\n\t\t\t\trequestTimeoutMs: server.config.requestTimeoutMs,\n\t\t\t\tresources: cachedResources,\n\t\t\t\tserver: entry.name,\n\t\t\t});\n\t\t}\n\t\tconst policy = computeMcpExposurePolicy(catalog, server.config, config.settings);\n\t\tfor (const warning of policy.warnings) entry.logger.warn(warning);\n\t\tif (policy.mode === \"search\") searchMode = true;\n\t\tif (policy.mode === \"proxy\") proxyGateways.push({ entries: [...policy.filteredEntries], server: entry.name });\n\t\tregisteredEntries.push(...policy.registeredEntries);\n\t\tactiveEntries.push(...policy.activeEntries);\n\t}\n\t// Skip touching the active set only when there is genuinely nothing to do.\n\tif (\n\t\tregisteredEntries.length === 0 &&\n\t\tactiveEntries.length === 0 &&\n\t\t!searchMode &&\n\t\tproxyGateways.length === 0 &&\n\t\toptions.refreshActiveSetWhenEmpty !== true\n\t) {\n\t\treturn undefined;\n\t}\n\tconst utilityTools = resourceServers.length > 0 ? createMcpResourceTools(() => resourceServers) : [];\n\tconst registration = registerMcpTierBTools(\n\t\tpi,\n\t\t{ activeEntries, proxyGateways, registeredEntries, searchMode, settings: config.settings, utilityTools },\n\t\ttoolSearchService,\n\t\t(message) => createMcpLogger(\"service\").warn(message),\n\t);\n\treturn { ...registration, promptServers, resourceServers };\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import type { ExtensionAPI } from "../../../types.ts";
2
+ import type { ToolSearchService } from "../../tool-search/service.ts";
2
3
  import type { McpToolCatalogEntry } from "../catalog.ts";
3
4
  import type { McpSettings } from "../config-schema.ts";
4
5
  import { type McpToolDefinition } from "./register.ts";
5
- import { type SearchableMcpTool } from "./tool-search.ts";
6
6
  type McpToolRegistrar = Pick<ExtensionAPI, "getActiveTools" | "setActiveTools" | "registerTool">;
7
7
  type WarnFn = (message: string) => void;
8
8
  export interface McpTierBRegistrationInput {
@@ -21,22 +21,24 @@ export interface McpTierBRegistrationInput {
21
21
  readonly utilityTools?: readonly McpToolDefinition[];
22
22
  readonly settings: McpSettings;
23
23
  }
24
+ export interface SearchableMcpTool {
25
+ readonly name: string;
26
+ readonly toolName: string;
27
+ readonly description?: string;
28
+ readonly server: string;
29
+ }
24
30
  export interface McpTierBRegistration {
25
31
  /** Searchable catalog (for reuse by /mcp status and list_changed). */
26
32
  readonly searchable: SearchableMcpTool[];
27
- /**
28
- * Replay activation markers found in session history through the SAME
29
- * activation path tool_search uses (stub swap + stable ordering), so a
30
- * resumed/compacted session restores its promoted tools without
31
- * re-searching. Returns the newly activated names (empty when nothing new).
32
- */
33
- rehydrateFromHistory(messages: readonly unknown[]): string[];
34
- /** Activate registered tools by name through the same stable path
35
- * tool_search uses (skill lazy-reveal, todo 37). Unknown names ignored. */
33
+ /** Activate registered tools through the shared feeder hook. */
36
34
  activate(names: readonly string[]): void;
37
35
  }
38
36
  /** Register MCP tools honouring Tier-B search mode + prompt-cache mitigations. */
39
- export declare function registerMcpTierBTools(pi: McpToolRegistrar, input: McpTierBRegistrationInput, warn?: WarnFn): McpTierBRegistration;
37
+ export declare function registerMcpTierBTools(pi: McpToolRegistrar, input: McpTierBRegistrationInput, toolSearchService: ToolSearchService, warn?: WarnFn): McpTierBRegistration;
38
+ /** Order the active set deterministically without disturbing base tools.
39
+ * Base tools retain reference order; every shared-catalog member sorts by
40
+ * canonical name so consecutive promotions remain byte-stable. */
41
+ export declare function orderActiveSet(names: readonly string[], reference: readonly string[], catalogNames: ReadonlySet<string>): string[];
40
42
  /** A 30-70 token placeholder for an inactive search-mode tool. Keeps the tools
41
43
  * array length-stable under stubSwap; guides the model to tool_search. */
42
44
  export declare function buildMcpStubDefinition(name: string): McpToolDefinition;
@@ -1 +1 @@
1
- {"version":3,"file":"tier-b.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/tier-b.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAEN,KAAK,iBAAiB,EAGtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAGN,KAAK,iBAAiB,EAGtB,MAAM,kBAAkB,CAAC;AAE1B,KAAK,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,cAAc,CAAC,CAAC;AACjG,KAAK,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAExC,MAAM,WAAW,yBAAyB;IACzC,wEAAwE;IACxE,QAAQ,CAAC,iBAAiB,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC3D,0EAA0E;IAC1E,QAAQ,CAAC,aAAa,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACvD,6DAA6D;IAC7D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAA;KAAE,EAAE,CAAC;IAChG,mFAAmF;IACnF,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACrD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACpC,sEAAsE;IACtE,QAAQ,CAAC,UAAU,EAAE,iBAAiB,EAAE,CAAC;IACzC;;;;;OAKG;IACH,oBAAoB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC;IAC7D;+EAC2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CACzC;AAID,kFAAkF;AAClF,wBAAgB,qBAAqB,CACpC,EAAE,EAAE,gBAAgB,EACpB,KAAK,EAAE,yBAAyB,EAChC,IAAI,CAAC,EAAE,MAAM,GACX,oBAAoB,CAwFtB;AA+BD;0EAC0E;AAC1E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAiBtE"}
1
+ {"version":3,"file":"tier-b.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/expose/tier-b.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAEN,KAAK,iBAAiB,EAGtB,MAAM,eAAe,CAAC;AAEvB,KAAK,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,cAAc,CAAC,CAAC;AACjG,KAAK,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAExC,MAAM,WAAW,yBAAyB;IACzC,wEAAwE;IACxE,QAAQ,CAAC,iBAAiB,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC3D,0EAA0E;IAC1E,QAAQ,CAAC,aAAa,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACvD,6DAA6D;IAC7D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAA;KAAE,EAAE,CAAC;IAChG,mFAAmF;IACnF,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACrD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACpC,sEAAsE;IACtE,QAAQ,CAAC,UAAU,EAAE,iBAAiB,EAAE,CAAC;IACzC,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CACzC;AAID,kFAAkF;AAClF,wBAAgB,qBAAqB,CACpC,EAAE,EAAE,gBAAgB,EACpB,KAAK,EAAE,yBAAyB,EAChC,iBAAiB,EAAE,iBAAiB,EACpC,IAAI,CAAC,EAAE,MAAM,GACX,oBAAoB,CAyFtB;AAiBD;;kEAEkE;AAClE,wBAAgB,cAAc,CAC7B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAC/B,MAAM,EAAE,CAQV;AAYD;0EAC0E;AAC1E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAiBtE"}
@@ -2,20 +2,17 @@
2
2
  //
3
3
  // Completes exposure:"auto": a server whose filtered tool count exceeds
4
4
  // searchThreshold enters SEARCH mode — the full catalog is registered but only
5
- // directTools stay active, and an always-active tool_search promotes the rest on
6
- // demand. Prompt-cache mitigations (SPEC §5): stable name sort everywhere;
7
- // activation turns accept a cache miss (documented); opt-in settings.stubSwap
8
- // registers 30-70-token stubs so the tools array stays length-stable and only
9
- // the activated entry's bytes change (stub -> full) on promotion.
5
+ // directTools stay active. The shared tool-search builtin owns tool_search and
6
+ // MCP feeds its searchable documents and activation hook into that service.
10
7
  import { Text } from "@earendil-works/pi-tui";
11
8
  import { Type } from "typebox";
9
+ import { deriveMcpRegistrationId } from "../../tool-search/engine/marker.js";
12
10
  import { registerToolsPreservingActiveSet } from "../active-set.js";
13
11
  import { createMcpProxyTool } from "./proxy.js";
14
12
  import { buildMcpToolDefinitions, mapMcpCatalogNames, } from "./register.js";
15
- import { createMcpSearchTool, rehydrateActiveToolsFromHistory, TOOL_SEARCH_TOOL_NAME, unionStable, } from "./tool-search.js";
16
- const NOOP_REHYDRATE = () => [];
13
+ const managedNamesByRegistrar = new WeakMap();
17
14
  /** Register MCP tools honouring Tier-B search mode + prompt-cache mitigations. */
18
- export function registerMcpTierBTools(pi, input, warn) {
15
+ export function registerMcpTierBTools(pi, input, toolSearchService, warn) {
19
16
  const named = mapMcpCatalogNames(input.registeredEntries, warn);
20
17
  const searchable = named.map(({ entry, name }) => ({
21
18
  name,
@@ -23,6 +20,17 @@ export function registerMcpTierBTools(pi, input, warn) {
23
20
  description: entry.description,
24
21
  server: entry.server,
25
22
  }));
23
+ const documents = named.map(({ entry, name }) => ({
24
+ name,
25
+ label: entry.tool,
26
+ aliases: [entry.tool],
27
+ description: entry.description,
28
+ keywords: [],
29
+ source: "mcp",
30
+ group: entry.server,
31
+ ownerLabel: entry.server,
32
+ registrationId: deriveMcpRegistrationId(entry.server, entry.tool),
33
+ }));
26
34
  const fullDefs = buildMcpToolDefinitions(input.registeredEntries, warn);
27
35
  const fullByName = new Map(fullDefs.map((def) => [def.name, def]));
28
36
  const gatewayNames = [];
@@ -36,56 +44,40 @@ export function registerMcpTierBTools(pi, input, warn) {
36
44
  gatewayNames.push(tool.name);
37
45
  }
38
46
  const activeMcpNames = [...mapMcpCatalogNames(input.activeEntries).map(({ name }) => name), ...gatewayNames];
39
- const reference = pi.getActiveTools();
40
- // Base tools carry over; any stale mcp_* names from a prior generation are
41
- // dropped (membership = base + the intended mcp set; reference orders only).
42
- const currentBase = reference.filter((name) => !name.startsWith("mcp_"));
43
- if (!input.searchMode) {
44
- registerToolsPreservingActiveSet(pi, fullDefs, orderActiveSet([...currentBase, ...activeMcpNames], reference));
45
- // Direct mode: everything registerable is already active, nothing to replay.
46
- const activateDirect = (names) => {
47
- pi.setActiveTools(orderActiveSet(unionStable(pi.getActiveTools(), names), pi.getActiveTools()));
48
- };
49
- return { activate: activateDirect, searchable, rehydrateFromHistory: NOOP_REHYDRATE };
50
- }
51
- const stubSwap = input.settings.stubSwap === true;
47
+ const managedNames = new Set([...fullDefs.map((def) => def.name), ...gatewayNames]);
48
+ const previousManagedNames = managedNamesByRegistrar.get(pi) ?? new Set();
49
+ managedNamesByRegistrar.set(pi, managedNames);
50
+ const stubSwap = input.searchMode && input.settings.stubSwap === true;
52
51
  const stubbed = new Set();
53
- const activateMcpTools = (names) => {
54
- if (stubSwap)
55
- swapStubsToFull(pi, names, stubbed, fullByName);
56
- pi.setActiveTools(orderActiveSet(names, pi.getActiveTools()));
57
- };
58
- const searchTool = createMcpSearchTool({
59
- getSearchableTools: () => searchable,
60
- getActiveTools: () => pi.getActiveTools(),
61
- setActiveTools: activateMcpTools,
62
- });
63
52
  const registeredNames = new Set(fullDefs.map((def) => def.name));
53
+ const catalogNames = new Set(toolSearchService.getCatalog().map((doc) => doc.name));
64
54
  const activate = (names) => {
65
- const known = names.filter((name) => registeredNames.has(name));
55
+ const known = [...new Set(names.filter((name) => registeredNames.has(name)))];
66
56
  if (known.length === 0)
67
57
  return;
68
- activateMcpTools(unionStable(pi.getActiveTools(), known));
69
- };
70
- const rehydrateFromHistory = (messages) => {
71
- const restored = rehydrateActiveToolsFromHistory(messages, registeredNames);
58
+ if (stubSwap)
59
+ swapStubsToFull(pi, known, stubbed, fullByName);
72
60
  const current = pi.getActiveTools();
73
- const fresh = restored.filter((name) => !current.includes(name));
74
- if (fresh.length === 0)
75
- return [];
76
- activateMcpTools(unionStable(current, fresh));
77
- return fresh;
61
+ pi.setActiveTools(orderActiveSet(unionStable(current, known), current, catalogNames));
78
62
  };
79
- // tool_search carries a distinct param schema, so register it on its own
80
- // rather than mixing it into the broadly-typed catalog def array.
81
- pi.registerTool(searchTool);
63
+ toolSearchService.feed("mcp", input.searchMode ? documents : [], { activate });
64
+ for (const doc of toolSearchService.getCatalog())
65
+ catalogNames.add(doc.name);
66
+ const reference = pi.getActiveTools();
67
+ // MCP owns only names from its previous/current registration generation.
68
+ // Everything else is a base tool, regardless of naming convention.
69
+ const currentBase = reference.filter((name) => !isLegacyMcpRegistrationName(name) && !previousManagedNames.has(name) && !managedNames.has(name));
70
+ if (!input.searchMode) {
71
+ registerToolsPreservingActiveSet(pi, fullDefs, orderActiveSet([...currentBase, ...activeMcpNames], reference, catalogNames));
72
+ return { activate, searchable };
73
+ }
82
74
  if (!stubSwap) {
83
- // Default search mode: full defs registered, only directTools + tool_search
84
- // active. Newly promoted tools enter the array on their activation turn
85
- // (an accepted cache miss).
86
- const active = orderActiveSet([...currentBase, TOOL_SEARCH_TOOL_NAME, ...activeMcpNames], reference);
75
+ // Default search mode: full defs registered, only directTools plus the
76
+ // shared service-managed tool_search are active. Promotions append on the
77
+ // activation turn (an accepted cache miss).
78
+ const active = orderActiveSet([...currentBase, ...activeMcpNames], reference, catalogNames);
87
79
  registerToolsPreservingActiveSet(pi, fullDefs, active);
88
- return { activate, searchable, rehydrateFromHistory };
80
+ return { activate, searchable };
89
81
  }
90
82
  // stubSwap: every search-mode tool is registered as a tiny stub and kept
91
83
  // active so the tools array is length-stable; direct tools stay full.
@@ -96,9 +88,9 @@ export function registerMcpTierBTools(pi, input, warn) {
96
88
  stubbed.add(def.name);
97
89
  return buildMcpStubDefinition(def.name);
98
90
  });
99
- const active = orderActiveSet([...currentBase, TOOL_SEARCH_TOOL_NAME, ...fullDefs.map((def) => def.name)], reference);
91
+ const active = orderActiveSet([...currentBase, ...fullDefs.map((def) => def.name)], reference, catalogNames);
100
92
  registerToolsPreservingActiveSet(pi, toRegister, active);
101
- return { activate, searchable, rehydrateFromHistory };
93
+ return { activate, searchable };
102
94
  }
103
95
  function swapStubsToFull(pi, names, stubbed, fullByName) {
104
96
  for (const name of names) {
@@ -111,18 +103,25 @@ function swapStubsToFull(pi, names, stubbed, fullByName) {
111
103
  stubbed.delete(name);
112
104
  }
113
105
  }
114
- /** Order the active set deterministically WITHOUT disturbing non-MCP (base)
115
- * tools: base tools keep their existing relative order (by `reference` index,
116
- * new ones appended), MCP tools (incl. tool_search) are sorted for cache
117
- * stability. Sorting base tools would churn the system-prompt tool listing. */
118
- function orderActiveSet(names, reference) {
106
+ /** Order the active set deterministically without disturbing base tools.
107
+ * Base tools retain reference order; every shared-catalog member sorts by
108
+ * canonical name so consecutive promotions remain byte-stable. */
109
+ export function orderActiveSet(names, reference, catalogNames) {
119
110
  const unique = [...new Set(names)];
120
111
  const rank = new Map(reference.map((name, index) => [name, index]));
121
112
  const base = unique
122
- .filter((name) => !name.startsWith("mcp_"))
113
+ .filter((name) => !catalogNames.has(name))
123
114
  .sort((a, b) => (rank.get(a) ?? Number.MAX_SAFE_INTEGER) - (rank.get(b) ?? Number.MAX_SAFE_INTEGER));
124
- const mcp = unique.filter((name) => name.startsWith("mcp_")).sort();
125
- return [...base, ...mcp];
115
+ const catalog = unique.filter((name) => catalogNames.has(name)).sort();
116
+ return [...base, ...catalog];
117
+ }
118
+ function unionStable(current, added) {
119
+ return [...new Set([...current, ...added])];
120
+ }
121
+ /** Preserve the existing stale-generation cleanup for active sets created
122
+ * before MCP catalog ownership was tracked. Ordering itself is catalog-based. */
123
+ function isLegacyMcpRegistrationName(name) {
124
+ return name.startsWith("mcp_");
126
125
  }
127
126
  /** A 30-70 token placeholder for an inactive search-mode tool. Keeps the tools
128
127
  * array length-stable under stubSwap; guides the model to tool_search. */