@herbertgao/pi-extensions 2026.8.2 → 2026.8.3

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 (272) hide show
  1. package/README.md +9 -2
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -8
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -7
  4. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +101 -0
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +1 -17
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +5 -3
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{utils/agent-summary.ts → feature/agent-summary/core.ts} +37 -35
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-summary.ts → agent-summary/index.ts} +2 -6
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference.ts → reference/index.ts} +1 -1
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-autocomplete.ts → reference/subagent.ts} +19 -9
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-startup-header.ts → shell/startup-header.ts} +1 -1
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{working-message.ts → shell/working-message.ts} +5 -2
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +32 -28
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +379 -85
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +727 -0
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +65 -775
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +35 -31
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-hover.ts → mouse/hover.ts} +5 -5
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +34 -35
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-layout.ts → mouse/layout.ts} +5 -21
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-packets.ts → mouse/packets.ts} +1 -1
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-scroll.ts → mouse/scroll.ts} +48 -37
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ansi-utils.ts +56 -1
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-renderer.ts +2 -2
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/line-width-safety.ts +1 -1
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +12 -0
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/write-execution.ts +1 -2
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-grouping.ts → tool/grouping.ts} +18 -8
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-result.ts → tool/result.ts} +4 -13
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +0 -27
  31. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  32. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  33. package/node_modules/@herbertgao/pi-subagents/package.json +2 -2
  34. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +1 -0
  35. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +3 -1
  36. package/node_modules/@herbertgao/pi-subagents/src/index.ts +33 -35
  37. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +26 -35
  38. package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +15 -1
  39. package/node_modules/pi-mcp-adapter/CHANGELOG.md +19 -0
  40. package/node_modules/pi-mcp-adapter/README.md +19 -4
  41. package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
  42. package/node_modules/pi-mcp-adapter/commands.ts +12 -2
  43. package/node_modules/pi-mcp-adapter/direct-tools.ts +6 -8
  44. package/node_modules/pi-mcp-adapter/index.ts +15 -3
  45. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +87 -4
  46. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
  47. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +43 -4
  48. package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
  49. package/node_modules/pi-mcp-adapter/package.json +8 -2
  50. package/node_modules/pi-mcp-adapter/proxy-modes.ts +8 -10
  51. package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
  52. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  53. package/node_modules/pi-web-access/CHANGELOG.md +45 -0
  54. package/node_modules/pi-web-access/README.md +104 -29
  55. package/node_modules/pi-web-access/bocha.ts +221 -0
  56. package/node_modules/pi-web-access/curator-page.ts +113 -12
  57. package/node_modules/pi-web-access/curator-server.ts +56 -20
  58. package/node_modules/pi-web-access/datalab-pdf-extract.ts +568 -0
  59. package/node_modules/pi-web-access/duckduckgo.ts +123 -0
  60. package/node_modules/pi-web-access/extract.ts +288 -143
  61. package/node_modules/pi-web-access/feature-config.ts +29 -0
  62. package/node_modules/pi-web-access/gemini-api.ts +4 -0
  63. package/node_modules/pi-web-access/gemini-search.ts +45 -12
  64. package/node_modules/pi-web-access/gemini-web.ts +68 -3
  65. package/node_modules/pi-web-access/index.ts +160 -71
  66. package/node_modules/pi-web-access/jina-search.ts +284 -0
  67. package/node_modules/pi-web-access/kagi.ts +12 -12
  68. package/node_modules/pi-web-access/openai-search.ts +12 -2
  69. package/node_modules/pi-web-access/package.json +4 -3
  70. package/node_modules/pi-web-access/pdf-extract.ts +327 -228
  71. package/node_modules/pi-web-access/storage.ts +440 -2
  72. package/node_modules/pi-web-access/summary-model-scope.ts +1 -1
  73. package/node_modules/pi-web-access/summary-review.ts +4 -2
  74. package/node_modules/pi-web-access/video-extract.ts +10 -8
  75. package/node_modules/pi-web-access/xai-search.ts +12 -2
  76. package/node_modules/pi-web-access/youtube-extract.ts +2 -1
  77. package/node_modules/remote-pi/LICENSE +21 -0
  78. package/node_modules/remote-pi/README.md +675 -0
  79. package/node_modules/remote-pi/dist/actions/handlers.d.ts +122 -0
  80. package/node_modules/remote-pi/dist/actions/handlers.js +160 -0
  81. package/node_modules/remote-pi/dist/actions/handlers.js.map +1 -0
  82. package/node_modules/remote-pi/dist/actions/registry.d.ts +39 -0
  83. package/node_modules/remote-pi/dist/actions/registry.js +58 -0
  84. package/node_modules/remote-pi/dist/actions/registry.js.map +1 -0
  85. package/node_modules/remote-pi/dist/bin/supervisord.d.ts +2 -0
  86. package/node_modules/remote-pi/dist/bin/supervisord.js +86 -0
  87. package/node_modules/remote-pi/dist/bin/supervisord.js.map +1 -0
  88. package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +58 -0
  89. package/node_modules/remote-pi/dist/commands/builtin_mirror.js +71 -0
  90. package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +1 -0
  91. package/node_modules/remote-pi/dist/commands/list_commands.d.ts +60 -0
  92. package/node_modules/remote-pi/dist/commands/list_commands.js +73 -0
  93. package/node_modules/remote-pi/dist/commands/list_commands.js.map +1 -0
  94. package/node_modules/remote-pi/dist/config.d.ts +62 -0
  95. package/node_modules/remote-pi/dist/config.js +115 -0
  96. package/node_modules/remote-pi/dist/config.js.map +1 -0
  97. package/node_modules/remote-pi/dist/daemon/client.d.ts +20 -0
  98. package/node_modules/remote-pi/dist/daemon/client.js +131 -0
  99. package/node_modules/remote-pi/dist/daemon/client.js.map +1 -0
  100. package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +176 -0
  101. package/node_modules/remote-pi/dist/daemon/control_protocol.js +63 -0
  102. package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +1 -0
  103. package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +45 -0
  104. package/node_modules/remote-pi/dist/daemon/cron_log.js +72 -0
  105. package/node_modules/remote-pi/dist/daemon/cron_log.js.map +1 -0
  106. package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +80 -0
  107. package/node_modules/remote-pi/dist/daemon/cron_registry.js +194 -0
  108. package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +1 -0
  109. package/node_modules/remote-pi/dist/daemon/id.d.ts +24 -0
  110. package/node_modules/remote-pi/dist/daemon/id.js +36 -0
  111. package/node_modules/remote-pi/dist/daemon/id.js.map +1 -0
  112. package/node_modules/remote-pi/dist/daemon/install.d.ts +170 -0
  113. package/node_modules/remote-pi/dist/daemon/install.js +547 -0
  114. package/node_modules/remote-pi/dist/daemon/install.js.map +1 -0
  115. package/node_modules/remote-pi/dist/daemon/registry.d.ts +63 -0
  116. package/node_modules/remote-pi/dist/daemon/registry.js +153 -0
  117. package/node_modules/remote-pi/dist/daemon/registry.js.map +1 -0
  118. package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +194 -0
  119. package/node_modules/remote-pi/dist/daemon/rpc_child.js +389 -0
  120. package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +1 -0
  121. package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +93 -0
  122. package/node_modules/remote-pi/dist/daemon/supervisor.js +596 -0
  123. package/node_modules/remote-pi/dist/daemon/supervisor.js.map +1 -0
  124. package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +26 -0
  125. package/node_modules/remote-pi/dist/extension_ui_bridge.js +341 -0
  126. package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +1 -0
  127. package/node_modules/remote-pi/dist/index.d.ts +213 -0
  128. package/node_modules/remote-pi/dist/index.js +4996 -0
  129. package/node_modules/remote-pi/dist/index.js.map +1 -0
  130. package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +10 -0
  131. package/node_modules/remote-pi/dist/mcp/mesh_result.js +42 -0
  132. package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +1 -0
  133. package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +16 -0
  134. package/node_modules/remote-pi/dist/mcp/mesh_server.js +327 -0
  135. package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +1 -0
  136. package/node_modules/remote-pi/dist/mesh/canonical.d.ts +30 -0
  137. package/node_modules/remote-pi/dist/mesh/canonical.js +61 -0
  138. package/node_modules/remote-pi/dist/mesh/canonical.js.map +1 -0
  139. package/node_modules/remote-pi/dist/mesh/client.d.ts +18 -0
  140. package/node_modules/remote-pi/dist/mesh/client.js +125 -0
  141. package/node_modules/remote-pi/dist/mesh/client.js.map +1 -0
  142. package/node_modules/remote-pi/dist/mesh/encoding.d.ts +38 -0
  143. package/node_modules/remote-pi/dist/mesh/encoding.js +216 -0
  144. package/node_modules/remote-pi/dist/mesh/encoding.js.map +1 -0
  145. package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +73 -0
  146. package/node_modules/remote-pi/dist/mesh/self_revoke.js +401 -0
  147. package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +1 -0
  148. package/node_modules/remote-pi/dist/mesh/siblings.d.ts +49 -0
  149. package/node_modules/remote-pi/dist/mesh/siblings.js +159 -0
  150. package/node_modules/remote-pi/dist/mesh/siblings.js.map +1 -0
  151. package/node_modules/remote-pi/dist/mesh/types.d.ts +34 -0
  152. package/node_modules/remote-pi/dist/mesh/types.js +11 -0
  153. package/node_modules/remote-pi/dist/mesh/types.js.map +1 -0
  154. package/node_modules/remote-pi/dist/mesh/verify.d.ts +17 -0
  155. package/node_modules/remote-pi/dist/mesh/verify.js +86 -0
  156. package/node_modules/remote-pi/dist/mesh/verify.js.map +1 -0
  157. package/node_modules/remote-pi/dist/pairing/crypto.d.ts +8 -0
  158. package/node_modules/remote-pi/dist/pairing/crypto.js +22 -0
  159. package/node_modules/remote-pi/dist/pairing/crypto.js.map +1 -0
  160. package/node_modules/remote-pi/dist/pairing/handshake.d.ts +28 -0
  161. package/node_modules/remote-pi/dist/pairing/handshake.js +113 -0
  162. package/node_modules/remote-pi/dist/pairing/handshake.js.map +1 -0
  163. package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +16 -0
  164. package/node_modules/remote-pi/dist/pairing/noise-sha256.js +103 -0
  165. package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +1 -0
  166. package/node_modules/remote-pi/dist/pairing/qr.d.ts +59 -0
  167. package/node_modules/remote-pi/dist/pairing/qr.js +125 -0
  168. package/node_modules/remote-pi/dist/pairing/qr.js.map +1 -0
  169. package/node_modules/remote-pi/dist/pairing/storage.d.ts +120 -0
  170. package/node_modules/remote-pi/dist/pairing/storage.js +604 -0
  171. package/node_modules/remote-pi/dist/pairing/storage.js.map +1 -0
  172. package/node_modules/remote-pi/dist/protocol/codec.d.ts +7 -0
  173. package/node_modules/remote-pi/dist/protocol/codec.js +49 -0
  174. package/node_modules/remote-pi/dist/protocol/codec.js.map +1 -0
  175. package/node_modules/remote-pi/dist/protocol/types.d.ts +393 -0
  176. package/node_modules/remote-pi/dist/protocol/types.js +2 -0
  177. package/node_modules/remote-pi/dist/protocol/types.js.map +1 -0
  178. package/node_modules/remote-pi/dist/rooms.d.ts +29 -0
  179. package/node_modules/remote-pi/dist/rooms.js +57 -0
  180. package/node_modules/remote-pi/dist/rooms.js.map +1 -0
  181. package/node_modules/remote-pi/dist/session/address.d.ts +49 -0
  182. package/node_modules/remote-pi/dist/session/address.js +58 -0
  183. package/node_modules/remote-pi/dist/session/address.js.map +1 -0
  184. package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +55 -0
  185. package/node_modules/remote-pi/dist/session/agent_bridge.js +146 -0
  186. package/node_modules/remote-pi/dist/session/agent_bridge.js.map +1 -0
  187. package/node_modules/remote-pi/dist/session/bridge.d.ts +37 -0
  188. package/node_modules/remote-pi/dist/session/bridge.js +130 -0
  189. package/node_modules/remote-pi/dist/session/bridge.js.map +1 -0
  190. package/node_modules/remote-pi/dist/session/broker.d.ts +189 -0
  191. package/node_modules/remote-pi/dist/session/broker.js +507 -0
  192. package/node_modules/remote-pi/dist/session/broker.js.map +1 -0
  193. package/node_modules/remote-pi/dist/session/broker_remote.d.ts +74 -0
  194. package/node_modules/remote-pi/dist/session/broker_remote.js +583 -0
  195. package/node_modules/remote-pi/dist/session/broker_remote.js.map +1 -0
  196. package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +33 -0
  197. package/node_modules/remote-pi/dist/session/cwd_lock.js +126 -0
  198. package/node_modules/remote-pi/dist/session/cwd_lock.js.map +1 -0
  199. package/node_modules/remote-pi/dist/session/envelope.d.ts +33 -0
  200. package/node_modules/remote-pi/dist/session/envelope.js +117 -0
  201. package/node_modules/remote-pi/dist/session/envelope.js.map +1 -0
  202. package/node_modules/remote-pi/dist/session/global_config.d.ts +33 -0
  203. package/node_modules/remote-pi/dist/session/global_config.js +73 -0
  204. package/node_modules/remote-pi/dist/session/global_config.js.map +1 -0
  205. package/node_modules/remote-pi/dist/session/ipc.d.ts +27 -0
  206. package/node_modules/remote-pi/dist/session/ipc.js +22 -0
  207. package/node_modules/remote-pi/dist/session/ipc.js.map +1 -0
  208. package/node_modules/remote-pi/dist/session/leader_election.d.ts +32 -0
  209. package/node_modules/remote-pi/dist/session/leader_election.js +106 -0
  210. package/node_modules/remote-pi/dist/session/leader_election.js.map +1 -0
  211. package/node_modules/remote-pi/dist/session/local_config.d.ts +55 -0
  212. package/node_modules/remote-pi/dist/session/local_config.js +157 -0
  213. package/node_modules/remote-pi/dist/session/local_config.js.map +1 -0
  214. package/node_modules/remote-pi/dist/session/mesh_message.d.ts +20 -0
  215. package/node_modules/remote-pi/dist/session/mesh_message.js +28 -0
  216. package/node_modules/remote-pi/dist/session/mesh_message.js.map +1 -0
  217. package/node_modules/remote-pi/dist/session/mesh_node.d.ts +116 -0
  218. package/node_modules/remote-pi/dist/session/mesh_node.js +573 -0
  219. package/node_modules/remote-pi/dist/session/mesh_node.js.map +1 -0
  220. package/node_modules/remote-pi/dist/session/peer.d.ts +139 -0
  221. package/node_modules/remote-pi/dist/session/peer.js +451 -0
  222. package/node_modules/remote-pi/dist/session/peer.js.map +1 -0
  223. package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +13 -0
  224. package/node_modules/remote-pi/dist/session/peer_inventory.js +48 -0
  225. package/node_modules/remote-pi/dist/session/peer_inventory.js.map +1 -0
  226. package/node_modules/remote-pi/dist/session/peer_limits.d.ts +9 -0
  227. package/node_modules/remote-pi/dist/session/peer_limits.js +21 -0
  228. package/node_modules/remote-pi/dist/session/peer_limits.js.map +1 -0
  229. package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +39 -0
  230. package/node_modules/remote-pi/dist/session/setup_wizard.js +63 -0
  231. package/node_modules/remote-pi/dist/session/setup_wizard.js.map +1 -0
  232. package/node_modules/remote-pi/dist/session/tool_gate.d.ts +5 -0
  233. package/node_modules/remote-pi/dist/session/tool_gate.js +11 -0
  234. package/node_modules/remote-pi/dist/session/tool_gate.js.map +1 -0
  235. package/node_modules/remote-pi/dist/session/tools.d.ts +24 -0
  236. package/node_modules/remote-pi/dist/session/tools.js +252 -0
  237. package/node_modules/remote-pi/dist/session/tools.js.map +1 -0
  238. package/node_modules/remote-pi/dist/session/wizard.d.ts +13 -0
  239. package/node_modules/remote-pi/dist/session/wizard.js +20 -0
  240. package/node_modules/remote-pi/dist/session/wizard.js.map +1 -0
  241. package/node_modules/remote-pi/dist/settings.d.ts +15 -0
  242. package/node_modules/remote-pi/dist/settings.js +52 -0
  243. package/node_modules/remote-pi/dist/settings.js.map +1 -0
  244. package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +37 -0
  245. package/node_modules/remote-pi/dist/transport/peer_channel.js +98 -0
  246. package/node_modules/remote-pi/dist/transport/peer_channel.js.map +1 -0
  247. package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +29 -0
  248. package/node_modules/remote-pi/dist/transport/pi_forward_client.js +62 -0
  249. package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +1 -0
  250. package/node_modules/remote-pi/dist/transport/relay_client.d.ts +91 -0
  251. package/node_modules/remote-pi/dist/transport/relay_client.js +206 -0
  252. package/node_modules/remote-pi/dist/transport/relay_client.js.map +1 -0
  253. package/node_modules/remote-pi/dist/ui/footer.d.ts +32 -0
  254. package/node_modules/remote-pi/dist/ui/footer.js +34 -0
  255. package/node_modules/remote-pi/dist/ui/footer.js.map +1 -0
  256. package/node_modules/remote-pi/docs/daemon.md +289 -0
  257. package/node_modules/remote-pi/package.json +88 -0
  258. package/node_modules/remote-pi/service-templates/launchd.plist.template +35 -0
  259. package/node_modules/remote-pi/service-templates/systemd.service.template +19 -0
  260. package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +10 -0
  261. package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +38 -0
  262. package/node_modules/remote-pi/skills/agent-network/SKILL.md +310 -0
  263. package/package.json +19 -9
  264. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool-diff/write-display-utils.ts +0 -29
  265. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference-core.ts → reference/session.ts} +0 -0
  266. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-aliases.ts → shell/aliases.ts} +0 -0
  267. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ATTRIBUTION.md +0 -0
  268. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-presentation.ts +0 -0
  269. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/index.ts +0 -0
  270. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/render-utils.ts +0 -0
  271. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/shiki-highlight.ts +0 -0
  272. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/types.ts +0 -0
@@ -19,6 +19,7 @@ import { toolErrorOverride } from "./error-signal.ts";
19
19
  import { createMcpRuntimeOwner, createOwnedUi, isAbortError, type McpRuntimeOwner } from "./runtime-owner.ts";
20
20
  import { publishMcpStatusShutdown } from "./mcp-status.ts";
21
21
  import { runMcpScript } from "./mcp-code.ts";
22
+ import { cleanupMaterializedBinaryResources } from "./tool-registrar.ts";
22
23
 
23
24
  export type { McpAdapterOptions } from "./types.ts";
24
25
  export {
@@ -168,13 +169,23 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
168
169
  return resolveDirectTools(config, cache, prefix, envDirectToolOverride);
169
170
  }
170
171
 
172
+ function getActiveToolsIfReady(): string[] | undefined {
173
+ try {
174
+ return pi.getActiveTools?.();
175
+ } catch (error) {
176
+ if (error instanceof Error
177
+ && error.message.includes("Action methods cannot be called during extension loading")) return undefined;
178
+ throw error;
179
+ }
180
+ }
181
+
171
182
  function deactivateTools(toolNames: string[]): string[] {
172
183
  if (toolNames.length === 0) return [];
173
184
  const unregisterTool = (pi as ExtensionAPI & { unregisterTool?: (name: string) => boolean }).unregisterTool;
174
185
  const unregistered = toolNames.filter((toolName) => unregisterTool?.(toolName) === true);
175
186
  const fallbackNames = toolNames.filter((toolName) => !unregistered.includes(toolName));
176
187
  const remove = new Set(toolNames);
177
- const activeTools = pi.getActiveTools?.();
188
+ const activeTools = getActiveToolsIfReady();
178
189
  if (!activeTools || activeTools.length === 0) {
179
190
  for (const toolName of fallbackNames) fallbackDeactivatedTools.add(toolName);
180
191
  return unregistered;
@@ -206,7 +217,7 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
206
217
  registerDirectTool(spec);
207
218
  registeredDirectTools.set(spec.prefixedName, fingerprint);
208
219
  if (fallbackDeactivatedTools.delete(spec.prefixedName)) {
209
- const activeTools = pi.getActiveTools?.();
220
+ const activeTools = getActiveToolsIfReady();
210
221
  if (activeTools && !activeTools.includes(spec.prefixedName)) {
211
222
  pi.setActiveTools([...activeTools, spec.prefixedName]);
212
223
  }
@@ -275,6 +286,7 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
275
286
  });
276
287
 
277
288
  function startInitialization(ctx: ExtensionContext, owner: McpRuntimeOwner, oauthRuntime: McpOAuthRuntime, generation: number, staleReason: string): Promise<void> {
289
+ owner.addCleanup(() => cleanupMaterializedBinaryResources(owner.signal));
278
290
  const promise = initializeMcp(pi, ctx, owner, {
279
291
  ...(programmaticConfig || options.configPath !== undefined
280
292
  ? {
@@ -847,7 +859,7 @@ function installMcpAdapter(pi: ExtensionAPI, options: McpAdapterOptions) {
847
859
  registerProxyTool(description);
848
860
  return;
849
861
  }
850
- const activeTools = pi.getActiveTools?.();
862
+ const activeTools = getActiveToolsIfReady();
851
863
  if (activeTools && !activeTools.includes("mcp")) {
852
864
  pi.setActiveTools([...activeTools, "mcp"]);
853
865
  }
@@ -31,6 +31,7 @@ import {
31
31
  getOAuthState,
32
32
  clearOAuthState,
33
33
  getAuthBaseDir,
34
+ OAuthCredentialStoreError,
34
35
  type AuthStorageOptions,
35
36
  type StoredTokens,
36
37
  } from "./mcp-auth.ts"
@@ -48,6 +49,10 @@ export interface McpOAuthRuntime {
48
49
 
49
50
  export interface AuthenticateOptions {
50
51
  onAuthorizationUrl?: (authorizationUrl: string) => void | Promise<void>
52
+ onAuthorizationInput?: (
53
+ authorizationUrl: string,
54
+ signal: AbortSignal,
55
+ ) => Promise<string | undefined>
51
56
  authStorageOptions?: AuthStorageOptions
52
57
  signal?: AbortSignal
53
58
  runtime?: McpOAuthRuntime
@@ -211,6 +216,27 @@ export function extractOAuthConfig(definition: ServerEntry): McpOAuthConfig {
211
216
  }
212
217
  config.clientUri = clientUri
213
218
  }
219
+ if (definition.oauth?.logoUri !== undefined) {
220
+ if (typeof definition.oauth.logoUri !== "string") {
221
+ throw new Error("OAuth logoUri must be a string")
222
+ }
223
+ const logoUri = interpolateEnvVars(definition.oauth.logoUri).trim()
224
+ if (!logoUri) {
225
+ throw new Error("OAuth logoUri must not be empty")
226
+ }
227
+ // Consent screens fetch this server-side, so a local path silently renders
228
+ // nothing. Fail here instead, where the message can say why.
229
+ let parsed: URL
230
+ try {
231
+ parsed = new URL(logoUri)
232
+ } catch {
233
+ throw new Error("OAuth logoUri must be an absolute http(s) URL")
234
+ }
235
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
236
+ throw new Error("OAuth logoUri must be an absolute http(s) URL")
237
+ }
238
+ config.logoUri = logoUri
239
+ }
214
240
  if (definition.oauth?.skipIssuerMetadataValidation !== undefined) {
215
241
  if (typeof definition.oauth.skipIssuerMetadataValidation !== "boolean") {
216
242
  throw new Error("OAuth skipIssuerMetadataValidation must be a boolean")
@@ -546,6 +572,53 @@ export function parseAuthorizationCodeInput(input: string, expectedState?: strin
546
572
  return parseAuthorizationRedirectInput(input, expectedState).code
547
573
  }
548
574
 
575
+ type AuthorizationResponse = {
576
+ input: AuthorizationCodeInput
577
+ source: "callback" | "manual"
578
+ }
579
+
580
+ /**
581
+ * Wait for either the localhost callback or a manually pasted redirect URL.
582
+ * The manual input prompt is dismissed as soon as either path finishes.
583
+ */
584
+ export async function waitForAuthorizationResponse(
585
+ callbackPromise: Promise<AuthorizationCodeInput>,
586
+ authorizationUrl: string,
587
+ expectedState: string,
588
+ onAuthorizationInput?: AuthenticateOptions["onAuthorizationInput"],
589
+ signal?: AbortSignal,
590
+ ): Promise<AuthorizationResponse> {
591
+ if (!onAuthorizationInput) {
592
+ return {
593
+ input: await abortable(callbackPromise, signal),
594
+ source: "callback",
595
+ }
596
+ }
597
+
598
+ const inputController = new AbortController()
599
+ try {
600
+ const response = await abortable(Promise.race([
601
+ callbackPromise.then((input) => ({ input, source: "callback" as const })),
602
+ onAuthorizationInput(authorizationUrl, inputController.signal).then((input) => ({
603
+ input,
604
+ source: "manual" as const,
605
+ })),
606
+ ]), signal)
607
+
608
+ if (response.source === "callback") return response
609
+ if (!response.input?.trim()) throw new Error("OAuth authentication cancelled")
610
+ if (!getSearchParamsFromInput(response.input.trim())) {
611
+ throw new Error("Paste the full OAuth callback URL, including its code and state parameters")
612
+ }
613
+ return {
614
+ input: parseAuthorizationRedirectInput(response.input, expectedState),
615
+ source: "manual",
616
+ }
617
+ } finally {
618
+ inputController.abort()
619
+ }
620
+ }
621
+
549
622
  /**
550
623
  * Complete OAuth authentication from manual user input.
551
624
  */
@@ -706,12 +779,22 @@ export async function authenticate(
706
779
  console.warn(`MCP Auth: Failed to open browser for ${serverName}; waiting for manual callback`, { error })
707
780
  }
708
781
 
709
- const callbackResult = await abortable(callbackPromise, signal)
782
+ const authorizationResponse = await waitForAuthorizationResponse(
783
+ callbackPromise,
784
+ authorizationUrl,
785
+ oauthState,
786
+ options.onAuthorizationInput,
787
+ signal,
788
+ )
789
+ if (authorizationResponse.source === "manual") {
790
+ cancelPendingCallback(oauthState)
791
+ }
710
792
 
711
- // The callback server accepted only the flow-local reserved state.
793
+ // The callback server accepted only the flow-local reserved state. Manual
794
+ // input is checked against the same state before token exchange.
712
795
  throwIfAborted(signal)
713
796
 
714
- return await completeAuth(serverName, callbackResult, {
797
+ return await completeAuth(serverName, authorizationResponse.input, {
715
798
  ...options,
716
799
  ...(signal ? { signal } : {}),
717
800
  runtime,
@@ -799,7 +882,7 @@ export async function getValidToken(
799
882
  authProvider.deactivate()
800
883
  }
801
884
  } catch (error) {
802
- if (isAbortError(error, signal)) throw error
885
+ if (isAbortError(error, signal) || error instanceof OAuthCredentialStoreError) throw error
803
886
  console.error(`MCP Auth: Token refresh failed for ${serverName}`, { error })
804
887
  return null
805
888
  }
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  import { createServer, type Server, type IncomingMessage, type ServerResponse } from "http"
9
+ import { getAppName } from "./agent-dir.ts"
9
10
  import {
10
11
  DEFAULT_OAUTH_CALLBACK_PATH,
11
12
  getConfiguredOAuthCallbackPort,
@@ -15,45 +16,106 @@ import {
15
16
  setOAuthCallbackPort,
16
17
  } from "./mcp-oauth-provider.ts"
17
18
 
18
- // HTML templates for callback responses
19
- const HTML_SUCCESS = `<!DOCTYPE html>
20
- <html>
21
- <head>
22
- <title>Pi - Authorization Successful</title>
23
- <style>
24
- body { font-family: system-ui, -apple-system, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #1a1a2e; color: #eee; }
25
- .container { text-align: center; padding: 2rem; }
26
- h1 { color: #4ade80; margin-bottom: 1rem; }
27
- p { color: #aaa; }
28
- </style>
29
- </head>
30
- <body>
31
- <div class="container">
32
- <h1>Authorization Successful</h1>
33
- <p>You can close this window and return to Pi.</p>
34
- </div>
35
- <script>setTimeout(() => window.close(), 2000);</script>
36
- </body>
37
- </html>`
38
-
39
- const HTML_MANUAL_SUCCESS = `<!DOCTYPE html>
40
- <html>
19
+ // HTML templates for callback responses.
20
+ //
21
+ // These pages are served from localhost during OAuth and are the last thing a
22
+ // user sees before returning to their terminal, so they are self-contained: no
23
+ // webfonts, no external assets, nothing that needs the network. They also name
24
+ // the host rather than hardcoding "Pi", so a distribution that rebrands pi
25
+ // (arc, tau, …) does not send its users back to an app they are not running.
26
+
27
+ /** Shared chrome: system fonts, a centred card, and light/dark support. */
28
+ const PAGE_STYLE = `
29
+ :root { color-scheme: light dark; }
30
+ * { box-sizing: border-box; }
31
+ body {
32
+ margin: 0;
33
+ min-height: 100vh;
34
+ display: flex;
35
+ align-items: center;
36
+ justify-content: center;
37
+ padding: 24px;
38
+ font: 15px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
39
+ background: #0f1117;
40
+ color: #e6e8ee;
41
+ }
42
+ .card {
43
+ width: 100%;
44
+ max-width: 26rem;
45
+ padding: 2.5rem 2rem;
46
+ text-align: center;
47
+ background: #161922;
48
+ border: 1px solid #242938;
49
+ border-radius: 14px;
50
+ box-shadow: 0 1px 2px rgba(0,0,0,.3), 0 12px 32px rgba(0,0,0,.25);
51
+ }
52
+ .badge {
53
+ width: 3rem; height: 3rem;
54
+ margin: 0 auto 1.25rem;
55
+ display: grid; place-items: center;
56
+ border-radius: 50%;
57
+ }
58
+ .badge svg { width: 1.5rem; height: 1.5rem; display: block; }
59
+ .ok { background: rgba(74,222,128,.12); color: #4ade80; }
60
+ .bad { background: rgba(248,113,113,.12); color: #f87171; }
61
+ h1 { margin: 0 0 .5rem; font-size: 1.15rem; font-weight: 600; letter-spacing: -0.01em; }
62
+ p { margin: 0; color: #9aa1b1; }
63
+ .app { color: #e6e8ee; font-weight: 500; }
64
+ .hint { margin-top: 1.25rem; font-size: .8125rem; color: #6b7280; }
65
+ code {
66
+ display: block;
67
+ margin-top: 1.25rem;
68
+ padding: .75rem .875rem;
69
+ text-align: left;
70
+ font: 12px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
71
+ color: #fca5a5;
72
+ background: rgba(248,113,113,.08);
73
+ border: 1px solid rgba(248,113,113,.2);
74
+ border-radius: 8px;
75
+ overflow-wrap: anywhere;
76
+ }
77
+ @media (prefers-color-scheme: light) {
78
+ body { background: #f6f7f9; color: #121620; }
79
+ .card { background: #fff; border-color: #e4e7ee; }
80
+ p { color: #5b6474; }
81
+ .app { color: #121620; }
82
+ .hint { color: #8b93a3; }
83
+ }`
84
+
85
+ const CHECK_ICON =
86
+ '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>'
87
+
88
+ const CROSS_ICON =
89
+ '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg>'
90
+
91
+ function page(options: {
92
+ title: string
93
+ heading: string
94
+ body: string
95
+ icon: string
96
+ tone: "ok" | "bad"
97
+ extra?: string
98
+ autoClose?: boolean
99
+ }): string {
100
+ return `<!DOCTYPE html>
101
+ <html lang="en">
41
102
  <head>
42
- <title>Pi - Authorization Received</title>
43
- <style>
44
- body { font-family: system-ui, -apple-system, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #1a1a2e; color: #eee; }
45
- .container { text-align: center; padding: 2rem; }
46
- h1 { color: #4ade80; margin-bottom: 1rem; }
47
- p { color: #aaa; }
103
+ <meta charset="utf-8">
104
+ <meta name="viewport" content="width=device-width, initial-scale=1">
105
+ <title>${options.title}</title>
106
+ <style>${PAGE_STYLE}
48
107
  </style>
49
108
  </head>
50
109
  <body>
51
- <div class="container">
52
- <h1>Authorization Received</h1>
53
- <p>Copy the full callback URL from your browser address bar and paste it back into Pi with auth-complete.</p>
54
- </div>
55
- </body>
110
+ <main class="card">
111
+ <div class="badge ${options.tone}">${options.icon}</div>
112
+ <h1>${options.heading}</h1>
113
+ <p>${options.body}</p>
114
+ ${options.extra ?? ""}
115
+ </main>
116
+ ${options.autoClose ? " <script>setTimeout(() => window.close(), 2000);</script>\n" : ""}</body>
56
117
  </html>`
118
+ }
57
119
 
58
120
  function escapeHtml(value: string): string {
59
121
  return value
@@ -64,26 +126,41 @@ function escapeHtml(value: string): string {
64
126
  .replace(/'/g, "&#39;")
65
127
  }
66
128
 
67
- const HTML_ERROR = (error: string) => `<!DOCTYPE html>
68
- <html>
69
- <head>
70
- <title>Pi - Authorization Failed</title>
71
- <style>
72
- body { font-family: system-ui, -apple-system, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #1a1a2e; color: #eee; }
73
- .container { text-align: center; padding: 2rem; }
74
- h1 { color: #f87171; margin-bottom: 1rem; }
75
- p { color: #aaa; }
76
- .error { color: #fca5a5; font-family: monospace; margin-top: 1rem; padding: 1rem; background: rgba(248,113,113,0.1); border-radius: 0.5rem; }
77
- </style>
78
- </head>
79
- <body>
80
- <div class="container">
81
- <h1>Authorization Failed</h1>
82
- <p>An error occurred during authorization.</p>
83
- <div class="error">${escapeHtml(error)}</div>
84
- </div>
85
- </body>
86
- </html>`
129
+ /** Built per request so a host that sets PI_PACKAGE_DIR late is still named right. */
130
+ function htmlSuccess(): string {
131
+ const app = escapeHtml(getAppName())
132
+ return page({
133
+ title: `${app} — Authorization Successful`,
134
+ heading: "Authorization Successful",
135
+ body: `You can close this window and return to <span class="app">${app}</span>.`,
136
+ icon: CHECK_ICON,
137
+ tone: "ok",
138
+ autoClose: true,
139
+ })
140
+ }
141
+
142
+ function htmlManualSuccess(): string {
143
+ const app = escapeHtml(getAppName())
144
+ return page({
145
+ title: `${app} — Authorization Received`,
146
+ heading: "Authorization Received",
147
+ body: `Copy the full callback URL from your browser address bar and paste it back into <span class="app">${app}</span> with auth-complete.`,
148
+ icon: CHECK_ICON,
149
+ tone: "ok",
150
+ })
151
+ }
152
+
153
+ function htmlError(error: string): string {
154
+ const app = escapeHtml(getAppName())
155
+ return page({
156
+ title: `${app} — Authorization Failed`,
157
+ heading: "Authorization Failed",
158
+ body: `Something went wrong during authorization. You can close this window and try again from <span class="app">${app}</span>.`,
159
+ icon: CROSS_ICON,
160
+ tone: "bad",
161
+ extra: `<code>${escapeHtml(error)}</code>`,
162
+ })
163
+ }
87
164
 
88
165
  /** Result of a successful OAuth callback */
89
166
  export interface OAuthCallbackResult {
@@ -145,7 +222,7 @@ function handleRequest(req: IncomingMessage, res: ServerResponse): void {
145
222
  if (!state) {
146
223
  const errorMsg = "Missing required state parameter - potential CSRF attack"
147
224
  res.writeHead(400, { "Content-Type": "text/html" })
148
- res.end(HTML_ERROR(errorMsg))
225
+ res.end(htmlError(errorMsg))
149
226
  return
150
227
  }
151
228
 
@@ -157,14 +234,14 @@ function handleRequest(req: IncomingMessage, res: ServerResponse): void {
157
234
  if (!pending && !isReserved) {
158
235
  const errorMsg = "Invalid or expired state parameter - potential CSRF attack"
159
236
  res.writeHead(400, { "Content-Type": "text/html" })
160
- res.end(HTML_ERROR(errorMsg))
237
+ res.end(htmlError(errorMsg))
161
238
  return
162
239
  }
163
240
 
164
241
  const errorMsg = errorDescription || error
165
242
  // Send HTTP response first before rejecting promise
166
243
  res.writeHead(200, { "Content-Type": "text/html" })
167
- res.end(HTML_ERROR(errorMsg))
244
+ res.end(htmlError(errorMsg))
168
245
  // Reject promise after response is sent (defer to allow test to attach handler)
169
246
  if (pending) {
170
247
  reservedAuthStates.delete(state)
@@ -179,20 +256,20 @@ function handleRequest(req: IncomingMessage, res: ServerResponse): void {
179
256
  if (!pending && !isReserved) {
180
257
  const errorMsg = "Invalid or expired state parameter - potential CSRF attack"
181
258
  res.writeHead(400, { "Content-Type": "text/html" })
182
- res.end(HTML_ERROR(errorMsg))
259
+ res.end(htmlError(errorMsg))
183
260
  return
184
261
  }
185
262
 
186
263
  // Require authorization code
187
264
  if (!code) {
188
265
  res.writeHead(400, { "Content-Type": "text/html" })
189
- res.end(HTML_ERROR("No authorization code provided"))
266
+ res.end(htmlError("No authorization code provided"))
190
267
  return
191
268
  }
192
269
 
193
270
  if (!pending) {
194
271
  res.writeHead(200, { "Content-Type": "text/html" })
195
- res.end(HTML_MANUAL_SUCCESS)
272
+ res.end(htmlManualSuccess())
196
273
  return
197
274
  }
198
275
 
@@ -202,7 +279,7 @@ function handleRequest(req: IncomingMessage, res: ServerResponse): void {
202
279
  pending.resolve({ code, ...(iss !== null ? { iss } : {}) })
203
280
 
204
281
  res.writeHead(200, { "Content-Type": "text/html" })
205
- res.end(HTML_SUCCESS)
282
+ res.end(htmlSuccess())
206
283
  }
207
284
 
208
285
  /**
@@ -30,6 +30,37 @@ import {
30
30
  type StoredClientInfo,
31
31
  } from "./mcp-auth.ts"
32
32
  import { resolveCommandSecret } from "./utils.ts"
33
+ import { getAppClientUri, getAppName } from "./agent-dir.ts"
34
+
35
+ /**
36
+ * Client name advertised during Dynamic Client Registration.
37
+ *
38
+ * A distribution that rebrands pi (arc, tau, …) should register under its own
39
+ * name — otherwise every consent screen its users see asks them to authorize
40
+ * an app they have never run. Stock pi keeps the long-standing
41
+ * "Pi Coding Agent" so existing registrations are unaffected.
42
+ */
43
+ function defaultClientName(): string {
44
+ const app = getAppName()
45
+ return app === "pi" ? "Pi Coding Agent" : app
46
+ }
47
+
48
+ /**
49
+ * Client homepage advertised during Dynamic Client Registration.
50
+ *
51
+ * RFC 7591 defines client_uri as the home page *of the client*. Under a
52
+ * rebranded pi the client is that distribution, not this adapter, so pointing
53
+ * at the adapter's repository misidentifies it on the consent screen. There is
54
+ * no way to guess the right URL and a wrong one is worse than none, so the
55
+ * field is omitted unless a server config supplies oauth.clientUri.
56
+ *
57
+ * Stock pi keeps the historical value.
58
+ */
59
+ function defaultClientUri(): string | undefined {
60
+ const declared = getAppClientUri()
61
+ if (declared) return declared
62
+ return getAppName() === "pi" ? "https://github.com/nicobailon/pi-mcp-adapter" : undefined
63
+ }
33
64
 
34
65
  type IssuerBoundClientInformation = OAuthClientInformationMixed & { issuer?: string }
35
66
  type IssuerBoundTokens = OAuthTokens & { issuer?: string }
@@ -86,6 +117,7 @@ export interface McpOAuthConfig {
86
117
  redirectUri?: string
87
118
  clientName?: string
88
119
  clientUri?: string
120
+ logoUri?: string
89
121
  skipIssuerMetadataValidation?: boolean
90
122
  }
91
123
 
@@ -189,6 +221,11 @@ export class McpOAuthProvider implements OAuthClientProvider {
189
221
  return this.redirectUrlSnapshot
190
222
  }
191
223
 
224
+ /** Configured homepage, else the historical default on stock pi, else nothing. */
225
+ private get clientUri(): string | undefined {
226
+ return this.config.clientUri ?? defaultClientUri()
227
+ }
228
+
192
229
  /**
193
230
  * Client metadata for dynamic registration.
194
231
  * Describes this client to the OAuth authorization server.
@@ -196,8 +233,9 @@ export class McpOAuthProvider implements OAuthClientProvider {
196
233
  get clientMetadata(): OAuthClientMetadata {
197
234
  if (this.usesClientCredentials) {
198
235
  return {
199
- client_name: this.config.clientName ?? "Pi Coding Agent",
200
- client_uri: this.config.clientUri ?? "https://github.com/nicobailon/pi-mcp-adapter",
236
+ client_name: this.config.clientName ?? defaultClientName(),
237
+ ...(this.clientUri !== undefined ? { client_uri: this.clientUri } : {}),
238
+ ...(this.config.logoUri !== undefined ? { logo_uri: this.config.logoUri } : {}),
201
239
  redirect_uris: [],
202
240
  grant_types: ["client_credentials"],
203
241
  token_endpoint_auth_method: this.config.clientSecret ? "client_secret_post" : "none",
@@ -211,8 +249,9 @@ export class McpOAuthProvider implements OAuthClientProvider {
211
249
 
212
250
  return {
213
251
  redirect_uris: [redirectUrl],
214
- client_name: this.config.clientName ?? "Pi Coding Agent",
215
- client_uri: this.config.clientUri ?? "https://github.com/nicobailon/pi-mcp-adapter",
252
+ client_name: this.config.clientName ?? defaultClientName(),
253
+ ...(this.clientUri !== undefined ? { client_uri: this.clientUri } : {}),
254
+ ...(this.config.logoUri !== undefined ? { logo_uri: this.config.logoUri } : {}),
216
255
  grant_types: ["authorization_code", "refresh_token"],
217
256
  response_types: ["code"],
218
257
  token_endpoint_auth_method: this.config.clientSecret ? "client_secret_post" : "none",
@@ -0,0 +1,48 @@
1
+ import { getValidToken } from "./mcp-auth-flow.ts";
2
+ import {
3
+ inspectAuthForUrl,
4
+ updateTokens,
5
+ type AuthStorageOptions,
6
+ type StoredTokens,
7
+ } from "./mcp-auth.ts";
8
+
9
+ export type McpOAuthTokens = StoredTokens;
10
+ export type McpOAuthStorageOptions = AuthStorageOptions;
11
+ export interface McpOAuthTokenOptions {
12
+ authStorageOptions?: McpOAuthStorageOptions;
13
+ signal?: AbortSignal;
14
+ skipIssuerMetadataValidation?: boolean;
15
+ }
16
+ export type McpOAuthTokenStatus =
17
+ | { status: "present"; tokens: McpOAuthTokens }
18
+ | { status: "absent" }
19
+ | { status: "unavailable"; message: string };
20
+
21
+ export async function getMcpOAuthTokensForUrl(
22
+ serverName: string,
23
+ serverUrl: string,
24
+ options: McpOAuthTokenOptions = {},
25
+ ): Promise<McpOAuthTokens | undefined> {
26
+ return (await getValidToken(serverName, serverUrl, options)) ?? undefined;
27
+ }
28
+
29
+ export function inspectMcpOAuthTokensForUrl(
30
+ serverName: string,
31
+ serverUrl: string,
32
+ options?: McpOAuthStorageOptions,
33
+ ): McpOAuthTokenStatus {
34
+ const status = inspectAuthForUrl(serverName, serverUrl, options);
35
+ if (status.status !== "present") return status;
36
+ return status.entry.tokens
37
+ ? { status: "present", tokens: status.entry.tokens }
38
+ : { status: "absent" };
39
+ }
40
+
41
+ export function updateMcpOAuthTokensForUrl(
42
+ serverName: string,
43
+ serverUrl: string,
44
+ tokens: McpOAuthTokens,
45
+ options?: McpOAuthStorageOptions,
46
+ ): void {
47
+ updateTokens(serverName, tokens, serverUrl, options);
48
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mcp-adapter",
3
- "version": "2.21.2",
3
+ "version": "2.23.0",
4
4
  "description": "MCP (Model Context Protocol) adapter extension for Pi coding agent",
5
5
  "type": "module",
6
6
  "types": "./index.ts",
@@ -14,6 +14,11 @@
14
14
  "types": "./types.ts",
15
15
  "import": "./types.ts",
16
16
  "default": "./types.ts"
17
+ },
18
+ "./oauth": {
19
+ "types": "./oauth.ts",
20
+ "import": "./oauth.ts",
21
+ "default": "./oauth.ts"
17
22
  }
18
23
  },
19
24
  "license": "MIT",
@@ -29,7 +34,7 @@
29
34
  "test": "vitest run",
30
35
  "test:watch": "vitest",
31
36
  "test:coverage": "vitest run --coverage",
32
- "test:oauth": "PI_MCP_ADAPTER_TEST_AUTH_STORE=memory node --import tsx --test --test-concurrency=1 mcp-auth.test.ts mcp-auth-flow.test.ts mcp-callback-server.test.ts mcp-oauth-provider.test.ts",
37
+ "test:oauth": "PI_MCP_ADAPTER_TEST_AUTH_STORE=memory node --import tsx --test --test-concurrency=1 oauth-public-api.test.ts mcp-auth.test.ts mcp-auth-flow.test.ts mcp-callback-server.test.ts mcp-oauth-provider.test.ts",
33
38
  "test:oauth-provider": "PI_MCP_ADAPTER_TEST_AUTH_STORE=memory node --import tsx --test mcp-oauth-provider.test.ts",
34
39
  "test:conformance": "bash conformance/run.sh"
35
40
  },
@@ -107,6 +112,7 @@
107
112
  "glimpse-ui.ts",
108
113
  "npx-resolver.ts",
109
114
  "oauth-handler.ts",
115
+ "oauth.ts",
110
116
  "mcp-auth.ts",
111
117
  "mcp-keyring-helper.cjs",
112
118
  "mcp-oauth-provider.ts",