@herbertgao/pi-extensions 2026.8.5 → 2026.8.7

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 (389) hide show
  1. package/README.md +5 -5
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +272 -22
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +48 -6
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
  17. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  18. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +16 -0
  19. package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
  20. package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
  21. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  22. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
  23. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
  24. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +22 -15
  25. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
  26. package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
  27. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
  28. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
  29. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
  30. package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
  31. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
  32. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
  33. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +34 -10
  34. package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
  35. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +29 -5
  36. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +3 -0
  37. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +46 -10
  38. package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +8 -1
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
  43. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
  44. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
  46. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  49. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
  50. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
  51. package/node_modules/@narumitw/pi-btw/README.md +119 -103
  52. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  53. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  54. package/node_modules/@narumitw/pi-btw/package.json +13 -9
  55. package/node_modules/@narumitw/pi-btw/src/btw.ts +40 -42
  56. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  57. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  58. package/node_modules/@narumitw/pi-btw/src/menu.ts +78 -15
  59. package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
  60. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  61. package/node_modules/pi-lens/CHANGELOG.md +1004 -0
  62. package/node_modules/pi-lens/README.md +11 -3
  63. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  64. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  65. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +427 -0
  66. package/node_modules/pi-lens/dist/clients/agent-nudge.js +79 -16
  67. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  68. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  69. package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
  70. package/node_modules/pi-lens/dist/clients/biome-client.js +176 -37
  71. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  72. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
  73. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  74. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  75. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
  76. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
  77. package/node_modules/pi-lens/dist/clients/bus-publish.js +11 -3
  78. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  79. package/node_modules/pi-lens/dist/clients/cascade-format.js +76 -2
  80. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  81. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  82. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  83. package/node_modules/pi-lens/dist/clients/console-guard-install.js +16 -4
  84. package/node_modules/pi-lens/dist/clients/dead-code-client.js +249 -52
  85. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  86. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  87. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
  88. package/node_modules/pi-lens/dist/clients/dependency-checker.js +43 -9
  89. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +153 -37
  90. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  91. package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
  92. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +165 -11
  93. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +325 -72
  94. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  95. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +81 -41
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +488 -0
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +84 -0
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  122. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +943 -93
  123. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  124. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
  125. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +106 -0
  126. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
  127. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
  128. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  129. package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
  130. package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
  131. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  132. package/node_modules/pi-lens/dist/clients/extension-log.js +317 -3
  133. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  134. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
  135. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  136. package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
  137. package/node_modules/pi-lens/dist/clients/format-events-publish.js +39 -8
  138. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  139. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  140. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  141. package/node_modules/pi-lens/dist/clients/git-guard.js +49 -21
  142. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  143. package/node_modules/pi-lens/dist/clients/go-client.js +21 -39
  144. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +219 -10
  145. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  146. package/node_modules/pi-lens/dist/clients/host-ports.js +9 -1
  147. package/node_modules/pi-lens/dist/clients/installer/index.js +1119 -101
  148. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  149. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  150. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  151. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  152. package/node_modules/pi-lens/dist/clients/jscpd-client.js +86 -15
  153. package/node_modules/pi-lens/dist/clients/knip-client.js +361 -24
  154. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  155. package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
  156. package/node_modules/pi-lens/dist/clients/latency-logger.js +487 -9
  157. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  158. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  159. package/node_modules/pi-lens/dist/clients/lens-events.js +56 -25
  160. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
  161. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +45 -2
  162. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
  163. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +160 -20
  164. package/node_modules/pi-lens/dist/clients/lsp/client.js +1666 -148
  165. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +111 -0
  166. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  167. package/node_modules/pi-lens/dist/clients/lsp/index.js +2496 -171
  168. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  169. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  170. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  171. package/node_modules/pi-lens/dist/clients/lsp/server.js +517 -69
  172. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  173. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  174. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +172 -0
  175. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
  176. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +61 -3
  177. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  178. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  179. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  180. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  181. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +4 -0
  182. package/node_modules/pi-lens/dist/clients/mcp/session.js +39 -18
  183. package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
  184. package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
  185. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  186. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  187. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  188. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  189. package/node_modules/pi-lens/dist/clients/pipeline.js +178 -30
  190. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  191. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  192. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  193. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +85 -15
  194. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  195. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
  196. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  197. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
  198. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  199. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  200. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  201. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  202. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
  203. package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
  204. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  205. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  206. package/node_modules/pi-lens/dist/clients/review-graph/query.js +76 -4
  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 +248 -13
  209. package/node_modules/pi-lens/dist/clients/runtime-context.js +112 -12
  210. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +472 -61
  211. package/node_modules/pi-lens/dist/clients/runtime-session.js +359 -13
  212. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  213. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +269 -22
  214. package/node_modules/pi-lens/dist/clients/runtime-turn.js +948 -87
  215. package/node_modules/pi-lens/dist/clients/rust-client.js +21 -37
  216. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  217. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  218. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  219. package/node_modules/pi-lens/dist/clients/security-scan-client.js +224 -8
  220. package/node_modules/pi-lens/dist/clients/sg-runner.js +249 -37
  221. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  222. package/node_modules/pi-lens/dist/clients/smells-rollup.js +18 -11
  223. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  224. package/node_modules/pi-lens/dist/clients/startup-timing.js +26 -2
  225. package/node_modules/pi-lens/dist/clients/test-runner-client.js +574 -32
  226. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  227. package/node_modules/pi-lens/dist/clients/tool-policy.js +127 -20
  228. package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
  229. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  230. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  231. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  232. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  233. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  234. package/node_modules/pi-lens/dist/clients/warm-attach.js +17 -0
  235. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  236. package/node_modules/pi-lens/dist/clients/word-index.js +305 -33
  237. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  238. package/node_modules/pi-lens/dist/index.js +64677 -49484
  239. package/node_modules/pi-lens/dist/mcp/server.js +8 -2
  240. package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
  241. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
  242. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
  243. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +469 -56
  244. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +190 -46
  245. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  246. package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
  247. package/node_modules/pi-lens/docs/agent-guide.md +44 -14
  248. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +518 -501
  249. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  250. package/node_modules/pi-lens/docs/features.md +33 -6
  251. package/node_modules/pi-lens/docs/globalconfig.md +14 -0
  252. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  253. package/node_modules/pi-lens/docs/mcp.md +2 -2
  254. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  255. package/node_modules/pi-lens/docs/settings.md +25 -1
  256. package/node_modules/pi-lens/docs/usage.md +24 -5
  257. package/node_modules/pi-lens/docs/word-index.md +35 -0
  258. package/node_modules/pi-lens/package.json +10 -6
  259. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  260. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  261. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  262. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  263. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +22 -0
  264. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
  265. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +9 -0
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +9 -0
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +9 -0
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +9 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  288. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  289. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  290. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  291. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  292. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  293. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  294. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +66 -0
  295. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  296. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
  297. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
  298. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  299. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  300. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  301. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  302. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  303. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  304. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +29 -0
  305. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +30 -0
  306. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +41 -0
  307. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +42 -0
  308. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  309. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  310. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  311. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  312. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  313. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  314. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +32 -0
  315. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  316. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  317. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  318. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  319. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  320. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  321. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  322. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  323. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  324. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +132 -1
  325. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  326. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  327. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +12 -11
  328. package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
  329. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +87 -116
  330. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +170 -0
  331. package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
  332. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  333. package/node_modules/pi-mcp-adapter/CHANGELOG.md +49 -0
  334. package/node_modules/pi-mcp-adapter/README.md +51 -6
  335. package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
  336. package/node_modules/pi-mcp-adapter/cli.js +188 -5
  337. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  338. package/node_modules/pi-mcp-adapter/config.ts +28 -10
  339. package/node_modules/pi-mcp-adapter/direct-tools.ts +23 -19
  340. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  341. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  342. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  343. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  344. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  345. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  346. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  347. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  348. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
  349. package/node_modules/pi-mcp-adapter/metadata-cache.ts +46 -25
  350. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  351. package/node_modules/pi-mcp-adapter/package.json +4 -1
  352. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  353. package/node_modules/pi-mcp-adapter/request-headers-command.ts +330 -0
  354. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  355. package/node_modules/pi-mcp-adapter/server-manager.ts +145 -2
  356. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  357. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  358. package/node_modules/pi-mcp-adapter/tool-metadata.ts +38 -18
  359. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  360. package/node_modules/pi-mcp-adapter/types.ts +95 -10
  361. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  362. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  363. package/node_modules/pi-web-access/CHANGELOG.md +37 -0
  364. package/node_modules/pi-web-access/README.md +38 -14
  365. package/node_modules/pi-web-access/anysearch.ts +4 -2
  366. package/node_modules/pi-web-access/auth-fetch.ts +148 -0
  367. package/node_modules/pi-web-access/brave.ts +16 -4
  368. package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
  369. package/node_modules/pi-web-access/curator-page.ts +8 -3
  370. package/node_modules/pi-web-access/curator-server.ts +5 -1
  371. package/node_modules/pi-web-access/exa.ts +18 -7
  372. package/node_modules/pi-web-access/extract.ts +134 -37
  373. package/node_modules/pi-web-access/fetch-params.ts +17 -3
  374. package/node_modules/pi-web-access/firecrawl.ts +172 -12
  375. package/node_modules/pi-web-access/gemini-search.ts +33 -7
  376. package/node_modules/pi-web-access/index.ts +160 -104
  377. package/node_modules/pi-web-access/package.json +2 -2
  378. package/node_modules/pi-web-access/page-query.ts +4 -2
  379. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  380. package/node_modules/pi-web-access/parallel.ts +2 -2
  381. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  382. package/node_modules/pi-web-access/serper.ts +211 -0
  383. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  384. package/node_modules/pi-web-access/summary-review.ts +51 -23
  385. package/node_modules/pi-web-access/tavily.ts +16 -4
  386. package/node_modules/pi-web-access/utils.ts +87 -0
  387. package/node_modules/pi-web-access/valyu.ts +199 -0
  388. package/node_modules/pi-web-access/youtube-extract.ts +2 -2
  389. package/package.json +13 -13
@@ -1,12 +1,16 @@
1
1
  import { mkdirSync } from "node:fs";
2
+ import { isDeepStrictEqual } from "node:util";
2
3
  import {
3
4
  Client,
5
+ SdkError,
6
+ SdkErrorCode,
4
7
  SdkHttpError,
5
8
  SSEClientTransport,
6
9
  StreamableHTTPClientTransport,
7
10
  UnauthorizedError,
8
11
  type GetPromptResult,
9
12
  type ReadResourceResult,
13
+ type CacheableRequestOptions,
10
14
  type RequestOptions,
11
15
  type UrlElicitationRequiredError,
12
16
  type VersionNegotiationOptions,
@@ -32,6 +36,7 @@ import { logger } from "./logger.ts";
32
36
  import { McpOAuthProvider } from "./mcp-oauth-provider.ts";
33
37
  import { extractOAuthConfig, supportsOAuth, type McpOAuthRuntime } from "./mcp-auth-flow.ts";
34
38
  import { invalidateAuthEntryCache, type AuthStorageOptions } from "./mcp-auth.ts";
39
+ import { getBearerTokenForUrl } from "./mcp-bearer-store.ts";
35
40
  import { registerSamplingHandler, type ServerSamplingConfig } from "./sampling-handler.ts";
36
41
  import {
37
42
  handleUrlElicitation,
@@ -56,6 +61,7 @@ import {
56
61
  traceTransportKind,
57
62
  wrapTransportWithMcpTrace,
58
63
  } from "./mcp-trace.ts";
64
+ import { createRequestHeadersCommandFetch } from "./request-headers-command.ts";
59
65
 
60
66
  const MAX_CAPTURED_STDERR_BYTES = 8 * 1024;
61
67
  const MAX_CAPTURED_STDERR_LINES = 3;
@@ -122,6 +128,8 @@ export interface ServerConnection {
122
128
  transport: Transport;
123
129
  definition: ServerDefinition;
124
130
  tools: McpTool[];
131
+ /** Monotonic guard against older refresh responses replacing newer notifications. */
132
+ toolsRevision?: number;
125
133
  resources: McpResource[];
126
134
  prompts: McpPrompt[];
127
135
  /** True when prompts were advertised but prompts/list failed. */
@@ -138,6 +146,10 @@ export interface ServerConnection {
138
146
  type UiStreamListener = (serverName: string, notification: ServerStreamResultPatchNotification["params"]) => void;
139
147
  type MetadataListChangedListener = (serverName: string, reason: string) => void;
140
148
 
149
+ export type ToolRefreshResult = "updated" | "unchanged" | "superseded" | "refresh-timeout";
150
+
151
+ const KEEP_ALIVE_REFRESH_TIMEOUT_MS = 5_000;
152
+
141
153
  export class McpServerManager {
142
154
  private connections = new Map<string, ServerConnection>();
143
155
  private connectPromises = new Map<string, Promise<ServerConnection>>();
@@ -145,6 +157,10 @@ export class McpServerManager {
145
157
  private uiStreamListeners = new Map<string, UiStreamListener>();
146
158
  private samplingConfig: ServerSamplingConfig | undefined;
147
159
  private metadataListChangedListener: MetadataListChangedListener | undefined;
160
+ private pendingMetadataPublications = new Map<
161
+ string,
162
+ { connection: ServerConnection; reason: string }
163
+ >();
148
164
  private elicitationConfig: ServerElicitationConfig | undefined;
149
165
  private authStorageOptions: AuthStorageOptions = {};
150
166
  private oauthRuntime: McpOAuthRuntime | undefined;
@@ -169,6 +185,25 @@ export class McpServerManager {
169
185
  this.metadataListChangedListener = listener;
170
186
  }
171
187
 
188
+ publishMetadataChanged(
189
+ name: string,
190
+ expectedConnection: ServerConnection,
191
+ reason: string,
192
+ ): boolean {
193
+ const current = this.connections.get(name);
194
+ if (current !== expectedConnection || current.status !== "connected") return false;
195
+ try {
196
+ this.metadataListChangedListener?.(name, reason);
197
+ this.pendingMetadataPublications.delete(name);
198
+ return true;
199
+ } catch (error) {
200
+ this.pendingMetadataPublications.set(name, { connection: expectedConnection, reason });
201
+ const message = error instanceof Error ? error.message : String(error);
202
+ logger.debug(`MCP: metadata publication failed for ${name}; queued for retry: ${message}`);
203
+ return false;
204
+ }
205
+ }
206
+
172
207
  setElicitationConfig(config: ServerElicitationConfig | undefined): void {
173
208
  this.elicitationConfig = config;
174
209
  }
@@ -302,6 +337,100 @@ export class McpServerManager {
302
337
  return abortable(promise, ownedSignal);
303
338
  }
304
339
 
340
+ /**
341
+ * Fetch the authoritative tool catalog for a connection that still appears
342
+ * connected. The SDK response cache is explicitly bypassed so this request
343
+ * also proves the remote Streamable HTTP session is usable. Results are
344
+ * identity-guarded: a late response from a replaced connection is ignored.
345
+ */
346
+ async refreshTools(
347
+ name: string,
348
+ expectedConnection: ServerConnection,
349
+ signal?: AbortSignal,
350
+ ): Promise<ToolRefreshResult> {
351
+ if (this.stopped) throw new Error("MCP server manager is closed");
352
+ const ownedSignal = combineAbortSignals(this.runtimeSignal, signal);
353
+ throwIfAborted(ownedSignal);
354
+
355
+ const current = this.connections.get(name);
356
+ if (current !== expectedConnection || current.status !== "connected") {
357
+ return "superseded";
358
+ }
359
+
360
+ const requestOptions = this.buildRequestOptions(expectedConnection.definition, signal);
361
+ const timeout = Math.min(requestOptions?.timeout ?? KEEP_ALIVE_REFRESH_TIMEOUT_MS, KEEP_ALIVE_REFRESH_TIMEOUT_MS);
362
+ const healthOptions = {
363
+ ...requestOptions,
364
+ timeout,
365
+ };
366
+ if (!expectedConnection.client.getServerCapabilities?.()?.tools) {
367
+ await expectedConnection.client.ping(healthOptions);
368
+ throwIfAborted(ownedSignal);
369
+ if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
370
+ return "superseded";
371
+ }
372
+ this.retryPendingMetadataPublication(name, expectedConnection);
373
+ return "unchanged";
374
+ }
375
+
376
+ const toolsRevision = expectedConnection.toolsRevision ?? 0;
377
+ const refreshSignal = combineAbortSignals(healthOptions.signal, AbortSignal.timeout(timeout));
378
+ let tools: McpTool[];
379
+ try {
380
+ tools = await this.fetchAllTools(expectedConnection.client, {
381
+ ...healthOptions,
382
+ ...(refreshSignal ? { signal: refreshSignal } : {}),
383
+ cacheMode: "refresh",
384
+ });
385
+ } catch (error) {
386
+ throwIfAborted(ownedSignal);
387
+ if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
388
+ return "superseded";
389
+ }
390
+ if (error instanceof SdkError && error.code === SdkErrorCode.RequestTimeout) {
391
+ return "refresh-timeout";
392
+ }
393
+ throw error;
394
+ }
395
+ throwIfAborted(ownedSignal);
396
+
397
+ if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
398
+ return "superseded";
399
+ }
400
+ if ((expectedConnection.toolsRevision ?? 0) !== toolsRevision) {
401
+ return "superseded";
402
+ }
403
+
404
+ if (isDeepStrictEqual(expectedConnection.tools, tools)) {
405
+ this.retryPendingMetadataPublication(name, expectedConnection);
406
+ return "unchanged";
407
+ }
408
+
409
+ const previousTools = expectedConnection.tools;
410
+ expectedConnection.tools = tools;
411
+ expectedConnection.toolsRevision = toolsRevision + 1;
412
+ try {
413
+ await this.metadataListChangedListener?.(name, "keep-alive-refresh");
414
+ this.pendingMetadataPublications.delete(name);
415
+ } catch (error) {
416
+ if (this.connections.get(name) === expectedConnection && expectedConnection.tools === tools) {
417
+ expectedConnection.tools = previousTools;
418
+ expectedConnection.toolsRevision = toolsRevision;
419
+ }
420
+ throw error;
421
+ }
422
+ return "updated";
423
+ }
424
+
425
+ private retryPendingMetadataPublication(name: string, connection: ServerConnection): void {
426
+ const pendingPublication = this.pendingMetadataPublications.get(name);
427
+ if (pendingPublication?.connection !== connection) return;
428
+ this.metadataListChangedListener?.(name, pendingPublication.reason);
429
+ if (this.pendingMetadataPublications.get(name) === pendingPublication) {
430
+ this.pendingMetadataPublications.delete(name);
431
+ }
432
+ }
433
+
305
434
  private async doReconnect(
306
435
  name: string,
307
436
  definition: ServerDefinition,
@@ -439,6 +568,7 @@ export class McpServerManager {
439
568
  transport,
440
569
  definition,
441
570
  tools: [],
571
+ toolsRevision: 0,
442
572
  resources: [],
443
573
  prompts: [],
444
574
  ...(instructions !== undefined ? { instructions } : {}),
@@ -640,7 +770,9 @@ export class McpServerManager {
640
770
  const connection = this.connections.get(serverName);
641
771
  if (!connection || connection.client !== client || connection.status !== "connected") return;
642
772
  connection.tools = tools;
773
+ connection.toolsRevision = (connection.toolsRevision ?? 0) + 1;
643
774
  this.metadataListChangedListener?.(serverName, "tools-list-changed");
775
+ this.pendingMetadataPublications.delete(serverName);
644
776
  }
645
777
 
646
778
  private handlePromptsListChanged(
@@ -659,6 +791,7 @@ export class McpServerManager {
659
791
  connection.prompts = prompts;
660
792
  connection.promptDiscoveryFailed = false;
661
793
  this.metadataListChangedListener?.(serverName, "prompts-list-changed");
794
+ this.pendingMetadataPublications.delete(serverName);
662
795
  }
663
796
 
664
797
  private handleResourcesListChanged(
@@ -676,6 +809,7 @@ export class McpServerManager {
676
809
  if (!connection || connection.client !== client || connection.status !== "connected") return;
677
810
  connection.resources = resources;
678
811
  this.metadataListChangedListener?.(serverName, "resources-list-changed");
812
+ this.pendingMetadataPublications.delete(serverName);
679
813
  }
680
814
 
681
815
  async handleUrlElicitationRequired(
@@ -733,7 +867,10 @@ export class McpServerManager {
733
867
  if (definition.auth === "bearer") {
734
868
  const token = commandBearer
735
869
  ? resolveCommandSecret(commandBearer, `MCP server "${serverName}" HTTP bearer token`)
736
- : resolveBearerToken(definition);
870
+ : resolveBearerToken(definition)
871
+ ?? (definition.bearerToken === undefined && definition.bearerTokenEnv === undefined && definition.bearerTokenStore === true
872
+ ? getBearerTokenForUrl(serverName, serverUrl)
873
+ : undefined);
737
874
  if (token) headers["Authorization"] = `Bearer ${token}`;
738
875
  }
739
876
 
@@ -746,6 +883,9 @@ export class McpServerManager {
746
883
  }
747
884
 
748
885
  const requestInit = Object.keys(headers).length > 0 ? { headers } : undefined;
886
+ const requestFetch = definition.requestHeadersCommand
887
+ ? createRequestHeadersCommandFetch(definition.requestHeadersCommand)
888
+ : undefined;
749
889
  const createAuthProvider = (): McpOAuthProvider => new McpOAuthProvider(
750
890
  serverName,
751
891
  serverUrl,
@@ -772,6 +912,7 @@ export class McpServerManager {
772
912
  const authProvider = "provider" in authState ? authState.provider : undefined;
773
913
  const transportOptions = {
774
914
  ...(requestInit !== undefined ? { requestInit } : {}),
915
+ ...(requestFetch !== undefined ? { fetch: requestFetch } : {}),
775
916
  ...(authProvider !== undefined ? { authProvider } : {}),
776
917
  ...(authProvider !== undefined
777
918
  && definition.oauth !== false
@@ -846,7 +987,7 @@ export class McpServerManager {
846
987
  }
847
988
  }
848
989
 
849
- private async fetchAllTools(client: Client, requestOptions?: RequestOptions): Promise<McpTool[]> {
990
+ private async fetchAllTools(client: Client, requestOptions?: CacheableRequestOptions): Promise<McpTool[]> {
850
991
  const allTools: McpTool[] = [];
851
992
  let cursor: string | undefined;
852
993
 
@@ -974,6 +1115,7 @@ export class McpServerManager {
974
1115
  async close(name: string): Promise<void> {
975
1116
  this.closeGenerations.set(name, (this.closeGenerations.get(name) ?? 0) + 1);
976
1117
  this.connectAttempts.get(name)?.abort(new Error(`MCP connection ${name} was closed`));
1118
+ this.pendingMetadataPublications.delete(name);
977
1119
 
978
1120
  const connection = this.connections.get(name);
979
1121
  if (!connection) {
@@ -1037,6 +1179,7 @@ export class McpServerManager {
1037
1179
  .filter(error => this.containsCleanupFailure(error));
1038
1180
  this.uiStreamListeners.clear();
1039
1181
  this.acceptedUrlElicitations.clear();
1182
+ this.pendingMetadataPublications.clear();
1040
1183
  this.samplingConfig = undefined;
1041
1184
  this.elicitationConfig = undefined;
1042
1185
  await this.traceWriter?.flush();
@@ -146,6 +146,13 @@ export async function withSessionRecovery<T>(
146
146
  throw err;
147
147
  }
148
148
 
149
+ try {
150
+ deps.manager.publishMetadataChanged(serverName, freshConnection, "session-reconnect");
151
+ } catch (publicationError) {
152
+ const message = publicationError instanceof Error ? publicationError.message : String(publicationError);
153
+ logger.debug(`MCP metadata publication after reconnect failed for "${serverName}": ${message}`);
154
+ }
155
+ throwIfAborted(deps.signal);
149
156
  return fn(freshConnection);
150
157
  }
151
158
  }
@@ -1,4 +1,4 @@
1
- import { randomUUID } from "node:crypto";
1
+ import { createHash, randomUUID } from "node:crypto";
2
2
  import { abortable } from "./abort.ts";
3
3
  import { combineAbortSignals } from "./runtime-owner.ts";
4
4
  import type { McpExtensionState } from "./state.ts";
@@ -20,6 +20,18 @@ export type ToolCallApprovalResult =
20
20
  | { ok: true }
21
21
  | { ok: false; reason: "denied" | "approval_required_headless" };
22
22
 
23
+ function stableStringify(value: unknown): string {
24
+ if (value === null || value === undefined || typeof value !== "object") {
25
+ const serialized = JSON.stringify(value);
26
+ return serialized === undefined ? "undefined" : serialized;
27
+ }
28
+ if (Array.isArray(value)) {
29
+ return `[${value.map(item => stableStringify(item)).join(",")}]`;
30
+ }
31
+ const object = value as Record<string, unknown>;
32
+ return `{${Object.keys(object).sort().map(key => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
33
+ }
34
+
23
35
  export function isToolCallApprovalRequired(
24
36
  config: McpConfig,
25
37
  serverName: string,
@@ -136,7 +148,8 @@ export async function ensureToolCallApproved(
136
148
  origin: McpToolApprovalOrigin = toolMeta.resourceUri ? "resource" : "proxy",
137
149
  approvalMetadata?: ReadonlyMap<string, readonly ToolMetadata[]>,
138
150
  ): Promise<ToolCallApprovalResult> {
139
- const cacheKey = `${serverName}\u0000${toolMeta.originalName}`;
151
+ const argsHash = createHash("sha256").update(stableStringify(args ?? {})).digest("hex");
152
+ const cacheKey = `${serverName}\u0000${toolMeta.originalName}\u0000${argsHash}`;
140
153
  const approvedToolCalls = state.approvedToolCalls ??= new Map<string, true>();
141
154
  if (approvedToolCalls.has(cacheKey)) {
142
155
  return { ok: true };
@@ -1,7 +1,7 @@
1
1
  import { getToolUiResourceUri } from "./ui-app-bridge-helpers.ts";
2
2
  import type { McpExtensionState } from "./state.ts";
3
3
  import type { ToolMetadata, McpTool, McpResource, ServerEntry, ToolPrefix } from "./types.ts";
4
- import { formatToolName, getToolNameCandidates, isToolAllowed, resolveToolPrefix } from "./types.ts";
4
+ import { createToolSelectorCandidateIndex, formatToolName, getToolNameCandidates, isToolAllowed, resolveToolPrefix } from "./types.ts";
5
5
  import { resourceNameToToolName } from "./resource-tools.ts";
6
6
  import { extractToolUiStreamMode } from "./utils.ts";
7
7
  import { extractUiToolVisibility, isUiToolVisibleToModel } from "./ui-tool-visibility.ts";
@@ -20,48 +20,68 @@ export function buildToolMetadata(
20
20
  const failedTools: string[] = [];
21
21
  const seenNames = new Set<string>();
22
22
  const effectivePrefix = resolveToolPrefix(definition, prefix);
23
- const getOtherCurrentCandidates = (toolName: string): Set<string> | undefined => {
24
- if (!configuredServers) return undefined;
23
+ const hasToolFilters =
24
+ (Array.isArray(definition.includeTools) && definition.includeTools.length > 0) ||
25
+ (Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0);
26
+ const selectorCandidateIndex = hasToolFilters && configuredServers ? (() => {
25
27
  const candidates = new Set<string>();
26
- const addCandidates = (originalName: string, candidateServerName: string, candidatePrefix: ToolPrefix) => {
27
- for (const candidate of getToolNameCandidates(originalName, candidateServerName, candidatePrefix, false)) candidates.add(candidate);
28
+ const additionalCandidatesByToolName = new Map<string, Set<string>>();
29
+ const evaluatedToolNames = new Set<string>();
30
+ const addCandidates = (
31
+ target: Set<string>,
32
+ originalName: string,
33
+ candidateServerName: string,
34
+ candidatePrefix: ToolPrefix,
35
+ ) => {
36
+ for (const candidate of getToolNameCandidates(originalName, candidateServerName, candidatePrefix, false)) target.add(candidate);
28
37
  };
29
38
 
30
39
  for (const tool of tools) {
31
- if (tool?.name) addCandidates(tool.name, serverName, effectivePrefix);
40
+ if (!tool?.name) continue;
41
+ evaluatedToolNames.add(tool.name);
42
+ addCandidates(candidates, tool.name, serverName, effectivePrefix);
32
43
  }
33
44
  if (definition.exposeResources !== false) {
34
45
  for (const resource of resources) {
35
- if (resource?.name && resource?.uri) addCandidates(`read_${resourceNameToToolName(resource.name)}`, serverName, effectivePrefix);
46
+ const baseName = `read_${resourceNameToToolName(resource.name)}`;
47
+ evaluatedToolNames.add(baseName);
48
+ if (resource?.name && resource?.uri) addCandidates(candidates, baseName, serverName, effectivePrefix);
36
49
  }
37
50
  }
38
51
  for (const [otherServerName, otherDefinition] of Object.entries(configuredServers)) {
39
52
  if (otherServerName === serverName) continue;
53
+ const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
40
54
  const knownTools = knownMetadata?.get(otherServerName);
41
55
  if (knownTools) {
42
- const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
43
56
  for (const tool of knownTools) {
44
57
  candidates.add(tool.name);
45
- addCandidates(tool.originalName, otherServerName, otherPrefix);
58
+ addCandidates(candidates, tool.originalName, otherServerName, otherPrefix);
46
59
  }
47
60
  } else if (!knownMetadata || includeMissingConfiguredCandidates) {
48
- const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
49
- addCandidates(toolName, otherServerName, otherPrefix);
50
- if (includeMissingConfiguredCandidates) {
51
- for (const candidate of getToolNameCandidates(toolName, otherServerName, otherPrefix, false)) candidates.add(candidate.replace(/-/g, "_"));
61
+ for (const toolName of evaluatedToolNames) {
62
+ let additionalCandidates = additionalCandidatesByToolName.get(toolName);
63
+ if (!additionalCandidates) {
64
+ additionalCandidates = new Set<string>();
65
+ additionalCandidatesByToolName.set(toolName, additionalCandidates);
66
+ }
67
+ addCandidates(additionalCandidates, toolName, otherServerName, otherPrefix);
68
+ if (includeMissingConfiguredCandidates) {
69
+ for (const candidate of getToolNameCandidates(toolName, otherServerName, otherPrefix, false)) {
70
+ additionalCandidates.add(candidate.replace(/-/g, "_"));
71
+ }
72
+ }
52
73
  }
53
74
  }
54
75
  }
55
- for (const candidate of getToolNameCandidates(toolName, serverName, effectivePrefix, false)) candidates.delete(candidate);
56
- return candidates;
57
- };
76
+ return createToolSelectorCandidateIndex(candidates, additionalCandidatesByToolName);
77
+ })() : undefined;
58
78
 
59
79
  for (const tool of tools) {
60
80
  if (!tool?.name) {
61
81
  failedTools.push("(unnamed)");
62
82
  continue;
63
83
  }
64
- if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(tool.name))) {
84
+ if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) {
65
85
  continue;
66
86
  }
67
87
 
@@ -97,7 +117,7 @@ export function buildToolMetadata(
97
117
  if (definition.exposeResources !== false) {
98
118
  for (const resource of resources) {
99
119
  const baseName = `read_${resourceNameToToolName(resource.name)}`;
100
- if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, getOtherCurrentCandidates(baseName))) {
120
+ if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) {
101
121
  continue;
102
122
  }
103
123
 
@@ -25,6 +25,7 @@ export interface McpProxyToolCallInput {
25
25
 
26
26
  interface McpToolRenderState {
27
27
  compactTitle?: string;
28
+ compactInputPreview?: string;
28
29
  }
29
30
 
30
31
  interface McpToolRenderContext {
@@ -52,6 +53,7 @@ export interface McpToolResultDisplay {
52
53
  }
53
54
 
54
55
  const DEFAULT_MAX_CALL_INPUT_CHARS = 1500;
56
+ const DEFAULT_MAX_COMPACT_INPUT_CHARS = 240;
55
57
  const DEFAULT_BOXED_COLLAPSED_LINES = 3;
56
58
  const DEFAULT_COMPACT_COLLAPSED_LINES = 1;
57
59
  const DEFAULT_MAX_COLLAPSED_CHARS = 8000;
@@ -70,6 +72,7 @@ class CompactMcpToolResult implements Component {
70
72
 
71
73
  constructor(
72
74
  private readonly title: string,
75
+ private readonly inputPreview: string,
73
76
  private readonly display: McpToolResultDisplay,
74
77
  private readonly theme: RenderTheme,
75
78
  ) {}
@@ -83,7 +86,7 @@ class CompactMcpToolResult implements Component {
83
86
  });
84
87
  const lines = resultLines.length > 0 ? resultLines : [""];
85
88
  const bodies = lines.map((line, index) => {
86
- const prefix = index === 0 && this.title ? `${this.theme.fg("toolTitle", this.title)} → ` : "";
89
+ const prefix = index === 0 ? this.renderPrefix(safeWidth) : "";
87
90
  return `${prefix}${this.theme.fg("toolOutput", line)}`;
88
91
  });
89
92
  const hiddenText = this.display.truncated || bodies.some((body) => visibleWidth(body) > safeWidth);
@@ -106,6 +109,22 @@ class CompactMcpToolResult implements Component {
106
109
  invalidate(): void {
107
110
  this.rendered = null;
108
111
  }
112
+
113
+ private renderPrefix(width: number): string {
114
+ if (!this.title) return "";
115
+ const arrow = " → ";
116
+ if (!this.inputPreview) return `${this.theme.fg("toolTitle", this.title)}${arrow}`;
117
+
118
+ const maxPrefixWidth = Math.max(12, Math.floor(width * 0.55));
119
+ const titleWidth = visibleWidth(this.title);
120
+ const inputWidth = Math.max(0, maxPrefixWidth - titleWidth - 1);
121
+ if (inputWidth <= 3) {
122
+ return `${this.theme.fg("toolTitle", truncateToWidth(this.title, maxPrefixWidth, "…"))}${arrow}`;
123
+ }
124
+
125
+ const input = truncateToWidth(this.inputPreview, inputWidth, "…");
126
+ return `${this.theme.fg("toolTitle", this.title)} ${this.theme.fg("muted", input)}${arrow}`;
127
+ }
109
128
  }
110
129
 
111
130
  class CollapsibleText implements Component {
@@ -239,6 +258,10 @@ function renderToolCallLines(lines: string[], theme?: RenderTheme) {
239
258
  return new Text([styledTitle, ...styledRest].join("\n"), 0, 0);
240
259
  }
241
260
 
261
+ function formatCompactInputPreview(lines: string[], maxChars = DEFAULT_MAX_COMPACT_INPUT_CHARS): string {
262
+ return truncateText(lines.slice(1).join(" ").replace(/\s+/g, " ").trim(), maxChars);
263
+ }
264
+
242
265
  export function resolveMcpToolRenderOptions(settings?: McpToolRenderSettings): McpToolRenderOptions {
243
266
  const resultRendering = settings?.toolResultRendering === "boxed" ? "boxed" : "compact";
244
267
  const collapsedLines = settings?.collapsedResultLines;
@@ -263,7 +286,10 @@ function renderToolCall(
263
286
  context: McpToolRenderContext | undefined,
264
287
  options: McpToolRenderOptions,
265
288
  ) {
266
- if (context?.state) context.state.compactTitle = lines[0] ?? "mcp";
289
+ if (context?.state) {
290
+ context.state.compactTitle = lines[0] ?? "mcp";
291
+ context.state.compactInputPreview = formatCompactInputPreview(lines);
292
+ }
267
293
  if (shouldUseCompactFinalRender(options, context)) return new EmptyComponent();
268
294
  return renderToolCallLines(lines, theme);
269
295
  }
@@ -307,6 +333,19 @@ function collectCollapsedResultLines(
307
333
  let truncated = false;
308
334
 
309
335
  const appendLine = (line: string) => {
336
+ if (lines.length === 0) {
337
+ const previewWidth = Math.min(line.length, remainingChars);
338
+ if (line.slice(0, previewWidth).trim() === "") {
339
+ if (line.length >= remainingChars) {
340
+ truncated = true;
341
+ remainingChars = 0;
342
+ return false;
343
+ }
344
+ remainingChars -= line.length + 1;
345
+ return true;
346
+ }
347
+ }
348
+
310
349
  if (lines.length >= maxLines || remainingChars <= 0) {
311
350
  truncated = true;
312
351
  return false;
@@ -342,7 +381,7 @@ function collectCollapsedResultLines(
342
381
  if (truncated) break;
343
382
  }
344
383
 
345
- if (lines.length === 0) lines.push("");
384
+ if (lines.length === 0) lines.push(truncated ? "(leading blank output omitted)" : "");
346
385
  if (truncated && lines.length >= maxLines) lines.push("…");
347
386
  return { lines, truncated };
348
387
  }
@@ -393,7 +432,8 @@ export function renderMcpToolResult(
393
432
  if (!expanded && renderOptions.resultRendering === "compact") {
394
433
  const display = formatMcpToolResultLines(result, false, renderOptions.collapsedResultLines);
395
434
  const title = context?.state?.compactTitle ?? formatMcpToolResultIdentity(result.details) ?? "";
396
- return new CompactMcpToolResult(title, display, activeTheme);
435
+ const inputPreview = context?.state?.compactInputPreview ?? "";
436
+ return new CompactMcpToolResult(title, inputPreview, display, activeTheme);
397
437
  }
398
438
 
399
439
  const display = formatMcpToolResultLines(result, expanded, renderOptions.collapsedResultLines);