@herbertgao/pi-extensions 2026.8.1 → 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 (403) hide show
  1. package/README.md +13 -3
  2. package/node_modules/@czottmann/pi-automode/README.md +16 -2
  3. package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +35 -0
  4. package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +18 -9
  5. package/node_modules/@czottmann/pi-automode/docs/defaults.md +6 -2
  6. package/node_modules/@czottmann/pi-automode/examples/automode.local.json +6 -0
  7. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +11 -7
  8. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +100 -0
  9. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +32 -0
  10. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +78 -3
  11. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +16 -4
  12. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +23 -1
  13. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +22 -1
  14. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +18 -2
  15. package/node_modules/@czottmann/pi-automode/package.json +4 -4
  16. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-audit.md +5 -0
  17. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-debt.md +5 -0
  18. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-gain.md +5 -0
  19. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-help.md +5 -0
  20. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-review.md +5 -0
  21. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail.md +5 -0
  22. package/node_modules/@dietrichgebert/ponytail/.opencode/plugins/ponytail-frontmatter.cjs +23 -0
  23. package/node_modules/@dietrichgebert/ponytail/.opencode/plugins/ponytail.mjs +99 -0
  24. package/node_modules/@dietrichgebert/ponytail/.qoder/rules/ponytail.md +30 -0
  25. package/node_modules/@dietrichgebert/ponytail/.qoder-plugin/plugin.json +16 -0
  26. package/node_modules/@dietrichgebert/ponytail/AGENTS.md +32 -0
  27. package/node_modules/@dietrichgebert/ponytail/LICENSE +21 -0
  28. package/node_modules/@dietrichgebert/ponytail/README.es.md +298 -0
  29. package/node_modules/@dietrichgebert/ponytail/README.ko.md +315 -0
  30. package/node_modules/@dietrichgebert/ponytail/README.md +351 -0
  31. package/node_modules/@dietrichgebert/ponytail/assets/benchmark-3model.svg +21 -0
  32. package/node_modules/@dietrichgebert/ponytail/assets/benchmark-agentic.svg +62 -0
  33. package/node_modules/@dietrichgebert/ponytail/assets/logo-dark.png +0 -0
  34. package/node_modules/@dietrichgebert/ponytail/assets/logo-dark.svg +115 -0
  35. package/node_modules/@dietrichgebert/ponytail/assets/logo-greenpt-dark.svg +27 -0
  36. package/node_modules/@dietrichgebert/ponytail/assets/logo-greenpt.svg +27 -0
  37. package/node_modules/@dietrichgebert/ponytail/assets/logo.png +0 -0
  38. package/node_modules/@dietrichgebert/ponytail/assets/social-preview.png +0 -0
  39. package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner-es.png +0 -0
  40. package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner-ko.png +0 -0
  41. package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner.png +0 -0
  42. package/node_modules/@dietrichgebert/ponytail/hooks/claude-codex-hooks.json +44 -0
  43. package/node_modules/@dietrichgebert/ponytail/hooks/copilot-hooks.json +21 -0
  44. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-activate.js +96 -0
  45. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-config.js +169 -0
  46. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-instructions.js +98 -0
  47. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-mode-tracker.js +130 -0
  48. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-runtime.js +85 -0
  49. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-statusline.ps1 +24 -0
  50. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-statusline.sh +18 -0
  51. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-subagent.js +77 -0
  52. package/node_modules/@dietrichgebert/ponytail/hooks/qoder-hooks.json +26 -0
  53. package/node_modules/@dietrichgebert/ponytail/package.json +47 -0
  54. package/node_modules/@dietrichgebert/ponytail/pi-extension/index.js +211 -0
  55. package/node_modules/@dietrichgebert/ponytail/pi-extension/package.json +8 -0
  56. package/node_modules/@dietrichgebert/ponytail/scripts/uninstall.js +60 -0
  57. package/node_modules/@dietrichgebert/ponytail/skills/ponytail/SKILL.md +120 -0
  58. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-audit/SKILL.md +41 -0
  59. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-debt/SKILL.md +44 -0
  60. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-gain/SKILL.md +50 -0
  61. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-help/SKILL.md +71 -0
  62. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-review/SKILL.md +57 -0
  63. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -10
  64. package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -9
  65. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +101 -0
  66. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +1 -17
  67. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +15 -9
  68. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{utils/agent-summary.ts → feature/agent-summary/core.ts} +37 -35
  69. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-summary.ts → agent-summary/index.ts} +3 -3
  70. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +24 -83
  71. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +1 -1
  72. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference.ts → reference/index.ts} +1 -1
  73. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-autocomplete.ts → reference/subagent.ts} +19 -9
  74. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-startup-header.ts → shell/startup-header.ts} +1 -1
  75. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{working-message.ts → shell/working-message.ts} +5 -2
  76. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +32 -28
  77. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +452 -94
  78. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +727 -0
  79. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +66 -776
  80. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +134 -11
  81. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +130 -0
  82. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +90 -568
  83. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +144 -0
  84. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +143 -0
  85. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +195 -0
  86. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ansi-utils.ts +56 -1
  87. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-renderer.ts +4 -4
  88. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/line-width-safety.ts +1 -1
  89. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +12 -0
  90. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/write-execution.ts +1 -2
  91. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-grouping.ts → tool/grouping.ts} +27 -10
  92. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-result.ts → tool/result.ts} +4 -13
  93. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/transcript-refresh.ts +91 -0
  94. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +0 -27
  95. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  96. package/node_modules/@herbertgao/pi-cc-extensions/themes/cc-dark.json +1 -0
  97. package/node_modules/@herbertgao/pi-cc-extensions/themes/cc-light.json +2 -2
  98. package/node_modules/@herbertgao/pi-stash/README.md +9 -9
  99. package/node_modules/@herbertgao/pi-stash/package.json +1 -1
  100. package/node_modules/@herbertgao/pi-stash/src/index.ts +2 -1
  101. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +20 -0
  102. package/node_modules/@herbertgao/pi-subagents/README.md +6 -2
  103. package/node_modules/@herbertgao/pi-subagents/package.json +3 -3
  104. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +1 -0
  105. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +3 -1
  106. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +85 -11
  107. package/node_modules/@herbertgao/pi-subagents/src/index.ts +61 -39
  108. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +26 -35
  109. package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +15 -1
  110. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +12 -0
  111. package/node_modules/@herbertgao/pi-subagents/src/types.ts +2 -0
  112. package/node_modules/@narumitw/pi-btw/LICENSE +21 -0
  113. package/node_modules/@narumitw/pi-btw/README.md +210 -0
  114. package/node_modules/@narumitw/pi-btw/package.json +53 -0
  115. package/node_modules/@narumitw/pi-btw/src/bring-to-main.ts +632 -0
  116. package/node_modules/@narumitw/pi-btw/src/btw.ts +996 -0
  117. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +339 -0
  118. package/node_modules/@narumitw/pi-btw/src/index.ts +1 -0
  119. package/node_modules/@narumitw/pi-btw/src/menu.ts +296 -0
  120. package/node_modules/@narumitw/pi-btw/src/settings.ts +237 -0
  121. package/node_modules/@narumitw/pi-btw/src/side-thread.ts +238 -0
  122. package/node_modules/@narumitw/pi-btw/src/text.ts +10 -0
  123. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +620 -0
  124. package/node_modules/@pi-plugins/fast-mode/LICENSE +21 -0
  125. package/node_modules/@pi-plugins/fast-mode/README.md +92 -0
  126. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts +6 -0
  127. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -0
  128. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +2026 -0
  129. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -0
  130. package/node_modules/@pi-plugins/fast-mode/package.json +73 -0
  131. package/node_modules/pi-mcp-adapter/CHANGELOG.md +78 -0
  132. package/node_modules/pi-mcp-adapter/README.md +80 -16
  133. package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
  134. package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +377 -0
  135. package/node_modules/pi-mcp-adapter/commands.ts +21 -9
  136. package/node_modules/pi-mcp-adapter/config.ts +110 -49
  137. package/node_modules/pi-mcp-adapter/direct-tools.ts +40 -27
  138. package/node_modules/pi-mcp-adapter/elicitation-handler.ts +37 -36
  139. package/node_modules/pi-mcp-adapter/errors.ts +21 -17
  140. package/node_modules/pi-mcp-adapter/host-html-template.ts +13 -7
  141. package/node_modules/pi-mcp-adapter/index.ts +52 -17
  142. package/node_modules/pi-mcp-adapter/init.ts +9 -7
  143. package/node_modules/pi-mcp-adapter/json-schema-validator.ts +2 -2
  144. package/node_modules/pi-mcp-adapter/lifecycle.ts +8 -8
  145. package/node_modules/pi-mcp-adapter/logger.ts +1 -1
  146. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +122 -25
  147. package/node_modules/pi-mcp-adapter/mcp-auth.ts +120 -2
  148. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
  149. package/node_modules/pi-mcp-adapter/mcp-code.ts +13 -11
  150. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +62 -17
  151. package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +15 -11
  152. package/node_modules/pi-mcp-adapter/mcp-panel.ts +34 -15
  153. package/node_modules/pi-mcp-adapter/mcp-probe.ts +131 -34
  154. package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +2 -2
  155. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +7 -4
  156. package/node_modules/pi-mcp-adapter/mcp-trace.ts +59 -64
  157. package/node_modules/pi-mcp-adapter/metadata-cache.ts +34 -26
  158. package/node_modules/pi-mcp-adapter/npx-resolver.ts +6 -4
  159. package/node_modules/pi-mcp-adapter/oauth-handler.ts +1 -1
  160. package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
  161. package/node_modules/pi-mcp-adapter/onboarding-state.ts +19 -11
  162. package/node_modules/pi-mcp-adapter/package.json +20 -9
  163. package/node_modules/pi-mcp-adapter/panel-keys.ts +20 -4
  164. package/node_modules/pi-mcp-adapter/prompts.ts +2 -2
  165. package/node_modules/pi-mcp-adapter/proxy-modes.ts +56 -21
  166. package/node_modules/pi-mcp-adapter/sampling-handler.ts +22 -15
  167. package/node_modules/pi-mcp-adapter/search-ranking.ts +2 -1
  168. package/node_modules/pi-mcp-adapter/server-manager.ts +165 -113
  169. package/node_modules/pi-mcp-adapter/session-recovery.ts +11 -12
  170. package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +3 -3
  171. package/node_modules/pi-mcp-adapter/state.ts +3 -1
  172. package/node_modules/pi-mcp-adapter/tool-approval.ts +67 -4
  173. package/node_modules/pi-mcp-adapter/tool-metadata.ts +6 -5
  174. package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
  175. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +14 -2
  176. package/node_modules/pi-mcp-adapter/ts-shape.ts +9 -2
  177. package/node_modules/pi-mcp-adapter/types.ts +111 -22
  178. package/node_modules/pi-mcp-adapter/ui-app-bridge-helpers.ts +40 -0
  179. package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +28 -19
  180. package/node_modules/pi-mcp-adapter/ui-server.ts +90 -58
  181. package/node_modules/pi-mcp-adapter/ui-session.ts +16 -14
  182. package/node_modules/pi-mcp-adapter/unix-socket-transport.ts +4 -4
  183. package/node_modules/pi-mcp-adapter/utils.ts +23 -9
  184. package/node_modules/pi-web-access/CHANGELOG.md +45 -0
  185. package/node_modules/pi-web-access/README.md +104 -29
  186. package/node_modules/pi-web-access/bocha.ts +221 -0
  187. package/node_modules/pi-web-access/curator-page.ts +113 -12
  188. package/node_modules/pi-web-access/curator-server.ts +56 -20
  189. package/node_modules/pi-web-access/datalab-pdf-extract.ts +568 -0
  190. package/node_modules/pi-web-access/duckduckgo.ts +123 -0
  191. package/node_modules/pi-web-access/extract.ts +288 -143
  192. package/node_modules/pi-web-access/feature-config.ts +29 -0
  193. package/node_modules/pi-web-access/gemini-api.ts +4 -0
  194. package/node_modules/pi-web-access/gemini-search.ts +45 -12
  195. package/node_modules/pi-web-access/gemini-web.ts +68 -3
  196. package/node_modules/pi-web-access/index.ts +160 -71
  197. package/node_modules/pi-web-access/jina-search.ts +284 -0
  198. package/node_modules/pi-web-access/kagi.ts +12 -12
  199. package/node_modules/pi-web-access/openai-search.ts +12 -2
  200. package/node_modules/pi-web-access/package.json +4 -3
  201. package/node_modules/pi-web-access/pdf-extract.ts +327 -228
  202. package/node_modules/pi-web-access/storage.ts +440 -2
  203. package/node_modules/pi-web-access/summary-model-scope.ts +1 -1
  204. package/node_modules/pi-web-access/summary-review.ts +4 -2
  205. package/node_modules/pi-web-access/video-extract.ts +10 -8
  206. package/node_modules/pi-web-access/xai-search.ts +12 -2
  207. package/node_modules/pi-web-access/youtube-extract.ts +2 -1
  208. package/node_modules/remote-pi/LICENSE +21 -0
  209. package/node_modules/remote-pi/README.md +675 -0
  210. package/node_modules/remote-pi/dist/actions/handlers.d.ts +122 -0
  211. package/node_modules/remote-pi/dist/actions/handlers.js +160 -0
  212. package/node_modules/remote-pi/dist/actions/handlers.js.map +1 -0
  213. package/node_modules/remote-pi/dist/actions/registry.d.ts +39 -0
  214. package/node_modules/remote-pi/dist/actions/registry.js +58 -0
  215. package/node_modules/remote-pi/dist/actions/registry.js.map +1 -0
  216. package/node_modules/remote-pi/dist/bin/supervisord.d.ts +2 -0
  217. package/node_modules/remote-pi/dist/bin/supervisord.js +86 -0
  218. package/node_modules/remote-pi/dist/bin/supervisord.js.map +1 -0
  219. package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +58 -0
  220. package/node_modules/remote-pi/dist/commands/builtin_mirror.js +71 -0
  221. package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +1 -0
  222. package/node_modules/remote-pi/dist/commands/list_commands.d.ts +60 -0
  223. package/node_modules/remote-pi/dist/commands/list_commands.js +73 -0
  224. package/node_modules/remote-pi/dist/commands/list_commands.js.map +1 -0
  225. package/node_modules/remote-pi/dist/config.d.ts +62 -0
  226. package/node_modules/remote-pi/dist/config.js +115 -0
  227. package/node_modules/remote-pi/dist/config.js.map +1 -0
  228. package/node_modules/remote-pi/dist/daemon/client.d.ts +20 -0
  229. package/node_modules/remote-pi/dist/daemon/client.js +131 -0
  230. package/node_modules/remote-pi/dist/daemon/client.js.map +1 -0
  231. package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +176 -0
  232. package/node_modules/remote-pi/dist/daemon/control_protocol.js +63 -0
  233. package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +1 -0
  234. package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +45 -0
  235. package/node_modules/remote-pi/dist/daemon/cron_log.js +72 -0
  236. package/node_modules/remote-pi/dist/daemon/cron_log.js.map +1 -0
  237. package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +80 -0
  238. package/node_modules/remote-pi/dist/daemon/cron_registry.js +194 -0
  239. package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +1 -0
  240. package/node_modules/remote-pi/dist/daemon/id.d.ts +24 -0
  241. package/node_modules/remote-pi/dist/daemon/id.js +36 -0
  242. package/node_modules/remote-pi/dist/daemon/id.js.map +1 -0
  243. package/node_modules/remote-pi/dist/daemon/install.d.ts +170 -0
  244. package/node_modules/remote-pi/dist/daemon/install.js +547 -0
  245. package/node_modules/remote-pi/dist/daemon/install.js.map +1 -0
  246. package/node_modules/remote-pi/dist/daemon/registry.d.ts +63 -0
  247. package/node_modules/remote-pi/dist/daemon/registry.js +153 -0
  248. package/node_modules/remote-pi/dist/daemon/registry.js.map +1 -0
  249. package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +194 -0
  250. package/node_modules/remote-pi/dist/daemon/rpc_child.js +389 -0
  251. package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +1 -0
  252. package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +93 -0
  253. package/node_modules/remote-pi/dist/daemon/supervisor.js +596 -0
  254. package/node_modules/remote-pi/dist/daemon/supervisor.js.map +1 -0
  255. package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +26 -0
  256. package/node_modules/remote-pi/dist/extension_ui_bridge.js +341 -0
  257. package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +1 -0
  258. package/node_modules/remote-pi/dist/index.d.ts +213 -0
  259. package/node_modules/remote-pi/dist/index.js +4996 -0
  260. package/node_modules/remote-pi/dist/index.js.map +1 -0
  261. package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +10 -0
  262. package/node_modules/remote-pi/dist/mcp/mesh_result.js +42 -0
  263. package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +1 -0
  264. package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +16 -0
  265. package/node_modules/remote-pi/dist/mcp/mesh_server.js +327 -0
  266. package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +1 -0
  267. package/node_modules/remote-pi/dist/mesh/canonical.d.ts +30 -0
  268. package/node_modules/remote-pi/dist/mesh/canonical.js +61 -0
  269. package/node_modules/remote-pi/dist/mesh/canonical.js.map +1 -0
  270. package/node_modules/remote-pi/dist/mesh/client.d.ts +18 -0
  271. package/node_modules/remote-pi/dist/mesh/client.js +125 -0
  272. package/node_modules/remote-pi/dist/mesh/client.js.map +1 -0
  273. package/node_modules/remote-pi/dist/mesh/encoding.d.ts +38 -0
  274. package/node_modules/remote-pi/dist/mesh/encoding.js +216 -0
  275. package/node_modules/remote-pi/dist/mesh/encoding.js.map +1 -0
  276. package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +73 -0
  277. package/node_modules/remote-pi/dist/mesh/self_revoke.js +401 -0
  278. package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +1 -0
  279. package/node_modules/remote-pi/dist/mesh/siblings.d.ts +49 -0
  280. package/node_modules/remote-pi/dist/mesh/siblings.js +159 -0
  281. package/node_modules/remote-pi/dist/mesh/siblings.js.map +1 -0
  282. package/node_modules/remote-pi/dist/mesh/types.d.ts +34 -0
  283. package/node_modules/remote-pi/dist/mesh/types.js +11 -0
  284. package/node_modules/remote-pi/dist/mesh/types.js.map +1 -0
  285. package/node_modules/remote-pi/dist/mesh/verify.d.ts +17 -0
  286. package/node_modules/remote-pi/dist/mesh/verify.js +86 -0
  287. package/node_modules/remote-pi/dist/mesh/verify.js.map +1 -0
  288. package/node_modules/remote-pi/dist/pairing/crypto.d.ts +8 -0
  289. package/node_modules/remote-pi/dist/pairing/crypto.js +22 -0
  290. package/node_modules/remote-pi/dist/pairing/crypto.js.map +1 -0
  291. package/node_modules/remote-pi/dist/pairing/handshake.d.ts +28 -0
  292. package/node_modules/remote-pi/dist/pairing/handshake.js +113 -0
  293. package/node_modules/remote-pi/dist/pairing/handshake.js.map +1 -0
  294. package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +16 -0
  295. package/node_modules/remote-pi/dist/pairing/noise-sha256.js +103 -0
  296. package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +1 -0
  297. package/node_modules/remote-pi/dist/pairing/qr.d.ts +59 -0
  298. package/node_modules/remote-pi/dist/pairing/qr.js +125 -0
  299. package/node_modules/remote-pi/dist/pairing/qr.js.map +1 -0
  300. package/node_modules/remote-pi/dist/pairing/storage.d.ts +120 -0
  301. package/node_modules/remote-pi/dist/pairing/storage.js +604 -0
  302. package/node_modules/remote-pi/dist/pairing/storage.js.map +1 -0
  303. package/node_modules/remote-pi/dist/protocol/codec.d.ts +7 -0
  304. package/node_modules/remote-pi/dist/protocol/codec.js +49 -0
  305. package/node_modules/remote-pi/dist/protocol/codec.js.map +1 -0
  306. package/node_modules/remote-pi/dist/protocol/types.d.ts +393 -0
  307. package/node_modules/remote-pi/dist/protocol/types.js +2 -0
  308. package/node_modules/remote-pi/dist/protocol/types.js.map +1 -0
  309. package/node_modules/remote-pi/dist/rooms.d.ts +29 -0
  310. package/node_modules/remote-pi/dist/rooms.js +57 -0
  311. package/node_modules/remote-pi/dist/rooms.js.map +1 -0
  312. package/node_modules/remote-pi/dist/session/address.d.ts +49 -0
  313. package/node_modules/remote-pi/dist/session/address.js +58 -0
  314. package/node_modules/remote-pi/dist/session/address.js.map +1 -0
  315. package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +55 -0
  316. package/node_modules/remote-pi/dist/session/agent_bridge.js +146 -0
  317. package/node_modules/remote-pi/dist/session/agent_bridge.js.map +1 -0
  318. package/node_modules/remote-pi/dist/session/bridge.d.ts +37 -0
  319. package/node_modules/remote-pi/dist/session/bridge.js +130 -0
  320. package/node_modules/remote-pi/dist/session/bridge.js.map +1 -0
  321. package/node_modules/remote-pi/dist/session/broker.d.ts +189 -0
  322. package/node_modules/remote-pi/dist/session/broker.js +507 -0
  323. package/node_modules/remote-pi/dist/session/broker.js.map +1 -0
  324. package/node_modules/remote-pi/dist/session/broker_remote.d.ts +74 -0
  325. package/node_modules/remote-pi/dist/session/broker_remote.js +583 -0
  326. package/node_modules/remote-pi/dist/session/broker_remote.js.map +1 -0
  327. package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +33 -0
  328. package/node_modules/remote-pi/dist/session/cwd_lock.js +126 -0
  329. package/node_modules/remote-pi/dist/session/cwd_lock.js.map +1 -0
  330. package/node_modules/remote-pi/dist/session/envelope.d.ts +33 -0
  331. package/node_modules/remote-pi/dist/session/envelope.js +117 -0
  332. package/node_modules/remote-pi/dist/session/envelope.js.map +1 -0
  333. package/node_modules/remote-pi/dist/session/global_config.d.ts +33 -0
  334. package/node_modules/remote-pi/dist/session/global_config.js +73 -0
  335. package/node_modules/remote-pi/dist/session/global_config.js.map +1 -0
  336. package/node_modules/remote-pi/dist/session/ipc.d.ts +27 -0
  337. package/node_modules/remote-pi/dist/session/ipc.js +22 -0
  338. package/node_modules/remote-pi/dist/session/ipc.js.map +1 -0
  339. package/node_modules/remote-pi/dist/session/leader_election.d.ts +32 -0
  340. package/node_modules/remote-pi/dist/session/leader_election.js +106 -0
  341. package/node_modules/remote-pi/dist/session/leader_election.js.map +1 -0
  342. package/node_modules/remote-pi/dist/session/local_config.d.ts +55 -0
  343. package/node_modules/remote-pi/dist/session/local_config.js +157 -0
  344. package/node_modules/remote-pi/dist/session/local_config.js.map +1 -0
  345. package/node_modules/remote-pi/dist/session/mesh_message.d.ts +20 -0
  346. package/node_modules/remote-pi/dist/session/mesh_message.js +28 -0
  347. package/node_modules/remote-pi/dist/session/mesh_message.js.map +1 -0
  348. package/node_modules/remote-pi/dist/session/mesh_node.d.ts +116 -0
  349. package/node_modules/remote-pi/dist/session/mesh_node.js +573 -0
  350. package/node_modules/remote-pi/dist/session/mesh_node.js.map +1 -0
  351. package/node_modules/remote-pi/dist/session/peer.d.ts +139 -0
  352. package/node_modules/remote-pi/dist/session/peer.js +451 -0
  353. package/node_modules/remote-pi/dist/session/peer.js.map +1 -0
  354. package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +13 -0
  355. package/node_modules/remote-pi/dist/session/peer_inventory.js +48 -0
  356. package/node_modules/remote-pi/dist/session/peer_inventory.js.map +1 -0
  357. package/node_modules/remote-pi/dist/session/peer_limits.d.ts +9 -0
  358. package/node_modules/remote-pi/dist/session/peer_limits.js +21 -0
  359. package/node_modules/remote-pi/dist/session/peer_limits.js.map +1 -0
  360. package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +39 -0
  361. package/node_modules/remote-pi/dist/session/setup_wizard.js +63 -0
  362. package/node_modules/remote-pi/dist/session/setup_wizard.js.map +1 -0
  363. package/node_modules/remote-pi/dist/session/tool_gate.d.ts +5 -0
  364. package/node_modules/remote-pi/dist/session/tool_gate.js +11 -0
  365. package/node_modules/remote-pi/dist/session/tool_gate.js.map +1 -0
  366. package/node_modules/remote-pi/dist/session/tools.d.ts +24 -0
  367. package/node_modules/remote-pi/dist/session/tools.js +252 -0
  368. package/node_modules/remote-pi/dist/session/tools.js.map +1 -0
  369. package/node_modules/remote-pi/dist/session/wizard.d.ts +13 -0
  370. package/node_modules/remote-pi/dist/session/wizard.js +20 -0
  371. package/node_modules/remote-pi/dist/session/wizard.js.map +1 -0
  372. package/node_modules/remote-pi/dist/settings.d.ts +15 -0
  373. package/node_modules/remote-pi/dist/settings.js +52 -0
  374. package/node_modules/remote-pi/dist/settings.js.map +1 -0
  375. package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +37 -0
  376. package/node_modules/remote-pi/dist/transport/peer_channel.js +98 -0
  377. package/node_modules/remote-pi/dist/transport/peer_channel.js.map +1 -0
  378. package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +29 -0
  379. package/node_modules/remote-pi/dist/transport/pi_forward_client.js +62 -0
  380. package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +1 -0
  381. package/node_modules/remote-pi/dist/transport/relay_client.d.ts +91 -0
  382. package/node_modules/remote-pi/dist/transport/relay_client.js +206 -0
  383. package/node_modules/remote-pi/dist/transport/relay_client.js.map +1 -0
  384. package/node_modules/remote-pi/dist/ui/footer.d.ts +32 -0
  385. package/node_modules/remote-pi/dist/ui/footer.js +34 -0
  386. package/node_modules/remote-pi/dist/ui/footer.js.map +1 -0
  387. package/node_modules/remote-pi/docs/daemon.md +289 -0
  388. package/node_modules/remote-pi/package.json +88 -0
  389. package/node_modules/remote-pi/service-templates/launchd.plist.template +35 -0
  390. package/node_modules/remote-pi/service-templates/systemd.service.template +19 -0
  391. package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +10 -0
  392. package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +38 -0
  393. package/node_modules/remote-pi/skills/agent-network/SKILL.md +310 -0
  394. package/package.json +37 -12
  395. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool-diff/write-display-utils.ts +0 -29
  396. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference-core.ts → reference/session.ts} +0 -0
  397. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-aliases.ts → shell/aliases.ts} +0 -0
  398. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ATTRIBUTION.md +0 -0
  399. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-presentation.ts +0 -0
  400. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/index.ts +0 -0
  401. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/render-utils.ts +0 -0
  402. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/shiki-highlight.ts +0 -0
  403. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/types.ts +0 -0
@@ -1,10 +1,10 @@
1
- import { RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/app-bridge";
2
- import { UrlElicitationRequiredError, type ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
1
+ import { RESOURCE_MIME_TYPE } from "./ui-app-bridge-helpers.ts";
2
+ import { UrlElicitationRequiredError, type ReadResourceResult } from "@modelcontextprotocol/client";
3
3
  import { ResourceFetchError, ResourceParseError } from "./errors.ts";
4
4
  import { logger } from "./logger.ts";
5
5
  import { SessionRecoveryAuthRequiredError, withSessionRecovery, type SessionRecoveryDeps } from "./session-recovery.ts";
6
6
  import type { McpServerManager } from "./server-manager.ts";
7
- import { isServerDisabled, type McpConfig, type UiResourceContent, type UiResourceCsp, type UiResourceMeta } from "./types.ts";
7
+ import { isServerDisabled, type McpConfig, type UiResourceContent, type UiResourceCsp, type UiResourceMeta, type UiResourcePermissions } from "./types.ts";
8
8
 
9
9
  interface ResourceContentRecord {
10
10
  uri?: string;
@@ -23,7 +23,7 @@ interface ReadUiResourceOptions {
23
23
  export class UiResourceHandler {
24
24
  private log = logger.child({ component: "UiResourceHandler" });
25
25
 
26
- constructor(private manager: McpServerManager, private config?: McpConfig) {}
26
+ constructor(private manager: McpServerManager, private config: McpConfig | undefined = undefined) {}
27
27
 
28
28
  async readUiResource(serverName: string, uri: string, options: ReadUiResourceOptions = {}): Promise<UiResourceContent> {
29
29
  const log = this.log.child({ server: serverName, uri });
@@ -45,7 +45,12 @@ export class UiResourceHandler {
45
45
  this.manager.incrementInFlight(serverName);
46
46
  try {
47
47
  result = await withSessionRecovery(
48
- { manager: this.manager, config, signal: options.signal, onNeedsAuth: options.onNeedsAuth },
48
+ {
49
+ manager: this.manager,
50
+ config,
51
+ ...(options.signal ? { signal: options.signal } : {}),
52
+ ...(options.onNeedsAuth ? { onNeedsAuth: options.onNeedsAuth } : {}),
53
+ },
49
54
  serverName,
50
55
  (connection) => connection.client.readResource({ uri }, this.manager.getRequestOptions(serverName, options.signal)),
51
56
  );
@@ -62,7 +67,7 @@ export class UiResourceHandler {
62
67
  log.error("Failed to read resource", error instanceof Error ? error : undefined);
63
68
  throw new ResourceFetchError(uri, message, {
64
69
  server: serverName,
65
- cause: error instanceof Error ? error : undefined,
70
+ ...(error instanceof Error ? { cause: error } : {}),
66
71
  });
67
72
  }
68
73
 
@@ -97,10 +102,14 @@ export class UiResourceHandler {
97
102
  html,
98
103
  mimeType: mimeType ?? RESOURCE_MIME_TYPE,
99
104
  meta: {
100
- csp: contentMeta.csp ?? listMeta.csp,
101
- permissions: contentMeta.permissions ?? listMeta.permissions,
102
- domain: contentMeta.domain ?? listMeta.domain,
103
- prefersBorder: contentMeta.prefersBorder ?? listMeta.prefersBorder,
105
+ ...((contentMeta.csp ?? listMeta.csp) !== undefined ? { csp: contentMeta.csp ?? listMeta.csp } : {}),
106
+ ...((contentMeta.permissions ?? listMeta.permissions) !== undefined
107
+ ? { permissions: contentMeta.permissions ?? listMeta.permissions }
108
+ : {}),
109
+ ...((contentMeta.domain ?? listMeta.domain) !== undefined ? { domain: contentMeta.domain ?? listMeta.domain } : {}),
110
+ ...((contentMeta.prefersBorder ?? listMeta.prefersBorder) !== undefined
111
+ ? { prefersBorder: contentMeta.prefersBorder ?? listMeta.prefersBorder }
112
+ : {}),
104
113
  },
105
114
  };
106
115
  }
@@ -128,7 +137,11 @@ function selectContent(result: ReadResourceResult, preferredUri: string): Resour
128
137
  );
129
138
  if (byHtmlMime) return byHtmlMime;
130
139
 
131
- return contents[0];
140
+ const firstContent = contents[0];
141
+ if (!firstContent) {
142
+ throw new Error(`No contents returned for UI resource: ${preferredUri}`);
143
+ }
144
+ return firstContent;
132
145
  }
133
146
 
134
147
  function isHtmlMimeType(mimeType: string): boolean {
@@ -166,10 +179,10 @@ function extractUiMeta(meta: Record<string, unknown> | undefined): UiResourceMet
166
179
 
167
180
  const ui = isRecord(meta.ui) ? meta.ui : undefined;
168
181
  const out: UiResourceMeta = {};
169
- const openAiCsp = hasOwnProperty(meta, "openai/widgetCSP")
182
+ const openAiCsp = Object.hasOwn(meta, "openai/widgetCSP")
170
183
  ? normalizeOpenAiWidgetCsp(meta["openai/widgetCSP"])
171
184
  : undefined;
172
- const hasStandardCsp = !!ui && hasOwnProperty(ui, "csp");
185
+ const hasStandardCsp = !!ui && Object.hasOwn(ui, "csp");
173
186
  const standardCspValue = hasStandardCsp ? ui.csp : undefined;
174
187
 
175
188
  if (hasStandardCsp && !isRecord(standardCspValue)) {
@@ -183,7 +196,7 @@ function extractUiMeta(meta: Record<string, unknown> | undefined): UiResourceMet
183
196
  out.csp = { ...openAiCsp, ...standardCsp };
184
197
  if (isRecord(standardCspValue)) {
185
198
  for (const [, standardField] of OPENAI_CSP_FIELD_MAPPINGS) {
186
- if (hasOwnProperty(standardCspValue, standardField) && !copyStringArray(standardCspValue[standardField])) {
199
+ if (Object.hasOwn(standardCspValue, standardField) && !copyStringArray(standardCspValue[standardField])) {
187
200
  delete out.csp[standardField];
188
201
  }
189
202
  }
@@ -192,7 +205,7 @@ function extractUiMeta(meta: Record<string, unknown> | undefined): UiResourceMet
192
205
  }
193
206
 
194
207
  if (ui && isRecord(ui.permissions)) {
195
- out.permissions = ui.permissions as UiResourceMeta["permissions"];
208
+ out.permissions = ui.permissions as UiResourcePermissions;
196
209
  }
197
210
  if (ui && typeof ui.domain === "string") {
198
211
  out.domain = ui.domain;
@@ -232,10 +245,6 @@ function copyStringArray(value: unknown): string[] | undefined {
232
245
  : undefined;
233
246
  }
234
247
 
235
- function hasOwnProperty(record: Record<string, unknown>, property: string): boolean {
236
- return Object.prototype.hasOwnProperty.call(record, property);
237
- }
238
-
239
248
  function isRecord(value: unknown): value is Record<string, unknown> {
240
249
  return typeof value === "object" && value !== null && !Array.isArray(value);
241
250
  }
@@ -2,12 +2,12 @@ import http, { type IncomingMessage, type ServerResponse } from "node:http";
2
2
  import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { randomUUID } from "node:crypto";
5
- import { buildAllowAttribute } from "@modelcontextprotocol/ext-apps/app-bridge";
5
+ import { buildAllowAttribute } from "./ui-app-bridge-helpers.ts";
6
6
  import {
7
- ContentBlockSchema,
8
7
  type CallToolRequest,
9
8
  type CallToolResult,
10
- } from "@modelcontextprotocol/sdk/types.js";
9
+ } from "@modelcontextprotocol/client";
10
+ import { ContentBlockSchema } from "@modelcontextprotocol/core";
11
11
  import type { ConsentManager } from "./consent-manager.ts";
12
12
  import { ServerError, wrapError } from "./errors.ts";
13
13
  import { formatAuthRequiredMessage } from "./utils.ts";
@@ -17,7 +17,7 @@ import type { McpServerManager } from "./server-manager.ts";
17
17
  import type { McpExtensionState } from "./state.ts";
18
18
  import { SessionRecoveryAuthRequiredError, withSessionRecovery, type SessionRecoveryDeps } from "./session-recovery.ts";
19
19
  import { ensureToolCallApproved, isToolCallApprovalRequired } from "./tool-approval.ts";
20
- import { extractUiToolVisibility, isUiToolCallableByApp } from "./ui-tool-visibility.ts";
20
+ import { extractUiToolVisibility, isUiToolCallableByApp, isUiToolVisibleToModel } from "./ui-tool-visibility.ts";
21
21
  import {
22
22
  createUiModelContextUpdate,
23
23
  extractUiPromptText,
@@ -95,6 +95,7 @@ export interface UiServerHandle {
95
95
 
96
96
  export async function startUiServer(options: UiServerOptions): Promise<UiServerHandle> {
97
97
  const sessionToken = options.sessionToken ?? randomUUID();
98
+ const uiResourceToken = randomUUID();
98
99
  const log = logger.child({
99
100
  component: "UiServer",
100
101
  server: options.serverName,
@@ -144,6 +145,41 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
144
145
  }
145
146
  }
146
147
 
148
+ const isAppOnlyTool = (toolName: string): boolean => {
149
+ const toolDefinition = options.manager.getConnection(options.serverName)?.tools?.find((tool) => tool.name === toolName);
150
+ if (!toolDefinition) return false;
151
+ const visibility = extractUiToolVisibility(toolDefinition._meta);
152
+ return isUiToolCallableByApp(visibility) && !isUiToolVisibleToModel(visibility);
153
+ };
154
+
155
+ const recordUiMessage = async (msgParams: UiMessageParams): Promise<void> => {
156
+ const promptText = extractUiPromptText(msgParams);
157
+
158
+ // Track messages by type (order: prompt → intent → notify)
159
+ // Must match the order in index.ts onMessage handler
160
+ if (promptText) {
161
+ sessionMessages.prompts.push(promptText);
162
+ log.debug("UI prompt received", { prompt: promptText.slice(0, 100) });
163
+ } else if (msgParams.type === "intent" || msgParams.intent) {
164
+ const intentName = msgParams.intent ?? "";
165
+ if (intentName) {
166
+ sessionMessages.intents.push({
167
+ intent: intentName,
168
+ ...(msgParams.params !== undefined ? { params: msgParams.params } : {}),
169
+ });
170
+ log.debug("UI intent received", { intent: intentName });
171
+ }
172
+ } else if (msgParams.type === "notify" || msgParams.message) {
173
+ const notifyText = msgParams.message ?? "";
174
+ if (notifyText) {
175
+ sessionMessages.notifications.push(notifyText);
176
+ log.debug("UI notification", { message: notifyText.slice(0, 100) });
177
+ }
178
+ }
179
+
180
+ await options.onMessage?.(msgParams);
181
+ };
182
+
147
183
  const touchHeartbeat = () => {
148
184
  lastHeartbeatAt = Date.now();
149
185
  };
@@ -164,7 +200,8 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
164
200
  streamSummary.phases.push(envelope.phase);
165
201
  }
166
202
  streamSummary.finalStatus = envelope.status;
167
- streamSummary.lastMessage = envelope.message;
203
+ if (envelope.message !== undefined) streamSummary.lastMessage = envelope.message;
204
+ else delete streamSummary.lastMessage;
168
205
  };
169
206
 
170
207
  const serializeEvent = (eventId: number, name: string, payload: unknown): string => {
@@ -174,6 +211,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
174
211
  const getLatestCheckpointIndex = () => {
175
212
  for (let index = eventLog.length - 1; index >= 0; index -= 1) {
176
213
  const entry = eventLog[index];
214
+ if (!entry) continue;
177
215
  const envelope = getVisualizationStreamEnvelope((entry.payload as { structuredContent?: unknown } | null)?.structuredContent);
178
216
  if (envelope?.frameType === "checkpoint" || envelope?.frameType === "final") {
179
217
  return index;
@@ -271,13 +309,11 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
271
309
  }
272
310
 
273
311
  if (method === "GET" && url.pathname === "/") {
274
- if (!url.searchParams.has("session") && isLoopbackAddress(req.socket.remoteAddress)) {
275
- const dest = `/?session=${encodeURIComponent(sessionToken)}`;
312
+ if (!url.searchParams.has("session")) {
276
313
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
277
314
  res.end(
278
- `<!doctype html><html><head><meta charset="utf-8"><title>${escapeHtml(`MCP UI - ${options.serverName} / ${options.toolName}`)}</title>` +
279
- `<noscript><meta http-equiv="refresh" content="0;url=${dest}"></noscript></head>` +
280
- `<body><script>location.replace(${JSON.stringify(dest)});</script></body></html>`,
315
+ "<!doctype html><html><head><meta charset=\"utf-8\"><title>MCP UI</title></head>" +
316
+ "<body><p>Open the authenticated MCP UI URL shown by Pi.</p></body></html>",
281
317
  );
282
318
  return;
283
319
  }
@@ -286,6 +322,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
286
322
 
287
323
  const html = buildHostHtmlTemplate({
288
324
  sessionToken,
325
+ uiResourceToken,
289
326
  serverName: options.serverName,
290
327
  toolName: options.toolName,
291
328
  toolArgs: options.toolArgs,
@@ -330,7 +367,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
330
367
  }
331
368
 
332
369
  if (method === "GET" && url.pathname === "/ui-app") {
333
- if (!validateTokenQuery(url, sessionToken, res)) return;
370
+ if (!validateTokenQuery(url, uiResourceToken, res, "resource")) return;
334
371
  touchHeartbeat();
335
372
  // Enforce host metadata independently of where app HTML places its document head.
336
373
  const cspContent = buildCspMetaContent(options.resource.meta.csp);
@@ -411,8 +448,8 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
411
448
  name: callParams.name,
412
449
  originalName: callParams.name,
413
450
  description: toolDefinition?.description ?? "",
414
- inputSchema: toolDefinition?.inputSchema,
415
- uiVisibility,
451
+ ...(toolDefinition?.inputSchema !== undefined ? { inputSchema: toolDefinition.inputSchema } : {}),
452
+ ...(uiVisibility !== undefined ? { uiVisibility } : {}),
416
453
  };
417
454
  const approval = options.state
418
455
  ? await ensureToolCallApproved(
@@ -421,6 +458,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
421
458
  toolMeta,
422
459
  callArgs.arguments,
423
460
  options.state.owner?.signal,
461
+ "iframe",
424
462
  )
425
463
  : options.config && isToolCallApprovalRequired(options.config, options.serverName, toolMeta)
426
464
  ? { ok: false as const, reason: "approval_required_headless" as const }
@@ -449,11 +487,15 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
449
487
  options.manager.incrementInFlight(options.serverName);
450
488
  const result = options.config
451
489
  ? await withSessionRecovery(
452
- { manager: options.manager, config: options.config, onNeedsAuth: options.onNeedsAuth },
490
+ {
491
+ manager: options.manager,
492
+ config: options.config,
493
+ ...(options.onNeedsAuth ? { onNeedsAuth: options.onNeedsAuth } : {}),
494
+ },
453
495
  options.serverName,
454
- (conn) => conn.client.callTool(callArgs, undefined, options.manager.getRequestOptions?.(options.serverName)),
496
+ (conn) => conn.client.callTool(callArgs, options.manager.getRequestOptions?.(options.serverName)),
455
497
  )
456
- : await connection.client.callTool(callArgs, undefined, options.manager.getRequestOptions?.(options.serverName));
498
+ : await connection.client.callTool(callArgs, options.manager.getRequestOptions?.(options.serverName));
457
499
  sendJson(res, 200, { ok: true, result });
458
500
  } finally {
459
501
  options.manager.decrementInFlight(options.serverName);
@@ -469,33 +511,27 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
469
511
  return;
470
512
  }
471
513
 
472
- if (url.pathname === "/proxy/ui/message") {
473
- const msgParams = params as UiMessageParams;
474
- const promptText = extractUiPromptText(msgParams);
475
-
476
- // Track messages by type (order: prompt → intent → notify)
477
- // Must match the order in index.ts onMessage handler
478
- if (promptText) {
479
- sessionMessages.prompts.push(promptText);
480
- log.debug("UI prompt received", { prompt: promptText.slice(0, 100) });
481
- } else if (msgParams.type === "intent" || msgParams.intent) {
482
- const intentName = msgParams.intent ?? "";
483
- if (intentName) {
484
- sessionMessages.intents.push({
485
- intent: intentName,
486
- params: msgParams.params
487
- });
488
- log.debug("UI intent received", { intent: intentName });
489
- }
490
- } else if (msgParams.type === "notify" || msgParams.message) {
491
- const notifyText = msgParams.message ?? "";
492
- if (notifyText) {
493
- sessionMessages.notifications.push(notifyText);
494
- log.debug("UI notification", { message: notifyText.slice(0, 100) });
495
- }
514
+ if (url.pathname === "/proxy/ui/generated-tool-call-intent") {
515
+ const tool = typeof params.tool === "string" ? params.tool : undefined;
516
+ if (tool && isAppOnlyTool(tool)) {
517
+ log.debug("Ignored generated app-only tool call intent", { tool });
518
+ } else {
519
+ await recordUiMessage({
520
+ type: "intent",
521
+ intent: "call_tool",
522
+ params: {
523
+ ...(tool !== undefined ? { tool } : {}),
524
+ ...(params.arguments !== undefined ? { arguments: params.arguments } : {}),
525
+ ...(params.isError !== undefined ? { isError: params.isError } : {}),
526
+ },
527
+ });
496
528
  }
497
-
498
- await options.onMessage?.(msgParams);
529
+ sendJson(res, 200, { ok: true, result: {} });
530
+ return;
531
+ }
532
+
533
+ if (url.pathname === "/proxy/ui/message") {
534
+ await recordUiMessage(params as UiMessageParams);
499
535
  sendJson(res, 200, { ok: true, result: {} });
500
536
  return;
501
537
  }
@@ -639,7 +675,11 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
639
675
  return;
640
676
  }
641
677
  log.error("Failed to start server", error);
642
- reject(new ServerError(error.message, { port: candidates[candidateIndex], cause: error }));
678
+ const port = candidates[candidateIndex];
679
+ reject(new ServerError(error.message, {
680
+ ...(port !== undefined ? { port } : {}),
681
+ cause: error,
682
+ }));
643
683
  };
644
684
 
645
685
  const onListening = () => {
@@ -760,21 +800,13 @@ function isAllowedHost(hostname: string): boolean {
760
800
  return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
761
801
  }
762
802
 
763
- function isLoopbackAddress(address: string | undefined): boolean {
764
- return address === "127.0.0.1" || address === "::1" || address === "::ffff:127.0.0.1";
765
- }
766
-
767
- function escapeHtml(value: string): string {
768
- return value
769
- .replace(/&/g, "&amp;")
770
- .replace(/</g, "&lt;")
771
- .replace(/>/g, "&gt;")
772
- .replace(/"/g, "&quot;")
773
- .replace(/'/g, "&#39;");
774
- }
775
-
776
- function validateTokenQuery(url: URL, expected: string, res: ServerResponse): boolean {
777
- const token = url.searchParams.get("session");
803
+ function validateTokenQuery(
804
+ url: URL,
805
+ expected: string,
806
+ res: ServerResponse,
807
+ parameter = "session",
808
+ ): boolean {
809
+ const token = url.searchParams.get(parameter);
778
810
  if (token !== expected) {
779
811
  sendJson(res, 403, { ok: false, error: "Invalid session" });
780
812
  return false;
@@ -1,7 +1,7 @@
1
1
  import { execFile } from "node:child_process";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import net from "node:net";
4
- import { UrlElicitationRequiredError, type CallToolResult } from "@modelcontextprotocol/sdk/types.js";
4
+ import { UrlElicitationRequiredError, type CallToolResult } from "@modelcontextprotocol/client";
5
5
  import type { McpExtensionState } from "./state.ts";
6
6
  import {
7
7
  createUiModelContextUpdate,
@@ -99,8 +99,10 @@ function withStreamEnvelope(
99
99
  return result;
100
100
  }
101
101
 
102
- const structuredContent = result.structuredContent && typeof result.structuredContent === "object" && !Array.isArray(result.structuredContent)
103
- ? { ...result.structuredContent }
102
+ const structuredContent: Record<string, unknown> = result.structuredContent
103
+ && typeof result.structuredContent === "object"
104
+ && !Array.isArray(result.structuredContent)
105
+ ? { ...(result.structuredContent as Record<string, unknown>) }
104
106
  : {};
105
107
 
106
108
  const rawEnvelope = structuredContent[UI_STREAM_STRUCTURED_CONTENT_KEY];
@@ -239,10 +241,10 @@ export async function maybeStartUiSession(
239
241
  serverName: request.serverName,
240
242
  toolName: request.toolName,
241
243
  reused: true,
242
- streamId,
243
- streamToken,
244
- streamMode,
245
- requestMeta: streamToken ? { [UI_STREAM_REQUEST_META_KEY]: streamToken } : undefined,
244
+ ...(streamId !== undefined ? { streamId } : {}),
245
+ ...(streamToken !== undefined ? { streamToken } : {}),
246
+ ...(streamMode !== undefined ? { streamMode } : {}),
247
+ ...(streamToken ? { requestMeta: { [UI_STREAM_REQUEST_META_KEY]: streamToken } } : {}),
246
248
  url: existingHandle.url,
247
249
  viewer: existingHandle.viewer ?? "browser",
248
250
  windowOpen: existingHandle.windowOpen ?? true,
@@ -326,9 +328,9 @@ export async function maybeStartUiSession(
326
328
  manager: state.manager,
327
329
  config: state.config,
328
330
  state,
329
- onNeedsAuth: request.onNeedsAuth,
331
+ ...(request.onNeedsAuth ? { onNeedsAuth: request.onNeedsAuth } : {}),
330
332
  consentManager: state.consentManager,
331
- hostContext,
333
+ ...(hostContext !== undefined ? { hostContext } : {}),
332
334
 
333
335
  onMessage: (params: UiMessageParams) => {
334
336
  const prompt = extractUiPromptText(params);
@@ -410,7 +412,7 @@ export async function maybeStartUiSession(
410
412
  completedAt: new Date(),
411
413
  reason,
412
414
  messages,
413
- stream,
415
+ ...(stream !== undefined ? { stream } : {}),
414
416
  });
415
417
 
416
418
  while (state.completedUiSessions.length > MAX_COMPLETED_SESSIONS) {
@@ -527,10 +529,10 @@ export async function maybeStartUiSession(
527
529
  serverName: request.serverName,
528
530
  toolName: request.toolName,
529
531
  reused: false,
530
- streamId,
531
- streamToken,
532
- streamMode,
533
- requestMeta: streamToken ? { [UI_STREAM_REQUEST_META_KEY]: streamToken } : undefined,
532
+ ...(streamId !== undefined ? { streamId } : {}),
533
+ ...(streamToken !== undefined ? { streamToken } : {}),
534
+ ...(streamMode !== undefined ? { streamMode } : {}),
535
+ ...(streamToken ? { requestMeta: { [UI_STREAM_REQUEST_META_KEY]: streamToken } } : {}),
534
536
  url: handle.url,
535
537
  viewer,
536
538
  windowOpen,
@@ -1,11 +1,11 @@
1
1
  import { createConnection, type Socket } from "node:net";
2
- import { ReadBuffer, serializeMessage } from "@modelcontextprotocol/sdk/shared/stdio.js";
3
- import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
4
- import type { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
2
+ import { ReadBuffer, serializeMessage } from "@modelcontextprotocol/client";
3
+ import type { Transport } from "@modelcontextprotocol/client";
4
+ import type { JSONRPCMessage } from "@modelcontextprotocol/client";
5
5
 
6
6
  /** MCP JSONL transport for an explicitly configured Unix-domain socket. */
7
7
  export class UnixSocketClientTransport implements Transport {
8
- private socket?: Socket;
8
+ private socket: Socket | undefined;
9
9
  private readonly readBuffer = new ReadBuffer();
10
10
 
11
11
  onclose?: () => void;
@@ -1,21 +1,30 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { spawnSync } from "node:child_process";
3
3
  import { homedir, platform } from "node:os";
4
- import { join } from "node:path";
4
+ import { extname, isAbsolute, join } from "node:path";
5
5
  import type { McpConfig, ServerEntry } from "./types.ts";
6
6
 
7
7
  async function execOpen(pi: ExtensionAPI, target: string, browser?: string, signal?: AbortSignal) {
8
8
  const os = platform();
9
9
 
10
10
  if (os === "darwin") {
11
- return browser ? pi.exec("open", ["-a", browser, target], { signal }) : pi.exec("open", [target], { signal });
11
+ if (browser) {
12
+ // An absolute executable path (e.g. from $BROWSER) names a launcher
13
+ // binary. App bundles still go through `open -a`, which handles them.
14
+ return isAbsolute(browser) && extname(browser).toLowerCase() !== ".app"
15
+ ? pi.exec(browser, [target], signal ? { signal } : {})
16
+ : pi.exec("open", ["-a", browser, target], signal ? { signal } : {});
17
+ }
18
+ return pi.exec("open", [target], signal ? { signal } : {});
12
19
  }
13
20
  if (os === "win32") {
14
21
  return browser
15
- ? pi.exec("cmd", ["/c", "start", "", browser, target], { signal })
16
- : pi.exec("cmd", ["/c", "start", "", target], { signal });
22
+ ? pi.exec("cmd", ["/c", "start", "", browser, target], signal ? { signal } : {})
23
+ : pi.exec("cmd", ["/c", "start", "", target], signal ? { signal } : {});
17
24
  }
18
- return browser ? pi.exec(browser, [target], { signal }) : pi.exec("xdg-open", [target], { signal });
25
+ return browser
26
+ ? pi.exec(browser, [target], signal ? { signal } : {})
27
+ : pi.exec("xdg-open", [target], signal ? { signal } : {});
19
28
  }
20
29
 
21
30
  export async function openUrl(pi: ExtensionAPI, url: string, browser?: string, signal?: AbortSignal): Promise<void> {
@@ -38,12 +47,14 @@ export async function parallelLimit<T, R>(
38
47
  fn: (item: T) => Promise<R>
39
48
  ): Promise<R[]> {
40
49
  const results: R[] = [];
41
- let index = 0;
50
+ const iterator = items.entries();
42
51
 
43
52
  async function worker() {
44
- while (index < items.length) {
45
- const i = index++;
46
- results[i] = await fn(items[i]);
53
+ while (true) {
54
+ const next = iterator.next();
55
+ if (next.done) return;
56
+ const [index, item] = next.value;
57
+ results[index] = await fn(item);
47
58
  }
48
59
  }
49
60
 
@@ -106,6 +117,9 @@ const COMMAND_SECRET_TIMEOUT_MS = 10_000;
106
117
  const COMMAND_SECRET_MAX_OUTPUT_BYTES = 1024 * 1024;
107
118
 
108
119
  /** Resolve a secret value, executing only a single leading `!` command marker. */
120
+ export function resolveCommandSecret(value: string, context: string): string;
121
+ export function resolveCommandSecret(value: undefined, context: string): undefined;
122
+ export function resolveCommandSecret(value: string | undefined, context: string): string | undefined;
109
123
  export function resolveCommandSecret(value: string | undefined, context: string): string | undefined {
110
124
  if (value === undefined) return undefined;
111
125
  if (value.startsWith("!!")) return interpolateEnvVars(value.slice(1));
@@ -4,6 +4,51 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.22.0] - 2026-08-11
8
+
9
+ ### Added
10
+ - Added Bocha web search provider support. Thanks @jingyulong for PR #243.
11
+ - Added `maxInlineContentChars` to configure the direct content and stored-content slice limit, with a 200,000-character maximum. Thanks @be4zad for issue #244.
12
+
13
+ ### Fixed
14
+ - Hardened the fetched-content cache against symlink traversal and unsafe permissions, and bounded it to 128 entries and 128 MiB with oldest-entry eviction. Thanks `@HerbertGao` for issue #240 and PR #241.
15
+
16
+ ## [0.21.0] - 2026-08-10
17
+
18
+ ### Added
19
+ - Added per-tool and per-command registration gates plus image and PDF extraction gates. Thanks @jaudiger for issue #234.
20
+ - Added `summaryGenerationDeadlineMs` to configure the summary model deadline for curator and auto-summary workflows. Thanks @cataldoc for issue #237.
21
+
22
+ ### Fixed
23
+ - Store full fetched content in an external cache instead of embedding it in session JSONL entries, preventing large search-heavy sessions from ballooning on restore. Thanks Igor Samokhovets (`@samohovets`) for issue #236.
24
+ - Document `get_search_content` parameter constraints in the tool schema. Thanks `@iwangjie` for PR #233.
25
+
26
+ ## [0.20.0] - 2026-08-10
27
+
28
+ ### Added
29
+ - Added keyless DuckDuckGo HTML search as an explicit and routing provider. Thanks @lmilojevicc for issue #228.
30
+ - Added Datalab hosted PDF-to-Markdown extraction as an optional PDF provider. Thanks José Antonio Galiano Sandoval (`@jagaliano`) for PR #226.
31
+
32
+ ### Changed
33
+ - Tightened Datalab JSON response validation and Gemini Web fetch initialization internals.
34
+
35
+ ### Fixed
36
+ - Fix Gemini Web "fetch failed" (`UND_ERR_HEADERS_OVERFLOW`) when running inside a host agent whose global undici dispatcher uses HTTP/1.1 with the default 16 KiB `maxHeaderSize`: Google's `/app` page exceeds that budget. Gemini Web requests now use a dedicated undici agent with a 4 MiB header budget. Thanks José Antonio Galiano Sandoval (`@jagaliano`) for PR #230.
37
+ - Preserve collapsed `web_search` result background padding. Thanks `@SheffeyG` for PR #224.
38
+
39
+ ## [0.19.0] - 2026-08-08
40
+
41
+ ### Added
42
+ - Added Jina Search as a normal configured `web_search` provider with `jinaApiKey` / `JINA_API_KEY`, explicit/auto/routing/all-provider support, domain and recency constraints, optional inline page content, and Curator integration. Thanks Orbio Agent (`@Gabrielgvl`) for PR #214.
43
+
44
+ ### Fixed
45
+ - Added a tracked npm lockfile for reproducible contributor installs, and updated model-registry auth header typing for current Pi peer packages. Thanks `@dougEfresh` for PR #218.
46
+ - Keep manual `/websearch` curator pages in sync if the live SSE stream disconnects or misses events while searches are still running. Thanks `@Whisperfall` for issue #215.
47
+ - Updated Kagi Search and Extract requests for the current v1 API contracts. Thanks `@mattgaff` for PR #217.
48
+ - Recognize `:max` thinking suffixes when matching scoped summary models. Thanks `@justin8ty` for PR #219.
49
+ - Route local video Gemini upload, polling, and deletion requests through configured `geminiBaseUrl` / `GOOGLE_GEMINI_BASE_URL` relays. Thanks Mr. (`@Liemo99`) for PR #213.
50
+ - Classify xAI `403` spending-limit and quota-exhaustion responses as quota errors so configured search routing can fall back, while preserving ordinary `403` responses as authentication errors. Thanks `@0xmarcinz` for PR #212.
51
+
7
52
  ## [0.18.0] - 2026-08-03
8
53
 
9
54
  ### Added