@herbertgao/pi-extensions 2026.9.17 → 2026.9.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. package/README.md +31 -33
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/node_modules/@herbertgao/pi-bark/package.json +2 -2
  4. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +4 -1
  5. package/node_modules/@herbertgao/pi-cc-extensions/README.md +4 -1
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/working-message.ts +21 -6
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +15 -4
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/index.ts +43 -7
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +7 -2
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +1 -1
  11. package/node_modules/@herbertgao/pi-cc-extensions/package.json +75 -75
  12. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  13. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  14. package/node_modules/@herbertgao/resume-from/package.json +4 -2
  15. package/node_modules/@herbertgao/sol-pi/package.json +6 -6
  16. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +99 -99
  17. package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
  18. package/node_modules/@tifan/pi-handoff/package.json +1 -1
  19. package/node_modules/@tifan/pi-handoff/src/index.ts +56 -26
  20. package/node_modules/@tifan/pi-mermaid-open/package.json +1 -1
  21. package/node_modules/@tifan/pi-preferred-thinking/package.json +1 -1
  22. package/node_modules/@tifan/pi-recap/package.json +1 -1
  23. package/node_modules/@tifan/pi-rename/package.json +1 -1
  24. package/node_modules/pi-antigravity/README.md +29 -6
  25. package/node_modules/pi-antigravity/package.json +14 -9
  26. package/node_modules/pi-antigravity/src/auth/accounts.ts +327 -0
  27. package/node_modules/pi-antigravity/src/auth/index.ts +9 -0
  28. package/node_modules/pi-antigravity/src/client/client.ts +1 -1
  29. package/node_modules/pi-antigravity/src/image/image.ts +4 -4
  30. package/node_modules/pi-antigravity/src/index.ts +203 -13
  31. package/node_modules/pi-antigravity/src/search/index.ts +1 -0
  32. package/node_modules/pi-antigravity/src/search/search.ts +325 -0
  33. package/node_modules/pi-antigravity/src/stream/stream.ts +191 -14
  34. package/node_modules/pi-antigravity/src/types/enums.ts +45 -36
  35. package/node_modules/pi-antigravity/src/types/types.ts +5 -12
  36. package/node_modules/pi-antigravity/src/utils/http.ts +7 -2
  37. package/node_modules/pi-antigravity/src/utils/util.ts +31 -3
  38. package/node_modules/pi-lens/package.json +158 -158
  39. package/node_modules/pi-multi-account/package.json +2 -2
  40. package/node_modules/pi-typesafe/README.md +3 -1
  41. package/node_modules/pi-typesafe/dist/auth.d.ts +9 -5
  42. package/node_modules/pi-typesafe/dist/auth.js +7 -3
  43. package/node_modules/pi-typesafe/dist/backends.d.ts +33 -3
  44. package/node_modules/pi-typesafe/dist/backends.js +95 -1
  45. package/node_modules/pi-typesafe/dist/client.d.ts +5 -5
  46. package/node_modules/pi-typesafe/dist/client.js +12 -9
  47. package/node_modules/pi-typesafe/dist/credentials.d.ts +14 -8
  48. package/node_modules/pi-typesafe/dist/credentials.js +10 -7
  49. package/node_modules/pi-typesafe/dist/errors.d.ts +2 -2
  50. package/node_modules/pi-typesafe/dist/index.d.ts +2 -2
  51. package/node_modules/pi-typesafe/dist/index.js +1 -1
  52. package/node_modules/pi-typesafe/dist/login.d.ts +2 -2
  53. package/node_modules/pi-typesafe/dist/login.js +2 -2
  54. package/node_modules/pi-typesafe/package.json +6 -5
  55. package/node_modules/pi-web-access/CHANGELOG.md +72 -0
  56. package/node_modules/pi-web-access/README.md +34 -13
  57. package/node_modules/pi-web-access/chrome-cookies.ts +79 -25
  58. package/node_modules/pi-web-access/curator-page.ts +5 -1
  59. package/node_modules/pi-web-access/curator-server.ts +2 -0
  60. package/node_modules/pi-web-access/dist/index.js +1337 -1009
  61. package/node_modules/pi-web-access/exa.ts +20 -52
  62. package/node_modules/pi-web-access/extract.ts +41 -4
  63. package/node_modules/pi-web-access/gemini-search.ts +12 -4
  64. package/node_modules/pi-web-access/index.ts +29 -37
  65. package/node_modules/pi-web-access/openai-search.ts +35 -7
  66. package/node_modules/pi-web-access/package.json +8 -7
  67. package/node_modules/pi-web-access/page-query.ts +2 -2
  68. package/node_modules/pi-web-access/query-rewrite.ts +2 -3
  69. package/node_modules/pi-web-access/ssrf-protection.ts +27 -10
  70. package/node_modules/pi-web-access/storage.ts +48 -77
  71. package/node_modules/pi-web-access/summary-model-scope.ts +6 -77
  72. package/node_modules/pi-web-access/summary-review.ts +3 -4
  73. package/node_modules/pi-web-access/tavily.ts +67 -20
  74. package/node_modules/pi-web-access/tool-activation.ts +53 -33
  75. package/node_modules/pi-web-access/utils.ts +1 -1
  76. package/node_modules/pi-web-access/you.ts +164 -0
  77. package/node_modules/pi-web-access/zai.ts +161 -0
  78. package/node_modules/remote-pi/package.json +5 -1
  79. package/package.json +19 -31
  80. package/node_modules/pi-mcp-adapter/CHANGELOG.md +0 -1013
  81. package/node_modules/pi-mcp-adapter/LICENSE +0 -21
  82. package/node_modules/pi-mcp-adapter/OAUTH.md +0 -369
  83. package/node_modules/pi-mcp-adapter/README.md +0 -1021
  84. package/node_modules/pi-mcp-adapter/abort.ts +0 -34
  85. package/node_modules/pi-mcp-adapter/agent-dir.ts +0 -68
  86. package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +0 -416
  87. package/node_modules/pi-mcp-adapter/agent-plugin-provenance.ts +0 -36
  88. package/node_modules/pi-mcp-adapter/app-bridge.bundle.js +0 -67
  89. package/node_modules/pi-mcp-adapter/banner.png +0 -0
  90. package/node_modules/pi-mcp-adapter/bearer-command-resolver.ts +0 -193
  91. package/node_modules/pi-mcp-adapter/claude-plugin-loader.ts +0 -365
  92. package/node_modules/pi-mcp-adapter/cli.js +0 -454
  93. package/node_modules/pi-mcp-adapter/commands.ts +0 -861
  94. package/node_modules/pi-mcp-adapter/config.ts +0 -1565
  95. package/node_modules/pi-mcp-adapter/consent-manager.ts +0 -95
  96. package/node_modules/pi-mcp-adapter/direct-tool-surface.ts +0 -244
  97. package/node_modules/pi-mcp-adapter/direct-tools.ts +0 -428
  98. package/node_modules/pi-mcp-adapter/dist/abort.d.ts +0 -2
  99. package/node_modules/pi-mcp-adapter/dist/abort.js +0 -36
  100. package/node_modules/pi-mcp-adapter/dist/abort.js.map +0 -1
  101. package/node_modules/pi-mcp-adapter/dist/agent-dir.d.ts +0 -10
  102. package/node_modules/pi-mcp-adapter/dist/agent-dir.js +0 -63
  103. package/node_modules/pi-mcp-adapter/dist/agent-dir.js.map +0 -1
  104. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.d.ts +0 -8
  105. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +0 -398
  106. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +0 -1
  107. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.d.ts +0 -1
  108. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js +0 -31
  109. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js.map +0 -1
  110. package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.d.ts +0 -6
  111. package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.js +0 -194
  112. package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.js.map +0 -1
  113. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.d.ts +0 -9
  114. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js +0 -362
  115. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js.map +0 -1
  116. package/node_modules/pi-mcp-adapter/dist/config.d.ts +0 -134
  117. package/node_modules/pi-mcp-adapter/dist/config.js +0 -1361
  118. package/node_modules/pi-mcp-adapter/dist/config.js.map +0 -1
  119. package/node_modules/pi-mcp-adapter/dist/consent-manager.d.ts +0 -18
  120. package/node_modules/pi-mcp-adapter/dist/consent-manager.js +0 -88
  121. package/node_modules/pi-mcp-adapter/dist/consent-manager.js.map +0 -1
  122. package/node_modules/pi-mcp-adapter/dist/elicitation-handler.d.ts +0 -17
  123. package/node_modules/pi-mcp-adapter/dist/elicitation-handler.js +0 -316
  124. package/node_modules/pi-mcp-adapter/dist/elicitation-handler.js.map +0 -1
  125. package/node_modules/pi-mcp-adapter/dist/errors.d.ts +0 -131
  126. package/node_modules/pi-mcp-adapter/dist/errors.js +0 -278
  127. package/node_modules/pi-mcp-adapter/dist/errors.js.map +0 -1
  128. package/node_modules/pi-mcp-adapter/dist/http-ca.d.ts +0 -8
  129. package/node_modules/pi-mcp-adapter/dist/http-ca.js +0 -88
  130. package/node_modules/pi-mcp-adapter/dist/http-ca.js.map +0 -1
  131. package/node_modules/pi-mcp-adapter/dist/jev-client.d.ts +0 -14
  132. package/node_modules/pi-mcp-adapter/dist/jev-client.js +0 -367
  133. package/node_modules/pi-mcp-adapter/dist/jev-client.js.map +0 -1
  134. package/node_modules/pi-mcp-adapter/dist/jev-contracts.d.ts +0 -77
  135. package/node_modules/pi-mcp-adapter/dist/jev-contracts.js +0 -2
  136. package/node_modules/pi-mcp-adapter/dist/jev-contracts.js.map +0 -1
  137. package/node_modules/pi-mcp-adapter/dist/jev-key-store.d.ts +0 -51
  138. package/node_modules/pi-mcp-adapter/dist/jev-key-store.js +0 -205
  139. package/node_modules/pi-mcp-adapter/dist/jev-key-store.js.map +0 -1
  140. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.d.ts +0 -2
  141. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js +0 -68
  142. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js.map +0 -1
  143. package/node_modules/pi-mcp-adapter/dist/lifecycle.d.ts +0 -56
  144. package/node_modules/pi-mcp-adapter/dist/lifecycle.js +0 -410
  145. package/node_modules/pi-mcp-adapter/dist/lifecycle.js.map +0 -1
  146. package/node_modules/pi-mcp-adapter/dist/logger.d.ts +0 -51
  147. package/node_modules/pi-mcp-adapter/dist/logger.js +0 -131
  148. package/node_modules/pi-mcp-adapter/dist/logger.js.map +0 -1
  149. package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.d.ts +0 -26
  150. package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.js +0 -103
  151. package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.js.map +0 -1
  152. package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.d.ts +0 -118
  153. package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.js +0 -1097
  154. package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.js.map +0 -1
  155. package/node_modules/pi-mcp-adapter/dist/mcp-auth.d.ts +0 -170
  156. package/node_modules/pi-mcp-adapter/dist/mcp-auth.js +0 -1142
  157. package/node_modules/pi-mcp-adapter/dist/mcp-auth.js.map +0 -1
  158. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.d.ts +0 -24
  159. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js +0 -203
  160. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js.map +0 -1
  161. package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.d.ts +0 -53
  162. package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.js +0 -441
  163. package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.js.map +0 -1
  164. package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.d.ts +0 -148
  165. package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.js +0 -689
  166. package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.js.map +0 -1
  167. package/node_modules/pi-mcp-adapter/dist/mcp-probe.d.ts +0 -6
  168. package/node_modules/pi-mcp-adapter/dist/mcp-probe.js +0 -166
  169. package/node_modules/pi-mcp-adapter/dist/mcp-probe.js.map +0 -1
  170. package/node_modules/pi-mcp-adapter/dist/mcp-tasks.d.ts +0 -102
  171. package/node_modules/pi-mcp-adapter/dist/mcp-tasks.js +0 -369
  172. package/node_modules/pi-mcp-adapter/dist/mcp-tasks.js.map +0 -1
  173. package/node_modules/pi-mcp-adapter/dist/mcp-trace.d.ts +0 -95
  174. package/node_modules/pi-mcp-adapter/dist/mcp-trace.js +0 -242
  175. package/node_modules/pi-mcp-adapter/dist/mcp-trace.js.map +0 -1
  176. package/node_modules/pi-mcp-adapter/dist/metadata-cache.d.ts +0 -19
  177. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +0 -301
  178. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +0 -1
  179. package/node_modules/pi-mcp-adapter/dist/npx-resolver.d.ts +0 -6
  180. package/node_modules/pi-mcp-adapter/dist/npx-resolver.js +0 -505
  181. package/node_modules/pi-mcp-adapter/dist/npx-resolver.js.map +0 -1
  182. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.d.ts +0 -2
  183. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +0 -144
  184. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +0 -1
  185. package/node_modules/pi-mcp-adapter/dist/request-headers-command.d.ts +0 -10
  186. package/node_modules/pi-mcp-adapter/dist/request-headers-command.js +0 -312
  187. package/node_modules/pi-mcp-adapter/dist/request-headers-command.js.map +0 -1
  188. package/node_modules/pi-mcp-adapter/dist/resource-tools.d.ts +0 -1
  189. package/node_modules/pi-mcp-adapter/dist/resource-tools.js +0 -15
  190. package/node_modules/pi-mcp-adapter/dist/resource-tools.js.map +0 -1
  191. package/node_modules/pi-mcp-adapter/dist/runtime-owner.d.ts +0 -13
  192. package/node_modules/pi-mcp-adapter/dist/runtime-owner.js +0 -97
  193. package/node_modules/pi-mcp-adapter/dist/runtime-owner.js.map +0 -1
  194. package/node_modules/pi-mcp-adapter/dist/sampling-handler.d.ts +0 -17
  195. package/node_modules/pi-mcp-adapter/dist/sampling-handler.js +0 -203
  196. package/node_modules/pi-mcp-adapter/dist/sampling-handler.js.map +0 -1
  197. package/node_modules/pi-mcp-adapter/dist/secure-keyring.d.ts +0 -11
  198. package/node_modules/pi-mcp-adapter/dist/secure-keyring.js +0 -172
  199. package/node_modules/pi-mcp-adapter/dist/secure-keyring.js.map +0 -1
  200. package/node_modules/pi-mcp-adapter/dist/server-manager.d.ts +0 -157
  201. package/node_modules/pi-mcp-adapter/dist/server-manager.js +0 -1745
  202. package/node_modules/pi-mcp-adapter/dist/server-manager.js.map +0 -1
  203. package/node_modules/pi-mcp-adapter/dist/session-approvals.d.ts +0 -34
  204. package/node_modules/pi-mcp-adapter/dist/session-approvals.js +0 -140
  205. package/node_modules/pi-mcp-adapter/dist/session-approvals.js.map +0 -1
  206. package/node_modules/pi-mcp-adapter/dist/session-recovery.d.ts +0 -26
  207. package/node_modules/pi-mcp-adapter/dist/session-recovery.js +0 -142
  208. package/node_modules/pi-mcp-adapter/dist/session-recovery.js.map +0 -1
  209. package/node_modules/pi-mcp-adapter/dist/state.d.ts +0 -73
  210. package/node_modules/pi-mcp-adapter/dist/state.js +0 -2
  211. package/node_modules/pi-mcp-adapter/dist/state.js.map +0 -1
  212. package/node_modules/pi-mcp-adapter/dist/types.d.ts +0 -642
  213. package/node_modules/pi-mcp-adapter/dist/types.js +0 -331
  214. package/node_modules/pi-mcp-adapter/dist/types.js.map +0 -1
  215. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.d.ts +0 -6
  216. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js +0 -37
  217. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js.map +0 -1
  218. package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.d.ts +0 -17
  219. package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.js +0 -219
  220. package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.js.map +0 -1
  221. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.d.ts +0 -104
  222. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js +0 -59
  223. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js.map +0 -1
  224. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.d.ts +0 -4
  225. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js +0 -27
  226. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js.map +0 -1
  227. package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.d.ts +0 -15
  228. package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.js +0 -85
  229. package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.js.map +0 -1
  230. package/node_modules/pi-mcp-adapter/dist/utils.d.ts +0 -41
  231. package/node_modules/pi-mcp-adapter/dist/utils.js +0 -417
  232. package/node_modules/pi-mcp-adapter/dist/utils.js.map +0 -1
  233. package/node_modules/pi-mcp-adapter/elicitation-handler.ts +0 -358
  234. package/node_modules/pi-mcp-adapter/error-signal.ts +0 -32
  235. package/node_modules/pi-mcp-adapter/errors.ts +0 -364
  236. package/node_modules/pi-mcp-adapter/examples/jev-accessibility-loop.mjs +0 -85
  237. package/node_modules/pi-mcp-adapter/examples/jev-semantic-filter.mjs +0 -34
  238. package/node_modules/pi-mcp-adapter/failure-backoff.ts +0 -23
  239. package/node_modules/pi-mcp-adapter/glimpse-ui.ts +0 -80
  240. package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -515
  241. package/node_modules/pi-mcp-adapter/http-ca.ts +0 -84
  242. package/node_modules/pi-mcp-adapter/index.ts +0 -2106
  243. package/node_modules/pi-mcp-adapter/init.ts +0 -721
  244. package/node_modules/pi-mcp-adapter/jev-client.ts +0 -300
  245. package/node_modules/pi-mcp-adapter/jev-contracts.ts +0 -53
  246. package/node_modules/pi-mcp-adapter/jev-key-store.ts +0 -192
  247. package/node_modules/pi-mcp-adapter/json-schema-validator.ts +0 -83
  248. package/node_modules/pi-mcp-adapter/lazy-loader.ts +0 -7
  249. package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -457
  250. package/node_modules/pi-mcp-adapter/logger.ts +0 -169
  251. package/node_modules/pi-mcp-adapter/mcp-auth-fetch.ts +0 -113
  252. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +0 -1296
  253. package/node_modules/pi-mcp-adapter/mcp-auth.ts +0 -1287
  254. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +0 -250
  255. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +0 -534
  256. package/node_modules/pi-mcp-adapter/mcp-code.ts +0 -495
  257. package/node_modules/pi-mcp-adapter/mcp-install.ts +0 -60
  258. package/node_modules/pi-mcp-adapter/mcp-keyring-helper.cjs +0 -89
  259. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +0 -819
  260. package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +0 -511
  261. package/node_modules/pi-mcp-adapter/mcp-panel-theme.ts +0 -104
  262. package/node_modules/pi-mcp-adapter/mcp-panel.ts +0 -1099
  263. package/node_modules/pi-mcp-adapter/mcp-probe.ts +0 -201
  264. package/node_modules/pi-mcp-adapter/mcp-references.ts +0 -373
  265. package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +0 -137
  266. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +0 -747
  267. package/node_modules/pi-mcp-adapter/mcp-status.ts +0 -105
  268. package/node_modules/pi-mcp-adapter/mcp-tasks.ts +0 -467
  269. package/node_modules/pi-mcp-adapter/mcp-trace.ts +0 -306
  270. package/node_modules/pi-mcp-adapter/metadata-cache.ts +0 -362
  271. package/node_modules/pi-mcp-adapter/namespace-tools.ts +0 -334
  272. package/node_modules/pi-mcp-adapter/npx-resolver.ts +0 -543
  273. package/node_modules/pi-mcp-adapter/oauth-handler.ts +0 -30
  274. package/node_modules/pi-mcp-adapter/oauth.ts +0 -52
  275. package/node_modules/pi-mcp-adapter/onboarding-state.ts +0 -76
  276. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +0 -156
  277. package/node_modules/pi-mcp-adapter/package.json +0 -219
  278. package/node_modules/pi-mcp-adapter/panel-keys.ts +0 -53
  279. package/node_modules/pi-mcp-adapter/prompts.ts +0 -385
  280. package/node_modules/pi-mcp-adapter/proxy-modes.ts +0 -1735
  281. package/node_modules/pi-mcp-adapter/request-headers-command.ts +0 -333
  282. package/node_modules/pi-mcp-adapter/resource-tools.ts +0 -17
  283. package/node_modules/pi-mcp-adapter/runtime-owner.ts +0 -106
  284. package/node_modules/pi-mcp-adapter/sampling-handler.ts +0 -261
  285. package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +0 -144
  286. package/node_modules/pi-mcp-adapter/search-ranking.ts +0 -309
  287. package/node_modules/pi-mcp-adapter/secure-keyring.ts +0 -170
  288. package/node_modules/pi-mcp-adapter/semantic-search.ts +0 -186
  289. package/node_modules/pi-mcp-adapter/server-manager.ts +0 -2088
  290. package/node_modules/pi-mcp-adapter/session-approvals.ts +0 -201
  291. package/node_modules/pi-mcp-adapter/session-recovery.ts +0 -158
  292. package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +0 -49
  293. package/node_modules/pi-mcp-adapter/state.ts +0 -71
  294. package/node_modules/pi-mcp-adapter/tool-approval.ts +0 -205
  295. package/node_modules/pi-mcp-adapter/tool-metadata.ts +0 -302
  296. package/node_modules/pi-mcp-adapter/tool-registrar.ts +0 -255
  297. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +0 -573
  298. package/node_modules/pi-mcp-adapter/ts-shape.ts +0 -149
  299. package/node_modules/pi-mcp-adapter/types.ts +0 -1120
  300. package/node_modules/pi-mcp-adapter/ui-app-bridge-helpers.ts +0 -40
  301. package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +0 -266
  302. package/node_modules/pi-mcp-adapter/ui-server.ts +0 -993
  303. package/node_modules/pi-mcp-adapter/ui-session.ts +0 -624
  304. package/node_modules/pi-mcp-adapter/ui-stream-types.ts +0 -89
  305. package/node_modules/pi-mcp-adapter/ui-tool-visibility.ts +0 -25
  306. package/node_modules/pi-mcp-adapter/unix-socket-transport.ts +0 -85
  307. package/node_modules/pi-mcp-adapter/utils.ts +0 -464
@@ -109,7 +109,7 @@ To route automatic searches through the active Pi model, configure an ordered ro
109
109
 
110
110
  With `useCurrentModel: true`, the automatic `openai` step uses Hosted `web_search` (or standalone search when `openaiUseAlphaSearch` is enabled) when the active model is a GPT model backed by an official OpenAI Responses endpoint: `openai`/`openai-responses` on HTTPS `api.openai.com`, or `openai-codex`/`openai-codex-responses` on the official ChatGPT Codex endpoint. Third-party gateways, Azure, and other models continue to the next route entry. A tool-level `provider` or top-level `provider` remains an explicit override; `provider: "openai"` keeps the existing independent OpenAI/Codex search-model behavior.
111
111
 
112
- For sandboxed networks that provide outbound proxy transport through environment variables, set `ssrf.trustEnvProxy` to `true` to skip local DNS preflight for proxied hostnames:
112
+ For sandboxed or corporate networks where only the proxy can resolve hostnames, set `ssrf.trustEnvProxy` to `true` to skip local DNS preflight for proxied hostnames:
113
113
 
114
114
  ```json
115
115
  {
@@ -119,7 +119,7 @@ For sandboxed networks that provide outbound proxy transport through environment
119
119
  }
120
120
  ```
121
121
 
122
- This is an opt-in DNS-preflight adjustment, not proxy transport configuration. `HTTP_PROXY`, `HTTPS_PROXY`, and `ALL_PROXY` are recognized; `NO_PROXY` hosts still undergo DNS validation, and localhost or literal private IP targets remain blocked.
122
+ This is an opt-in DNS-preflight adjustment, not proxy transport configuration. It applies to requests sent through the `proxy` set in `web-search.json` (HTTP(S), `socks5h`, or `socks4a`, including a per-call `proxy` with the same value). When no `proxy` is configured, it applies to hostnames covered by `HTTP_PROXY`, `HTTPS_PROXY`, or `ALL_PROXY`, for sandboxes that route outbound traffic through those variables themselves; the extension does not route requests through environment proxies. A per-call `proxy` that differs from the configured one still gets local DNS validation. `NO_PROXY` hosts still undergo DNS validation, and localhost or literal private IP targets remain blocked.
123
123
 
124
124
  Optional dependencies for video frame extraction:
125
125
 
@@ -163,7 +163,7 @@ fetch_content({ url: "/path/to/recording.mp4", prompt: "What error appears on sc
163
163
 
164
164
  ### web_search
165
165
 
166
- Search the web via OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, AnySearch, XCrawl, Valyu, xAI, Mistral, Bright Data SERP, SerpBase, SerpApi, Serper, Serply, self-hosted SearXNG, keyless DuckDuckGo, Exa, Perplexity AI, Gemini, or Kimi. The default `none` workflow makes no summary-generation model call and opens no curator/browser: it returns bounded raw results, identifies the provider used for each query, and stores the full results for retrieval by responseId. The selected search provider may itself be model-backed.
166
+ Search the web via OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, AnySearch, XCrawl, Valyu, xAI, Mistral, Bright Data SERP, SerpBase, SerpApi, Serper, Serply, You.com, self-hosted SearXNG, keyless DuckDuckGo, Exa, Perplexity AI, Gemini, or Kimi. The default `none` workflow makes no summary-generation model call and opens no curator/browser: it returns bounded raw results, identifies the provider used for each query, and stores the full results for retrieval by responseId. The selected search provider may itself be model-backed.
167
167
 
168
168
  ```typescript
169
169
  web_search({ query: "rust async programming" })
@@ -186,7 +186,7 @@ web_search({ queries: ["query 1", "query 2"], workflow: "auto-summary" })
186
186
  | `numResults` | Results per query (default: 5, max: 20) |
187
187
  | `recencyFilter` | `day`, `week`, `month`, or `year` |
188
188
  | `domainFilter` | Limit to domains (prefix with `-` to exclude) |
189
- | `provider` | Configured provider when omitted or set to `auto`; `all` searches every eligible provider except Parallel MCP, DuckDuckGo, Kimi, AnySearch, XCrawl, Valyu, xAI, Mistral, Bright Data, SerpBase, SerpApi, Serper, Serply, and Baizhi simultaneously; otherwise `openai`, `brave`, `parallel`, `parallel-mcp`, `tinyfish`, `search1api`, `searchinfinity`, `querit`, `tavily`, `firecrawl`, `jina`, `serpdive`, `kagi`, `bocha`, `ollama`, `anysearch`, `xcrawl`, `valyu`, `xai`, `mistral`, `brightdata`, `serpbase`, `serpapi`, `serper`, `serply`, `baizhi`, `searxng`, `duckduckgo`, `exa`, `perplexity`, `gemini`, or `kimi` (auto-selects when no provider or routing is configured; Parallel MCP, DuckDuckGo, Kimi, AnySearch, XCrawl, Valyu, xAI, Mistral, Bright Data, SerpBase, SerpApi, Serper, Serply, and Baizhi are explicit-only) |
189
+ | `provider` | Configured provider when omitted or set to `auto`; `all` searches every eligible provider except Parallel MCP, DuckDuckGo, Kimi, AnySearch, XCrawl, Valyu, xAI, Mistral, Bright Data, SerpBase, SerpApi, Serper, Serply, You.com, Baizhi, and Z.ai simultaneously; otherwise `openai`, `brave`, `parallel`, `parallel-mcp`, `tinyfish`, `search1api`, `searchinfinity`, `querit`, `tavily`, `you`, `firecrawl`, `jina`, `serpdive`, `kagi`, `bocha`, `ollama`, `anysearch`, `xcrawl`, `valyu`, `xai`, `mistral`, `brightdata`, `serpbase`, `serpapi`, `serper`, `serply`, `baizhi`, `zai`, `searxng`, `duckduckgo`, `exa`, `perplexity`, `gemini`, or `kimi` (auto-selects when no provider or routing is configured; Parallel MCP, DuckDuckGo, Kimi, AnySearch, XCrawl, Valyu, xAI, Mistral, Bright Data, SerpBase, SerpApi, Serper, Serply, You.com, Baizhi, and Z.ai are explicit-only) |
190
190
  | `includeContent` | Fetch full page content from sources in background |
191
191
  | `workflow` | `none` (skip curator; fresh-install default), `summary-review` (open curator and auto-generate a summary draft), or `auto-summary` (generate a summary without opening the curator) |
192
192
 
@@ -226,7 +226,7 @@ Thanks to [@linuxtextadventurer](https://github.com/linuxtextadventurer) for PR
226
226
 
227
227
  ### get_search_content
228
228
 
229
- Retrieve stored content from previous searches or fetches. Search provider answers and every result remain available in full and can be paged with `offset` and `limit` or searched with `findText`. Fetched URL content is stored in full in a private `web-search-cache` directory under the Pi config directory, not in the session JSONL. This includes `fetch_content` answer mode, which stores the original page content. The cache has a one-hour lifetime and fixed limits of 128 entries and 128 MiB; when either limit is reached, the oldest entries are removed first. On macOS and Linux the cache directory and files are kept at permissions `0700` and `0600`, respectively. Use `findText` to locate bounded matching passages without paging through a large page, or use `offset` and `limit` to retrieve slices intentionally.
229
+ Retrieve stored content from previous searches or fetches. Search provider answers and every result remain available in full and can be paged with `offset` and `limit` or searched with `findText`. Fetched URL content is stored in full in a private `web-search-cache` directory under the Pi config directory, not in the session JSONL. This includes `fetch_content` answer mode, which stores the original page content. The cache has a one-hour lifetime and fixed limits of 128 entries and 128 MiB; when either limit is reached, the oldest entries are removed first. Concurrent Pi processes share this cache and its limits. To give a process its own cache without moving `web-search.json`, set `PI_WEB_ACCESS_CACHE_ROOT` to a directory; the cache then lives in `web-search-cache` inside it, and a session resumed without the same value cannot read content cached there. On macOS and Linux the cache directory and files are kept at permissions `0700` and `0600`, respectively. Use `findText` to locate bounded matching passages without paging through a large page, or use `offset` and `limit` to retrieve slices intentionally.
230
230
 
231
231
  ```typescript
232
232
  get_search_content({ responseId: "abc123", urlIndex: 0 })
@@ -433,6 +433,7 @@ Config defaults to `~/.pi/agent/web-search.json` when neither `PI_CODING_AGENT_D
433
433
  "search1apiApiKey": "...",
434
434
  "tavilyApiKey": "tvly-...",
435
435
  "tavilyBaseUrl": "https://gateway.example.com/tavily",
436
+ "youApiKey": "your-ydc-api-key",
436
437
  "jinaApiKey": "$JINA_API_KEY",
437
438
  "serpdiveApiKey": "sd_live_...",
438
439
  "serpdiveModel": "krill",
@@ -444,6 +445,7 @@ Config defaults to `~/.pi/agent/web-search.json` when neither `PI_CODING_AGENT_D
444
445
  "serperApiKey": "$SERPER_API_KEY",
445
446
  "serplyApiKey": "$SERPLY_API_KEY",
446
447
  "baizhiApiKey": "$BAIZHI_API_KEY",
448
+ "zaiApiKey": "$ZAI_API_KEY",
447
449
  "brightdataApiKey": "$BRIGHTDATA_API_KEY",
448
450
  "brightdataSerpZone": "pi_serp",
449
451
  "xaiApiKey": "xai-...",
@@ -497,6 +499,7 @@ Config defaults to `~/.pi/agent/web-search.json` when neither `PI_CODING_AGENT_D
497
499
  "fetchContent": { "enabled": true },
498
500
  "getSearchContent": { "enabled": true }
499
501
  },
502
+ "toolActivation": "auto",
500
503
  "commands": {
501
504
  "websearch": { "enabled": true },
502
505
  "curator": { "enabled": true },
@@ -568,7 +571,7 @@ Config defaults to `~/.pi/agent/web-search.json` when neither `PI_CODING_AGENT_D
568
571
 
569
572
  `summaryModel` accepts an optional thinking-level suffix, such as `anthropic/claude-haiku-4-5:low`. Supported suffixes are `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`.
570
573
 
571
- All provider API-key fields (`openaiApiKey`, `braveApiKey`, `parallelApiKey`, `tinyfishApiKey`, `search1apiApiKey`, `searchinfinityApiKey`, `queritApiKey`, `tavilyApiKey`, `jinaApiKey`, `serpdiveApiKey`, `kagiApiKey`, `bochaApiKey`, `ollamaApiKey`, `valyuApiKey`, `serpbaseApiKey`, `serpapiApiKey`, `serperApiKey`, `serplyApiKey`, `baizhiApiKey`, `anysearchApiKey`, `xcrawlApiKey`, `xaiApiKey`, `mistralApiKey`, `brightdataApiKey`, `firecrawlApiKey`, `crawl4aiApiToken`, `exaApiKey`, `perplexityApiKey`, `geminiApiKey`, `datalabApiKey`, and `cloudflareApiKey`) accept explicit credential sources. Use `$NAME` or `${NAME}` to read one named environment variable, or prefix a trusted local shell command with `!` to resolve one value at provider request time. Escape `$$` as a literal leading `$` and `$!` as a literal leading `!`:
574
+ All provider API-key fields (`openaiApiKey`, `braveApiKey`, `parallelApiKey`, `tinyfishApiKey`, `search1apiApiKey`, `searchinfinityApiKey`, `queritApiKey`, `tavilyApiKey`, `youApiKey`, `jinaApiKey`, `serpdiveApiKey`, `kagiApiKey`, `bochaApiKey`, `ollamaApiKey`, `valyuApiKey`, `serpbaseApiKey`, `serpapiApiKey`, `serperApiKey`, `serplyApiKey`, `baizhiApiKey`, `zaiApiKey`, `anysearchApiKey`, `xcrawlApiKey`, `xaiApiKey`, `mistralApiKey`, `brightdataApiKey`, `firecrawlApiKey`, `crawl4aiApiToken`, `exaApiKey`, `perplexityApiKey`, `geminiApiKey`, `datalabApiKey`, and `cloudflareApiKey`) accept explicit credential sources. Use `$NAME` or `${NAME}` to read one named environment variable, or prefix a trusted local shell command with `!` to resolve one value at provider request time. Escape `$$` as a literal leading `$` and `$!` as a literal leading `!`:
572
575
 
573
576
  ```json
574
577
  {
@@ -579,13 +582,13 @@ All provider API-key fields (`openaiApiKey`, `braveApiKey`, `parallelApiKey`, `t
579
582
  }
580
583
  ```
581
584
 
582
- This syntax applies to provider credentials only; other configuration fields are not interpolated. `firecrawlApiKey`, `crawl4aiApiToken`, `kagiApiKey`, `ollamaApiKey`, `valyuApiKey`, `serpbaseApiKey`, `serpapiApiKey`, `serperApiKey`, `serplyApiKey`, `baizhiApiKey`, `mistralApiKey`, and `brightdataApiKey` use the same credential-source rules, while `braveBaseUrl`, `exaBaseUrl`, `tavilyBaseUrl`, `firecrawlBaseUrl`, `firecrawlApiVersion`, `firecrawlFreshScrape`, `crawl4aiBaseUrl`, `brightdataSerpZone`, and `brightdataUnlockerZone` are literal config values.
585
+ This syntax applies to provider credentials only; other configuration fields are not interpolated. `firecrawlApiKey`, `crawl4aiApiToken`, `kagiApiKey`, `ollamaApiKey`, `valyuApiKey`, `serpbaseApiKey`, `serpapiApiKey`, `serperApiKey`, `serplyApiKey`, `baizhiApiKey`, `zaiApiKey`, `mistralApiKey`, and `brightdataApiKey` use the same credential-source rules, while `braveBaseUrl`, `exaBaseUrl`, `tavilyBaseUrl`, `firecrawlBaseUrl`, `firecrawlApiVersion`, `firecrawlFreshScrape`, `crawl4aiBaseUrl`, `brightdataSerpZone`, `brightdataUnlockerZone`, and `zaiEndpoint` are literal config values.
583
586
 
584
587
  A command source is not run while the extension loads or registers tools. Each selected provider request runs it again with a five-second timeout, a 16 KiB output limit, a minimized environment, and a one-line non-empty stdout requirement. Command text and stderr are omitted from errors. These commands are trusted local configuration, not a same-user process isolation boundary; use absolute executable paths and protect the config file. `OP_SESSION_*` and `OP_SERVICE_ACCOUNT_TOKEN`, when present in Pi's environment, are forwarded to trusted resolver commands so 1Password CLI sessions and service accounts can be reused without storing their credentials in config. For example, `"braveApiKey": "!/absolute/path/to/op read 'op://Automation/Brave/credential'"` resolves that item after you replace the executable placeholder with your trusted installation's absolute path, but the `op://` argument is not an authorization boundary: every configured resolver command that receives the token can exercise all vault and item permissions granted to its service account. Prefer a narrowly scoped service account. An explicit source overrides legacy provider environment variables and fails that provider locally rather than falling back with a stale credential. Direct Google Gemini API requests send the resolved key only in the `x-goog-api-key` header, never in the URL.
585
588
 
586
589
  `mistralSearchModel` defaults to `mistral-small-latest` and must be a non-empty string. `mistralSearchTool` defaults to `web_search` and accepts only `web_search` or the opt-in `web_search_premium` tool.
587
590
 
588
- Set `braveBaseUrl`, `exaBaseUrl`, or `tavilyBaseUrl` to route those providers through a compatible HTTPS API gateway. `BRAVE_BASE_URL`, `EXA_BASE_URL`, and `TAVILY_BASE_URL` are the environment-variable equivalents and take precedence over config. Brave appends `/web/search`, Exa appends `/answer` or `/search`, and Tavily appends `/search`. Defaults remain the providers' official API roots. `exaBaseUrl` applies only to keyed direct API calls; zero-config Exa MCP search continues to use Exa's hosted MCP endpoint. Invalid overrides fail before a request is sent instead of falling back to an official endpoint, and credential headers are removed if a gateway redirects to another origin.
591
+ Set `braveBaseUrl`, `exaBaseUrl`, or `tavilyBaseUrl` to route those providers through a compatible HTTPS API gateway. `BRAVE_BASE_URL`, `EXA_BASE_URL`, and `TAVILY_BASE_URL` are the environment-variable equivalents and take precedence over config. Brave appends `/web/search`; Exa and Tavily append `/search`. Defaults remain the providers' official API roots. `exaBaseUrl` applies only to keyed direct API calls; zero-config Exa MCP search continues to use Exa's hosted MCP endpoint. Invalid overrides fail before a request is sent instead of falling back to an official endpoint, and credential headers are removed if a gateway redirects to another origin.
589
592
 
590
593
  `authFetch` configures named local browser-cookie auth profiles for explicit `fetch_content` calls. A profile can be a host array (`"work": ["docs.company.com"]`) or an object with `hosts`, optional `chromeProfile`, `redirects: "same-origin"`, and `cache: "session" | "off"`.
591
594
 
@@ -625,17 +628,23 @@ Bright Data Web Unlocker is a paid `fetch_content` fallback after Parallel and b
625
628
 
626
629
  **Serper.** Set `serperApiKey` or `SERPER_API_KEY` and select `provider: "serper"` to query Serper's Google Search API. Serper is explicit-only: it is never chosen by `auto` or `provider: "all"`, but it can be configured as the named provider or added to `searchRouting`.
627
630
 
631
+ **Tavily key pool.** Set `TAVILY_API_KEY_1` through `TAVILY_API_KEY_20` to try another key when Tavily returns HTTP 401, 402, 403, 429, or 432. `TAVILY_API_KEY_INDEX` picks the first slot to try (default `1`). Search tries each distinct numbered key once, wrapping around, then tries `tavilyApiKey` / `TAVILY_API_KEY`. Explicit `$VAR` and `!command` sources still fail closed. All attempts share the 60-second search deadline.
632
+
628
633
  **Baizhi.** Set `BAIZHI_API_KEY` (or `baizhiApiKey: "$BAIZHI_API_KEY"` in `web-search.json`) and explicitly select `provider: "baizhi"` to call [Baizhi Cloud Agent Toolkit](https://baizhi.cloud/landing/agent-toolkit)'s `websearch_search` over Streamable HTTP MCP. It is excluded from automatic selection and `all`; you may explicitly configure it as the default or in `searchRouting`. The client initializes an MCP session, sends your own key only in the Bearer header, and closes the session after each search. Requests and response bodies share a 60-second deadline and respect cancellation. Redirects are rejected. Queries and filters are sent to the hosted commercial service, and calls may consume credits; review your account permissions and balance. Domain include/exclude filters map to the tool's `filter` object; recency maps to `time_range`, which defaults to `month`. Generated summaries are disabled.
629
634
 
630
635
  The Baizhi input contract is based on the [published September 16 discovery snapshot](https://github.com/ct-jaryn/baizhi-agent-toolkit/blob/b774c117369b8da2a1e42c7d01bf9535bb9a41c6/tests/fixtures/tools-history-2026-09-16.json); it has no output schema. This first version preserves MCP text and structured content as the provider answer rather than guessing result item fields. Consequently it does not populate source cards or fetch pages with `includeContent`. Tests use a synthetic MCP backend; live service results and billing have not been validated. This integration does not imply the hosted backend is open source.
631
636
 
637
+ **Z.ai.** Set `ZAI_API_KEY` (or `zaiApiKey: "$ZAI_API_KEY"` in `web-search.json`) to a GLM Coding Plan key and explicitly select `provider: "zai"` to call the plan's [Web Search MCP server](https://docs.z.ai/devpack/mcp/search-mcp-server) (`webSearchPrime`). Searches count against your Coding Plan quota rather than per-call API billing. Keys are issued per site: the default `zaiEndpoint: "global"` uses `api.z.ai`, and `zaiEndpoint: "china"` uses `open.bigmodel.cn` for keys from bigmodel.cn. No other endpoint can be configured, redirects are rejected, and the key is sent only in the Bearer header. Z.ai is excluded from automatic selection and `all`; you may configure it as the default or in `searchRouting`. Recency maps to `search_recency_filter`; `domainFilter` accepts one included domain, because the tool takes a single `search_domain_filter` and has no exclusions. The tool has no result count, so results are trimmed to `numResults`. Z.ai does not publish the tool's input or output schema; the mapping follows established MCP clients, and tests use a synthetic MCP backend.
638
+
632
639
  **Serply.** Set `serplyApiKey` or `SERPLY_API_KEY` and select `provider: "serply"` to query [Serply](https://serply.io)'s Google Search API. Serply is explicit-only: it is never chosen by `auto` or `provider: "all"`, but it can be configured as the named provider or added to `searchRouting`. The key is sent in the `X-Api-Key` request header. Domain filters are sent as Google `site:` clauses and reapplied locally; recency maps to Google's `tbs` time filter. Each request consumes Serply search credits; see the [API documentation](https://serply.io/docs).
633
640
 
641
+ **You.com.** Set `youApiKey` or `YDC_API_KEY` and select `provider: "you"` to query the [You.com Web Search API](https://you.com/docs/guides/search). You.com is explicit-only: it is never chosen by `auto` or `provider: "all"`, but it can be configured as the named provider or added to `searchRouting`. The key is sent in the `X-API-Key` request header. Domain filters map to `include_domains` and `exclude_domains`, and recency maps to `freshness`. Each request consumes You.com API credits.
642
+
634
643
  **Parallel MCP.** Select `provider: "parallel-mcp"` to use Parallel Search MCP without an API key, or add it to `searchRouting`. It is explicit-only and is never chosen by `auto` or `provider: "all"`; the existing `parallel` provider remains the key-required REST API. A configured `parallelApiKey` or `PARALLEL_API_KEY` is sent as an optional Bearer token for higher MCP limits. To use MCP `web_fetch`, add `parallel-mcp` to `fetchRouting.providers` and set `fetchRouting.allowRemoteHostedProviders` to `true`; it is not part of the default fetch route.
635
644
 
636
- Without an explicit `$` or `!` source, `OPENAI_API_KEY`, `BRAVE_API_KEY`, `PARALLEL_API_KEY`, `TINYFISH_API_KEY`, `SEARCH1API_KEY`, `SEARCHINFINITY_API_KEY`, `QUERIT_API_KEY`, `TAVILY_API_KEY`, `JINA_API_KEY`, `SERPDIVE_API_KEY`, `KAGI_API_KEY`, `BOCHA_API_KEY`, `OLLAMA_API_KEY`, `SERPBASE_API_KEY`, `SERPAPI_KEY`, `SERPER_API_KEY`, `SERPLY_API_KEY`, `BAIZHI_API_KEY`, `ANYSEARCH_API_KEY`, `XCRAWL_API_KEY`, `VALYU_API_KEY`, `XAI_API_KEY`, `MISTRAL_API_KEY`, `BRIGHTDATA_API_KEY`, `FIRECRAWL_API_KEY`, `CRAWL4AI_API_TOKEN`, `EXA_API_KEY`, `GEMINI_API_KEY`, `DATALAB_API_KEY`, `DATALAB_PROCESSING_LOCATION`, `DATALAB_MODE`, `DATALAB_API_BASE`, `PERPLEXITY_API_KEY`, `GOOGLE_GEMINI_BASE_URL`, and `CLOUDFLARE_API_KEY` env vars retain their existing precedence over literal config file values. `openaiResponsesUrl` can point OpenAI `web_search` and `source_check` at a third-party gateway that supports the OpenAI Responses API and web search tool; it is an explicit endpoint override, not derived from Pi model provider settings, and defaults to `https://api.openai.com/v1/responses`. `openaiSearchModel` pins the model id used for OpenAI `web_search`, bypassing automatic selection (newest terra-tier model); the id is sent verbatim with whichever OpenAI auth resolves, so gateway-only model ids work too. `xaiSearchModel` similarly pins the xAI search model. `openaiSearchProviders` sets which Pi model providers OpenAI `web_search` resolves login credentials from, in priority order; it defaults to `["openai-codex", "openai"]`, entries that are not registered or not signed in are skipped, and an empty array skips Pi credentials entirely so the `openaiApiKey` / `OPENAI_API_KEY` fallback applies. Useful for choosing between multiple Codex accounts (for example a second account registered by an extension) or forcing API-key billing while signed into Codex. Configured Exa API keys use Exa's own account limits directly; any legacy local `exa-usage.json` file is ignored. `GOOGLE_GEMINI_BASE_URL` overrides the Gemini API host for Gemini generate-content calls such as search, URL context, YouTube, and local video analysis. Set it to a bare host with no trailing slash and no version segment, for example `https://my-gateway.example.com/gemini`; `geminiBaseUrl` is the config-file equivalent. When the configured host contains `gateway.ai.cloudflare.com`, authentication uses `cf-aig-authorization: Bearer <token>` from `CLOUDFLARE_API_KEY` or `cloudflareApiKey`, and `GEMINI_API_KEY` is not required for generate-content calls. Alternatively, set `geminiAuth` to `"adc"` to authenticate Gemini generate-content calls with Google Application Default Credentials (ADC) instead of an API key; calls go to the Vertex AI endpoint (`aiplatform.googleapis.com`) with an OAuth bearer token minted from the ADC file (`GOOGLE_APPLICATION_CREDENTIALS` or `~/.config/gcloud/application_default_credentials.json`, i.e. `gcloud auth application-default login`). `geminiProject`/`geminiLocation` set the Vertex project and location and fall back to the `GOOGLE_CLOUD_PROJECT`/`GOOGLE_CLOUD_LOCATION` (or `GCLOUD_PROJECT`) env vars; project and location are required. ADC supports `authorized_user` (OAuth refresh token) and `service_account` (JWT assertion) credential files, and tokens are cached and refreshed from expiry. ADC mode covers search, URL context, and PDF/inline-data extraction; YouTube and local video analysis still go through the Gemini Files API, so they fall back to Gemini Web unless a `GEMINI_API_KEY` is also configured. The access token is treated as a credential and is redacted from errors. Local video file upload still uses Google's Files API directly, so gateway-only video extraction falls back to Gemini Web unless a `GEMINI_API_KEY` is also configured. `provider` or `searchProvider` sets the default search provider and is used when a tool call omits `provider` or sends `"auto"`: `"all"`, `"openai"`, `"brave"`, `"parallel"`, `"parallel-mcp"`, `"tinyfish"`, `"search1api"`, `"searchinfinity"`, `"querit"`, `"tavily"`, `"firecrawl"`, `"jina"`, `"serpdive"`, `"kagi"`, `"bocha"`, `"ollama"`, `"anysearch"`, `"xcrawl"`, `"valyu"`, `"xai"`, `"mistral"`, `"brightdata"`, `"serpbase"`, `"serpapi"`, `"serper"`, `"serply"`, `"baizhi"`, `"searxng"`, `"exa"`, `"perplexity"`, or `"gemini"`. Parallel MCP, AnySearch, XCrawl, Valyu, xAI, Mistral, Bright Data, SerpBase, SerpApi, Serper, Serply, and Baizhi are never selected by `auto`; choose them explicitly or place them in `searchRouting`. If either single-provider field is configured, it takes precedence over `searchRouting`. Otherwise, `searchRouting` can opt into an ordered `providers` list and an explicit `fallbackOn` list containing `"transient"`, `"quota"`, `"network"`, and/or `"invalid-response"`; only those typed failures continue to the next available candidate. `"all"` is not valid inside `searchRouting.providers`, because that list defines sequential fallback rather than multi-provider aggregation. Named providers remain strict, and exhausted routes return per-provider diagnostics. `provider` can also be a non-empty array of named providers such as `["brave", "exa"]`; those providers run concurrently using the same aggregation path as `"all"`, while `"auto"` and `"all"` are invalid inside arrays. Random, weighted, sticky, and cooldown routing are not enabled. This is also updated automatically when you change the provider in the curator UI. Set `webSearch.enabled` to `false` to unregister the configured search and source-check tools while leaving fetch/content tools available. `toolNames` can opt into alternate public tool names for environments where another extension or model reserves the defaults, without changing behavior: `webSearch`, `sourceCheck`, `fetchContent`, and `getSearchContent` default to `web_search`, `source_check`, `fetch_content`, and `get_search_content`. `workflow` sets the default search workflow: `"none"` (default; raw results, no curator), `"summary-review"` (opens curator with an auto-generated summary draft), or `"auto-summary"` (returns a model-generated summary without opening the browser curator). Overridden per-call via the `workflow` parameter on the configured search tool, or toggled at runtime with `/curator`. `browserCookies.profile` pins Gemini Web cookie lookup to a specific Chromium profile. When omitted, detected Chromium profiles are scanned in stable order and the first profile containing the required Gemini cookies is used. macOS discovery supports Helium, Chrome, Brave, and Arc; Linux discovery supports Chromium and Chrome. `allowBrowserCookies` enables Chromium cookie extraction for Gemini Web; it defaults to `false` to avoid browser data access and surprise macOS Keychain prompts. You can also set `PI_ALLOW_BROWSER_COOKIES=1`. Cookie databases are copied to a temporary read-only working copy; the reader uses `node:sqlite` when available and otherwise tries the `sqlite3` CLI or Python's standard-library SQLite module. `searchModel` overrides the Gemini API model used by the configured search tool without changing URL, YouTube, or video extraction defaults. Gemini API grounded search uses `gemini-3.6-flash` by default; set `searchModel` to choose another model. Gemini Web browser-cookie fallback uses its separate `gemini-3.1-pro` default because Gemini Web relies on private header values; explicitly configured unsupported Web models fail instead of silently falling back to 2.5 Flash. `summaryModel` sets the default model used for generating summary drafts in the curator UI and `auto-summary` mode (e.g. `"anthropic/claude-haiku-4-5"`, `"openai-codex/gpt-5.3-codex-spark"`, or `"openrouter/nvidia/nemotron-3-super-120b-a12b:free"`). Preferred summary and query-rewrite models also resolve through routed provider registrations such as OpenRouter when the native provider is unavailable. When Pi `enabledModels` is configured, summaries are limited to that allowlist; if no enabled summary model is available, the tool returns a deterministic summary instead of calling an unrelated model. `summaryGenerationDeadlineMs` sets the maximum time for one summary model attempt in the curator UI and `auto-summary` mode. It defaults to `30000`, must be a positive integer, and is capped at `600000`. `maxInlineContentChars` sets the direct `fetch_content` content slice and the default and maximum `get_search_content` slice. It defaults to `30000`, must be a positive integer, and is capped at `200000`; full fetched content remains stored for later retrieval. `curatorTimeoutSeconds` controls the initial curator idle timeout (default `20`, max `600`); users can still adjust the timer in the curator UI. `ssrf.allowRanges` lists CIDR ranges (e.g. `"198.18.0.0/15"`, `"fd00::/8"`) exempted from the SSRF guard that otherwise blocks private/reserved IP ranges. This unblocks `fetch_content`/`web_search` on hosts whose network proxy runs in TUN + fake-IP mode (Surge, Clash, Mihomo, Stash, ...), where public domains resolve into a synthetic reserved range. It is **off by default** — the guard stays fully enabled unless you list ranges here. Use the narrowest range that covers your proxy's fake-IP pool. All-address CIDRs such as `0.0.0.0/0` and `::/0` are rejected. `ssrf.trustEnvProxy` is a separate opt-in for sandboxed environments with valid HTTP(S) proxy env vars; it skips local DNS preflight only for proxied hostnames and still blocks localhost, literal private IP targets, and `NO_PROXY` matches. It does not configure proxy transport.
637
- ### Kimi Code Plan
645
+ Without an explicit `$` or `!` source, `OPENAI_API_KEY`, `BRAVE_API_KEY`, `PARALLEL_API_KEY`, `TINYFISH_API_KEY`, `SEARCH1API_KEY`, `SEARCHINFINITY_API_KEY`, `QUERIT_API_KEY`, `TAVILY_API_KEY`, `YDC_API_KEY`, `JINA_API_KEY`, `SERPDIVE_API_KEY`, `KAGI_API_KEY`, `BOCHA_API_KEY`, `OLLAMA_API_KEY`, `SERPBASE_API_KEY`, `SERPAPI_KEY`, `SERPER_API_KEY`, `SERPLY_API_KEY`, `BAIZHI_API_KEY`, `ZAI_API_KEY`, `ANYSEARCH_API_KEY`, `XCRAWL_API_KEY`, `VALYU_API_KEY`, `XAI_API_KEY`, `MISTRAL_API_KEY`, `BRIGHTDATA_API_KEY`, `FIRECRAWL_API_KEY`, `CRAWL4AI_API_TOKEN`, `EXA_API_KEY`, `GEMINI_API_KEY`, `DATALAB_API_KEY`, `DATALAB_PROCESSING_LOCATION`, `DATALAB_MODE`, `DATALAB_API_BASE`, `PERPLEXITY_API_KEY`, `GOOGLE_GEMINI_BASE_URL`, and `CLOUDFLARE_API_KEY` env vars retain their existing precedence over literal config file values. `openaiResponsesUrl` can point OpenAI `web_search` and `source_check` at a third-party gateway that supports the OpenAI Responses API and web search tool; it is an explicit endpoint override, not derived from Pi model provider settings, and defaults to `https://api.openai.com/v1/responses`. `openaiSearchModel` pins the model id used for OpenAI `web_search`, bypassing automatic selection (newest terra-tier model, then newest bare `gpt-N` or `gpt-N.N` id, then newest other `gpt-<version>` id); the id is sent verbatim with whichever OpenAI auth resolves, so gateway-only model ids work too. `xaiSearchModel` similarly pins the xAI search model. `openaiSearchProviders` sets which Pi model providers OpenAI `web_search` resolves login credentials from, in priority order; it defaults to `["openai-codex", "openai"]`, entries that are not registered or not signed in are skipped, and an empty array skips Pi credentials entirely so the `openaiApiKey` / `OPENAI_API_KEY` fallback applies. Useful for choosing between multiple Codex accounts (for example a second account registered by an extension) or forcing API-key billing while signed into Codex. Configured Exa API keys use Exa's own account limits directly; any legacy local `exa-usage.json` file is ignored. `GOOGLE_GEMINI_BASE_URL` overrides the Gemini API host for Gemini generate-content calls such as search, URL context, YouTube, and local video analysis. Set it to a bare host with no trailing slash and no version segment, for example `https://my-gateway.example.com/gemini`; `geminiBaseUrl` is the config-file equivalent. When the configured host contains `gateway.ai.cloudflare.com`, authentication uses `cf-aig-authorization: Bearer <token>` from `CLOUDFLARE_API_KEY` or `cloudflareApiKey`, and `GEMINI_API_KEY` is not required for generate-content calls. Alternatively, set `geminiAuth` to `"adc"` to authenticate Gemini generate-content calls with Google Application Default Credentials (ADC) instead of an API key; calls go to the Vertex AI endpoint (`aiplatform.googleapis.com`) with an OAuth bearer token minted from the ADC file (`GOOGLE_APPLICATION_CREDENTIALS` or `~/.config/gcloud/application_default_credentials.json`, i.e. `gcloud auth application-default login`). `geminiProject`/`geminiLocation` set the Vertex project and location and fall back to the `GOOGLE_CLOUD_PROJECT`/`GOOGLE_CLOUD_LOCATION` (or `GCLOUD_PROJECT`) env vars; project and location are required. ADC supports `authorized_user` (OAuth refresh token) and `service_account` (JWT assertion) credential files, and tokens are cached and refreshed from expiry. ADC mode covers search, URL context, and PDF/inline-data extraction; YouTube and local video analysis still go through the Gemini Files API, so they fall back to Gemini Web unless a `GEMINI_API_KEY` is also configured. The access token is treated as a credential and is redacted from errors. Local video file upload still uses Google's Files API directly, so gateway-only video extraction falls back to Gemini Web unless a `GEMINI_API_KEY` is also configured. `provider` or `searchProvider` sets the default search provider and is used when a tool call omits `provider` or sends `"auto"`: `"all"`, `"openai"`, `"brave"`, `"parallel"`, `"parallel-mcp"`, `"tinyfish"`, `"search1api"`, `"searchinfinity"`, `"querit"`, `"tavily"`, `"firecrawl"`, `"jina"`, `"serpdive"`, `"kagi"`, `"bocha"`, `"ollama"`, `"anysearch"`, `"xcrawl"`, `"valyu"`, `"xai"`, `"mistral"`, `"brightdata"`, `"serpbase"`, `"serpapi"`, `"serper"`, `"serply"`, `"you"`, `"baizhi"`, `"zai"`, `"searxng"`, `"exa"`, `"perplexity"`, or `"gemini"`. Parallel MCP, AnySearch, XCrawl, Valyu, xAI, Mistral, Bright Data, SerpBase, SerpApi, Serper, Serply, You.com, Baizhi, and Z.ai are never selected by `auto`; choose them explicitly or place them in `searchRouting`. If either single-provider field is configured, it takes precedence over `searchRouting`. Otherwise, `searchRouting` can opt into an ordered `providers` list and an explicit `fallbackOn` list containing `"transient"`, `"quota"`, `"network"`, and/or `"invalid-response"`; only those typed failures continue to the next available candidate. `"all"` is not valid inside `searchRouting.providers`, because that list defines sequential fallback rather than multi-provider aggregation. Named providers remain strict, and exhausted routes return per-provider diagnostics. `provider` can also be a non-empty array of named providers such as `["brave", "exa"]`; those providers run concurrently using the same aggregation path as `"all"`, while `"auto"` and `"all"` are invalid inside arrays. Random, weighted, sticky, and cooldown routing are not enabled. This is also updated automatically when you change the provider in the curator UI. Set `webSearch.enabled` to `false` to unregister the configured search and source-check tools while leaving fetch/content tools available. `toolNames` can opt into alternate public tool names for environments where another extension or model reserves the defaults, without changing behavior: `webSearch`, `sourceCheck`, `fetchContent`, and `getSearchContent` default to `web_search`, `source_check`, `fetch_content`, and `get_search_content`. `workflow` sets the default search workflow: `"none"` (default; raw results, no curator), `"summary-review"` (opens curator with an auto-generated summary draft), or `"auto-summary"` (returns a model-generated summary without opening the browser curator). Overridden per-call via the `workflow` parameter on the configured search tool, or toggled at runtime with `/curator`. `browserCookies.profile` pins Gemini Web cookie lookup to a specific Chromium profile. When omitted, detected Chromium profiles are scanned in stable order and the first profile containing the required Gemini cookies is used. macOS discovery supports Helium, Chrome, Brave, and Arc; Linux discovery supports Chromium and Chrome. `allowBrowserCookies` enables Chromium cookie extraction for Gemini Web; it defaults to `false` to avoid browser data access and surprise macOS Keychain prompts. You can also set `PI_ALLOW_BROWSER_COOKIES=1`. Cookie databases are copied to a temporary read-only working copy; the reader uses `node:sqlite` when available and otherwise tries the `sqlite3` CLI or Python's standard-library SQLite module. `searchModel` overrides the Gemini API model used by the configured search tool without changing URL, YouTube, or video extraction defaults. Gemini API grounded search uses `gemini-3.6-flash` by default; set `searchModel` to choose another model. Gemini Web browser-cookie fallback uses its separate `gemini-3.1-pro` default because Gemini Web relies on private header values; explicitly configured unsupported Web models fail instead of silently falling back to 2.5 Flash. `summaryModel` sets the default model used for generating summary drafts in the curator UI and `auto-summary` mode (e.g. `"anthropic/claude-haiku-4-5"`, `"openai-codex/gpt-5.3-codex-spark"`, or `"openrouter/nvidia/nemotron-3-super-120b-a12b:free"`). Preferred summary and query-rewrite models also resolve through routed provider registrations such as OpenRouter when the native provider is unavailable. When Pi `enabledModels` is configured, summaries are limited to that allowlist; if no enabled summary model is available, the tool returns a deterministic summary instead of calling an unrelated model. `summaryGenerationDeadlineMs` sets the maximum time for one summary model attempt in the curator UI and `auto-summary` mode. It defaults to `30000`, must be a positive integer, and is capped at `600000`. `maxInlineContentChars` sets the direct `fetch_content` content slice and the default and maximum `get_search_content` slice. It defaults to `30000`, must be a positive integer, and is capped at `200000`; full fetched content remains stored for later retrieval. `curatorTimeoutSeconds` controls the initial curator idle timeout (default `20`, max `600`); users can still adjust the timer in the curator UI. `ssrf.allowRanges` lists CIDR ranges (e.g. `"198.18.0.0/15"`, `"fd00::/8"`) exempted from the SSRF guard that otherwise blocks private/reserved IP ranges. This unblocks `fetch_content`/`web_search` on hosts whose network proxy runs in TUN + fake-IP mode (Surge, Clash, Mihomo, Stash, ...), where public domains resolve into a synthetic reserved range. It is **off by default** — the guard stays fully enabled unless you list ranges here. Use the narrowest range that covers your proxy's fake-IP pool. All-address CIDRs such as `0.0.0.0/0` and `::/0` are rejected. `ssrf.trustEnvProxy` is a separate opt-in for networks where only the proxy can resolve hostnames; it skips local DNS preflight only for hostnames sent through the configured `proxy` or, when none is configured, hostnames covered by valid HTTP(S) proxy env vars in sandboxes that route through them, and still blocks localhost, literal private IP targets, and `NO_PROXY` matches. It does not configure proxy transport.
638
646
 
647
+ ### Kimi Code Plan
639
648
  Run `/login kimi-coding` in Pi and complete sign-in for an active Kimi Code Plan. Then select `provider: "kimi"`, include `"kimi"` in an explicit provider array, or add it to `searchRouting.providers`. The extension resolves a model with provider `kimi-coding` from Pi's model registry and reuses Pi's refreshed OAuth credential; no Moonshot Open Platform key is configured here.
640
649
 
641
650
  Kimi search calls `POST https://api.kimi.com/coding/v1/search` with the query as `text_query`. This is the Kimi Code Plan search service, not Moonshot Open Platform `$web_search`. The endpoint exposes no native recency parameter, so `recencyFilter` is unsupported and is not sent. Shared `domainFilter` and `numResults` behavior is enforced locally on the returned `search_results`.
@@ -644,7 +653,7 @@ Kimi is explicit-only: it is never chosen by `auto` and never participates in `p
644
653
 
645
654
  ### All providers
646
655
 
647
- Set `provider: "all"` on `web_search` or `source_check`, or configure `"provider": "all"` as the default, to run the same query against every eligible search provider simultaneously. Parallel MCP, DuckDuckGo, Kimi, AnySearch, XCrawl, Valyu, xAI, Mistral, Bright Data, SerpBase, SerpApi, Serper, Serply, and Baizhi are always excluded because they are explicit-only; Bright Data, SerpBase, SerpApi, Serper, and Serply are paid Google SERP providers, while Baizhi, Kimi, and Mistral may consume account quota or paid search-tool usage, so `all` never spends either resource without an explicit request. Exa remains eligible through its zero-config MCP path, OpenAI can use Pi auth, and other API-backed search providers participate when their API key, local endpoint, or gateway makes them available. Browser-cookie access alone does not opt Gemini into `all`; select Gemini explicitly or configure its API/gateway.
656
+ Set `provider: "all"` on `web_search` or `source_check`, or configure `"provider": "all"` as the default, to run the same query against every eligible search provider simultaneously. Parallel MCP, DuckDuckGo, Kimi, AnySearch, XCrawl, Valyu, xAI, Mistral, Bright Data, SerpBase, SerpApi, Serper, Serply, You.com, Baizhi, and Z.ai are always excluded because they are explicit-only; Bright Data, SerpBase, SerpApi, Serper, Serply, and You.com are paid search APIs, while Baizhi, Z.ai, Kimi, and Mistral may consume account quota or paid search-tool usage, so `all` never spends either resource without an explicit request. Exa remains eligible through its zero-config MCP path, OpenAI can use Pi auth, and other API-backed search providers participate when their API key, local endpoint, or gateway makes them available. Browser-cookie access alone does not opt Gemini into `all`; select Gemini explicitly or configure its API/gateway.
648
657
 
649
658
  Successful provider answers are preserved separately while source URLs and inline content are deduplicated, and one provider failure does not discard the other results. If every participating provider fails, the tool returns per-provider diagnostics. Configured Firecrawl participates in `all` like other eligible providers. In the Curator, **All** can also be selected like the other provider buttons. Each participating provider gets its own result card, including a provider badge and independent selection checkbox; failed providers get their own disabled error card. The final summary is generated from the selected provider cards and is what Pi receives. Outside the Curator, the same provider answers remain available as labeled sections in one tool response.
650
659
 
@@ -985,7 +994,17 @@ When `false`, a requested Curator session never tries to open a Glimpse window o
985
994
 
986
995
  ### Tool activation
987
996
 
988
- Pi starts normal sessions with the compact `web_enable` tool. Its guidance lists only the web capabilities enabled in `web-search.json`. The model can call it without a human toggle; the configured search, source-check, fetch, and stored-content tools then appear on the immediately following model request. Disabled tools stay unregistered, and alternate `toolNames` are preserved. Warm and resumed sessions retain their recorded tool selection.
997
+ With dynamic activation, Pi starts a session with only the compact `web_enable` tool. Its guidance lists only the web capabilities enabled in `web-search.json`. The model can call it without a human toggle; the configured search, source-check, fetch, and stored-content tools then appear on the immediately following model request. Disabled tools stay unregistered, and alternate `toolNames` are preserved. Warm and resumed sessions retain their recorded tool selection, so a session recorded without `web_enable` does not gain it after an install or upgrade; start a new session to use web tools there.
998
+
999
+ Enabling the tools mid-conversation can cost a prompt-cache miss. Some models accept tools added partway through a conversation. For the others, Pi resends the whole conversation on the request after `web_enable`, which can invalidate the cached prefix for that request. Later requests can cache the updated conversation again.
1000
+
1001
+ `"toolActivation"` in `web-search.json` picks the behavior:
1002
+
1003
+ - `"auto"` (the default) uses dynamic activation when the session's model accepts added tools, according to Pi's model catalog. Otherwise every enabled web tool is available from the first request, so `web_enable` never causes that cache miss. The choice is made once, from the model selected when a new session starts; switching models later doesn't change it, and warm or resumed sessions keep their recorded tools.
1004
+ - `"dynamic"` starts every new session with `web_enable`, even on models where enabling the tools can cause a cache miss.
1005
+ - `"eager"` never uses `web_enable` and keeps every enabled web tool available from the first request. It also suits models that rarely call `web_enable` on their own.
1006
+
1007
+ Restart Pi after changing it. Dynamic activation needs Pi 0.86.0 or newer; older Pi logs a warning and keeps every enabled web tool available.
989
1008
 
990
1009
  ### Shortcuts
991
1010
 
@@ -1009,7 +1028,7 @@ Rate limits: Perplexity is capped at 10 requests/minute (client-side). Jina Sear
1009
1028
  ## Limitations
1010
1029
 
1011
1030
  - If the curator cannot open a browser automatically, such as in Docker, WSL, SSH, or headless environments, the running curator URL is shown in the tool output. Copy it into a browser that can reach the Pi host, or use a tunnel/port-forward when needed.
1012
- - Chromium cookie extraction for Gemini Web is opt-in via `allowBrowserCookies: true` or `PI_ALLOW_BROWSER_COOKIES=1`; no browser data or password store is touched while it is disabled. On macOS, enabling it may trigger a Keychain dialog. On Windows, Chrome and Edge v10 cookies use the current user's DPAPI key; v20 app-bound cookies are not supported. Required cookie names are checked before password-store access, and browser encryption passwords are cached only in-process. If `node:sqlite` is unavailable, the reader falls back to the `sqlite3` CLI or Python stdlib; `/google-account` reports sanitized browser/profile attempts and classifies SQLite, profile, missing-cookie, password-store, and decryption failures.
1031
+ - Chromium cookie extraction for Gemini Web is opt-in via `allowBrowserCookies: true` or `PI_ALLOW_BROWSER_COOKIES=1`; no browser data or password store is touched while it is disabled. On macOS, enabling it may trigger a Keychain dialog. On Linux, Chrome and Chromium check Secret Service first, then use `kwallet-query` for the standard KWallet safe-storage entry during a KDE session. On Windows, Chrome and Edge v10 cookies use the current user's DPAPI key; v20 app-bound cookies are not supported. Required cookie names are checked before password-store access, and browser encryption passwords are cached only in-process. If `node:sqlite` is unavailable, the reader falls back to the `sqlite3` CLI or Python stdlib; `/google-account` reports sanitized browser/profile attempts and classifies SQLite, profile, missing-cookie, password-store, and decryption failures.
1013
1032
  - YouTube private/age-restricted videos may fail on all extraction paths.
1014
1033
  - Gemini can process videos up to ~1 hour; longer videos may be truncated.
1015
1034
  - PDFs are text-extracted only (no OCR for scanned documents).
@@ -1034,6 +1053,7 @@ Rate limits: Perplexity is capped at 10 requests/minute (client-side). Jina Sear
1034
1053
  | `searchinfinity.ts` | Byteplus Searchinfinity search provider |
1035
1054
  | `querit.ts` | Querit Search and Contents API provider |
1036
1055
  | `tavily.ts` | Tavily Search API provider |
1056
+ | `you.ts` | You.com Search API provider |
1037
1057
  | `firecrawl.ts` | Firecrawl search provider and extraction fallback |
1038
1058
  | `crawl4ai.ts` | Self-hosted Crawl4AI extraction fallback |
1039
1059
  | `jina-search.ts` | Jina Search API provider |
@@ -1046,6 +1066,7 @@ Rate limits: Perplexity is capped at 10 requests/minute (client-side). Jina Sear
1046
1066
  | `serper.ts` | Explicit-only Serper Google SERP provider |
1047
1067
  | `serply.ts` | Explicit-only Serply Google SERP provider |
1048
1068
  | `baizhi.ts` | Explicit-only Baizhi Streamable HTTP MCP search provider |
1069
+ | `zai.ts` | Explicit-only Z.ai GLM Coding Plan MCP search provider |
1049
1070
  | `anysearch.ts` | Explicit-only AnySearch search provider |
1050
1071
  | `xcrawl.ts` | Explicit-only XCrawl search provider |
1051
1072
  | `valyu.ts` | Explicit-only Valyu research search provider |
@@ -15,8 +15,16 @@ interface BrowserConfig {
15
15
  keychainService?: string;
16
16
  keychainAccount?: string;
17
17
  secretToolApp?: string;
18
+ kwalletFolder?: string;
19
+ kwalletEntry?: string;
18
20
  }
19
21
 
22
+ type BrowserPassword = {
23
+ value: string | null;
24
+ source?: "secret-service" | "kwallet";
25
+ warning?: string;
26
+ };
27
+
20
28
  type SqliteRow = Record<string, unknown>;
21
29
  type SqliteFailure = "unavailable" | "query";
22
30
 
@@ -67,8 +75,8 @@ const MACOS_BROWSER_CONFIGS: BrowserConfig[] = [
67
75
  ];
68
76
 
69
77
  const LINUX_BROWSER_CONFIGS: BrowserConfig[] = [
70
- { id: "chromium", name: "Chromium", baseDir: ".config/chromium", secretToolApp: "chromium" },
71
- { id: "chrome", name: "Chrome", baseDir: ".config/google-chrome", secretToolApp: "chrome" },
78
+ { id: "chromium", name: "Chromium", baseDir: ".config/chromium", secretToolApp: "chromium", kwalletFolder: "Chromium Keys", kwalletEntry: "Chromium Safe Storage" },
79
+ { id: "chrome", name: "Chrome", baseDir: ".config/google-chrome", secretToolApp: "chrome", kwalletFolder: "Chrome Keys", kwalletEntry: "Chrome Safe Storage" },
72
80
  ];
73
81
 
74
82
  const WINDOWS_BROWSER_CONFIGS: BrowserConfig[] = [
@@ -76,7 +84,7 @@ const WINDOWS_BROWSER_CONFIGS: BrowserConfig[] = [
76
84
  { id: "edge", name: "Edge", baseDir: "Microsoft/Edge/User Data", usesLocalAppData: true },
77
85
  ];
78
86
 
79
- const browserPasswordCache = new Map<string, Promise<string | null>>();
87
+ const browserPasswordCache = new Map<string, Promise<BrowserPassword[]>>();
80
88
  let lastCookieDiagnostic: string | null = null;
81
89
  let lastCookieDiagnosticDetails: BrowserCookieDiagnosticDetails | null = null;
82
90
  let sqliteModule: typeof import("node:sqlite") | null = null;
@@ -194,10 +202,13 @@ export async function getBrowserCookiesForHosts(
194
202
  sawRequiredCookies = true;
195
203
  }
196
204
 
197
- const key = currentPlatform === "win32"
198
- ? await readWindowsEncryptionKey(config, home)
199
- : await readBrowserPassword(config, currentPlatform).then((password) => password ? pbkdf2Sync(password, "saltysalt", currentPlatform === "darwin" ? 1003 : 1, 16, "sha1") : null);
200
- if (!key) {
205
+ const browserPasswords = currentPlatform === "win32" ? [] : await readBrowserPasswords(config, currentPlatform);
206
+ for (const password of browserPasswords) if (password.warning) warningSet.add(password.warning);
207
+ const windowsKey = currentPlatform === "win32" ? await readWindowsEncryptionKey(config, home) : null;
208
+ const browserKeys = browserPasswords.flatMap((password) => password.value
209
+ ? [pbkdf2Sync(password.value, "saltysalt", currentPlatform === "darwin" ? 1003 : 1, 16, "sha1")]
210
+ : []);
211
+ if (currentPlatform === "win32" ? !windowsKey : browserKeys.length === 0) {
201
212
  warningSet.add(currentPlatform === "win32"
202
213
  ? `Could not read ${config.name} Windows cookie encryption key`
203
214
  : `Could not read ${config.name} cookie encryption password`);
@@ -220,6 +231,7 @@ export async function getBrowserCookiesForHosts(
220
231
  const entries: BrowserCookieEntry[] = [];
221
232
  const cookies: CookieMap = {};
222
233
  const requiredDecryptFailures = new Set<string>();
234
+ let kwalletAttempted = browserPasswords.some((password) => password.source === "kwallet");
223
235
  for (const row of rowsResult.rows) {
224
236
  const name = typeof row.name === "string" ? row.name : "";
225
237
  if (!name) continue;
@@ -227,9 +239,28 @@ export async function getBrowserCookiesForHosts(
227
239
  if (!value && typeof row.encrypted_value_hex === "string" && /^[0-9a-f]*$/i.test(row.encrypted_value_hex)) {
228
240
  const encrypted = Buffer.from(row.encrypted_value_hex, "hex");
229
241
  if (currentPlatform === "win32" && encrypted.subarray(0, 3).toString("utf8") === "v20") sawWindowsAppBoundCookie = true;
230
- value = currentPlatform === "win32"
231
- ? decryptWindowsCookieValue(encrypted, key, metaVersion.value >= 24)
232
- : decryptCookieValue(encrypted, key, metaVersion.value >= 24);
242
+ if (currentPlatform === "win32") {
243
+ value = decryptWindowsCookieValue(encrypted, windowsKey!, metaVersion.value >= 24);
244
+ } else {
245
+ for (const key of browserKeys) {
246
+ value = decryptCookieValue(encrypted, key, metaVersion.value >= 24);
247
+ if (value) break;
248
+ }
249
+ }
250
+ if (!value && currentPlatform === "linux" && !kwalletAttempted && browserPasswords.some((password) => password.source === "secret-service") && requiredCookies?.includes(name)) {
251
+ kwalletAttempted = true;
252
+ const fallback = await readKWalletPassword(config);
253
+ if (fallback.warning) warningSet.add(fallback.warning);
254
+ if (fallback.value) {
255
+ const key = pbkdf2Sync(fallback.value, "saltysalt", 1, 16, "sha1");
256
+ browserKeys.push(key);
257
+ value = decryptCookieValue(encrypted, key, metaVersion.value >= 24);
258
+ if (value) {
259
+ browserPasswords.push(fallback);
260
+ browserPasswordCache.set(passwordCacheKey(config, currentPlatform), Promise.resolve([...browserPasswords]));
261
+ }
262
+ }
263
+ }
233
264
  if (!value && requiredCookies?.includes(name)) requiredDecryptFailures.add(name);
234
265
  }
235
266
  if (!value) continue;
@@ -417,20 +448,24 @@ function removePkcs7Padding(buf: Buffer): Buffer {
417
448
  return !padding || padding > 16 ? buf : buf.subarray(0, buf.length - padding);
418
449
  }
419
450
 
420
- function readBrowserPassword(config: BrowserConfig, currentPlatform: typeof process.platform): Promise<string | null> {
421
- const cacheKey = `${currentPlatform}:${config.name}`;
451
+ function passwordCacheKey(config: BrowserConfig, currentPlatform: typeof process.platform): string {
452
+ return `${currentPlatform}:${config.name}`;
453
+ }
454
+
455
+ function readBrowserPasswords(config: BrowserConfig, currentPlatform: typeof process.platform): Promise<BrowserPassword[]> {
456
+ const cacheKey = passwordCacheKey(config, currentPlatform);
422
457
  const cached = browserPasswordCache.get(cacheKey);
423
458
  if (cached) return cached;
424
459
  const passwordResult = currentPlatform === "darwin"
425
460
  ? config.keychainAccount && config.keychainService
426
- ? readKeychainPassword(config.keychainAccount, config.keychainService).then(password => ({ password, cacheable: Boolean(password) }))
427
- : Promise.resolve({ password: null, cacheable: false })
461
+ ? readKeychainPassword(config.keychainAccount, config.keychainService).then(value => ({ value, cacheable: Boolean(value) }))
462
+ : Promise.resolve({ value: null, cacheable: false })
428
463
  : currentPlatform === "linux"
429
- ? readLinuxPassword(config.secretToolApp)
430
- : Promise.resolve({ password: null, cacheable: false });
431
- const passwordPromise = passwordResult.then(({ password, cacheable }) => {
464
+ ? readLinuxPassword(config)
465
+ : Promise.resolve({ value: null, cacheable: false });
466
+ const passwordPromise = passwordResult.then(({ cacheable, ...password }) => {
432
467
  if (!cacheable) browserPasswordCache.delete(cacheKey);
433
- return password;
468
+ return [password];
434
469
  }, (error) => {
435
470
  browserPasswordCache.delete(cacheKey);
436
471
  throw error;
@@ -477,17 +512,36 @@ function readKeychainPassword(account: string, service: string): Promise<string
477
512
  });
478
513
  }
479
514
 
480
- function readLinuxPassword(secretToolApp: string | undefined): Promise<{ password: string; cacheable: boolean }> {
481
- if (!secretToolApp) return Promise.resolve({ password: "peanuts", cacheable: true });
515
+ function readLinuxCommandPassword(command: string, args: string[]): Promise<{ value: string | null; failed: boolean }> {
482
516
  return new Promise((resolve) => {
483
- execFile("secret-tool", ["lookup", "application", secretToolApp], { timeout: 5000 }, (err, stdout) => {
484
- if (err) { resolve({ password: "peanuts", cacheable: false }); return; }
485
- const password = stdout.trim();
486
- resolve(password ? { password, cacheable: true } : { password: "peanuts", cacheable: false });
487
- });
517
+ execFile(command, args, { timeout: 5000 }, (err, stdout) => resolve({ value: err ? null : stdout.trim() || null, failed: Boolean(err) }));
488
518
  });
489
519
  }
490
520
 
521
+ function isKdeSession(): boolean {
522
+ const desktop = process.env.XDG_CURRENT_DESKTOP?.toLowerCase().split(":") ?? [];
523
+ return process.env.KDE_FULL_SESSION?.toLowerCase() === "true" || desktop.includes("kde");
524
+ }
525
+
526
+ async function readKWalletPassword(config: BrowserConfig): Promise<BrowserPassword> {
527
+ if (!isKdeSession() || !config.kwalletFolder || !config.kwalletEntry) return { value: null };
528
+ const result = await readLinuxCommandPassword("kwallet-query", ["-f", config.kwalletFolder, "-r", config.kwalletEntry, "kdewallet"]);
529
+ return {
530
+ value: result.value,
531
+ source: result.value ? "kwallet" : undefined,
532
+ ...(result.failed ? { warning: `Could not read ${config.name} KWallet cookie encryption password` } : {}),
533
+ };
534
+ }
535
+
536
+ async function readLinuxPassword(config: BrowserConfig): Promise<BrowserPassword & { cacheable: boolean }> {
537
+ if (!config.secretToolApp) return { value: "peanuts", cacheable: false };
538
+ const secretService = await readLinuxCommandPassword("secret-tool", ["lookup", "application", config.secretToolApp]);
539
+ if (secretService.value) return { value: secretService.value, source: "secret-service", cacheable: true };
540
+ const kwallet = await readKWalletPassword(config);
541
+ if (kwallet.value) return { ...kwallet, cacheable: true };
542
+ return { value: "peanuts", warning: kwallet.warning, cacheable: false };
543
+ }
544
+
491
545
  async function importSqlite(): Promise<typeof import("node:sqlite") | null> {
492
546
  if (process.env.PI_WEB_ACCESS_DISABLE_NODE_SQLITE === "1") return null;
493
547
  if (sqliteImportAttempted) return sqliteModule;
@@ -46,7 +46,9 @@ function buildProviderButtons(
46
46
  { value: "serpapi", label: "SerpApi", available: available.serpapi },
47
47
  { value: "serper", label: "Serper", available: available.serper },
48
48
  { value: "serply", label: "Serply", available: available.serply },
49
+ { value: "you", label: "You.com", available: available.you },
49
50
  { value: "baizhi", label: "Baizhi", available: available.baizhi },
51
+ { value: "zai", label: "Z.ai", available: available.zai },
50
52
  { value: "valyu", label: "Valyu", available: available.valyu },
51
53
  ];
52
54
 
@@ -1474,7 +1476,7 @@ const SCRIPT = `(function() {
1474
1476
  var token = DATA.sessionToken;
1475
1477
  var timeoutSec = DATA.timeout;
1476
1478
  var queries = Array.isArray(DATA.queries) ? DATA.queries : [];
1477
- var providers = ["auto", "all", "openai", "exa", "brave", "parallel", "parallel-mcp", "tinyfish", "search1api", "searchinfinity", "querit", "tavily", "firecrawl", "jina", "serpdive", "kagi", "bocha", "ollama", "searxng", "duckduckgo", "perplexity", "gemini", "kimi", "anysearch", "xcrawl", "xai", "mistral", "brightdata", "serpbase", "serpapi", "serper", "serply", "valyu", "baizhi"];
1479
+ var providers = ["auto", "all", "openai", "exa", "brave", "parallel", "parallel-mcp", "tinyfish", "search1api", "searchinfinity", "querit", "tavily", "firecrawl", "jina", "serpdive", "kagi", "bocha", "ollama", "searxng", "duckduckgo", "perplexity", "gemini", "kimi", "anysearch", "xcrawl", "xai", "mistral", "brightdata", "serpbase", "serpapi", "serper", "serply", "valyu", "baizhi", "you", "zai"];
1478
1480
  var availProviders = DATA.availableProviders && typeof DATA.availableProviders === "object" ? DATA.availableProviders : {};
1479
1481
  var workflow = "summary-review";
1480
1482
  var initialDefaultProvider = typeof DATA.defaultProvider === "string" ? DATA.defaultProvider : "exa";
@@ -1709,7 +1711,9 @@ const SCRIPT = `(function() {
1709
1711
  if (provider === "serpapi") return "SerpApi";
1710
1712
  if (provider === "serper") return "Serper";
1711
1713
  if (provider === "serply") return "Serply";
1714
+ if (provider === "you") return "You.com";
1712
1715
  if (provider === "baizhi") return "Baizhi";
1716
+ if (provider === "zai") return "Z.ai";
1713
1717
  if (provider === "valyu") return "Valyu";
1714
1718
  return "Unknown";
1715
1719
  }
@@ -305,7 +305,9 @@ export function startCuratorServer(
305
305
  if (provider === "serpbase") return availableProviders.serpbase;
306
306
  if (provider === "serper") return availableProviders.serper;
307
307
  if (provider === "serply") return availableProviders.serply;
308
+ if (provider === "you") return availableProviders.you;
308
309
  if (provider === "baizhi") return availableProviders.baizhi;
310
+ if (provider === "zai") return availableProviders.zai;
309
311
  if (provider === "valyu") return availableProviders.valyu;
310
312
  return false;
311
313
  }