@herbertgao/pi-extensions 2026.8.2 → 2026.8.4

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 (392) hide show
  1. package/README.md +50 -2
  2. package/examples/pi-footer.json +275 -0
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -8
  4. package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -7
  5. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +101 -0
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +1 -17
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +5 -3
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{utils/agent-summary.ts → feature/agent-summary/core.ts} +37 -35
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-summary.ts → agent-summary/index.ts} +2 -6
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference.ts → reference/index.ts} +1 -1
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-autocomplete.ts → reference/subagent.ts} +19 -9
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-startup-header.ts → shell/startup-header.ts} +1 -1
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{working-message.ts → shell/working-message.ts} +5 -2
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +32 -28
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +379 -85
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +727 -0
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +65 -775
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +35 -31
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-hover.ts → mouse/hover.ts} +5 -5
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +34 -35
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-layout.ts → mouse/layout.ts} +5 -21
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-packets.ts → mouse/packets.ts} +1 -1
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-scroll.ts → mouse/scroll.ts} +48 -37
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ansi-utils.ts +56 -1
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-renderer.ts +2 -2
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/line-width-safety.ts +1 -1
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +12 -0
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/write-execution.ts +1 -2
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-grouping.ts → tool/grouping.ts} +18 -8
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-result.ts → tool/result.ts} +4 -13
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +0 -27
  32. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  33. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  34. package/node_modules/@herbertgao/pi-subagents/package.json +2 -2
  35. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +1 -0
  36. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +3 -1
  37. package/node_modules/@herbertgao/pi-subagents/src/index.ts +33 -35
  38. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +26 -35
  39. package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +15 -1
  40. package/node_modules/pi-footer/CHANGELOG.md +145 -0
  41. package/node_modules/pi-footer/LICENSE +21 -0
  42. package/node_modules/pi-footer/README.md +354 -0
  43. package/node_modules/pi-footer/package.json +68 -0
  44. package/node_modules/pi-footer/src/cache.ts +106 -0
  45. package/node_modules/pi-footer/src/colors.ts +237 -0
  46. package/node_modules/pi-footer/src/config.ts +202 -0
  47. package/node_modules/pi-footer/src/event-widgets.ts +41 -0
  48. package/node_modules/pi-footer/src/extension-statuses.ts +102 -0
  49. package/node_modules/pi-footer/src/git.ts +135 -0
  50. package/node_modules/pi-footer/src/index.ts +268 -0
  51. package/node_modules/pi-footer/src/metrics.ts +141 -0
  52. package/node_modules/pi-footer/src/presets.ts +383 -0
  53. package/node_modules/pi-footer/src/render.ts +114 -0
  54. package/node_modules/pi-footer/src/separators.ts +52 -0
  55. package/node_modules/pi-footer/src/types.ts +122 -0
  56. package/node_modules/pi-footer/src/ui/color-level-confirm.ts +22 -0
  57. package/node_modules/pi-footer/src/ui/color-options.ts +195 -0
  58. package/node_modules/pi-footer/src/ui/config-lifecycle.ts +61 -0
  59. package/node_modules/pi-footer/src/ui/edit-colors.ts +13 -0
  60. package/node_modules/pi-footer/src/ui/events.ts +35 -0
  61. package/node_modules/pi-footer/src/ui/extension-status-picker.ts +60 -0
  62. package/node_modules/pi-footer/src/ui/extension-statuses.ts +73 -0
  63. package/node_modules/pi-footer/src/ui/fields.ts +252 -0
  64. package/node_modules/pi-footer/src/ui/global-menu.ts +126 -0
  65. package/node_modules/pi-footer/src/ui/helpers.ts +44 -0
  66. package/node_modules/pi-footer/src/ui/layout.ts +17 -0
  67. package/node_modules/pi-footer/src/ui/line-list.ts +19 -0
  68. package/node_modules/pi-footer/src/ui/model.ts +64 -0
  69. package/node_modules/pi-footer/src/ui/navigation.ts +29 -0
  70. package/node_modules/pi-footer/src/ui/option-edit.ts +93 -0
  71. package/node_modules/pi-footer/src/ui/overlay-render.ts +103 -0
  72. package/node_modules/pi-footer/src/ui/screen-context.ts +18 -0
  73. package/node_modules/pi-footer/src/ui/screen-controller.ts +27 -0
  74. package/node_modules/pi-footer/src/ui/screen-render.ts +32 -0
  75. package/node_modules/pi-footer/src/ui/screen-state.ts +20 -0
  76. package/node_modules/pi-footer/src/ui/screen.ts +243 -0
  77. package/node_modules/pi-footer/src/ui/screens/add-widget.ts +92 -0
  78. package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +52 -0
  79. package/node_modules/pi-footer/src/ui/screens/controller.ts +12 -0
  80. package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +68 -0
  81. package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +115 -0
  82. package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +61 -0
  83. package/node_modules/pi-footer/src/ui/screens/global.ts +75 -0
  84. package/node_modules/pi-footer/src/ui/screens/line-list.ts +108 -0
  85. package/node_modules/pi-footer/src/ui/screens/main.ts +99 -0
  86. package/node_modules/pi-footer/src/ui/screens/terminal.ts +121 -0
  87. package/node_modules/pi-footer/src/ui/screens/widget-list.ts +154 -0
  88. package/node_modules/pi-footer/src/ui/terminal-menu.ts +32 -0
  89. package/node_modules/pi-footer/src/ui/theme.ts +48 -0
  90. package/node_modules/pi-footer/src/ui/title-bar.ts +100 -0
  91. package/node_modules/pi-footer/src/ui/widget-actions.ts +76 -0
  92. package/node_modules/pi-footer/src/ui.ts +66 -0
  93. package/node_modules/pi-footer/src/widgets/context.ts +28 -0
  94. package/node_modules/pi-footer/src/widgets/core/active-tools.ts +17 -0
  95. package/node_modules/pi-footer/src/widgets/core/context-window.ts +24 -0
  96. package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +19 -0
  97. package/node_modules/pi-footer/src/widgets/core/cwd.ts +108 -0
  98. package/node_modules/pi-footer/src/widgets/core/event.ts +34 -0
  99. package/node_modules/pi-footer/src/widgets/core/external-status.ts +102 -0
  100. package/node_modules/pi-footer/src/widgets/core/model-provider.ts +20 -0
  101. package/node_modules/pi-footer/src/widgets/core/model.ts +35 -0
  102. package/node_modules/pi-footer/src/widgets/core/provider.ts +17 -0
  103. package/node_modules/pi-footer/src/widgets/core/session-name.ts +17 -0
  104. package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +17 -0
  105. package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +17 -0
  106. package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +17 -0
  107. package/node_modules/pi-footer/src/widgets/git/branch.ts +81 -0
  108. package/node_modules/pi-footer/src/widgets/git/clean.ts +19 -0
  109. package/node_modules/pi-footer/src/widgets/git/deletions.ts +17 -0
  110. package/node_modules/pi-footer/src/widgets/git/diff.ts +38 -0
  111. package/node_modules/pi-footer/src/widgets/git/insertions.ts +17 -0
  112. package/node_modules/pi-footer/src/widgets/git/remote.ts +17 -0
  113. package/node_modules/pi-footer/src/widgets/git/root.ts +17 -0
  114. package/node_modules/pi-footer/src/widgets/git/sha.ts +17 -0
  115. package/node_modules/pi-footer/src/widgets/git/staged.ts +17 -0
  116. package/node_modules/pi-footer/src/widgets/git/status.ts +19 -0
  117. package/node_modules/pi-footer/src/widgets/git/unstaged.ts +17 -0
  118. package/node_modules/pi-footer/src/widgets/git/untracked.ts +17 -0
  119. package/node_modules/pi-footer/src/widgets/instance.ts +118 -0
  120. package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +18 -0
  121. package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +32 -0
  122. package/node_modules/pi-footer/src/widgets/layout/separator.ts +57 -0
  123. package/node_modules/pi-footer/src/widgets/layout/spacer.ts +31 -0
  124. package/node_modules/pi-footer/src/widgets/options.ts +122 -0
  125. package/node_modules/pi-footer/src/widgets/project/runtime.ts +361 -0
  126. package/node_modules/pi-footer/src/widgets/registry.ts +223 -0
  127. package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +17 -0
  128. package/node_modules/pi-footer/src/widgets/session/compactions.ts +17 -0
  129. package/node_modules/pi-footer/src/widgets/session/elapsed.ts +18 -0
  130. package/node_modules/pi-footer/src/widgets/session/last-activity.ts +18 -0
  131. package/node_modules/pi-footer/src/widgets/session/messages.ts +19 -0
  132. package/node_modules/pi-footer/src/widgets/session/session-id.ts +17 -0
  133. package/node_modules/pi-footer/src/widgets/session/session-start.ts +18 -0
  134. package/node_modules/pi-footer/src/widgets/session/tool-results.ts +17 -0
  135. package/node_modules/pi-footer/src/widgets/session/total-messages.ts +19 -0
  136. package/node_modules/pi-footer/src/widgets/session/total-time.ts +18 -0
  137. package/node_modules/pi-footer/src/widgets/session/user-messages.ts +17 -0
  138. package/node_modules/pi-footer/src/widgets/store.ts +26 -0
  139. package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +55 -0
  140. package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +18 -0
  141. package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +18 -0
  142. package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +108 -0
  143. package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +26 -0
  144. package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +29 -0
  145. package/node_modules/pi-footer/src/widgets/tokens/context.ts +29 -0
  146. package/node_modules/pi-footer/src/widgets/tokens/cost.ts +51 -0
  147. package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +25 -0
  148. package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +18 -0
  149. package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +25 -0
  150. package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +18 -0
  151. package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +20 -0
  152. package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +25 -0
  153. package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +18 -0
  154. package/node_modules/pi-footer/src/widgets/types.ts +181 -0
  155. package/node_modules/pi-footer/src/widgets/utils/colors.ts +11 -0
  156. package/node_modules/pi-footer/src/widgets/utils/context.ts +112 -0
  157. package/node_modules/pi-footer/src/widgets/utils/session.ts +19 -0
  158. package/node_modules/pi-footer/src/widgets/utils/token-format.ts +78 -0
  159. package/node_modules/pi-mcp-adapter/CHANGELOG.md +19 -0
  160. package/node_modules/pi-mcp-adapter/README.md +19 -4
  161. package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
  162. package/node_modules/pi-mcp-adapter/commands.ts +12 -2
  163. package/node_modules/pi-mcp-adapter/direct-tools.ts +6 -8
  164. package/node_modules/pi-mcp-adapter/index.ts +15 -3
  165. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +87 -4
  166. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
  167. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +43 -4
  168. package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
  169. package/node_modules/pi-mcp-adapter/package.json +8 -2
  170. package/node_modules/pi-mcp-adapter/proxy-modes.ts +8 -10
  171. package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
  172. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  173. package/node_modules/pi-web-access/CHANGELOG.md +45 -0
  174. package/node_modules/pi-web-access/README.md +104 -29
  175. package/node_modules/pi-web-access/bocha.ts +221 -0
  176. package/node_modules/pi-web-access/curator-page.ts +113 -12
  177. package/node_modules/pi-web-access/curator-server.ts +56 -20
  178. package/node_modules/pi-web-access/datalab-pdf-extract.ts +568 -0
  179. package/node_modules/pi-web-access/duckduckgo.ts +123 -0
  180. package/node_modules/pi-web-access/extract.ts +288 -143
  181. package/node_modules/pi-web-access/feature-config.ts +29 -0
  182. package/node_modules/pi-web-access/gemini-api.ts +4 -0
  183. package/node_modules/pi-web-access/gemini-search.ts +45 -12
  184. package/node_modules/pi-web-access/gemini-web.ts +68 -3
  185. package/node_modules/pi-web-access/index.ts +160 -71
  186. package/node_modules/pi-web-access/jina-search.ts +284 -0
  187. package/node_modules/pi-web-access/kagi.ts +12 -12
  188. package/node_modules/pi-web-access/openai-search.ts +12 -2
  189. package/node_modules/pi-web-access/package.json +4 -3
  190. package/node_modules/pi-web-access/pdf-extract.ts +327 -228
  191. package/node_modules/pi-web-access/storage.ts +440 -2
  192. package/node_modules/pi-web-access/summary-model-scope.ts +1 -1
  193. package/node_modules/pi-web-access/summary-review.ts +4 -2
  194. package/node_modules/pi-web-access/video-extract.ts +10 -8
  195. package/node_modules/pi-web-access/xai-search.ts +12 -2
  196. package/node_modules/pi-web-access/youtube-extract.ts +2 -1
  197. package/node_modules/remote-pi/LICENSE +21 -0
  198. package/node_modules/remote-pi/README.md +675 -0
  199. package/node_modules/remote-pi/dist/actions/handlers.d.ts +122 -0
  200. package/node_modules/remote-pi/dist/actions/handlers.js +160 -0
  201. package/node_modules/remote-pi/dist/actions/handlers.js.map +1 -0
  202. package/node_modules/remote-pi/dist/actions/registry.d.ts +39 -0
  203. package/node_modules/remote-pi/dist/actions/registry.js +58 -0
  204. package/node_modules/remote-pi/dist/actions/registry.js.map +1 -0
  205. package/node_modules/remote-pi/dist/bin/supervisord.d.ts +2 -0
  206. package/node_modules/remote-pi/dist/bin/supervisord.js +86 -0
  207. package/node_modules/remote-pi/dist/bin/supervisord.js.map +1 -0
  208. package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +58 -0
  209. package/node_modules/remote-pi/dist/commands/builtin_mirror.js +71 -0
  210. package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +1 -0
  211. package/node_modules/remote-pi/dist/commands/list_commands.d.ts +60 -0
  212. package/node_modules/remote-pi/dist/commands/list_commands.js +73 -0
  213. package/node_modules/remote-pi/dist/commands/list_commands.js.map +1 -0
  214. package/node_modules/remote-pi/dist/config.d.ts +62 -0
  215. package/node_modules/remote-pi/dist/config.js +115 -0
  216. package/node_modules/remote-pi/dist/config.js.map +1 -0
  217. package/node_modules/remote-pi/dist/daemon/client.d.ts +20 -0
  218. package/node_modules/remote-pi/dist/daemon/client.js +131 -0
  219. package/node_modules/remote-pi/dist/daemon/client.js.map +1 -0
  220. package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +176 -0
  221. package/node_modules/remote-pi/dist/daemon/control_protocol.js +63 -0
  222. package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +1 -0
  223. package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +45 -0
  224. package/node_modules/remote-pi/dist/daemon/cron_log.js +72 -0
  225. package/node_modules/remote-pi/dist/daemon/cron_log.js.map +1 -0
  226. package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +80 -0
  227. package/node_modules/remote-pi/dist/daemon/cron_registry.js +194 -0
  228. package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +1 -0
  229. package/node_modules/remote-pi/dist/daemon/id.d.ts +24 -0
  230. package/node_modules/remote-pi/dist/daemon/id.js +36 -0
  231. package/node_modules/remote-pi/dist/daemon/id.js.map +1 -0
  232. package/node_modules/remote-pi/dist/daemon/install.d.ts +170 -0
  233. package/node_modules/remote-pi/dist/daemon/install.js +547 -0
  234. package/node_modules/remote-pi/dist/daemon/install.js.map +1 -0
  235. package/node_modules/remote-pi/dist/daemon/registry.d.ts +63 -0
  236. package/node_modules/remote-pi/dist/daemon/registry.js +153 -0
  237. package/node_modules/remote-pi/dist/daemon/registry.js.map +1 -0
  238. package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +194 -0
  239. package/node_modules/remote-pi/dist/daemon/rpc_child.js +389 -0
  240. package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +1 -0
  241. package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +93 -0
  242. package/node_modules/remote-pi/dist/daemon/supervisor.js +596 -0
  243. package/node_modules/remote-pi/dist/daemon/supervisor.js.map +1 -0
  244. package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +26 -0
  245. package/node_modules/remote-pi/dist/extension_ui_bridge.js +341 -0
  246. package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +1 -0
  247. package/node_modules/remote-pi/dist/index.d.ts +213 -0
  248. package/node_modules/remote-pi/dist/index.js +4996 -0
  249. package/node_modules/remote-pi/dist/index.js.map +1 -0
  250. package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +10 -0
  251. package/node_modules/remote-pi/dist/mcp/mesh_result.js +42 -0
  252. package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +1 -0
  253. package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +16 -0
  254. package/node_modules/remote-pi/dist/mcp/mesh_server.js +327 -0
  255. package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +1 -0
  256. package/node_modules/remote-pi/dist/mesh/canonical.d.ts +30 -0
  257. package/node_modules/remote-pi/dist/mesh/canonical.js +61 -0
  258. package/node_modules/remote-pi/dist/mesh/canonical.js.map +1 -0
  259. package/node_modules/remote-pi/dist/mesh/client.d.ts +18 -0
  260. package/node_modules/remote-pi/dist/mesh/client.js +125 -0
  261. package/node_modules/remote-pi/dist/mesh/client.js.map +1 -0
  262. package/node_modules/remote-pi/dist/mesh/encoding.d.ts +38 -0
  263. package/node_modules/remote-pi/dist/mesh/encoding.js +216 -0
  264. package/node_modules/remote-pi/dist/mesh/encoding.js.map +1 -0
  265. package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +73 -0
  266. package/node_modules/remote-pi/dist/mesh/self_revoke.js +401 -0
  267. package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +1 -0
  268. package/node_modules/remote-pi/dist/mesh/siblings.d.ts +49 -0
  269. package/node_modules/remote-pi/dist/mesh/siblings.js +159 -0
  270. package/node_modules/remote-pi/dist/mesh/siblings.js.map +1 -0
  271. package/node_modules/remote-pi/dist/mesh/types.d.ts +34 -0
  272. package/node_modules/remote-pi/dist/mesh/types.js +11 -0
  273. package/node_modules/remote-pi/dist/mesh/types.js.map +1 -0
  274. package/node_modules/remote-pi/dist/mesh/verify.d.ts +17 -0
  275. package/node_modules/remote-pi/dist/mesh/verify.js +86 -0
  276. package/node_modules/remote-pi/dist/mesh/verify.js.map +1 -0
  277. package/node_modules/remote-pi/dist/pairing/crypto.d.ts +8 -0
  278. package/node_modules/remote-pi/dist/pairing/crypto.js +22 -0
  279. package/node_modules/remote-pi/dist/pairing/crypto.js.map +1 -0
  280. package/node_modules/remote-pi/dist/pairing/handshake.d.ts +28 -0
  281. package/node_modules/remote-pi/dist/pairing/handshake.js +113 -0
  282. package/node_modules/remote-pi/dist/pairing/handshake.js.map +1 -0
  283. package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +16 -0
  284. package/node_modules/remote-pi/dist/pairing/noise-sha256.js +103 -0
  285. package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +1 -0
  286. package/node_modules/remote-pi/dist/pairing/qr.d.ts +59 -0
  287. package/node_modules/remote-pi/dist/pairing/qr.js +125 -0
  288. package/node_modules/remote-pi/dist/pairing/qr.js.map +1 -0
  289. package/node_modules/remote-pi/dist/pairing/storage.d.ts +120 -0
  290. package/node_modules/remote-pi/dist/pairing/storage.js +604 -0
  291. package/node_modules/remote-pi/dist/pairing/storage.js.map +1 -0
  292. package/node_modules/remote-pi/dist/protocol/codec.d.ts +7 -0
  293. package/node_modules/remote-pi/dist/protocol/codec.js +49 -0
  294. package/node_modules/remote-pi/dist/protocol/codec.js.map +1 -0
  295. package/node_modules/remote-pi/dist/protocol/types.d.ts +393 -0
  296. package/node_modules/remote-pi/dist/protocol/types.js +2 -0
  297. package/node_modules/remote-pi/dist/protocol/types.js.map +1 -0
  298. package/node_modules/remote-pi/dist/rooms.d.ts +29 -0
  299. package/node_modules/remote-pi/dist/rooms.js +57 -0
  300. package/node_modules/remote-pi/dist/rooms.js.map +1 -0
  301. package/node_modules/remote-pi/dist/session/address.d.ts +49 -0
  302. package/node_modules/remote-pi/dist/session/address.js +58 -0
  303. package/node_modules/remote-pi/dist/session/address.js.map +1 -0
  304. package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +55 -0
  305. package/node_modules/remote-pi/dist/session/agent_bridge.js +146 -0
  306. package/node_modules/remote-pi/dist/session/agent_bridge.js.map +1 -0
  307. package/node_modules/remote-pi/dist/session/bridge.d.ts +37 -0
  308. package/node_modules/remote-pi/dist/session/bridge.js +130 -0
  309. package/node_modules/remote-pi/dist/session/bridge.js.map +1 -0
  310. package/node_modules/remote-pi/dist/session/broker.d.ts +189 -0
  311. package/node_modules/remote-pi/dist/session/broker.js +507 -0
  312. package/node_modules/remote-pi/dist/session/broker.js.map +1 -0
  313. package/node_modules/remote-pi/dist/session/broker_remote.d.ts +74 -0
  314. package/node_modules/remote-pi/dist/session/broker_remote.js +583 -0
  315. package/node_modules/remote-pi/dist/session/broker_remote.js.map +1 -0
  316. package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +33 -0
  317. package/node_modules/remote-pi/dist/session/cwd_lock.js +126 -0
  318. package/node_modules/remote-pi/dist/session/cwd_lock.js.map +1 -0
  319. package/node_modules/remote-pi/dist/session/envelope.d.ts +33 -0
  320. package/node_modules/remote-pi/dist/session/envelope.js +117 -0
  321. package/node_modules/remote-pi/dist/session/envelope.js.map +1 -0
  322. package/node_modules/remote-pi/dist/session/global_config.d.ts +33 -0
  323. package/node_modules/remote-pi/dist/session/global_config.js +73 -0
  324. package/node_modules/remote-pi/dist/session/global_config.js.map +1 -0
  325. package/node_modules/remote-pi/dist/session/ipc.d.ts +27 -0
  326. package/node_modules/remote-pi/dist/session/ipc.js +22 -0
  327. package/node_modules/remote-pi/dist/session/ipc.js.map +1 -0
  328. package/node_modules/remote-pi/dist/session/leader_election.d.ts +32 -0
  329. package/node_modules/remote-pi/dist/session/leader_election.js +106 -0
  330. package/node_modules/remote-pi/dist/session/leader_election.js.map +1 -0
  331. package/node_modules/remote-pi/dist/session/local_config.d.ts +55 -0
  332. package/node_modules/remote-pi/dist/session/local_config.js +157 -0
  333. package/node_modules/remote-pi/dist/session/local_config.js.map +1 -0
  334. package/node_modules/remote-pi/dist/session/mesh_message.d.ts +20 -0
  335. package/node_modules/remote-pi/dist/session/mesh_message.js +28 -0
  336. package/node_modules/remote-pi/dist/session/mesh_message.js.map +1 -0
  337. package/node_modules/remote-pi/dist/session/mesh_node.d.ts +116 -0
  338. package/node_modules/remote-pi/dist/session/mesh_node.js +573 -0
  339. package/node_modules/remote-pi/dist/session/mesh_node.js.map +1 -0
  340. package/node_modules/remote-pi/dist/session/peer.d.ts +139 -0
  341. package/node_modules/remote-pi/dist/session/peer.js +451 -0
  342. package/node_modules/remote-pi/dist/session/peer.js.map +1 -0
  343. package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +13 -0
  344. package/node_modules/remote-pi/dist/session/peer_inventory.js +48 -0
  345. package/node_modules/remote-pi/dist/session/peer_inventory.js.map +1 -0
  346. package/node_modules/remote-pi/dist/session/peer_limits.d.ts +9 -0
  347. package/node_modules/remote-pi/dist/session/peer_limits.js +21 -0
  348. package/node_modules/remote-pi/dist/session/peer_limits.js.map +1 -0
  349. package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +39 -0
  350. package/node_modules/remote-pi/dist/session/setup_wizard.js +63 -0
  351. package/node_modules/remote-pi/dist/session/setup_wizard.js.map +1 -0
  352. package/node_modules/remote-pi/dist/session/tool_gate.d.ts +5 -0
  353. package/node_modules/remote-pi/dist/session/tool_gate.js +11 -0
  354. package/node_modules/remote-pi/dist/session/tool_gate.js.map +1 -0
  355. package/node_modules/remote-pi/dist/session/tools.d.ts +24 -0
  356. package/node_modules/remote-pi/dist/session/tools.js +252 -0
  357. package/node_modules/remote-pi/dist/session/tools.js.map +1 -0
  358. package/node_modules/remote-pi/dist/session/wizard.d.ts +13 -0
  359. package/node_modules/remote-pi/dist/session/wizard.js +20 -0
  360. package/node_modules/remote-pi/dist/session/wizard.js.map +1 -0
  361. package/node_modules/remote-pi/dist/settings.d.ts +15 -0
  362. package/node_modules/remote-pi/dist/settings.js +52 -0
  363. package/node_modules/remote-pi/dist/settings.js.map +1 -0
  364. package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +37 -0
  365. package/node_modules/remote-pi/dist/transport/peer_channel.js +98 -0
  366. package/node_modules/remote-pi/dist/transport/peer_channel.js.map +1 -0
  367. package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +29 -0
  368. package/node_modules/remote-pi/dist/transport/pi_forward_client.js +62 -0
  369. package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +1 -0
  370. package/node_modules/remote-pi/dist/transport/relay_client.d.ts +91 -0
  371. package/node_modules/remote-pi/dist/transport/relay_client.js +206 -0
  372. package/node_modules/remote-pi/dist/transport/relay_client.js.map +1 -0
  373. package/node_modules/remote-pi/dist/ui/footer.d.ts +32 -0
  374. package/node_modules/remote-pi/dist/ui/footer.js +34 -0
  375. package/node_modules/remote-pi/dist/ui/footer.js.map +1 -0
  376. package/node_modules/remote-pi/docs/daemon.md +289 -0
  377. package/node_modules/remote-pi/package.json +88 -0
  378. package/node_modules/remote-pi/service-templates/launchd.plist.template +35 -0
  379. package/node_modules/remote-pi/service-templates/systemd.service.template +19 -0
  380. package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +10 -0
  381. package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +38 -0
  382. package/node_modules/remote-pi/skills/agent-network/SKILL.md +310 -0
  383. package/package.json +25 -10
  384. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool-diff/write-display-utils.ts +0 -29
  385. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference-core.ts → reference/session.ts} +0 -0
  386. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-aliases.ts → shell/aliases.ts} +0 -0
  387. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ATTRIBUTION.md +0 -0
  388. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-presentation.ts +0 -0
  389. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/index.ts +0 -0
  390. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/render-utils.ts +0 -0
  391. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/shiki-highlight.ts +0 -0
  392. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/types.ts +0 -0
@@ -0,0 +1,284 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { activityMonitor } from "./activity.ts";
3
+ import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.ts";
4
+ import type { ExtractedContent } from "./extract.ts";
5
+ import type { SearchOptions, SearchResponse } from "./perplexity.ts";
6
+ import { getWebSearchConfigPath } from "./utils.ts";
7
+
8
+ const JINA_SEARCH_BASE_URL = "https://s.jina.ai/";
9
+ const CONFIG_PATH = getWebSearchConfigPath();
10
+ const SEARCH_TIMEOUT_MS = 60_000;
11
+
12
+ interface WebSearchConfig {
13
+ jinaApiKey?: unknown;
14
+ }
15
+
16
+ interface JinaSearchItem {
17
+ title?: unknown;
18
+ url?: unknown;
19
+ description?: unknown;
20
+ content?: unknown;
21
+ }
22
+
23
+ interface JinaSearchEnvelope {
24
+ code?: unknown;
25
+ data?: unknown;
26
+ }
27
+
28
+ interface JinaSearchOptions extends SearchOptions {
29
+ includeContent?: boolean;
30
+ }
31
+
32
+ let cachedConfig: WebSearchConfig | null = null;
33
+
34
+ function loadConfig(): WebSearchConfig {
35
+ if (cachedConfig) return cachedConfig;
36
+ if (!existsSync(CONFIG_PATH)) {
37
+ cachedConfig = {};
38
+ return cachedConfig;
39
+ }
40
+
41
+ const raw = readFileSync(CONFIG_PATH, "utf8");
42
+ try {
43
+ const parsed: unknown = JSON.parse(raw);
44
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
45
+ throw new Error("expected a JSON object");
46
+ }
47
+ cachedConfig = parsed as WebSearchConfig;
48
+ return cachedConfig;
49
+ } catch (err) {
50
+ const message = err instanceof Error ? err.message : String(err);
51
+ throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
52
+ }
53
+ }
54
+
55
+ async function getApiKey(signal?: AbortSignal): Promise<string | null> {
56
+ return resolveCredential({
57
+ provider: "Jina Search",
58
+ configuredValue: loadConfig().jinaApiKey,
59
+ environmentValue: process.env.JINA_API_KEY,
60
+ signal,
61
+ });
62
+ }
63
+
64
+ async function requireApiKey(signal?: AbortSignal): Promise<string> {
65
+ const apiKey = await getApiKey(signal);
66
+ if (!apiKey) {
67
+ throw new Error(
68
+ "Jina Search API key not found. Either:\n" +
69
+ ` 1. Create ${CONFIG_PATH} with { "jinaApiKey": "your-key" }\n` +
70
+ " 2. Set JINA_API_KEY environment variable\n" +
71
+ "Get a key at https://jina.ai/api-dashboard",
72
+ );
73
+ }
74
+ return apiKey;
75
+ }
76
+
77
+ function normalizeCount(value: number | undefined): number {
78
+ if (typeof value !== "number" || !Number.isFinite(value)) return 5;
79
+ return Math.max(1, Math.min(Math.floor(value), 20));
80
+ }
81
+
82
+ function normalizeDomain(value: string): string | null {
83
+ let input = value.trim().toLowerCase();
84
+ if (input.startsWith("-")) input = input.slice(1).trim();
85
+ if (!input) return null;
86
+ try {
87
+ const parsed = input.includes("://") ? new URL(input) : new URL(`https://${input}`);
88
+ input = parsed.hostname;
89
+ } catch {
90
+ input = input.split("/")[0]?.split(":")[0] ?? "";
91
+ }
92
+ input = input.replace(/^\.+|\.+$/g, "");
93
+ return /^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/i.test(input) ? input : null;
94
+ }
95
+
96
+ function mapDomainFilter(domainFilter: string[] | undefined): { includes: string[]; excludes: string[] } {
97
+ const includes: string[] = [];
98
+ const excludes: string[] = [];
99
+ for (const raw of domainFilter ?? []) {
100
+ const domain = normalizeDomain(raw);
101
+ if (!domain) continue;
102
+ const target = raw.trim().startsWith("-") ? excludes : includes;
103
+ if (!target.includes(domain)) target.push(domain);
104
+ }
105
+ return { includes, excludes };
106
+ }
107
+
108
+ function buildSearchRequest(query: string, options: JinaSearchOptions, numResults: number): { url: string; filters: ReturnType<typeof mapDomainFilter> } {
109
+ const filters = mapDomainFilter(options.domainFilter);
110
+ const recency = options.recencyFilter ? ` published in the past ${options.recencyFilter}` : "";
111
+ const exclusions = filters.excludes.map((domain) => ` -site:${domain}`).join("");
112
+ const constrainedQuery = `${query.trim()}${exclusions}${recency}`.trim();
113
+ const url = new URL(encodeURIComponent(constrainedQuery), JINA_SEARCH_BASE_URL);
114
+ url.searchParams.set("count", String(numResults));
115
+ for (const domain of filters.includes) url.searchParams.append("site", domain);
116
+ return { url: url.toString(), filters };
117
+ }
118
+
119
+ function requestSignal(signal?: AbortSignal): { signal: AbortSignal; timeout: AbortSignal } {
120
+ const timeout = AbortSignal.timeout(SEARCH_TIMEOUT_MS);
121
+ return {
122
+ timeout,
123
+ signal: signal ? AbortSignal.any([signal, timeout]) : timeout,
124
+ };
125
+ }
126
+
127
+ function errorMessage(err: unknown): string {
128
+ return err instanceof Error ? err.message : String(err);
129
+ }
130
+
131
+ function parseItems(value: unknown): JinaSearchItem[] {
132
+ if (Array.isArray(value)) return value as JinaSearchItem[];
133
+ if (!value || typeof value !== "object") {
134
+ throw new Error("Jina Search API returned invalid response: expected an object or array");
135
+ }
136
+ const envelope = value as JinaSearchEnvelope;
137
+ if (typeof envelope.code === "number" && envelope.code !== 200) {
138
+ throw new Error(`Jina Search API error ${envelope.code}: response envelope reported failure`);
139
+ }
140
+ if (!Array.isArray(envelope.data)) {
141
+ throw new Error("Jina Search API returned invalid response: expected data array");
142
+ }
143
+ return envelope.data as JinaSearchItem[];
144
+ }
145
+
146
+ function passesDomainFilter(url: string, filters: ReturnType<typeof mapDomainFilter>): boolean {
147
+ let hostname: string;
148
+ try {
149
+ hostname = new URL(url).hostname.toLowerCase();
150
+ } catch {
151
+ return false;
152
+ }
153
+ const matches = (domain: string): boolean => hostname === domain || hostname.endsWith(`.${domain}`);
154
+ if (filters.includes.length > 0 && !filters.includes.some(matches)) return false;
155
+ return !filters.excludes.some(matches);
156
+ }
157
+
158
+ function mapItems(items: JinaSearchItem[], numResults: number, filters: ReturnType<typeof mapDomainFilter>): {
159
+ results: SearchResponse["results"];
160
+ content: ExtractedContent[];
161
+ } {
162
+ const results: SearchResponse["results"] = [];
163
+ const content: ExtractedContent[] = [];
164
+ const seen = new Set<string>();
165
+ for (const item of items) {
166
+ const url = typeof item?.url === "string" ? item.url.trim() : "";
167
+ if (!url || seen.has(url) || !passesDomainFilter(url, filters)) continue;
168
+ seen.add(url);
169
+ const title = typeof item.title === "string" && item.title.trim()
170
+ ? item.title.trim()
171
+ : `Source ${results.length + 1}`;
172
+ const snippet = typeof item.description === "string"
173
+ ? item.description.replace(/\s+/g, " ").trim()
174
+ : "";
175
+ results.push({ title, url, snippet });
176
+ if (typeof item.content === "string" && item.content.trim()) {
177
+ content.push({ url, title, content: item.content.trim(), error: null });
178
+ }
179
+ if (results.length >= numResults) break;
180
+ }
181
+ return { results, content };
182
+ }
183
+
184
+ function buildAnswer(results: SearchResponse["results"]): string {
185
+ return results
186
+ .map((result) => result.snippet
187
+ ? `${result.snippet}\nSource: ${result.title} (${result.url})`
188
+ : `Source: ${result.title} (${result.url})`)
189
+ .join("\n\n");
190
+ }
191
+
192
+ function rethrowRequestError(
193
+ err: unknown,
194
+ apiKey: string,
195
+ activityId: string,
196
+ request: ReturnType<typeof requestSignal>,
197
+ callerSignal?: AbortSignal,
198
+ ): never {
199
+ if (request.timeout.aborted && !callerSignal?.aborted) {
200
+ activityMonitor.logComplete(activityId, 408);
201
+ throw new Error("Jina Search API error 408: request timed out");
202
+ }
203
+ const message = errorMessage(err);
204
+ const redactedMessage = redactCredential(message, apiKey);
205
+ if (redactedMessage.toLowerCase().includes("abort")) activityMonitor.logComplete(activityId, 0);
206
+ else activityMonitor.logError(activityId, redactedMessage);
207
+ if (redactedMessage === message) throw err;
208
+ const redactedError = new Error(redactedMessage);
209
+ if (err instanceof Error) redactedError.name = err.name;
210
+ throw redactedError;
211
+ }
212
+
213
+ export function isJinaSearchAvailable(): boolean {
214
+ return hasCredentialSource({
215
+ provider: "Jina Search",
216
+ configuredValue: loadConfig().jinaApiKey,
217
+ environmentValue: process.env.JINA_API_KEY,
218
+ });
219
+ }
220
+
221
+ export async function searchWithJina(query: string, options: JinaSearchOptions = {}): Promise<SearchResponse> {
222
+ const apiKey = await requireApiKey(options.signal);
223
+ const numResults = normalizeCount(options.numResults);
224
+ const { url, filters } = buildSearchRequest(query, options, numResults);
225
+ const activityId = activityMonitor.logStart({ type: "api", query });
226
+ const request = requestSignal(options.signal);
227
+ let response: Response;
228
+ try {
229
+ response = await fetch(url, {
230
+ headers: {
231
+ "Accept": "application/json",
232
+ "Authorization": `Bearer ${apiKey}`,
233
+ "User-Agent": "pi-web-access",
234
+ "X-Respond-With": options.includeContent ? "content" : "no-content",
235
+ "X-Retain-Images": "none",
236
+ },
237
+ signal: request.signal,
238
+ });
239
+ } catch (err) {
240
+ rethrowRequestError(err, apiKey, activityId, request, options.signal);
241
+ }
242
+
243
+ if (!response.ok) {
244
+ let body: string;
245
+ try {
246
+ body = redactCredential(await response.text(), apiKey);
247
+ } catch (err) {
248
+ rethrowRequestError(err, apiKey, activityId, request, options.signal);
249
+ }
250
+ activityMonitor.logComplete(activityId, response.status);
251
+ throw new Error(`Jina Search API error ${response.status}: ${body.slice(0, 300)}`);
252
+ }
253
+
254
+ let raw: unknown;
255
+ try {
256
+ raw = await response.json();
257
+ } catch (err) {
258
+ if (!(err instanceof SyntaxError)) {
259
+ rethrowRequestError(err, apiKey, activityId, request, options.signal);
260
+ }
261
+ activityMonitor.logComplete(activityId, response.status);
262
+ throw new Error("Jina Search API returned invalid JSON");
263
+ }
264
+
265
+ let mapped: ReturnType<typeof mapItems>;
266
+ try {
267
+ mapped = mapItems(parseItems(raw), numResults, filters);
268
+ } catch (err) {
269
+ const message = errorMessage(err);
270
+ const redactedMessage = redactCredential(message, apiKey);
271
+ activityMonitor.logError(activityId, redactedMessage);
272
+ if (redactedMessage === message) throw err;
273
+ const redactedError = new Error(redactedMessage);
274
+ if (err instanceof Error) redactedError.name = err.name;
275
+ throw redactedError;
276
+ }
277
+ activityMonitor.logComplete(activityId, response.status);
278
+ const result: SearchResponse = {
279
+ answer: buildAnswer(mapped.results),
280
+ results: mapped.results,
281
+ };
282
+ if (options.includeContent && mapped.content.length > 0) result.inlineContent = mapped.content;
283
+ return result;
284
+ }
@@ -6,7 +6,7 @@ import { hasCredentialSource, redactCredential, resolveCredential } from "./cred
6
6
  import { fetchRemoteUrl, loadFetchContentDomainPolicy, loadSsrfConfig, validateRemoteUrl, type SsrfConfig } from "./ssrf-protection.ts";
7
7
  import { getWebSearchConfigPath } from "./utils.ts";
8
8
 
9
- const KAGI_SEARCH_URL = "https://kagi.com/api/v0/search";
9
+ const KAGI_SEARCH_URL = "https://kagi.com/api/v1/search";
10
10
  const KAGI_EXTRACT_URL = "https://kagi.com/api/v1/extract";
11
11
  const CONFIG_PATH = getWebSearchConfigPath();
12
12
  const SEARCH_TIMEOUT_MS = 60_000;
@@ -95,8 +95,6 @@ function appendSearchItems(value: unknown, results: SearchResponse["results"], i
95
95
  }
96
96
  if (!value || typeof value !== "object") return;
97
97
  const item = value as Record<string, unknown>;
98
- const nested = item.results ?? item.items ?? item.list;
99
- if (Array.isArray(nested)) appendSearchItems(nested, results, inlineContent);
100
98
  const url = firstString(item.url, item.href, item.link);
101
99
  if (!url) return;
102
100
  const title = firstString(item.title, item.name) ?? url;
@@ -126,8 +124,11 @@ function parseSearchResponse(value: unknown): { results: SearchResponse["results
126
124
  const envelope = value as Record<string, unknown>;
127
125
  const results: SearchResponse["results"] = [];
128
126
  const inlineContent: ExtractedContent[] = [];
129
- appendSearchItems(envelope.data, results, inlineContent);
130
- if (results.length === 0 && envelope.data !== null) appendSearchItems(envelope, results, inlineContent);
127
+ const data = envelope.data;
128
+ const items = (typeof data === "object" && data !== null && !Array.isArray(data))
129
+ ? (data as Record<string, unknown>).search
130
+ : data;
131
+ appendSearchItems(items, results, inlineContent);
131
132
  return { results, inlineContent };
132
133
  }
133
134
 
@@ -165,14 +166,13 @@ export function isKagiAvailable(): boolean {
165
166
  export async function searchWithKagi(query: string, options: KagiSearchOptions = {}): Promise<SearchResponse> {
166
167
  const apiKey = await requireApiKey(options.signal);
167
168
  const numResults = normalizeCount(options.numResults);
168
- const url = new URL(KAGI_SEARCH_URL);
169
- url.searchParams.set("q", query);
170
- url.searchParams.set("limit", String(numResults));
171
169
  const activityId = activityMonitor.logStart({ type: "api", query });
172
170
  let response: Response;
173
171
  try {
174
- response = await fetch(url, {
175
- headers: { Authorization: `Bot ${apiKey}`, Accept: "application/json" },
172
+ response = await fetch(KAGI_SEARCH_URL, {
173
+ method: "POST",
174
+ headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", Accept: "application/json" },
175
+ body: JSON.stringify({ query, limit: numResults }),
176
176
  signal: options.signal ? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal]) : AbortSignal.timeout(SEARCH_TIMEOUT_MS),
177
177
  });
178
178
  } catch (err) {
@@ -228,8 +228,8 @@ export async function extractWithKagi(url: string, signal?: AbortSignal, options
228
228
  try {
229
229
  response = await fetchRemoteUrl(KAGI_EXTRACT_URL, {
230
230
  method: "POST",
231
- headers: { Authorization: `Bot ${apiKey}`, "Content-Type": "application/json", Accept: "application/json" },
232
- body: JSON.stringify({ urls: [url] }),
231
+ headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", Accept: "application/json" },
232
+ body: JSON.stringify({ pages: [{ url }] }),
233
233
  signal: signal ? AbortSignal.any([AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS), signal]) : AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS),
234
234
  }, {
235
235
  allowRanges: ssrf.allowRanges,
@@ -38,11 +38,13 @@ interface WebSearchConfig {
38
38
  openaiSearchModel?: unknown;
39
39
  }
40
40
 
41
+ type ProviderHeaders = Record<string, string | null>;
42
+
41
43
  interface OpenAIAuth {
42
44
  provider: "openai-codex" | "openai";
43
45
  apiKey: string;
44
46
  model: string;
45
- headers: Record<string, string>;
47
+ headers: ProviderHeaders;
46
48
  responsesUrl: string;
47
49
  }
48
50
 
@@ -155,6 +157,14 @@ function resolveConfiguredSearchModel(value: unknown): string | undefined {
155
157
  return value.trim();
156
158
  }
157
159
 
160
+ function toRequestHeaders(headers: ProviderHeaders): Record<string, string> {
161
+ const requestHeaders: Record<string, string> = {};
162
+ for (const [name, value] of Object.entries(headers)) {
163
+ if (value !== null) requestHeaders[name] = value;
164
+ }
165
+ return requestHeaders;
166
+ }
167
+
158
168
  async function resolvePiAuth(ctx: ExtensionContext, responsesUrl: string, modelOverride?: string): Promise<OpenAIAuth | undefined> {
159
169
  let models: ReturnType<typeof ctx.modelRegistry.getAll>;
160
170
  try {
@@ -407,7 +417,7 @@ export async function searchWithOpenAI(
407
417
 
408
418
  const activityId = activityMonitor.logStart({ type: "api", query });
409
419
  const headers: Record<string, string> = {
410
- ...auth.headers,
420
+ ...toRequestHeaders(auth.headers),
411
421
  Authorization: `Bearer ${auth.apiKey}`,
412
422
  "Content-Type": "application/json",
413
423
  "OpenAI-Beta": "responses=experimental",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-web-access",
3
- "version": "0.18.0",
4
- "description": "Web search, URL fetching, GitHub repo cloning, PDF extraction, YouTube video understanding, and local video analysis for Pi coding agent. Supports OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, SERPdive, Kagi, Ollama, AnySearch, Bright Data SERP, SerpBase, SearXNG, Firecrawl extraction, Exa, Perplexity, and Gemini.",
3
+ "version": "0.22.0",
4
+ "description": "Web search, URL fetching, GitHub repo cloning, PDF extraction, YouTube video understanding, and local video analysis for Pi coding agent. Supports OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Jina, SERPdive, Kagi, Ollama, AnySearch, Bright Data SERP, SerpBase, SearXNG, Firecrawl extraction, Exa, Perplexity, and Gemini.",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "test": "node --test",
@@ -50,7 +50,8 @@
50
50
  "promise.try": "^2.0.1",
51
51
  "turndown": "^7.2.0",
52
52
  "typebox": "^1.1.38",
53
- "unpdf": "^1.6.2"
53
+ "unpdf": "^1.6.2",
54
+ "undici": "^8.9.0"
54
55
  },
55
56
  "peerDependencies": {
56
57
  "@earendil-works/pi-ai": "*",