@herbertgao/pi-extensions 2026.8.4 → 2026.8.6

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 (360) hide show
  1. package/README.md +5 -5
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +11 -3
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +11 -3
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +7 -6
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +21 -12
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +4 -5
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +53 -14
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +22 -12
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +2 -4
  14. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  15. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +18 -0
  16. package/node_modules/@herbertgao/pi-subagents/package.json +8 -4
  17. package/node_modules/@herbertgao/pi-subagents/src/agent-color.ts +72 -67
  18. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +255 -0
  19. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +191 -3
  20. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +20 -4
  21. package/node_modules/@herbertgao/pi-subagents/src/index.ts +289 -113
  22. package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +24 -1
  23. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +24 -2
  24. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +15 -6
  25. package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
  26. package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
  27. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
  28. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
  29. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
  30. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
  31. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
  32. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  33. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
  34. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
  36. package/node_modules/@narumitw/pi-btw/README.md +32 -24
  37. package/node_modules/@narumitw/pi-btw/package.json +6 -6
  38. package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
  39. package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -13
  40. package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
  41. package/node_modules/pi-lens/CHANGELOG.md +2535 -954
  42. package/node_modules/pi-lens/README.md +13 -0
  43. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
  44. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
  45. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
  46. package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
  47. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
  48. package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
  49. package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
  50. package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
  51. package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
  52. package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
  53. package/node_modules/pi-lens/dist/clients/biome-client.js +136 -24
  54. package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
  55. package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
  56. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +192 -0
  57. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
  58. package/node_modules/pi-lens/dist/clients/bus-publish.js +19 -4
  59. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
  60. package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
  61. package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
  62. package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
  63. package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
  64. package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
  65. package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
  66. package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
  67. package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
  68. package/node_modules/pi-lens/dist/clients/console-guard-install.js +26 -0
  69. package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
  70. package/node_modules/pi-lens/dist/clients/dead-code-client.js +137 -31
  71. package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
  72. package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
  73. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
  74. package/node_modules/pi-lens/dist/clients/dependency-checker.js +361 -77
  75. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +65 -13
  76. package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +18 -4
  77. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +176 -29
  78. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
  79. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
  80. package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
  81. package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
  82. package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
  83. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1172 -683
  84. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
  85. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
  86. package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
  87. package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
  88. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +47 -6
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +473 -42
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
  114. package/node_modules/pi-lens/dist/clients/disposition-publish.js +18 -4
  115. package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
  116. package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
  117. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
  118. package/node_modules/pi-lens/dist/clients/extension-log.js +432 -0
  119. package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
  120. package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
  121. package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
  122. package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
  123. package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
  124. package/node_modules/pi-lens/dist/clients/format-events-publish.js +51 -7
  125. package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
  126. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
  127. package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
  128. package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
  129. package/node_modules/pi-lens/dist/clients/git-guard.js +678 -11
  130. package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
  131. package/node_modules/pi-lens/dist/clients/go-client.js +23 -40
  132. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +124 -7
  133. package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
  134. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
  135. package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
  136. package/node_modules/pi-lens/dist/clients/installer/index.js +395 -100
  137. package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
  138. package/node_modules/pi-lens/dist/clients/jscpd-client.js +27 -55
  139. package/node_modules/pi-lens/dist/clients/knip-client.js +58 -42
  140. package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
  141. package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
  142. package/node_modules/pi-lens/dist/clients/latency-logger.js +72 -1
  143. package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
  144. package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
  145. package/node_modules/pi-lens/dist/clients/lens-events.js +63 -9
  146. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
  147. package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
  148. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +73 -0
  149. package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
  150. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
  151. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +59 -14
  152. package/node_modules/pi-lens/dist/clients/lsp/client.js +662 -56
  153. package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
  154. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +115 -0
  155. package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
  156. package/node_modules/pi-lens/dist/clients/lsp/index.js +2025 -800
  157. package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
  158. package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
  159. package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
  160. package/node_modules/pi-lens/dist/clients/lsp/server.js +437 -86
  161. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -0
  162. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
  163. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +18 -3
  164. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
  165. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
  166. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
  167. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +127 -32
  168. package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
  169. package/node_modules/pi-lens/dist/clients/mcp/session.js +235 -14
  170. package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
  171. package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
  172. package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
  173. package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
  174. package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
  175. package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
  176. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
  177. package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
  178. package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
  179. package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
  180. package/node_modules/pi-lens/dist/clients/pipeline.js +76 -15
  181. package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
  182. package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
  183. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
  184. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
  185. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
  186. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
  187. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +21 -1
  188. package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
  189. package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
  190. package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
  191. package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
  192. package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
  193. package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
  194. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
  195. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
  196. package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
  197. package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
  198. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
  199. package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
  200. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
  201. package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
  202. package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
  203. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
  204. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
  205. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
  206. package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
  207. package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
  208. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +257 -77
  209. package/node_modules/pi-lens/dist/clients/runtime-context.js +129 -12
  210. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +242 -26
  211. package/node_modules/pi-lens/dist/clients/runtime-session.js +428 -117
  212. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
  213. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +342 -33
  214. package/node_modules/pi-lens/dist/clients/runtime-turn.js +619 -93
  215. package/node_modules/pi-lens/dist/clients/rust-client.js +23 -38
  216. package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
  217. package/node_modules/pi-lens/dist/clients/security-scan-client.js +90 -6
  218. package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
  219. package/node_modules/pi-lens/dist/clients/sg-runner.js +424 -196
  220. package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
  221. package/node_modules/pi-lens/dist/clients/smells-rollup.js +231 -0
  222. package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
  223. package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
  224. package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
  225. package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
  226. package/node_modules/pi-lens/dist/clients/test-runner-client.js +469 -32
  227. package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
  228. package/node_modules/pi-lens/dist/clients/tool-policy.js +390 -39
  229. package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
  230. package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
  231. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
  232. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
  233. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
  234. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
  235. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
  236. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
  237. package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
  238. package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
  239. package/node_modules/pi-lens/dist/clients/warm-attach.js +50 -13
  240. package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
  241. package/node_modules/pi-lens/dist/clients/word-index.js +680 -81
  242. package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
  243. package/node_modules/pi-lens/dist/index.js +51785 -36118
  244. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
  245. package/node_modules/pi-lens/dist/mcp/server.js +219 -46
  246. package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
  247. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
  248. package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
  249. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
  250. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +203 -38
  251. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +210 -42
  252. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
  253. package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
  254. package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
  255. package/node_modules/pi-lens/docs/agent-guide.md +40 -15
  256. package/node_modules/pi-lens/docs/agent-tools.md +21 -10
  257. package/node_modules/pi-lens/docs/analysisall.md +192 -0
  258. package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
  259. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +14 -3
  260. package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
  261. package/node_modules/pi-lens/docs/environment-variables.md +44 -0
  262. package/node_modules/pi-lens/docs/fable.md +27 -0
  263. package/node_modules/pi-lens/docs/features.md +45 -3
  264. package/node_modules/pi-lens/docs/globalconfig.md +56 -1
  265. package/node_modules/pi-lens/docs/language-coverage.md +4 -3
  266. package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
  267. package/node_modules/pi-lens/docs/mcp.md +37 -4
  268. package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
  269. package/node_modules/pi-lens/docs/settings.md +18 -1
  270. package/node_modules/pi-lens/docs/tools.md +4 -1
  271. package/node_modules/pi-lens/docs/usage.md +41 -5
  272. package/node_modules/pi-lens/docs/word-index.md +35 -0
  273. package/node_modules/pi-lens/package.json +10 -10
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
  288. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
  289. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
  290. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
  291. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
  292. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
  293. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
  294. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
  295. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
  296. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
  297. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
  298. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
  299. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
  300. package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
  301. package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
  302. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +134 -2
  303. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -11
  304. package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
  305. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +8 -114
  306. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
  307. package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
  308. package/node_modules/pi-mcp-adapter/CHANGELOG.md +38 -0
  309. package/node_modules/pi-mcp-adapter/README.md +38 -4
  310. package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
  311. package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
  312. package/node_modules/pi-mcp-adapter/cli.js +25 -4
  313. package/node_modules/pi-mcp-adapter/commands.ts +15 -7
  314. package/node_modules/pi-mcp-adapter/config.ts +4 -4
  315. package/node_modules/pi-mcp-adapter/direct-tools.ts +58 -8
  316. package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
  317. package/node_modules/pi-mcp-adapter/index.ts +8 -3
  318. package/node_modules/pi-mcp-adapter/init.ts +29 -5
  319. package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
  320. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
  321. package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
  322. package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
  323. package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
  324. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
  325. package/node_modules/pi-mcp-adapter/metadata-cache.ts +37 -4
  326. package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
  327. package/node_modules/pi-mcp-adapter/package.json +4 -3
  328. package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
  329. package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
  330. package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
  331. package/node_modules/pi-mcp-adapter/server-manager.ts +41 -7
  332. package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
  333. package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
  334. package/node_modules/pi-mcp-adapter/tool-metadata.ts +62 -4
  335. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
  336. package/node_modules/pi-mcp-adapter/types.ts +176 -27
  337. package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
  338. package/node_modules/pi-web-access/CHANGELOG.md +14 -0
  339. package/node_modules/pi-web-access/README.md +18 -12
  340. package/node_modules/pi-web-access/auth-fetch.ts +148 -0
  341. package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
  342. package/node_modules/pi-web-access/curator-page.ts +5 -3
  343. package/node_modules/pi-web-access/curator-server.ts +2 -1
  344. package/node_modules/pi-web-access/extract.ts +106 -34
  345. package/node_modules/pi-web-access/fetch-params.ts +17 -3
  346. package/node_modules/pi-web-access/firecrawl.ts +172 -12
  347. package/node_modules/pi-web-access/gemini-search.ts +18 -4
  348. package/node_modules/pi-web-access/index.ts +120 -48
  349. package/node_modules/pi-web-access/package.json +2 -2
  350. package/node_modules/pi-web-access/summary-review.ts +11 -5
  351. package/node_modules/pi-web-access/youtube-extract.ts +2 -2
  352. package/package.json +12 -13
  353. package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
  354. package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
  355. package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
  356. package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
  357. package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
  358. package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
  359. package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
  360. package/node_modules/pi-lens/dist/clients/types.js +0 -11
@@ -1,11 +1,11 @@
1
1
  // npx-resolver.ts - Resolve npx/npm exec binaries to avoid npm parent processes
2
- import { existsSync, readFileSync, realpathSync, readdirSync, statSync, writeFileSync, renameSync, mkdirSync, openSync, readSync, closeSync } from "node:fs";
2
+ import { existsSync, readFileSync, realpathSync, readdirSync, statSync, writeFileSync, renameSync, mkdirSync, openSync, readSync, closeSync, unlinkSync } from "node:fs";
3
3
  import { join, dirname, extname, resolve, sep } from "node:path";
4
4
  import { getAgentPath } from "./agent-dir.ts";
5
5
  import { throwIfAborted } from "./abort.ts";
6
6
  import crossSpawn from "cross-spawn";
7
7
 
8
- const CACHE_VERSION = 1;
8
+ const CACHE_VERSION = 2;
9
9
  const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
10
10
  const EXACT_PACKAGE_VERSION_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z][0-9A-Za-z.-]*)?(?:\+[0-9A-Za-z][0-9A-Za-z.-]*)?$/;
11
11
 
@@ -53,7 +53,7 @@ export async function resolveNpxBinary(
53
53
  if (!parsed) return null;
54
54
 
55
55
  const packageSpec = parsePackageSpec(parsed.packageSpec);
56
- const cacheKey = JSON.stringify([command, ...args]);
56
+ const cacheKey = JSON.stringify([command, parsed.packageSpec, parsed.binName ?? ""]);
57
57
  const cache = loadCache();
58
58
  const cached = cache?.entries?.[cacheKey];
59
59
 
@@ -434,41 +434,96 @@ function getNpxCachePath(): string {
434
434
  return getAgentPath("mcp-npx-cache.json");
435
435
  }
436
436
 
437
- function loadCache(): NpxCache | null {
438
- const cachePath = getNpxCachePath();
437
+ function readNpxCachePayload(cachePath: string): unknown | null {
439
438
  if (!existsSync(cachePath)) return null;
440
439
  try {
441
- const raw = JSON.parse(readFileSync(cachePath, "utf-8"));
442
- if (!raw || typeof raw !== "object") return null;
443
- if (raw.version !== CACHE_VERSION) return null;
444
- if (!raw.entries || typeof raw.entries !== "object") return null;
445
- return raw as NpxCache;
440
+ return JSON.parse(readFileSync(cachePath, "utf-8")) as unknown;
446
441
  } catch {
447
442
  return null;
448
443
  }
449
444
  }
450
445
 
451
- function saveCacheEntry(key: string, entry: NpxCacheEntry): void {
452
- const cachePath = getNpxCachePath();
453
- const dir = dirname(cachePath);
454
- mkdirSync(dir, { recursive: true });
446
+ function asRecord(value: unknown): Record<string, unknown> | null {
447
+ return typeof value === "object" && value !== null && !Array.isArray(value)
448
+ ? value as Record<string, unknown>
449
+ : null;
450
+ }
451
+
452
+ function createCacheEntries(): Record<string, NpxCacheEntry> {
453
+ return Object.create(null) as Record<string, NpxCacheEntry>;
454
+ }
455
+
456
+ function toNpxCacheEntry(value: unknown): NpxCacheEntry | null {
457
+ const raw = asRecord(value);
458
+ if (!raw) return null;
459
+ if (typeof raw.resolvedBin !== "string") return null;
460
+ if (typeof raw.resolvedAt !== "number" || !Number.isFinite(raw.resolvedAt)) return null;
461
+ if (typeof raw.isJs !== "boolean") return null;
462
+ if (raw.packageVersion !== undefined && typeof raw.packageVersion !== "string") return null;
463
+ return {
464
+ resolvedBin: raw.resolvedBin,
465
+ resolvedAt: raw.resolvedAt,
466
+ ...(raw.packageVersion !== undefined ? { packageVersion: raw.packageVersion } : {}),
467
+ isJs: raw.isJs,
468
+ };
469
+ }
470
+
471
+ function toNpxCache(value: unknown): NpxCache | null {
472
+ const raw = asRecord(value);
473
+ if (!raw || raw.version !== CACHE_VERSION) return null;
474
+ const rawEntries = asRecord(raw.entries);
475
+ if (!rawEntries) return null;
476
+
477
+ const entries = createCacheEntries();
478
+ for (const [key, rawEntry] of Object.entries(rawEntries)) {
479
+ const entry = toNpxCacheEntry(rawEntry);
480
+ if (entry) entries[key] = entry;
481
+ }
482
+ return { version: CACHE_VERSION, entries };
483
+ }
455
484
 
456
- let merged: NpxCache = { version: CACHE_VERSION, entries: {} };
485
+ function clearLegacyCache(): boolean {
486
+ const cachePath = getNpxCachePath();
487
+ const raw = asRecord(readNpxCachePayload(cachePath));
488
+ if (raw?.version !== 1) return false;
457
489
  try {
458
- if (existsSync(cachePath)) {
459
- const existing = JSON.parse(readFileSync(cachePath, "utf-8")) as NpxCache;
460
- if (existing && existing.version === CACHE_VERSION && existing.entries) {
461
- merged.entries = { ...existing.entries };
462
- }
463
- }
490
+ unlinkSync(cachePath);
464
491
  } catch {
465
- // Ignore parse errors
492
+ try {
493
+ writeFileSync(cachePath, "", "utf-8");
494
+ } catch {
495
+ // Cache cleanup is best effort; resolution must still proceed.
496
+ }
466
497
  }
498
+ return true;
499
+ }
467
500
 
468
- merged.entries[key] = entry;
469
- const tmpPath = `${cachePath}.${process.pid}.tmp`;
470
- writeFileSync(tmpPath, JSON.stringify(merged, null, 2), "utf-8");
471
- renameSync(tmpPath, cachePath);
501
+ clearLegacyCache();
502
+
503
+ function loadCache(): NpxCache | null {
504
+ if (clearLegacyCache()) return null;
505
+
506
+ return toNpxCache(readNpxCachePayload(getNpxCachePath()));
507
+ }
508
+
509
+ function saveCacheEntry(key: string, entry: NpxCacheEntry): void {
510
+ try {
511
+ const cachePath = getNpxCachePath();
512
+ const dir = dirname(cachePath);
513
+ mkdirSync(dir, { recursive: true });
514
+
515
+ const existing = toNpxCache(readNpxCachePayload(cachePath));
516
+ const entries = createCacheEntries();
517
+ if (existing) Object.assign(entries, existing.entries);
518
+ const merged: NpxCache = { version: CACHE_VERSION, entries };
519
+
520
+ merged.entries[key] = entry;
521
+ const tmpPath = `${cachePath}.${process.pid}.tmp`;
522
+ writeFileSync(tmpPath, JSON.stringify(merged, null, 2), "utf-8");
523
+ renameSync(tmpPath, cachePath);
524
+ } catch {
525
+ // Cache writes are best effort; resolution must still proceed.
526
+ }
472
527
  }
473
528
 
474
529
  function safeRealpath(path: string): string {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mcp-adapter",
3
- "version": "2.23.0",
3
+ "version": "2.26.0",
4
4
  "description": "MCP (Model Context Protocol) adapter extension for Pi coding agent",
5
5
  "type": "module",
6
6
  "types": "./index.ts",
@@ -34,8 +34,8 @@
34
34
  "test": "vitest run",
35
35
  "test:watch": "vitest",
36
36
  "test:coverage": "vitest run --coverage",
37
- "test:oauth": "PI_MCP_ADAPTER_TEST_AUTH_STORE=memory node --import tsx --test --test-concurrency=1 oauth-public-api.test.ts mcp-auth.test.ts mcp-auth-flow.test.ts mcp-callback-server.test.ts mcp-oauth-provider.test.ts",
38
- "test:oauth-provider": "PI_MCP_ADAPTER_TEST_AUTH_STORE=memory node --import tsx --test mcp-oauth-provider.test.ts",
37
+ "test:oauth": "PI_MCP_ADAPTER_TEST_AUTH_STORE=memory PI_MCP_ADAPTER_DISABLE_AUTH_CACHE=1 node --import tsx --test --test-concurrency=1 oauth-public-api.test.ts mcp-auth.test.ts mcp-auth-flow.test.ts mcp-callback-server.test.ts mcp-oauth-provider.test.ts",
38
+ "test:oauth-provider": "PI_MCP_ADAPTER_TEST_AUTH_STORE=memory PI_MCP_ADAPTER_DISABLE_AUTH_CACHE=1 node --import tsx --test mcp-oauth-provider.test.ts",
39
39
  "test:conformance": "bash conformance/run.sh"
40
40
  },
41
41
  "repository": {
@@ -89,6 +89,7 @@
89
89
  "ui-app-bridge-helpers.ts",
90
90
  "config.ts",
91
91
  "server-manager.ts",
92
+ "request-headers-command.ts",
92
93
  "unix-socket-transport.ts",
93
94
  "json-schema-validator.ts",
94
95
  "session-recovery.ts",
@@ -16,7 +16,7 @@ import { maybeStartUiSession, summarizeUiSessionResult, type UiSessionRuntime }
16
16
  import { formatAuthRequiredMessage, formatMcpStatus, resolveServerUrl, truncateAtWord } from "./utils.ts";
17
17
  import { authenticate, completeAuthFromInput, startAuth, supportsOAuth } from "./mcp-auth-flow.ts";
18
18
  import { SessionRecoveryAuthRequiredError, withSessionRecovery } from "./session-recovery.ts";
19
- import { paginate, rankSuggestions, rankToolMatches } from "./search-ranking.ts";
19
+ import { paginate, rankSuggestions, rankToolMatches, resolveSearchKeywords } from "./search-ranking.ts";
20
20
  import { ensureToolCallApproved, isToolCallApprovalRequired } from "./tool-approval.ts";
21
21
 
22
22
  type ProxyToolResult = AgentToolResult<Record<string, unknown>>;
@@ -37,6 +37,36 @@ type AutoAuthResult =
37
37
  | { status: "success" }
38
38
  | { status: "failed"; message: string };
39
39
 
40
+ function getToolMatches(metadata: ToolMetadata[] | undefined, toolName: string, exact: boolean): ToolMetadata[] {
41
+ if (!metadata) return [];
42
+ if (exact) return metadata.filter(tool => tool.name === toolName);
43
+ const normalizedName = toolName.replace(/-/g, "_");
44
+ return metadata.filter(tool => tool.name.replace(/-/g, "_") === normalizedName);
45
+ }
46
+
47
+ function getEnabledToolMatches(state: McpExtensionState, toolName: string, exact: boolean): { server: string; tool: ToolMetadata }[] {
48
+ const matches: { server: string; tool: ToolMetadata }[] = [];
49
+ for (const [server, metadata] of state.toolMetadata) {
50
+ if (isServerDisabled(state.config.mcpServers[server])) continue;
51
+ for (const tool of getToolMatches(metadata, toolName, exact)) matches.push({ server, tool });
52
+ }
53
+ return matches;
54
+ }
55
+
56
+ function getSingleToolMatch(metadata: ToolMetadata[] | undefined, toolName: string): ToolMetadata | "ambiguous" | undefined {
57
+ const exactMatches = getToolMatches(metadata, toolName, true);
58
+ const matches = exactMatches.length > 0 ? exactMatches : getToolMatches(metadata, toolName, false);
59
+ return matches.length > 1 ? "ambiguous" : matches[0];
60
+ }
61
+
62
+ function ambiguousToolResult(mode: "call" | "describe", toolName: string): ProxyToolResult {
63
+ const message = `Tool "${toolName}" matches multiple servers. Specify a server.`;
64
+ return {
65
+ content: [{ type: "text" as const, text: message }],
66
+ details: { mode, error: "ambiguous_tool", requestedTool: toolName, message },
67
+ };
68
+ }
69
+
40
70
  function disabledResult(mode: string, serverName: string): ProxyToolResult {
41
71
  const message = `Server "${serverName}" is disabled. Run /mcp enable ${serverName} and /reload to enable it.`;
42
72
  return {
@@ -404,20 +434,28 @@ export async function executeAuthComplete(state: McpExtensionState, serverName:
404
434
  }
405
435
 
406
436
  export function executeDescribe(state: McpExtensionState, toolName: string): ProxyToolResult {
407
- let serverName: string | undefined;
408
- let toolMeta: ToolMetadata | undefined;
437
+ const exactMatches = getEnabledToolMatches(state, toolName, true);
438
+ if (exactMatches.length > 1) return ambiguousToolResult("describe", toolName);
439
+ if (exactMatches.length === 0 && getEnabledToolMatches(state, toolName, false).length > 1) {
440
+ return ambiguousToolResult("describe", toolName);
441
+ }
442
+
443
+ let serverName = exactMatches[0]?.server;
444
+ let toolMeta = exactMatches[0]?.tool;
409
445
  let disabledMatch: string | undefined;
410
446
 
411
- for (const [server, metadata] of state.toolMetadata.entries()) {
412
- const found = findToolByName(metadata, toolName);
413
- if (!found) continue;
414
- if (isServerDisabled(state.config.mcpServers[server])) {
415
- disabledMatch ??= server;
416
- continue;
447
+ if (!toolMeta) {
448
+ for (const [server, metadata] of state.toolMetadata.entries()) {
449
+ const found = findToolByName(metadata, toolName);
450
+ if (!found) continue;
451
+ if (isServerDisabled(state.config.mcpServers[server])) {
452
+ disabledMatch ??= server;
453
+ continue;
454
+ }
455
+ serverName = server;
456
+ toolMeta = found;
457
+ break;
417
458
  }
418
- serverName = server;
419
- toolMeta = found;
420
- break;
421
459
  }
422
460
 
423
461
  if (!serverName || !toolMeta) {
@@ -430,7 +468,7 @@ export function executeDescribe(state: McpExtensionState, toolName: string): Pro
430
468
  };
431
469
  }
432
470
 
433
- const approvalMarker = isToolCallApprovalRequired(state.config, serverName, toolMeta)
471
+ const approvalMarker = isToolCallApprovalRequired(state.config, serverName, toolMeta, state.toolMetadata)
434
472
  ? " (requires approval)"
435
473
  : "";
436
474
  let text = `${toolMeta.name}${approvalMarker}\n`;
@@ -503,11 +541,15 @@ export function executeSearch(
503
541
  }
504
542
 
505
543
  matches = [];
544
+ const globalPrefix = state.config.settings?.toolPrefix ?? "server";
506
545
  for (const [serverName, metadata] of state.toolMetadata.entries()) {
507
- if (isServerDisabled(state.config.mcpServers[serverName])) continue;
546
+ const definition = state.config.mcpServers[serverName];
547
+ if (isServerDisabled(definition)) continue;
508
548
  if (server && serverName !== server) continue;
509
549
  for (const tool of metadata) {
510
- if (pattern.test(tool.name) || pattern.test(tool.description)) matches.push({ server: serverName, tool, score: 0 });
550
+ const matched = pattern.test(tool.name) || pattern.test(tool.description)
551
+ || resolveSearchKeywords(definition, tool.originalName, serverName, globalPrefix).some(keyword => pattern.test(keyword));
552
+ if (matched) matches.push({ server: serverName, tool, score: 0 });
511
553
  }
512
554
  }
513
555
  } else if (query.trim().length === 0) {
@@ -553,7 +595,7 @@ export function executeSearch(
553
595
 
554
596
  let text = `Found ${page.total} tool${page.total === 1 ? "" : "s"} matching "${query}":\n\n`;
555
597
  for (const match of page.items) {
556
- const approvalMarker = isToolCallApprovalRequired(state.config, match.server, match.tool)
598
+ const approvalMarker = isToolCallApprovalRequired(state.config, match.server, match.tool, state.toolMetadata)
557
599
  ? " (requires approval)"
558
600
  : "";
559
601
  if (showSchemas) {
@@ -733,7 +775,7 @@ export async function executeConnect(state: McpExtensionState, serverName: strin
733
775
  }
734
776
  }
735
777
  const prefix = state.config.settings?.toolPrefix ?? "server";
736
- const { metadata } = buildToolMetadata(connection.tools, connection.resources, definition, serverName, prefix);
778
+ const { metadata } = buildToolMetadata(connection.tools, connection.resources, definition, serverName, prefix, state.config.mcpServers, state.toolMetadata);
737
779
  state.toolMetadata.set(serverName, metadata);
738
780
  if (!connection.promptDiscoveryFailed) {
739
781
  state.promptMetadata?.set(serverName, reconstructPromptMetadata(serverName, connection.prompts ?? [], prefix, definition));
@@ -801,14 +843,22 @@ export async function executeCall(
801
843
  };
802
844
  }
803
845
  if (serverName) {
804
- toolMeta = findToolByName(state.toolMetadata.get(serverName), toolName);
846
+ const match = getSingleToolMatch(state.toolMetadata.get(serverName), toolName);
847
+ if (match === "ambiguous") return ambiguousToolResult("call", toolName);
848
+ toolMeta = match;
805
849
  if (isServerDisabled(state.config.mcpServers[serverName])) {
806
850
  return disabledCallResult(serverName, toolMeta);
807
851
  }
808
852
  } else {
853
+ const exactMatches = getEnabledToolMatches(state, toolName, true);
854
+ if (exactMatches.length > 1) return ambiguousToolResult("call", toolName);
855
+ if (exactMatches.length === 0 && getEnabledToolMatches(state, toolName, false).length > 1) {
856
+ return ambiguousToolResult("call", toolName);
857
+ }
858
+
809
859
  let disabledMatch: { serverName: string; toolMeta: ToolMetadata } | undefined;
810
860
  for (const [server, metadata] of state.toolMetadata.entries()) {
811
- const found = findToolByName(metadata, toolName);
861
+ const found = metadata.find(tool => tool.name === toolName);
812
862
  if (!found) continue;
813
863
  if (isServerDisabled(state.config.mcpServers[server])) {
814
864
  disabledMatch ??= { serverName: server, toolMeta: found };
@@ -818,13 +868,28 @@ export async function executeCall(
818
868
  toolMeta = found;
819
869
  break;
820
870
  }
871
+ if (!toolMeta && !disabledMatch) {
872
+ for (const [server, metadata] of state.toolMetadata.entries()) {
873
+ const found = findToolByName(metadata, toolName);
874
+ if (!found) continue;
875
+ if (isServerDisabled(state.config.mcpServers[server])) {
876
+ disabledMatch ??= { serverName: server, toolMeta: found };
877
+ continue;
878
+ }
879
+ serverName = server;
880
+ toolMeta = found;
881
+ break;
882
+ }
883
+ }
821
884
  if (!toolMeta && disabledMatch) return disabledCallResult(disabledMatch.serverName, disabledMatch.toolMeta);
822
885
  }
823
886
 
824
887
  if (serverName && !toolMeta) {
825
888
  const connected = await lazyConnect(state, serverName, ownedSignal);
826
889
  if (connected) {
827
- toolMeta = findToolByName(state.toolMetadata.get(serverName), toolName);
890
+ const match = getSingleToolMatch(state.toolMetadata.get(serverName), toolName);
891
+ if (match === "ambiguous") return ambiguousToolResult("call", toolName);
892
+ toolMeta = match;
828
893
  } else {
829
894
  const needsAuthConnection = state.manager.getConnection(serverName);
830
895
  if (needsAuthConnection?.status === "needs-auth") {
@@ -842,7 +907,9 @@ export async function executeCall(
842
907
  clearFailure(state, serverName);
843
908
  const connectedAfterAuth = await lazyConnect(state, serverName, ownedSignal);
844
909
  if (connectedAfterAuth) {
845
- toolMeta = findToolByName(state.toolMetadata.get(serverName), toolName);
910
+ const match = getSingleToolMatch(state.toolMetadata.get(serverName), toolName);
911
+ if (match === "ambiguous") return ambiguousToolResult("call", toolName);
912
+ toolMeta = match;
846
913
  if (!toolMeta) {
847
914
  const suggestions = rankSuggestions(state, toolName, 5);
848
915
  const suggestionText = suggestions.length > 0 ? ` Did you mean: ${suggestions.join(", ")}` : "";
@@ -879,6 +946,8 @@ export async function executeCall(
879
946
  let prefixMatchedServer: string | undefined;
880
947
 
881
948
  if (!serverName && !toolMeta && prefixMode !== "none") {
949
+ const lazyExactMatches: { serverName: string; toolMeta: ToolMetadata }[] = [];
950
+ const lazyFallbackMatches: { serverName: string; toolMeta: ToolMetadata }[] = [];
882
951
  const candidates = Object.keys(state.config.mcpServers)
883
952
  .filter(name => !isServerDisabled(state.config.mcpServers[name]))
884
953
  .map(name => ({ name, prefix: getServerPrefix(name, prefixMode) }))
@@ -909,11 +978,22 @@ export async function executeCall(
909
978
 
910
979
  if (!connected) continue;
911
980
  if (!prefixMatchedServer) prefixMatchedServer = configuredServer;
912
- toolMeta = findToolByName(state.toolMetadata.get(configuredServer), toolName);
913
- if (toolMeta) {
914
- serverName = configuredServer;
915
- break;
981
+ const metadata = state.toolMetadata.get(configuredServer);
982
+ const exactMatches = getToolMatches(metadata, toolName, true);
983
+ if (exactMatches.length > 1) return ambiguousToolResult("call", toolName);
984
+ if (exactMatches.length === 1) {
985
+ lazyExactMatches.push({ serverName: configuredServer, toolMeta: exactMatches[0]! });
986
+ continue;
916
987
  }
988
+ const fallbackMatches = getToolMatches(metadata, toolName, false);
989
+ if (fallbackMatches.length > 1) return ambiguousToolResult("call", toolName);
990
+ if (fallbackMatches.length === 1) lazyFallbackMatches.push({ serverName: configuredServer, toolMeta: fallbackMatches[0]! });
991
+ }
992
+ const lazyMatches = lazyExactMatches.length > 0 ? lazyExactMatches : lazyFallbackMatches;
993
+ if (lazyMatches.length > 1) return ambiguousToolResult("call", toolName);
994
+ if (lazyMatches.length === 1) {
995
+ serverName = lazyMatches[0]!.serverName;
996
+ toolMeta = lazyMatches[0]!.toolMeta;
917
997
  }
918
998
  }
919
999
 
@@ -1026,7 +1106,9 @@ export async function executeCall(
1026
1106
  notifyToolMetadataUpdated(state, serverName, "proxy-call-reconnect");
1027
1107
  markKeepAliveAfterConnect(state, serverName);
1028
1108
  updateStatusBar(state);
1029
- toolMeta = findToolByName(state.toolMetadata.get(serverName), toolName);
1109
+ const match = getSingleToolMatch(state.toolMetadata.get(serverName), toolName);
1110
+ if (match === "ambiguous") return ambiguousToolResult("call", toolName);
1111
+ toolMeta = match;
1030
1112
  if (!toolMeta) {
1031
1113
  const available = getToolNames(state, serverName);
1032
1114
  const hint = available.length > 0