@herbertgao/pi-extensions 2026.9.17 → 2026.9.19

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 (307) hide show
  1. package/README.md +31 -33
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/node_modules/@herbertgao/pi-bark/package.json +2 -2
  4. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +4 -1
  5. package/node_modules/@herbertgao/pi-cc-extensions/README.md +4 -1
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/working-message.ts +21 -6
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +15 -4
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/index.ts +43 -7
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +7 -2
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +1 -1
  11. package/node_modules/@herbertgao/pi-cc-extensions/package.json +75 -75
  12. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  13. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  14. package/node_modules/@herbertgao/resume-from/package.json +4 -2
  15. package/node_modules/@herbertgao/sol-pi/package.json +6 -6
  16. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +99 -99
  17. package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
  18. package/node_modules/@tifan/pi-handoff/package.json +1 -1
  19. package/node_modules/@tifan/pi-handoff/src/index.ts +56 -26
  20. package/node_modules/@tifan/pi-mermaid-open/package.json +1 -1
  21. package/node_modules/@tifan/pi-preferred-thinking/package.json +1 -1
  22. package/node_modules/@tifan/pi-recap/package.json +1 -1
  23. package/node_modules/@tifan/pi-rename/package.json +1 -1
  24. package/node_modules/pi-antigravity/README.md +29 -6
  25. package/node_modules/pi-antigravity/package.json +14 -9
  26. package/node_modules/pi-antigravity/src/auth/accounts.ts +327 -0
  27. package/node_modules/pi-antigravity/src/auth/index.ts +9 -0
  28. package/node_modules/pi-antigravity/src/client/client.ts +1 -1
  29. package/node_modules/pi-antigravity/src/image/image.ts +4 -4
  30. package/node_modules/pi-antigravity/src/index.ts +203 -13
  31. package/node_modules/pi-antigravity/src/search/index.ts +1 -0
  32. package/node_modules/pi-antigravity/src/search/search.ts +325 -0
  33. package/node_modules/pi-antigravity/src/stream/stream.ts +191 -14
  34. package/node_modules/pi-antigravity/src/types/enums.ts +45 -36
  35. package/node_modules/pi-antigravity/src/types/types.ts +5 -12
  36. package/node_modules/pi-antigravity/src/utils/http.ts +7 -2
  37. package/node_modules/pi-antigravity/src/utils/util.ts +31 -3
  38. package/node_modules/pi-lens/package.json +158 -158
  39. package/node_modules/pi-multi-account/package.json +2 -2
  40. package/node_modules/pi-typesafe/README.md +3 -1
  41. package/node_modules/pi-typesafe/dist/auth.d.ts +9 -5
  42. package/node_modules/pi-typesafe/dist/auth.js +7 -3
  43. package/node_modules/pi-typesafe/dist/backends.d.ts +33 -3
  44. package/node_modules/pi-typesafe/dist/backends.js +95 -1
  45. package/node_modules/pi-typesafe/dist/client.d.ts +5 -5
  46. package/node_modules/pi-typesafe/dist/client.js +12 -9
  47. package/node_modules/pi-typesafe/dist/credentials.d.ts +14 -8
  48. package/node_modules/pi-typesafe/dist/credentials.js +10 -7
  49. package/node_modules/pi-typesafe/dist/errors.d.ts +2 -2
  50. package/node_modules/pi-typesafe/dist/index.d.ts +2 -2
  51. package/node_modules/pi-typesafe/dist/index.js +1 -1
  52. package/node_modules/pi-typesafe/dist/login.d.ts +2 -2
  53. package/node_modules/pi-typesafe/dist/login.js +2 -2
  54. package/node_modules/pi-typesafe/package.json +6 -5
  55. package/node_modules/pi-web-access/CHANGELOG.md +72 -0
  56. package/node_modules/pi-web-access/README.md +34 -13
  57. package/node_modules/pi-web-access/chrome-cookies.ts +79 -25
  58. package/node_modules/pi-web-access/curator-page.ts +5 -1
  59. package/node_modules/pi-web-access/curator-server.ts +2 -0
  60. package/node_modules/pi-web-access/dist/index.js +1337 -1009
  61. package/node_modules/pi-web-access/exa.ts +20 -52
  62. package/node_modules/pi-web-access/extract.ts +41 -4
  63. package/node_modules/pi-web-access/gemini-search.ts +12 -4
  64. package/node_modules/pi-web-access/index.ts +29 -37
  65. package/node_modules/pi-web-access/openai-search.ts +35 -7
  66. package/node_modules/pi-web-access/package.json +8 -7
  67. package/node_modules/pi-web-access/page-query.ts +2 -2
  68. package/node_modules/pi-web-access/query-rewrite.ts +2 -3
  69. package/node_modules/pi-web-access/ssrf-protection.ts +27 -10
  70. package/node_modules/pi-web-access/storage.ts +48 -77
  71. package/node_modules/pi-web-access/summary-model-scope.ts +6 -77
  72. package/node_modules/pi-web-access/summary-review.ts +3 -4
  73. package/node_modules/pi-web-access/tavily.ts +67 -20
  74. package/node_modules/pi-web-access/tool-activation.ts +53 -33
  75. package/node_modules/pi-web-access/utils.ts +1 -1
  76. package/node_modules/pi-web-access/you.ts +164 -0
  77. package/node_modules/pi-web-access/zai.ts +161 -0
  78. package/node_modules/remote-pi/package.json +5 -1
  79. package/package.json +19 -31
  80. package/node_modules/pi-mcp-adapter/CHANGELOG.md +0 -1013
  81. package/node_modules/pi-mcp-adapter/LICENSE +0 -21
  82. package/node_modules/pi-mcp-adapter/OAUTH.md +0 -369
  83. package/node_modules/pi-mcp-adapter/README.md +0 -1021
  84. package/node_modules/pi-mcp-adapter/abort.ts +0 -34
  85. package/node_modules/pi-mcp-adapter/agent-dir.ts +0 -68
  86. package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +0 -416
  87. package/node_modules/pi-mcp-adapter/agent-plugin-provenance.ts +0 -36
  88. package/node_modules/pi-mcp-adapter/app-bridge.bundle.js +0 -67
  89. package/node_modules/pi-mcp-adapter/banner.png +0 -0
  90. package/node_modules/pi-mcp-adapter/bearer-command-resolver.ts +0 -193
  91. package/node_modules/pi-mcp-adapter/claude-plugin-loader.ts +0 -365
  92. package/node_modules/pi-mcp-adapter/cli.js +0 -454
  93. package/node_modules/pi-mcp-adapter/commands.ts +0 -861
  94. package/node_modules/pi-mcp-adapter/config.ts +0 -1565
  95. package/node_modules/pi-mcp-adapter/consent-manager.ts +0 -95
  96. package/node_modules/pi-mcp-adapter/direct-tool-surface.ts +0 -244
  97. package/node_modules/pi-mcp-adapter/direct-tools.ts +0 -428
  98. package/node_modules/pi-mcp-adapter/dist/abort.d.ts +0 -2
  99. package/node_modules/pi-mcp-adapter/dist/abort.js +0 -36
  100. package/node_modules/pi-mcp-adapter/dist/abort.js.map +0 -1
  101. package/node_modules/pi-mcp-adapter/dist/agent-dir.d.ts +0 -10
  102. package/node_modules/pi-mcp-adapter/dist/agent-dir.js +0 -63
  103. package/node_modules/pi-mcp-adapter/dist/agent-dir.js.map +0 -1
  104. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.d.ts +0 -8
  105. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +0 -398
  106. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +0 -1
  107. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.d.ts +0 -1
  108. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js +0 -31
  109. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js.map +0 -1
  110. package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.d.ts +0 -6
  111. package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.js +0 -194
  112. package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.js.map +0 -1
  113. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.d.ts +0 -9
  114. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js +0 -362
  115. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js.map +0 -1
  116. package/node_modules/pi-mcp-adapter/dist/config.d.ts +0 -134
  117. package/node_modules/pi-mcp-adapter/dist/config.js +0 -1361
  118. package/node_modules/pi-mcp-adapter/dist/config.js.map +0 -1
  119. package/node_modules/pi-mcp-adapter/dist/consent-manager.d.ts +0 -18
  120. package/node_modules/pi-mcp-adapter/dist/consent-manager.js +0 -88
  121. package/node_modules/pi-mcp-adapter/dist/consent-manager.js.map +0 -1
  122. package/node_modules/pi-mcp-adapter/dist/elicitation-handler.d.ts +0 -17
  123. package/node_modules/pi-mcp-adapter/dist/elicitation-handler.js +0 -316
  124. package/node_modules/pi-mcp-adapter/dist/elicitation-handler.js.map +0 -1
  125. package/node_modules/pi-mcp-adapter/dist/errors.d.ts +0 -131
  126. package/node_modules/pi-mcp-adapter/dist/errors.js +0 -278
  127. package/node_modules/pi-mcp-adapter/dist/errors.js.map +0 -1
  128. package/node_modules/pi-mcp-adapter/dist/http-ca.d.ts +0 -8
  129. package/node_modules/pi-mcp-adapter/dist/http-ca.js +0 -88
  130. package/node_modules/pi-mcp-adapter/dist/http-ca.js.map +0 -1
  131. package/node_modules/pi-mcp-adapter/dist/jev-client.d.ts +0 -14
  132. package/node_modules/pi-mcp-adapter/dist/jev-client.js +0 -367
  133. package/node_modules/pi-mcp-adapter/dist/jev-client.js.map +0 -1
  134. package/node_modules/pi-mcp-adapter/dist/jev-contracts.d.ts +0 -77
  135. package/node_modules/pi-mcp-adapter/dist/jev-contracts.js +0 -2
  136. package/node_modules/pi-mcp-adapter/dist/jev-contracts.js.map +0 -1
  137. package/node_modules/pi-mcp-adapter/dist/jev-key-store.d.ts +0 -51
  138. package/node_modules/pi-mcp-adapter/dist/jev-key-store.js +0 -205
  139. package/node_modules/pi-mcp-adapter/dist/jev-key-store.js.map +0 -1
  140. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.d.ts +0 -2
  141. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js +0 -68
  142. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js.map +0 -1
  143. package/node_modules/pi-mcp-adapter/dist/lifecycle.d.ts +0 -56
  144. package/node_modules/pi-mcp-adapter/dist/lifecycle.js +0 -410
  145. package/node_modules/pi-mcp-adapter/dist/lifecycle.js.map +0 -1
  146. package/node_modules/pi-mcp-adapter/dist/logger.d.ts +0 -51
  147. package/node_modules/pi-mcp-adapter/dist/logger.js +0 -131
  148. package/node_modules/pi-mcp-adapter/dist/logger.js.map +0 -1
  149. package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.d.ts +0 -26
  150. package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.js +0 -103
  151. package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.js.map +0 -1
  152. package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.d.ts +0 -118
  153. package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.js +0 -1097
  154. package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.js.map +0 -1
  155. package/node_modules/pi-mcp-adapter/dist/mcp-auth.d.ts +0 -170
  156. package/node_modules/pi-mcp-adapter/dist/mcp-auth.js +0 -1142
  157. package/node_modules/pi-mcp-adapter/dist/mcp-auth.js.map +0 -1
  158. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.d.ts +0 -24
  159. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js +0 -203
  160. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js.map +0 -1
  161. package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.d.ts +0 -53
  162. package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.js +0 -441
  163. package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.js.map +0 -1
  164. package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.d.ts +0 -148
  165. package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.js +0 -689
  166. package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.js.map +0 -1
  167. package/node_modules/pi-mcp-adapter/dist/mcp-probe.d.ts +0 -6
  168. package/node_modules/pi-mcp-adapter/dist/mcp-probe.js +0 -166
  169. package/node_modules/pi-mcp-adapter/dist/mcp-probe.js.map +0 -1
  170. package/node_modules/pi-mcp-adapter/dist/mcp-tasks.d.ts +0 -102
  171. package/node_modules/pi-mcp-adapter/dist/mcp-tasks.js +0 -369
  172. package/node_modules/pi-mcp-adapter/dist/mcp-tasks.js.map +0 -1
  173. package/node_modules/pi-mcp-adapter/dist/mcp-trace.d.ts +0 -95
  174. package/node_modules/pi-mcp-adapter/dist/mcp-trace.js +0 -242
  175. package/node_modules/pi-mcp-adapter/dist/mcp-trace.js.map +0 -1
  176. package/node_modules/pi-mcp-adapter/dist/metadata-cache.d.ts +0 -19
  177. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +0 -301
  178. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +0 -1
  179. package/node_modules/pi-mcp-adapter/dist/npx-resolver.d.ts +0 -6
  180. package/node_modules/pi-mcp-adapter/dist/npx-resolver.js +0 -505
  181. package/node_modules/pi-mcp-adapter/dist/npx-resolver.js.map +0 -1
  182. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.d.ts +0 -2
  183. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +0 -144
  184. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +0 -1
  185. package/node_modules/pi-mcp-adapter/dist/request-headers-command.d.ts +0 -10
  186. package/node_modules/pi-mcp-adapter/dist/request-headers-command.js +0 -312
  187. package/node_modules/pi-mcp-adapter/dist/request-headers-command.js.map +0 -1
  188. package/node_modules/pi-mcp-adapter/dist/resource-tools.d.ts +0 -1
  189. package/node_modules/pi-mcp-adapter/dist/resource-tools.js +0 -15
  190. package/node_modules/pi-mcp-adapter/dist/resource-tools.js.map +0 -1
  191. package/node_modules/pi-mcp-adapter/dist/runtime-owner.d.ts +0 -13
  192. package/node_modules/pi-mcp-adapter/dist/runtime-owner.js +0 -97
  193. package/node_modules/pi-mcp-adapter/dist/runtime-owner.js.map +0 -1
  194. package/node_modules/pi-mcp-adapter/dist/sampling-handler.d.ts +0 -17
  195. package/node_modules/pi-mcp-adapter/dist/sampling-handler.js +0 -203
  196. package/node_modules/pi-mcp-adapter/dist/sampling-handler.js.map +0 -1
  197. package/node_modules/pi-mcp-adapter/dist/secure-keyring.d.ts +0 -11
  198. package/node_modules/pi-mcp-adapter/dist/secure-keyring.js +0 -172
  199. package/node_modules/pi-mcp-adapter/dist/secure-keyring.js.map +0 -1
  200. package/node_modules/pi-mcp-adapter/dist/server-manager.d.ts +0 -157
  201. package/node_modules/pi-mcp-adapter/dist/server-manager.js +0 -1745
  202. package/node_modules/pi-mcp-adapter/dist/server-manager.js.map +0 -1
  203. package/node_modules/pi-mcp-adapter/dist/session-approvals.d.ts +0 -34
  204. package/node_modules/pi-mcp-adapter/dist/session-approvals.js +0 -140
  205. package/node_modules/pi-mcp-adapter/dist/session-approvals.js.map +0 -1
  206. package/node_modules/pi-mcp-adapter/dist/session-recovery.d.ts +0 -26
  207. package/node_modules/pi-mcp-adapter/dist/session-recovery.js +0 -142
  208. package/node_modules/pi-mcp-adapter/dist/session-recovery.js.map +0 -1
  209. package/node_modules/pi-mcp-adapter/dist/state.d.ts +0 -73
  210. package/node_modules/pi-mcp-adapter/dist/state.js +0 -2
  211. package/node_modules/pi-mcp-adapter/dist/state.js.map +0 -1
  212. package/node_modules/pi-mcp-adapter/dist/types.d.ts +0 -642
  213. package/node_modules/pi-mcp-adapter/dist/types.js +0 -331
  214. package/node_modules/pi-mcp-adapter/dist/types.js.map +0 -1
  215. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.d.ts +0 -6
  216. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js +0 -37
  217. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js.map +0 -1
  218. package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.d.ts +0 -17
  219. package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.js +0 -219
  220. package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.js.map +0 -1
  221. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.d.ts +0 -104
  222. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js +0 -59
  223. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js.map +0 -1
  224. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.d.ts +0 -4
  225. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js +0 -27
  226. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js.map +0 -1
  227. package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.d.ts +0 -15
  228. package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.js +0 -85
  229. package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.js.map +0 -1
  230. package/node_modules/pi-mcp-adapter/dist/utils.d.ts +0 -41
  231. package/node_modules/pi-mcp-adapter/dist/utils.js +0 -417
  232. package/node_modules/pi-mcp-adapter/dist/utils.js.map +0 -1
  233. package/node_modules/pi-mcp-adapter/elicitation-handler.ts +0 -358
  234. package/node_modules/pi-mcp-adapter/error-signal.ts +0 -32
  235. package/node_modules/pi-mcp-adapter/errors.ts +0 -364
  236. package/node_modules/pi-mcp-adapter/examples/jev-accessibility-loop.mjs +0 -85
  237. package/node_modules/pi-mcp-adapter/examples/jev-semantic-filter.mjs +0 -34
  238. package/node_modules/pi-mcp-adapter/failure-backoff.ts +0 -23
  239. package/node_modules/pi-mcp-adapter/glimpse-ui.ts +0 -80
  240. package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -515
  241. package/node_modules/pi-mcp-adapter/http-ca.ts +0 -84
  242. package/node_modules/pi-mcp-adapter/index.ts +0 -2106
  243. package/node_modules/pi-mcp-adapter/init.ts +0 -721
  244. package/node_modules/pi-mcp-adapter/jev-client.ts +0 -300
  245. package/node_modules/pi-mcp-adapter/jev-contracts.ts +0 -53
  246. package/node_modules/pi-mcp-adapter/jev-key-store.ts +0 -192
  247. package/node_modules/pi-mcp-adapter/json-schema-validator.ts +0 -83
  248. package/node_modules/pi-mcp-adapter/lazy-loader.ts +0 -7
  249. package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -457
  250. package/node_modules/pi-mcp-adapter/logger.ts +0 -169
  251. package/node_modules/pi-mcp-adapter/mcp-auth-fetch.ts +0 -113
  252. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +0 -1296
  253. package/node_modules/pi-mcp-adapter/mcp-auth.ts +0 -1287
  254. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +0 -250
  255. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +0 -534
  256. package/node_modules/pi-mcp-adapter/mcp-code.ts +0 -495
  257. package/node_modules/pi-mcp-adapter/mcp-install.ts +0 -60
  258. package/node_modules/pi-mcp-adapter/mcp-keyring-helper.cjs +0 -89
  259. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +0 -819
  260. package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +0 -511
  261. package/node_modules/pi-mcp-adapter/mcp-panel-theme.ts +0 -104
  262. package/node_modules/pi-mcp-adapter/mcp-panel.ts +0 -1099
  263. package/node_modules/pi-mcp-adapter/mcp-probe.ts +0 -201
  264. package/node_modules/pi-mcp-adapter/mcp-references.ts +0 -373
  265. package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +0 -137
  266. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +0 -747
  267. package/node_modules/pi-mcp-adapter/mcp-status.ts +0 -105
  268. package/node_modules/pi-mcp-adapter/mcp-tasks.ts +0 -467
  269. package/node_modules/pi-mcp-adapter/mcp-trace.ts +0 -306
  270. package/node_modules/pi-mcp-adapter/metadata-cache.ts +0 -362
  271. package/node_modules/pi-mcp-adapter/namespace-tools.ts +0 -334
  272. package/node_modules/pi-mcp-adapter/npx-resolver.ts +0 -543
  273. package/node_modules/pi-mcp-adapter/oauth-handler.ts +0 -30
  274. package/node_modules/pi-mcp-adapter/oauth.ts +0 -52
  275. package/node_modules/pi-mcp-adapter/onboarding-state.ts +0 -76
  276. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +0 -156
  277. package/node_modules/pi-mcp-adapter/package.json +0 -219
  278. package/node_modules/pi-mcp-adapter/panel-keys.ts +0 -53
  279. package/node_modules/pi-mcp-adapter/prompts.ts +0 -385
  280. package/node_modules/pi-mcp-adapter/proxy-modes.ts +0 -1735
  281. package/node_modules/pi-mcp-adapter/request-headers-command.ts +0 -333
  282. package/node_modules/pi-mcp-adapter/resource-tools.ts +0 -17
  283. package/node_modules/pi-mcp-adapter/runtime-owner.ts +0 -106
  284. package/node_modules/pi-mcp-adapter/sampling-handler.ts +0 -261
  285. package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +0 -144
  286. package/node_modules/pi-mcp-adapter/search-ranking.ts +0 -309
  287. package/node_modules/pi-mcp-adapter/secure-keyring.ts +0 -170
  288. package/node_modules/pi-mcp-adapter/semantic-search.ts +0 -186
  289. package/node_modules/pi-mcp-adapter/server-manager.ts +0 -2088
  290. package/node_modules/pi-mcp-adapter/session-approvals.ts +0 -201
  291. package/node_modules/pi-mcp-adapter/session-recovery.ts +0 -158
  292. package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +0 -49
  293. package/node_modules/pi-mcp-adapter/state.ts +0 -71
  294. package/node_modules/pi-mcp-adapter/tool-approval.ts +0 -205
  295. package/node_modules/pi-mcp-adapter/tool-metadata.ts +0 -302
  296. package/node_modules/pi-mcp-adapter/tool-registrar.ts +0 -255
  297. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +0 -573
  298. package/node_modules/pi-mcp-adapter/ts-shape.ts +0 -149
  299. package/node_modules/pi-mcp-adapter/types.ts +0 -1120
  300. package/node_modules/pi-mcp-adapter/ui-app-bridge-helpers.ts +0 -40
  301. package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +0 -266
  302. package/node_modules/pi-mcp-adapter/ui-server.ts +0 -993
  303. package/node_modules/pi-mcp-adapter/ui-session.ts +0 -624
  304. package/node_modules/pi-mcp-adapter/ui-stream-types.ts +0 -89
  305. package/node_modules/pi-mcp-adapter/ui-tool-visibility.ts +0 -25
  306. package/node_modules/pi-mcp-adapter/unix-socket-transport.ts +0 -85
  307. package/node_modules/pi-mcp-adapter/utils.ts +0 -464
@@ -1,861 +0,0 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
3
- import type { OverlayHandle } from "@earendil-works/pi-tui";
4
- import type { McpExtensionState } from "./state.ts";
5
- import { isServerDisabled, type McpAuthResult, type McpConfig, type McpPanelCallbacks, type McpPanelResult, type ImportKind } from "./types.ts";
6
- import {
7
- ensureCompatibilityImports,
8
- getSharedConfigPath,
9
- getMcpDiscoverySummary,
10
- getMcpStandardConfigSummary,
11
- type KnownServerPreset,
12
- type SharedConfigTarget,
13
- getServerProvenance,
14
- previewCompatibilityImports,
15
- previewSharedServerEntry,
16
- previewStarterSharedConfig,
17
- writeDirectToolsConfig,
18
- writeJevSemanticSearchConfig,
19
- writeProjectServerDisabledOverride,
20
- writeSharedServerEntry,
21
- writeSharedConfigText,
22
- writeStarterSharedConfig,
23
- } from "./config.ts";
24
- import { markKeepAliveAfterConnect, notifyToolMetadataUpdated, updateMetadataCache, updateStatusBar, getFailureAgeSeconds, getFailureMessage, clearFailure, recordFailure } from "./init.ts";
25
- import { isServerInActiveFailureBackoff } from "./failure-backoff.ts";
26
- import { loadMetadataCache, reconstructPromptMetadata } from "./metadata-cache.ts";
27
- import { buildToolMetadata } from "./tool-metadata.ts";
28
- import { supportsOAuth, authenticate, removeAuth, type McpOAuthRuntime } from "./mcp-auth-flow.ts";
29
- import { getAuthStorageOptions, inspectAuthForUrl } from "./mcp-auth.ts";
30
- import { inspectBearerTokenForUrl, removeBearerToken } from "./mcp-bearer-store.ts";
31
- import { loadOnboardingState, markSetupCompleted as persistSetupCompleted, markSharedConfigHintShown } from "./onboarding-state.ts";
32
- import { formatTerminalError, openPath, resolveServerUrl, sanitizeTerminalText } from "./utils.ts";
33
- import { isAbortError } from "./runtime-owner.ts";
34
- import { resolveJevCredential } from "./jev-key-store.ts";
35
-
36
- function terminalHyperlink(label: string, url: string): string {
37
- return `\u001B]8;;${sanitizeTerminalText(url)}\u001B\\${sanitizeTerminalText(label)}\u001B]8;;\u001B\\`;
38
- }
39
-
40
- /**
41
- * True when this run mode can display a `ctx.ui.custom()` overlay.
42
- *
43
- * `ctx.hasUI` only reports that *some* UI context is bound. In rpc/print mode
44
- * that context is a headless stub whose `custom()` returns immediately without
45
- * ever invoking the factory or the `done` callback, so a panel awaited through
46
- * `new Promise(resolve => ctx.ui.custom(...))` never settles and the command
47
- * hangs. Overlay panels therefore additionally require `ctx.mode === "tui"`.
48
- */
49
- function canRenderPanel(ctx: ExtensionContext): boolean {
50
- return ctx.hasUI && ctx.mode === "tui";
51
- }
52
-
53
- export async function editSharedConfig(ctx: ExtensionContext, target: SharedConfigTarget): Promise<boolean> {
54
- if (!ctx.hasUI) return false;
55
- const path = getSharedConfigPath(target, ctx.cwd);
56
- const before = existsSync(path) ? readFileSync(path, "utf8") : '{\n "mcpServers": {}\n}\n';
57
- const after = await ctx.ui.editor(`Edit ${path} (Ctrl+G opens $EDITOR)`, before);
58
- if (after === undefined || after === before) return false;
59
- try {
60
- writeSharedConfigText(path, after);
61
- } catch (error) {
62
- ctx.ui.notify(`MCP: not saved: ${formatTerminalError(error)}`, "error");
63
- return false;
64
- }
65
- return true;
66
- }
67
-
68
- export async function setupJevSemanticSearch(
69
- state: McpExtensionState,
70
- ctx: ExtensionContext,
71
- configOverridePath?: string,
72
- ): Promise<boolean> {
73
- if (!ctx.hasUI) return false;
74
- const credential = resolveJevCredential();
75
- if (credential.status !== "present") {
76
- const detail = credential.status === "unavailable" ? ` ${credential.message}` : "";
77
- ctx.ui.notify(
78
- `Jev needs a System One API key.${detail}\nRun \`pi-mcp-adapter key set systemone\` in a terminal, then run \`/mcp jev setup\` again.`,
79
- "error",
80
- );
81
- return false;
82
- }
83
-
84
- const servers = Object.keys(state.config.mcpServers)
85
- .filter((name) => !isServerDisabled(state.config.mcpServers[name]))
86
- .sort((a, b) => a.localeCompare(b));
87
- if (servers.length === 0) {
88
- ctx.ui.notify("Enable or add an MCP server before setting up Jev semantic search.", "error");
89
- return false;
90
- }
91
- const configuredJev = state.config.settings?.jev;
92
- const payloadDisclosure = configuredJev && configuredJev.scriptEvaluation
93
- ? " Allowed servers can also be sources for script evaluations, which may send state and MCP results."
94
- : " Semantic search does not send tool results.";
95
-
96
- const choice = await ctx.ui.select("Configure Jev semantic search", [
97
- `Use all ${servers.length} enabled servers (default)`,
98
- "Restrict to selected servers",
99
- "Cancel",
100
- ]);
101
- if (!choice || choice === "Cancel") return false;
102
-
103
- let allowedServers: string[];
104
- if (choice.startsWith("Use all ")) {
105
- const confirmed = await ctx.ui.confirm(
106
- "Share MCP tool metadata with Jev?",
107
- `Semantic searches send the query text, server names, tool paths, tool names, and descriptions from ${servers.length} servers to the configured Jev endpoint.${payloadDisclosure}`,
108
- );
109
- if (!confirmed) return false;
110
- allowedServers = servers;
111
- } else {
112
- allowedServers = [];
113
- for (const server of servers) {
114
- if (await ctx.ui.confirm(
115
- `Allow ${server}?`,
116
- `Semantic searches send the query text, server name, tool paths, tool names, and descriptions to the configured Jev endpoint.${payloadDisclosure}`,
117
- )) allowedServers.push(server);
118
- }
119
- if (allowedServers.length === 0) {
120
- ctx.ui.notify("Jev setup cancelled because no servers were allowed.", "info");
121
- return false;
122
- }
123
- }
124
-
125
- try {
126
- const result = writeJevSemanticSearchConfig(configOverridePath, ctx.cwd, allowedServers, state.config.settings?.jev);
127
- ctx.ui.notify(
128
- result.changed
129
- ? `Jev semantic search configured for ${allowedServers.length} server${allowedServers.length === 1 ? "" : "s"}. Reloading Pi…`
130
- : "Jev semantic search is already configured for those servers.",
131
- "info",
132
- );
133
- return result.changed;
134
- } catch (error) {
135
- ctx.ui.notify(`Jev setup failed: ${formatTerminalError(error)}`, "error");
136
- return false;
137
- }
138
- }
139
-
140
- export async function showStatus(state: McpExtensionState, ctx: ExtensionContext): Promise<void> {
141
- if (!ctx.hasUI) return;
142
-
143
- const lines: string[] = ["MCP Server Status:", ""];
144
- if (!state.programmaticConfig) {
145
- lines.push(
146
- "Shared MCP config: .mcp.json for this project/team or ~/.config/mcp/mcp.json for all projects.",
147
- "Pi-owned files hold compatibility imports and adapter-specific overrides.",
148
- "",
149
- );
150
- }
151
-
152
- for (const name of Object.keys(state.config.mcpServers)) {
153
- const definition = state.config.mcpServers[name];
154
- if (isServerDisabled(definition)) {
155
- lines.push(`⊘ ${name}: disabled (run /mcp enable ${name}, then /reload)`);
156
- continue;
157
- }
158
- const connection = state.manager.getConnection(name);
159
- const metadata = state.toolMetadata.get(name);
160
- const toolCount = metadata?.length ?? 0;
161
- const failedAgo = getFailureAgeSeconds(state, name);
162
- let status = "not listening (disconnected)";
163
- let statusIcon = "○";
164
- let failed = false;
165
-
166
- if (connection?.status === "connected") {
167
- status = connection.listenState === "active"
168
- ? connection.listenCatalogStale
169
- ? "connected; listen active; catalog may be stale"
170
- : "connected; listen active"
171
- : connection.listenState === "dropped"
172
- ? "connected; catalog may be stale — will reconcile on next keep-alive or tool use"
173
- : connection.listenState === "re-establishing"
174
- ? "connected; re-establishing listen"
175
- : connection.listenState === "legacy"
176
- ? "connected; legacy notification path"
177
- : "connected; not listening for catalog updates";
178
- statusIcon = "✓";
179
- } else if (connection?.status === "needs-auth") {
180
- status = "needs auth";
181
- statusIcon = "⚠";
182
- } else if (failedAgo !== null) {
183
- const reason = sanitizeTerminalText(getFailureMessage(state, name) ?? "");
184
- status = reason ? `failed ${failedAgo}s ago — ${reason}` : `failed ${failedAgo}s ago`;
185
- statusIcon = "✗";
186
- failed = true;
187
- } else if (metadata !== undefined) {
188
- status = "cached; not listening (disconnected)";
189
- }
190
-
191
- const toolSuffix = failed ? "" : ` (${toolCount} tools${status.startsWith("cached") ? ", cached" : ""})`;
192
- lines.push(`${statusIcon} ${name}: ${status}${toolSuffix}`);
193
- }
194
-
195
- if (state.config.settings?.freezeDirectTools === true) {
196
- lines.push("", "Direct tools frozen; active registrations may differ from current metadata.");
197
- }
198
-
199
- if (Object.keys(state.config.mcpServers).length === 0) {
200
- lines.push("No MCP servers configured");
201
- lines.push("Run /mcp setup to add a server to .mcp.json or ~/.config/mcp/mcp.json");
202
- }
203
-
204
- ctx.ui.notify(lines.join("\n"), "info");
205
- }
206
-
207
- export async function showPrompts(state: McpExtensionState, ctx: ExtensionContext): Promise<void> {
208
- if (!ctx.hasUI) return;
209
- const allPrompts = [...(state.promptMetadata?.values() ?? [])].flat();
210
- const failedPromptServers = [...(state.manager.getAllConnections?.() ?? [])]
211
- .filter(([, connection]) => connection.status === "connected" && connection.promptDiscoveryFailed)
212
- .map(([serverName]) => serverName)
213
- .sort();
214
- if (allPrompts.length === 0) {
215
- const failureNote = failedPromptServers.length > 0
216
- ? ` Prompt discovery failed for: ${failedPromptServers.join(", ")}.`
217
- : "";
218
- ctx.ui.notify(`No MCP prompts available. Prompts are discovered when servers with the \`prompts\` capability connect.${failureNote}`, "info");
219
- return;
220
- }
221
- const lines = ["MCP Prompts:", ""];
222
- const grouped = new Map<string, typeof allPrompts>();
223
- for (const prompt of allPrompts) {
224
- const list = grouped.get(prompt.serverName) ?? [];
225
- list.push(prompt);
226
- grouped.set(prompt.serverName, list);
227
- }
228
- for (const [serverName, prompts] of [...grouped.entries()].sort(([a], [b]) => a.localeCompare(b))) {
229
- lines.push(`${serverName}:`);
230
- for (const prompt of prompts.sort((a, b) => a.commandName.localeCompare(b.commandName))) {
231
- const args = prompt.arguments.map(argument => argument.required ? `<${argument.name}>` : `[${argument.name}]`).join(" ");
232
- lines.push(` /${prompt.commandName}${args ? ` ${args}` : ""}`);
233
- if (prompt.description) lines.push(` ${prompt.description}`);
234
- }
235
- lines.push("");
236
- }
237
- lines.push(`Total: ${allPrompts.length} prompt${allPrompts.length === 1 ? "" : "s"}`);
238
- if (failedPromptServers.length > 0) {
239
- lines.push(`Prompt discovery failed for: ${failedPromptServers.join(", ")}. Cached prompt metadata may be stale.`);
240
- }
241
- ctx.ui.notify(lines.join("\n"), "info");
242
- }
243
-
244
- export async function showTools(state: McpExtensionState, ctx: ExtensionContext): Promise<void> {
245
- if (!ctx.hasUI) return;
246
-
247
- const allTools = [...state.toolMetadata.entries()]
248
- .filter(([serverName]) => !isServerDisabled(state.config.mcpServers[serverName]))
249
- .filter(([serverName]) => !isServerInActiveFailureBackoff(state, serverName))
250
- .flatMap(([, metadata]) => metadata.map(m => m.name));
251
-
252
- if (allTools.length === 0) {
253
- ctx.ui.notify("No MCP tools available", "info");
254
- return;
255
- }
256
-
257
- const lines = [
258
- "MCP Tools:",
259
- "",
260
- ...allTools.map(t => ` ${t}`),
261
- "",
262
- `Total: ${allTools.length} tools`,
263
- ];
264
-
265
- ctx.ui.notify(lines.join("\n"), "info");
266
- }
267
-
268
- export async function reconnectServer(
269
- state: McpExtensionState,
270
- ctx: ExtensionContext,
271
- name: string,
272
- ): Promise<boolean> {
273
- const definition = state.config.mcpServers[name];
274
- const ui = ctx.hasUI ? ctx.ui : undefined;
275
- const signal = state.owner?.signal;
276
- if (!definition) {
277
- if (ui) {
278
- ui.notify(`Server "${name}" not found in config`, "error");
279
- }
280
- return false;
281
- }
282
- if (isServerDisabled(definition)) {
283
- if (ui) ui.notify(`MCP: ${name} is disabled. Run /mcp enable ${name}, then /reload.`, "warning");
284
- return false;
285
- }
286
-
287
- try {
288
- state.owner?.throwIfInactive();
289
- const current = state.manager.getConnection(name);
290
- const connection = current
291
- ? await state.manager.reconnect(name, definition, current, signal)
292
- : await state.manager.connect(name, definition, signal);
293
- state.owner?.throwIfInactive();
294
- if (connection.status === "needs-auth") {
295
- if (ui) {
296
- ui.notify(`MCP: ${name} requires OAuth. Run /mcp-auth ${name} first.`, "warning");
297
- }
298
- updateStatusBar(state);
299
- return false;
300
- }
301
-
302
- const prefix = state.config.settings?.toolPrefix ?? "server";
303
- const { metadata, failedTools } = buildToolMetadata(connection.tools, connection.resources, definition, name, prefix, state.config.mcpServers, state.toolMetadata);
304
- state.toolMetadata.set(name, metadata);
305
- if (!connection.promptDiscoveryFailed) {
306
- state.promptMetadata?.set(name, reconstructPromptMetadata(name, connection.prompts ?? [], prefix, definition));
307
- state.promptMetadataLive?.add(name);
308
- }
309
- if (connection.instructions) {
310
- state.serverInstructions.set(name, connection.instructions);
311
- } else {
312
- state.serverInstructions.delete(name);
313
- }
314
- updateMetadataCache(state, name);
315
- const restored = clearFailure(state, name, "command-reconnect");
316
- if (!restored) notifyToolMetadataUpdated(state, name, "command-reconnect");
317
- markKeepAliveAfterConnect(state, name);
318
-
319
- if (ui) {
320
- ui.notify(
321
- `MCP: Reconnected to ${name} (${connection.tools.length} tools, ${connection.resources.length} resources)`,
322
- "info"
323
- );
324
- if (failedTools.length > 0) {
325
- ui.notify(`MCP: ${name} - ${failedTools.length} tools skipped`, "warning");
326
- }
327
- }
328
- updateStatusBar(state);
329
- return true;
330
- } catch (error) {
331
- const message = error instanceof Error ? error.message : String(error);
332
- if (isAbortError(error, signal)) throw error;
333
- recordFailure(state, name, message);
334
- if (ui) {
335
- ui.notify(`MCP: Failed to reconnect to ${name}: ${sanitizeTerminalText(message)}`, "error");
336
- }
337
- updateStatusBar(state);
338
- return false;
339
- }
340
- }
341
-
342
- export async function reconnectServers(
343
- state: McpExtensionState,
344
- ctx: ExtensionContext,
345
- targetServer?: string
346
- ): Promise<void> {
347
- if (targetServer && !state.config.mcpServers[targetServer]) {
348
- if (ctx.hasUI) {
349
- ctx.ui.notify(`Server "${targetServer}" not found in config`, "error");
350
- }
351
- return;
352
- }
353
-
354
- const names = targetServer ? [targetServer] : Object.keys(state.config.mcpServers);
355
- for (const name of names) {
356
- await reconnectServer(state, ctx, name);
357
- }
358
-
359
- updateStatusBar(state);
360
- }
361
-
362
- export async function authenticateServer(
363
- serverName: string,
364
- config: McpConfig,
365
- ctx: ExtensionContext,
366
- signal?: AbortSignal,
367
- runtime?: McpOAuthRuntime,
368
- ): Promise<McpAuthResult> {
369
- const ui = ctx.hasUI ? ctx.ui : undefined;
370
- const cwd = ctx.cwd;
371
- signal ??= ctx.signal;
372
- if (!ui) return { ok: false, message: "OAuth authentication requires an interactive session." };
373
-
374
- const definition = config.mcpServers[serverName];
375
- if (!definition) {
376
- const message = `Server "${serverName}" not found in config`;
377
- ui.notify(message, "error");
378
- return { ok: false, message };
379
- }
380
- if (isServerDisabled(definition)) {
381
- const message = `Server "${serverName}" is disabled. Run /mcp enable ${serverName}, then /reload.`;
382
- ui.notify(message, "warning");
383
- return { ok: false, message };
384
- }
385
-
386
- if (!supportsOAuth(definition)) {
387
- const message = `Server "${serverName}" does not use OAuth authentication. Set "auth": "oauth" or omit auth for auto-detection.`;
388
- ui.notify(
389
- `Server "${serverName}" does not use OAuth authentication.\n` +
390
- `Set "auth": "oauth" or omit auth for auto-detection.`,
391
- "error"
392
- );
393
- return { ok: false, message };
394
- }
395
-
396
- try {
397
- const serverUrl = resolveServerUrl(definition);
398
- if (!serverUrl) {
399
- const message = `Server "${serverName}" has no URL configured (OAuth requires HTTP transport)`;
400
- ui.notify(message, "error");
401
- return { ok: false, message };
402
- }
403
-
404
- ui.setStatus("mcp-auth", `Authenticating ${serverName}...`);
405
- const authStorageOptions = getAuthStorageOptions(config.settings?.oauthDir, cwd, config.settings?.oauthCredentialStore);
406
- const status = await authenticate(serverName, serverUrl, definition, {
407
- ...(Object.keys(authStorageOptions).length > 0 ? { authStorageOptions } : {}),
408
- onAuthorizationUrl: () => {},
409
- onAuthorizationInput: async (authorizationUrl, inputSignal) => {
410
- if (inputSignal.aborted) return undefined;
411
- return ui.input(
412
- `Complete ${serverName} OAuth\n\n` +
413
- `${terminalHyperlink("Open authorization page", authorizationUrl)}\n${authorizationUrl}\n\n` +
414
- "Approve access, then paste the full callback URL from the browser address bar below.",
415
- undefined,
416
- { signal: inputSignal },
417
- );
418
- },
419
- ...(signal ? { signal } : {}),
420
- ...(runtime ? { runtime } : {}),
421
- });
422
- if (signal?.aborted) signal.throwIfAborted();
423
-
424
- if (status === "authenticated") {
425
- const message = `OAuth authentication successful for "${serverName}".`;
426
- ui.notify(message, "info");
427
- return { ok: true, message };
428
- }
429
-
430
- const message = `OAuth authentication failed for "${serverName}".`;
431
- ui.notify(message, "error");
432
- return { ok: false, message };
433
- } catch (error) {
434
- if (signal?.aborted) throw error;
435
- const message = error instanceof Error ? error.message : String(error);
436
- ui.notify(`Failed to authenticate "${serverName}": ${message}`, "error");
437
- return { ok: false, message };
438
- } finally {
439
- if (!signal?.aborted) ui.setStatus("mcp-auth", undefined);
440
- }
441
- }
442
-
443
- export async function logoutServer(
444
- serverName: string,
445
- state: McpExtensionState,
446
- ctx: ExtensionContext
447
- ): Promise<{ ok: boolean; message: string }> {
448
- const definition = state.config.mcpServers[serverName];
449
- const ui = ctx.hasUI ? ctx.ui : undefined;
450
- if (!definition) {
451
- const message = `Server "${serverName}" not found in config`;
452
- if (ui) ui.notify(message, "error");
453
- return { ok: false, message };
454
- }
455
-
456
- const signal = state.owner?.signal;
457
- try {
458
- await state.manager.close(serverName);
459
- } catch (error) {
460
- if (isAbortError(error, signal)) throw error;
461
- const message = error instanceof Error ? error.message : String(error);
462
- if (ui) {
463
- ui.notify(`Failed to close OAuth server "${serverName}"; credentials were not cleared: ${sanitizeTerminalText(message)}`, "error");
464
- }
465
- return { ok: false, message };
466
- }
467
-
468
- state.owner?.throwIfInactive();
469
- try {
470
- await removeAuth(serverName, { authStorageOptions: state.authStorageOptions, signal, runtime: state.oauthRuntime });
471
- } catch (error) {
472
- if (isAbortError(error, signal)) throw error;
473
- const message = error instanceof Error ? error.message : String(error);
474
- if (ui) {
475
- ui.notify(`Failed to clear OAuth credentials for "${serverName}": ${sanitizeTerminalText(message)}`, "error");
476
- }
477
- return { ok: false, message };
478
- }
479
-
480
- state.owner?.throwIfInactive();
481
- updateStatusBar(state);
482
-
483
- const message = `OAuth credentials cleared for "${serverName}". Run /mcp-auth ${serverName} to authenticate again.`;
484
- if (ui) ui.notify(message, "info");
485
- return { ok: true, message };
486
- }
487
-
488
- function validateBearerTokenStoreServer(
489
- serverName: string,
490
- state: McpExtensionState,
491
- ): { ok: true; serverUrl: string } | { ok: false; message: string; type: "error" | "warning" } {
492
- const safeName = sanitizeTerminalText(serverName);
493
- const definition = state.config.mcpServers[serverName];
494
- if (!definition) return { ok: false, message: `Server "${safeName}" not found in config`, type: "error" };
495
- if (isServerDisabled(definition)) return { ok: false, message: `Server "${safeName}" is disabled. Run /mcp enable ${safeName}, then /reload.`, type: "warning" };
496
- if (definition.auth !== "bearer" || definition.bearerTokenStore !== true) {
497
- return { ok: false, message: `Server "${safeName}" is not configured for bearerTokenStore.`, type: "error" };
498
- }
499
- // resolveServerUrl embeds the interpolated URL in its exceptions; redact it
500
- // because the URL can carry userinfo or interpolated secrets.
501
- let serverUrl: string | undefined;
502
- try {
503
- serverUrl = resolveServerUrl(definition);
504
- } catch {
505
- return { ok: false, message: `Server "${safeName}" has an invalid or unresolvable URL.`, type: "error" };
506
- }
507
- if (!serverUrl) return { ok: false, message: `Server "${safeName}" has no URL configured.`, type: "error" };
508
- return { ok: true, serverUrl };
509
- }
510
-
511
- export async function manageBearerToken(
512
- action: "set" | "remove" | "status",
513
- serverName: string,
514
- state: McpExtensionState,
515
- ctx: ExtensionContext,
516
- ): Promise<{ ok: boolean; message: string }> {
517
- const ui = ctx.hasUI ? ctx.ui : undefined;
518
- const safeName = sanitizeTerminalText(serverName);
519
- const validation = validateBearerTokenStoreServer(serverName, state);
520
- if (!validation.ok) {
521
- if (ui) ui.notify(validation.message, validation.type);
522
- return { ok: false, message: validation.message };
523
- }
524
-
525
- if (action === "set") {
526
- const message = `Cannot store bearer token here: Pi extension UI has no masked secret input primitive. Run \`pi-mcp-adapter token set ${safeName}\` in a terminal; it reads the token from stdin only.`;
527
- if (ui) ui.notify(message, "error");
528
- return { ok: false, message };
529
- }
530
-
531
- if (action === "status") {
532
- const status = inspectBearerTokenForUrl(serverName, validation.serverUrl);
533
- const message = status.status === "present"
534
- ? `Bearer token is stored for "${safeName}".`
535
- : status.status === "url-mismatch"
536
- ? `Bearer token is stored for "${safeName}", but its URL does not match the current server URL.`
537
- : status.status === "unavailable"
538
- ? status.message
539
- : `No bearer token is stored for "${safeName}".`;
540
- if (ui) ui.notify(message, status.status === "unavailable" ? "error" : "info");
541
- return { ok: status.status !== "unavailable", message };
542
- }
543
-
544
- try {
545
- removeBearerToken(serverName);
546
- } catch (error) {
547
- const message = error instanceof Error ? error.message : String(error);
548
- if (ui) ui.notify(`Failed to remove bearer token for "${safeName}": ${sanitizeTerminalText(message)}`, "error");
549
- return { ok: false, message };
550
- }
551
-
552
- const message = `Bearer token removed for "${safeName}".`;
553
- if (ui) ui.notify(message, "info");
554
- return { ok: true, message };
555
- }
556
-
557
- export interface PanelFlowResult {
558
- configChanged: boolean;
559
- }
560
-
561
- function buildSharedConfigNoticeLines(configOverridePath: string | undefined, cwd: string): { lines: string[]; fingerprint: string | null } {
562
- const discovery = getMcpStandardConfigSummary(configOverridePath, cwd);
563
- const onboardingState = loadOnboardingState();
564
- const sharedSources = discovery.sources.filter((source) =>
565
- (source.id === "shared-project" || source.id === "shared-project-ancestor" || source.id === "shared-global") && source.serverCount > 0,
566
- );
567
- if (sharedSources.length === 0 || onboardingState.sharedConfigHintShown) {
568
- return { lines: [], fingerprint: null };
569
- }
570
-
571
- const sourceList = sharedSources.map((source) => source.path).join(", ");
572
- return {
573
- lines: [
574
- `Using standard MCP config from ${sourceList}.`,
575
- "Use .mcp.json for project/team config or ~/.config/mcp/mcp.json for all projects. Pi only writes compatibility imports and adapter-specific overrides into Pi-owned files when needed.",
576
- ],
577
- fingerprint: discovery.fingerprint,
578
- };
579
- }
580
-
581
- export async function openMcpSetup(
582
- state: McpExtensionState,
583
- pi: ExtensionAPI,
584
- ctx: ExtensionContext,
585
- configOverridePath?: string,
586
- mode: "empty" | "setup" = "setup",
587
- options: { includeHostConfigs?: boolean } = {},
588
- ): Promise<PanelFlowResult> {
589
- if (!ctx.hasUI) return { configChanged: false };
590
- if (!canRenderPanel(ctx)) {
591
- ctx.ui.notify(`The interactive MCP setup panel is only available in the terminal UI (current mode: ${ctx.mode}). Edit .mcp.json directly, or run /mcp status to review servers.`, "info");
592
- return { configChanged: false };
593
- }
594
- if (state.programmaticConfig) {
595
- ctx.ui.notify("MCP setup is unavailable when config is supplied by createMcpAdapter().", "info");
596
- return { configChanged: false };
597
- }
598
-
599
- const discovery = getMcpDiscoverySummary(configOverridePath, ctx.cwd, options);
600
- const onboardingState = loadOnboardingState();
601
- const { createMcpSetupPanel } = await import("./mcp-setup-panel.ts");
602
- let configChanged = false;
603
-
604
- const callbacks = {
605
- previewImports: (imports: ImportKind[]) => previewCompatibilityImports(imports, configOverridePath),
606
- previewStarterConfig: (target: SharedConfigTarget) => previewStarterSharedConfig(target, ctx.cwd),
607
- previewRepoPrompt: (target: SharedConfigTarget) => {
608
- const repoPrompt = getMcpDiscoverySummary(configOverridePath, ctx.cwd, options).repoPrompt;
609
- if (!repoPrompt.entry || !repoPrompt.targetPath || !repoPrompt.serverName) return null;
610
- return previewSharedServerEntry(getSharedConfigPath(target, ctx.cwd), repoPrompt.serverName, repoPrompt.entry);
611
- },
612
- previewKnownServer: (preset: KnownServerPreset, target: SharedConfigTarget) => previewSharedServerEntry(getSharedConfigPath(target, ctx.cwd), preset.id, preset.entry),
613
- adoptImports: async (imports: ImportKind[]) => {
614
- const result = ensureCompatibilityImports(imports, configOverridePath);
615
- if (result.added.length > 0) configChanged = true;
616
- return result;
617
- },
618
- scaffoldConfig: async (target: SharedConfigTarget) => {
619
- const path = writeStarterSharedConfig(target, ctx.cwd);
620
- configChanged = true;
621
- return { path };
622
- },
623
- addRepoPrompt: async (target: SharedConfigTarget) => {
624
- const repoPrompt = getMcpDiscoverySummary(configOverridePath, ctx.cwd, options).repoPrompt;
625
- if (!repoPrompt.entry || !repoPrompt.targetPath || !repoPrompt.serverName) {
626
- throw new Error("RepoPrompt is not available to add from this setup screen.");
627
- }
628
- const path = writeSharedServerEntry(getSharedConfigPath(target, ctx.cwd), repoPrompt.serverName, repoPrompt.entry);
629
- configChanged = true;
630
- return { path, serverName: repoPrompt.serverName };
631
- },
632
- addKnownServer: async (preset: KnownServerPreset, target: SharedConfigTarget) => {
633
- const path = writeSharedServerEntry(getSharedConfigPath(target, ctx.cwd), preset.id, preset.entry);
634
- configChanged = true;
635
- return { path, serverName: preset.name };
636
- },
637
- openPath: async (targetPath: string) => {
638
- await openPath(pi, targetPath);
639
- },
640
- markSetupCompleted: () => {
641
- persistSetupCompleted(discovery.fingerprint);
642
- },
643
- };
644
-
645
- return new Promise<PanelFlowResult>((resolve) => {
646
- ctx.ui.custom(
647
- (tui, theme, keybindings, done) => {
648
- return createMcpSetupPanel(discovery, callbacks, { mode, onboardingState, keybindings, theme }, tui, () => {
649
- done(undefined);
650
- resolve({ configChanged });
651
- });
652
- },
653
- { overlay: true, overlayOptions: { anchor: "center", width: 92 } },
654
- );
655
- });
656
- }
657
-
658
- function buildMcpPanelCallbacks(
659
- state: McpExtensionState,
660
- config: McpConfig,
661
- ctx: ExtensionContext,
662
- getOverlayHandle?: () => OverlayHandle | undefined,
663
- ): McpPanelCallbacks {
664
- // Panel-only diagnostics keep status inspection from mutating connection
665
- // failure state while allowing the existing panel failure UI to show why the
666
- // credential store could not be inspected.
667
- const authStatusFailures = new Map<string, string>();
668
-
669
- return {
670
- reconnect: (serverName: string) => reconnectServer(state, ctx, serverName),
671
- canAuthenticate: (serverName: string) => {
672
- const definition = config.mcpServers[serverName];
673
- return definition ? !isServerDisabled(definition) && supportsOAuth(definition) : false;
674
- },
675
- authenticate: async (serverName: string) => {
676
- const overlay = getOverlayHandle?.();
677
- overlay?.setHidden(true);
678
- try {
679
- return await authenticateServer(serverName, config, ctx, state.owner?.signal, state.oauthRuntime);
680
- } finally {
681
- overlay?.setHidden(false);
682
- overlay?.focus();
683
- }
684
- },
685
- getConnectionStatus: (serverName: string) => {
686
- authStatusFailures.delete(serverName);
687
- const definition = config.mcpServers[serverName];
688
- if (isServerDisabled(definition)) return "disabled";
689
- const connection = state.manager.getConnection(serverName);
690
- let serverUrl: string | undefined;
691
- try {
692
- serverUrl = definition ? resolveServerUrl(definition) : undefined;
693
- } catch {
694
- return "failed";
695
- }
696
- if (
697
- definition?.auth === "oauth"
698
- && serverUrl
699
- && definition.oauth !== false
700
- && definition.oauth?.grantType !== "client_credentials"
701
- ) {
702
- const authStatus = inspectAuthForUrl(serverName, serverUrl, state.authStorageOptions);
703
- if (authStatus.status === "unavailable") {
704
- authStatusFailures.set(serverName, authStatus.message);
705
- return "failed";
706
- }
707
- if (authStatus.status === "absent" || !authStatus.entry.tokens) {
708
- return "needs-auth";
709
- }
710
- }
711
- if (connection?.status === "needs-auth") return "needs-auth";
712
- if (connection?.status === "connected") return "connected";
713
- if (getFailureAgeSeconds(state, serverName) !== null) return "failed";
714
- return "idle";
715
- },
716
- getFailureMessage: (serverName: string) => authStatusFailures.get(serverName) ?? getFailureMessage(state, serverName),
717
- refreshCacheAfterReconnect: (serverName: string) => {
718
- const freshCache = loadMetadataCache();
719
- return freshCache?.servers?.[serverName] ?? null;
720
- },
721
- };
722
- }
723
-
724
- export async function openMcpPanel(
725
- state: McpExtensionState,
726
- pi: ExtensionAPI,
727
- ctx: ExtensionContext,
728
- configOverridePath?: string,
729
- onDirectToolsConfigChanged?: (changes: Map<string, true | string[] | false>) => void | Promise<void>,
730
- ): Promise<PanelFlowResult> {
731
- if (state.programmaticConfig) {
732
- if (ctx.hasUI) {
733
- ctx.ui.notify("MCP status is shown from the in-memory SDK config; configuration discovery is unavailable.", "info");
734
- await showStatus(state, ctx);
735
- }
736
- return { configChanged: false };
737
- }
738
- if (!canRenderPanel(ctx)) {
739
- // No overlay here, but the same information is available as text.
740
- await showStatus(state, ctx);
741
- return { configChanged: false };
742
- }
743
- if (Object.keys(state.config.mcpServers).length === 0) {
744
- return openMcpSetup(state, pi, ctx, configOverridePath, "empty", { includeHostConfigs: false });
745
- }
746
-
747
- const config = state.config;
748
- const cache = loadMetadataCache();
749
- const configPath = pi.getFlag("mcp-config") as string | undefined ?? configOverridePath;
750
- const provenanceMap = getServerProvenance(configPath, ctx.cwd);
751
- const { lines: noticeLines, fingerprint } = buildSharedConfigNoticeLines(configPath, ctx.cwd);
752
-
753
- let overlayHandle: OverlayHandle | undefined;
754
- const callbacks = buildMcpPanelCallbacks(state, config, ctx, () => overlayHandle);
755
-
756
- const { createMcpPanel } = await import("./mcp-panel.ts");
757
- let configChanged = false;
758
-
759
- await new Promise<void>((resolve) => {
760
- ctx.ui.custom(
761
- (tui, theme, keybindings, done) => {
762
- return createMcpPanel(config, cache, provenanceMap, callbacks, tui, (result: McpPanelResult) => {
763
- void (async () => {
764
- if (!result.cancelled && result.disabledChanges.size > 0) {
765
- for (const [serverName, disabled] of result.disabledChanges) {
766
- try {
767
- const override = writeProjectServerDisabledOverride(configPath, ctx.cwd, serverName, disabled);
768
- if (override.changed) {
769
- configChanged = true;
770
- }
771
- } catch (error) {
772
- ctx.ui.notify(`Failed to ${disabled ? "disable" : "enable"} server "${serverName}": ${error instanceof Error ? error.message : String(error)}`, "error");
773
- }
774
- }
775
- }
776
- if (!result.cancelled && result.changes.size > 0) {
777
- writeDirectToolsConfig(result.changes, provenanceMap, config);
778
- await onDirectToolsConfigChanged?.(result.changes);
779
- ctx.ui.notify("Direct tools updated for this session.", "info");
780
- }
781
- done(undefined);
782
- resolve();
783
- })().catch((error) => {
784
- const message = error instanceof Error ? error.message : String(error);
785
- ctx.ui.notify(`Direct tools updated, but live refresh failed: ${message}`, "error");
786
- configChanged = true;
787
- done(undefined);
788
- resolve();
789
- });
790
- }, { noticeLines, keybindings, theme });
791
- },
792
- {
793
- overlay: true,
794
- overlayOptions: { anchor: "center", width: 82 },
795
- onHandle: (handle) => { overlayHandle = handle; },
796
- },
797
- );
798
- });
799
-
800
- if (noticeLines.length > 0 && fingerprint) {
801
- markSharedConfigHintShown(fingerprint);
802
- }
803
-
804
- return { configChanged };
805
- }
806
-
807
- export async function openMcpAuthPanel(
808
- state: McpExtensionState,
809
- pi: ExtensionAPI,
810
- ctx: ExtensionContext,
811
- configOverridePath?: string,
812
- ): Promise<PanelFlowResult> {
813
- if (!ctx.hasUI) return { configChanged: false };
814
- if (!canRenderPanel(ctx)) {
815
- ctx.ui.notify(`The interactive MCP auth panel is only available in the terminal UI (current mode: ${ctx.mode}). Use /mcp-auth <server> to authenticate a specific server.`, "info");
816
- return { configChanged: false };
817
- }
818
- if (state.programmaticConfig) {
819
- ctx.ui.notify("Use /mcp-auth <server> to authenticate a server from the in-memory SDK config.", "info");
820
- return { configChanged: false };
821
- }
822
-
823
- const config = state.config;
824
- const oauthServers = Object.entries(config.mcpServers).filter(
825
- ([, definition]) => !isServerDisabled(definition) && supportsOAuth(definition),
826
- );
827
- if (oauthServers.length === 0) {
828
- ctx.ui.notify("No OAuth-capable MCP servers are configured.", "warning");
829
- return { configChanged: false };
830
- }
831
-
832
- const cache = loadMetadataCache();
833
- const configPath = pi.getFlag("mcp-config") as string | undefined ?? configOverridePath;
834
- const provenanceMap = getServerProvenance(configPath, ctx.cwd);
835
- let overlayHandle: OverlayHandle | undefined;
836
- const callbacks = buildMcpPanelCallbacks(state, config, ctx, () => overlayHandle);
837
- const { createMcpPanel } = await import("./mcp-panel.ts");
838
-
839
- await new Promise<void>((resolve) => {
840
- ctx.ui.custom(
841
- (tui, theme, keybindings, done) => {
842
- return createMcpPanel(config, cache, provenanceMap, callbacks, tui, () => {
843
- done(undefined);
844
- resolve();
845
- }, {
846
- authOnly: true,
847
- keybindings,
848
- theme,
849
- noticeLines: ["Select an OAuth MCP server and press Enter or ctrl+a to authenticate."],
850
- });
851
- },
852
- {
853
- overlay: true,
854
- overlayOptions: { anchor: "center", width: 82 },
855
- onHandle: (handle) => { overlayHandle = handle; },
856
- },
857
- );
858
- });
859
-
860
- return { configChanged: false };
861
- }