@herbertgao/pi-extensions 2026.8.2 → 2026.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/README.md +9 -2
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -8
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -7
  4. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +101 -0
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +1 -17
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +5 -3
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{utils/agent-summary.ts → feature/agent-summary/core.ts} +37 -35
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-summary.ts → agent-summary/index.ts} +2 -6
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference.ts → reference/index.ts} +1 -1
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-autocomplete.ts → reference/subagent.ts} +19 -9
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-startup-header.ts → shell/startup-header.ts} +1 -1
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{working-message.ts → shell/working-message.ts} +5 -2
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +32 -28
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +379 -85
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +727 -0
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +65 -775
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +35 -31
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-hover.ts → mouse/hover.ts} +5 -5
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +34 -35
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-layout.ts → mouse/layout.ts} +5 -21
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-packets.ts → mouse/packets.ts} +1 -1
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-scroll.ts → mouse/scroll.ts} +48 -37
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ansi-utils.ts +56 -1
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-renderer.ts +2 -2
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/line-width-safety.ts +1 -1
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +12 -0
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/write-execution.ts +1 -2
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-grouping.ts → tool/grouping.ts} +18 -8
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-result.ts → tool/result.ts} +4 -13
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +0 -27
  31. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  32. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  33. package/node_modules/@herbertgao/pi-subagents/package.json +2 -2
  34. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +1 -0
  35. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +3 -1
  36. package/node_modules/@herbertgao/pi-subagents/src/index.ts +33 -35
  37. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +26 -35
  38. package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +15 -1
  39. package/node_modules/pi-mcp-adapter/CHANGELOG.md +19 -0
  40. package/node_modules/pi-mcp-adapter/README.md +19 -4
  41. package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
  42. package/node_modules/pi-mcp-adapter/commands.ts +12 -2
  43. package/node_modules/pi-mcp-adapter/direct-tools.ts +6 -8
  44. package/node_modules/pi-mcp-adapter/index.ts +15 -3
  45. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +87 -4
  46. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
  47. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +43 -4
  48. package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
  49. package/node_modules/pi-mcp-adapter/package.json +8 -2
  50. package/node_modules/pi-mcp-adapter/proxy-modes.ts +8 -10
  51. package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
  52. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  53. package/node_modules/pi-web-access/CHANGELOG.md +45 -0
  54. package/node_modules/pi-web-access/README.md +104 -29
  55. package/node_modules/pi-web-access/bocha.ts +221 -0
  56. package/node_modules/pi-web-access/curator-page.ts +113 -12
  57. package/node_modules/pi-web-access/curator-server.ts +56 -20
  58. package/node_modules/pi-web-access/datalab-pdf-extract.ts +568 -0
  59. package/node_modules/pi-web-access/duckduckgo.ts +123 -0
  60. package/node_modules/pi-web-access/extract.ts +288 -143
  61. package/node_modules/pi-web-access/feature-config.ts +29 -0
  62. package/node_modules/pi-web-access/gemini-api.ts +4 -0
  63. package/node_modules/pi-web-access/gemini-search.ts +45 -12
  64. package/node_modules/pi-web-access/gemini-web.ts +68 -3
  65. package/node_modules/pi-web-access/index.ts +160 -71
  66. package/node_modules/pi-web-access/jina-search.ts +284 -0
  67. package/node_modules/pi-web-access/kagi.ts +12 -12
  68. package/node_modules/pi-web-access/openai-search.ts +12 -2
  69. package/node_modules/pi-web-access/package.json +4 -3
  70. package/node_modules/pi-web-access/pdf-extract.ts +327 -228
  71. package/node_modules/pi-web-access/storage.ts +440 -2
  72. package/node_modules/pi-web-access/summary-model-scope.ts +1 -1
  73. package/node_modules/pi-web-access/summary-review.ts +4 -2
  74. package/node_modules/pi-web-access/video-extract.ts +10 -8
  75. package/node_modules/pi-web-access/xai-search.ts +12 -2
  76. package/node_modules/pi-web-access/youtube-extract.ts +2 -1
  77. package/node_modules/remote-pi/LICENSE +21 -0
  78. package/node_modules/remote-pi/README.md +675 -0
  79. package/node_modules/remote-pi/dist/actions/handlers.d.ts +122 -0
  80. package/node_modules/remote-pi/dist/actions/handlers.js +160 -0
  81. package/node_modules/remote-pi/dist/actions/handlers.js.map +1 -0
  82. package/node_modules/remote-pi/dist/actions/registry.d.ts +39 -0
  83. package/node_modules/remote-pi/dist/actions/registry.js +58 -0
  84. package/node_modules/remote-pi/dist/actions/registry.js.map +1 -0
  85. package/node_modules/remote-pi/dist/bin/supervisord.d.ts +2 -0
  86. package/node_modules/remote-pi/dist/bin/supervisord.js +86 -0
  87. package/node_modules/remote-pi/dist/bin/supervisord.js.map +1 -0
  88. package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +58 -0
  89. package/node_modules/remote-pi/dist/commands/builtin_mirror.js +71 -0
  90. package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +1 -0
  91. package/node_modules/remote-pi/dist/commands/list_commands.d.ts +60 -0
  92. package/node_modules/remote-pi/dist/commands/list_commands.js +73 -0
  93. package/node_modules/remote-pi/dist/commands/list_commands.js.map +1 -0
  94. package/node_modules/remote-pi/dist/config.d.ts +62 -0
  95. package/node_modules/remote-pi/dist/config.js +115 -0
  96. package/node_modules/remote-pi/dist/config.js.map +1 -0
  97. package/node_modules/remote-pi/dist/daemon/client.d.ts +20 -0
  98. package/node_modules/remote-pi/dist/daemon/client.js +131 -0
  99. package/node_modules/remote-pi/dist/daemon/client.js.map +1 -0
  100. package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +176 -0
  101. package/node_modules/remote-pi/dist/daemon/control_protocol.js +63 -0
  102. package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +1 -0
  103. package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +45 -0
  104. package/node_modules/remote-pi/dist/daemon/cron_log.js +72 -0
  105. package/node_modules/remote-pi/dist/daemon/cron_log.js.map +1 -0
  106. package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +80 -0
  107. package/node_modules/remote-pi/dist/daemon/cron_registry.js +194 -0
  108. package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +1 -0
  109. package/node_modules/remote-pi/dist/daemon/id.d.ts +24 -0
  110. package/node_modules/remote-pi/dist/daemon/id.js +36 -0
  111. package/node_modules/remote-pi/dist/daemon/id.js.map +1 -0
  112. package/node_modules/remote-pi/dist/daemon/install.d.ts +170 -0
  113. package/node_modules/remote-pi/dist/daemon/install.js +547 -0
  114. package/node_modules/remote-pi/dist/daemon/install.js.map +1 -0
  115. package/node_modules/remote-pi/dist/daemon/registry.d.ts +63 -0
  116. package/node_modules/remote-pi/dist/daemon/registry.js +153 -0
  117. package/node_modules/remote-pi/dist/daemon/registry.js.map +1 -0
  118. package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +194 -0
  119. package/node_modules/remote-pi/dist/daemon/rpc_child.js +389 -0
  120. package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +1 -0
  121. package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +93 -0
  122. package/node_modules/remote-pi/dist/daemon/supervisor.js +596 -0
  123. package/node_modules/remote-pi/dist/daemon/supervisor.js.map +1 -0
  124. package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +26 -0
  125. package/node_modules/remote-pi/dist/extension_ui_bridge.js +341 -0
  126. package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +1 -0
  127. package/node_modules/remote-pi/dist/index.d.ts +213 -0
  128. package/node_modules/remote-pi/dist/index.js +4996 -0
  129. package/node_modules/remote-pi/dist/index.js.map +1 -0
  130. package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +10 -0
  131. package/node_modules/remote-pi/dist/mcp/mesh_result.js +42 -0
  132. package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +1 -0
  133. package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +16 -0
  134. package/node_modules/remote-pi/dist/mcp/mesh_server.js +327 -0
  135. package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +1 -0
  136. package/node_modules/remote-pi/dist/mesh/canonical.d.ts +30 -0
  137. package/node_modules/remote-pi/dist/mesh/canonical.js +61 -0
  138. package/node_modules/remote-pi/dist/mesh/canonical.js.map +1 -0
  139. package/node_modules/remote-pi/dist/mesh/client.d.ts +18 -0
  140. package/node_modules/remote-pi/dist/mesh/client.js +125 -0
  141. package/node_modules/remote-pi/dist/mesh/client.js.map +1 -0
  142. package/node_modules/remote-pi/dist/mesh/encoding.d.ts +38 -0
  143. package/node_modules/remote-pi/dist/mesh/encoding.js +216 -0
  144. package/node_modules/remote-pi/dist/mesh/encoding.js.map +1 -0
  145. package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +73 -0
  146. package/node_modules/remote-pi/dist/mesh/self_revoke.js +401 -0
  147. package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +1 -0
  148. package/node_modules/remote-pi/dist/mesh/siblings.d.ts +49 -0
  149. package/node_modules/remote-pi/dist/mesh/siblings.js +159 -0
  150. package/node_modules/remote-pi/dist/mesh/siblings.js.map +1 -0
  151. package/node_modules/remote-pi/dist/mesh/types.d.ts +34 -0
  152. package/node_modules/remote-pi/dist/mesh/types.js +11 -0
  153. package/node_modules/remote-pi/dist/mesh/types.js.map +1 -0
  154. package/node_modules/remote-pi/dist/mesh/verify.d.ts +17 -0
  155. package/node_modules/remote-pi/dist/mesh/verify.js +86 -0
  156. package/node_modules/remote-pi/dist/mesh/verify.js.map +1 -0
  157. package/node_modules/remote-pi/dist/pairing/crypto.d.ts +8 -0
  158. package/node_modules/remote-pi/dist/pairing/crypto.js +22 -0
  159. package/node_modules/remote-pi/dist/pairing/crypto.js.map +1 -0
  160. package/node_modules/remote-pi/dist/pairing/handshake.d.ts +28 -0
  161. package/node_modules/remote-pi/dist/pairing/handshake.js +113 -0
  162. package/node_modules/remote-pi/dist/pairing/handshake.js.map +1 -0
  163. package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +16 -0
  164. package/node_modules/remote-pi/dist/pairing/noise-sha256.js +103 -0
  165. package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +1 -0
  166. package/node_modules/remote-pi/dist/pairing/qr.d.ts +59 -0
  167. package/node_modules/remote-pi/dist/pairing/qr.js +125 -0
  168. package/node_modules/remote-pi/dist/pairing/qr.js.map +1 -0
  169. package/node_modules/remote-pi/dist/pairing/storage.d.ts +120 -0
  170. package/node_modules/remote-pi/dist/pairing/storage.js +604 -0
  171. package/node_modules/remote-pi/dist/pairing/storage.js.map +1 -0
  172. package/node_modules/remote-pi/dist/protocol/codec.d.ts +7 -0
  173. package/node_modules/remote-pi/dist/protocol/codec.js +49 -0
  174. package/node_modules/remote-pi/dist/protocol/codec.js.map +1 -0
  175. package/node_modules/remote-pi/dist/protocol/types.d.ts +393 -0
  176. package/node_modules/remote-pi/dist/protocol/types.js +2 -0
  177. package/node_modules/remote-pi/dist/protocol/types.js.map +1 -0
  178. package/node_modules/remote-pi/dist/rooms.d.ts +29 -0
  179. package/node_modules/remote-pi/dist/rooms.js +57 -0
  180. package/node_modules/remote-pi/dist/rooms.js.map +1 -0
  181. package/node_modules/remote-pi/dist/session/address.d.ts +49 -0
  182. package/node_modules/remote-pi/dist/session/address.js +58 -0
  183. package/node_modules/remote-pi/dist/session/address.js.map +1 -0
  184. package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +55 -0
  185. package/node_modules/remote-pi/dist/session/agent_bridge.js +146 -0
  186. package/node_modules/remote-pi/dist/session/agent_bridge.js.map +1 -0
  187. package/node_modules/remote-pi/dist/session/bridge.d.ts +37 -0
  188. package/node_modules/remote-pi/dist/session/bridge.js +130 -0
  189. package/node_modules/remote-pi/dist/session/bridge.js.map +1 -0
  190. package/node_modules/remote-pi/dist/session/broker.d.ts +189 -0
  191. package/node_modules/remote-pi/dist/session/broker.js +507 -0
  192. package/node_modules/remote-pi/dist/session/broker.js.map +1 -0
  193. package/node_modules/remote-pi/dist/session/broker_remote.d.ts +74 -0
  194. package/node_modules/remote-pi/dist/session/broker_remote.js +583 -0
  195. package/node_modules/remote-pi/dist/session/broker_remote.js.map +1 -0
  196. package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +33 -0
  197. package/node_modules/remote-pi/dist/session/cwd_lock.js +126 -0
  198. package/node_modules/remote-pi/dist/session/cwd_lock.js.map +1 -0
  199. package/node_modules/remote-pi/dist/session/envelope.d.ts +33 -0
  200. package/node_modules/remote-pi/dist/session/envelope.js +117 -0
  201. package/node_modules/remote-pi/dist/session/envelope.js.map +1 -0
  202. package/node_modules/remote-pi/dist/session/global_config.d.ts +33 -0
  203. package/node_modules/remote-pi/dist/session/global_config.js +73 -0
  204. package/node_modules/remote-pi/dist/session/global_config.js.map +1 -0
  205. package/node_modules/remote-pi/dist/session/ipc.d.ts +27 -0
  206. package/node_modules/remote-pi/dist/session/ipc.js +22 -0
  207. package/node_modules/remote-pi/dist/session/ipc.js.map +1 -0
  208. package/node_modules/remote-pi/dist/session/leader_election.d.ts +32 -0
  209. package/node_modules/remote-pi/dist/session/leader_election.js +106 -0
  210. package/node_modules/remote-pi/dist/session/leader_election.js.map +1 -0
  211. package/node_modules/remote-pi/dist/session/local_config.d.ts +55 -0
  212. package/node_modules/remote-pi/dist/session/local_config.js +157 -0
  213. package/node_modules/remote-pi/dist/session/local_config.js.map +1 -0
  214. package/node_modules/remote-pi/dist/session/mesh_message.d.ts +20 -0
  215. package/node_modules/remote-pi/dist/session/mesh_message.js +28 -0
  216. package/node_modules/remote-pi/dist/session/mesh_message.js.map +1 -0
  217. package/node_modules/remote-pi/dist/session/mesh_node.d.ts +116 -0
  218. package/node_modules/remote-pi/dist/session/mesh_node.js +573 -0
  219. package/node_modules/remote-pi/dist/session/mesh_node.js.map +1 -0
  220. package/node_modules/remote-pi/dist/session/peer.d.ts +139 -0
  221. package/node_modules/remote-pi/dist/session/peer.js +451 -0
  222. package/node_modules/remote-pi/dist/session/peer.js.map +1 -0
  223. package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +13 -0
  224. package/node_modules/remote-pi/dist/session/peer_inventory.js +48 -0
  225. package/node_modules/remote-pi/dist/session/peer_inventory.js.map +1 -0
  226. package/node_modules/remote-pi/dist/session/peer_limits.d.ts +9 -0
  227. package/node_modules/remote-pi/dist/session/peer_limits.js +21 -0
  228. package/node_modules/remote-pi/dist/session/peer_limits.js.map +1 -0
  229. package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +39 -0
  230. package/node_modules/remote-pi/dist/session/setup_wizard.js +63 -0
  231. package/node_modules/remote-pi/dist/session/setup_wizard.js.map +1 -0
  232. package/node_modules/remote-pi/dist/session/tool_gate.d.ts +5 -0
  233. package/node_modules/remote-pi/dist/session/tool_gate.js +11 -0
  234. package/node_modules/remote-pi/dist/session/tool_gate.js.map +1 -0
  235. package/node_modules/remote-pi/dist/session/tools.d.ts +24 -0
  236. package/node_modules/remote-pi/dist/session/tools.js +252 -0
  237. package/node_modules/remote-pi/dist/session/tools.js.map +1 -0
  238. package/node_modules/remote-pi/dist/session/wizard.d.ts +13 -0
  239. package/node_modules/remote-pi/dist/session/wizard.js +20 -0
  240. package/node_modules/remote-pi/dist/session/wizard.js.map +1 -0
  241. package/node_modules/remote-pi/dist/settings.d.ts +15 -0
  242. package/node_modules/remote-pi/dist/settings.js +52 -0
  243. package/node_modules/remote-pi/dist/settings.js.map +1 -0
  244. package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +37 -0
  245. package/node_modules/remote-pi/dist/transport/peer_channel.js +98 -0
  246. package/node_modules/remote-pi/dist/transport/peer_channel.js.map +1 -0
  247. package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +29 -0
  248. package/node_modules/remote-pi/dist/transport/pi_forward_client.js +62 -0
  249. package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +1 -0
  250. package/node_modules/remote-pi/dist/transport/relay_client.d.ts +91 -0
  251. package/node_modules/remote-pi/dist/transport/relay_client.js +206 -0
  252. package/node_modules/remote-pi/dist/transport/relay_client.js.map +1 -0
  253. package/node_modules/remote-pi/dist/ui/footer.d.ts +32 -0
  254. package/node_modules/remote-pi/dist/ui/footer.js +34 -0
  255. package/node_modules/remote-pi/dist/ui/footer.js.map +1 -0
  256. package/node_modules/remote-pi/docs/daemon.md +289 -0
  257. package/node_modules/remote-pi/package.json +88 -0
  258. package/node_modules/remote-pi/service-templates/launchd.plist.template +35 -0
  259. package/node_modules/remote-pi/service-templates/systemd.service.template +19 -0
  260. package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +10 -0
  261. package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +38 -0
  262. package/node_modules/remote-pi/skills/agent-network/SKILL.md +310 -0
  263. package/package.json +19 -9
  264. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool-diff/write-display-utils.ts +0 -29
  265. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference-core.ts → reference/session.ts} +0 -0
  266. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-aliases.ts → shell/aliases.ts} +0 -0
  267. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ATTRIBUTION.md +0 -0
  268. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-presentation.ts +0 -0
  269. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/index.ts +0 -0
  270. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/render-utils.ts +0 -0
  271. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/shiki-highlight.ts +0 -0
  272. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/types.ts +0 -0
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * PDF Content Extractor
3
3
  *
4
- * Uses Gemini for structured PDF-to-Markdown conversion when configured,
5
- * with unpdf as the deterministic local fallback.
4
+ * Converts PDFs to Markdown. The `auto` provider chain runs Datalab
5
+ * (deterministic, layout-aware) first, then Gemini API, with unpdf as the
6
+ * deterministic local fallback; the chain can also be pinned with
7
+ * `pdf.provider`.
6
8
  */
7
9
 
8
10
  import { existsSync, readFileSync } from "node:fs";
@@ -10,288 +12,385 @@ import { writeFile, mkdir } from "node:fs/promises";
10
12
  import { join, basename } from "node:path";
11
13
  import { tmpdir } from "node:os";
12
14
  import { CredentialResolutionError } from "./credential-source.ts";
15
+ import {
16
+ DATALAB_MODE_VALUES,
17
+ DEFAULT_DATALAB_TIMEOUT_MS,
18
+ isDatalabApiAvailable,
19
+ normalizeDatalabMode,
20
+ extractPDFViaDatalab,
21
+ type DatalabMode,
22
+ } from "./datalab-pdf-extract.ts";
13
23
  import { isGeminiApiAvailable } from "./gemini-api.ts";
14
24
  import { extractPDFViaGemini } from "./gemini-pdf-extract.ts";
15
25
  import { getWebSearchConfigPath } from "./utils.ts";
16
26
 
17
27
  export interface PDFExtractResult {
18
- title: string;
19
- pages: number;
20
- chars: number;
21
- outputPath: string;
28
+ title: string;
29
+ pages: number;
30
+ chars: number;
31
+ outputPath: string;
22
32
  }
23
33
 
24
34
  export interface PDFExtractOptions {
25
- maxPages?: number;
26
- outputDir?: string;
27
- filename?: string;
28
- signal?: AbortSignal;
29
- geminiTimeoutMs?: number;
35
+ maxPages?: number;
36
+ outputDir?: string;
37
+ filename?: string;
38
+ signal?: AbortSignal;
39
+ geminiTimeoutMs?: number;
30
40
  }
31
41
 
42
+ export type PDFProvider = "auto" | "gemini" | "datalab" | "unpdf";
43
+
44
+ export const PDF_PROVIDER_VALUES = new Set<PDFProvider>([
45
+ "auto",
46
+ "gemini",
47
+ "datalab",
48
+ "unpdf",
49
+ ]);
50
+
32
51
  export interface PDFConfig {
33
- maxSizeMB: number;
52
+ enabled: boolean;
53
+ maxSizeMB: number;
54
+ provider: PDFProvider;
55
+ datalabMode: DatalabMode;
56
+ datalabTimeoutMs: number;
34
57
  }
35
58
 
36
59
  export const DEFAULT_PDF_MAX_SIZE_MB = 20;
37
60
  export const MAX_PDF_MAX_SIZE_MB = 50;
61
+ export const MAX_DATALAB_TIMEOUT_MS = 300_000;
38
62
  const DEFAULT_MAX_PAGES = 100;
39
63
  const DEFAULT_OUTPUT_DIR = join(tmpdir(), "pi-web-pdf");
40
64
  const CONFIG_PATH = getWebSearchConfigPath();
41
65
  const PAGE_MARKER_PATTERN = /^<!-- Page (\d+) -->$/gm;
42
66
 
43
- let cachedPDFConfig: PDFConfig | null = null;
44
-
45
67
  export function loadPDFConfig(): PDFConfig {
46
- if (cachedPDFConfig) return { ...cachedPDFConfig };
47
- if (!existsSync(CONFIG_PATH)) {
48
- cachedPDFConfig = { maxSizeMB: DEFAULT_PDF_MAX_SIZE_MB };
49
- return { ...cachedPDFConfig };
50
- }
51
-
52
- const rawText = readFileSync(CONFIG_PATH, "utf-8");
53
- let raw: unknown;
54
- try {
55
- raw = JSON.parse(rawText) as unknown;
56
- } catch (err) {
57
- const message = err instanceof Error ? err.message : String(err);
58
- throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
59
- }
60
-
61
- const root = raw && typeof raw === "object" ? raw as Record<string, unknown> : {};
62
- const pdf = root.pdf && typeof root.pdf === "object"
63
- ? root.pdf as Record<string, unknown>
64
- : {};
65
- const configured = pdf.maxSizeMB;
66
- const normalized = typeof configured === "number" && Number.isFinite(configured) && configured > 0
67
- ? Math.min(configured, MAX_PDF_MAX_SIZE_MB)
68
- : DEFAULT_PDF_MAX_SIZE_MB;
69
-
70
- cachedPDFConfig = { maxSizeMB: normalized };
71
- return { ...cachedPDFConfig };
68
+ if (!existsSync(CONFIG_PATH)) {
69
+ return {
70
+ enabled: true,
71
+ maxSizeMB: DEFAULT_PDF_MAX_SIZE_MB,
72
+ provider: "auto",
73
+ datalabMode: normalizeDatalabMode(process.env.DATALAB_MODE),
74
+ datalabTimeoutMs: DEFAULT_DATALAB_TIMEOUT_MS,
75
+ };
76
+ }
77
+
78
+ const rawText = readFileSync(CONFIG_PATH, "utf-8");
79
+ let raw: unknown;
80
+ try {
81
+ raw = JSON.parse(rawText) as unknown;
82
+ } catch (err) {
83
+ const message = err instanceof Error ? err.message : String(err);
84
+ throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
85
+ }
86
+
87
+ const root =
88
+ raw && typeof raw === "object" ? (raw as Record<string, unknown>) : {};
89
+ const pdf =
90
+ root.pdf && typeof root.pdf === "object"
91
+ ? (root.pdf as Record<string, unknown>)
92
+ : {};
93
+ const enabled = pdf.enabled !== false;
94
+ const configured = pdf.maxSizeMB;
95
+ const normalized =
96
+ typeof configured === "number" &&
97
+ Number.isFinite(configured) &&
98
+ configured > 0
99
+ ? Math.min(configured, MAX_PDF_MAX_SIZE_MB)
100
+ : DEFAULT_PDF_MAX_SIZE_MB;
101
+
102
+ const provider =
103
+ typeof pdf.provider === "string" &&
104
+ PDF_PROVIDER_VALUES.has(pdf.provider as PDFProvider)
105
+ ? (pdf.provider as PDFProvider)
106
+ : "auto";
107
+ const datalabMode =
108
+ typeof pdf.datalabMode === "string" &&
109
+ DATALAB_MODE_VALUES.has(pdf.datalabMode as DatalabMode)
110
+ ? (pdf.datalabMode as DatalabMode)
111
+ : normalizeDatalabMode(process.env.DATALAB_MODE);
112
+ const configuredTimeout = pdf.datalabTimeoutMs;
113
+ const datalabTimeoutMs =
114
+ typeof configuredTimeout === "number" &&
115
+ Number.isFinite(configuredTimeout) &&
116
+ configuredTimeout > 0
117
+ ? Math.min(configuredTimeout, MAX_DATALAB_TIMEOUT_MS)
118
+ : DEFAULT_DATALAB_TIMEOUT_MS;
119
+
120
+ return {
121
+ enabled,
122
+ maxSizeMB: normalized,
123
+ provider,
124
+ datalabMode,
125
+ datalabTimeoutMs,
126
+ };
72
127
  }
73
128
 
74
129
  async function getUnpdf() {
75
- if (typeof (Promise as PromiseConstructor & { try?: unknown }).try !== "function") {
76
- const { default: promiseTry } = await import("promise.try");
77
- promiseTry.shim();
78
- }
79
-
80
- const [unpdf, pdfjs] = await Promise.all([
81
- import("unpdf"),
82
- import("unpdf/pdfjs"),
83
- ]);
84
- const { VerbosityLevel } = pdfjs as typeof pdfjs & { VerbosityLevel: { ERRORS: number } };
85
-
86
- return { getDocumentProxy: unpdf.getDocumentProxy, VerbosityLevel };
130
+ if (
131
+ typeof (Promise as PromiseConstructor & { try?: unknown }).try !==
132
+ "function"
133
+ ) {
134
+ const { default: promiseTry } = await import("promise.try");
135
+ promiseTry.shim();
136
+ }
137
+
138
+ const [unpdf, pdfjs] = await Promise.all([
139
+ import("unpdf"),
140
+ import("unpdf/pdfjs"),
141
+ ]);
142
+ const { VerbosityLevel } = pdfjs as typeof pdfjs & {
143
+ VerbosityLevel: { ERRORS: number };
144
+ };
145
+
146
+ return { getDocumentProxy: unpdf.getDocumentProxy, VerbosityLevel };
87
147
  }
88
148
 
89
149
  /**
90
150
  * Extract text from a PDF buffer and save it to a Markdown file.
91
151
  */
92
152
  export async function extractPDFToMarkdown(
93
- buffer: ArrayBuffer,
94
- url: string,
95
- options: PDFExtractOptions = {}
153
+ buffer: ArrayBuffer,
154
+ url: string,
155
+ options: PDFExtractOptions = {},
96
156
  ): Promise<PDFExtractResult> {
97
- const {
98
- maxPages = DEFAULT_MAX_PAGES,
99
- outputDir = DEFAULT_OUTPUT_DIR,
100
- filename,
101
- signal,
102
- geminiTimeoutMs,
103
- } = options;
104
-
105
- const safeMaxPages = Number.isFinite(maxPages)
106
- ? Math.max(1, Math.floor(maxPages))
107
- : DEFAULT_MAX_PAGES;
108
- const urlTitle = extractTitleFromURL(url);
109
-
110
- try {
111
- if (isGeminiApiAvailable()) {
112
- const markdownBody = await extractPDFViaGemini(buffer, {
113
- maxPages: safeMaxPages,
114
- title: urlTitle,
115
- ...(signal ? { signal } : {}),
116
- ...(geminiTimeoutMs !== undefined ? { timeoutMs: geminiTimeoutMs } : {}),
117
- });
118
- return writeMarkdownResult({
119
- markdownBody,
120
- title: urlTitle,
121
- pages: countPageMarkers(markdownBody),
122
- outputDir,
123
- filename,
124
- url,
125
- });
126
- }
127
- } catch (err) {
128
- if (shouldRethrowGeminiError(err, signal)) throw err;
129
- }
130
-
131
- const { getDocumentProxy, VerbosityLevel } = await getUnpdf();
132
- const pdf = await getDocumentProxy(new Uint8Array(buffer), {
133
- verbosity: VerbosityLevel.ERRORS,
134
- });
135
- const metadata = await pdf.getMetadata();
136
- const metadataInfo = metadata.info && typeof metadata.info === "object"
137
- ? metadata.info as Record<string, unknown>
138
- : null;
139
-
140
- const metaTitle = typeof metadataInfo?.Title === "string" ? metadataInfo.Title : undefined;
141
- const metaAuthor = typeof metadataInfo?.Author === "string" ? metadataInfo.Author : undefined;
142
- const title = metaTitle?.trim() || urlTitle;
143
- const pagesToExtract = Math.min(pdf.numPages, safeMaxPages);
144
- const truncated = pdf.numPages > safeMaxPages;
145
- const pages: { pageNum: number; text: string }[] = [];
146
-
147
- for (let i = 1; i <= pagesToExtract; i++) {
148
- const page = await pdf.getPage(i);
149
- const textContent = await page.getTextContent();
150
- const pageText = textContent.items
151
- .map((item: unknown) => {
152
- const textItem = item as { str?: string };
153
- return textItem.str || "";
154
- })
155
- .join(" ")
156
- .replace(/\s+/g, " ")
157
- .trim();
158
-
159
- if (pageText) {
160
- pages.push({ pageNum: i, text: pageText });
161
- }
162
- }
163
-
164
- const bodyLines: string[] = [];
165
- for (let i = 0; i < pages.length; i++) {
166
- if (i > 0) {
167
- bodyLines.push("");
168
- bodyLines.push(`<!-- Page ${pages[i].pageNum} -->`);
169
- bodyLines.push("");
170
- }
171
- bodyLines.push(pages[i].text);
172
- }
173
-
174
- return writeMarkdownResult({
175
- markdownBody: bodyLines.join("\n"),
176
- title,
177
- pages: pdf.numPages,
178
- outputDir,
179
- filename,
180
- url,
181
- metaAuthor,
182
- truncated,
183
- pagesToExtract,
184
- });
157
+ const {
158
+ maxPages = DEFAULT_MAX_PAGES,
159
+ outputDir = DEFAULT_OUTPUT_DIR,
160
+ filename,
161
+ signal,
162
+ geminiTimeoutMs,
163
+ } = options;
164
+
165
+ const safeMaxPages = Number.isFinite(maxPages)
166
+ ? Math.max(1, Math.floor(maxPages))
167
+ : DEFAULT_MAX_PAGES;
168
+ const urlTitle = extractTitleFromURL(url);
169
+ const pdfConfig = loadPDFConfig();
170
+ const provider = pdfConfig.provider;
171
+
172
+ if (provider === "auto" || provider === "datalab") {
173
+ try {
174
+ if (isDatalabApiAvailable()) {
175
+ const result = await extractPDFViaDatalab(buffer, {
176
+ maxPages: safeMaxPages,
177
+ title: urlTitle,
178
+ mode: pdfConfig.datalabMode,
179
+ timeoutMs: pdfConfig.datalabTimeoutMs,
180
+ ...(signal ? { signal } : {}),
181
+ });
182
+ return writeMarkdownResult({
183
+ markdownBody: result.markdown,
184
+ title: urlTitle,
185
+ pages: result.pages,
186
+ outputDir,
187
+ filename,
188
+ url,
189
+ });
190
+ }
191
+ } catch (err) {
192
+ if (shouldRethrowExtractionError(err, signal)) throw err;
193
+ }
194
+ }
195
+
196
+ if (provider === "auto" || provider === "gemini") {
197
+ try {
198
+ if (isGeminiApiAvailable()) {
199
+ const markdownBody = await extractPDFViaGemini(buffer, {
200
+ maxPages: safeMaxPages,
201
+ title: urlTitle,
202
+ ...(signal ? { signal } : {}),
203
+ ...(geminiTimeoutMs !== undefined
204
+ ? { timeoutMs: geminiTimeoutMs }
205
+ : {}),
206
+ });
207
+ return writeMarkdownResult({
208
+ markdownBody,
209
+ title: urlTitle,
210
+ pages: countPageMarkers(markdownBody),
211
+ outputDir,
212
+ filename,
213
+ url,
214
+ });
215
+ }
216
+ } catch (err) {
217
+ if (shouldRethrowExtractionError(err, signal)) throw err;
218
+ }
219
+ }
220
+
221
+ const { getDocumentProxy, VerbosityLevel } = await getUnpdf();
222
+ const pdf = await getDocumentProxy(new Uint8Array(buffer), {
223
+ verbosity: VerbosityLevel.ERRORS,
224
+ });
225
+ const metadata = await pdf.getMetadata();
226
+ const metadataInfo =
227
+ metadata.info && typeof metadata.info === "object"
228
+ ? (metadata.info as Record<string, unknown>)
229
+ : null;
230
+
231
+ const metaTitle =
232
+ typeof metadataInfo?.Title === "string" ? metadataInfo.Title : undefined;
233
+ const metaAuthor =
234
+ typeof metadataInfo?.Author === "string" ? metadataInfo.Author : undefined;
235
+ const title = metaTitle?.trim() || urlTitle;
236
+ const pagesToExtract = Math.min(pdf.numPages, safeMaxPages);
237
+ const truncated = pdf.numPages > safeMaxPages;
238
+ const pages: { pageNum: number; text: string }[] = [];
239
+
240
+ for (let i = 1; i <= pagesToExtract; i++) {
241
+ const page = await pdf.getPage(i);
242
+ const textContent = await page.getTextContent();
243
+ const pageText = textContent.items
244
+ .map((item: unknown) => {
245
+ const textItem = item as { str?: string };
246
+ return textItem.str || "";
247
+ })
248
+ .join(" ")
249
+ .replace(/\s+/g, " ")
250
+ .trim();
251
+
252
+ if (pageText) {
253
+ pages.push({ pageNum: i, text: pageText });
254
+ }
255
+ }
256
+
257
+ const bodyLines: string[] = [];
258
+ for (let i = 0; i < pages.length; i++) {
259
+ if (i > 0) {
260
+ bodyLines.push("");
261
+ bodyLines.push(`<!-- Page ${pages[i].pageNum} -->`);
262
+ bodyLines.push("");
263
+ }
264
+ bodyLines.push(pages[i].text);
265
+ }
266
+
267
+ return writeMarkdownResult({
268
+ markdownBody: bodyLines.join("\n"),
269
+ title,
270
+ pages: pdf.numPages,
271
+ outputDir,
272
+ filename,
273
+ url,
274
+ metaAuthor,
275
+ truncated,
276
+ pagesToExtract,
277
+ });
185
278
  }
186
279
 
187
280
  async function writeMarkdownResult(options: {
188
- markdownBody: string;
189
- title: string;
190
- pages: number;
191
- outputDir: string;
192
- filename?: string;
193
- url: string;
194
- metaAuthor?: string;
195
- truncated?: boolean;
196
- pagesToExtract?: number;
281
+ markdownBody: string;
282
+ title: string;
283
+ pages: number;
284
+ outputDir: string;
285
+ filename?: string;
286
+ url: string;
287
+ metaAuthor?: string;
288
+ truncated?: boolean;
289
+ pagesToExtract?: number;
197
290
  }): Promise<PDFExtractResult> {
198
- const lines: string[] = [];
199
- lines.push(`# ${options.title}`);
200
- lines.push("");
201
- lines.push(`> Source: ${options.url}`);
202
- lines.push(`> Pages: ${options.pages}${options.truncated ? ` (extracted first ${options.pagesToExtract})` : ""}`);
203
- if (options.metaAuthor) lines.push(`> Author: ${options.metaAuthor}`);
204
- lines.push("");
205
- lines.push("---");
206
- lines.push("");
207
- if (options.markdownBody) lines.push(options.markdownBody);
208
-
209
- if (options.truncated) {
210
- lines.push("");
211
- lines.push("---");
212
- lines.push("");
213
- lines.push(`*[Truncated: Only first ${options.pagesToExtract} of ${options.pages} pages extracted]*`);
214
- }
215
-
216
- const content = lines.join("\n");
217
- const outputFilename = options.filename || sanitizeFilename(options.title) + ".md";
218
- const outputPath = join(options.outputDir, outputFilename);
219
-
220
- await mkdir(options.outputDir, { recursive: true });
221
- await writeFile(outputPath, content, "utf-8");
222
-
223
- return {
224
- title: options.title,
225
- pages: options.pages,
226
- chars: content.length,
227
- outputPath,
228
- };
291
+ const lines: string[] = [];
292
+ lines.push(`# ${options.title}`);
293
+ lines.push("");
294
+ lines.push(`> Source: ${options.url}`);
295
+ lines.push(
296
+ `> Pages: ${options.pages}${options.truncated ? ` (extracted first ${options.pagesToExtract})` : ""}`,
297
+ );
298
+ if (options.metaAuthor) lines.push(`> Author: ${options.metaAuthor}`);
299
+ lines.push("");
300
+ lines.push("---");
301
+ lines.push("");
302
+ if (options.markdownBody) lines.push(options.markdownBody);
303
+
304
+ if (options.truncated) {
305
+ lines.push("");
306
+ lines.push("---");
307
+ lines.push("");
308
+ lines.push(
309
+ `*[Truncated: Only first ${options.pagesToExtract} of ${options.pages} pages extracted]*`,
310
+ );
311
+ }
312
+
313
+ const content = lines.join("\n");
314
+ const outputFilename =
315
+ options.filename || sanitizeFilename(options.title) + ".md";
316
+ const outputPath = join(options.outputDir, outputFilename);
317
+
318
+ await mkdir(options.outputDir, { recursive: true });
319
+ await writeFile(outputPath, content, "utf-8");
320
+
321
+ return {
322
+ title: options.title,
323
+ pages: options.pages,
324
+ chars: content.length,
325
+ outputPath,
326
+ };
229
327
  }
230
328
 
231
329
  function countPageMarkers(markdown: string): number {
232
- return [...markdown.matchAll(PAGE_MARKER_PATTERN)].length;
330
+ return [...markdown.matchAll(PAGE_MARKER_PATTERN)].length;
233
331
  }
234
332
 
235
- function shouldRethrowGeminiError(err: unknown, signal?: AbortSignal): boolean {
236
- if (signal?.aborted) return true;
237
- if (err instanceof CredentialResolutionError) return true;
238
- const message = err instanceof Error ? err.message : String(err);
239
- return message.startsWith("Failed to parse ");
333
+ function shouldRethrowExtractionError(
334
+ err: unknown,
335
+ signal?: AbortSignal,
336
+ ): boolean {
337
+ if (signal?.aborted) return true;
338
+ if (err instanceof CredentialResolutionError) return true;
339
+ const message = err instanceof Error ? err.message : String(err);
340
+ return message.startsWith("Failed to parse ");
240
341
  }
241
342
 
242
343
  /**
243
344
  * Extract a reasonable title from URL
244
345
  */
245
346
  function extractTitleFromURL(url: string): string {
246
- try {
247
- const urlObj = new URL(url);
248
- const pathname = urlObj.pathname;
249
-
250
- let filename = basename(pathname, ".pdf");
251
-
252
- if (urlObj.hostname.includes("arxiv.org")) {
253
- const match = pathname.match(/\/(?:pdf|abs)\/(\d+\.\d+)/);
254
- if (match) {
255
- filename = `arxiv-${match[1]}`;
256
- }
257
- }
258
-
259
- filename = filename
260
- .replace(/[_-]+/g, " ")
261
- .replace(/\s+/g, " ")
262
- .trim();
263
-
264
- return filename || "document";
265
- } catch {
266
- return "document";
267
- }
347
+ try {
348
+ const urlObj = new URL(url);
349
+ const pathname = urlObj.pathname;
350
+
351
+ let filename = basename(pathname, ".pdf");
352
+
353
+ if (urlObj.hostname.includes("arxiv.org")) {
354
+ const match = pathname.match(/\/(?:pdf|abs)\/(\d+\.\d+)/);
355
+ if (match) {
356
+ filename = `arxiv-${match[1]}`;
357
+ }
358
+ }
359
+
360
+ filename = filename.replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
361
+
362
+ return filename || "document";
363
+ } catch {
364
+ return "document";
365
+ }
268
366
  }
269
367
 
270
368
  /**
271
369
  * Sanitize string for use as filename
272
370
  */
273
371
  function sanitizeFilename(name: string): string {
274
- return name
275
- .toLowerCase()
276
- .replace(/[^a-z0-9\s-]/g, "")
277
- .replace(/\s+/g, "-")
278
- .replace(/-+/g, "-")
279
- .slice(0, 100)
280
- .replace(/^-|-$/g, "")
281
- || "document";
372
+ return (
373
+ name
374
+ .toLowerCase()
375
+ .replace(/[^a-z0-9\s-]/g, "")
376
+ .replace(/\s+/g, "-")
377
+ .replace(/-+/g, "-")
378
+ .slice(0, 100)
379
+ .replace(/^-|-$/g, "") || "document"
380
+ );
282
381
  }
283
382
 
284
383
  /**
285
384
  * Check if URL or content-type indicates a PDF
286
385
  */
287
386
  export function isPDF(url: string, contentType?: string): boolean {
288
- if (contentType?.includes("application/pdf")) {
289
- return true;
290
- }
291
- try {
292
- const urlObj = new URL(url);
293
- return urlObj.pathname.toLowerCase().endsWith(".pdf");
294
- } catch {
295
- return false;
296
- }
387
+ if (contentType?.includes("application/pdf")) {
388
+ return true;
389
+ }
390
+ try {
391
+ const urlObj = new URL(url);
392
+ return urlObj.pathname.toLowerCase().endsWith(".pdf");
393
+ } catch {
394
+ return false;
395
+ }
297
396
  }