@ashx-j/lunr 0.2.26 → 0.2.28

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 (697) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/LICENSE +22 -0
  3. package/dist/builtin-extensions/ashxj-thinking.d.ts +1 -1
  4. package/dist/builtin-extensions/ashxj-thinking.d.ts.map +1 -1
  5. package/dist/builtin-extensions/ashxj-thinking.js +1 -1
  6. package/dist/builtin-extensions/ashxj-thinking.js.map +1 -1
  7. package/dist/builtin-extensions/ashxj-tui.d.ts +11 -1
  8. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  9. package/dist/builtin-extensions/ashxj-tui.js +6 -10
  10. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  11. package/dist/builtin-extensions/lunr-cron.d.ts +4 -5
  12. package/dist/builtin-extensions/lunr-cron.d.ts.map +1 -1
  13. package/dist/builtin-extensions/lunr-cron.js +94 -108
  14. package/dist/builtin-extensions/lunr-cron.js.map +1 -1
  15. package/dist/builtin-extensions/lunr-local-providers/local-servers.d.ts.map +1 -1
  16. package/dist/builtin-extensions/lunr-local-providers/local-servers.js +3 -1
  17. package/dist/builtin-extensions/lunr-local-providers/local-servers.js.map +1 -1
  18. package/dist/builtin-extensions/narumiruna-pi-goal/src/accounting.d.ts.map +1 -1
  19. package/dist/builtin-extensions/narumiruna-pi-goal/src/accounting.js +5 -2
  20. package/dist/builtin-extensions/narumiruna-pi-goal/src/accounting.js.map +1 -1
  21. package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.d.ts.map +1 -1
  22. package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.js +2 -2
  23. package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.js.map +1 -1
  24. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.d.ts.map +1 -1
  25. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js +1 -1
  26. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js.map +1 -1
  27. package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.d.ts.map +1 -1
  28. package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.js +1 -1
  29. package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.js.map +1 -1
  30. package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
  31. package/dist/builtin-extensions/pi-intercom/index.js +2 -2
  32. package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
  33. package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.d.ts +1 -1
  34. package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.d.ts.map +1 -1
  35. package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.js +1 -1
  36. package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.js.map +1 -1
  37. package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts.map +1 -1
  38. package/dist/builtin-extensions/pi-lsp-extension/src/index.js +1 -15
  39. package/dist/builtin-extensions/pi-lsp-extension/src/index.js.map +1 -1
  40. package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.d.ts +6 -0
  41. package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.d.ts.map +1 -1
  42. package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.js +187 -132
  43. package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.js.map +1 -1
  44. package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.d.ts +8 -0
  45. package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.d.ts.map +1 -1
  46. package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.js +142 -112
  47. package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.js.map +1 -1
  48. package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.d.ts +12 -1
  49. package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.d.ts.map +1 -1
  50. package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.js +14 -7
  51. package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.js.map +1 -1
  52. package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.d.ts +11 -3
  53. package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.d.ts.map +1 -1
  54. package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.js +67 -41
  55. package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.js.map +1 -1
  56. package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.d.ts +4 -2
  57. package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.d.ts.map +1 -1
  58. package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.js +3 -0
  59. package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.js.map +1 -1
  60. package/dist/builtin-extensions/pi-mcp-adapter/commands.d.ts +2 -1
  61. package/dist/builtin-extensions/pi-mcp-adapter/commands.d.ts.map +1 -1
  62. package/dist/builtin-extensions/pi-mcp-adapter/commands.js +6 -6
  63. package/dist/builtin-extensions/pi-mcp-adapter/commands.js.map +1 -1
  64. package/dist/builtin-extensions/pi-mcp-adapter/config.d.ts +1 -1
  65. package/dist/builtin-extensions/pi-mcp-adapter/config.d.ts.map +1 -1
  66. package/dist/builtin-extensions/pi-mcp-adapter/config.js +11 -5
  67. package/dist/builtin-extensions/pi-mcp-adapter/config.js.map +1 -1
  68. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts.map +1 -1
  69. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js +2 -2
  70. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js.map +1 -1
  71. package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.d.ts.map +1 -1
  72. package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.js +1 -1
  73. package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.js.map +1 -1
  74. package/dist/builtin-extensions/pi-mcp-adapter/index.d.ts.map +1 -1
  75. package/dist/builtin-extensions/pi-mcp-adapter/index.js +48 -40
  76. package/dist/builtin-extensions/pi-mcp-adapter/index.js.map +1 -1
  77. package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts.map +1 -1
  78. package/dist/builtin-extensions/pi-mcp-adapter/init.js +3 -1
  79. package/dist/builtin-extensions/pi-mcp-adapter/init.js.map +1 -1
  80. package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.d.ts +12 -40
  81. package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.d.ts.map +1 -1
  82. package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.js +166 -235
  83. package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.js.map +1 -1
  84. package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.d.ts +5 -0
  85. package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.d.ts.map +1 -1
  86. package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.js +43 -13
  87. package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.js.map +1 -1
  88. package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.d.ts +14 -3
  89. package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.d.ts.map +1 -1
  90. package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.js +73 -21
  91. package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.js.map +1 -1
  92. package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.d.ts.map +1 -1
  93. package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.js +4 -4
  94. package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.js.map +1 -1
  95. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts.map +1 -1
  96. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js +2 -2
  97. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js.map +1 -1
  98. package/dist/builtin-extensions/pi-mcp-adapter/state.d.ts +2 -0
  99. package/dist/builtin-extensions/pi-mcp-adapter/state.d.ts.map +1 -1
  100. package/dist/builtin-extensions/pi-mcp-adapter/state.js.map +1 -1
  101. package/dist/builtin-extensions/pi-ollama-cloud/index.d.ts +1 -1
  102. package/dist/builtin-extensions/pi-ollama-cloud/index.d.ts.map +1 -1
  103. package/dist/builtin-extensions/pi-ollama-cloud/index.js +1 -1
  104. package/dist/builtin-extensions/pi-ollama-cloud/index.js.map +1 -1
  105. package/dist/builtin-extensions/pi-ollama-cloud/models.d.ts +11 -5
  106. package/dist/builtin-extensions/pi-ollama-cloud/models.d.ts.map +1 -1
  107. package/dist/builtin-extensions/pi-ollama-cloud/models.js +12 -32
  108. package/dist/builtin-extensions/pi-ollama-cloud/models.js.map +1 -1
  109. package/dist/builtin-extensions/pi-prompt-template-model/index.d.ts.map +1 -1
  110. package/dist/builtin-extensions/pi-prompt-template-model/index.js +5 -3
  111. package/dist/builtin-extensions/pi-prompt-template-model/index.js.map +1 -1
  112. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts +2 -1
  113. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts.map +1 -1
  114. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js +21 -12
  115. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js.map +1 -1
  116. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts.map +1 -1
  117. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js +7 -24
  118. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js.map +1 -1
  119. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  120. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +39 -77
  121. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  122. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-root-attachment.d.ts +4 -1
  123. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-root-attachment.d.ts.map +1 -1
  124. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-root-attachment.js +2 -0
  125. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-root-attachment.js.map +1 -1
  126. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +6 -1
  127. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
  128. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +17 -31
  129. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
  130. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
  131. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +7 -2
  132. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
  133. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts +5 -1
  134. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
  135. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +78 -42
  136. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
  137. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  138. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +8 -1
  139. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  140. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts +0 -3
  141. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  142. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +134 -28
  143. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  144. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  145. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +26 -5
  146. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  147. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +1 -1
  148. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
  149. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +1 -1
  150. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
  151. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +7 -8
  152. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  153. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js +60 -32
  154. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  155. package/dist/builtin-extensions/pi-subagents/src/shared/session-tokens.d.ts +7 -1
  156. package/dist/builtin-extensions/pi-subagents/src/shared/session-tokens.d.ts.map +1 -1
  157. package/dist/builtin-extensions/pi-subagents/src/shared/session-tokens.js +70 -38
  158. package/dist/builtin-extensions/pi-subagents/src/shared/session-tokens.js.map +1 -1
  159. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +9 -0
  160. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  161. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  162. package/dist/builtin-extensions/pi-subagents/src/shared/utils.d.ts +1 -1
  163. package/dist/builtin-extensions/pi-subagents/src/shared/utils.d.ts.map +1 -1
  164. package/dist/builtin-extensions/pi-subagents/src/shared/utils.js +15 -5
  165. package/dist/builtin-extensions/pi-subagents/src/shared/utils.js.map +1 -1
  166. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
  167. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +4 -3
  168. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
  169. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  170. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +13 -62
  171. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  172. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +1 -1
  173. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  174. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +18 -9
  175. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  176. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts.map +1 -1
  177. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js +3 -3
  178. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js.map +1 -1
  179. package/dist/builtin-extensions/pi-tps.d.ts.map +1 -1
  180. package/dist/builtin-extensions/pi-tps.js +28 -17
  181. package/dist/builtin-extensions/pi-tps.js.map +1 -1
  182. package/dist/builtin-extensions/pi-web-access/activity.d.ts +1 -0
  183. package/dist/builtin-extensions/pi-web-access/activity.d.ts.map +1 -1
  184. package/dist/builtin-extensions/pi-web-access/activity.js +27 -5
  185. package/dist/builtin-extensions/pi-web-access/activity.js.map +1 -1
  186. package/dist/builtin-extensions/pi-web-access/bounded-body.d.ts +3 -0
  187. package/dist/builtin-extensions/pi-web-access/bounded-body.d.ts.map +1 -0
  188. package/dist/builtin-extensions/pi-web-access/bounded-body.js +43 -0
  189. package/dist/builtin-extensions/pi-web-access/bounded-body.js.map +1 -0
  190. package/dist/builtin-extensions/pi-web-access/content-page.d.ts +24 -0
  191. package/dist/builtin-extensions/pi-web-access/content-page.d.ts.map +1 -0
  192. package/dist/builtin-extensions/pi-web-access/content-page.js +57 -0
  193. package/dist/builtin-extensions/pi-web-access/content-page.js.map +1 -0
  194. package/dist/builtin-extensions/pi-web-access/extract.d.ts.map +1 -1
  195. package/dist/builtin-extensions/pi-web-access/extract.js +7 -2
  196. package/dist/builtin-extensions/pi-web-access/extract.js.map +1 -1
  197. package/dist/builtin-extensions/pi-web-access/github-extract.d.ts +0 -1
  198. package/dist/builtin-extensions/pi-web-access/github-extract.d.ts.map +1 -1
  199. package/dist/builtin-extensions/pi-web-access/github-extract.js +147 -36
  200. package/dist/builtin-extensions/pi-web-access/github-extract.js.map +1 -1
  201. package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
  202. package/dist/builtin-extensions/pi-web-access/index.js +48 -73
  203. package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
  204. package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts +12 -4
  205. package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts.map +1 -1
  206. package/dist/builtin-extensions/pi-web-access/session-cleanup.js +35 -12
  207. package/dist/builtin-extensions/pi-web-access/session-cleanup.js.map +1 -1
  208. package/dist/builtin-extensions/pi-web-access/storage.d.ts +9 -6
  209. package/dist/builtin-extensions/pi-web-access/storage.d.ts.map +1 -1
  210. package/dist/builtin-extensions/pi-web-access/storage.js +36 -24
  211. package/dist/builtin-extensions/pi-web-access/storage.js.map +1 -1
  212. package/dist/builtin-extensions/simple-pi-memory.d.ts +1 -1
  213. package/dist/builtin-extensions/simple-pi-memory.d.ts.map +1 -1
  214. package/dist/builtin-extensions/simple-pi-memory.js +1 -1
  215. package/dist/builtin-extensions/simple-pi-memory.js.map +1 -1
  216. package/dist/catalog/models.json +1 -1
  217. package/dist/catalog/providers/google-vertex.json +1 -1
  218. package/dist/catalog/providers/google.json +1 -1
  219. package/dist/catalog/publication.json +3 -3
  220. package/dist/cli/install-cli.d.ts.map +1 -1
  221. package/dist/cli/install-cli.js +38 -30
  222. package/dist/cli/install-cli.js.map +1 -1
  223. package/dist/core/agent-session-runtime.d.ts +13 -0
  224. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  225. package/dist/core/agent-session-runtime.js +75 -11
  226. package/dist/core/agent-session-runtime.js.map +1 -1
  227. package/dist/core/agent-session-services.d.ts +1 -0
  228. package/dist/core/agent-session-services.d.ts.map +1 -1
  229. package/dist/core/agent-session-services.js +1 -0
  230. package/dist/core/agent-session-services.js.map +1 -1
  231. package/dist/core/agent-session.d.ts +46 -21
  232. package/dist/core/agent-session.d.ts.map +1 -1
  233. package/dist/core/agent-session.js +344 -126
  234. package/dist/core/agent-session.js.map +1 -1
  235. package/dist/core/browser/runtime.d.ts +2 -0
  236. package/dist/core/browser/runtime.d.ts.map +1 -1
  237. package/dist/core/browser/runtime.js +80 -45
  238. package/dist/core/browser/runtime.js.map +1 -1
  239. package/dist/core/browser/setup.d.ts.map +1 -1
  240. package/dist/core/browser/setup.js +12 -1
  241. package/dist/core/browser/setup.js.map +1 -1
  242. package/dist/core/cache-stats.d.ts +1 -1
  243. package/dist/core/cache-stats.d.ts.map +1 -1
  244. package/dist/core/cache-stats.js +1 -1
  245. package/dist/core/cache-stats.js.map +1 -1
  246. package/dist/core/compaction/branch-summarization.d.ts +2 -1
  247. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  248. package/dist/core/compaction/branch-summarization.js +1 -0
  249. package/dist/core/compaction/branch-summarization.js.map +1 -1
  250. package/dist/core/compaction/compaction.d.ts +5 -11
  251. package/dist/core/compaction/compaction.d.ts.map +1 -1
  252. package/dist/core/compaction/compaction.js +38 -92
  253. package/dist/core/compaction/compaction.js.map +1 -1
  254. package/dist/core/computer-use/adapter.d.ts.map +1 -1
  255. package/dist/core/computer-use/adapter.js +7 -2
  256. package/dist/core/computer-use/adapter.js.map +1 -1
  257. package/dist/core/computer-use/image.d.ts.map +1 -1
  258. package/dist/core/computer-use/image.js +17 -5
  259. package/dist/core/computer-use/image.js.map +1 -1
  260. package/dist/core/computer-use/schemas.d.ts.map +1 -1
  261. package/dist/core/computer-use/schemas.js +23 -6
  262. package/dist/core/computer-use/schemas.js.map +1 -1
  263. package/dist/core/computer-use/workflow.d.ts.map +1 -1
  264. package/dist/core/computer-use/workflow.js +459 -119
  265. package/dist/core/computer-use/workflow.js.map +1 -1
  266. package/dist/core/context-breakdown.d.ts +2 -2
  267. package/dist/core/context-breakdown.d.ts.map +1 -1
  268. package/dist/core/context-breakdown.js +22 -20
  269. package/dist/core/context-breakdown.js.map +1 -1
  270. package/dist/core/cron/jobs.d.ts +26 -8
  271. package/dist/core/cron/jobs.d.ts.map +1 -1
  272. package/dist/core/cron/jobs.js +357 -232
  273. package/dist/core/cron/jobs.js.map +1 -1
  274. package/dist/core/cron/origin-context.d.ts +1 -0
  275. package/dist/core/cron/origin-context.d.ts.map +1 -1
  276. package/dist/core/cron/origin-context.js.map +1 -1
  277. package/dist/core/cron/scheduler.d.ts +22 -17
  278. package/dist/core/cron/scheduler.d.ts.map +1 -1
  279. package/dist/core/cron/scheduler.js +153 -73
  280. package/dist/core/cron/scheduler.js.map +1 -1
  281. package/dist/core/extensions/index.d.ts +1 -1
  282. package/dist/core/extensions/index.d.ts.map +1 -1
  283. package/dist/core/extensions/index.js.map +1 -1
  284. package/dist/core/extensions/runner.d.ts +1 -0
  285. package/dist/core/extensions/runner.d.ts.map +1 -1
  286. package/dist/core/extensions/runner.js +8 -0
  287. package/dist/core/extensions/runner.js.map +1 -1
  288. package/dist/core/extensions/types.d.ts +11 -1
  289. package/dist/core/extensions/types.d.ts.map +1 -1
  290. package/dist/core/extensions/types.js.map +1 -1
  291. package/dist/core/footer-data-provider.d.ts +4 -0
  292. package/dist/core/footer-data-provider.d.ts.map +1 -1
  293. package/dist/core/footer-data-provider.js +22 -1
  294. package/dist/core/footer-data-provider.js.map +1 -1
  295. package/dist/core/large-subagent-launch.d.ts +1 -1
  296. package/dist/core/large-subagent-launch.d.ts.map +1 -1
  297. package/dist/core/large-subagent-launch.js +7 -7
  298. package/dist/core/large-subagent-launch.js.map +1 -1
  299. package/dist/core/model-registry.d.ts +2 -0
  300. package/dist/core/model-registry.d.ts.map +1 -1
  301. package/dist/core/model-registry.js +5 -0
  302. package/dist/core/model-registry.js.map +1 -1
  303. package/dist/core/model-runtime.d.ts +4 -1
  304. package/dist/core/model-runtime.d.ts.map +1 -1
  305. package/dist/core/model-runtime.js +40 -4
  306. package/dist/core/model-runtime.js.map +1 -1
  307. package/dist/core/package-manager.d.ts.map +1 -1
  308. package/dist/core/package-manager.js.map +1 -1
  309. package/dist/core/permissions.d.ts +3 -3
  310. package/dist/core/permissions.d.ts.map +1 -1
  311. package/dist/core/permissions.js +11 -35
  312. package/dist/core/permissions.js.map +1 -1
  313. package/dist/core/plan-mode.d.ts +5 -13
  314. package/dist/core/plan-mode.d.ts.map +1 -1
  315. package/dist/core/plan-mode.js +126 -116
  316. package/dist/core/plan-mode.js.map +1 -1
  317. package/dist/core/project-trust.d.ts.map +1 -1
  318. package/dist/core/project-trust.js +1 -1
  319. package/dist/core/project-trust.js.map +1 -1
  320. package/dist/core/prompt-resource-bridge.d.ts +12 -0
  321. package/dist/core/prompt-resource-bridge.d.ts.map +1 -0
  322. package/dist/core/prompt-resource-bridge.js +9 -0
  323. package/dist/core/prompt-resource-bridge.js.map +1 -0
  324. package/dist/core/protected-targets.d.ts +6 -0
  325. package/dist/core/protected-targets.d.ts.map +1 -0
  326. package/dist/core/protected-targets.js +45 -0
  327. package/dist/core/protected-targets.js.map +1 -0
  328. package/dist/core/resource-loader.d.ts.map +1 -1
  329. package/dist/core/resource-loader.js +7 -0
  330. package/dist/core/resource-loader.js.map +1 -1
  331. package/dist/core/rollback.d.ts +19 -3
  332. package/dist/core/rollback.d.ts.map +1 -1
  333. package/dist/core/rollback.js +172 -56
  334. package/dist/core/rollback.js.map +1 -1
  335. package/dist/core/runtime-credentials.d.ts +3 -0
  336. package/dist/core/runtime-credentials.d.ts.map +1 -1
  337. package/dist/core/runtime-credentials.js +14 -1
  338. package/dist/core/runtime-credentials.js.map +1 -1
  339. package/dist/core/sdk.d.ts +3 -0
  340. package/dist/core/sdk.d.ts.map +1 -1
  341. package/dist/core/sdk.js +1 -0
  342. package/dist/core/sdk.js.map +1 -1
  343. package/dist/core/session-manager.d.ts +11 -1
  344. package/dist/core/session-manager.d.ts.map +1 -1
  345. package/dist/core/session-manager.js +111 -33
  346. package/dist/core/session-manager.js.map +1 -1
  347. package/dist/core/session-ownership.d.ts.map +1 -1
  348. package/dist/core/session-ownership.js +8 -3
  349. package/dist/core/session-ownership.js.map +1 -1
  350. package/dist/core/session-retention.d.ts.map +1 -1
  351. package/dist/core/session-retention.js +18 -7
  352. package/dist/core/session-retention.js.map +1 -1
  353. package/dist/core/session-startup-settings.d.ts +10 -0
  354. package/dist/core/session-startup-settings.d.ts.map +1 -0
  355. package/dist/core/session-startup-settings.js +70 -0
  356. package/dist/core/session-startup-settings.js.map +1 -0
  357. package/dist/core/subscriptions.d.ts +16 -7
  358. package/dist/core/subscriptions.d.ts.map +1 -1
  359. package/dist/core/subscriptions.js +96 -55
  360. package/dist/core/subscriptions.js.map +1 -1
  361. package/dist/core/trust-manager.d.ts +2 -1
  362. package/dist/core/trust-manager.d.ts.map +1 -1
  363. package/dist/core/trust-manager.js +6 -1
  364. package/dist/core/trust-manager.js.map +1 -1
  365. package/dist/core/update-check.d.ts.map +1 -1
  366. package/dist/core/update-check.js.map +1 -1
  367. package/dist/core/usage-accounting.d.ts +47 -0
  368. package/dist/core/usage-accounting.d.ts.map +1 -0
  369. package/dist/core/usage-accounting.js +205 -0
  370. package/dist/core/usage-accounting.js.map +1 -0
  371. package/dist/core/usage-adapters/kimi-coding.d.ts +2 -2
  372. package/dist/core/usage-adapters/kimi-coding.d.ts.map +1 -1
  373. package/dist/core/usage-adapters/kimi-coding.js +2 -2
  374. package/dist/core/usage-adapters/kimi-coding.js.map +1 -1
  375. package/dist/core/usage-adapters/openai-codex.d.ts +3 -2
  376. package/dist/core/usage-adapters/openai-codex.d.ts.map +1 -1
  377. package/dist/core/usage-adapters/openai-codex.js +3 -3
  378. package/dist/core/usage-adapters/openai-codex.js.map +1 -1
  379. package/dist/core/usage-adapters/xai.d.ts +2 -2
  380. package/dist/core/usage-adapters/xai.d.ts.map +1 -1
  381. package/dist/core/usage-adapters/xai.js +3 -3
  382. package/dist/core/usage-adapters/xai.js.map +1 -1
  383. package/dist/core/usage-adapters/zai.d.ts +2 -2
  384. package/dist/core/usage-adapters/zai.d.ts.map +1 -1
  385. package/dist/core/usage-adapters/zai.js +2 -2
  386. package/dist/core/usage-adapters/zai.js.map +1 -1
  387. package/dist/core/usage-history.d.ts +1 -18
  388. package/dist/core/usage-history.d.ts.map +1 -1
  389. package/dist/core/usage-history.js +46 -114
  390. package/dist/core/usage-history.js.map +1 -1
  391. package/dist/core/usage-service.d.ts +9 -2
  392. package/dist/core/usage-service.d.ts.map +1 -1
  393. package/dist/core/usage-service.js +95 -50
  394. package/dist/core/usage-service.js.map +1 -1
  395. package/dist/gateway/agent-bridge.d.ts +9 -1
  396. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  397. package/dist/gateway/agent-bridge.js +91 -37
  398. package/dist/gateway/agent-bridge.js.map +1 -1
  399. package/dist/gateway/buttons.d.ts +8 -1
  400. package/dist/gateway/buttons.d.ts.map +1 -1
  401. package/dist/gateway/buttons.js +76 -18
  402. package/dist/gateway/buttons.js.map +1 -1
  403. package/dist/gateway/commands.d.ts +1 -0
  404. package/dist/gateway/commands.d.ts.map +1 -1
  405. package/dist/gateway/commands.js +10 -4
  406. package/dist/gateway/commands.js.map +1 -1
  407. package/dist/gateway/cron.d.ts +12 -11
  408. package/dist/gateway/cron.d.ts.map +1 -1
  409. package/dist/gateway/cron.js +65 -56
  410. package/dist/gateway/cron.js.map +1 -1
  411. package/dist/gateway/index.d.ts.map +1 -1
  412. package/dist/gateway/index.js +2 -1
  413. package/dist/gateway/index.js.map +1 -1
  414. package/dist/gateway/mobile-commands.d.ts +1 -0
  415. package/dist/gateway/mobile-commands.d.ts.map +1 -1
  416. package/dist/gateway/mobile-commands.js +69 -15
  417. package/dist/gateway/mobile-commands.js.map +1 -1
  418. package/dist/gateway/presenter.d.ts +12 -2
  419. package/dist/gateway/presenter.d.ts.map +1 -1
  420. package/dist/gateway/presenter.js +73 -38
  421. package/dist/gateway/presenter.js.map +1 -1
  422. package/dist/gateway/router.d.ts +2 -2
  423. package/dist/gateway/router.d.ts.map +1 -1
  424. package/dist/gateway/router.js +17 -2
  425. package/dist/gateway/router.js.map +1 -1
  426. package/dist/gateway/service.d.ts +2 -0
  427. package/dist/gateway/service.d.ts.map +1 -1
  428. package/dist/gateway/service.js +153 -0
  429. package/dist/gateway/service.js.map +1 -1
  430. package/dist/main.d.ts.map +1 -1
  431. package/dist/main.js +86 -33
  432. package/dist/main.js.map +1 -1
  433. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  434. package/dist/modes/interactive/components/assistant-message.js +6 -4
  435. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  436. package/dist/modes/interactive/components/context-view.d.ts.map +1 -1
  437. package/dist/modes/interactive/components/context-view.js +2 -2
  438. package/dist/modes/interactive/components/context-view.js.map +1 -1
  439. package/dist/modes/interactive/components/copyable-text.d.ts.map +1 -1
  440. package/dist/modes/interactive/components/copyable-text.js +3 -2
  441. package/dist/modes/interactive/components/copyable-text.js.map +1 -1
  442. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  443. package/dist/modes/interactive/components/extension-editor.js +1 -1
  444. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  445. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  446. package/dist/modes/interactive/components/footer.js +8 -12
  447. package/dist/modes/interactive/components/footer.js.map +1 -1
  448. package/dist/modes/interactive/components/usage-view.d.ts +5 -0
  449. package/dist/modes/interactive/components/usage-view.d.ts.map +1 -1
  450. package/dist/modes/interactive/components/usage-view.js +21 -6
  451. package/dist/modes/interactive/components/usage-view.js.map +1 -1
  452. package/dist/modes/interactive/interactive-mode.d.ts +3 -7
  453. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  454. package/dist/modes/interactive/interactive-mode.js +151 -131
  455. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  456. package/dist/modes/interactive/smooth-streaming.d.ts.map +1 -1
  457. package/dist/modes/interactive/smooth-streaming.js.map +1 -1
  458. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  459. package/dist/modes/rpc/rpc-mode.js +2 -1
  460. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  461. package/dist/node-runtime/{adapter-VFG7WNPX.js → adapter-247RTYLS.js} +4 -5
  462. package/dist/node-runtime/agent-session-services-RTUGP3XR.js +54 -0
  463. package/dist/node-runtime/{brave-UWDA3I22.js → brave-2AFFAXNN.js} +1 -1
  464. package/dist/node-runtime/{builtin-extensions-I2HIFEMY.js → builtin-extensions-N4EUD6SB.js} +8 -7
  465. package/dist/node-runtime/{chunk-QH6YL7VK.js → chunk-252ZVPPF.js} +3 -3
  466. package/dist/node-runtime/{chunk-PCEW76PM.js → chunk-2OIPYKLZ.js} +6 -6
  467. package/dist/node-runtime/{chunk-XBWPBZBN.js → chunk-2SWW7KMW.js} +1 -1
  468. package/dist/node-runtime/{chunk-UQUCFAJ3.js → chunk-2VIW3IMF.js} +40 -7
  469. package/dist/node-runtime/{chunk-UOEDI7RP.js → chunk-4KNKQGHM.js} +2 -2
  470. package/dist/node-runtime/chunk-4QRUZ64T.js +1203 -0
  471. package/dist/node-runtime/{chunk-FQMM2EZ2.js → chunk-64XTQNLA.js} +29 -7
  472. package/dist/node-runtime/{chunk-SPVDBUOS.js → chunk-6O3IW3IA.js} +2 -2
  473. package/dist/node-runtime/{chunk-5ZQXRPMC.js → chunk-6ZZHGUSA.js} +2 -2
  474. package/dist/node-runtime/{chunk-WIF24I7G.js → chunk-APVM5NEU.js} +149 -144
  475. package/dist/node-runtime/{chunk-LWYIVUGV.js → chunk-B2IBAXNX.js} +48 -31
  476. package/dist/node-runtime/{chunk-M3LZLQW2.js → chunk-BDRGN3L2.js} +1 -0
  477. package/dist/node-runtime/{chunk-LJTIVM7I.js → chunk-BMRXLQWQ.js} +464 -160
  478. package/dist/node-runtime/{chunk-GJ2RDBRL.js → chunk-BYC6RKCN.js} +4 -2
  479. package/dist/node-runtime/{chunk-T4DA4XE7.js → chunk-DFMPRAQQ.js} +162 -82
  480. package/dist/node-runtime/{chunk-SN2KSMPQ.js → chunk-DQSCFU7R.js} +13 -7
  481. package/dist/node-runtime/{chunk-UVWCDQYF.js → chunk-E5DQGNJI.js} +455 -278
  482. package/dist/node-runtime/{chunk-4SBQAI4T.js → chunk-EBLAZVSA.js} +2058 -73
  483. package/dist/node-runtime/{chunk-CSFI6YXL.js → chunk-ES6PBSIE.js} +1 -1
  484. package/dist/node-runtime/{chunk-IF24A3FH.js → chunk-EVM653DD.js} +4 -4
  485. package/dist/node-runtime/{chunk-HTFRRDSF.js → chunk-F2SMQ6ES.js} +3 -2
  486. package/dist/node-runtime/chunk-F2V2F4ZG.js +114 -0
  487. package/dist/node-runtime/{chunk-IKU6Y7DL.js → chunk-FE3WZI7F.js} +9 -6
  488. package/dist/node-runtime/{chunk-6VYZ5UFP.js → chunk-FLGEEH27.js} +1 -1
  489. package/dist/node-runtime/{chunk-5EFIU3OM.js → chunk-FTKEZL27.js} +1 -1
  490. package/dist/node-runtime/{chunk-RGQAEOM5.js → chunk-FYIFPFXE.js} +23 -6
  491. package/dist/node-runtime/{chunk-HMBGROQK.js → chunk-GLDXBBL6.js} +3 -3
  492. package/dist/node-runtime/{chunk-KWA4OC2J.js → chunk-H6YBCWKG.js} +1 -1
  493. package/dist/node-runtime/{chunk-2MI5OPMN.js → chunk-HNNHHJAB.js} +68 -50
  494. package/dist/node-runtime/{chunk-I74LN5JG.js → chunk-HUD2RFJW.js} +2 -2
  495. package/dist/node-runtime/{chunk-XHIRAZ26.js → chunk-IAZSK7KK.js} +1 -1
  496. package/dist/node-runtime/{chunk-GYIXXQAO.js → chunk-ICKGAKWX.js} +23 -59
  497. package/dist/node-runtime/{chunk-X3PGBLQ7.js → chunk-IHHTWSXN.js} +9 -9
  498. package/dist/node-runtime/{chunk-DAPBPCBP.js → chunk-IPP5BIV5.js} +25 -3
  499. package/dist/node-runtime/{chunk-QFWG2RVL.js → chunk-IXG6F4NT.js} +11 -0
  500. package/dist/node-runtime/{chunk-L24TPBS4.js → chunk-JEK35V2M.js} +45 -31
  501. package/dist/node-runtime/{chunk-RDDAZOMU.js → chunk-JL4HYQXK.js} +1 -1
  502. package/dist/node-runtime/{chunk-2HMIRK7W.js → chunk-LHV3V67B.js} +5 -5
  503. package/dist/node-runtime/{chunk-UAEOTO52.js → chunk-MNQXDFPV.js} +6 -2
  504. package/dist/node-runtime/{chunk-MPKSOJBT.js → chunk-NHATCSOI.js} +4 -7
  505. package/dist/node-runtime/{chunk-RMQZU2YU.js → chunk-NNNR3QIY.js} +1 -1
  506. package/dist/node-runtime/{chunk-2KIPT4HJ.js → chunk-PWHTSQC4.js} +83 -21
  507. package/dist/node-runtime/{chunk-RWTKOC3B.js → chunk-QBTJG3UM.js} +1 -1
  508. package/dist/node-runtime/{chunk-RCR3XAQY.js → chunk-QT3F6UEV.js} +233 -169
  509. package/dist/node-runtime/{chunk-GS42T6MX.js → chunk-QW3AAHWN.js} +1 -1
  510. package/dist/node-runtime/{chunk-DVQSHCVP.js → chunk-R4WSB2MQ.js} +5 -5
  511. package/dist/node-runtime/{chunk-B4HP6ZWM.js → chunk-RHCGYWO7.js} +1 -1
  512. package/dist/node-runtime/{chunk-2CFDTH5B.js → chunk-RLGY2QIL.js} +45 -59
  513. package/dist/node-runtime/{chunk-CDVHZOOK.js → chunk-RY3FJ6WI.js} +29 -27
  514. package/dist/node-runtime/{chunk-KKUTQQV7.js → chunk-RYRGL7P4.js} +1 -1
  515. package/dist/node-runtime/{chunk-I54LGHWM.js → chunk-STMX7W5I.js} +3 -3
  516. package/dist/node-runtime/chunk-SWWHZ2RI.js +158 -0
  517. package/dist/node-runtime/{chunk-5Q4A37RB.js → chunk-TCT6PCUR.js} +32 -11
  518. package/dist/node-runtime/{chunk-P7XBVXGT.js → chunk-U3YVZ6UC.js} +18 -14
  519. package/dist/node-runtime/{chunk-D5UCKPBQ.js → chunk-UBWW2PID.js} +1 -1
  520. package/dist/node-runtime/{chunk-E75WFZ33.js → chunk-UNUZICC4.js} +3 -3
  521. package/dist/node-runtime/{chunk-RAK2QA2B.js → chunk-UYRKUKFE.js} +4 -4
  522. package/dist/node-runtime/{chunk-LWJXTA6Z.js → chunk-VSUEAI7O.js} +1377 -45
  523. package/dist/node-runtime/{chunk-NAY6UUQZ.js → chunk-WDIVLMOH.js} +1 -1
  524. package/dist/node-runtime/{chunk-E24EO34J.js → chunk-WPXUR3HE.js} +1 -1
  525. package/dist/node-runtime/{chunk-SLVOAQOY.js → chunk-WXYNALHD.js} +113 -1
  526. package/dist/node-runtime/{chunk-KJ6DWS3K.js → chunk-XEOCUEUJ.js} +121 -60
  527. package/dist/node-runtime/chunk-YD3IZAZ7.js +47 -0
  528. package/dist/node-runtime/chunk-YSB6URMT.js +41 -0
  529. package/dist/node-runtime/{chunk-YWOJIGFY.js → chunk-ZEVFBFNF.js} +95 -142
  530. package/dist/node-runtime/{chunk-5B6VKFEV.js → chunk-ZIQUS5QO.js} +1 -1
  531. package/dist/node-runtime/cli-runtime.js +4 -4
  532. package/dist/node-runtime/{command-FSBU2EVZ.js → command-YRT7I2BW.js} +5 -5
  533. package/dist/node-runtime/{commands-NAAL7KNT.js → commands-2ETOWWRA.js} +16 -16
  534. package/dist/node-runtime/{commands-EMBQQVVT.js → commands-D6A6H4TS.js} +11 -18
  535. package/dist/node-runtime/{config-QDD5PUE2.js → config-CU7M7BTK.js} +1 -1
  536. package/dist/node-runtime/{config-D4QUPAHX.js → config-DS7XLMEM.js} +2 -2
  537. package/dist/node-runtime/{direct-tool-executor-4D7UXYU4.js → direct-tool-executor-2QJXVQD2.js} +6 -11
  538. package/dist/node-runtime/{exa-LL64QZR2.js → exa-6VBZNPGE.js} +1 -1
  539. package/dist/node-runtime/{export-html-VM4J2MNR.js → export-html-DBQRRMAY.js} +4 -4
  540. package/dist/node-runtime/{extension-input-E7BJZ35H.js → extension-input-VBBMX7YV.js} +5 -5
  541. package/dist/node-runtime/{extension-selector-WU42XDTU.js → extension-selector-T5AOG5XB.js} +5 -5
  542. package/dist/node-runtime/{extract-EQJE7FZZ.js → extract-BFX2N35A.js} +3 -3
  543. package/dist/node-runtime/{gateway-DQM333YV.js → gateway-V6K2CDWN.js} +51 -42
  544. package/dist/node-runtime/{gemini-search-35OCRFLN.js → gemini-search-C66QHDT6.js} +2 -2
  545. package/dist/node-runtime/{gemini-url-context-UQY3PHHW.js → gemini-url-context-T7DEK73R.js} +3 -3
  546. package/dist/node-runtime/{github-extract-F64RZOEA.js → github-extract-HOGE3D6F.js} +107 -38
  547. package/dist/node-runtime/{goal-NJEE5CTU.js → goal-J7TYMOBK.js} +14 -8
  548. package/dist/node-runtime/index.js +51 -48
  549. package/dist/node-runtime/{init-P5AUV77I.js → init-JBQJIPYI.js} +3 -6
  550. package/dist/node-runtime/{install-cli-NN4YAU44.js → install-cli-INGHIVBY.js} +30 -25
  551. package/dist/node-runtime/interactive-mode-ASZ7APYP.js +75 -0
  552. package/dist/node-runtime/{interactive-view-NGFAMHPW.js → interactive-view-K33PM4OS.js} +8 -8
  553. package/dist/node-runtime/{lsp-manager-3ASUSO4T.js → lsp-manager-S554V5HR.js} +240 -155
  554. package/dist/node-runtime/{lunr-browser-IR7TL3J7.js → lunr-browser-H4FDOR3C.js} +7 -7
  555. package/dist/node-runtime/{lunr-computer-use-Y23CCDIJ.js → lunr-computer-use-VDP2QNRQ.js} +9 -9
  556. package/dist/node-runtime/{lunr-cron-USHC4LXH.js → lunr-cron-WD3YH4CR.js} +93 -80
  557. package/dist/node-runtime/main.js +43 -41
  558. package/dist/node-runtime/{mobile-commands-O5LCHL32.js → mobile-commands-ICUXFW5V.js} +12 -12
  559. package/dist/node-runtime/{model-runtime-OO5HFLWE.js → model-runtime-MZ2JMDV4.js} +4 -4
  560. package/dist/node-runtime/{openai-search-B3MSNCQA.js → openai-search-K72LJDYN.js} +1 -1
  561. package/dist/node-runtime/{package-manager-cli-Q7BL6KZO.js → package-manager-cli-CYM262SI.js} +20 -20
  562. package/dist/node-runtime/{parallel-AI2MNSCU.js → parallel-X724NCNU.js} +1 -1
  563. package/dist/node-runtime/{perplexity-QVJW3I35.js → perplexity-RDHQHVMK.js} +2 -2
  564. package/dist/node-runtime/{pi-intercom-QM53RLTS.js → pi-intercom-NHHEPBMI.js} +2 -2
  565. package/dist/node-runtime/{pi-mcp-adapter-3PHF4KZ4.js → pi-mcp-adapter-PP3GQJQ2.js} +98 -94
  566. package/dist/node-runtime/{pi-ollama-cloud-2F3Y2QNM.js → pi-ollama-cloud-4MNWIMFN.js} +11 -24
  567. package/dist/node-runtime/{pi-prompt-template-model-QWTCGLJU.js → pi-prompt-template-model-FTGELLS5.js} +32 -36
  568. package/dist/node-runtime/{pi-subagents-7IBSSGEW.js → pi-subagents-QPU3OXE4.js} +114 -167
  569. package/dist/node-runtime/{pi-web-access-WTGMNZ32.js → pi-web-access-Z3LP246C.js} +144 -108
  570. package/dist/node-runtime/{print-mode-XQ76CYMT.js → print-mode-2XHN5SUA.js} +3 -3
  571. package/dist/node-runtime/{process-registry-4FAKZQOL.js → process-registry-Q4QWIU33.js} +3 -3
  572. package/dist/node-runtime/{proxy-modes-5FAPSZEZ.js → proxy-modes-VEGC6QG5.js} +8 -15
  573. package/dist/node-runtime/rpc-entry.js +43 -41
  574. package/dist/node-runtime/{rpc-mode-O3XV4SID.js → rpc-mode-32DHJPEJ.js} +4 -4
  575. package/dist/node-runtime/{runtime-4VA6JKNF.js → runtime-EDUUGAQD.js} +56 -46
  576. package/dist/node-runtime/{runtime-EFPPD2UW.js → runtime-UGXM4NPQ.js} +2 -2
  577. package/dist/node-runtime/{runtime-bridges-7WVCLI76.js → runtime-bridges-DNKMNJCF.js} +7 -7
  578. package/dist/node-runtime/{service-MDQIPQ26.js → service-IHLGFLBT.js} +6 -4
  579. package/dist/node-runtime/{session-handoff-GWARVEWT.js → session-handoff-LYH53ESV.js} +4 -4
  580. package/dist/node-runtime/{session-manager-JB5J6XBN.js → session-manager-ZJ3N5Q74.js} +3 -3
  581. package/dist/node-runtime/{session-selector-GIM4DHQ2.js → session-selector-I73U3EIO.js} +7 -7
  582. package/dist/node-runtime/{settings-manager-DJDM5AHM.js → settings-manager-P2TKGYTR.js} +5 -5
  583. package/dist/node-runtime/{setup-JBKOLJ6F.js → setup-H7CCELIL.js} +15 -1
  584. package/dist/node-runtime/{setup-PFBWRNUI.js → setup-OLQ4GXWS.js} +17 -17
  585. package/dist/node-runtime/{src-IVPNZ2BX.js → src-6RV4PXKJ.js} +64 -36
  586. package/dist/node-runtime/{subagent-executor-LPZ4BHWE.js → subagent-executor-UI6SHG3X.js} +412 -288
  587. package/dist/node-runtime/{tavily-WEZFVFP7.js → tavily-KZBFYQB6.js} +1 -1
  588. package/dist/node-runtime/{theme-UOO5RVFN.js → theme-YLVZKKZD.js} +2 -2
  589. package/dist/node-runtime/{trust-manager-MMISNCYO.js → trust-manager-ZCU76D23.js} +2 -2
  590. package/dist/node-runtime/{update-cli-HNMOTNGX.js → update-cli-F3XXJANQ.js} +6 -6
  591. package/dist/node-runtime/{usage-service-LFB2SWYV.js → usage-service-CPAGBED5.js} +1 -1
  592. package/dist/node-runtime/{video-extract-OOZHR7SU.js → video-extract-UPKYIBW3.js} +3 -3
  593. package/dist/node-runtime/{workflow-OHPBEFO4.js → workflow-ICDI4N3J.js} +208 -78
  594. package/dist/node-runtime/{youtube-extract-FNPAUNHU.js → youtube-extract-77NT7FWH.js} +4 -4
  595. package/dist/utils/clipboard-image.d.ts.map +1 -1
  596. package/dist/utils/clipboard-image.js.map +1 -1
  597. package/dist/utils/exif-orientation.d.ts.map +1 -1
  598. package/dist/utils/exif-orientation.js +25 -10
  599. package/dist/utils/exif-orientation.js.map +1 -1
  600. package/dist/utils/image-resize-core.d.ts.map +1 -1
  601. package/dist/utils/image-resize-core.js +2 -0
  602. package/dist/utils/image-resize-core.js.map +1 -1
  603. package/dist/utils/paths.d.ts +4 -0
  604. package/dist/utils/paths.d.ts.map +1 -1
  605. package/dist/utils/paths.js +33 -2
  606. package/dist/utils/paths.js.map +1 -1
  607. package/dist/utils/sanitize-terminal-text.d.ts +7 -0
  608. package/dist/utils/sanitize-terminal-text.d.ts.map +1 -0
  609. package/dist/utils/sanitize-terminal-text.js +67 -0
  610. package/dist/utils/sanitize-terminal-text.js.map +1 -0
  611. package/docs/browser.md +1 -1
  612. package/docs/custom-provider.md +3 -3
  613. package/docs/extensions.md +8 -4
  614. package/docs/features.md +25 -7
  615. package/docs/keybindings.md +1 -1
  616. package/docs/models.md +5 -5
  617. package/docs/packages.md +1 -1
  618. package/docs/providers.md +2 -2
  619. package/docs/rpc.md +7 -7
  620. package/docs/security.md +10 -5
  621. package/docs/sessions.md +2 -2
  622. package/docs/skills.md +1 -1
  623. package/docs/terminal-setup.md +7 -7
  624. package/docs/themes.md +1 -1
  625. package/docs/usage.md +1 -1
  626. package/examples/extensions/auto-commit-on-exit.ts +1 -1
  627. package/examples/extensions/bash-spawn-hook.ts +1 -1
  628. package/examples/extensions/built-in-tool-renderer.ts +1 -1
  629. package/examples/extensions/claude-rules.ts +1 -1
  630. package/examples/extensions/commands.ts +1 -1
  631. package/examples/extensions/custom-compaction.ts +1 -1
  632. package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
  633. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  634. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  635. package/examples/extensions/custom-provider-gitlab-duo/index.ts +1 -1
  636. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  637. package/examples/extensions/doom-overlay/index.ts +1 -1
  638. package/examples/extensions/git-merge-and-resolve.ts +2 -2
  639. package/examples/extensions/gondolin/index.ts +1 -1
  640. package/examples/extensions/gondolin/package-lock.json +2 -2
  641. package/examples/extensions/gondolin/package.json +1 -1
  642. package/examples/extensions/hidden-thinking-label.ts +1 -1
  643. package/examples/extensions/inline-bash.ts +2 -2
  644. package/examples/extensions/input-transform-streaming.ts +2 -2
  645. package/examples/extensions/input-transform.ts +2 -2
  646. package/examples/extensions/interactive-shell.ts +1 -1
  647. package/examples/extensions/kimi-deferred-tools.ts +1 -1
  648. package/examples/extensions/mac-system-theme.ts +1 -1
  649. package/examples/extensions/minimal-mode.ts +1 -1
  650. package/examples/extensions/modal-editor.ts +1 -1
  651. package/examples/extensions/model-status.ts +1 -1
  652. package/examples/extensions/notify.ts +3 -3
  653. package/examples/extensions/overlay-qa-tests.ts +1 -1
  654. package/examples/extensions/overlay-test.ts +1 -1
  655. package/examples/extensions/pirate.ts +1 -1
  656. package/examples/extensions/preset.ts +3 -3
  657. package/examples/extensions/project-trust.ts +4 -4
  658. package/examples/extensions/prompt-customizer.ts +1 -1
  659. package/examples/extensions/rainbow-editor.ts +1 -1
  660. package/examples/extensions/rpc-demo.ts +1 -1
  661. package/examples/extensions/sandbox/index.ts +7 -7
  662. package/examples/extensions/sandbox/package-lock.json +2 -2
  663. package/examples/extensions/sandbox/package.json +1 -1
  664. package/examples/extensions/shutdown-command.ts +5 -5
  665. package/examples/extensions/ssh.ts +2 -2
  666. package/examples/extensions/subagent/README.md +3 -3
  667. package/examples/extensions/subagent/index.ts +2 -2
  668. package/examples/extensions/titlebar-spinner.ts +1 -1
  669. package/examples/extensions/tool-override.ts +1 -1
  670. package/examples/extensions/tools.ts +1 -1
  671. package/examples/extensions/with-deps/package-lock.json +2 -2
  672. package/examples/extensions/with-deps/package.json +1 -1
  673. package/examples/extensions/working-indicator.ts +1 -1
  674. package/examples/extensions/working-message-test.ts +1 -1
  675. package/examples/sdk/01-minimal.ts +1 -1
  676. package/examples/sdk/03-custom-prompt.ts +1 -1
  677. package/examples/sdk/04-skills.ts +1 -1
  678. package/examples/sdk/06-extensions.ts +2 -2
  679. package/examples/sdk/08-prompt-templates.ts +1 -1
  680. package/install-lock/package-lock.json +24 -24
  681. package/install-lock/package.json +2 -2
  682. package/npm-shrinkwrap.json +60 -24
  683. package/package.json +9 -9
  684. package/dist/modes/interactive/components/exit-card.d.ts +0 -22
  685. package/dist/modes/interactive/components/exit-card.d.ts.map +0 -1
  686. package/dist/modes/interactive/components/exit-card.js +0 -69
  687. package/dist/modes/interactive/components/exit-card.js.map +0 -1
  688. package/dist/node-runtime/agent-session-services-5YXS2PLF.js +0 -51
  689. package/dist/node-runtime/chunk-2IDTZAG5.js +0 -1415
  690. package/dist/node-runtime/chunk-3MISGG4S.js +0 -769
  691. package/dist/node-runtime/chunk-4HXHDDCF.js +0 -16
  692. package/dist/node-runtime/chunk-5B5QN3ZQ.js +0 -356
  693. package/dist/node-runtime/chunk-7IQGBKBJ.js +0 -2033
  694. package/dist/node-runtime/chunk-AUXVGBO4.js +0 -19
  695. package/dist/node-runtime/chunk-PTFBPO3C.js +0 -50
  696. package/dist/node-runtime/interactive-mode-YOHZVMKX.js +0 -74
  697. package/dist/node-runtime/mcp-auth-flow-QVLFVLEO.js +0 -33
@@ -0,0 +1,57 @@
1
+ import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, truncateHead, } from "../../core/tools/truncate.js";
2
+ function utf8Prefix(bytes, limit) {
3
+ let end = Math.min(limit, bytes.length);
4
+ while (end > 0 && end < bytes.length && (bytes[end] & 0xc0) === 0x80)
5
+ end--;
6
+ return bytes.subarray(0, end).toString("utf8");
7
+ }
8
+ /** Page every retrieval response, including lists and errors. Offset counts UTF-8 bytes. */
9
+ export function contentPage(text, offset = 0, details = {}) {
10
+ const bytes = Buffer.from(text, "utf8");
11
+ if (!Number.isSafeInteger(offset) ||
12
+ offset < 0 ||
13
+ offset > bytes.length ||
14
+ (offset < bytes.length && (bytes[offset] & 0xc0) === 0x80)) {
15
+ return {
16
+ content: [
17
+ {
18
+ type: "text",
19
+ text: "Invalid offset. Use 0 or the nextOffset returned by the previous page.",
20
+ },
21
+ ],
22
+ details: { error: "Invalid offset" },
23
+ };
24
+ }
25
+ // Reserve space for the continuation notice within the same byte and line limits.
26
+ const remaining = bytes.subarray(offset).toString("utf8");
27
+ const page = truncateHead(remaining, {
28
+ maxBytes: DEFAULT_MAX_BYTES - 256,
29
+ maxLines: DEFAULT_MAX_LINES - 3,
30
+ });
31
+ const body = page.firstLineExceedsLimit
32
+ ? utf8Prefix(bytes.subarray(offset), DEFAULT_MAX_BYTES - 256)
33
+ : page.content;
34
+ const end = offset + Buffer.byteLength(body, "utf8");
35
+ const truncated = end < bytes.length;
36
+ const notice = truncated
37
+ ? `\n\n[Truncated. Continue with the same responseId and selectors, offset: ${end}.]`
38
+ : "";
39
+ const metadata = Object.fromEntries(Object.entries(details).map(([key, value]) => [
40
+ key,
41
+ typeof value === "string"
42
+ ? utf8Prefix(Buffer.from(value, "utf8"), 512)
43
+ : value,
44
+ ]));
45
+ return {
46
+ content: [{ type: "text", text: body + notice }],
47
+ details: {
48
+ ...metadata,
49
+ offset,
50
+ nextOffset: truncated ? end : null,
51
+ truncated,
52
+ totalBytes: bytes.length,
53
+ pageBytes: end - offset,
54
+ },
55
+ };
56
+ }
57
+ //# sourceMappingURL=content-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-page.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-web-access/content-page.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\ttruncateHead,\n} from \"../../core/tools/truncate.ts\";\n\nfunction utf8Prefix(bytes: Buffer, limit: number): string {\n\tlet end = Math.min(limit, bytes.length);\n\twhile (end > 0 && end < bytes.length && (bytes[end] & 0xc0) === 0x80) end--;\n\treturn bytes.subarray(0, end).toString(\"utf8\");\n}\n\n/** Page every retrieval response, including lists and errors. Offset counts UTF-8 bytes. */\nexport function contentPage(\n\ttext: string,\n\toffset = 0,\n\tdetails: Record<string, unknown> = {},\n) {\n\tconst bytes = Buffer.from(text, \"utf8\");\n\tif (\n\t\t!Number.isSafeInteger(offset) ||\n\t\toffset < 0 ||\n\t\toffset > bytes.length ||\n\t\t(offset < bytes.length && (bytes[offset] & 0xc0) === 0x80)\n\t) {\n\t\treturn {\n\t\t\tcontent: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\ttext: \"Invalid offset. Use 0 or the nextOffset returned by the previous page.\",\n\t\t\t\t},\n\t\t\t],\n\t\t\tdetails: { error: \"Invalid offset\" },\n\t\t};\n\t}\n\n\t// Reserve space for the continuation notice within the same byte and line limits.\n\tconst remaining = bytes.subarray(offset).toString(\"utf8\");\n\tconst page = truncateHead(remaining, {\n\t\tmaxBytes: DEFAULT_MAX_BYTES - 256,\n\t\tmaxLines: DEFAULT_MAX_LINES - 3,\n\t});\n\tconst body = page.firstLineExceedsLimit\n\t\t? utf8Prefix(bytes.subarray(offset), DEFAULT_MAX_BYTES - 256)\n\t\t: page.content;\n\tconst end = offset + Buffer.byteLength(body, \"utf8\");\n\tconst truncated = end < bytes.length;\n\tconst notice = truncated\n\t\t? `\\n\\n[Truncated. Continue with the same responseId and selectors, offset: ${end}.]`\n\t\t: \"\";\n\tconst metadata = Object.fromEntries(\n\t\tObject.entries(details).map(([key, value]) => [\n\t\t\tkey,\n\t\t\ttypeof value === \"string\"\n\t\t\t\t? utf8Prefix(Buffer.from(value, \"utf8\"), 512)\n\t\t\t\t: value,\n\t\t]),\n\t);\n\treturn {\n\t\tcontent: [{ type: \"text\" as const, text: body + notice }],\n\t\tdetails: {\n\t\t\t...metadata,\n\t\t\toffset,\n\t\t\tnextOffset: truncated ? end : null,\n\t\t\ttruncated,\n\t\t\ttotalBytes: bytes.length,\n\t\t\tpageBytes: end - offset,\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-web-access/extract.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAqC,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAgDtF;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAuB9C;AAyBD,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAC3D,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAgJD,wBAAsB,cAAc,CACnC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,gBAAgB,CAAC,CA0Q3B;AAuLD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/D;AAMD,wBAAsB,eAAe,CACpC,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAE7B","sourcesContent":["// @ts-nocheck\nimport { Readability } from \"@mozilla/readability\";\nimport { parseHTML } from \"linkedom\";\nimport TurndownService from \"turndown\";\nimport pLimit from \"p-limit\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { extractRSCContent } from \"./rsc-extract.ts\";\nimport {\n\tloadGeminiUrlContext,\n\tloadGithubExtract,\n\tloadParallel,\n\tloadPdfExtract,\n\tloadVideoExtract,\n\tloadYoutubeExtract,\n} from \"./lazy.ts\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { fetchRemoteUrl, validateRemoteUrl, type Lookup } from \"./ssrf-protection.ts\";\nimport { formatSeconds, getWebSearchConfigPath } from \"./utils.ts\";\n\nconst YOUTUBE_URL_RE =\n\t/(?:(?:www\\.|m\\.)?youtube\\.com\\/(?:watch\\?.*v=|shorts\\/|live\\/|embed\\/|v\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/;\n\nfunction isYouTubeURL(url: string): { isYouTube: boolean; videoId: string | null } {\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.pathname === \"/playlist\") {\n\t\t\treturn { isYouTube: false, videoId: null };\n\t\t}\n\t} catch {\n\t}\n\tconst match = url.match(YOUTUBE_URL_RE);\n\tif (!match) return { isYouTube: false, videoId: null };\n\treturn { isYouTube: true, videoId: match[1] };\n}\n\nfunction isPDF(url: string, contentType?: string): boolean {\n\tif (contentType?.includes(\"application/pdf\")) return true;\n\ttry {\n\t\treturn new URL(url).pathname.toLowerCase().endsWith(\".pdf\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction looksLikeLocalPath(input: string): boolean {\n\treturn input.startsWith(\"/\") || input.startsWith(\"./\") || input.startsWith(\"../\") || input.startsWith(\"file://\");\n}\n\nfunction looksLikeGitHubUrl(url: string): boolean {\n\ttry {\n\t\tconst host = new URL(url).hostname.toLowerCase();\n\t\treturn host === \"github.com\" || host === \"www.github.com\" || host.endsWith(\".github.com\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nconst DEFAULT_TIMEOUT_MS = 30000;\nconst CONCURRENT_LIMIT = 3;\n\nconst NON_RECOVERABLE_ERRORS = [\"Unsupported content type\", \"Response too large\"];\nconst MIN_USEFUL_CONTENT = 500;\nconst WEB_SEARCH_CONFIG_PATH = getWebSearchConfigPath();\n\n/**\n * Read `ssrf.allowRanges` (CIDR strings) from web-search.json. Returns [] when\n * the file is missing, unreadable, or the key is unset so SSRF protection stays\n * fully on by default. Throws when `ssrf.allowRanges` is present but not an array\n * so a mistyped value (e.g. a bare string instead of a JSON array) fails loudly\n * instead of being silently ignored. Exempts synthetic ranges used by TUN/fake-IP\n * proxies (e.g. 198.18.0.0/15).\n */\nexport function loadSsrfAllowRanges(): string[] {\n\tlet value: unknown;\n\ttry {\n\t\tif (!existsSync(WEB_SEARCH_CONFIG_PATH)) return [];\n\t\tconst raw = readFileSync(WEB_SEARCH_CONFIG_PATH, \"utf-8\");\n\t\tvalue = (JSON.parse(raw) as { ssrf?: { allowRanges?: unknown } })?.ssrf?.allowRanges;\n\t} catch {\n\t\t// Missing/unreadable file or invalid JSON: fail safe with SSRF fully on.\n\t\treturn [];\n\t}\n\tif (value === undefined || value === null) return [];\n\tif (!Array.isArray(value)) {\n\t\tthrow new Error(`ssrf.allowRanges in ${WEB_SEARCH_CONFIG_PATH} must be an array of CIDR strings`);\n\t}\n\tconst ranges: string[] = [];\n\tfor (const [index, entry] of value.entries()) {\n\t\tif (typeof entry !== \"string\") {\n\t\t\tthrow new Error(`ssrf.allowRanges in ${WEB_SEARCH_CONFIG_PATH} must contain only CIDR strings; entry ${index + 1} is ${typeof entry}`);\n\t\t}\n\t\tconst trimmed = entry.trim();\n\t\tif (trimmed) ranges.push(trimmed);\n\t}\n\treturn ranges;\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction isConfigParseError(err: unknown): boolean {\n\treturn errorMessage(err).startsWith(\"Failed to parse \");\n}\n\nfunction isAbortError(err: unknown): boolean {\n\treturn errorMessage(err).toLowerCase().includes(\"abort\");\n}\n\nfunction abortedResult(url: string): ExtractedContent {\n\treturn { url, title: \"\", content: \"\", error: \"Aborted\" };\n}\n\nconst turndown = new TurndownService({\n\theadingStyle: \"atx\",\n\tcodeBlockStyle: \"fenced\",\n});\n\nconst fetchLimit = pLimit(CONCURRENT_LIMIT);\n\nexport interface VideoFrame {\n\tdata: string;\n\tmimeType: string;\n\ttimestamp: string;\n}\n\nexport type FrameData = { data: string; mimeType: string };\nexport type FrameResult = FrameData | { error: string };\n\nexport interface ExtractedContent {\n\turl: string;\n\ttitle: string;\n\tcontent: string;\n\terror: string | null;\n\tthumbnail?: { data: string; mimeType: string };\n\tframes?: VideoFrame[];\n\tduration?: number;\n}\n\nexport interface ExtractOptions {\n\ttimeoutMs?: number;\n\tforceClone?: boolean;\n\tprompt?: string;\n\ttimestamp?: string;\n\tframes?: number;\n\tmodel?: string;\n\t/** Custom DNS resolver used for SSRF validation. Primarily a test seam. */\n\tlookup?: Lookup;\n}\n\nconst JINA_READER_BASE = \"https://r.jina.ai/\";\nconst JINA_TIMEOUT_MS = 30000;\n\nasync function extractWithJinaReader(\n\turl: string,\n\tsignal?: AbortSignal,\n\tlookup?: Lookup,\n): Promise<ExtractedContent | null> {\n\tconst jinaUrl = JINA_READER_BASE + url;\n\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query: `jina: ${url}` });\n\n\ttry {\n\t\tawait validateRemoteUrl(url, { allowRanges: loadSsrfAllowRanges(), lookup });\n\t\tconst res = await fetch(jinaUrl, {\n\t\t\theaders: {\n\t\t\t\t\"Accept\": \"text/markdown\",\n\t\t\t\t\"X-No-Cache\": \"true\",\n\t\t\t},\n\t\t\tsignal: AbortSignal.any([\n\t\t\t\tAbortSignal.timeout(JINA_TIMEOUT_MS),\n\t\t\t\t...(signal ? [signal] : []),\n\t\t\t]),\n\t\t});\n\n\t\tif (!res.ok) {\n\t\t\tactivityMonitor.logComplete(activityId, res.status);\n\t\t\treturn null;\n\t\t}\n\n\t\tconst content = await res.text();\n\t\tactivityMonitor.logComplete(activityId, res.status);\n\n\t\tconst contentStart = content.indexOf(\"Markdown Content:\");\n\t\tif (contentStart < 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst markdownPart = content.slice(contentStart + 17).trim(); // 17 = \"Markdown Content:\".length\n\n\t\t// Check for failed JS rendering or minimal content\n\t\tif (markdownPart.length < 100 ||\n\t\t\tmarkdownPart.startsWith(\"Loading...\") ||\n\t\t\tmarkdownPart.startsWith(\"Please enable JavaScript\")) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst title = extractHeadingTitle(markdownPart) ?? (new URL(url).pathname.split(\"/\").pop() || url);\n\t\treturn { url, title, content: markdownPart, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (message.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, message);\n\t\t}\n\t\treturn null;\n\t}\n}\n\nfunction parseTimestamp(ts: string): number | null {\n\tconst num = Number(ts);\n\tif (!isNaN(num) && num >= 0) return Math.floor(num);\n\tconst parts = ts.split(\":\").map(Number);\n\tif (parts.some(p => isNaN(p) || p < 0)) return null;\n\tif (parts.length === 3) return Math.floor(parts[0] * 3600 + parts[1] * 60 + parts[2]);\n\tif (parts.length === 2) return Math.floor(parts[0] * 60 + parts[1]);\n\treturn null;\n}\n\ntype TimestampSpec = { type: \"single\"; seconds: number } | { type: \"range\"; start: number; end: number };\n\nfunction parseTimestampSpec(ts: string): TimestampSpec | null {\n\tconst dashIdx = ts.indexOf(\"-\", 1);\n\tif (dashIdx > 0) {\n\t\tconst start = parseTimestamp(ts.slice(0, dashIdx));\n\t\tconst end = parseTimestamp(ts.slice(dashIdx + 1));\n\t\tif (start !== null && end !== null && end > start) return { type: \"range\", start, end };\n\t}\n\tconst seconds = parseTimestamp(ts);\n\treturn seconds !== null ? { type: \"single\", seconds } : null;\n}\n\nconst DEFAULT_RANGE_FRAMES = 6;\nconst MIN_FRAME_INTERVAL = 5;\n\nfunction computeRangeTimestamps(start: number, end: number, maxFrames: number = DEFAULT_RANGE_FRAMES): number[] {\n\tif (maxFrames <= 1) return [start];\n\tconst duration = end - start;\n\tconst idealInterval = duration / (maxFrames - 1);\n\tif (idealInterval < MIN_FRAME_INTERVAL) {\n\t\tconst timestamps: number[] = [];\n\t\tfor (let t = start; t <= end && timestamps.length < maxFrames; t += MIN_FRAME_INTERVAL) {\n\t\t\ttimestamps.push(t);\n\t\t}\n\t\treturn timestamps;\n\t}\n\treturn Array.from({ length: maxFrames }, (_, i) => Math.round(start + i * idealInterval));\n}\n\nfunction buildFrameResult(\n\turl: string, label: string, requestedCount: number,\n\tframes: VideoFrame[], error: string | null, duration?: number,\n): ExtractedContent {\n\tif (frames.length === 0) {\n\t\tconst msg = error ?? \"Frame extraction failed\";\n\t\treturn { url, title: `Frames ${label} (0/${requestedCount})`, content: msg, error: msg };\n\t}\n\treturn {\n\t\turl,\n\t\ttitle: `Frames ${label} (${frames.length}/${requestedCount})`,\n\t\tcontent: `${frames.length} frames extracted from ${label}`,\n\t\terror: null,\n\t\tframes,\n\t\tduration,\n\t};\n}\n\nasync function extractLocalFrames(\n\tfilePath: string, timestamps: number[],\n): Promise<{ frames: VideoFrame[]; error: string | null }> {\n\tconst { extractVideoFrame } = await loadVideoExtract();\n\tconst results = await Promise.all(timestamps.map(async (t) => {\n\t\tconst frame = await extractVideoFrame(filePath, t);\n\t\tif (\"error\" in frame) return { error: frame.error };\n\t\treturn { ...frame, timestamp: formatSeconds(t) };\n\t}));\n\tconst frames = results.filter((f): f is VideoFrame => \"data\" in f);\n\tconst firstError = results.find((f): f is { error: string } => \"error\" in f);\n\treturn { frames, error: frames.length === 0 && firstError ? firstError.error : null };\n}\n\nasync function safeVideoInfo(url: string): Promise<{ info: Awaited<ReturnType<typeof loadVideoExtract>> extends { isVideoFile: infer F } ? (F extends (...args: any) => infer R ? R : null) : null; error?: string }> {\n\tif (!looksLikeLocalPath(url)) return { info: null };\n\ttry {\n\t\tconst { isVideoFile } = await loadVideoExtract();\n\t\treturn { info: isVideoFile(url) };\n\t} catch (err) {\n\t\treturn { info: null, error: errorMessage(err) };\n\t}\n}\n\nexport async function extractContent(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent> {\n\tif (signal?.aborted) {\n\t\treturn { url, title: \"\", content: \"\", error: \"Aborted\" };\n\t}\n\n\tif (options?.frames && !options.timestamp) {\n\t\tconst frameCount = options.frames;\n\t\tconst ytInfo = isYouTubeURL(url);\n\t\tif (ytInfo.isYouTube && ytInfo.videoId) {\n\t\t\tconst yt = await loadYoutubeExtract();\n\t\t\tconst streamInfo = await yt.getYouTubeStreamInfo(ytInfo.videoId);\n\t\t\tif (\"error\" in streamInfo) {\n\t\t\t\treturn { url, title: \"Frames\", content: streamInfo.error, error: streamInfo.error };\n\t\t\t}\n\t\t\tif (streamInfo.duration === null) {\n\t\t\t\tconst error = \"Cannot determine video duration. Use a timestamp range instead.\";\n\t\t\t\treturn { url, title: \"Frames\", content: error, error };\n\t\t\t}\n\t\t\tconst dur = Math.floor(streamInfo.duration);\n\t\t\tconst timestamps = computeRangeTimestamps(0, dur, frameCount);\n\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\tconst label = `${formatSeconds(0)}-${formatSeconds(dur)}`;\n\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, streamInfo.duration);\n\t\t}\n\n\t\tconst localVideo = await safeVideoInfo(url);\n\t\tif (localVideo.error) {\n\t\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t\t}\n\t\tif (localVideo.info) {\n\t\t\tconst { getLocalVideoDuration } = await loadVideoExtract();\n\t\t\tconst durationResult = await getLocalVideoDuration(localVideo.info.absolutePath);\n\t\t\tif (typeof durationResult !== \"number\") {\n\t\t\t\treturn { url, title: \"Frames\", content: durationResult.error, error: durationResult.error };\n\t\t\t}\n\t\t\tconst dur = Math.floor(durationResult);\n\t\t\tconst timestamps = computeRangeTimestamps(0, dur, frameCount);\n\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\tconst label = `${formatSeconds(0)}-${formatSeconds(dur)}`;\n\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, durationResult);\n\t\t}\n\n\t\treturn { url, title: \"\", content: \"\", error: \"Frame extraction only works with YouTube and local video files\" };\n\t}\n\n\tif (options?.timestamp) {\n\t\tconst spec = parseTimestampSpec(options.timestamp);\n\t\tif (!spec) {\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `Invalid timestamp format: \"${options.timestamp}\". Use \"H:MM:SS\", \"MM:SS\", \"85\", or \"start-end\".`,\n\t\t\t};\n\t\t}\n\n\t\tconst frameCount = options.frames;\n\t\tconst ytInfo = isYouTubeURL(url);\n\t\tif (ytInfo.isYouTube && ytInfo.videoId) {\n\t\t\tconst yt = await loadYoutubeExtract();\n\t\t\tconst streamInfo = await yt.getYouTubeStreamInfo(ytInfo.videoId);\n\t\t\tif (\"error\" in streamInfo) {\n\t\t\t\tif (spec.type === \"range\") {\n\t\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t\t}\n\t\t\t\tif (frameCount) {\n\t\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t\t}\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t}\n\n\t\t\tif (spec.type === \"range\") {\n\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\tif (streamInfo.duration !== null && spec.end > streamInfo.duration) {\n\t\t\t\t\tconst error = `Timestamp ${formatSeconds(spec.end)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: error, error };\n\t\t\t\t}\n\t\t\t\tconst timestamps = frameCount\n\t\t\t\t\t? computeRangeTimestamps(spec.start, spec.end, frameCount)\n\t\t\t\t\t: computeRangeTimestamps(spec.start, spec.end);\n\t\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, result.duration ?? undefined);\n\t\t\t}\n\n\t\t\tif (frameCount) {\n\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\tif (streamInfo.duration !== null && end > streamInfo.duration) {\n\t\t\t\t\tconst error = `Timestamp ${formatSeconds(end)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: error, error };\n\t\t\t\t}\n\t\t\t\tconst timestamps = computeRangeTimestamps(spec.seconds, end, frameCount);\n\t\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, result.duration ?? undefined);\n\t\t\t}\n\n\t\t\tif (streamInfo.duration !== null && spec.seconds > streamInfo.duration) {\n\t\t\t\tconst error = `Timestamp ${formatSeconds(spec.seconds)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: error, error };\n\t\t\t}\n\t\t\tconst frame = await yt.extractYouTubeFrame(ytInfo.videoId, spec.seconds, streamInfo);\n\t\t\tif (\"error\" in frame) {\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: frame.error, error: frame.error };\n\t\t\t}\n\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: `Video frame at ${options.timestamp}`, error: null, thumbnail: frame };\n\t\t}\n\n\t\tconst localVideo = await safeVideoInfo(url);\n\t\tif (localVideo.error) {\n\t\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t\t}\n\t\tif (localVideo.info) {\n\t\t\tif (spec.type === \"range\") {\n\t\t\t\tconst timestamps = frameCount\n\t\t\t\t\t? computeRangeTimestamps(spec.start, spec.end, frameCount)\n\t\t\t\t\t: computeRangeTimestamps(spec.start, spec.end);\n\t\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error);\n\t\t\t}\n\n\t\t\tif (frameCount) {\n\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\tconst timestamps = computeRangeTimestamps(spec.seconds, end, frameCount);\n\t\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error);\n\t\t\t}\n\n\t\t\tconst { extractVideoFrame } = await loadVideoExtract();\n\t\t\tconst frame = await extractVideoFrame(localVideo.info.absolutePath, spec.seconds);\n\t\t\tif (\"error\" in frame) {\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: frame.error, error: frame.error };\n\t\t\t}\n\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: `Video frame at ${options.timestamp}`, error: null, thumbnail: frame };\n\t\t}\n\n\t\treturn { url, title: \"\", content: \"\", error: \"Timestamp extraction only works with YouTube and local video files\" };\n\t}\n\n\tconst localVideo = await safeVideoInfo(url);\n\tif (localVideo.error) {\n\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t}\n\tif (localVideo.info) {\n\t\ttry {\n\t\t\tconst { extractVideo } = await loadVideoExtract();\n\t\t\tconst result = await extractVideo(localVideo.info, signal, options);\n\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t\treturn result ?? { url, title: \"\", content: \"\", error: `Video analysis requires Gemini access. Either:\\n 1. Sign into gemini.google.com in Chrome (free, uses cookies)\\n 2. Set GEMINI_API_KEY in ${WEB_SEARCH_CONFIG_PATH}` };\n\t\t} catch (err) {\n\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t\t}\n\t}\n\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") {\n\t\t\tawait validateRemoteUrl(parsed, { allowRanges: loadSsrfAllowRanges(), lookup: options?.lookup });\n\t\t}\n\t} catch (err) {\n\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t}\n\n\tif (looksLikeGitHubUrl(url)) {\n\t\ttry {\n\t\t\tconst { extractGitHub } = await loadGithubExtract();\n\t\t\tconst ghResult = await extractGitHub(url, signal, options?.forceClone);\n\t\t\tif (ghResult) return ghResult;\n\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t} catch (err) {\n\t\t\tconst message = errorMessage(err);\n\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\tif (isConfigParseError(err)) {\n\t\t\t\treturn { url, title: \"\", content: \"\", error: message };\n\t\t\t}\n\t\t}\n\t}\n\n\tconst ytInfo = isYouTubeURL(url);\n\tif (ytInfo.isYouTube) {\n\t\tlet youtubeEnabled = false;\n\t\tlet yt;\n\t\ttry {\n\t\t\tyt = await loadYoutubeExtract();\n\t\t\tyoutubeEnabled = yt.isYouTubeEnabled();\n\t\t} catch (err) {\n\t\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t\t}\n\t\tif (youtubeEnabled) {\n\t\t\ttry {\n\t\t\t\tconst ytResult = await yt.extractYouTube(url, signal, options?.prompt, options?.model);\n\t\t\t\tif (ytResult) return ytResult;\n\t\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t\t} catch (err) {\n\t\t\t\tconst message = errorMessage(err);\n\t\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\t\treturn { url, title: \"\", content: \"\", error: message };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: \"Could not extract YouTube video content. Sign into Google in Chrome for automatic access, or set GEMINI_API_KEY.\",\n\t\t\t};\n\t\t}\n\t}\n\n\tif (signal?.aborted) return abortedResult(url);\n\n\tconst httpResult = await extractViaHttp(url, signal, options);\n\n\tif (signal?.aborted) return abortedResult(url);\n\tif (!httpResult.error) return httpResult;\n\tif (NON_RECOVERABLE_ERRORS.some(prefix => httpResult.error!.startsWith(prefix))) return httpResult;\n\n\tconst jinaResult = await extractWithJinaReader(url, signal, options?.lookup);\n\tif (jinaResult) return jinaResult;\n\tif (signal?.aborted) return abortedResult(url);\n\n\tlet parallelError: string | null = null;\n\ttry {\n\t\tconst parallel = await loadParallel();\n\t\tif (parallel.isParallelAvailable()) {\n\t\t\tconst parallelResult = await parallel.extractWithParallel(url, signal, options);\n\t\t\tif (parallelResult) return parallelResult;\n\t\t}\n\t} catch (err) {\n\t\tif (isAbortError(err)) return abortedResult(url);\n\t\tparallelError = errorMessage(err);\n\t\tif (isConfigParseError(err)) {\n\t\t\treturn { ...httpResult, error: parallelError };\n\t\t}\n\t}\n\tif (signal?.aborted) return abortedResult(url);\n\n\tlet geminiResult: ExtractedContent | null = null;\n\ttry {\n\t\tconst geminiUrl = await loadGeminiUrlContext();\n\t\tgeminiResult = await geminiUrl.extractWithUrlContext(url, signal)\n\t\t\t?? await geminiUrl.extractWithGeminiWeb(url, signal);\n\t} catch (err) {\n\t\tif (isAbortError(err)) return abortedResult(url);\n\t\tif (isConfigParseError(err)) {\n\t\t\treturn { ...httpResult, error: errorMessage(err) };\n\t\t}\n\t}\n\n\tif (geminiResult) return geminiResult;\n\tif (signal?.aborted) return abortedResult(url);\n\n\tconst guidance = [\n\t\thttpResult.error,\n\t\t...(parallelError ? [`Parallel fallback failed: ${parallelError}`] : []),\n\t\t\"\",\n\t\t\"Fallback options:\",\n\t\t` \\u2022 Set PARALLEL_API_KEY in ${WEB_SEARCH_CONFIG_PATH}`,\n\t\t` \\u2022 Set GEMINI_API_KEY in ${WEB_SEARCH_CONFIG_PATH}`,\n\t\t\" \\u2022 Sign into gemini.google.com in Chrome\",\n\t\t\" \\u2022 Use web_search to find content about this topic\",\n\t].join(\"\\n\");\n\treturn { ...httpResult, error: guidance };\n}\n\nfunction isLikelyJSRendered(html: string): boolean {\n\t// Extract body content\n\tconst bodyMatch = html.match(/<body[^>]*>([\\s\\S]*?)<\\/body>/i);\n\tif (!bodyMatch) return false;\n\n\tconst bodyHtml = bodyMatch[1];\n\n\t// Strip tags to get text content\n\tconst textContent = bodyHtml\n\t\t.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n\t\t.replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n\t\t.replace(/<[^>]+>/g, \"\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\n\t// Count scripts\n\tconst scriptCount = (html.match(/<script/gi) || []).length;\n\n\t// Heuristic: little text content but many scripts suggests JS rendering\n\treturn textContent.length < 500 && scriptCount > 3;\n}\n\nasync function extractViaHttp(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent> {\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url });\n\n\tconst controller = new AbortController();\n\tconst timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n\tconst onAbort = () => controller.abort();\n\tsignal?.addEventListener(\"abort\", onAbort);\n\n\ttry {\n\t\tconst response = await fetchRemoteUrl(\n\t\t\turl,\n\t\t\t{\n\t\t\t\tsignal: controller.signal,\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\",\n\t\t\t\t\t\"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8\",\n\t\t\t\t\t\"Accept-Language\": \"en-US,en;q=0.9\",\n\t\t\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t\t\t\t\"Sec-Fetch-Dest\": \"document\",\n\t\t\t\t\t\"Sec-Fetch-Mode\": \"navigate\",\n\t\t\t\t\t\"Sec-Fetch-Site\": \"none\",\n\t\t\t\t\t\"Sec-Fetch-User\": \"?1\",\n\t\t\t\t\t\"Upgrade-Insecure-Requests\": \"1\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ allowRanges: loadSsrfAllowRanges(), lookup: options?.lookup },\n\t\t);\n\n\t\tif (!response.ok) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `HTTP ${response.status}: ${response.statusText}`,\n\t\t\t};\n\t\t}\n\n\t\tconst contentLengthHeader = response.headers.get(\"content-length\");\n\t\tconst contentType = response.headers.get(\"content-type\") || \"\";\n\t\tconst isPDFContent = isPDF(url, contentType);\n\t\tconst maxResponseSize = isPDFContent ? 20 * 1024 * 1024 : 5 * 1024 * 1024;\n\t\tif (contentLengthHeader) {\n\t\t\tconst contentLength = parseInt(contentLengthHeader, 10);\n\t\t\tif (contentLength > maxResponseSize) {\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn {\n\t\t\t\t\turl,\n\t\t\t\t\ttitle: \"\",\n\t\t\t\t\tcontent: \"\",\n\t\t\t\t\terror: `Response too large (${Math.round(contentLength / 1024 / 1024)}MB)`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif (isPDFContent) {\n\t\t\ttry {\n\t\t\t\tconst buffer = await response.arrayBuffer();\n\t\t\t\tconst { extractPDFToMarkdown } = await loadPdfExtract();\n\t\t\t\tconst result = await extractPDFToMarkdown(buffer, url);\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn {\n\t\t\t\t\turl,\n\t\t\t\t\ttitle: result.title,\n\t\t\t\t\tcontent: `PDF extracted and saved to: ${result.outputPath}\\n\\nPages: ${result.pages}\\nCharacters: ${result.chars}`,\n\t\t\t\t\terror: null,\n\t\t\t\t};\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\tactivityMonitor.logError(activityId, message);\n\t\t\t\treturn { url, title: \"\", content: \"\", error: `PDF extraction failed: ${message}` };\n\t\t\t}\n\t\t}\n\n\t\tif (contentType.includes(\"application/octet-stream\") ||\n\t\t\tcontentType.includes(\"image/\") ||\n\t\t\tcontentType.includes(\"audio/\") ||\n\t\t\tcontentType.includes(\"video/\") ||\n\t\t\tcontentType.includes(\"application/zip\")) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `Unsupported content type: ${contentType.split(\";\")[0]}`,\n\t\t\t};\n\t\t}\n\n\t\tconst text = await response.text();\n\t\tconst isHTML = contentType.includes(\"text/html\") || contentType.includes(\"application/xhtml+xml\");\n\n\t\tif (!isHTML) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\tconst title = extractTextTitle(text, url);\n\t\t\treturn { url, title, content: text, error: null };\n\t\t}\n\n\t\tconst { document } = parseHTML(text);\n\t\tconst reader = new Readability(document as unknown as Document);\n\t\tconst article = reader.parse();\n\n\t\tif (!article) {\n\t\t\tconst rscResult = extractRSCContent(text);\n\t\t\tif (rscResult) {\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn { url, title: rscResult.title, content: rscResult.content, error: null };\n\t\t\t}\n\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\n\t\t\t// Provide more specific error message\n\t\t\tconst jsRendered = isLikelyJSRendered(text);\n\t\t\tconst errorMsg = jsRendered\n\t\t\t\t? \"Page appears to be JavaScript-rendered (content loads dynamically)\"\n\t\t\t\t: \"Could not extract readable content from HTML structure\";\n\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: errorMsg,\n\t\t\t};\n\t\t}\n\n\t\tconst markdown = turndown.turndown(article.content);\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\n\t\tif (markdown.length < MIN_USEFUL_CONTENT) {\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: article.title || \"\",\n\t\t\t\tcontent: markdown,\n\t\t\t\terror: isLikelyJSRendered(text)\n\t\t\t\t\t? \"Page appears to be JavaScript-rendered (content loads dynamically)\"\n\t\t\t\t\t: \"Extracted content appears incomplete\",\n\t\t\t};\n\t\t}\n\n\t\treturn { url, title: article.title || \"\", content: markdown, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (message.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, message);\n\t\t}\n\t\treturn { url, title: \"\", content: \"\", error: message };\n\t} finally {\n\t\tclearTimeout(timeoutId);\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t}\n}\n\nexport function extractHeadingTitle(text: string): string | null {\n\tconst match = text.match(/^#{1,2}\\s+(.+)/m);\n\tif (!match) return null;\n\tconst cleaned = match[1].replace(/\\*+/g, \"\").trim();\n\treturn cleaned || null;\n}\n\nfunction extractTextTitle(text: string, url: string): string {\n\treturn extractHeadingTitle(text) ?? (new URL(url).pathname.split(\"/\").pop() || url);\n}\n\nexport async function fetchAllContent(\n\turls: string[],\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent[]> {\n\treturn Promise.all(urls.map((url) => fetchLimit(() => extractContent(url, signal, options))));\n}\n"]}
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-web-access/extract.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAqC,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAgDtF;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAuB9C;AAyBD,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAC3D,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAgJD,wBAAsB,cAAc,CACnC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,gBAAgB,CAAC,CA0Q3B;AA0LD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/D;AAMD,wBAAsB,eAAe,CACpC,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAE7B","sourcesContent":["// @ts-nocheck\nimport { Readability } from \"@mozilla/readability\";\nimport { parseHTML } from \"linkedom\";\nimport TurndownService from \"turndown\";\nimport pLimit from \"p-limit\";\nimport { readBoundedBody } from \"./bounded-body.ts\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { extractRSCContent } from \"./rsc-extract.ts\";\nimport {\n\tloadGeminiUrlContext,\n\tloadGithubExtract,\n\tloadParallel,\n\tloadPdfExtract,\n\tloadVideoExtract,\n\tloadYoutubeExtract,\n} from \"./lazy.ts\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { fetchRemoteUrl, validateRemoteUrl, type Lookup } from \"./ssrf-protection.ts\";\nimport { formatSeconds, getWebSearchConfigPath } from \"./utils.ts\";\n\nconst YOUTUBE_URL_RE =\n\t/(?:(?:www\\.|m\\.)?youtube\\.com\\/(?:watch\\?.*v=|shorts\\/|live\\/|embed\\/|v\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/;\n\nfunction isYouTubeURL(url: string): { isYouTube: boolean; videoId: string | null } {\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.pathname === \"/playlist\") {\n\t\t\treturn { isYouTube: false, videoId: null };\n\t\t}\n\t} catch {\n\t}\n\tconst match = url.match(YOUTUBE_URL_RE);\n\tif (!match) return { isYouTube: false, videoId: null };\n\treturn { isYouTube: true, videoId: match[1] };\n}\n\nfunction isPDF(url: string, contentType?: string): boolean {\n\tif (contentType?.includes(\"application/pdf\")) return true;\n\ttry {\n\t\treturn new URL(url).pathname.toLowerCase().endsWith(\".pdf\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction looksLikeLocalPath(input: string): boolean {\n\treturn input.startsWith(\"/\") || input.startsWith(\"./\") || input.startsWith(\"../\") || input.startsWith(\"file://\");\n}\n\nfunction looksLikeGitHubUrl(url: string): boolean {\n\ttry {\n\t\tconst host = new URL(url).hostname.toLowerCase();\n\t\treturn host === \"github.com\" || host === \"www.github.com\" || host.endsWith(\".github.com\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nconst DEFAULT_TIMEOUT_MS = 30000;\nconst CONCURRENT_LIMIT = 3;\n\nconst NON_RECOVERABLE_ERRORS = [\"Unsupported content type\", \"Response too large\"];\nconst MIN_USEFUL_CONTENT = 500;\nconst WEB_SEARCH_CONFIG_PATH = getWebSearchConfigPath();\n\n/**\n * Read `ssrf.allowRanges` (CIDR strings) from web-search.json. Returns [] when\n * the file is missing, unreadable, or the key is unset so SSRF protection stays\n * fully on by default. Throws when `ssrf.allowRanges` is present but not an array\n * so a mistyped value (e.g. a bare string instead of a JSON array) fails loudly\n * instead of being silently ignored. Exempts synthetic ranges used by TUN/fake-IP\n * proxies (e.g. 198.18.0.0/15).\n */\nexport function loadSsrfAllowRanges(): string[] {\n\tlet value: unknown;\n\ttry {\n\t\tif (!existsSync(WEB_SEARCH_CONFIG_PATH)) return [];\n\t\tconst raw = readFileSync(WEB_SEARCH_CONFIG_PATH, \"utf-8\");\n\t\tvalue = (JSON.parse(raw) as { ssrf?: { allowRanges?: unknown } })?.ssrf?.allowRanges;\n\t} catch {\n\t\t// Missing/unreadable file or invalid JSON: fail safe with SSRF fully on.\n\t\treturn [];\n\t}\n\tif (value === undefined || value === null) return [];\n\tif (!Array.isArray(value)) {\n\t\tthrow new Error(`ssrf.allowRanges in ${WEB_SEARCH_CONFIG_PATH} must be an array of CIDR strings`);\n\t}\n\tconst ranges: string[] = [];\n\tfor (const [index, entry] of value.entries()) {\n\t\tif (typeof entry !== \"string\") {\n\t\t\tthrow new Error(`ssrf.allowRanges in ${WEB_SEARCH_CONFIG_PATH} must contain only CIDR strings; entry ${index + 1} is ${typeof entry}`);\n\t\t}\n\t\tconst trimmed = entry.trim();\n\t\tif (trimmed) ranges.push(trimmed);\n\t}\n\treturn ranges;\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction isConfigParseError(err: unknown): boolean {\n\treturn errorMessage(err).startsWith(\"Failed to parse \");\n}\n\nfunction isAbortError(err: unknown): boolean {\n\treturn errorMessage(err).toLowerCase().includes(\"abort\");\n}\n\nfunction abortedResult(url: string): ExtractedContent {\n\treturn { url, title: \"\", content: \"\", error: \"Aborted\" };\n}\n\nconst turndown = new TurndownService({\n\theadingStyle: \"atx\",\n\tcodeBlockStyle: \"fenced\",\n});\n\nconst fetchLimit = pLimit(CONCURRENT_LIMIT);\n\nexport interface VideoFrame {\n\tdata: string;\n\tmimeType: string;\n\ttimestamp: string;\n}\n\nexport type FrameData = { data: string; mimeType: string };\nexport type FrameResult = FrameData | { error: string };\n\nexport interface ExtractedContent {\n\turl: string;\n\ttitle: string;\n\tcontent: string;\n\terror: string | null;\n\tthumbnail?: { data: string; mimeType: string };\n\tframes?: VideoFrame[];\n\tduration?: number;\n}\n\nexport interface ExtractOptions {\n\ttimeoutMs?: number;\n\tforceClone?: boolean;\n\tprompt?: string;\n\ttimestamp?: string;\n\tframes?: number;\n\tmodel?: string;\n\t/** Custom DNS resolver used for SSRF validation. Primarily a test seam. */\n\tlookup?: Lookup;\n}\n\nconst JINA_READER_BASE = \"https://r.jina.ai/\";\nconst JINA_TIMEOUT_MS = 30000;\n\nasync function extractWithJinaReader(\n\turl: string,\n\tsignal?: AbortSignal,\n\tlookup?: Lookup,\n): Promise<ExtractedContent | null> {\n\tconst jinaUrl = JINA_READER_BASE + url;\n\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query: `jina: ${url}` });\n\n\ttry {\n\t\tawait validateRemoteUrl(url, { allowRanges: loadSsrfAllowRanges(), lookup });\n\t\tconst res = await fetch(jinaUrl, {\n\t\t\theaders: {\n\t\t\t\t\"Accept\": \"text/markdown\",\n\t\t\t\t\"X-No-Cache\": \"true\",\n\t\t\t},\n\t\t\tsignal: AbortSignal.any([\n\t\t\t\tAbortSignal.timeout(JINA_TIMEOUT_MS),\n\t\t\t\t...(signal ? [signal] : []),\n\t\t\t]),\n\t\t});\n\n\t\tif (!res.ok) {\n\t\t\tactivityMonitor.logComplete(activityId, res.status);\n\t\t\treturn null;\n\t\t}\n\n\t\tconst content = await res.text();\n\t\tactivityMonitor.logComplete(activityId, res.status);\n\n\t\tconst contentStart = content.indexOf(\"Markdown Content:\");\n\t\tif (contentStart < 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst markdownPart = content.slice(contentStart + 17).trim(); // 17 = \"Markdown Content:\".length\n\n\t\t// Check for failed JS rendering or minimal content\n\t\tif (markdownPart.length < 100 ||\n\t\t\tmarkdownPart.startsWith(\"Loading...\") ||\n\t\t\tmarkdownPart.startsWith(\"Please enable JavaScript\")) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst title = extractHeadingTitle(markdownPart) ?? (new URL(url).pathname.split(\"/\").pop() || url);\n\t\treturn { url, title, content: markdownPart, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (message.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, message);\n\t\t}\n\t\treturn null;\n\t}\n}\n\nfunction parseTimestamp(ts: string): number | null {\n\tconst num = Number(ts);\n\tif (!isNaN(num) && num >= 0) return Math.floor(num);\n\tconst parts = ts.split(\":\").map(Number);\n\tif (parts.some(p => isNaN(p) || p < 0)) return null;\n\tif (parts.length === 3) return Math.floor(parts[0] * 3600 + parts[1] * 60 + parts[2]);\n\tif (parts.length === 2) return Math.floor(parts[0] * 60 + parts[1]);\n\treturn null;\n}\n\ntype TimestampSpec = { type: \"single\"; seconds: number } | { type: \"range\"; start: number; end: number };\n\nfunction parseTimestampSpec(ts: string): TimestampSpec | null {\n\tconst dashIdx = ts.indexOf(\"-\", 1);\n\tif (dashIdx > 0) {\n\t\tconst start = parseTimestamp(ts.slice(0, dashIdx));\n\t\tconst end = parseTimestamp(ts.slice(dashIdx + 1));\n\t\tif (start !== null && end !== null && end > start) return { type: \"range\", start, end };\n\t}\n\tconst seconds = parseTimestamp(ts);\n\treturn seconds !== null ? { type: \"single\", seconds } : null;\n}\n\nconst DEFAULT_RANGE_FRAMES = 6;\nconst MIN_FRAME_INTERVAL = 5;\n\nfunction computeRangeTimestamps(start: number, end: number, maxFrames: number = DEFAULT_RANGE_FRAMES): number[] {\n\tif (maxFrames <= 1) return [start];\n\tconst duration = end - start;\n\tconst idealInterval = duration / (maxFrames - 1);\n\tif (idealInterval < MIN_FRAME_INTERVAL) {\n\t\tconst timestamps: number[] = [];\n\t\tfor (let t = start; t <= end && timestamps.length < maxFrames; t += MIN_FRAME_INTERVAL) {\n\t\t\ttimestamps.push(t);\n\t\t}\n\t\treturn timestamps;\n\t}\n\treturn Array.from({ length: maxFrames }, (_, i) => Math.round(start + i * idealInterval));\n}\n\nfunction buildFrameResult(\n\turl: string, label: string, requestedCount: number,\n\tframes: VideoFrame[], error: string | null, duration?: number,\n): ExtractedContent {\n\tif (frames.length === 0) {\n\t\tconst msg = error ?? \"Frame extraction failed\";\n\t\treturn { url, title: `Frames ${label} (0/${requestedCount})`, content: msg, error: msg };\n\t}\n\treturn {\n\t\turl,\n\t\ttitle: `Frames ${label} (${frames.length}/${requestedCount})`,\n\t\tcontent: `${frames.length} frames extracted from ${label}`,\n\t\terror: null,\n\t\tframes,\n\t\tduration,\n\t};\n}\n\nasync function extractLocalFrames(\n\tfilePath: string, timestamps: number[],\n): Promise<{ frames: VideoFrame[]; error: string | null }> {\n\tconst { extractVideoFrame } = await loadVideoExtract();\n\tconst results = await Promise.all(timestamps.map(async (t) => {\n\t\tconst frame = await extractVideoFrame(filePath, t);\n\t\tif (\"error\" in frame) return { error: frame.error };\n\t\treturn { ...frame, timestamp: formatSeconds(t) };\n\t}));\n\tconst frames = results.filter((f): f is VideoFrame => \"data\" in f);\n\tconst firstError = results.find((f): f is { error: string } => \"error\" in f);\n\treturn { frames, error: frames.length === 0 && firstError ? firstError.error : null };\n}\n\nasync function safeVideoInfo(url: string): Promise<{ info: Awaited<ReturnType<typeof loadVideoExtract>> extends { isVideoFile: infer F } ? (F extends (...args: any) => infer R ? R : null) : null; error?: string }> {\n\tif (!looksLikeLocalPath(url)) return { info: null };\n\ttry {\n\t\tconst { isVideoFile } = await loadVideoExtract();\n\t\treturn { info: isVideoFile(url) };\n\t} catch (err) {\n\t\treturn { info: null, error: errorMessage(err) };\n\t}\n}\n\nexport async function extractContent(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent> {\n\tif (signal?.aborted) {\n\t\treturn { url, title: \"\", content: \"\", error: \"Aborted\" };\n\t}\n\n\tif (options?.frames && !options.timestamp) {\n\t\tconst frameCount = options.frames;\n\t\tconst ytInfo = isYouTubeURL(url);\n\t\tif (ytInfo.isYouTube && ytInfo.videoId) {\n\t\t\tconst yt = await loadYoutubeExtract();\n\t\t\tconst streamInfo = await yt.getYouTubeStreamInfo(ytInfo.videoId);\n\t\t\tif (\"error\" in streamInfo) {\n\t\t\t\treturn { url, title: \"Frames\", content: streamInfo.error, error: streamInfo.error };\n\t\t\t}\n\t\t\tif (streamInfo.duration === null) {\n\t\t\t\tconst error = \"Cannot determine video duration. Use a timestamp range instead.\";\n\t\t\t\treturn { url, title: \"Frames\", content: error, error };\n\t\t\t}\n\t\t\tconst dur = Math.floor(streamInfo.duration);\n\t\t\tconst timestamps = computeRangeTimestamps(0, dur, frameCount);\n\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\tconst label = `${formatSeconds(0)}-${formatSeconds(dur)}`;\n\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, streamInfo.duration);\n\t\t}\n\n\t\tconst localVideo = await safeVideoInfo(url);\n\t\tif (localVideo.error) {\n\t\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t\t}\n\t\tif (localVideo.info) {\n\t\t\tconst { getLocalVideoDuration } = await loadVideoExtract();\n\t\t\tconst durationResult = await getLocalVideoDuration(localVideo.info.absolutePath);\n\t\t\tif (typeof durationResult !== \"number\") {\n\t\t\t\treturn { url, title: \"Frames\", content: durationResult.error, error: durationResult.error };\n\t\t\t}\n\t\t\tconst dur = Math.floor(durationResult);\n\t\t\tconst timestamps = computeRangeTimestamps(0, dur, frameCount);\n\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\tconst label = `${formatSeconds(0)}-${formatSeconds(dur)}`;\n\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, durationResult);\n\t\t}\n\n\t\treturn { url, title: \"\", content: \"\", error: \"Frame extraction only works with YouTube and local video files\" };\n\t}\n\n\tif (options?.timestamp) {\n\t\tconst spec = parseTimestampSpec(options.timestamp);\n\t\tif (!spec) {\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `Invalid timestamp format: \"${options.timestamp}\". Use \"H:MM:SS\", \"MM:SS\", \"85\", or \"start-end\".`,\n\t\t\t};\n\t\t}\n\n\t\tconst frameCount = options.frames;\n\t\tconst ytInfo = isYouTubeURL(url);\n\t\tif (ytInfo.isYouTube && ytInfo.videoId) {\n\t\t\tconst yt = await loadYoutubeExtract();\n\t\t\tconst streamInfo = await yt.getYouTubeStreamInfo(ytInfo.videoId);\n\t\t\tif (\"error\" in streamInfo) {\n\t\t\t\tif (spec.type === \"range\") {\n\t\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t\t}\n\t\t\t\tif (frameCount) {\n\t\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t\t}\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t}\n\n\t\t\tif (spec.type === \"range\") {\n\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\tif (streamInfo.duration !== null && spec.end > streamInfo.duration) {\n\t\t\t\t\tconst error = `Timestamp ${formatSeconds(spec.end)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: error, error };\n\t\t\t\t}\n\t\t\t\tconst timestamps = frameCount\n\t\t\t\t\t? computeRangeTimestamps(spec.start, spec.end, frameCount)\n\t\t\t\t\t: computeRangeTimestamps(spec.start, spec.end);\n\t\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, result.duration ?? undefined);\n\t\t\t}\n\n\t\t\tif (frameCount) {\n\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\tif (streamInfo.duration !== null && end > streamInfo.duration) {\n\t\t\t\t\tconst error = `Timestamp ${formatSeconds(end)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: error, error };\n\t\t\t\t}\n\t\t\t\tconst timestamps = computeRangeTimestamps(spec.seconds, end, frameCount);\n\t\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, result.duration ?? undefined);\n\t\t\t}\n\n\t\t\tif (streamInfo.duration !== null && spec.seconds > streamInfo.duration) {\n\t\t\t\tconst error = `Timestamp ${formatSeconds(spec.seconds)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: error, error };\n\t\t\t}\n\t\t\tconst frame = await yt.extractYouTubeFrame(ytInfo.videoId, spec.seconds, streamInfo);\n\t\t\tif (\"error\" in frame) {\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: frame.error, error: frame.error };\n\t\t\t}\n\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: `Video frame at ${options.timestamp}`, error: null, thumbnail: frame };\n\t\t}\n\n\t\tconst localVideo = await safeVideoInfo(url);\n\t\tif (localVideo.error) {\n\t\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t\t}\n\t\tif (localVideo.info) {\n\t\t\tif (spec.type === \"range\") {\n\t\t\t\tconst timestamps = frameCount\n\t\t\t\t\t? computeRangeTimestamps(spec.start, spec.end, frameCount)\n\t\t\t\t\t: computeRangeTimestamps(spec.start, spec.end);\n\t\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error);\n\t\t\t}\n\n\t\t\tif (frameCount) {\n\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\tconst timestamps = computeRangeTimestamps(spec.seconds, end, frameCount);\n\t\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error);\n\t\t\t}\n\n\t\t\tconst { extractVideoFrame } = await loadVideoExtract();\n\t\t\tconst frame = await extractVideoFrame(localVideo.info.absolutePath, spec.seconds);\n\t\t\tif (\"error\" in frame) {\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: frame.error, error: frame.error };\n\t\t\t}\n\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: `Video frame at ${options.timestamp}`, error: null, thumbnail: frame };\n\t\t}\n\n\t\treturn { url, title: \"\", content: \"\", error: \"Timestamp extraction only works with YouTube and local video files\" };\n\t}\n\n\tconst localVideo = await safeVideoInfo(url);\n\tif (localVideo.error) {\n\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t}\n\tif (localVideo.info) {\n\t\ttry {\n\t\t\tconst { extractVideo } = await loadVideoExtract();\n\t\t\tconst result = await extractVideo(localVideo.info, signal, options);\n\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t\treturn result ?? { url, title: \"\", content: \"\", error: `Video analysis requires Gemini access. Either:\\n 1. Sign into gemini.google.com in Chrome (free, uses cookies)\\n 2. Set GEMINI_API_KEY in ${WEB_SEARCH_CONFIG_PATH}` };\n\t\t} catch (err) {\n\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t\t}\n\t}\n\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") {\n\t\t\tawait validateRemoteUrl(parsed, { allowRanges: loadSsrfAllowRanges(), lookup: options?.lookup });\n\t\t}\n\t} catch (err) {\n\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t}\n\n\tif (looksLikeGitHubUrl(url)) {\n\t\ttry {\n\t\t\tconst { extractGitHub } = await loadGithubExtract();\n\t\t\tconst ghResult = await extractGitHub(url, signal, options?.forceClone);\n\t\t\tif (ghResult) return ghResult;\n\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t} catch (err) {\n\t\t\tconst message = errorMessage(err);\n\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\tif (isConfigParseError(err)) {\n\t\t\t\treturn { url, title: \"\", content: \"\", error: message };\n\t\t\t}\n\t\t}\n\t}\n\n\tconst ytInfo = isYouTubeURL(url);\n\tif (ytInfo.isYouTube) {\n\t\tlet youtubeEnabled = false;\n\t\tlet yt;\n\t\ttry {\n\t\t\tyt = await loadYoutubeExtract();\n\t\t\tyoutubeEnabled = yt.isYouTubeEnabled();\n\t\t} catch (err) {\n\t\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t\t}\n\t\tif (youtubeEnabled) {\n\t\t\ttry {\n\t\t\t\tconst ytResult = await yt.extractYouTube(url, signal, options?.prompt, options?.model);\n\t\t\t\tif (ytResult) return ytResult;\n\t\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t\t} catch (err) {\n\t\t\t\tconst message = errorMessage(err);\n\t\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\t\treturn { url, title: \"\", content: \"\", error: message };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: \"Could not extract YouTube video content. Sign into Google in Chrome for automatic access, or set GEMINI_API_KEY.\",\n\t\t\t};\n\t\t}\n\t}\n\n\tif (signal?.aborted) return abortedResult(url);\n\n\tconst httpResult = await extractViaHttp(url, signal, options);\n\n\tif (signal?.aborted) return abortedResult(url);\n\tif (!httpResult.error) return httpResult;\n\tif (NON_RECOVERABLE_ERRORS.some(prefix => httpResult.error!.startsWith(prefix))) return httpResult;\n\n\tconst jinaResult = await extractWithJinaReader(url, signal, options?.lookup);\n\tif (jinaResult) return jinaResult;\n\tif (signal?.aborted) return abortedResult(url);\n\n\tlet parallelError: string | null = null;\n\ttry {\n\t\tconst parallel = await loadParallel();\n\t\tif (parallel.isParallelAvailable()) {\n\t\t\tconst parallelResult = await parallel.extractWithParallel(url, signal, options);\n\t\t\tif (parallelResult) return parallelResult;\n\t\t}\n\t} catch (err) {\n\t\tif (isAbortError(err)) return abortedResult(url);\n\t\tparallelError = errorMessage(err);\n\t\tif (isConfigParseError(err)) {\n\t\t\treturn { ...httpResult, error: parallelError };\n\t\t}\n\t}\n\tif (signal?.aborted) return abortedResult(url);\n\n\tlet geminiResult: ExtractedContent | null = null;\n\ttry {\n\t\tconst geminiUrl = await loadGeminiUrlContext();\n\t\tgeminiResult = await geminiUrl.extractWithUrlContext(url, signal)\n\t\t\t?? await geminiUrl.extractWithGeminiWeb(url, signal);\n\t} catch (err) {\n\t\tif (isAbortError(err)) return abortedResult(url);\n\t\tif (isConfigParseError(err)) {\n\t\t\treturn { ...httpResult, error: errorMessage(err) };\n\t\t}\n\t}\n\n\tif (geminiResult) return geminiResult;\n\tif (signal?.aborted) return abortedResult(url);\n\n\tconst guidance = [\n\t\thttpResult.error,\n\t\t...(parallelError ? [`Parallel fallback failed: ${parallelError}`] : []),\n\t\t\"\",\n\t\t\"Fallback options:\",\n\t\t` \\u2022 Set PARALLEL_API_KEY in ${WEB_SEARCH_CONFIG_PATH}`,\n\t\t` \\u2022 Set GEMINI_API_KEY in ${WEB_SEARCH_CONFIG_PATH}`,\n\t\t\" \\u2022 Sign into gemini.google.com in Chrome\",\n\t\t\" \\u2022 Use web_search to find content about this topic\",\n\t].join(\"\\n\");\n\treturn { ...httpResult, error: guidance };\n}\n\nfunction isLikelyJSRendered(html: string): boolean {\n\t// Extract body content\n\tconst bodyMatch = html.match(/<body[^>]*>([\\s\\S]*?)<\\/body>/i);\n\tif (!bodyMatch) return false;\n\n\tconst bodyHtml = bodyMatch[1];\n\n\t// Strip tags to get text content\n\tconst textContent = bodyHtml\n\t\t.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n\t\t.replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n\t\t.replace(/<[^>]+>/g, \"\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\n\t// Count scripts\n\tconst scriptCount = (html.match(/<script/gi) || []).length;\n\n\t// Heuristic: little text content but many scripts suggests JS rendering\n\treturn textContent.length < 500 && scriptCount > 3;\n}\n\nasync function extractViaHttp(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent> {\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url });\n\n\tconst controller = new AbortController();\n\tconst timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n\tconst onAbort = () => controller.abort();\n\tif (signal?.aborted) controller.abort();\n\tsignal?.addEventListener(\"abort\", onAbort);\n\n\ttry {\n\t\tconst response = await fetchRemoteUrl(\n\t\t\turl,\n\t\t\t{\n\t\t\t\tsignal: controller.signal,\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\",\n\t\t\t\t\t\"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8\",\n\t\t\t\t\t\"Accept-Language\": \"en-US,en;q=0.9\",\n\t\t\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t\t\t\t\"Sec-Fetch-Dest\": \"document\",\n\t\t\t\t\t\"Sec-Fetch-Mode\": \"navigate\",\n\t\t\t\t\t\"Sec-Fetch-Site\": \"none\",\n\t\t\t\t\t\"Sec-Fetch-User\": \"?1\",\n\t\t\t\t\t\"Upgrade-Insecure-Requests\": \"1\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ allowRanges: loadSsrfAllowRanges(), lookup: options?.lookup },\n\t\t);\n\n\t\tif (!response.ok) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `HTTP ${response.status}: ${response.statusText}`,\n\t\t\t};\n\t\t}\n\n\t\tconst contentLengthHeader = response.headers.get(\"content-length\");\n\t\tconst contentType = response.headers.get(\"content-type\") || \"\";\n\t\tconst isPDFContent = isPDF(url, contentType);\n\t\tconst maxResponseSize = isPDFContent ? 20 * 1024 * 1024 : 5 * 1024 * 1024;\n\t\tif (contentLengthHeader) {\n\t\t\tconst contentLength = parseInt(contentLengthHeader, 10);\n\t\t\tif (contentLength > maxResponseSize) {\n\t\t\t\tawait response.body?.cancel();\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn {\n\t\t\t\t\turl,\n\t\t\t\t\ttitle: \"\",\n\t\t\t\t\tcontent: \"\",\n\t\t\t\t\terror: `Response too large (${Math.round(contentLength / 1024 / 1024)}MB)`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif (isPDFContent) {\n\t\t\tconst bytes = await readBoundedBody(response, maxResponseSize, controller.signal);\n\t\t\ttry {\n\t\t\t\tconst buffer = bytes.buffer;\n\t\t\t\tconst { extractPDFToMarkdown } = await loadPdfExtract();\n\t\t\t\tconst result = await extractPDFToMarkdown(buffer, url);\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn {\n\t\t\t\t\turl,\n\t\t\t\t\ttitle: result.title,\n\t\t\t\t\tcontent: `PDF extracted and saved to: ${result.outputPath}\\n\\nPages: ${result.pages}\\nCharacters: ${result.chars}`,\n\t\t\t\t\terror: null,\n\t\t\t\t};\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\tactivityMonitor.logError(activityId, message);\n\t\t\t\treturn { url, title: \"\", content: \"\", error: `PDF extraction failed: ${message}` };\n\t\t\t}\n\t\t}\n\n\t\tif (contentType.includes(\"application/octet-stream\") ||\n\t\t\tcontentType.includes(\"image/\") ||\n\t\t\tcontentType.includes(\"audio/\") ||\n\t\t\tcontentType.includes(\"video/\") ||\n\t\t\tcontentType.includes(\"application/zip\")) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `Unsupported content type: ${contentType.split(\";\")[0]}`,\n\t\t\t};\n\t\t}\n\n\t\tconst text = new TextDecoder().decode(await readBoundedBody(response, maxResponseSize, controller.signal));\n\t\tconst isHTML = contentType.includes(\"text/html\") || contentType.includes(\"application/xhtml+xml\");\n\n\t\tif (!isHTML) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\tconst title = extractTextTitle(text, url);\n\t\t\treturn { url, title, content: text, error: null };\n\t\t}\n\n\t\tconst { document } = parseHTML(text);\n\t\tconst reader = new Readability(document as unknown as Document);\n\t\tconst article = reader.parse();\n\n\t\tif (!article) {\n\t\t\tconst rscResult = extractRSCContent(text);\n\t\t\tif (rscResult) {\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn { url, title: rscResult.title, content: rscResult.content, error: null };\n\t\t\t}\n\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\n\t\t\t// Provide more specific error message\n\t\t\tconst jsRendered = isLikelyJSRendered(text);\n\t\t\tconst errorMsg = jsRendered\n\t\t\t\t? \"Page appears to be JavaScript-rendered (content loads dynamically)\"\n\t\t\t\t: \"Could not extract readable content from HTML structure\";\n\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: errorMsg,\n\t\t\t};\n\t\t}\n\n\t\tconst markdown = turndown.turndown(article.content);\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\n\t\tif (markdown.length < MIN_USEFUL_CONTENT) {\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: article.title || \"\",\n\t\t\t\tcontent: markdown,\n\t\t\t\terror: isLikelyJSRendered(text)\n\t\t\t\t\t? \"Page appears to be JavaScript-rendered (content loads dynamically)\"\n\t\t\t\t\t: \"Extracted content appears incomplete\",\n\t\t\t};\n\t\t}\n\n\t\treturn { url, title: article.title || \"\", content: markdown, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (message.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, message);\n\t\t}\n\t\treturn { url, title: \"\", content: \"\", error: message };\n\t} finally {\n\t\tclearTimeout(timeoutId);\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t}\n}\n\nexport function extractHeadingTitle(text: string): string | null {\n\tconst match = text.match(/^#{1,2}\\s+(.+)/m);\n\tif (!match) return null;\n\tconst cleaned = match[1].replace(/\\*+/g, \"\").trim();\n\treturn cleaned || null;\n}\n\nfunction extractTextTitle(text: string, url: string): string {\n\treturn extractHeadingTitle(text) ?? (new URL(url).pathname.split(\"/\").pop() || url);\n}\n\nexport async function fetchAllContent(\n\turls: string[],\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent[]> {\n\treturn Promise.all(urls.map((url) => fetchLimit(() => extractContent(url, signal, options))));\n}\n"]}
@@ -3,6 +3,7 @@ import { Readability } from "@mozilla/readability";
3
3
  import { parseHTML } from "linkedom";
4
4
  import TurndownService from "turndown";
5
5
  import pLimit from "p-limit";
6
+ import { readBoundedBody } from "./bounded-body.js";
6
7
  import { activityMonitor } from "./activity.js";
7
8
  import { extractRSCContent } from "./rsc-extract.js";
8
9
  import { loadGeminiUrlContext, loadGithubExtract, loadParallel, loadPdfExtract, loadVideoExtract, loadYoutubeExtract, } from "./lazy.js";
@@ -523,6 +524,8 @@ async function extractViaHttp(url, signal, options) {
523
524
  const controller = new AbortController();
524
525
  const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
525
526
  const onAbort = () => controller.abort();
527
+ if (signal?.aborted)
528
+ controller.abort();
526
529
  signal?.addEventListener("abort", onAbort);
527
530
  try {
528
531
  const response = await fetchRemoteUrl(url, {
@@ -555,6 +558,7 @@ async function extractViaHttp(url, signal, options) {
555
558
  if (contentLengthHeader) {
556
559
  const contentLength = parseInt(contentLengthHeader, 10);
557
560
  if (contentLength > maxResponseSize) {
561
+ await response.body?.cancel();
558
562
  activityMonitor.logComplete(activityId, response.status);
559
563
  return {
560
564
  url,
@@ -565,8 +569,9 @@ async function extractViaHttp(url, signal, options) {
565
569
  }
566
570
  }
567
571
  if (isPDFContent) {
572
+ const bytes = await readBoundedBody(response, maxResponseSize, controller.signal);
568
573
  try {
569
- const buffer = await response.arrayBuffer();
574
+ const buffer = bytes.buffer;
570
575
  const { extractPDFToMarkdown } = await loadPdfExtract();
571
576
  const result = await extractPDFToMarkdown(buffer, url);
572
577
  activityMonitor.logComplete(activityId, response.status);
@@ -596,7 +601,7 @@ async function extractViaHttp(url, signal, options) {
596
601
  error: `Unsupported content type: ${contentType.split(";")[0]}`,
597
602
  };
598
603
  }
599
- const text = await response.text();
604
+ const text = new TextDecoder().decode(await readBoundedBody(response, maxResponseSize, controller.signal));
600
605
  const isHTML = contentType.includes("text/html") || contentType.includes("application/xhtml+xml");
601
606
  if (!isHTML) {
602
607
  activityMonitor.logComplete(activityId, response.status);
@@ -1 +1 @@
1
- {"version":3,"file":"extract.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-web-access/extract.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport { Readability } from \"@mozilla/readability\";\nimport { parseHTML } from \"linkedom\";\nimport TurndownService from \"turndown\";\nimport pLimit from \"p-limit\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { extractRSCContent } from \"./rsc-extract.ts\";\nimport {\n\tloadGeminiUrlContext,\n\tloadGithubExtract,\n\tloadParallel,\n\tloadPdfExtract,\n\tloadVideoExtract,\n\tloadYoutubeExtract,\n} from \"./lazy.ts\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { fetchRemoteUrl, validateRemoteUrl, type Lookup } from \"./ssrf-protection.ts\";\nimport { formatSeconds, getWebSearchConfigPath } from \"./utils.ts\";\n\nconst YOUTUBE_URL_RE =\n\t/(?:(?:www\\.|m\\.)?youtube\\.com\\/(?:watch\\?.*v=|shorts\\/|live\\/|embed\\/|v\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/;\n\nfunction isYouTubeURL(url: string): { isYouTube: boolean; videoId: string | null } {\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.pathname === \"/playlist\") {\n\t\t\treturn { isYouTube: false, videoId: null };\n\t\t}\n\t} catch {\n\t}\n\tconst match = url.match(YOUTUBE_URL_RE);\n\tif (!match) return { isYouTube: false, videoId: null };\n\treturn { isYouTube: true, videoId: match[1] };\n}\n\nfunction isPDF(url: string, contentType?: string): boolean {\n\tif (contentType?.includes(\"application/pdf\")) return true;\n\ttry {\n\t\treturn new URL(url).pathname.toLowerCase().endsWith(\".pdf\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction looksLikeLocalPath(input: string): boolean {\n\treturn input.startsWith(\"/\") || input.startsWith(\"./\") || input.startsWith(\"../\") || input.startsWith(\"file://\");\n}\n\nfunction looksLikeGitHubUrl(url: string): boolean {\n\ttry {\n\t\tconst host = new URL(url).hostname.toLowerCase();\n\t\treturn host === \"github.com\" || host === \"www.github.com\" || host.endsWith(\".github.com\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nconst DEFAULT_TIMEOUT_MS = 30000;\nconst CONCURRENT_LIMIT = 3;\n\nconst NON_RECOVERABLE_ERRORS = [\"Unsupported content type\", \"Response too large\"];\nconst MIN_USEFUL_CONTENT = 500;\nconst WEB_SEARCH_CONFIG_PATH = getWebSearchConfigPath();\n\n/**\n * Read `ssrf.allowRanges` (CIDR strings) from web-search.json. Returns [] when\n * the file is missing, unreadable, or the key is unset so SSRF protection stays\n * fully on by default. Throws when `ssrf.allowRanges` is present but not an array\n * so a mistyped value (e.g. a bare string instead of a JSON array) fails loudly\n * instead of being silently ignored. Exempts synthetic ranges used by TUN/fake-IP\n * proxies (e.g. 198.18.0.0/15).\n */\nexport function loadSsrfAllowRanges(): string[] {\n\tlet value: unknown;\n\ttry {\n\t\tif (!existsSync(WEB_SEARCH_CONFIG_PATH)) return [];\n\t\tconst raw = readFileSync(WEB_SEARCH_CONFIG_PATH, \"utf-8\");\n\t\tvalue = (JSON.parse(raw) as { ssrf?: { allowRanges?: unknown } })?.ssrf?.allowRanges;\n\t} catch {\n\t\t// Missing/unreadable file or invalid JSON: fail safe with SSRF fully on.\n\t\treturn [];\n\t}\n\tif (value === undefined || value === null) return [];\n\tif (!Array.isArray(value)) {\n\t\tthrow new Error(`ssrf.allowRanges in ${WEB_SEARCH_CONFIG_PATH} must be an array of CIDR strings`);\n\t}\n\tconst ranges: string[] = [];\n\tfor (const [index, entry] of value.entries()) {\n\t\tif (typeof entry !== \"string\") {\n\t\t\tthrow new Error(`ssrf.allowRanges in ${WEB_SEARCH_CONFIG_PATH} must contain only CIDR strings; entry ${index + 1} is ${typeof entry}`);\n\t\t}\n\t\tconst trimmed = entry.trim();\n\t\tif (trimmed) ranges.push(trimmed);\n\t}\n\treturn ranges;\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction isConfigParseError(err: unknown): boolean {\n\treturn errorMessage(err).startsWith(\"Failed to parse \");\n}\n\nfunction isAbortError(err: unknown): boolean {\n\treturn errorMessage(err).toLowerCase().includes(\"abort\");\n}\n\nfunction abortedResult(url: string): ExtractedContent {\n\treturn { url, title: \"\", content: \"\", error: \"Aborted\" };\n}\n\nconst turndown = new TurndownService({\n\theadingStyle: \"atx\",\n\tcodeBlockStyle: \"fenced\",\n});\n\nconst fetchLimit = pLimit(CONCURRENT_LIMIT);\n\nexport interface VideoFrame {\n\tdata: string;\n\tmimeType: string;\n\ttimestamp: string;\n}\n\nexport type FrameData = { data: string; mimeType: string };\nexport type FrameResult = FrameData | { error: string };\n\nexport interface ExtractedContent {\n\turl: string;\n\ttitle: string;\n\tcontent: string;\n\terror: string | null;\n\tthumbnail?: { data: string; mimeType: string };\n\tframes?: VideoFrame[];\n\tduration?: number;\n}\n\nexport interface ExtractOptions {\n\ttimeoutMs?: number;\n\tforceClone?: boolean;\n\tprompt?: string;\n\ttimestamp?: string;\n\tframes?: number;\n\tmodel?: string;\n\t/** Custom DNS resolver used for SSRF validation. Primarily a test seam. */\n\tlookup?: Lookup;\n}\n\nconst JINA_READER_BASE = \"https://r.jina.ai/\";\nconst JINA_TIMEOUT_MS = 30000;\n\nasync function extractWithJinaReader(\n\turl: string,\n\tsignal?: AbortSignal,\n\tlookup?: Lookup,\n): Promise<ExtractedContent | null> {\n\tconst jinaUrl = JINA_READER_BASE + url;\n\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query: `jina: ${url}` });\n\n\ttry {\n\t\tawait validateRemoteUrl(url, { allowRanges: loadSsrfAllowRanges(), lookup });\n\t\tconst res = await fetch(jinaUrl, {\n\t\t\theaders: {\n\t\t\t\t\"Accept\": \"text/markdown\",\n\t\t\t\t\"X-No-Cache\": \"true\",\n\t\t\t},\n\t\t\tsignal: AbortSignal.any([\n\t\t\t\tAbortSignal.timeout(JINA_TIMEOUT_MS),\n\t\t\t\t...(signal ? [signal] : []),\n\t\t\t]),\n\t\t});\n\n\t\tif (!res.ok) {\n\t\t\tactivityMonitor.logComplete(activityId, res.status);\n\t\t\treturn null;\n\t\t}\n\n\t\tconst content = await res.text();\n\t\tactivityMonitor.logComplete(activityId, res.status);\n\n\t\tconst contentStart = content.indexOf(\"Markdown Content:\");\n\t\tif (contentStart < 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst markdownPart = content.slice(contentStart + 17).trim(); // 17 = \"Markdown Content:\".length\n\n\t\t// Check for failed JS rendering or minimal content\n\t\tif (markdownPart.length < 100 ||\n\t\t\tmarkdownPart.startsWith(\"Loading...\") ||\n\t\t\tmarkdownPart.startsWith(\"Please enable JavaScript\")) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst title = extractHeadingTitle(markdownPart) ?? (new URL(url).pathname.split(\"/\").pop() || url);\n\t\treturn { url, title, content: markdownPart, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (message.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, message);\n\t\t}\n\t\treturn null;\n\t}\n}\n\nfunction parseTimestamp(ts: string): number | null {\n\tconst num = Number(ts);\n\tif (!isNaN(num) && num >= 0) return Math.floor(num);\n\tconst parts = ts.split(\":\").map(Number);\n\tif (parts.some(p => isNaN(p) || p < 0)) return null;\n\tif (parts.length === 3) return Math.floor(parts[0] * 3600 + parts[1] * 60 + parts[2]);\n\tif (parts.length === 2) return Math.floor(parts[0] * 60 + parts[1]);\n\treturn null;\n}\n\ntype TimestampSpec = { type: \"single\"; seconds: number } | { type: \"range\"; start: number; end: number };\n\nfunction parseTimestampSpec(ts: string): TimestampSpec | null {\n\tconst dashIdx = ts.indexOf(\"-\", 1);\n\tif (dashIdx > 0) {\n\t\tconst start = parseTimestamp(ts.slice(0, dashIdx));\n\t\tconst end = parseTimestamp(ts.slice(dashIdx + 1));\n\t\tif (start !== null && end !== null && end > start) return { type: \"range\", start, end };\n\t}\n\tconst seconds = parseTimestamp(ts);\n\treturn seconds !== null ? { type: \"single\", seconds } : null;\n}\n\nconst DEFAULT_RANGE_FRAMES = 6;\nconst MIN_FRAME_INTERVAL = 5;\n\nfunction computeRangeTimestamps(start: number, end: number, maxFrames: number = DEFAULT_RANGE_FRAMES): number[] {\n\tif (maxFrames <= 1) return [start];\n\tconst duration = end - start;\n\tconst idealInterval = duration / (maxFrames - 1);\n\tif (idealInterval < MIN_FRAME_INTERVAL) {\n\t\tconst timestamps: number[] = [];\n\t\tfor (let t = start; t <= end && timestamps.length < maxFrames; t += MIN_FRAME_INTERVAL) {\n\t\t\ttimestamps.push(t);\n\t\t}\n\t\treturn timestamps;\n\t}\n\treturn Array.from({ length: maxFrames }, (_, i) => Math.round(start + i * idealInterval));\n}\n\nfunction buildFrameResult(\n\turl: string, label: string, requestedCount: number,\n\tframes: VideoFrame[], error: string | null, duration?: number,\n): ExtractedContent {\n\tif (frames.length === 0) {\n\t\tconst msg = error ?? \"Frame extraction failed\";\n\t\treturn { url, title: `Frames ${label} (0/${requestedCount})`, content: msg, error: msg };\n\t}\n\treturn {\n\t\turl,\n\t\ttitle: `Frames ${label} (${frames.length}/${requestedCount})`,\n\t\tcontent: `${frames.length} frames extracted from ${label}`,\n\t\terror: null,\n\t\tframes,\n\t\tduration,\n\t};\n}\n\nasync function extractLocalFrames(\n\tfilePath: string, timestamps: number[],\n): Promise<{ frames: VideoFrame[]; error: string | null }> {\n\tconst { extractVideoFrame } = await loadVideoExtract();\n\tconst results = await Promise.all(timestamps.map(async (t) => {\n\t\tconst frame = await extractVideoFrame(filePath, t);\n\t\tif (\"error\" in frame) return { error: frame.error };\n\t\treturn { ...frame, timestamp: formatSeconds(t) };\n\t}));\n\tconst frames = results.filter((f): f is VideoFrame => \"data\" in f);\n\tconst firstError = results.find((f): f is { error: string } => \"error\" in f);\n\treturn { frames, error: frames.length === 0 && firstError ? firstError.error : null };\n}\n\nasync function safeVideoInfo(url: string): Promise<{ info: Awaited<ReturnType<typeof loadVideoExtract>> extends { isVideoFile: infer F } ? (F extends (...args: any) => infer R ? R : null) : null; error?: string }> {\n\tif (!looksLikeLocalPath(url)) return { info: null };\n\ttry {\n\t\tconst { isVideoFile } = await loadVideoExtract();\n\t\treturn { info: isVideoFile(url) };\n\t} catch (err) {\n\t\treturn { info: null, error: errorMessage(err) };\n\t}\n}\n\nexport async function extractContent(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent> {\n\tif (signal?.aborted) {\n\t\treturn { url, title: \"\", content: \"\", error: \"Aborted\" };\n\t}\n\n\tif (options?.frames && !options.timestamp) {\n\t\tconst frameCount = options.frames;\n\t\tconst ytInfo = isYouTubeURL(url);\n\t\tif (ytInfo.isYouTube && ytInfo.videoId) {\n\t\t\tconst yt = await loadYoutubeExtract();\n\t\t\tconst streamInfo = await yt.getYouTubeStreamInfo(ytInfo.videoId);\n\t\t\tif (\"error\" in streamInfo) {\n\t\t\t\treturn { url, title: \"Frames\", content: streamInfo.error, error: streamInfo.error };\n\t\t\t}\n\t\t\tif (streamInfo.duration === null) {\n\t\t\t\tconst error = \"Cannot determine video duration. Use a timestamp range instead.\";\n\t\t\t\treturn { url, title: \"Frames\", content: error, error };\n\t\t\t}\n\t\t\tconst dur = Math.floor(streamInfo.duration);\n\t\t\tconst timestamps = computeRangeTimestamps(0, dur, frameCount);\n\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\tconst label = `${formatSeconds(0)}-${formatSeconds(dur)}`;\n\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, streamInfo.duration);\n\t\t}\n\n\t\tconst localVideo = await safeVideoInfo(url);\n\t\tif (localVideo.error) {\n\t\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t\t}\n\t\tif (localVideo.info) {\n\t\t\tconst { getLocalVideoDuration } = await loadVideoExtract();\n\t\t\tconst durationResult = await getLocalVideoDuration(localVideo.info.absolutePath);\n\t\t\tif (typeof durationResult !== \"number\") {\n\t\t\t\treturn { url, title: \"Frames\", content: durationResult.error, error: durationResult.error };\n\t\t\t}\n\t\t\tconst dur = Math.floor(durationResult);\n\t\t\tconst timestamps = computeRangeTimestamps(0, dur, frameCount);\n\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\tconst label = `${formatSeconds(0)}-${formatSeconds(dur)}`;\n\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, durationResult);\n\t\t}\n\n\t\treturn { url, title: \"\", content: \"\", error: \"Frame extraction only works with YouTube and local video files\" };\n\t}\n\n\tif (options?.timestamp) {\n\t\tconst spec = parseTimestampSpec(options.timestamp);\n\t\tif (!spec) {\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `Invalid timestamp format: \"${options.timestamp}\". Use \"H:MM:SS\", \"MM:SS\", \"85\", or \"start-end\".`,\n\t\t\t};\n\t\t}\n\n\t\tconst frameCount = options.frames;\n\t\tconst ytInfo = isYouTubeURL(url);\n\t\tif (ytInfo.isYouTube && ytInfo.videoId) {\n\t\t\tconst yt = await loadYoutubeExtract();\n\t\t\tconst streamInfo = await yt.getYouTubeStreamInfo(ytInfo.videoId);\n\t\t\tif (\"error\" in streamInfo) {\n\t\t\t\tif (spec.type === \"range\") {\n\t\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t\t}\n\t\t\t\tif (frameCount) {\n\t\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t\t}\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t}\n\n\t\t\tif (spec.type === \"range\") {\n\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\tif (streamInfo.duration !== null && spec.end > streamInfo.duration) {\n\t\t\t\t\tconst error = `Timestamp ${formatSeconds(spec.end)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: error, error };\n\t\t\t\t}\n\t\t\t\tconst timestamps = frameCount\n\t\t\t\t\t? computeRangeTimestamps(spec.start, spec.end, frameCount)\n\t\t\t\t\t: computeRangeTimestamps(spec.start, spec.end);\n\t\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, result.duration ?? undefined);\n\t\t\t}\n\n\t\t\tif (frameCount) {\n\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\tif (streamInfo.duration !== null && end > streamInfo.duration) {\n\t\t\t\t\tconst error = `Timestamp ${formatSeconds(end)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: error, error };\n\t\t\t\t}\n\t\t\t\tconst timestamps = computeRangeTimestamps(spec.seconds, end, frameCount);\n\t\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, result.duration ?? undefined);\n\t\t\t}\n\n\t\t\tif (streamInfo.duration !== null && spec.seconds > streamInfo.duration) {\n\t\t\t\tconst error = `Timestamp ${formatSeconds(spec.seconds)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: error, error };\n\t\t\t}\n\t\t\tconst frame = await yt.extractYouTubeFrame(ytInfo.videoId, spec.seconds, streamInfo);\n\t\t\tif (\"error\" in frame) {\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: frame.error, error: frame.error };\n\t\t\t}\n\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: `Video frame at ${options.timestamp}`, error: null, thumbnail: frame };\n\t\t}\n\n\t\tconst localVideo = await safeVideoInfo(url);\n\t\tif (localVideo.error) {\n\t\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t\t}\n\t\tif (localVideo.info) {\n\t\t\tif (spec.type === \"range\") {\n\t\t\t\tconst timestamps = frameCount\n\t\t\t\t\t? computeRangeTimestamps(spec.start, spec.end, frameCount)\n\t\t\t\t\t: computeRangeTimestamps(spec.start, spec.end);\n\t\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error);\n\t\t\t}\n\n\t\t\tif (frameCount) {\n\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\tconst timestamps = computeRangeTimestamps(spec.seconds, end, frameCount);\n\t\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error);\n\t\t\t}\n\n\t\t\tconst { extractVideoFrame } = await loadVideoExtract();\n\t\t\tconst frame = await extractVideoFrame(localVideo.info.absolutePath, spec.seconds);\n\t\t\tif (\"error\" in frame) {\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: frame.error, error: frame.error };\n\t\t\t}\n\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: `Video frame at ${options.timestamp}`, error: null, thumbnail: frame };\n\t\t}\n\n\t\treturn { url, title: \"\", content: \"\", error: \"Timestamp extraction only works with YouTube and local video files\" };\n\t}\n\n\tconst localVideo = await safeVideoInfo(url);\n\tif (localVideo.error) {\n\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t}\n\tif (localVideo.info) {\n\t\ttry {\n\t\t\tconst { extractVideo } = await loadVideoExtract();\n\t\t\tconst result = await extractVideo(localVideo.info, signal, options);\n\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t\treturn result ?? { url, title: \"\", content: \"\", error: `Video analysis requires Gemini access. Either:\\n 1. Sign into gemini.google.com in Chrome (free, uses cookies)\\n 2. Set GEMINI_API_KEY in ${WEB_SEARCH_CONFIG_PATH}` };\n\t\t} catch (err) {\n\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t\t}\n\t}\n\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") {\n\t\t\tawait validateRemoteUrl(parsed, { allowRanges: loadSsrfAllowRanges(), lookup: options?.lookup });\n\t\t}\n\t} catch (err) {\n\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t}\n\n\tif (looksLikeGitHubUrl(url)) {\n\t\ttry {\n\t\t\tconst { extractGitHub } = await loadGithubExtract();\n\t\t\tconst ghResult = await extractGitHub(url, signal, options?.forceClone);\n\t\t\tif (ghResult) return ghResult;\n\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t} catch (err) {\n\t\t\tconst message = errorMessage(err);\n\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\tif (isConfigParseError(err)) {\n\t\t\t\treturn { url, title: \"\", content: \"\", error: message };\n\t\t\t}\n\t\t}\n\t}\n\n\tconst ytInfo = isYouTubeURL(url);\n\tif (ytInfo.isYouTube) {\n\t\tlet youtubeEnabled = false;\n\t\tlet yt;\n\t\ttry {\n\t\t\tyt = await loadYoutubeExtract();\n\t\t\tyoutubeEnabled = yt.isYouTubeEnabled();\n\t\t} catch (err) {\n\t\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t\t}\n\t\tif (youtubeEnabled) {\n\t\t\ttry {\n\t\t\t\tconst ytResult = await yt.extractYouTube(url, signal, options?.prompt, options?.model);\n\t\t\t\tif (ytResult) return ytResult;\n\t\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t\t} catch (err) {\n\t\t\t\tconst message = errorMessage(err);\n\t\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\t\treturn { url, title: \"\", content: \"\", error: message };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: \"Could not extract YouTube video content. Sign into Google in Chrome for automatic access, or set GEMINI_API_KEY.\",\n\t\t\t};\n\t\t}\n\t}\n\n\tif (signal?.aborted) return abortedResult(url);\n\n\tconst httpResult = await extractViaHttp(url, signal, options);\n\n\tif (signal?.aborted) return abortedResult(url);\n\tif (!httpResult.error) return httpResult;\n\tif (NON_RECOVERABLE_ERRORS.some(prefix => httpResult.error!.startsWith(prefix))) return httpResult;\n\n\tconst jinaResult = await extractWithJinaReader(url, signal, options?.lookup);\n\tif (jinaResult) return jinaResult;\n\tif (signal?.aborted) return abortedResult(url);\n\n\tlet parallelError: string | null = null;\n\ttry {\n\t\tconst parallel = await loadParallel();\n\t\tif (parallel.isParallelAvailable()) {\n\t\t\tconst parallelResult = await parallel.extractWithParallel(url, signal, options);\n\t\t\tif (parallelResult) return parallelResult;\n\t\t}\n\t} catch (err) {\n\t\tif (isAbortError(err)) return abortedResult(url);\n\t\tparallelError = errorMessage(err);\n\t\tif (isConfigParseError(err)) {\n\t\t\treturn { ...httpResult, error: parallelError };\n\t\t}\n\t}\n\tif (signal?.aborted) return abortedResult(url);\n\n\tlet geminiResult: ExtractedContent | null = null;\n\ttry {\n\t\tconst geminiUrl = await loadGeminiUrlContext();\n\t\tgeminiResult = await geminiUrl.extractWithUrlContext(url, signal)\n\t\t\t?? await geminiUrl.extractWithGeminiWeb(url, signal);\n\t} catch (err) {\n\t\tif (isAbortError(err)) return abortedResult(url);\n\t\tif (isConfigParseError(err)) {\n\t\t\treturn { ...httpResult, error: errorMessage(err) };\n\t\t}\n\t}\n\n\tif (geminiResult) return geminiResult;\n\tif (signal?.aborted) return abortedResult(url);\n\n\tconst guidance = [\n\t\thttpResult.error,\n\t\t...(parallelError ? [`Parallel fallback failed: ${parallelError}`] : []),\n\t\t\"\",\n\t\t\"Fallback options:\",\n\t\t` \\u2022 Set PARALLEL_API_KEY in ${WEB_SEARCH_CONFIG_PATH}`,\n\t\t` \\u2022 Set GEMINI_API_KEY in ${WEB_SEARCH_CONFIG_PATH}`,\n\t\t\" \\u2022 Sign into gemini.google.com in Chrome\",\n\t\t\" \\u2022 Use web_search to find content about this topic\",\n\t].join(\"\\n\");\n\treturn { ...httpResult, error: guidance };\n}\n\nfunction isLikelyJSRendered(html: string): boolean {\n\t// Extract body content\n\tconst bodyMatch = html.match(/<body[^>]*>([\\s\\S]*?)<\\/body>/i);\n\tif (!bodyMatch) return false;\n\n\tconst bodyHtml = bodyMatch[1];\n\n\t// Strip tags to get text content\n\tconst textContent = bodyHtml\n\t\t.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n\t\t.replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n\t\t.replace(/<[^>]+>/g, \"\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\n\t// Count scripts\n\tconst scriptCount = (html.match(/<script/gi) || []).length;\n\n\t// Heuristic: little text content but many scripts suggests JS rendering\n\treturn textContent.length < 500 && scriptCount > 3;\n}\n\nasync function extractViaHttp(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent> {\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url });\n\n\tconst controller = new AbortController();\n\tconst timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n\tconst onAbort = () => controller.abort();\n\tsignal?.addEventListener(\"abort\", onAbort);\n\n\ttry {\n\t\tconst response = await fetchRemoteUrl(\n\t\t\turl,\n\t\t\t{\n\t\t\t\tsignal: controller.signal,\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\",\n\t\t\t\t\t\"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8\",\n\t\t\t\t\t\"Accept-Language\": \"en-US,en;q=0.9\",\n\t\t\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t\t\t\t\"Sec-Fetch-Dest\": \"document\",\n\t\t\t\t\t\"Sec-Fetch-Mode\": \"navigate\",\n\t\t\t\t\t\"Sec-Fetch-Site\": \"none\",\n\t\t\t\t\t\"Sec-Fetch-User\": \"?1\",\n\t\t\t\t\t\"Upgrade-Insecure-Requests\": \"1\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ allowRanges: loadSsrfAllowRanges(), lookup: options?.lookup },\n\t\t);\n\n\t\tif (!response.ok) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `HTTP ${response.status}: ${response.statusText}`,\n\t\t\t};\n\t\t}\n\n\t\tconst contentLengthHeader = response.headers.get(\"content-length\");\n\t\tconst contentType = response.headers.get(\"content-type\") || \"\";\n\t\tconst isPDFContent = isPDF(url, contentType);\n\t\tconst maxResponseSize = isPDFContent ? 20 * 1024 * 1024 : 5 * 1024 * 1024;\n\t\tif (contentLengthHeader) {\n\t\t\tconst contentLength = parseInt(contentLengthHeader, 10);\n\t\t\tif (contentLength > maxResponseSize) {\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn {\n\t\t\t\t\turl,\n\t\t\t\t\ttitle: \"\",\n\t\t\t\t\tcontent: \"\",\n\t\t\t\t\terror: `Response too large (${Math.round(contentLength / 1024 / 1024)}MB)`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif (isPDFContent) {\n\t\t\ttry {\n\t\t\t\tconst buffer = await response.arrayBuffer();\n\t\t\t\tconst { extractPDFToMarkdown } = await loadPdfExtract();\n\t\t\t\tconst result = await extractPDFToMarkdown(buffer, url);\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn {\n\t\t\t\t\turl,\n\t\t\t\t\ttitle: result.title,\n\t\t\t\t\tcontent: `PDF extracted and saved to: ${result.outputPath}\\n\\nPages: ${result.pages}\\nCharacters: ${result.chars}`,\n\t\t\t\t\terror: null,\n\t\t\t\t};\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\tactivityMonitor.logError(activityId, message);\n\t\t\t\treturn { url, title: \"\", content: \"\", error: `PDF extraction failed: ${message}` };\n\t\t\t}\n\t\t}\n\n\t\tif (contentType.includes(\"application/octet-stream\") ||\n\t\t\tcontentType.includes(\"image/\") ||\n\t\t\tcontentType.includes(\"audio/\") ||\n\t\t\tcontentType.includes(\"video/\") ||\n\t\t\tcontentType.includes(\"application/zip\")) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `Unsupported content type: ${contentType.split(\";\")[0]}`,\n\t\t\t};\n\t\t}\n\n\t\tconst text = await response.text();\n\t\tconst isHTML = contentType.includes(\"text/html\") || contentType.includes(\"application/xhtml+xml\");\n\n\t\tif (!isHTML) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\tconst title = extractTextTitle(text, url);\n\t\t\treturn { url, title, content: text, error: null };\n\t\t}\n\n\t\tconst { document } = parseHTML(text);\n\t\tconst reader = new Readability(document as unknown as Document);\n\t\tconst article = reader.parse();\n\n\t\tif (!article) {\n\t\t\tconst rscResult = extractRSCContent(text);\n\t\t\tif (rscResult) {\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn { url, title: rscResult.title, content: rscResult.content, error: null };\n\t\t\t}\n\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\n\t\t\t// Provide more specific error message\n\t\t\tconst jsRendered = isLikelyJSRendered(text);\n\t\t\tconst errorMsg = jsRendered\n\t\t\t\t? \"Page appears to be JavaScript-rendered (content loads dynamically)\"\n\t\t\t\t: \"Could not extract readable content from HTML structure\";\n\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: errorMsg,\n\t\t\t};\n\t\t}\n\n\t\tconst markdown = turndown.turndown(article.content);\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\n\t\tif (markdown.length < MIN_USEFUL_CONTENT) {\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: article.title || \"\",\n\t\t\t\tcontent: markdown,\n\t\t\t\terror: isLikelyJSRendered(text)\n\t\t\t\t\t? \"Page appears to be JavaScript-rendered (content loads dynamically)\"\n\t\t\t\t\t: \"Extracted content appears incomplete\",\n\t\t\t};\n\t\t}\n\n\t\treturn { url, title: article.title || \"\", content: markdown, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (message.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, message);\n\t\t}\n\t\treturn { url, title: \"\", content: \"\", error: message };\n\t} finally {\n\t\tclearTimeout(timeoutId);\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t}\n}\n\nexport function extractHeadingTitle(text: string): string | null {\n\tconst match = text.match(/^#{1,2}\\s+(.+)/m);\n\tif (!match) return null;\n\tconst cleaned = match[1].replace(/\\*+/g, \"\").trim();\n\treturn cleaned || null;\n}\n\nfunction extractTextTitle(text: string, url: string): string {\n\treturn extractHeadingTitle(text) ?? (new URL(url).pathname.split(\"/\").pop() || url);\n}\n\nexport async function fetchAllContent(\n\turls: string[],\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent[]> {\n\treturn Promise.all(urls.map((url) => fetchLimit(() => extractContent(url, signal, options))));\n}\n"]}
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-web-access/extract.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport { Readability } from \"@mozilla/readability\";\nimport { parseHTML } from \"linkedom\";\nimport TurndownService from \"turndown\";\nimport pLimit from \"p-limit\";\nimport { readBoundedBody } from \"./bounded-body.ts\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { extractRSCContent } from \"./rsc-extract.ts\";\nimport {\n\tloadGeminiUrlContext,\n\tloadGithubExtract,\n\tloadParallel,\n\tloadPdfExtract,\n\tloadVideoExtract,\n\tloadYoutubeExtract,\n} from \"./lazy.ts\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { fetchRemoteUrl, validateRemoteUrl, type Lookup } from \"./ssrf-protection.ts\";\nimport { formatSeconds, getWebSearchConfigPath } from \"./utils.ts\";\n\nconst YOUTUBE_URL_RE =\n\t/(?:(?:www\\.|m\\.)?youtube\\.com\\/(?:watch\\?.*v=|shorts\\/|live\\/|embed\\/|v\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/;\n\nfunction isYouTubeURL(url: string): { isYouTube: boolean; videoId: string | null } {\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.pathname === \"/playlist\") {\n\t\t\treturn { isYouTube: false, videoId: null };\n\t\t}\n\t} catch {\n\t}\n\tconst match = url.match(YOUTUBE_URL_RE);\n\tif (!match) return { isYouTube: false, videoId: null };\n\treturn { isYouTube: true, videoId: match[1] };\n}\n\nfunction isPDF(url: string, contentType?: string): boolean {\n\tif (contentType?.includes(\"application/pdf\")) return true;\n\ttry {\n\t\treturn new URL(url).pathname.toLowerCase().endsWith(\".pdf\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction looksLikeLocalPath(input: string): boolean {\n\treturn input.startsWith(\"/\") || input.startsWith(\"./\") || input.startsWith(\"../\") || input.startsWith(\"file://\");\n}\n\nfunction looksLikeGitHubUrl(url: string): boolean {\n\ttry {\n\t\tconst host = new URL(url).hostname.toLowerCase();\n\t\treturn host === \"github.com\" || host === \"www.github.com\" || host.endsWith(\".github.com\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nconst DEFAULT_TIMEOUT_MS = 30000;\nconst CONCURRENT_LIMIT = 3;\n\nconst NON_RECOVERABLE_ERRORS = [\"Unsupported content type\", \"Response too large\"];\nconst MIN_USEFUL_CONTENT = 500;\nconst WEB_SEARCH_CONFIG_PATH = getWebSearchConfigPath();\n\n/**\n * Read `ssrf.allowRanges` (CIDR strings) from web-search.json. Returns [] when\n * the file is missing, unreadable, or the key is unset so SSRF protection stays\n * fully on by default. Throws when `ssrf.allowRanges` is present but not an array\n * so a mistyped value (e.g. a bare string instead of a JSON array) fails loudly\n * instead of being silently ignored. Exempts synthetic ranges used by TUN/fake-IP\n * proxies (e.g. 198.18.0.0/15).\n */\nexport function loadSsrfAllowRanges(): string[] {\n\tlet value: unknown;\n\ttry {\n\t\tif (!existsSync(WEB_SEARCH_CONFIG_PATH)) return [];\n\t\tconst raw = readFileSync(WEB_SEARCH_CONFIG_PATH, \"utf-8\");\n\t\tvalue = (JSON.parse(raw) as { ssrf?: { allowRanges?: unknown } })?.ssrf?.allowRanges;\n\t} catch {\n\t\t// Missing/unreadable file or invalid JSON: fail safe with SSRF fully on.\n\t\treturn [];\n\t}\n\tif (value === undefined || value === null) return [];\n\tif (!Array.isArray(value)) {\n\t\tthrow new Error(`ssrf.allowRanges in ${WEB_SEARCH_CONFIG_PATH} must be an array of CIDR strings`);\n\t}\n\tconst ranges: string[] = [];\n\tfor (const [index, entry] of value.entries()) {\n\t\tif (typeof entry !== \"string\") {\n\t\t\tthrow new Error(`ssrf.allowRanges in ${WEB_SEARCH_CONFIG_PATH} must contain only CIDR strings; entry ${index + 1} is ${typeof entry}`);\n\t\t}\n\t\tconst trimmed = entry.trim();\n\t\tif (trimmed) ranges.push(trimmed);\n\t}\n\treturn ranges;\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction isConfigParseError(err: unknown): boolean {\n\treturn errorMessage(err).startsWith(\"Failed to parse \");\n}\n\nfunction isAbortError(err: unknown): boolean {\n\treturn errorMessage(err).toLowerCase().includes(\"abort\");\n}\n\nfunction abortedResult(url: string): ExtractedContent {\n\treturn { url, title: \"\", content: \"\", error: \"Aborted\" };\n}\n\nconst turndown = new TurndownService({\n\theadingStyle: \"atx\",\n\tcodeBlockStyle: \"fenced\",\n});\n\nconst fetchLimit = pLimit(CONCURRENT_LIMIT);\n\nexport interface VideoFrame {\n\tdata: string;\n\tmimeType: string;\n\ttimestamp: string;\n}\n\nexport type FrameData = { data: string; mimeType: string };\nexport type FrameResult = FrameData | { error: string };\n\nexport interface ExtractedContent {\n\turl: string;\n\ttitle: string;\n\tcontent: string;\n\terror: string | null;\n\tthumbnail?: { data: string; mimeType: string };\n\tframes?: VideoFrame[];\n\tduration?: number;\n}\n\nexport interface ExtractOptions {\n\ttimeoutMs?: number;\n\tforceClone?: boolean;\n\tprompt?: string;\n\ttimestamp?: string;\n\tframes?: number;\n\tmodel?: string;\n\t/** Custom DNS resolver used for SSRF validation. Primarily a test seam. */\n\tlookup?: Lookup;\n}\n\nconst JINA_READER_BASE = \"https://r.jina.ai/\";\nconst JINA_TIMEOUT_MS = 30000;\n\nasync function extractWithJinaReader(\n\turl: string,\n\tsignal?: AbortSignal,\n\tlookup?: Lookup,\n): Promise<ExtractedContent | null> {\n\tconst jinaUrl = JINA_READER_BASE + url;\n\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query: `jina: ${url}` });\n\n\ttry {\n\t\tawait validateRemoteUrl(url, { allowRanges: loadSsrfAllowRanges(), lookup });\n\t\tconst res = await fetch(jinaUrl, {\n\t\t\theaders: {\n\t\t\t\t\"Accept\": \"text/markdown\",\n\t\t\t\t\"X-No-Cache\": \"true\",\n\t\t\t},\n\t\t\tsignal: AbortSignal.any([\n\t\t\t\tAbortSignal.timeout(JINA_TIMEOUT_MS),\n\t\t\t\t...(signal ? [signal] : []),\n\t\t\t]),\n\t\t});\n\n\t\tif (!res.ok) {\n\t\t\tactivityMonitor.logComplete(activityId, res.status);\n\t\t\treturn null;\n\t\t}\n\n\t\tconst content = await res.text();\n\t\tactivityMonitor.logComplete(activityId, res.status);\n\n\t\tconst contentStart = content.indexOf(\"Markdown Content:\");\n\t\tif (contentStart < 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst markdownPart = content.slice(contentStart + 17).trim(); // 17 = \"Markdown Content:\".length\n\n\t\t// Check for failed JS rendering or minimal content\n\t\tif (markdownPart.length < 100 ||\n\t\t\tmarkdownPart.startsWith(\"Loading...\") ||\n\t\t\tmarkdownPart.startsWith(\"Please enable JavaScript\")) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst title = extractHeadingTitle(markdownPart) ?? (new URL(url).pathname.split(\"/\").pop() || url);\n\t\treturn { url, title, content: markdownPart, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (message.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, message);\n\t\t}\n\t\treturn null;\n\t}\n}\n\nfunction parseTimestamp(ts: string): number | null {\n\tconst num = Number(ts);\n\tif (!isNaN(num) && num >= 0) return Math.floor(num);\n\tconst parts = ts.split(\":\").map(Number);\n\tif (parts.some(p => isNaN(p) || p < 0)) return null;\n\tif (parts.length === 3) return Math.floor(parts[0] * 3600 + parts[1] * 60 + parts[2]);\n\tif (parts.length === 2) return Math.floor(parts[0] * 60 + parts[1]);\n\treturn null;\n}\n\ntype TimestampSpec = { type: \"single\"; seconds: number } | { type: \"range\"; start: number; end: number };\n\nfunction parseTimestampSpec(ts: string): TimestampSpec | null {\n\tconst dashIdx = ts.indexOf(\"-\", 1);\n\tif (dashIdx > 0) {\n\t\tconst start = parseTimestamp(ts.slice(0, dashIdx));\n\t\tconst end = parseTimestamp(ts.slice(dashIdx + 1));\n\t\tif (start !== null && end !== null && end > start) return { type: \"range\", start, end };\n\t}\n\tconst seconds = parseTimestamp(ts);\n\treturn seconds !== null ? { type: \"single\", seconds } : null;\n}\n\nconst DEFAULT_RANGE_FRAMES = 6;\nconst MIN_FRAME_INTERVAL = 5;\n\nfunction computeRangeTimestamps(start: number, end: number, maxFrames: number = DEFAULT_RANGE_FRAMES): number[] {\n\tif (maxFrames <= 1) return [start];\n\tconst duration = end - start;\n\tconst idealInterval = duration / (maxFrames - 1);\n\tif (idealInterval < MIN_FRAME_INTERVAL) {\n\t\tconst timestamps: number[] = [];\n\t\tfor (let t = start; t <= end && timestamps.length < maxFrames; t += MIN_FRAME_INTERVAL) {\n\t\t\ttimestamps.push(t);\n\t\t}\n\t\treturn timestamps;\n\t}\n\treturn Array.from({ length: maxFrames }, (_, i) => Math.round(start + i * idealInterval));\n}\n\nfunction buildFrameResult(\n\turl: string, label: string, requestedCount: number,\n\tframes: VideoFrame[], error: string | null, duration?: number,\n): ExtractedContent {\n\tif (frames.length === 0) {\n\t\tconst msg = error ?? \"Frame extraction failed\";\n\t\treturn { url, title: `Frames ${label} (0/${requestedCount})`, content: msg, error: msg };\n\t}\n\treturn {\n\t\turl,\n\t\ttitle: `Frames ${label} (${frames.length}/${requestedCount})`,\n\t\tcontent: `${frames.length} frames extracted from ${label}`,\n\t\terror: null,\n\t\tframes,\n\t\tduration,\n\t};\n}\n\nasync function extractLocalFrames(\n\tfilePath: string, timestamps: number[],\n): Promise<{ frames: VideoFrame[]; error: string | null }> {\n\tconst { extractVideoFrame } = await loadVideoExtract();\n\tconst results = await Promise.all(timestamps.map(async (t) => {\n\t\tconst frame = await extractVideoFrame(filePath, t);\n\t\tif (\"error\" in frame) return { error: frame.error };\n\t\treturn { ...frame, timestamp: formatSeconds(t) };\n\t}));\n\tconst frames = results.filter((f): f is VideoFrame => \"data\" in f);\n\tconst firstError = results.find((f): f is { error: string } => \"error\" in f);\n\treturn { frames, error: frames.length === 0 && firstError ? firstError.error : null };\n}\n\nasync function safeVideoInfo(url: string): Promise<{ info: Awaited<ReturnType<typeof loadVideoExtract>> extends { isVideoFile: infer F } ? (F extends (...args: any) => infer R ? R : null) : null; error?: string }> {\n\tif (!looksLikeLocalPath(url)) return { info: null };\n\ttry {\n\t\tconst { isVideoFile } = await loadVideoExtract();\n\t\treturn { info: isVideoFile(url) };\n\t} catch (err) {\n\t\treturn { info: null, error: errorMessage(err) };\n\t}\n}\n\nexport async function extractContent(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent> {\n\tif (signal?.aborted) {\n\t\treturn { url, title: \"\", content: \"\", error: \"Aborted\" };\n\t}\n\n\tif (options?.frames && !options.timestamp) {\n\t\tconst frameCount = options.frames;\n\t\tconst ytInfo = isYouTubeURL(url);\n\t\tif (ytInfo.isYouTube && ytInfo.videoId) {\n\t\t\tconst yt = await loadYoutubeExtract();\n\t\t\tconst streamInfo = await yt.getYouTubeStreamInfo(ytInfo.videoId);\n\t\t\tif (\"error\" in streamInfo) {\n\t\t\t\treturn { url, title: \"Frames\", content: streamInfo.error, error: streamInfo.error };\n\t\t\t}\n\t\t\tif (streamInfo.duration === null) {\n\t\t\t\tconst error = \"Cannot determine video duration. Use a timestamp range instead.\";\n\t\t\t\treturn { url, title: \"Frames\", content: error, error };\n\t\t\t}\n\t\t\tconst dur = Math.floor(streamInfo.duration);\n\t\t\tconst timestamps = computeRangeTimestamps(0, dur, frameCount);\n\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\tconst label = `${formatSeconds(0)}-${formatSeconds(dur)}`;\n\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, streamInfo.duration);\n\t\t}\n\n\t\tconst localVideo = await safeVideoInfo(url);\n\t\tif (localVideo.error) {\n\t\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t\t}\n\t\tif (localVideo.info) {\n\t\t\tconst { getLocalVideoDuration } = await loadVideoExtract();\n\t\t\tconst durationResult = await getLocalVideoDuration(localVideo.info.absolutePath);\n\t\t\tif (typeof durationResult !== \"number\") {\n\t\t\t\treturn { url, title: \"Frames\", content: durationResult.error, error: durationResult.error };\n\t\t\t}\n\t\t\tconst dur = Math.floor(durationResult);\n\t\t\tconst timestamps = computeRangeTimestamps(0, dur, frameCount);\n\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\tconst label = `${formatSeconds(0)}-${formatSeconds(dur)}`;\n\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, durationResult);\n\t\t}\n\n\t\treturn { url, title: \"\", content: \"\", error: \"Frame extraction only works with YouTube and local video files\" };\n\t}\n\n\tif (options?.timestamp) {\n\t\tconst spec = parseTimestampSpec(options.timestamp);\n\t\tif (!spec) {\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `Invalid timestamp format: \"${options.timestamp}\". Use \"H:MM:SS\", \"MM:SS\", \"85\", or \"start-end\".`,\n\t\t\t};\n\t\t}\n\n\t\tconst frameCount = options.frames;\n\t\tconst ytInfo = isYouTubeURL(url);\n\t\tif (ytInfo.isYouTube && ytInfo.videoId) {\n\t\t\tconst yt = await loadYoutubeExtract();\n\t\t\tconst streamInfo = await yt.getYouTubeStreamInfo(ytInfo.videoId);\n\t\t\tif (\"error\" in streamInfo) {\n\t\t\t\tif (spec.type === \"range\") {\n\t\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t\t}\n\t\t\t\tif (frameCount) {\n\t\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t\t}\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: streamInfo.error, error: streamInfo.error };\n\t\t\t}\n\n\t\t\tif (spec.type === \"range\") {\n\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\tif (streamInfo.duration !== null && spec.end > streamInfo.duration) {\n\t\t\t\t\tconst error = `Timestamp ${formatSeconds(spec.end)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: error, error };\n\t\t\t\t}\n\t\t\t\tconst timestamps = frameCount\n\t\t\t\t\t? computeRangeTimestamps(spec.start, spec.end, frameCount)\n\t\t\t\t\t: computeRangeTimestamps(spec.start, spec.end);\n\t\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, result.duration ?? undefined);\n\t\t\t}\n\n\t\t\tif (frameCount) {\n\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\tif (streamInfo.duration !== null && end > streamInfo.duration) {\n\t\t\t\t\tconst error = `Timestamp ${formatSeconds(end)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\t\treturn { url, title: `Frames ${label}`, content: error, error };\n\t\t\t\t}\n\t\t\t\tconst timestamps = computeRangeTimestamps(spec.seconds, end, frameCount);\n\t\t\t\tconst result = await yt.extractYouTubeFrames(ytInfo.videoId, timestamps, streamInfo);\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error, result.duration ?? undefined);\n\t\t\t}\n\n\t\t\tif (streamInfo.duration !== null && spec.seconds > streamInfo.duration) {\n\t\t\t\tconst error = `Timestamp ${formatSeconds(spec.seconds)} exceeds video duration (${formatSeconds(Math.floor(streamInfo.duration))})`;\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: error, error };\n\t\t\t}\n\t\t\tconst frame = await yt.extractYouTubeFrame(ytInfo.videoId, spec.seconds, streamInfo);\n\t\t\tif (\"error\" in frame) {\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: frame.error, error: frame.error };\n\t\t\t}\n\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: `Video frame at ${options.timestamp}`, error: null, thumbnail: frame };\n\t\t}\n\n\t\tconst localVideo = await safeVideoInfo(url);\n\t\tif (localVideo.error) {\n\t\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t\t}\n\t\tif (localVideo.info) {\n\t\t\tif (spec.type === \"range\") {\n\t\t\t\tconst timestamps = frameCount\n\t\t\t\t\t? computeRangeTimestamps(spec.start, spec.end, frameCount)\n\t\t\t\t\t: computeRangeTimestamps(spec.start, spec.end);\n\t\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\t\tconst label = `${formatSeconds(spec.start)}-${formatSeconds(spec.end)}`;\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error);\n\t\t\t}\n\n\t\t\tif (frameCount) {\n\t\t\t\tconst end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;\n\t\t\t\tconst timestamps = computeRangeTimestamps(spec.seconds, end, frameCount);\n\t\t\t\tconst result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);\n\t\t\t\tconst label = `${formatSeconds(spec.seconds)}-${formatSeconds(end)}`;\n\t\t\t\treturn buildFrameResult(url, label, timestamps.length, result.frames, result.error);\n\t\t\t}\n\n\t\t\tconst { extractVideoFrame } = await loadVideoExtract();\n\t\t\tconst frame = await extractVideoFrame(localVideo.info.absolutePath, spec.seconds);\n\t\t\tif (\"error\" in frame) {\n\t\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: frame.error, error: frame.error };\n\t\t\t}\n\t\t\treturn { url, title: `Frame at ${options.timestamp}`, content: `Video frame at ${options.timestamp}`, error: null, thumbnail: frame };\n\t\t}\n\n\t\treturn { url, title: \"\", content: \"\", error: \"Timestamp extraction only works with YouTube and local video files\" };\n\t}\n\n\tconst localVideo = await safeVideoInfo(url);\n\tif (localVideo.error) {\n\t\treturn { url, title: \"\", content: \"\", error: localVideo.error };\n\t}\n\tif (localVideo.info) {\n\t\ttry {\n\t\t\tconst { extractVideo } = await loadVideoExtract();\n\t\t\tconst result = await extractVideo(localVideo.info, signal, options);\n\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t\treturn result ?? { url, title: \"\", content: \"\", error: `Video analysis requires Gemini access. Either:\\n 1. Sign into gemini.google.com in Chrome (free, uses cookies)\\n 2. Set GEMINI_API_KEY in ${WEB_SEARCH_CONFIG_PATH}` };\n\t\t} catch (err) {\n\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t\t}\n\t}\n\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") {\n\t\t\tawait validateRemoteUrl(parsed, { allowRanges: loadSsrfAllowRanges(), lookup: options?.lookup });\n\t\t}\n\t} catch (err) {\n\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t}\n\n\tif (looksLikeGitHubUrl(url)) {\n\t\ttry {\n\t\t\tconst { extractGitHub } = await loadGithubExtract();\n\t\t\tconst ghResult = await extractGitHub(url, signal, options?.forceClone);\n\t\t\tif (ghResult) return ghResult;\n\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t} catch (err) {\n\t\t\tconst message = errorMessage(err);\n\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\tif (isConfigParseError(err)) {\n\t\t\t\treturn { url, title: \"\", content: \"\", error: message };\n\t\t\t}\n\t\t}\n\t}\n\n\tconst ytInfo = isYouTubeURL(url);\n\tif (ytInfo.isYouTube) {\n\t\tlet youtubeEnabled = false;\n\t\tlet yt;\n\t\ttry {\n\t\t\tyt = await loadYoutubeExtract();\n\t\t\tyoutubeEnabled = yt.isYouTubeEnabled();\n\t\t} catch (err) {\n\t\t\treturn { url, title: \"\", content: \"\", error: errorMessage(err) };\n\t\t}\n\t\tif (youtubeEnabled) {\n\t\t\ttry {\n\t\t\t\tconst ytResult = await yt.extractYouTube(url, signal, options?.prompt, options?.model);\n\t\t\t\tif (ytResult) return ytResult;\n\t\t\t\tif (signal?.aborted) return abortedResult(url);\n\t\t\t} catch (err) {\n\t\t\t\tconst message = errorMessage(err);\n\t\t\t\tif (isAbortError(err)) return abortedResult(url);\n\t\t\t\treturn { url, title: \"\", content: \"\", error: message };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: \"Could not extract YouTube video content. Sign into Google in Chrome for automatic access, or set GEMINI_API_KEY.\",\n\t\t\t};\n\t\t}\n\t}\n\n\tif (signal?.aborted) return abortedResult(url);\n\n\tconst httpResult = await extractViaHttp(url, signal, options);\n\n\tif (signal?.aborted) return abortedResult(url);\n\tif (!httpResult.error) return httpResult;\n\tif (NON_RECOVERABLE_ERRORS.some(prefix => httpResult.error!.startsWith(prefix))) return httpResult;\n\n\tconst jinaResult = await extractWithJinaReader(url, signal, options?.lookup);\n\tif (jinaResult) return jinaResult;\n\tif (signal?.aborted) return abortedResult(url);\n\n\tlet parallelError: string | null = null;\n\ttry {\n\t\tconst parallel = await loadParallel();\n\t\tif (parallel.isParallelAvailable()) {\n\t\t\tconst parallelResult = await parallel.extractWithParallel(url, signal, options);\n\t\t\tif (parallelResult) return parallelResult;\n\t\t}\n\t} catch (err) {\n\t\tif (isAbortError(err)) return abortedResult(url);\n\t\tparallelError = errorMessage(err);\n\t\tif (isConfigParseError(err)) {\n\t\t\treturn { ...httpResult, error: parallelError };\n\t\t}\n\t}\n\tif (signal?.aborted) return abortedResult(url);\n\n\tlet geminiResult: ExtractedContent | null = null;\n\ttry {\n\t\tconst geminiUrl = await loadGeminiUrlContext();\n\t\tgeminiResult = await geminiUrl.extractWithUrlContext(url, signal)\n\t\t\t?? await geminiUrl.extractWithGeminiWeb(url, signal);\n\t} catch (err) {\n\t\tif (isAbortError(err)) return abortedResult(url);\n\t\tif (isConfigParseError(err)) {\n\t\t\treturn { ...httpResult, error: errorMessage(err) };\n\t\t}\n\t}\n\n\tif (geminiResult) return geminiResult;\n\tif (signal?.aborted) return abortedResult(url);\n\n\tconst guidance = [\n\t\thttpResult.error,\n\t\t...(parallelError ? [`Parallel fallback failed: ${parallelError}`] : []),\n\t\t\"\",\n\t\t\"Fallback options:\",\n\t\t` \\u2022 Set PARALLEL_API_KEY in ${WEB_SEARCH_CONFIG_PATH}`,\n\t\t` \\u2022 Set GEMINI_API_KEY in ${WEB_SEARCH_CONFIG_PATH}`,\n\t\t\" \\u2022 Sign into gemini.google.com in Chrome\",\n\t\t\" \\u2022 Use web_search to find content about this topic\",\n\t].join(\"\\n\");\n\treturn { ...httpResult, error: guidance };\n}\n\nfunction isLikelyJSRendered(html: string): boolean {\n\t// Extract body content\n\tconst bodyMatch = html.match(/<body[^>]*>([\\s\\S]*?)<\\/body>/i);\n\tif (!bodyMatch) return false;\n\n\tconst bodyHtml = bodyMatch[1];\n\n\t// Strip tags to get text content\n\tconst textContent = bodyHtml\n\t\t.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n\t\t.replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n\t\t.replace(/<[^>]+>/g, \"\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\n\t// Count scripts\n\tconst scriptCount = (html.match(/<script/gi) || []).length;\n\n\t// Heuristic: little text content but many scripts suggests JS rendering\n\treturn textContent.length < 500 && scriptCount > 3;\n}\n\nasync function extractViaHttp(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent> {\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url });\n\n\tconst controller = new AbortController();\n\tconst timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n\tconst onAbort = () => controller.abort();\n\tif (signal?.aborted) controller.abort();\n\tsignal?.addEventListener(\"abort\", onAbort);\n\n\ttry {\n\t\tconst response = await fetchRemoteUrl(\n\t\t\turl,\n\t\t\t{\n\t\t\t\tsignal: controller.signal,\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\",\n\t\t\t\t\t\"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8\",\n\t\t\t\t\t\"Accept-Language\": \"en-US,en;q=0.9\",\n\t\t\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t\t\t\t\"Sec-Fetch-Dest\": \"document\",\n\t\t\t\t\t\"Sec-Fetch-Mode\": \"navigate\",\n\t\t\t\t\t\"Sec-Fetch-Site\": \"none\",\n\t\t\t\t\t\"Sec-Fetch-User\": \"?1\",\n\t\t\t\t\t\"Upgrade-Insecure-Requests\": \"1\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ allowRanges: loadSsrfAllowRanges(), lookup: options?.lookup },\n\t\t);\n\n\t\tif (!response.ok) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `HTTP ${response.status}: ${response.statusText}`,\n\t\t\t};\n\t\t}\n\n\t\tconst contentLengthHeader = response.headers.get(\"content-length\");\n\t\tconst contentType = response.headers.get(\"content-type\") || \"\";\n\t\tconst isPDFContent = isPDF(url, contentType);\n\t\tconst maxResponseSize = isPDFContent ? 20 * 1024 * 1024 : 5 * 1024 * 1024;\n\t\tif (contentLengthHeader) {\n\t\t\tconst contentLength = parseInt(contentLengthHeader, 10);\n\t\t\tif (contentLength > maxResponseSize) {\n\t\t\t\tawait response.body?.cancel();\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn {\n\t\t\t\t\turl,\n\t\t\t\t\ttitle: \"\",\n\t\t\t\t\tcontent: \"\",\n\t\t\t\t\terror: `Response too large (${Math.round(contentLength / 1024 / 1024)}MB)`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif (isPDFContent) {\n\t\t\tconst bytes = await readBoundedBody(response, maxResponseSize, controller.signal);\n\t\t\ttry {\n\t\t\t\tconst buffer = bytes.buffer;\n\t\t\t\tconst { extractPDFToMarkdown } = await loadPdfExtract();\n\t\t\t\tconst result = await extractPDFToMarkdown(buffer, url);\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn {\n\t\t\t\t\turl,\n\t\t\t\t\ttitle: result.title,\n\t\t\t\t\tcontent: `PDF extracted and saved to: ${result.outputPath}\\n\\nPages: ${result.pages}\\nCharacters: ${result.chars}`,\n\t\t\t\t\terror: null,\n\t\t\t\t};\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\t\tactivityMonitor.logError(activityId, message);\n\t\t\t\treturn { url, title: \"\", content: \"\", error: `PDF extraction failed: ${message}` };\n\t\t\t}\n\t\t}\n\n\t\tif (contentType.includes(\"application/octet-stream\") ||\n\t\t\tcontentType.includes(\"image/\") ||\n\t\t\tcontentType.includes(\"audio/\") ||\n\t\t\tcontentType.includes(\"video/\") ||\n\t\t\tcontentType.includes(\"application/zip\")) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: `Unsupported content type: ${contentType.split(\";\")[0]}`,\n\t\t\t};\n\t\t}\n\n\t\tconst text = new TextDecoder().decode(await readBoundedBody(response, maxResponseSize, controller.signal));\n\t\tconst isHTML = contentType.includes(\"text/html\") || contentType.includes(\"application/xhtml+xml\");\n\n\t\tif (!isHTML) {\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\tconst title = extractTextTitle(text, url);\n\t\t\treturn { url, title, content: text, error: null };\n\t\t}\n\n\t\tconst { document } = parseHTML(text);\n\t\tconst reader = new Readability(document as unknown as Document);\n\t\tconst article = reader.parse();\n\n\t\tif (!article) {\n\t\t\tconst rscResult = extractRSCContent(text);\n\t\t\tif (rscResult) {\n\t\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\t\t\treturn { url, title: rscResult.title, content: rscResult.content, error: null };\n\t\t\t}\n\n\t\t\tactivityMonitor.logComplete(activityId, response.status);\n\n\t\t\t// Provide more specific error message\n\t\t\tconst jsRendered = isLikelyJSRendered(text);\n\t\t\tconst errorMsg = jsRendered\n\t\t\t\t? \"Page appears to be JavaScript-rendered (content loads dynamically)\"\n\t\t\t\t: \"Could not extract readable content from HTML structure\";\n\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"\",\n\t\t\t\tcontent: \"\",\n\t\t\t\terror: errorMsg,\n\t\t\t};\n\t\t}\n\n\t\tconst markdown = turndown.turndown(article.content);\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\n\t\tif (markdown.length < MIN_USEFUL_CONTENT) {\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: article.title || \"\",\n\t\t\t\tcontent: markdown,\n\t\t\t\terror: isLikelyJSRendered(text)\n\t\t\t\t\t? \"Page appears to be JavaScript-rendered (content loads dynamically)\"\n\t\t\t\t\t: \"Extracted content appears incomplete\",\n\t\t\t};\n\t\t}\n\n\t\treturn { url, title: article.title || \"\", content: markdown, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (message.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, message);\n\t\t}\n\t\treturn { url, title: \"\", content: \"\", error: message };\n\t} finally {\n\t\tclearTimeout(timeoutId);\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t}\n}\n\nexport function extractHeadingTitle(text: string): string | null {\n\tconst match = text.match(/^#{1,2}\\s+(.+)/m);\n\tif (!match) return null;\n\tconst cleaned = match[1].replace(/\\*+/g, \"\").trim();\n\treturn cleaned || null;\n}\n\nfunction extractTextTitle(text: string, url: string): string {\n\treturn extractHeadingTitle(text) ?? (new URL(url).pathname.split(\"/\").pop() || url);\n}\n\nexport async function fetchAllContent(\n\turls: string[],\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent[]> {\n\treturn Promise.all(urls.map((url) => fetchLimit(() => extractContent(url, signal, options))));\n}\n"]}
@@ -9,5 +9,4 @@ export interface GitHubUrlInfo {
9
9
  }
10
10
  export declare function parseGitHubUrl(url: string): GitHubUrlInfo | null;
11
11
  export declare function extractGitHub(url: string, signal?: AbortSignal, forceClone?: boolean): Promise<ExtractedContent | null>;
12
- export declare function clearCloneCache(): void;
13
12
  //# sourceMappingURL=github-extract.d.ts.map