@herbertgao/pi-extensions 2026.8.6 → 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 (343) hide show
  1. package/README.md +5 -5
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +1 -1
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
  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/renderer/compact-mode.ts +94 -77
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
  15. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  16. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  17. package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
  18. package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
  19. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  20. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
  21. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
  22. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +17 -13
  23. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
  24. package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
  25. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
  26. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
  27. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
  28. package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
  29. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
  30. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
  31. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +21 -6
  32. package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
  33. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +20 -0
  34. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +1 -0
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +26 -10
  36. package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
  37. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
  38. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +2 -1
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  43. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
  44. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
  46. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
  49. package/node_modules/@narumitw/pi-btw/README.md +120 -111
  50. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  51. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  52. package/node_modules/@narumitw/pi-btw/package.json +10 -6
  53. package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
  54. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  55. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  56. package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
  57. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  58. package/node_modules/pi-lens/CHANGELOG.md +909 -0
  59. package/node_modules/pi-lens/README.md +11 -3
  60. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  61. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  62. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
  63. package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
  64. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  65. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  66. package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
  67. package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
  68. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  69. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
  70. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  71. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  72. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
  73. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  74. package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
  75. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  76. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  77. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  78. package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
  79. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  80. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  81. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
  82. package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
  83. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
  84. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  85. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
  86. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
  87. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  88. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  122. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  123. package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
  124. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  125. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
  126. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  127. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  128. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  129. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  130. package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
  131. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  132. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
  133. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  134. package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
  135. package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
  136. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  137. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  138. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  139. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  140. package/node_modules/pi-lens/dist/clients/jscpd-client.js +82 -6
  141. package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
  142. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  143. package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
  144. package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
  145. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  146. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  147. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  148. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +102 -7
  149. package/node_modules/pi-lens/dist/clients/lsp/client.js +1516 -159
  150. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
  151. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  152. package/node_modules/pi-lens/dist/clients/lsp/index.js +2274 -147
  153. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  154. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  155. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  156. package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
  157. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  158. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  159. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
  160. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
  161. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  162. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  163. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  164. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  165. package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
  166. package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
  167. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  168. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  169. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  170. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  171. package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
  172. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  173. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  174. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  175. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
  176. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  177. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  178. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
  179. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  180. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  181. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  182. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  183. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
  184. package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
  185. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  186. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  187. package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
  188. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
  189. package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
  190. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +308 -45
  191. package/node_modules/pi-lens/dist/clients/runtime-session.js +332 -9
  192. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  193. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
  194. package/node_modules/pi-lens/dist/clients/runtime-turn.js +575 -67
  195. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  196. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  197. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  198. package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
  199. package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
  200. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  201. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  202. package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
  203. package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
  204. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  205. package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
  206. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  207. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  208. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  209. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  210. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  211. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  212. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  213. package/node_modules/pi-lens/dist/index.js +67738 -55739
  214. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +466 -54
  215. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
  216. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  217. package/node_modules/pi-lens/docs/agent-guide.md +6 -1
  218. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
  219. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  220. package/node_modules/pi-lens/docs/features.md +19 -5
  221. package/node_modules/pi-lens/docs/globalconfig.md +3 -0
  222. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  223. package/node_modules/pi-lens/docs/mcp.md +2 -2
  224. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  225. package/node_modules/pi-lens/docs/settings.md +19 -1
  226. package/node_modules/pi-lens/docs/usage.md +1 -0
  227. package/node_modules/pi-lens/package.json +10 -6
  228. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  229. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  230. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  231. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  232. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +15 -1
  233. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
  234. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  235. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  236. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  237. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  238. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  239. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
  240. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
  241. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
  242. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
  243. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  244. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  245. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  246. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  247. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  248. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  249. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  250. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  251. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  252. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  253. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  254. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  255. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  256. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  257. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  258. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  259. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  260. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
  261. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  262. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  263. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  264. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  265. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  288. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
  289. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  290. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  291. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
  292. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
  293. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
  294. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  295. package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
  296. package/node_modules/pi-mcp-adapter/README.md +47 -5
  297. package/node_modules/pi-mcp-adapter/cli.js +163 -1
  298. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  299. package/node_modules/pi-mcp-adapter/config.ts +25 -7
  300. package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
  301. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  302. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  303. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  304. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  305. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  306. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  307. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  308. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  309. package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
  310. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  311. package/node_modules/pi-mcp-adapter/package.json +3 -1
  312. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  313. package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
  314. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  315. package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
  316. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  317. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  318. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  319. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  320. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  321. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  322. package/node_modules/pi-web-access/CHANGELOG.md +23 -0
  323. package/node_modules/pi-web-access/README.md +27 -9
  324. package/node_modules/pi-web-access/anysearch.ts +4 -2
  325. package/node_modules/pi-web-access/brave.ts +16 -4
  326. package/node_modules/pi-web-access/curator-page.ts +6 -3
  327. package/node_modules/pi-web-access/curator-server.ts +4 -1
  328. package/node_modules/pi-web-access/exa.ts +18 -7
  329. package/node_modules/pi-web-access/extract.ts +28 -3
  330. package/node_modules/pi-web-access/gemini-search.ts +16 -4
  331. package/node_modules/pi-web-access/index.ts +41 -57
  332. package/node_modules/pi-web-access/package.json +1 -1
  333. package/node_modules/pi-web-access/page-query.ts +4 -2
  334. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  335. package/node_modules/pi-web-access/parallel.ts +2 -2
  336. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  337. package/node_modules/pi-web-access/serper.ts +211 -0
  338. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  339. package/node_modules/pi-web-access/summary-review.ts +44 -22
  340. package/node_modules/pi-web-access/tavily.ts +16 -4
  341. package/node_modules/pi-web-access/utils.ts +87 -0
  342. package/node_modules/pi-web-access/valyu.ts +199 -0
  343. 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,
@@ -123,6 +128,8 @@ export interface ServerConnection {
123
128
  transport: Transport;
124
129
  definition: ServerDefinition;
125
130
  tools: McpTool[];
131
+ /** Monotonic guard against older refresh responses replacing newer notifications. */
132
+ toolsRevision?: number;
126
133
  resources: McpResource[];
127
134
  prompts: McpPrompt[];
128
135
  /** True when prompts were advertised but prompts/list failed. */
@@ -139,6 +146,10 @@ export interface ServerConnection {
139
146
  type UiStreamListener = (serverName: string, notification: ServerStreamResultPatchNotification["params"]) => void;
140
147
  type MetadataListChangedListener = (serverName: string, reason: string) => void;
141
148
 
149
+ export type ToolRefreshResult = "updated" | "unchanged" | "superseded" | "refresh-timeout";
150
+
151
+ const KEEP_ALIVE_REFRESH_TIMEOUT_MS = 5_000;
152
+
142
153
  export class McpServerManager {
143
154
  private connections = new Map<string, ServerConnection>();
144
155
  private connectPromises = new Map<string, Promise<ServerConnection>>();
@@ -146,6 +157,10 @@ export class McpServerManager {
146
157
  private uiStreamListeners = new Map<string, UiStreamListener>();
147
158
  private samplingConfig: ServerSamplingConfig | undefined;
148
159
  private metadataListChangedListener: MetadataListChangedListener | undefined;
160
+ private pendingMetadataPublications = new Map<
161
+ string,
162
+ { connection: ServerConnection; reason: string }
163
+ >();
149
164
  private elicitationConfig: ServerElicitationConfig | undefined;
150
165
  private authStorageOptions: AuthStorageOptions = {};
151
166
  private oauthRuntime: McpOAuthRuntime | undefined;
@@ -170,6 +185,25 @@ export class McpServerManager {
170
185
  this.metadataListChangedListener = listener;
171
186
  }
172
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
+
173
207
  setElicitationConfig(config: ServerElicitationConfig | undefined): void {
174
208
  this.elicitationConfig = config;
175
209
  }
@@ -303,6 +337,100 @@ export class McpServerManager {
303
337
  return abortable(promise, ownedSignal);
304
338
  }
305
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
+
306
434
  private async doReconnect(
307
435
  name: string,
308
436
  definition: ServerDefinition,
@@ -440,6 +568,7 @@ export class McpServerManager {
440
568
  transport,
441
569
  definition,
442
570
  tools: [],
571
+ toolsRevision: 0,
443
572
  resources: [],
444
573
  prompts: [],
445
574
  ...(instructions !== undefined ? { instructions } : {}),
@@ -641,7 +770,9 @@ export class McpServerManager {
641
770
  const connection = this.connections.get(serverName);
642
771
  if (!connection || connection.client !== client || connection.status !== "connected") return;
643
772
  connection.tools = tools;
773
+ connection.toolsRevision = (connection.toolsRevision ?? 0) + 1;
644
774
  this.metadataListChangedListener?.(serverName, "tools-list-changed");
775
+ this.pendingMetadataPublications.delete(serverName);
645
776
  }
646
777
 
647
778
  private handlePromptsListChanged(
@@ -660,6 +791,7 @@ export class McpServerManager {
660
791
  connection.prompts = prompts;
661
792
  connection.promptDiscoveryFailed = false;
662
793
  this.metadataListChangedListener?.(serverName, "prompts-list-changed");
794
+ this.pendingMetadataPublications.delete(serverName);
663
795
  }
664
796
 
665
797
  private handleResourcesListChanged(
@@ -677,6 +809,7 @@ export class McpServerManager {
677
809
  if (!connection || connection.client !== client || connection.status !== "connected") return;
678
810
  connection.resources = resources;
679
811
  this.metadataListChangedListener?.(serverName, "resources-list-changed");
812
+ this.pendingMetadataPublications.delete(serverName);
680
813
  }
681
814
 
682
815
  async handleUrlElicitationRequired(
@@ -734,7 +867,10 @@ export class McpServerManager {
734
867
  if (definition.auth === "bearer") {
735
868
  const token = commandBearer
736
869
  ? resolveCommandSecret(commandBearer, `MCP server "${serverName}" HTTP bearer token`)
737
- : resolveBearerToken(definition);
870
+ : resolveBearerToken(definition)
871
+ ?? (definition.bearerToken === undefined && definition.bearerTokenEnv === undefined && definition.bearerTokenStore === true
872
+ ? getBearerTokenForUrl(serverName, serverUrl)
873
+ : undefined);
738
874
  if (token) headers["Authorization"] = `Bearer ${token}`;
739
875
  }
740
876
 
@@ -851,7 +987,7 @@ export class McpServerManager {
851
987
  }
852
988
  }
853
989
 
854
- private async fetchAllTools(client: Client, requestOptions?: RequestOptions): Promise<McpTool[]> {
990
+ private async fetchAllTools(client: Client, requestOptions?: CacheableRequestOptions): Promise<McpTool[]> {
855
991
  const allTools: McpTool[] = [];
856
992
  let cursor: string | undefined;
857
993
 
@@ -979,6 +1115,7 @@ export class McpServerManager {
979
1115
  async close(name: string): Promise<void> {
980
1116
  this.closeGenerations.set(name, (this.closeGenerations.get(name) ?? 0) + 1);
981
1117
  this.connectAttempts.get(name)?.abort(new Error(`MCP connection ${name} was closed`));
1118
+ this.pendingMetadataPublications.delete(name);
982
1119
 
983
1120
  const connection = this.connections.get(name);
984
1121
  if (!connection) {
@@ -1042,6 +1179,7 @@ export class McpServerManager {
1042
1179
  .filter(error => this.containsCleanupFailure(error));
1043
1180
  this.uiStreamListeners.clear();
1044
1181
  this.acceptedUrlElicitations.clear();
1182
+ this.pendingMetadataPublications.clear();
1045
1183
  this.samplingConfig = undefined;
1046
1184
  this.elicitationConfig = undefined;
1047
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 };
@@ -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);
@@ -392,6 +392,8 @@ export interface ServerEntry {
392
392
  auth?: "oauth" | "bearer" | false;
393
393
  bearerToken?: string;
394
394
  bearerTokenEnv?: string;
395
+ /** Read a static bearer token from the adapter-owned OS credential store. */
396
+ bearerTokenStore?: true;
395
397
  /**
396
398
  * OAuth configuration (optional).
397
399
  * If not provided, the SDK will attempt dynamic client registration.
@@ -10,7 +10,7 @@ import {
10
10
  import { ContentBlockSchema } from "@modelcontextprotocol/core";
11
11
  import type { ConsentManager } from "./consent-manager.ts";
12
12
  import { ServerError, wrapError } from "./errors.ts";
13
- import { formatAuthRequiredMessage } from "./utils.ts";
13
+ import { formatAuthRequiredMessage, normalizeToolArguments } from "./utils.ts";
14
14
  import { buildHostHtmlTemplate, buildCspMetaContent } from "./host-html-template.ts";
15
15
  import { logger } from "./logger.ts";
16
16
  import type { McpServerManager } from "./server-manager.ts";
@@ -113,6 +113,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
113
113
  let currentDisplayMode: UiDisplayMode = options.hostContext?.displayMode ?? "inline";
114
114
  let nextEventId = 1;
115
115
  const eventLog: Array<{ id: number; name: string; payload: unknown }> = [];
116
+ let latestCheckpointEventId: number | undefined;
116
117
  let streamSummary: UiStreamSummary | undefined;
117
118
 
118
119
  // Track messages from UI for retrieval
@@ -185,9 +186,12 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
185
186
  lastHeartbeatAt = Date.now();
186
187
  };
187
188
 
188
- const updateStreamSummary = (payload: unknown) => {
189
+ const updateStreamSummary = (eventId: number, payload: unknown) => {
189
190
  const envelope = getVisualizationStreamEnvelope((payload as { structuredContent?: unknown } | null)?.structuredContent);
190
191
  if (!envelope) return;
192
+ if (envelope.frameType === "checkpoint" || envelope.frameType === "final") {
193
+ latestCheckpointEventId = eventId;
194
+ }
191
195
  if (!streamSummary) {
192
196
  streamSummary = {
193
197
  streamId: envelope.streamId,
@@ -210,15 +214,9 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
210
214
  };
211
215
 
212
216
  const getLatestCheckpointIndex = () => {
213
- for (let index = eventLog.length - 1; index >= 0; index -= 1) {
214
- const entry = eventLog[index];
215
- if (!entry) continue;
216
- const envelope = getVisualizationStreamEnvelope((entry.payload as { structuredContent?: unknown } | null)?.structuredContent);
217
- if (envelope?.frameType === "checkpoint" || envelope?.frameType === "final") {
218
- return index;
219
- }
220
- }
221
- return -1;
217
+ const firstEventId = eventLog[0]?.id;
218
+ if (latestCheckpointEventId === undefined || firstEventId === undefined || latestCheckpointEventId < firstEventId) return -1;
219
+ return latestCheckpointEventId - firstEventId;
222
220
  };
223
221
 
224
222
  const pruneEventLog = () => {
@@ -238,7 +236,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
238
236
  if (completed) return;
239
237
  const eventId = nextEventId++;
240
238
  eventLog.push({ id: eventId, name, payload });
241
- updateStreamSummary(payload);
239
+ updateStreamSummary(eventId, payload);
242
240
  pruneEventLog();
243
241
  const chunk = serializeEvent(eventId, name, payload);
244
242
  for (const client of sseClients) {
@@ -438,12 +436,16 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
438
436
  return;
439
437
  }
440
438
 
439
+ let normalizedArguments: Record<string, unknown>;
440
+ try {
441
+ normalizedArguments = normalizeToolArguments(callParams.arguments, `tool "${callParams.name}" arguments`);
442
+ } catch (error) {
443
+ sendJson(res, 400, { ok: false, error: error instanceof Error ? error.message : String(error) });
444
+ return;
445
+ }
441
446
  const callArgs = {
442
447
  name: callParams.name,
443
- arguments:
444
- callParams.arguments && typeof callParams.arguments === "object" && !Array.isArray(callParams.arguments)
445
- ? callParams.arguments
446
- : {},
448
+ arguments: normalizedArguments,
447
449
  };
448
450
  const toolMeta = {
449
451
  name: callParams.name,
@@ -282,6 +282,76 @@ export function normalizeDirectToolInputSchema(schema: unknown): Record<string,
282
282
  return normalized;
283
283
  }
284
284
 
285
+ export function normalizeToolArguments(
286
+ value: unknown,
287
+ context = "tool arguments",
288
+ ): Record<string, unknown> {
289
+ if (value === undefined || value === null || value === "") return {};
290
+
291
+ if (typeof value === "string") {
292
+ const trimmed = value.trim();
293
+ if (trimmed === "") return {};
294
+ let parsed: unknown;
295
+ try {
296
+ parsed = JSON.parse(trimmed);
297
+ } catch (error) {
298
+ throw new Error(
299
+ `${context}: invalid args JSON (${error instanceof SyntaxError ? error.message : String(error)}); ` +
300
+ `pass args as a JSON object, or as a valid JSON string encoding one`,
301
+ { cause: error },
302
+ );
303
+ }
304
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
305
+ throw new Error(
306
+ `${context}: expected a JSON object, got ${Array.isArray(parsed) ? "array" : typeof parsed}`,
307
+ );
308
+ }
309
+ return parsed as Record<string, unknown>;
310
+ }
311
+
312
+ if (typeof value !== "object" || Array.isArray(value)) {
313
+ throw new Error(
314
+ `${context}: expected a JSON object, got ${Array.isArray(value) ? "array" : typeof value}`,
315
+ );
316
+ }
317
+
318
+ assertJsonSerializable(value, context);
319
+ try {
320
+ return JSON.parse(JSON.stringify(value)) as Record<string, unknown>;
321
+ } catch (error) {
322
+ throw new Error(
323
+ `${context}: value is not JSON-serializable: ${error instanceof Error ? error.message : String(error)}`,
324
+ { cause: error },
325
+ );
326
+ }
327
+ }
328
+
329
+ function assertJsonSerializable(value: unknown, context: string, path = ""): void {
330
+ if (value === null) return;
331
+ if (typeof value === "string" || typeof value === "boolean") return;
332
+ if (typeof value === "number") {
333
+ if (!Number.isFinite(value)) throw new Error(`${context}: value at ${path || "root"} is not a finite number`);
334
+ return;
335
+ }
336
+ if (Array.isArray(value)) {
337
+ for (const [index, item] of value.entries()) assertJsonSerializable(item, context, `${path}[${index}]`);
338
+ return;
339
+ }
340
+ if (typeof value === "object") {
341
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
342
+ throw new Error(`${context}: value at ${path || "root"} is not a plain JSON object`);
343
+ }
344
+ if (Object.getOwnPropertySymbols(value).length > 0) {
345
+ throw new Error(`${context}: value at ${path || "root"} has symbol keys`);
346
+ }
347
+ for (const [key, item] of Object.entries(value)) {
348
+ assertJsonSerializable(item, context, path ? `${path}.${key}` : key);
349
+ }
350
+ return;
351
+ }
352
+ throw new Error(`${context}: value at ${path || "root"} is not JSON-serializable`);
353
+ }
354
+
285
355
  export function formatAuthRequiredMessage(
286
356
  config: Pick<McpConfig, "settings">,
287
357
  serverName: string,
@@ -4,6 +4,29 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.24.0] - 2026-08-18
8
+
9
+ ### Highlights
10
+ - Added more provider choices, including Parallel Search MCP, Valyu, and Serper.
11
+ - Made `fetch_content` recover useful article text from more Next.js and React Server Components pages.
12
+ - Updated summary and query rewrite model defaults to newer fast models.
13
+ - Made nested summary and rewrite model calls follow Pi's model registry routing.
14
+ - Added more control over summary thinking levels and provider API base URLs.
15
+
16
+ ### Added
17
+ - Added `summaryModel` thinking-level suffix support. Thanks to [@pkos98](https://github.com/pkos98) for issue #264.
18
+ - Added explicit-only Parallel Search MCP support for keyless search and opt-in hosted fetch. Thanks to [@happytomatoe](https://github.com/happytomatoe) for #257.
19
+ - Added explicit-only Valyu and Serper search providers. Thanks to [@mikhel01](https://github.com/mikhel01) for issues #259 and #260.
20
+ - Added configurable API base URLs for Brave, keyed Exa, and Tavily requests, with credential stripping across redirect origins. Thanks to [@XWIlluDelu](https://github.com/XWIlluDelu) for #265.
21
+
22
+ ### Changed
23
+ - Refreshed default summary and query rewrite model preferences. Thanks to [@hyein-cbio](https://github.com/hyein-cbio) for #266.
24
+
25
+ ### Fixed
26
+ - Route nested model calls through Pi's model registry. Thanks to [@rany2](https://github.com/rany2) for #263.
27
+ - Recover useful Next.js RSC content when Readability only extracts a loading shell, and report full, partial, or failed background content fetches accurately (#272, #273).
28
+ - Keep valid AnySearch results when the API omits or nulls result content. Thanks to [@mikhel01](https://github.com/mikhel01) for #258.
29
+
7
30
  ## [0.23.0] - 2026-08-15
8
31
 
9
32
  ### Added