@herbertgao/pi-extensions 2026.8.11 → 2026.8.13

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 (476) hide show
  1. package/README.md +23 -10
  2. package/{node_modules/@herbertgao/pi-mermaid-open/LICENSE → THIRD_PARTY_NOTICES.md} +19 -1
  3. package/node_modules/@czottmann/pi-automode/CHANGELOG.md +15 -0
  4. package/node_modules/@czottmann/pi-automode/README.md +5 -3
  5. package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +2 -0
  6. package/node_modules/@czottmann/pi-automode/docs/adr/ADR-002-global-config-in-extension-data-directory.md +60 -0
  7. package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +1 -0
  8. package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +4 -4
  9. package/node_modules/@czottmann/pi-automode/docs/configuration.md +20 -4
  10. package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +1 -1
  11. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/bash.ts +692 -0
  12. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +181 -3
  13. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +4 -1
  14. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +143 -36
  15. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +103 -148
  16. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +32 -6
  17. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +344 -22
  18. package/node_modules/@czottmann/pi-automode/extensions/auto-mode.ts +1 -0
  19. package/node_modules/@czottmann/pi-automode/package.json +4 -1
  20. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -1
  21. package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -1
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +4 -0
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +21 -1
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +1 -1
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +19 -19
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +4 -2
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +2 -1
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +10 -2
  29. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  30. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +10 -0
  31. package/node_modules/@herbertgao/pi-subagents/README.md +21 -15
  32. package/node_modules/@herbertgao/pi-subagents/package.json +3 -3
  33. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +11 -8
  34. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +184 -106
  35. package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +31 -11
  36. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +9 -1
  37. package/node_modules/@herbertgao/pi-subagents/src/index.ts +156 -31
  38. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +17 -0
  39. package/node_modules/@herbertgao/pi-subagents/src/model-resolver.ts +14 -0
  40. package/node_modules/@herbertgao/pi-subagents/src/schedule.ts +8 -0
  41. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +32 -1
  42. package/node_modules/@herbertgao/pi-subagents/src/types.ts +17 -2
  43. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +23 -2
  44. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +259 -24
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  46. package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +376 -0
  47. package/node_modules/@luxusai/pi-hindsight/README.md +92 -0
  48. package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +56 -0
  49. package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +169 -0
  50. package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +107 -0
  51. package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +89 -0
  52. package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +189 -0
  53. package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
  54. package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
  55. package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +54 -0
  56. package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +75 -0
  57. package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +300 -0
  58. package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +158 -0
  59. package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +164 -0
  60. package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +139 -0
  61. package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +74 -0
  62. package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +261 -0
  63. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +151 -0
  64. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +18 -0
  65. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +46 -0
  66. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +383 -0
  67. package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +240 -0
  68. package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +176 -0
  69. package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +178 -0
  70. package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +41 -0
  71. package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +386 -0
  72. package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +39 -0
  73. package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +34 -0
  74. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +140 -0
  75. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +61 -0
  76. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +925 -0
  77. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +247 -0
  78. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +547 -0
  79. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +480 -0
  80. package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +182 -0
  81. package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +86 -0
  82. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +1010 -0
  83. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +175 -0
  84. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +425 -0
  85. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +210 -0
  86. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +817 -0
  87. package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +25 -0
  88. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +319 -0
  89. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +196 -0
  90. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +189 -0
  91. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +65 -0
  92. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +260 -0
  93. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +244 -0
  94. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +59 -0
  95. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +82 -0
  96. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +45 -0
  97. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +331 -0
  98. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +354 -0
  99. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +66 -0
  100. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +132 -0
  101. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +228 -0
  102. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +74 -0
  103. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +16 -0
  104. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +648 -0
  105. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +105 -0
  106. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +68 -0
  107. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +71 -0
  108. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +13 -0
  109. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +162 -0
  110. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +131 -0
  111. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +104 -0
  112. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +37 -0
  113. package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +893 -0
  114. package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +35 -0
  115. package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +177 -0
  116. package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +7 -0
  117. package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +21 -0
  118. package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +112 -0
  119. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +111 -0
  120. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +214 -0
  121. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +70 -0
  122. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +392 -0
  123. package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +45 -0
  124. package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +9 -0
  125. package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +860 -0
  126. package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +105 -0
  127. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +189 -0
  128. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +299 -0
  129. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +201 -0
  130. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +47 -0
  131. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +239 -0
  132. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +50 -0
  133. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +259 -0
  134. package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +77 -0
  135. package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +534 -0
  136. package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +319 -0
  137. package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +325 -0
  138. package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +42 -0
  139. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +244 -0
  140. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +56 -0
  141. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +50 -0
  142. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +167 -0
  143. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +207 -0
  144. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +120 -0
  145. package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +8 -0
  146. package/node_modules/@luxusai/pi-hindsight/package.json +118 -0
  147. package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +75 -0
  148. package/node_modules/@narumitw/pi-btw/dist/index.ts +143 -46
  149. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
  150. package/node_modules/@narumitw/pi-btw/package.json +6 -6
  151. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +136 -22
  152. package/node_modules/{@herbertgao → @tifan}/pi-copy-response/README.md +2 -4
  153. package/node_modules/{@herbertgao → @tifan}/pi-copy-response/package.json +5 -15
  154. package/node_modules/{@herbertgao → @tifan}/pi-handoff/README.md +4 -6
  155. package/node_modules/@tifan/pi-handoff/package.json +43 -0
  156. package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/index.ts +1 -1
  157. package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/README.md +2 -4
  158. package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/package.json +5 -15
  159. package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/README.md +5 -7
  160. package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/package.json +5 -19
  161. package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/README.md +4 -6
  162. package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/package.json +6 -16
  163. package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/src/index.ts +1 -6
  164. package/node_modules/{@herbertgao → @tifan}/pi-recap/README.md +4 -6
  165. package/node_modules/@tifan/pi-recap/package.json +42 -0
  166. package/node_modules/{@herbertgao → @tifan}/pi-recap/src/models.ts +1 -6
  167. package/node_modules/{@herbertgao → @tifan}/pi-rename/README.md +13 -8
  168. package/node_modules/@tifan/pi-rename/package.json +47 -0
  169. package/node_modules/@tifan/pi-rename/src/herdr-label.ts +4 -0
  170. package/node_modules/{@herbertgao → @tifan}/pi-rename/src/index.ts +4 -16
  171. package/node_modules/{@herbertgao → @tifan}/pi-rename/src/models.ts +1 -6
  172. package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/README.md +2 -4
  173. package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/package.json +5 -15
  174. package/node_modules/pi-lens/CHANGELOG.md +96 -1
  175. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -1
  176. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +14 -5
  177. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +48 -18
  178. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +1 -3
  179. package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +16 -4
  180. package/node_modules/pi-lens/dist/clients/bash-file-access.js +3 -1
  181. package/node_modules/pi-lens/dist/clients/biome-client.js +1 -3
  182. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +21 -8
  183. package/node_modules/pi-lens/dist/clients/bounded-cache.js +24 -8
  184. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +4 -3
  185. package/node_modules/pi-lens/dist/clients/cache-manager.js +6 -7
  186. package/node_modules/pi-lens/dist/clients/cache-observability.js +461 -66
  187. package/node_modules/pi-lens/dist/clients/call-graph.js +238 -63
  188. package/node_modules/pi-lens/dist/clients/codebase-model.js +13 -5
  189. package/node_modules/pi-lens/dist/clients/complexity-client.js +1 -3
  190. package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -8
  191. package/node_modules/pi-lens/dist/clients/dead-code-logger.js +1 -2
  192. package/node_modules/pi-lens/dist/clients/deadline-utils.js +3 -1
  193. package/node_modules/pi-lens/dist/clients/debug-heap.js +8 -1
  194. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +1 -1
  195. package/node_modules/pi-lens/dist/clients/dependency-checker.js +11 -7
  196. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +39 -2
  197. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +5 -1
  198. package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +2 -3
  199. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +13 -1
  200. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +3 -1
  201. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +2 -1
  202. package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +1 -1
  203. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +9 -4
  204. package/node_modules/pi-lens/dist/clients/dispatch/rules/error-swallowing.js +3 -1
  205. package/node_modules/pi-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +6 -2
  206. package/node_modules/pi-lens/dist/clients/dispatch/rules/unsafe-boundary.js +31 -7
  207. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +5 -2
  208. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +10 -14
  209. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +5 -1
  210. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +1 -1
  211. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +3 -1
  212. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +25 -6
  213. package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +1 -1
  214. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +1 -1
  215. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +3 -1
  216. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +13 -8
  217. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +4 -1
  218. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +25 -10
  219. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +1 -1
  220. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +1 -1
  221. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +1 -1
  222. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +28 -4
  223. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +6 -8
  224. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +212 -11
  225. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +1 -1
  226. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +8 -4
  227. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +10 -6
  228. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +23 -14
  229. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -1
  230. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +7 -9
  231. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +5 -2
  232. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +7 -7
  233. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +6 -8
  234. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +13 -8
  235. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +13 -8
  236. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +17 -3
  237. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +7 -1
  238. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +24 -1
  239. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +35 -0
  240. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +1 -3
  241. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +6 -8
  242. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +1 -1
  243. package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +2 -1
  244. package/node_modules/pi-lens/dist/clients/dispatch/types.js +6 -1
  245. package/node_modules/pi-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +6 -2
  246. package/node_modules/pi-lens/dist/clients/extension-log.js +5 -3
  247. package/node_modules/pi-lens/dist/clients/feature-hints.js +8 -1
  248. package/node_modules/pi-lens/dist/clients/file-kinds.js +34 -129
  249. package/node_modules/pi-lens/dist/clients/file-utils.js +17 -1
  250. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +57 -2
  251. package/node_modules/pi-lens/dist/clients/formatters.js +144 -27
  252. package/node_modules/pi-lens/dist/clients/freshness.js +38 -0
  253. package/node_modules/pi-lens/dist/clients/git-guard.js +43 -13
  254. package/node_modules/pi-lens/dist/clients/go-client.js +1 -3
  255. package/node_modules/pi-lens/dist/clients/grammar-source.js +1 -1
  256. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +30 -4
  257. package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +1 -3
  258. package/node_modules/pi-lens/dist/clients/install-diagnostics.js +4 -2
  259. package/node_modules/pi-lens/dist/clients/installer/index.js +86 -77
  260. package/node_modules/pi-lens/dist/clients/instance-reaper.js +5 -2
  261. package/node_modules/pi-lens/dist/clients/instance-registry.js +4 -2
  262. package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
  263. package/node_modules/pi-lens/dist/clients/knip-client.js +29 -15
  264. package/node_modules/pi-lens/dist/clients/language-profile.js +4 -1
  265. package/node_modules/pi-lens/dist/clients/latency-logger.js +13 -2
  266. package/node_modules/pi-lens/dist/clients/lens-config.js +1 -1
  267. package/node_modules/pi-lens/dist/clients/lens-map.js +8 -3
  268. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +1 -1
  269. package/node_modules/pi-lens/dist/clients/lsp/config.js +4 -6
  270. package/node_modules/pi-lens/dist/clients/lsp/edits.js +119 -32
  271. package/node_modules/pi-lens/dist/clients/lsp/index.js +94 -35
  272. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +2 -1
  273. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +4 -1
  274. package/node_modules/pi-lens/dist/clients/lsp/launch.js +11 -3
  275. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +152 -0
  276. package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -7
  277. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +10 -2
  278. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +9 -4
  279. package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -3
  280. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +10 -20
  281. package/node_modules/pi-lens/dist/clients/mcp/host-shim.js +1 -1
  282. package/node_modules/pi-lens/dist/clients/memory-sampler.js +73 -7
  283. package/node_modules/pi-lens/dist/clients/metrics-client.js +1 -3
  284. package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +8 -3
  285. package/node_modules/pi-lens/dist/clients/module-report-lsp.js +7 -1
  286. package/node_modules/pi-lens/dist/clients/module-report.js +14 -17
  287. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +3 -5
  288. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +220 -0
  289. package/node_modules/pi-lens/dist/clients/package-manager.js +6 -1
  290. package/node_modules/pi-lens/dist/clients/pipeline.js +57 -9
  291. package/node_modules/pi-lens/dist/clients/project-conventions.js +2 -8
  292. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +10 -7
  293. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +2 -1
  294. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +3 -1
  295. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +13 -9
  296. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +3 -1
  297. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -2
  298. package/node_modules/pi-lens/dist/clients/project-lens-config.js +12 -5
  299. package/node_modules/pi-lens/dist/clients/project-snapshot-fingerprint.js +48 -0
  300. package/node_modules/pi-lens/dist/clients/project-snapshot-persist-worker.js +15 -1
  301. package/node_modules/pi-lens/dist/clients/project-snapshot.js +472 -66
  302. package/node_modules/pi-lens/dist/clients/read-expansion.js +12 -2
  303. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +5 -4
  304. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +5 -2
  305. package/node_modules/pi-lens/dist/clients/read-guard.js +1 -1
  306. package/node_modules/pi-lens/dist/clients/resource-sampler.js +1 -1
  307. package/node_modules/pi-lens/dist/clients/reverse-deps.js +6 -5
  308. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +42 -17
  309. package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +8 -2
  310. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +10 -1
  311. package/node_modules/pi-lens/dist/clients/review-graph/query.js +2 -1
  312. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +4 -2
  313. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +2 -2
  314. package/node_modules/pi-lens/dist/clients/ruff-client.js +6 -5
  315. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +63 -31
  316. package/node_modules/pi-lens/dist/clients/runtime-context.js +12 -4
  317. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +83 -4
  318. package/node_modules/pi-lens/dist/clients/runtime-session.js +14 -0
  319. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +59 -3
  320. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +148 -34
  321. package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -6
  322. package/node_modules/pi-lens/dist/clients/rust-client.js +1 -3
  323. package/node_modules/pi-lens/dist/clients/safe-spawn.js +150 -11
  324. package/node_modules/pi-lens/dist/clients/security-scan-client.js +1 -3
  325. package/node_modules/pi-lens/dist/clients/session-summary.js +3 -1
  326. package/node_modules/pi-lens/dist/clients/sg-runner.js +1 -3
  327. package/node_modules/pi-lens/dist/clients/source-filter.js +10 -6
  328. package/node_modules/pi-lens/dist/clients/source-walker.js +1 -1
  329. package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +96 -0
  330. package/node_modules/pi-lens/dist/clients/startup-scan.js +4 -1
  331. package/node_modules/pi-lens/dist/clients/tool-definition.js +7 -0
  332. package/node_modules/pi-lens/dist/clients/tool-policy.js +26 -11
  333. package/node_modules/pi-lens/dist/clients/tool-render.js +2 -1
  334. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +10 -4
  335. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
  336. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +12 -5
  337. package/node_modules/pi-lens/dist/clients/warm-attach.js +12 -5
  338. package/node_modules/pi-lens/dist/clients/widget-state.js +27 -11
  339. package/node_modules/pi-lens/dist/clients/word-index.js +3 -1
  340. package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -2
  341. package/node_modules/pi-lens/dist/clients/zizmor-config.js +9 -1
  342. package/node_modules/pi-lens/dist/i18n.js +13 -5
  343. package/node_modules/pi-lens/dist/index.js +10797 -8627
  344. package/node_modules/pi-lens/dist/mcp/server.js +3 -1
  345. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +68 -12
  346. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +21 -7
  347. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +164 -35
  348. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +24 -7
  349. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
  350. package/node_modules/pi-lens/dist/tools/module-report.js +1 -1
  351. package/node_modules/pi-lens/dist/tools/project-report.js +1 -1
  352. package/node_modules/pi-lens/dist/tools/symbol-search.js +5 -2
  353. package/node_modules/pi-lens/docs/durable-store-audit-1202.md +1 -1
  354. package/node_modules/pi-lens/docs/servercapabilities.md +1 -1
  355. package/node_modules/pi-lens/package.json +160 -156
  356. package/node_modules/pi-lens/rules/typos/_typos.toml +2 -2
  357. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +31 -13
  358. package/node_modules/pi-lens/scripts/download-grammars.js +9 -3
  359. package/node_modules/pi-lens/scripts/rpc-load-check.mjs +30 -9
  360. package/node_modules/pi-mcp-adapter/CHANGELOG.md +47 -0
  361. package/node_modules/pi-mcp-adapter/README.md +42 -13
  362. package/node_modules/pi-mcp-adapter/commands.ts +4 -2
  363. package/node_modules/pi-mcp-adapter/config.ts +45 -5
  364. package/node_modules/pi-mcp-adapter/direct-tools.ts +103 -92
  365. package/node_modules/pi-mcp-adapter/dist/agent-dir.d.ts +10 -0
  366. package/node_modules/pi-mcp-adapter/dist/agent-dir.js +63 -0
  367. package/node_modules/pi-mcp-adapter/dist/agent-dir.js.map +1 -0
  368. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.d.ts +8 -0
  369. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +356 -0
  370. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +1 -0
  371. package/node_modules/pi-mcp-adapter/dist/config.d.ts +123 -0
  372. package/node_modules/pi-mcp-adapter/dist/config.js +1087 -0
  373. package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -0
  374. package/node_modules/pi-mcp-adapter/dist/metadata-cache.d.ts +19 -0
  375. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +319 -0
  376. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -0
  377. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.d.ts +2 -0
  378. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +156 -0
  379. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +1 -0
  380. package/node_modules/pi-mcp-adapter/dist/resource-tools.d.ts +1 -0
  381. package/node_modules/pi-mcp-adapter/dist/resource-tools.js +15 -0
  382. package/node_modules/pi-mcp-adapter/dist/resource-tools.js.map +1 -0
  383. package/node_modules/pi-mcp-adapter/dist/types.d.ts +564 -0
  384. package/node_modules/pi-mcp-adapter/dist/types.js +287 -0
  385. package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -0
  386. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.d.ts +6 -0
  387. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js +37 -0
  388. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js.map +1 -0
  389. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.d.ts +104 -0
  390. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js +59 -0
  391. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js.map +1 -0
  392. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.d.ts +4 -0
  393. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js +27 -0
  394. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js.map +1 -0
  395. package/node_modules/pi-mcp-adapter/dist/utils.d.ts +32 -0
  396. package/node_modules/pi-mcp-adapter/dist/utils.js +338 -0
  397. package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -0
  398. package/node_modules/pi-mcp-adapter/failure-backoff.ts +23 -0
  399. package/node_modules/pi-mcp-adapter/index.ts +204 -82
  400. package/node_modules/pi-mcp-adapter/init.ts +41 -30
  401. package/node_modules/pi-mcp-adapter/lifecycle.ts +16 -8
  402. package/node_modules/pi-mcp-adapter/mcp-code.ts +2 -0
  403. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +66 -16
  404. package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +95 -7
  405. package/node_modules/pi-mcp-adapter/mcp-probe.ts +18 -4
  406. package/node_modules/pi-mcp-adapter/mcp-references.ts +368 -0
  407. package/node_modules/pi-mcp-adapter/mcp-status.ts +8 -19
  408. package/node_modules/pi-mcp-adapter/metadata-cache.ts +20 -12
  409. package/node_modules/pi-mcp-adapter/namespace-tools.ts +276 -0
  410. package/node_modules/pi-mcp-adapter/package.json +24 -6
  411. package/node_modules/pi-mcp-adapter/proxy-modes.ts +66 -10
  412. package/node_modules/pi-mcp-adapter/search-ranking.ts +2 -0
  413. package/node_modules/pi-mcp-adapter/server-manager.ts +63 -12
  414. package/node_modules/pi-mcp-adapter/state.ts +1 -3
  415. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +16 -2
  416. package/node_modules/pi-mcp-adapter/types.ts +48 -1
  417. package/node_modules/pi-mcp-adapter/ui-server.ts +3 -19
  418. package/node_modules/pi-mcp-adapter/ui-session.ts +2 -1
  419. package/node_modules/pi-mcp-adapter/utils.ts +21 -19
  420. package/node_modules/pi-web-access/CHANGELOG.md +26 -0
  421. package/node_modules/pi-web-access/README.md +71 -14
  422. package/node_modules/pi-web-access/chrome-cookies.ts +115 -35
  423. package/node_modules/pi-web-access/credential-source.ts +6 -2
  424. package/node_modules/pi-web-access/curator-page.ts +5 -3
  425. package/node_modules/pi-web-access/curator-server.ts +2 -1
  426. package/node_modules/pi-web-access/extract.ts +89 -9
  427. package/node_modules/pi-web-access/fetch-params.ts +13 -0
  428. package/node_modules/pi-web-access/gemini-adc.ts +298 -0
  429. package/node_modules/pi-web-access/gemini-api.ts +59 -15
  430. package/node_modules/pi-web-access/gemini-search.ts +58 -18
  431. package/node_modules/pi-web-access/gemini-url-context.ts +3 -2
  432. package/node_modules/pi-web-access/gemini-web-config.ts +57 -7
  433. package/node_modules/pi-web-access/gemini-web.ts +9 -3
  434. package/node_modules/pi-web-access/github-api.ts +5 -4
  435. package/node_modules/pi-web-access/github-issue-pr.ts +700 -0
  436. package/node_modules/pi-web-access/index.ts +403 -297
  437. package/node_modules/pi-web-access/kimi-search.ts +234 -0
  438. package/node_modules/pi-web-access/openai-search.ts +118 -21
  439. package/node_modules/pi-web-access/package.json +3 -2
  440. package/node_modules/pi-web-access/ssrf-protection.ts +4 -1
  441. package/node_modules/pi-web-access/utils.ts +307 -1
  442. package/node_modules/pi-web-access/youtube-extract.ts +2 -2
  443. package/package.json +46 -37
  444. package/node_modules/@herbertgao/pi-copy-response/CHANGELOG.md +0 -49
  445. package/node_modules/@herbertgao/pi-copy-response/LICENSE +0 -22
  446. package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +0 -83
  447. package/node_modules/@herbertgao/pi-handoff/LICENSE +0 -22
  448. package/node_modules/@herbertgao/pi-handoff/package.json +0 -60
  449. package/node_modules/@herbertgao/pi-inline-skills/CHANGELOG.md +0 -57
  450. package/node_modules/@herbertgao/pi-inline-skills/LICENSE +0 -22
  451. package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +0 -39
  452. package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +0 -63
  453. package/node_modules/@herbertgao/pi-preferred-thinking/LICENSE +0 -22
  454. package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +0 -101
  455. package/node_modules/@herbertgao/pi-recap/LICENSE +0 -22
  456. package/node_modules/@herbertgao/pi-recap/package.json +0 -55
  457. package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +0 -49
  458. package/node_modules/@herbertgao/pi-rename/LICENSE +0 -22
  459. package/node_modules/@herbertgao/pi-rename/package.json +0 -63
  460. package/node_modules/@herbertgao/pi-titlebar-spinner/CHANGELOG.md +0 -25
  461. package/node_modules/@herbertgao/pi-titlebar-spinner/LICENSE +0 -22
  462. /package/node_modules/{@herbertgao → @tifan}/pi-copy-response/src/index.ts +0 -0
  463. /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/complete-text.ts +0 -0
  464. /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/session-query.ts +0 -0
  465. /package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/src/index.ts +0 -0
  466. /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +0 -0
  467. /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/viewer.mjs +0 -0
  468. /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/src/index.ts +0 -0
  469. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/index.ts +0 -0
  470. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/model-picker.ts +0 -0
  471. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/sanitize.ts +0 -0
  472. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/tui.ts +0 -0
  473. /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/model-picker.ts +0 -0
  474. /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/naming.ts +0 -0
  475. /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/sanitize.ts +0 -0
  476. /package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/src/index.ts +0 -0
@@ -7,6 +7,53 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.29.0] - 2026-08-26
11
+
12
+ ### Highlights
13
+ - `/mcp setup` can now add Parallel Search as an opt-in preset.
14
+ - Users can try web search and page fetching without first creating an API key.
15
+ - MCP status updates work better in non-TUI hosts that provide plain theme values.
16
+
17
+ ### Added
18
+ - Added an opt-in Parallel Search preset to `/mcp setup` for web search and page fetching without an API key. Thanks to [@georgeatparallel](https://github.com/georgeatparallel) for PR #448.
19
+
20
+ ### Fixed
21
+ - MCP status updates now use plain text when a non-TUI host provides a theme without styling methods. Thanks to [@jinnnyang](https://github.com/jinnnyang) for #449.
22
+
23
+ ## [2.28.0] - 2026-08-26
24
+
25
+ ### Highlights
26
+ - MCP connections are less fragile when servers fail, recover, move slowly, or refresh their catalogs.
27
+ - Direct MCP tools are safer to expose, with stricter input checks and bounded result details when hosts opt in.
28
+ - Other Pi extensions can register MCP servers at runtime without sharing module state.
29
+ - Proxy calls now show live server progress in the interactive UI.
30
+ - Package installs and public helper imports are easier to use from downstream hosts.
31
+
32
+ ### Added
33
+ - Persistent metadata cache entries now honor server `ttlMs` hints without extending the default max age. Thanks to [@Seinra](https://github.com/Seinra) for #431.
34
+ - Proxy tool calls now forward server progress notifications to the interactive UI. Thanks to [@Seinra](https://github.com/Seinra) for PR #440 and for mapping the area in #431.
35
+ - Added a pure `mcp:` reference resolver API for consumers that validate adapter tool names from explicit config and cache inputs. Thanks to [@abdwhb-png](https://github.com/abdwhb-png) for PR #420.
36
+ - Direct tools can opt into strict advertised-schema validation with one-layer JSON recovery for object and array properties. Thanks to [@4ndr3wxh1ll](https://github.com/4ndr3wxh1ll) for PR #430.
37
+ - Direct tools can opt into guarded raw MCP result details, retaining bounded structured fields while summarizing oversized values.
38
+ - Embedding hosts can import the configuration loader and metadata cache helpers from public package subpaths, and can validate cached metadata against an explicit private process environment.
39
+
40
+ ### Fixed
41
+ - Runtime MCP registration now works across separately loaded Pi extensions through a versioned shared event contract. Thanks to [@fmoda3](https://github.com/fmoda3) for #443.
42
+ - Stdio MCP startup errors now identify a configured missing or non-directory `cwd` instead of blaming the executable. Thanks to [@SoyElf](https://github.com/SoyElf) for #442.
43
+ - Package installs with `--omit=dev` no longer run the public helper build during `prepare`; Git installs and package tarballs still include the built public exports. Thanks to [@KripaMishra](https://github.com/KripaMishra) for #441.
44
+ - MCP gateway descriptions now stay stable across metadata-only refreshes and keep live counts behind `mcp({})`. Thanks to [@voidfreud](https://github.com/voidfreud) for PR #432.
45
+ - Failed MCP servers in active backoff no longer remain advertised through cached direct tools, gateway list/search/describe results, or status tool counts. Thanks to [@voidfreud](https://github.com/voidfreud) for PR #434.
46
+ - OAuth token invalidation now preserves credentials replaced by another Pi process instead of letting a stale refresh delete newly authorized shared credentials. Thanks to [@mjlbach](https://github.com/mjlbach) for PR #422.
47
+ - Failed first-time MCP initialization no longer leaves the session permanently stuck with only `MCP not initialized`; the gateway keeps the failure reason and retries initialization on the next `mcp(...)` call. Thanks to [@hara-seihun](https://github.com/hara-seihun) for #428.
48
+ - HTTP 202 and unauthenticated HTTP 401 endpoint probes now report ambiguous endpoint shape instead of claiming the URL is not MCP. Thanks to [@jayshah5696](https://github.com/jayshah5696) for #415.
49
+ - Expanded `mcpScript` calls now show bounded submitted code. Thanks to [@DenisBalan](https://github.com/DenisBalan) for #413.
50
+ - Gateway parameters nested inside `args` now fail with top-level guidance instead of dispatching inconsistently. Thanks to [@voidfreud](https://github.com/voidfreud) for PR #417.
51
+ - Large direct-tool advisories now explain how to hide them with `settings.warnOnLargeDirectTools: false`. Thanks to [@afrodao2394](https://github.com/afrodao2394) for #412.
52
+ - Namespace proxy tools now use valid cached metadata, include resource-only proxy servers, clean up only prior namespace registrations, follow `MCP_DIRECT_TOOLS` selection, and skip ambiguous normalized server names. Thanks to [@abdwhb-png](https://github.com/abdwhb-png) for PR #414.
53
+ - Kept transient HTTP 503 connection failures as availability errors without multiplying gateway retries or misdiagnosing the endpoint as non-MCP. Thanks to [@elkaix](https://github.com/elkaix) for PR #411.
54
+ - Preserved cached keep-alive catalogs during transient 503 refresh outages while deferred recovery continues with bounded backoff.
55
+ - Startup connections that fail with a transient HTTP 503 now surface one quiet "temporarily unavailable; retry later" warning instead of the full hard failure; documented lifecycle behavior is unchanged, and keep-alive health checks continue their existing self-healing path. Thanks to [@elkaix](https://github.com/elkaix) for PR #424.
56
+
10
57
  ## [2.27.0] - 2026-08-20
11
58
 
12
59
  ### Highlights
@@ -24,6 +24,8 @@ pi install npm:pi-mcp-adapter
24
24
 
25
25
  Restart Pi after installation.
26
26
 
27
+ > **DeepSeek Harness (third-party bridge):** Run the unmodified adapter in DSH via [pi2dsh](https://github.com/weijiafu14/pi2dsh); see the [verified dsh-TUI and Web MCP guide](https://github.com/weijiafu14/pi2dsh/tree/main/examples/tui-mcp).
28
+
27
29
  ## What happens on first run
28
30
 
29
31
  The adapter reads standard MCP files automatically. No extra setup needed if you already have them.
@@ -145,22 +147,43 @@ A Pi package can ship MCP servers for the installed adapter without requiring a
145
147
  An extension can register MCP servers with the installed adapter at runtime, for example a plugin host that discovers plugins after load:
146
148
 
147
149
  ```ts
148
- import { registerMcpServer } from "pi-mcp-adapter";
150
+ const MCP_RUNTIME_REGISTER_EVENT = "pi-mcp-adapter:runtime-register:v1";
151
+ type RuntimeRegistrationRequest = {
152
+ version: 1;
153
+ name: string;
154
+ definition: { url: string };
155
+ result?:
156
+ | { ok: true; registration: { dispose(): Promise<void> } }
157
+ | { ok: false; error: Error };
158
+ };
149
159
 
150
160
  export default function pluginHost(pi) {
151
- const registration = registerMcpServer({
152
- pi,
153
- name: "acme__docs",
154
- definition: {
155
- url: "https://mcp.example.com/mcp",
156
- },
161
+ let registration: { dispose(): Promise<void> } | undefined;
162
+
163
+ pi.on("session_start", () => {
164
+ if (registration) return;
165
+ const request: RuntimeRegistrationRequest = {
166
+ version: 1,
167
+ name: "acme__docs",
168
+ definition: { url: "https://mcp.example.com/mcp" },
169
+ };
170
+ pi.events.emit(MCP_RUNTIME_REGISTER_EVENT, request);
171
+ if (!request.result) throw new Error("pi-mcp-adapter is not installed");
172
+ if (!request.result.ok) throw request.result.error;
173
+ registration = request.result.registration;
174
+ });
175
+
176
+ pi.on("session_shutdown", async () => {
177
+ const current = registration;
178
+ registration = undefined;
179
+ await current?.dispose();
157
180
  });
158
- // Later, when the plugin is uninstalled:
159
- await registration.dispose();
160
181
  }
161
182
  ```
162
183
 
163
- Runtime registrations are session scoped and never written to config files. Duplicate server names fail closed against configured servers and other registrations. Registered servers use the normal lazy connection, OAuth, approval, and shutdown behavior, but they are proxy-tool-only and their tools become visible at the next tool sync. To change a definition, dispose the registration and register again. Registration throws when no adapter is installed for the given Pi instance.
184
+ Cross-extension registration uses Pi's shared event bus and does not require a runtime import from `pi-mcp-adapter`. Emit during `session_start` or later so the adapter listener is installed. The adapter writes `request.result` synchronously; the first adapter listener to respond wins.
185
+
186
+ Runtime registrations are session scoped and never written to config files. Duplicate server names fail closed against configured servers and other registrations. Registered servers use the normal lazy connection, OAuth, approval, and shutdown behavior, but they are proxy-tool-only and their tools become visible at the next tool sync. To change a definition, dispose the registration and register again.
164
187
 
165
188
  ### SDK configuration
166
189
 
@@ -383,6 +406,8 @@ When any enabled server uses `eager` or `keep-alive`, initialization also starts
383
406
  | `oauthDir` | Legacy OAuth `tokens.json` import directory for this MCP config. Relative paths resolve from the active project cwd. `MCP_OAUTH_DIR` still wins when set. Persistent OAuth credentials are stored in the OS credential store, not this directory. |
384
407
  | `mcpServers.<name>.oauth.authorizationParams` | Extra authorization URL parameters for provider-specific OAuth extensions. Flow-owned parameters such as `client_id`, `redirect_uri`, `scope`, `state`, `code_challenge`, `response_type`, and `resource` cannot be overridden. |
385
408
  | `directTools` | Global default for all servers (default: false). Per-server overrides this. |
409
+ | `strictDirectToolArguments` | Validate direct-tool inputs against their advertised schemas and recover one JSON string layer for object and array properties (default: false). |
410
+ | `directToolResultDetails` | Direct-tool result details: `"lean"` (default) or `"bounded"` to retain the guarded raw MCP result. |
386
411
  | `warnOnLargeDirectTools` | Show the advisory when 75 or more direct tools resolve (default: `true`). Set to `false` to suppress only this advisory. |
387
412
  | `freezeDirectTools` | Keep direct-tool registration stable after the initial sync so automatic reconnects and list-change notifications do not rebuild the system prompt. Use `mcp({ connect: "server" })` or `/mcp reconnect <server>` to refresh deliberately. Default: false. |
388
413
  | `scriptMode` | Register the MCP-only `mcpScript` plain-JavaScript tool (default: true). Set to `false` to hide it. |
@@ -438,7 +463,7 @@ Oversized MCP tool/resource results are guarded by default so a single huge resp
438
463
  - Inline text output is capped at **50 KiB / 2,000 lines** (matching Pi's built-in `bash` guard). Larger output is truncated to a head preview and the full text is saved to a temp file whose path is included in the result, so the agent can `read`/`grep` it.
439
464
  - **Image content blocks pass through unchanged** — only text output is guarded. Images are delivered to the provider as native image content.
440
465
  - Binary resource blobs up to **10 MiB** are decoded to private temp files and replaced with file references. Each session is limited to **100 MiB** and **10,000 files**. The files are removed at session teardown.
441
- - In proxy mode, `details.mcpResult` is kept raw when its JSON is **≤ 16 KiB**; larger results are replaced with a compact summary (block counts, sizes, key previews) and the raw JSON is saved to a temp file. Direct tools keep their lean details and never carry `mcpResult`.
466
+ - In proxy mode, `details.mcpResult` is kept raw when its JSON is **≤ 16 KiB**; larger results are replaced with a compact summary (block counts, sizes, key previews) and the raw JSON is saved to a temp file. Direct tools keep lean details unless `settings.directToolResultDetails` is set to `"bounded"`, which applies the same guarded `mcpResult` limit.
442
467
 
443
468
  Tune the text and details limits with the object form:
444
469
 
@@ -592,6 +617,10 @@ Each direct tool costs ~150-300 tokens in the system prompt (name + description
592
617
 
593
618
  Direct tools register from the metadata cache in the Pi agent dir (`~/.pi/agent/mcp-cache.json` by default, or `$PI_CODING_AGENT_DIR/mcp-cache.json` when set), so no server connections are needed at startup. On the first session after adding `directTools` to a new server, the cache won't exist yet — tools fall back to proxy-only while the cache populates, then the extension hot-loads the refreshed direct tools into the current session. Servers that advertise MCP list-change notifications refresh the current session when their tool or resource list changes. On Pi versions that expose `pi.unregisterTool()`, stale direct tools are removed from the registry during refresh; older Pi versions still deactivate them from the active tool set. To force a refresh: `/mcp reconnect <server>`.
594
619
 
620
+ Models sometimes encode an object or array argument as a JSON string. Set `settings.strictDirectToolArguments` to `true` to recover one such layer for schema-declared object and array properties, then validate the complete input against the advertised schema before execution.
621
+
622
+ Set `settings.directToolResultDetails` to `"bounded"` when an extension needs structured MCP result fields in Pi's direct-tool result details. The same output guard limits apply. Small leading structured fields stay available, while large fields receive bounded summaries and the complete guarded result follows the output guard's spill-file policy. The default `"lean"` mode keeps the existing server and tool metadata only.
623
+
595
624
  If prompt-cache stability matters more than automatic direct-tool hot-loading, set `settings.freezeDirectTools` to `true`. The initial direct-tool sync still runs, but later automatic reconnects, lazy-connects, and list-change notifications keep the registered tool surface unchanged. Deliberate refreshes through `mcp({ connect: "server" })` or `/mcp reconnect <server>` still update direct tools.
596
625
 
597
626
  When you change direct-tool toggles in `/mcp`, the extension updates direct tool registration in the current session. Broader setup writes from `/mcp setup` still use Pi's normal reload flow because they can add or restructure MCP config files.
@@ -730,9 +759,9 @@ Keys match a tool's original name, prefixed name, or a glob (`*` applies to ever
730
759
 
731
760
  When `includeSchemas` is enabled, search and describe render common JSON Schema parameters as compact TypeScript shapes like `{ query: string; limit?: number; }`, with the older schema formatter retained as a fallback for unsupported schemas.
732
761
 
733
- For HTTP servers, failed connects run a one-request shape probe that can turn opaque transport errors into setup hints such as `endpoint returned HTML (200) — this URL does not appear to speak MCP`. Healthy connections are not probed.
762
+ For HTTP servers, Pi reports HTTP 503 as temporary unavailability and does not add another immediate retry loop. Keep-alive servers keep cached metadata available and retry after 30 seconds, backing off to 5 minutes. Other failed connects run a one-request shape probe that can turn opaque transport errors into setup hints such as `endpoint returned HTML (200) — this URL does not appear to speak MCP`. Healthy connections are not probed.
734
763
 
735
- Servers that provide usage guidance via the MCP `instructions` field surface it at three levels: a truncated head in the `mcp` proxy tool description itself (so the model sees it without any call), a longer preview at the end of `mcp({ server: "name" })` listings, and the full text via `mcp({ instructions: "name" })`. Instructions are captured at connect time and cached alongside tool metadata, so they stay available without a live connection.
764
+ Servers that provide usage guidance via the MCP `instructions` field surface it through discovery paths: `mcp({ server: "name" })` includes a preview, and `mcp({ instructions: "name" })` returns the full text. Instructions are captured at connect time and cached alongside tool metadata, so they stay available without a live connection.
736
765
 
737
766
  ## Commands
738
767
 
@@ -17,6 +17,7 @@ import {
17
17
  writeStarterProjectConfig,
18
18
  } from "./config.ts";
19
19
  import { markKeepAliveAfterConnect, notifyToolMetadataUpdated, updateMetadataCache, updateStatusBar, getFailureAgeSeconds, getFailureMessage, clearFailure, recordFailure } from "./init.ts";
20
+ import { isServerInActiveFailureBackoff } from "./failure-backoff.ts";
20
21
  import { loadMetadataCache, reconstructPromptMetadata } from "./metadata-cache.ts";
21
22
  import { buildToolMetadata } from "./tool-metadata.ts";
22
23
  import { supportsOAuth, authenticate, removeAuth, type McpOAuthRuntime } from "./mcp-auth-flow.ts";
@@ -131,6 +132,7 @@ export async function showTools(state: McpExtensionState, ctx: ExtensionContext)
131
132
 
132
133
  const allTools = [...state.toolMetadata.entries()]
133
134
  .filter(([serverName]) => !isServerDisabled(state.config.mcpServers[serverName]))
135
+ .filter(([serverName]) => !isServerInActiveFailureBackoff(state, serverName))
134
136
  .flatMap(([, metadata]) => metadata.map(m => m.name));
135
137
 
136
138
  if (allTools.length === 0) {
@@ -196,9 +198,9 @@ export async function reconnectServer(
196
198
  state.serverInstructions.delete(name);
197
199
  }
198
200
  updateMetadataCache(state, name);
199
- notifyToolMetadataUpdated(state, name, "command-reconnect");
201
+ const restored = clearFailure(state, name, "command-reconnect");
202
+ if (!restored) notifyToolMetadataUpdated(state, name, "command-reconnect");
200
203
  markKeepAliveAfterConnect(state, name);
201
- clearFailure(state, name);
202
204
 
203
205
  if (ui) {
204
206
  ui.notify(
@@ -42,6 +42,16 @@ export const KNOWN_SERVER_PRESETS: readonly KnownServerPreset[] = [
42
42
  summary: "Look up current library documentation and examples.",
43
43
  entry: { url: "https://mcp.context7.com/mcp", protocolVersion: "auto" },
44
44
  },
45
+ {
46
+ id: "parallel-search",
47
+ name: "Parallel Search",
48
+ summary: "Search the web and fetch pages without an API key.",
49
+ entry: {
50
+ url: "https://search.parallel.ai/mcp",
51
+ protocolVersion: "auto",
52
+ directTools: true,
53
+ },
54
+ },
45
55
  {
46
56
  id: "notion",
47
57
  name: "Notion",
@@ -190,6 +200,7 @@ export function getConfigDiscoveryPaths(overridePath?: string, cwd = process.cwd
190
200
  }
191
201
 
192
202
  export function findAvailableImportConfigs(cwd = process.cwd()): DiscoveredImportConfig[] {
203
+ if (isExclusiveConfigMode()) return [];
193
204
  const discovered: DiscoveredImportConfig[] = [];
194
205
 
195
206
  for (const importKind of Object.keys(IMPORT_PATHS) as ImportKind[]) {
@@ -235,8 +246,11 @@ export function getMcpDiscoverySummary(
235
246
  const sources = getConfigSourceSummaries(sourceSpecs);
236
247
  const includeHostConfigs = options.includeHostConfigs !== false;
237
248
 
249
+ const importKinds = isExclusiveConfigMode()
250
+ ? (readValidatedConfig(getEffectivePiGlobalConfigPath(overridePath), "MCP exclusive config")?.imports ?? [])
251
+ : (Object.keys(IMPORT_PATHS) as ImportKind[]);
238
252
  const imports = includeHostConfigs
239
- ? (Object.keys(IMPORT_PATHS) as ImportKind[])
253
+ ? importKinds
240
254
  .map((kind) => {
241
255
  const imported = loadImportedConfig(kind, cwd, `Failed to inspect imported MCP config from ${kind}:`);
242
256
  if (!imported) return null;
@@ -248,10 +262,14 @@ export function getMcpDiscoverySummary(
248
262
  })
249
263
  .filter((value): value is ImportConfigSummary => value !== null)
250
264
  : [];
251
- const hostConfigDiscovery = getConfiguredHostConfigDiscovery(overridePath, cwd);
265
+ const hostConfigDiscovery = isExclusiveConfigMode()
266
+ ? "off"
267
+ : getConfiguredHostConfigDiscovery(overridePath, cwd);
252
268
  const hostConfigs = imports.map((entry) => ({ ...entry, active: hostConfigDiscovery === "on" }));
253
269
  const settings = getMergedSettings(overridePath, cwd);
254
- const agentPlugins = getAgentPluginSummaries(settings?.agentPluginPaths, cwd);
270
+ const agentPlugins = isExclusiveConfigMode()
271
+ ? []
272
+ : getAgentPluginSummaries(settings?.agentPluginPaths, cwd);
255
273
  const totalServerCount = sources.reduce((sum, source) => sum + source.serverCount, 0) + agentPlugins.reduce((sum, plugin) => sum + plugin.serverCount, 0);
256
274
  const hasSharedServers = sources.some((source) => source.kind === "shared" && source.serverCount > 0) || agentPlugins.some(plugin => plugin.serverCount > 0);
257
275
  const hasPiOwnedServers = sources.some((source) => source.kind === "pi" && source.serverCount > 0);
@@ -297,7 +315,7 @@ export function loadMcpConfig(overridePath?: string, cwd = process.cwd()): McpCo
297
315
  // Host files are a lower-precedence fallback. This ordering means an opt-in
298
316
  // discovery cannot override a shared or Pi-owned definition, and all normal
299
317
  // URL-bound credential stripping remains in mergeServerMaps.
300
- let config: McpConfig = hostConfigDiscovery === "on"
318
+ let config: McpConfig = !isExclusiveConfigMode() && hostConfigDiscovery === "on"
301
319
  ? loadDiscoveredHostConfigs(cwd)
302
320
  : { mcpServers: {} };
303
321
 
@@ -307,6 +325,8 @@ export function loadMcpConfig(overridePath?: string, cwd = process.cwd()): McpCo
307
325
  config = mergeConfigs(config, expandImports(loaded, cwd));
308
326
  }
309
327
 
328
+ if (isExclusiveConfigMode()) return config;
329
+
310
330
  const packageConfig = loadPackageMcpConfigs(cwd);
311
331
  const pluginConfig = loadAgentPluginConfigs(config.settings?.agentPluginPaths, cwd);
312
332
  const packageServers = Object.fromEntries(
@@ -392,11 +412,23 @@ function getConfigConflicts(
392
412
  }
393
413
 
394
414
  function getConfigSources(overridePath?: string, cwd = process.cwd()): ConfigSourceSpec[] {
395
- const userPath = getPiGlobalConfigPath(overridePath);
415
+ const userPath = getEffectivePiGlobalConfigPath(overridePath);
396
416
  const projectPath = getProjectConfigPath(cwd);
397
417
  const projectPiPath = getProjectPiConfigPath(cwd);
398
418
  const sources: ConfigSourceSpec[] = [];
399
419
 
420
+ if (isExclusiveConfigMode()) {
421
+ return [{
422
+ id: "pi-global",
423
+ label: "Pi exclusive config",
424
+ readPath: userPath,
425
+ writePath: userPath,
426
+ kind: "user",
427
+ shared: false,
428
+ scope: "global",
429
+ }];
430
+ }
431
+
400
432
  if (GENERIC_GLOBAL_CONFIG_PATH !== userPath) {
401
433
  sources.push({
402
434
  id: "shared-global",
@@ -461,6 +493,14 @@ function getConfigSources(overridePath?: string, cwd = process.cwd()): ConfigSou
461
493
  return sources;
462
494
  }
463
495
 
496
+ function isExclusiveConfigMode(): boolean {
497
+ return process.env.PI_MCP_CONFIG_MODE?.trim().toLowerCase() === "exclusive";
498
+ }
499
+
500
+ function getEffectivePiGlobalConfigPath(overridePath?: string): string {
501
+ return getPiGlobalConfigPath(isExclusiveConfigMode() ? undefined : overridePath);
502
+ }
503
+
464
504
  function mergeConfigs(base: McpConfig, next: McpConfig): McpConfig {
465
505
  const imports = mergeImports(base.imports, next.imports);
466
506
  const settings = next.settings ? { ...base.settings, ...next.settings } : base.settings;
@@ -15,16 +15,16 @@ import { createToolSelectorCandidateIndex, formatToolName, getToolNameCandidates
15
15
  import { isUiToolVisibleToModel } from "./ui-tool-visibility.ts";
16
16
  import { resourceNameToToolName } from "./resource-tools.ts";
17
17
  import { authenticate, supportsOAuth } from "./mcp-auth-flow.ts";
18
- import { formatAuthRequiredMessage, normalizeToolArguments, resolveServerUrl, truncateAtWord } from "./utils.ts";
18
+ import { formatAuthRequiredMessage, normalizeToolArguments, resolveServerUrl } from "./utils.ts";
19
19
  import { SessionRecoveryAuthRequiredError, withSessionRecovery } from "./session-recovery.ts";
20
20
  import { combineAbortSignals, isAbortError } from "./runtime-owner.ts";
21
21
  import { ensureToolCallApproved } from "./tool-approval.ts";
22
+ import { Check, Errors } from "typebox/value";
22
23
 
23
24
  type ClientCallToolResult = Awaited<ReturnType<Client["callTool"]>>;
24
25
  type ClientReadResourceResult = Awaited<ReturnType<Client["readResource"]>>;
25
26
 
26
27
  const BUILTIN_NAMES = new Set(["read", "bash", "edit", "write", "grep", "find", "ls", "mcp"]);
27
- const INSTRUCTIONS_SNIPPET_LENGTH = 150;
28
28
  export const DIRECT_TOOLS_ADVISORY_THRESHOLD = 75;
29
29
 
30
30
  type DirectAutoAuthResult =
@@ -32,6 +32,58 @@ type DirectAutoAuthResult =
32
32
  | { status: "success" }
33
33
  | { status: "failed"; message: string };
34
34
 
35
+ /**
36
+ * Recover one model-emitted JSON layer for schema-declared object and array
37
+ * properties, then validate the complete input against the same schema.
38
+ */
39
+ export function prepareDirectToolArguments(inputSchema: unknown, args: unknown): unknown {
40
+ if (!inputSchema || typeof inputSchema !== "object" || Array.isArray(inputSchema)) return args;
41
+ const schema = inputSchema as Record<string, unknown>;
42
+ if (schema.type !== "object") return args;
43
+ const input = args && typeof args === "object" && !Array.isArray(args)
44
+ ? args as Record<string, unknown>
45
+ : null;
46
+ const properties = schema.properties;
47
+ let prepared: Record<string, unknown> | undefined;
48
+
49
+ if (input && properties && typeof properties === "object" && !Array.isArray(properties)) {
50
+ for (const [name, propertySchema] of Object.entries(properties)) {
51
+ if (!Object.hasOwn(input, name) || typeof input[name] !== "string"
52
+ || !propertySchema || typeof propertySchema !== "object" || Array.isArray(propertySchema)) continue;
53
+ const expectedType = (propertySchema as Record<string, unknown>).type;
54
+ if (expectedType !== "object" && expectedType !== "array") continue;
55
+ try {
56
+ const parsed: unknown = JSON.parse(input[name] as string);
57
+ const matches = expectedType === "array"
58
+ ? Array.isArray(parsed)
59
+ : parsed !== null && typeof parsed === "object" && !Array.isArray(parsed);
60
+ if (matches) {
61
+ prepared ??= { ...input };
62
+ prepared[name] = parsed;
63
+ }
64
+ } catch {
65
+ // Validation below reports malformed or shape-incompatible values.
66
+ }
67
+ }
68
+ }
69
+
70
+ const candidate = prepared ?? args;
71
+ if (!Check(inputSchema as never, candidate)) {
72
+ const errors = Errors(inputSchema as never, candidate);
73
+ const issues = errors.slice(0, 8).map((error) => ({
74
+ instancePath: error.instancePath || "/",
75
+ keyword: error.keyword,
76
+ message: error.message,
77
+ }));
78
+ throw new TypeError(`MCP direct tool arguments do not match the advertised input schema: ${JSON.stringify({
79
+ issues,
80
+ total: errors.length,
81
+ truncated: errors.length > issues.length,
82
+ })}`);
83
+ }
84
+ return candidate;
85
+ }
86
+
35
87
  function getDirectAuthRequiredMessage(
36
88
  state: McpExtensionState,
37
89
  serverName: string,
@@ -117,6 +169,8 @@ export function resolveDirectTools(
117
169
  cache: MetadataCache | null,
118
170
  prefix: ToolPrefix,
119
171
  envOverride?: string[],
172
+ unavailableServers: ReadonlySet<string> = new Set(),
173
+ reservedNames?: Set<string>,
120
174
  ): DirectToolSpec[] {
121
175
  const specs: DirectToolSpec[] = [];
122
176
  if (!cache) return specs;
@@ -224,82 +278,33 @@ export function resolveDirectTools(
224
278
  }
225
279
  }
226
280
 
227
- if (config.settings?.warnOnLargeDirectTools !== false && specs.length >= DIRECT_TOOLS_ADVISORY_THRESHOLD) {
228
- console.warn(`MCP: ${specs.length} direct tools resolved. Each direct tool adds prompt context; README guidance recommends targeted sets of 5-20 tools and using the proxy or an explicit string[] when 75+ direct tools would be registered.`);
281
+ for (const spec of specs) reservedNames?.add(spec.prefixedName);
282
+
283
+ const emittedSpecs = unavailableServers.size === 0
284
+ ? specs
285
+ : specs.filter((spec) => !unavailableServers.has(spec.serverName));
286
+
287
+ if (config.settings?.warnOnLargeDirectTools !== false && emittedSpecs.length >= DIRECT_TOOLS_ADVISORY_THRESHOLD) {
288
+ console.warn(`MCP: ${emittedSpecs.length} direct tools resolved. Each direct tool adds prompt context; README guidance recommends targeted sets of 5-20 tools and using the proxy or an explicit string[] when 75+ direct tools would be registered. Set settings.warnOnLargeDirectTools to false to hide this advisory.`);
229
289
  }
230
290
 
231
- return specs;
291
+ return emittedSpecs;
232
292
  }
233
293
 
234
- export function buildProxyDescription(
235
- config: McpConfig,
236
- cache: MetadataCache | null,
237
- directSpecs: DirectToolSpec[],
238
- ): string {
239
- const prefix = config.settings?.toolPrefix ?? "server";
294
+ /**
295
+ * Pure function of config: the description must stay byte-stable across
296
+ * runtime metadata changes (tool counts, instructions, connection state) so
297
+ * re-registering the proxy tool never rewrites the cached prompt prefix.
298
+ * Live counts/status belong to `mcp({ })`, full instructions to
299
+ * `mcp({ instructions })`.
300
+ */
301
+ export function buildProxyDescription(config: McpConfig): string {
240
302
  let desc = `MCP gateway — server status, tool search/describe, auth, and single MCP tool calls. When one request needs several MCP calls with logic between them, use mcpScript. Non-MCP Pi tools should be called directly, not through mcp.\n`;
241
303
 
242
- const directByServer = new Map<string, number>();
243
- for (const spec of directSpecs) {
244
- directByServer.set(spec.serverName, (directByServer.get(spec.serverName) ?? 0) + 1);
245
- }
246
- if (directByServer.size > 0) {
247
- const parts = [...directByServer.entries()].map(
248
- ([server, count]) => `${server} (${count})`,
249
- );
250
- desc += `\nDirect tools available (call as normal tools): ${parts.join(", ")}\n`;
251
- }
252
-
253
- const serverSummaries: string[] = [];
254
- for (const serverName of Object.keys(config.mcpServers)) {
255
- const definition = config.mcpServers[serverName];
256
- if (!definition || isServerDisabled(definition)) continue;
257
- const cachedEntry = cache?.servers?.[serverName];
258
- const entry = cachedEntry && isServerCacheValid(cachedEntry, definition) ? cachedEntry : undefined;
259
- const effectivePrefix = resolveToolPrefix(definition, prefix);
260
- const hasToolFilters =
261
- (Array.isArray(definition.includeTools) && definition.includeTools.length > 0) ||
262
- (Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0);
263
- const selectorCandidateIndex = hasToolFilters && cache ? (() => {
264
- const candidates = new Set<string>();
265
- for (const [otherServerName, otherDefinition] of Object.entries(config.mcpServers)) {
266
- const otherEntry = cache.servers[otherServerName];
267
- if (!otherEntry || !isServerCacheValid(otherEntry, otherDefinition) || isServerDisabled(otherDefinition)) continue;
268
- const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
269
- for (const otherTool of otherEntry.tools ?? []) {
270
- if (!isUiToolVisibleToModel(otherTool.uiVisibility)) continue;
271
- for (const candidate of getToolNameCandidates(otherTool.name, otherServerName, otherPrefix, false)) candidates.add(candidate);
272
- }
273
- if (otherDefinition.exposeResources !== false) {
274
- for (const resource of otherEntry.resources ?? []) {
275
- const baseName = `read_${resourceNameToToolName(resource.name)}`;
276
- for (const candidate of getToolNameCandidates(baseName, otherServerName, otherPrefix, false)) candidates.add(candidate);
277
- }
278
- }
279
- }
280
- return createToolSelectorCandidateIndex(candidates);
281
- })() : undefined;
282
- const toolCount = (entry?.tools ?? []).filter(
283
- (tool) => isUiToolVisibleToModel(tool.uiVisibility)
284
- && isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex),
285
- ).length;
286
- const resourceCount = definition?.exposeResources !== false
287
- ? (entry?.resources ?? []).filter((resource) => {
288
- const baseName = `read_${resourceNameToToolName(resource.name)}`;
289
- return isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex);
290
- }).length
291
- : 0;
292
- const totalItems = toolCount + resourceCount;
293
- if (totalItems === 0) continue;
294
- const directCount = directByServer.get(serverName) ?? 0;
295
- const proxyCount = totalItems - directCount;
296
- if (proxyCount > 0) {
297
- serverSummaries.push(`${serverName} (${proxyCount} tools)`);
298
- }
299
- }
300
-
301
- if (serverSummaries.length > 0) {
302
- desc += `\nServers: ${serverSummaries.join(", ")}\n`;
304
+ const serverNames = Object.keys(config.mcpServers)
305
+ .filter((serverName) => !isServerDisabled(config.mcpServers[serverName]));
306
+ if (serverNames.length > 0) {
307
+ desc += `\nServers: ${serverNames.join(", ")}\n`;
303
308
  }
304
309
 
305
310
  const disabledServers = Object.entries(config.mcpServers)
@@ -309,22 +314,8 @@ export function buildProxyDescription(
309
314
  desc += `\nDisabled servers (enable with /mcp enable <server> and /reload): ${disabledServers.join(", ")}\n`;
310
315
  }
311
316
 
312
- const instructionSummaries: string[] = [];
313
- for (const serverName of Object.keys(config.mcpServers)) {
314
- if (isServerDisabled(config.mcpServers[serverName])) continue;
315
- const definition = config.mcpServers[serverName];
316
- const entry = definition && cache?.servers?.[serverName];
317
- const instructions = entry && definition && isServerCacheValid(entry, definition) ? entry.instructions : undefined;
318
- if (!instructions) continue;
319
- const snippet = truncateAtWord(instructions.replace(/\s+/g, " ").trim(), INSTRUCTIONS_SNIPPET_LENGTH);
320
- instructionSummaries.push(` ${serverName}: ${snippet}`);
321
- }
322
- if (instructionSummaries.length > 0) {
323
- desc += `\nServer instructions (truncated - full text via mcp({ instructions: "name" })):\n${instructionSummaries.join("\n")}\n`;
324
- }
325
-
326
317
  desc += `\nUsage:\n`;
327
- desc += ` mcp({ }) → Show server status\n`;
318
+ desc += ` mcp({ }) → Show server status and tool counts\n`;
328
319
  desc += ` mcp({ server: "name" }) → List tools from server\n`;
329
320
  desc += ` mcp({ search: "query" }) → Search MCP tools by name/description\n`;
330
321
  desc += ` mcp({ describe: "tool_name" }) → Show tool details and parameters\n`;
@@ -498,7 +489,10 @@ export function createDirectToolExecutor(
498
489
  (conn) => conn.client.readResource({ uri: spec.resourceUri! }, requestOptions),
499
490
  );
500
491
  const content = transformMcpResourceContents(result.contents ?? [], state.owner?.signal);
501
- const guarded = await guardMcpOutput(content.length > 0 ? content : [{ type: "text" as const, text: "(empty resource)" }], outputGuardOptions);
492
+ const guarded = await guardMcpOutput(content.length > 0 ? content : [{ type: "text" as const, text: "(empty resource)" }], {
493
+ ...outputGuardOptions,
494
+ ...(state.config.settings?.directToolResultDetails === "bounded" ? { rawMcpResult: result } : {}),
495
+ });
502
496
  return {
503
497
  content: guarded.content,
504
498
  details: { server: spec.serverName, resourceUri: spec.resourceUri, ...guardedMcpDetails(guarded) },
@@ -539,7 +533,13 @@ export function createDirectToolExecutor(
539
533
  const content = transformMcpContent(mcpContent, state.owner?.signal);
540
534
  const outputContent = content.length > 0 ? content : [{ type: "text" as const, text: "(empty result)" }];
541
535
  const schemaText = spec.inputSchema ? `\n\nExpected parameters:\n${formatSchema(spec.inputSchema)}` : "";
542
- const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions, prefix: "Error: ", suffix: schemaText, emptyTextFallback: "Tool execution failed" });
536
+ const guarded = await guardMcpOutput(outputContent, {
537
+ ...outputGuardOptions,
538
+ prefix: "Error: ",
539
+ suffix: schemaText,
540
+ emptyTextFallback: "Tool execution failed",
541
+ ...(state.config.settings?.directToolResultDetails === "bounded" ? { rawMcpResult: result } : {}),
542
+ });
543
543
  return {
544
544
  content: guarded.content,
545
545
  details: { error: "tool_error", server: spec.serverName, ...guardedMcpDetails(guarded) },
@@ -550,7 +550,11 @@ export function createDirectToolExecutor(
550
550
  const outputContent = content.length > 0 ? content : [{ type: "text" as const, text: "(empty result)" }];
551
551
  if (hasUi) {
552
552
  const uiSummary = summarizeUiSessionResult(uiSession);
553
- const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions, suffix: `\n\n${uiSummary.message}` });
553
+ const guarded = await guardMcpOutput(outputContent, {
554
+ ...outputGuardOptions,
555
+ suffix: `\n\n${uiSummary.message}`,
556
+ ...(state.config.settings?.directToolResultDetails === "bounded" ? { rawMcpResult: result } : {}),
557
+ });
554
558
  return {
555
559
  content: guarded.content,
556
560
  details: {
@@ -564,7 +568,10 @@ export function createDirectToolExecutor(
564
568
  };
565
569
  }
566
570
 
567
- const guarded = await guardMcpOutput(outputContent, { ...outputGuardOptions });
571
+ const guarded = await guardMcpOutput(outputContent, {
572
+ ...outputGuardOptions,
573
+ ...(state.config.settings?.directToolResultDetails === "bounded" ? { rawMcpResult: result } : {}),
574
+ });
568
575
  return {
569
576
  content: guarded.content,
570
577
  details: { server: spec.serverName, tool: spec.originalName, ...guardedMcpDetails(guarded) },
@@ -590,12 +597,16 @@ export function createDirectToolExecutor(
590
597
  };
591
598
  }
592
599
  const message = error instanceof Error ? error.message : String(error);
600
+ const aborted = isAbortError(error, ownedSignal);
601
+ if (!aborted) {
602
+ await state.manager.close(spec.serverName).catch(() => {});
603
+ }
593
604
  uiSession?.sendToolCancelled(message);
594
605
  const schemaText = spec.inputSchema ? `\n\nExpected parameters:\n${formatSchema(spec.inputSchema)}` : "";
595
606
  const guarded = await guardMcpOutput([{ type: "text" as const, text: message }], { ...outputGuardOptions, prefix: "Failed to call tool: ", suffix: schemaText });
596
607
  return {
597
608
  content: guarded.content,
598
- details: { error: isAbortError(error, ownedSignal) ? "aborted" : "call_failed", server: spec.serverName, ...guardedMcpDetails(guarded) },
609
+ details: { error: aborted ? "aborted" : "call_failed", server: spec.serverName, ...guardedMcpDetails(guarded) },
599
610
  };
600
611
  } finally {
601
612
  if (uiSession?.reused) {
@@ -0,0 +1,10 @@
1
+ export declare function getConfigDirName(): string;
2
+ export declare function getAgentDir(): string;
3
+ export declare function getAgentPath(...segments: string[]): string;
4
+ export declare function getAppName(): string;
5
+ /**
6
+ * Home page the host declares for itself, via `piConfig.clientUri` in the same
7
+ * manifest that carries `piConfig.name`. Only the distribution knows its own
8
+ * URL, so this is the one place it can come from without guessing.
9
+ */
10
+ export declare function getAppClientUri(): string | undefined;