webpeel 0.19.4 → 0.20.0

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 (544) hide show
  1. package/README.md +2 -2
  2. package/dist/cache.d.ts +0 -1
  3. package/dist/cache.js +0 -1
  4. package/dist/cli/commands/auth.d.ts +5 -0
  5. package/dist/cli/commands/auth.js +476 -0
  6. package/dist/cli/commands/fetch.d.ts +6 -0
  7. package/dist/cli/commands/fetch.js +1015 -0
  8. package/dist/cli/commands/interact.d.ts +5 -0
  9. package/dist/cli/commands/interact.js +839 -0
  10. package/dist/cli/commands/jobs.d.ts +5 -0
  11. package/dist/cli/commands/jobs.js +997 -0
  12. package/dist/cli/commands/screenshot.d.ts +5 -0
  13. package/dist/cli/commands/screenshot.js +273 -0
  14. package/dist/cli/commands/search.d.ts +5 -0
  15. package/dist/cli/commands/search.js +524 -0
  16. package/dist/cli/utils.d.ts +84 -0
  17. package/dist/cli/utils.js +686 -0
  18. package/dist/cli-auth.d.ts +0 -1
  19. package/dist/cli-auth.js +0 -1
  20. package/dist/cli.d.ts +7 -6
  21. package/dist/cli.js +35 -4698
  22. package/dist/core/actions.d.ts +0 -1
  23. package/dist/core/actions.js +0 -1
  24. package/dist/core/agent.d.ts +0 -1
  25. package/dist/core/agent.js +9 -12
  26. package/dist/core/answer.d.ts +0 -1
  27. package/dist/core/answer.js +0 -1
  28. package/dist/core/application-tracker.d.ts +0 -1
  29. package/dist/core/application-tracker.js +0 -1
  30. package/dist/core/apply.d.ts +0 -1
  31. package/dist/core/apply.js +0 -1
  32. package/dist/core/auto-extract.d.ts +0 -1
  33. package/dist/core/auto-extract.js +0 -1
  34. package/dist/core/auto-interact.d.ts +0 -1
  35. package/dist/core/auto-interact.js +0 -1
  36. package/dist/core/bm25-filter.d.ts +0 -1
  37. package/dist/core/bm25-filter.js +0 -1
  38. package/dist/core/branding.d.ts +0 -1
  39. package/dist/core/branding.js +0 -1
  40. package/dist/core/browser-fetch.d.ts +0 -1
  41. package/dist/core/browser-fetch.js +17 -10
  42. package/dist/core/browser-pool.d.ts +0 -1
  43. package/dist/core/browser-pool.js +0 -1
  44. package/dist/core/budget.d.ts +0 -1
  45. package/dist/core/budget.js +0 -1
  46. package/dist/core/cache.d.ts +0 -1
  47. package/dist/core/cache.js +0 -1
  48. package/dist/core/cf-worker-proxy.d.ts +0 -1
  49. package/dist/core/cf-worker-proxy.js +0 -1
  50. package/dist/core/challenge-detection.d.ts +0 -1
  51. package/dist/core/challenge-detection.js +0 -1
  52. package/dist/core/change-tracking.d.ts +0 -1
  53. package/dist/core/change-tracking.js +0 -1
  54. package/dist/core/chunker.d.ts +0 -1
  55. package/dist/core/chunker.js +0 -1
  56. package/dist/core/chunking.d.ts +0 -1
  57. package/dist/core/chunking.js +0 -1
  58. package/dist/core/cloak-fetch.d.ts +0 -1
  59. package/dist/core/cloak-fetch.js +0 -1
  60. package/dist/core/content-pruner.d.ts +0 -1
  61. package/dist/core/content-pruner.js +0 -1
  62. package/dist/core/crawl-checkpoint.d.ts +0 -1
  63. package/dist/core/crawl-checkpoint.js +0 -1
  64. package/dist/core/crawler.d.ts +0 -1
  65. package/dist/core/crawler.js +6 -5
  66. package/dist/core/cycle-fetch.d.ts +0 -1
  67. package/dist/core/cycle-fetch.js +0 -1
  68. package/dist/core/deep-fetch.d.ts +0 -1
  69. package/dist/core/deep-fetch.js +0 -1
  70. package/dist/core/design-analysis.d.ts +0 -1
  71. package/dist/core/design-analysis.js +0 -1
  72. package/dist/core/design-compare.d.ts +0 -1
  73. package/dist/core/design-compare.js +0 -1
  74. package/dist/core/diff.d.ts +0 -1
  75. package/dist/core/diff.js +0 -1
  76. package/dist/core/dns-cache.d.ts +0 -1
  77. package/dist/core/dns-cache.js +0 -1
  78. package/dist/core/documents.d.ts +0 -1
  79. package/dist/core/documents.js +0 -1
  80. package/dist/core/domain-extractors.d.ts +0 -1
  81. package/dist/core/domain-extractors.js +0 -1
  82. package/dist/core/extract-inline.d.ts +0 -1
  83. package/dist/core/extract-inline.js +0 -1
  84. package/dist/core/extract-listings.d.ts +0 -1
  85. package/dist/core/extract-listings.js +0 -1
  86. package/dist/core/extract.d.ts +0 -1
  87. package/dist/core/extract.js +0 -1
  88. package/dist/core/fetcher.d.ts +0 -1
  89. package/dist/core/fetcher.js +0 -1
  90. package/dist/core/google-cache.d.ts +0 -1
  91. package/dist/core/google-cache.js +0 -1
  92. package/dist/core/hotel-search.d.ts +0 -1
  93. package/dist/core/hotel-search.js +0 -1
  94. package/dist/core/http-fetch.d.ts +0 -1
  95. package/dist/core/http-fetch.js +5 -7
  96. package/dist/core/human.d.ts +0 -1
  97. package/dist/core/human.js +0 -1
  98. package/dist/core/jobs.d.ts +0 -1
  99. package/dist/core/jobs.js +0 -1
  100. package/dist/core/json-ld.d.ts +0 -1
  101. package/dist/core/json-ld.js +0 -1
  102. package/dist/core/llm-extract.d.ts +0 -1
  103. package/dist/core/llm-extract.js +0 -1
  104. package/dist/core/logger.d.ts +17 -0
  105. package/dist/core/logger.js +44 -0
  106. package/dist/core/map.d.ts +0 -1
  107. package/dist/core/map.js +0 -1
  108. package/dist/core/markdown.d.ts +0 -1
  109. package/dist/core/markdown.js +0 -1
  110. package/dist/core/metadata.d.ts +0 -1
  111. package/dist/core/metadata.js +0 -1
  112. package/dist/core/paginate.d.ts +0 -1
  113. package/dist/core/paginate.js +0 -1
  114. package/dist/core/pdf.d.ts +0 -1
  115. package/dist/core/pdf.js +0 -1
  116. package/dist/core/peel-tls.d.ts +0 -1
  117. package/dist/core/peel-tls.js +0 -1
  118. package/dist/core/pipeline.d.ts +0 -1
  119. package/dist/core/pipeline.js +22 -25
  120. package/dist/core/profiles.d.ts +0 -1
  121. package/dist/core/profiles.js +0 -1
  122. package/dist/core/quick-answer.d.ts +0 -1
  123. package/dist/core/quick-answer.js +0 -1
  124. package/dist/core/rate-governor.d.ts +0 -1
  125. package/dist/core/rate-governor.js +0 -1
  126. package/dist/core/readability.d.ts +0 -1
  127. package/dist/core/readability.js +0 -1
  128. package/dist/core/research.d.ts +0 -1
  129. package/dist/core/research.js +0 -1
  130. package/dist/core/schema-extraction.d.ts +0 -1
  131. package/dist/core/schema-extraction.js +0 -1
  132. package/dist/core/schema-postprocess.d.ts +0 -1
  133. package/dist/core/schema-postprocess.js +0 -1
  134. package/dist/core/schema-templates.d.ts +0 -1
  135. package/dist/core/schema-templates.js +0 -1
  136. package/dist/core/screenshot.d.ts +0 -1
  137. package/dist/core/screenshot.js +0 -1
  138. package/dist/core/search-fallback.d.ts +0 -1
  139. package/dist/core/search-fallback.js +0 -1
  140. package/dist/core/search-provider.d.ts +0 -1
  141. package/dist/core/search-provider.js +18 -21
  142. package/dist/core/site-search.d.ts +0 -1
  143. package/dist/core/site-search.js +0 -1
  144. package/dist/core/sitemap.d.ts +0 -1
  145. package/dist/core/sitemap.js +0 -1
  146. package/dist/core/stealth-patches.d.ts +0 -1
  147. package/dist/core/stealth-patches.js +0 -1
  148. package/dist/core/stemmer.d.ts +0 -1
  149. package/dist/core/stemmer.js +0 -1
  150. package/dist/core/strategies.d.ts +6 -1
  151. package/dist/core/strategies.js +29 -41
  152. package/dist/core/strategy-hooks.d.ts +0 -1
  153. package/dist/core/strategy-hooks.js +0 -1
  154. package/dist/core/summarize.d.ts +0 -1
  155. package/dist/core/summarize.js +0 -1
  156. package/dist/core/synonyms.d.ts +0 -1
  157. package/dist/core/synonyms.js +0 -1
  158. package/dist/core/table-format.d.ts +0 -1
  159. package/dist/core/table-format.js +0 -1
  160. package/dist/core/timing.d.ts +0 -1
  161. package/dist/core/timing.js +0 -1
  162. package/dist/core/user-agents.d.ts +0 -1
  163. package/dist/core/user-agents.js +0 -1
  164. package/dist/core/watch-manager.d.ts +0 -1
  165. package/dist/core/watch-manager.js +0 -1
  166. package/dist/core/watch.d.ts +0 -1
  167. package/dist/core/watch.js +0 -1
  168. package/dist/core/youtube.d.ts +0 -1
  169. package/dist/core/youtube.js +0 -1
  170. package/dist/index.d.ts +8 -3
  171. package/dist/index.js +27 -3
  172. package/dist/integrations/index.d.ts +0 -1
  173. package/dist/integrations/index.js +0 -1
  174. package/dist/integrations/langchain.d.ts +0 -1
  175. package/dist/integrations/langchain.js +0 -1
  176. package/dist/integrations/llamaindex.d.ts +0 -1
  177. package/dist/integrations/llamaindex.js +0 -1
  178. package/dist/mcp/handlers/act.d.ts +5 -0
  179. package/dist/mcp/handlers/act.js +34 -0
  180. package/dist/mcp/handlers/definitions.d.ts +6 -0
  181. package/dist/mcp/handlers/definitions.js +266 -0
  182. package/dist/mcp/handlers/extract.d.ts +6 -0
  183. package/dist/mcp/handlers/extract.js +102 -0
  184. package/dist/mcp/handlers/fetch.d.ts +6 -0
  185. package/dist/mcp/handlers/fetch.js +98 -0
  186. package/dist/mcp/handlers/find.d.ts +5 -0
  187. package/dist/mcp/handlers/find.js +137 -0
  188. package/dist/mcp/handlers/index.d.ts +13 -0
  189. package/dist/mcp/handlers/index.js +61 -0
  190. package/dist/mcp/handlers/legacy.d.ts +25 -0
  191. package/dist/mcp/handlers/legacy.js +450 -0
  192. package/dist/mcp/handlers/meta.d.ts +6 -0
  193. package/dist/mcp/handlers/meta.js +31 -0
  194. package/dist/mcp/handlers/monitor.d.ts +5 -0
  195. package/dist/mcp/handlers/monitor.js +41 -0
  196. package/dist/mcp/handlers/read.d.ts +6 -0
  197. package/dist/mcp/handlers/read.js +63 -0
  198. package/dist/mcp/handlers/see.d.ts +5 -0
  199. package/dist/mcp/handlers/see.js +75 -0
  200. package/dist/mcp/handlers/types.d.ts +29 -0
  201. package/dist/mcp/handlers/types.js +28 -0
  202. package/dist/mcp/server.d.ts +3 -4
  203. package/dist/mcp/server.js +35 -1101
  204. package/dist/mcp/smart-router.d.ts +0 -1
  205. package/dist/mcp/smart-router.js +3 -1
  206. package/dist/types.d.ts +6 -1
  207. package/dist/types.js +0 -1
  208. package/package.json +3 -13
  209. package/dist/cache.d.ts.map +0 -1
  210. package/dist/cache.js.map +0 -1
  211. package/dist/cli-auth.d.ts.map +0 -1
  212. package/dist/cli-auth.js.map +0 -1
  213. package/dist/cli.bundle.cjs +0 -159248
  214. package/dist/cli.d.ts.map +0 -1
  215. package/dist/cli.js.map +0 -1
  216. package/dist/core/actions.d.ts.map +0 -1
  217. package/dist/core/actions.js.map +0 -1
  218. package/dist/core/agent.d.ts.map +0 -1
  219. package/dist/core/agent.js.map +0 -1
  220. package/dist/core/answer.d.ts.map +0 -1
  221. package/dist/core/answer.js.map +0 -1
  222. package/dist/core/application-tracker.d.ts.map +0 -1
  223. package/dist/core/application-tracker.js.map +0 -1
  224. package/dist/core/apply.d.ts.map +0 -1
  225. package/dist/core/apply.js.map +0 -1
  226. package/dist/core/auto-extract.d.ts.map +0 -1
  227. package/dist/core/auto-extract.js.map +0 -1
  228. package/dist/core/auto-interact.d.ts.map +0 -1
  229. package/dist/core/auto-interact.js.map +0 -1
  230. package/dist/core/bm25-filter.d.ts.map +0 -1
  231. package/dist/core/bm25-filter.js.map +0 -1
  232. package/dist/core/branding.d.ts.map +0 -1
  233. package/dist/core/branding.js.map +0 -1
  234. package/dist/core/browser-fetch.d.ts.map +0 -1
  235. package/dist/core/browser-fetch.js.map +0 -1
  236. package/dist/core/browser-pool.d.ts.map +0 -1
  237. package/dist/core/browser-pool.js.map +0 -1
  238. package/dist/core/budget.d.ts.map +0 -1
  239. package/dist/core/budget.js.map +0 -1
  240. package/dist/core/cache.d.ts.map +0 -1
  241. package/dist/core/cache.js.map +0 -1
  242. package/dist/core/cf-worker-proxy.d.ts.map +0 -1
  243. package/dist/core/cf-worker-proxy.js.map +0 -1
  244. package/dist/core/challenge-detection.d.ts.map +0 -1
  245. package/dist/core/challenge-detection.js.map +0 -1
  246. package/dist/core/change-tracking.d.ts.map +0 -1
  247. package/dist/core/change-tracking.js.map +0 -1
  248. package/dist/core/chunker.d.ts.map +0 -1
  249. package/dist/core/chunker.js.map +0 -1
  250. package/dist/core/chunking.d.ts.map +0 -1
  251. package/dist/core/chunking.js.map +0 -1
  252. package/dist/core/cloak-fetch.d.ts.map +0 -1
  253. package/dist/core/cloak-fetch.js.map +0 -1
  254. package/dist/core/content-pruner.d.ts.map +0 -1
  255. package/dist/core/content-pruner.js.map +0 -1
  256. package/dist/core/crawl-checkpoint.d.ts.map +0 -1
  257. package/dist/core/crawl-checkpoint.js.map +0 -1
  258. package/dist/core/crawler.d.ts.map +0 -1
  259. package/dist/core/crawler.js.map +0 -1
  260. package/dist/core/cycle-fetch.d.ts.map +0 -1
  261. package/dist/core/cycle-fetch.js.map +0 -1
  262. package/dist/core/deep-fetch.d.ts.map +0 -1
  263. package/dist/core/deep-fetch.js.map +0 -1
  264. package/dist/core/design-analysis.d.ts.map +0 -1
  265. package/dist/core/design-analysis.js.map +0 -1
  266. package/dist/core/design-compare.d.ts.map +0 -1
  267. package/dist/core/design-compare.js.map +0 -1
  268. package/dist/core/diff.d.ts.map +0 -1
  269. package/dist/core/diff.js.map +0 -1
  270. package/dist/core/dns-cache.d.ts.map +0 -1
  271. package/dist/core/dns-cache.js.map +0 -1
  272. package/dist/core/documents.d.ts.map +0 -1
  273. package/dist/core/documents.js.map +0 -1
  274. package/dist/core/domain-extractors.d.ts.map +0 -1
  275. package/dist/core/domain-extractors.js.map +0 -1
  276. package/dist/core/extract-inline.d.ts.map +0 -1
  277. package/dist/core/extract-inline.js.map +0 -1
  278. package/dist/core/extract-listings.d.ts.map +0 -1
  279. package/dist/core/extract-listings.js.map +0 -1
  280. package/dist/core/extract.d.ts.map +0 -1
  281. package/dist/core/extract.js.map +0 -1
  282. package/dist/core/fetcher.d.ts.map +0 -1
  283. package/dist/core/fetcher.js.map +0 -1
  284. package/dist/core/google-cache.d.ts.map +0 -1
  285. package/dist/core/google-cache.js.map +0 -1
  286. package/dist/core/hotel-search.d.ts.map +0 -1
  287. package/dist/core/hotel-search.js.map +0 -1
  288. package/dist/core/http-fetch.d.ts.map +0 -1
  289. package/dist/core/http-fetch.js.map +0 -1
  290. package/dist/core/human.d.ts.map +0 -1
  291. package/dist/core/human.js.map +0 -1
  292. package/dist/core/jobs.d.ts.map +0 -1
  293. package/dist/core/jobs.js.map +0 -1
  294. package/dist/core/json-ld.d.ts.map +0 -1
  295. package/dist/core/json-ld.js.map +0 -1
  296. package/dist/core/llm-extract.d.ts.map +0 -1
  297. package/dist/core/llm-extract.js.map +0 -1
  298. package/dist/core/map.d.ts.map +0 -1
  299. package/dist/core/map.js.map +0 -1
  300. package/dist/core/markdown.d.ts.map +0 -1
  301. package/dist/core/markdown.js.map +0 -1
  302. package/dist/core/metadata.d.ts.map +0 -1
  303. package/dist/core/metadata.js.map +0 -1
  304. package/dist/core/paginate.d.ts.map +0 -1
  305. package/dist/core/paginate.js.map +0 -1
  306. package/dist/core/pdf.d.ts.map +0 -1
  307. package/dist/core/pdf.js.map +0 -1
  308. package/dist/core/peel-tls.d.ts.map +0 -1
  309. package/dist/core/peel-tls.js.map +0 -1
  310. package/dist/core/pipeline.d.ts.map +0 -1
  311. package/dist/core/pipeline.js.map +0 -1
  312. package/dist/core/profiles.d.ts.map +0 -1
  313. package/dist/core/profiles.js.map +0 -1
  314. package/dist/core/quick-answer.d.ts.map +0 -1
  315. package/dist/core/quick-answer.js.map +0 -1
  316. package/dist/core/rate-governor.d.ts.map +0 -1
  317. package/dist/core/rate-governor.js.map +0 -1
  318. package/dist/core/readability.d.ts.map +0 -1
  319. package/dist/core/readability.js.map +0 -1
  320. package/dist/core/research.d.ts.map +0 -1
  321. package/dist/core/research.js.map +0 -1
  322. package/dist/core/schema-extraction.d.ts.map +0 -1
  323. package/dist/core/schema-extraction.js.map +0 -1
  324. package/dist/core/schema-postprocess.d.ts.map +0 -1
  325. package/dist/core/schema-postprocess.js.map +0 -1
  326. package/dist/core/schema-templates.d.ts.map +0 -1
  327. package/dist/core/schema-templates.js.map +0 -1
  328. package/dist/core/screenshot.d.ts.map +0 -1
  329. package/dist/core/screenshot.js.map +0 -1
  330. package/dist/core/search-fallback.d.ts.map +0 -1
  331. package/dist/core/search-fallback.js.map +0 -1
  332. package/dist/core/search-provider.d.ts.map +0 -1
  333. package/dist/core/search-provider.js.map +0 -1
  334. package/dist/core/site-search.d.ts.map +0 -1
  335. package/dist/core/site-search.js.map +0 -1
  336. package/dist/core/sitemap.d.ts.map +0 -1
  337. package/dist/core/sitemap.js.map +0 -1
  338. package/dist/core/stealth-patches.d.ts.map +0 -1
  339. package/dist/core/stealth-patches.js.map +0 -1
  340. package/dist/core/stemmer.d.ts.map +0 -1
  341. package/dist/core/stemmer.js.map +0 -1
  342. package/dist/core/strategies.d.ts.map +0 -1
  343. package/dist/core/strategies.js.map +0 -1
  344. package/dist/core/strategy-hooks.d.ts.map +0 -1
  345. package/dist/core/strategy-hooks.js.map +0 -1
  346. package/dist/core/summarize.d.ts.map +0 -1
  347. package/dist/core/summarize.js.map +0 -1
  348. package/dist/core/synonyms.d.ts.map +0 -1
  349. package/dist/core/synonyms.js.map +0 -1
  350. package/dist/core/table-format.d.ts.map +0 -1
  351. package/dist/core/table-format.js.map +0 -1
  352. package/dist/core/timing.d.ts.map +0 -1
  353. package/dist/core/timing.js.map +0 -1
  354. package/dist/core/user-agents.d.ts.map +0 -1
  355. package/dist/core/user-agents.js.map +0 -1
  356. package/dist/core/watch-manager.d.ts.map +0 -1
  357. package/dist/core/watch-manager.js.map +0 -1
  358. package/dist/core/watch.d.ts.map +0 -1
  359. package/dist/core/watch.js.map +0 -1
  360. package/dist/core/youtube.d.ts.map +0 -1
  361. package/dist/core/youtube.js.map +0 -1
  362. package/dist/index.d.ts.map +0 -1
  363. package/dist/index.js.map +0 -1
  364. package/dist/integrations/index.d.ts.map +0 -1
  365. package/dist/integrations/index.js.map +0 -1
  366. package/dist/integrations/langchain.d.ts.map +0 -1
  367. package/dist/integrations/langchain.js.map +0 -1
  368. package/dist/integrations/llamaindex.d.ts.map +0 -1
  369. package/dist/integrations/llamaindex.js.map +0 -1
  370. package/dist/mcp/server.d.ts.map +0 -1
  371. package/dist/mcp/server.js.map +0 -1
  372. package/dist/mcp/smart-router.d.ts.map +0 -1
  373. package/dist/mcp/smart-router.js.map +0 -1
  374. package/dist/server/app.d.ts +0 -15
  375. package/dist/server/app.d.ts.map +0 -1
  376. package/dist/server/app.js +0 -350
  377. package/dist/server/app.js.map +0 -1
  378. package/dist/server/auth-store.d.ts +0 -28
  379. package/dist/server/auth-store.d.ts.map +0 -1
  380. package/dist/server/auth-store.js +0 -89
  381. package/dist/server/auth-store.js.map +0 -1
  382. package/dist/server/email-service.d.ts +0 -22
  383. package/dist/server/email-service.d.ts.map +0 -1
  384. package/dist/server/email-service.js +0 -80
  385. package/dist/server/email-service.js.map +0 -1
  386. package/dist/server/job-queue.d.ts +0 -93
  387. package/dist/server/job-queue.d.ts.map +0 -1
  388. package/dist/server/job-queue.js +0 -146
  389. package/dist/server/job-queue.js.map +0 -1
  390. package/dist/server/logger.d.ts +0 -11
  391. package/dist/server/logger.d.ts.map +0 -1
  392. package/dist/server/logger.js +0 -38
  393. package/dist/server/logger.js.map +0 -1
  394. package/dist/server/middleware/auth.d.ts +0 -29
  395. package/dist/server/middleware/auth.d.ts.map +0 -1
  396. package/dist/server/middleware/auth.js +0 -222
  397. package/dist/server/middleware/auth.js.map +0 -1
  398. package/dist/server/middleware/rate-limit.d.ts +0 -25
  399. package/dist/server/middleware/rate-limit.d.ts.map +0 -1
  400. package/dist/server/middleware/rate-limit.js +0 -168
  401. package/dist/server/middleware/rate-limit.js.map +0 -1
  402. package/dist/server/middleware/url-validator.d.ts +0 -16
  403. package/dist/server/middleware/url-validator.d.ts.map +0 -1
  404. package/dist/server/middleware/url-validator.js +0 -187
  405. package/dist/server/middleware/url-validator.js.map +0 -1
  406. package/dist/server/openapi.yaml +0 -4944
  407. package/dist/server/pg-auth-store.d.ts +0 -133
  408. package/dist/server/pg-auth-store.d.ts.map +0 -1
  409. package/dist/server/pg-auth-store.js +0 -473
  410. package/dist/server/pg-auth-store.js.map +0 -1
  411. package/dist/server/pg-job-queue.d.ts +0 -60
  412. package/dist/server/pg-job-queue.d.ts.map +0 -1
  413. package/dist/server/pg-job-queue.js +0 -365
  414. package/dist/server/pg-job-queue.js.map +0 -1
  415. package/dist/server/premium/domain-intel.d.ts +0 -17
  416. package/dist/server/premium/domain-intel.d.ts.map +0 -1
  417. package/dist/server/premium/domain-intel.js +0 -134
  418. package/dist/server/premium/domain-intel.js.map +0 -1
  419. package/dist/server/premium/index.d.ts +0 -18
  420. package/dist/server/premium/index.d.ts.map +0 -1
  421. package/dist/server/premium/index.js +0 -36
  422. package/dist/server/premium/index.js.map +0 -1
  423. package/dist/server/premium/swr-cache.d.ts +0 -15
  424. package/dist/server/premium/swr-cache.d.ts.map +0 -1
  425. package/dist/server/premium/swr-cache.js +0 -35
  426. package/dist/server/premium/swr-cache.js.map +0 -1
  427. package/dist/server/routes/activity.d.ts +0 -7
  428. package/dist/server/routes/activity.d.ts.map +0 -1
  429. package/dist/server/routes/activity.js +0 -68
  430. package/dist/server/routes/activity.js.map +0 -1
  431. package/dist/server/routes/agent.d.ts +0 -16
  432. package/dist/server/routes/agent.d.ts.map +0 -1
  433. package/dist/server/routes/agent.js +0 -247
  434. package/dist/server/routes/agent.js.map +0 -1
  435. package/dist/server/routes/answer.d.ts +0 -6
  436. package/dist/server/routes/answer.d.ts.map +0 -1
  437. package/dist/server/routes/answer.js +0 -133
  438. package/dist/server/routes/answer.js.map +0 -1
  439. package/dist/server/routes/ask.d.ts +0 -23
  440. package/dist/server/routes/ask.d.ts.map +0 -1
  441. package/dist/server/routes/ask.js +0 -119
  442. package/dist/server/routes/ask.js.map +0 -1
  443. package/dist/server/routes/batch.d.ts +0 -7
  444. package/dist/server/routes/batch.d.ts.map +0 -1
  445. package/dist/server/routes/batch.js +0 -412
  446. package/dist/server/routes/batch.js.map +0 -1
  447. package/dist/server/routes/cli-usage.d.ts +0 -7
  448. package/dist/server/routes/cli-usage.d.ts.map +0 -1
  449. package/dist/server/routes/cli-usage.js +0 -121
  450. package/dist/server/routes/cli-usage.js.map +0 -1
  451. package/dist/server/routes/compat.d.ts +0 -24
  452. package/dist/server/routes/compat.d.ts.map +0 -1
  453. package/dist/server/routes/compat.js +0 -653
  454. package/dist/server/routes/compat.js.map +0 -1
  455. package/dist/server/routes/deep-fetch.d.ts +0 -9
  456. package/dist/server/routes/deep-fetch.d.ts.map +0 -1
  457. package/dist/server/routes/deep-fetch.js +0 -50
  458. package/dist/server/routes/deep-fetch.js.map +0 -1
  459. package/dist/server/routes/demo.d.ts +0 -25
  460. package/dist/server/routes/demo.d.ts.map +0 -1
  461. package/dist/server/routes/demo.js +0 -434
  462. package/dist/server/routes/demo.js.map +0 -1
  463. package/dist/server/routes/extract.d.ts +0 -9
  464. package/dist/server/routes/extract.d.ts.map +0 -1
  465. package/dist/server/routes/extract.js +0 -150
  466. package/dist/server/routes/extract.js.map +0 -1
  467. package/dist/server/routes/fetch.d.ts +0 -8
  468. package/dist/server/routes/fetch.d.ts.map +0 -1
  469. package/dist/server/routes/fetch.js +0 -988
  470. package/dist/server/routes/fetch.js.map +0 -1
  471. package/dist/server/routes/health.d.ts +0 -8
  472. package/dist/server/routes/health.d.ts.map +0 -1
  473. package/dist/server/routes/health.js +0 -20
  474. package/dist/server/routes/health.js.map +0 -1
  475. package/dist/server/routes/jobs.d.ts +0 -8
  476. package/dist/server/routes/jobs.d.ts.map +0 -1
  477. package/dist/server/routes/jobs.js +0 -487
  478. package/dist/server/routes/jobs.js.map +0 -1
  479. package/dist/server/routes/mcp.d.ts +0 -18
  480. package/dist/server/routes/mcp.d.ts.map +0 -1
  481. package/dist/server/routes/mcp.js +0 -1260
  482. package/dist/server/routes/mcp.js.map +0 -1
  483. package/dist/server/routes/oauth.d.ts +0 -10
  484. package/dist/server/routes/oauth.d.ts.map +0 -1
  485. package/dist/server/routes/oauth.js +0 -334
  486. package/dist/server/routes/oauth.js.map +0 -1
  487. package/dist/server/routes/quick-answer.d.ts +0 -9
  488. package/dist/server/routes/quick-answer.d.ts.map +0 -1
  489. package/dist/server/routes/quick-answer.js +0 -93
  490. package/dist/server/routes/quick-answer.js.map +0 -1
  491. package/dist/server/routes/screenshot.d.ts +0 -23
  492. package/dist/server/routes/screenshot.d.ts.map +0 -1
  493. package/dist/server/routes/screenshot.js +0 -819
  494. package/dist/server/routes/screenshot.js.map +0 -1
  495. package/dist/server/routes/search.d.ts +0 -7
  496. package/dist/server/routes/search.d.ts.map +0 -1
  497. package/dist/server/routes/search.js +0 -312
  498. package/dist/server/routes/search.js.map +0 -1
  499. package/dist/server/routes/session.d.ts +0 -16
  500. package/dist/server/routes/session.d.ts.map +0 -1
  501. package/dist/server/routes/session.js +0 -278
  502. package/dist/server/routes/session.js.map +0 -1
  503. package/dist/server/routes/stats.d.ts +0 -7
  504. package/dist/server/routes/stats.d.ts.map +0 -1
  505. package/dist/server/routes/stats.js +0 -65
  506. package/dist/server/routes/stats.js.map +0 -1
  507. package/dist/server/routes/stripe.d.ts +0 -16
  508. package/dist/server/routes/stripe.d.ts.map +0 -1
  509. package/dist/server/routes/stripe.js +0 -283
  510. package/dist/server/routes/stripe.js.map +0 -1
  511. package/dist/server/routes/users.d.ts +0 -9
  512. package/dist/server/routes/users.d.ts.map +0 -1
  513. package/dist/server/routes/users.js +0 -1211
  514. package/dist/server/routes/users.js.map +0 -1
  515. package/dist/server/routes/watch.d.ts +0 -16
  516. package/dist/server/routes/watch.d.ts.map +0 -1
  517. package/dist/server/routes/watch.js +0 -257
  518. package/dist/server/routes/watch.js.map +0 -1
  519. package/dist/server/routes/webhooks.d.ts +0 -16
  520. package/dist/server/routes/webhooks.d.ts.map +0 -1
  521. package/dist/server/routes/webhooks.js +0 -74
  522. package/dist/server/routes/webhooks.js.map +0 -1
  523. package/dist/server/routes/youtube.d.ts +0 -7
  524. package/dist/server/routes/youtube.d.ts.map +0 -1
  525. package/dist/server/routes/youtube.js +0 -93
  526. package/dist/server/routes/youtube.js.map +0 -1
  527. package/dist/server/sentry.d.ts +0 -14
  528. package/dist/server/sentry.d.ts.map +0 -1
  529. package/dist/server/sentry.js +0 -39
  530. package/dist/server/sentry.js.map +0 -1
  531. package/dist/server/types.d.ts +0 -16
  532. package/dist/server/types.d.ts.map +0 -1
  533. package/dist/server/types.js +0 -8
  534. package/dist/server/types.js.map +0 -1
  535. package/dist/server/utils/response.d.ts +0 -45
  536. package/dist/server/utils/response.d.ts.map +0 -1
  537. package/dist/server/utils/response.js +0 -70
  538. package/dist/server/utils/response.js.map +0 -1
  539. package/dist/server/utils/sse.d.ts +0 -23
  540. package/dist/server/utils/sse.d.ts.map +0 -1
  541. package/dist/server/utils/sse.js +0 -39
  542. package/dist/server/utils/sse.js.map +0 -1
  543. package/dist/types.d.ts.map +0 -1
  544. package/dist/types.js.map +0 -1
@@ -0,0 +1,839 @@
1
+ /**
2
+ * Interact commands: ask, webask, watch, diff, track, summarize, agent, answer, research, schemas
3
+ */
4
+ import ora from 'ora';
5
+ import { peel, cleanup } from '../../index.js';
6
+ import { loadConfig } from '../../cli-auth.js';
7
+ import { writeStdout, formatRelativeTime } from '../utils.js';
8
+ import { runFetch } from './fetch.js';
9
+ import { SCHEMA_TEMPLATES, getSchemaTemplate, listSchemaTemplates } from '../../core/schema-templates.js';
10
+ export function registerInteractCommands(program) {
11
+ // ── ask subcommand (question mode) ────────────────────────────────────────
12
+ program
13
+ .command('ask <url> <question>')
14
+ .description('Ask a question about any page')
15
+ .option('--json', 'Output as JSON')
16
+ .option('-s, --silent', 'Silent mode')
17
+ .action(async (url, question, opts) => {
18
+ await runFetch(url, {
19
+ ...opts,
20
+ question,
21
+ readable: true,
22
+ });
23
+ });
24
+ // ── watch command ─────────────────────────────────────────────────────────
25
+ program
26
+ .command('watch <url>')
27
+ .description('Monitor a URL for changes and assertion failures')
28
+ .option('--interval <duration>', 'Check interval (e.g. 30s, 5m, 1h)', '5m')
29
+ .option('--assert <condition...>', 'Assertion(s) to check (e.g. "status=200" "body.health=ok")')
30
+ .option('--webhook <url>', 'POST this URL on assertion failure or content change')
31
+ .option('-t, --timeout <ms>', 'Per-request timeout in ms', (v) => parseInt(v, 10), 10000)
32
+ .option('--max-checks <n>', 'Stop after N checks (default: unlimited)', (v) => parseInt(v, 10))
33
+ .option('--json', 'Output each check as NDJSON to stdout')
34
+ .option('-s, --silent', 'Only output on failures/changes')
35
+ .option('-r, --render', 'Use browser rendering for checks')
36
+ .action(async (url, options) => {
37
+ const { watch: runWatch, parseDuration, parseAssertion } = await import('../../core/watch.js');
38
+ // Validate URL
39
+ try {
40
+ const parsed = new URL(url);
41
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
42
+ console.error('Error: Only HTTP and HTTPS protocols are allowed');
43
+ process.exit(1);
44
+ }
45
+ }
46
+ catch {
47
+ console.error(`Error: Invalid URL format: ${url}`);
48
+ process.exit(1);
49
+ }
50
+ // Parse interval
51
+ let intervalMs;
52
+ try {
53
+ intervalMs = parseDuration(options.interval);
54
+ }
55
+ catch (e) {
56
+ console.error(`Error: ${e.message}`);
57
+ process.exit(1);
58
+ }
59
+ // Parse assertions
60
+ const assertions = [];
61
+ if (options.assert && Array.isArray(options.assert)) {
62
+ for (const expr of options.assert) {
63
+ try {
64
+ assertions.push(parseAssertion(expr));
65
+ }
66
+ catch (e) {
67
+ console.error(`Error: ${e.message}`);
68
+ process.exit(1);
69
+ }
70
+ }
71
+ }
72
+ if (!options.json && !options.silent) {
73
+ const intervalLabel = options.interval;
74
+ const assertLabel = assertions.length > 0
75
+ ? ` with ${assertions.length} assertion(s)`
76
+ : '';
77
+ process.stderr.write(`Watching ${url} every ${intervalLabel}${assertLabel}. Press Ctrl+C to stop.\n`);
78
+ }
79
+ const watchOptions = {
80
+ url,
81
+ intervalMs,
82
+ assertions,
83
+ webhookUrl: options.webhook,
84
+ timeout: options.timeout,
85
+ maxChecks: options.maxChecks,
86
+ render: options.render || false,
87
+ json: options.json || false,
88
+ silent: options.silent || false,
89
+ };
90
+ try {
91
+ await runWatch(watchOptions);
92
+ }
93
+ catch (error) {
94
+ console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
95
+ process.exit(1);
96
+ }
97
+ process.exit(0);
98
+ });
99
+ // ── diff command ──────────────────────────────────────────────────────────
100
+ program
101
+ .command('diff <url>')
102
+ .description('Show semantic diff between current content and the last tracked snapshot')
103
+ .option('--last', 'Compare against last tracked snapshot (default)')
104
+ .option('--against <snapshot-url>', 'Compare against the snapshot stored for a different URL')
105
+ .option('--fields <fields>', 'For JSON responses: only diff these fields (comma-separated dot-notation)')
106
+ .option('--json', 'Output diff as JSON')
107
+ .option('-r, --render', 'Use browser rendering')
108
+ .option('-t, --timeout <ms>', 'Request timeout in ms', (v) => parseInt(v, 10), 30000)
109
+ .option('-s, --silent', 'Silent mode (no spinner)')
110
+ .action(async (url, options) => {
111
+ const isJson = options.json;
112
+ // Validate URL
113
+ try {
114
+ const parsed = new URL(url);
115
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
116
+ if (isJson) {
117
+ await writeStdout(JSON.stringify({ success: false, error: { type: 'invalid_url', message: 'Only HTTP and HTTPS protocols are allowed' } }) + '\n');
118
+ }
119
+ else {
120
+ console.error('Error: Only HTTP and HTTPS protocols are allowed');
121
+ }
122
+ process.exit(1);
123
+ }
124
+ }
125
+ catch {
126
+ if (isJson) {
127
+ await writeStdout(JSON.stringify({ success: false, error: { type: 'invalid_url', message: `Invalid URL format: ${url}` } }) + '\n');
128
+ }
129
+ else {
130
+ console.error(`Error: Invalid URL format: ${url}`);
131
+ }
132
+ process.exit(1);
133
+ }
134
+ const spinner = options.silent ? null : ora('Fetching and diffing...').start();
135
+ try {
136
+ const { diffUrl } = await import('../../core/diff.js');
137
+ const fields = options.fields
138
+ ? options.fields.split(',').map((f) => f.trim()).filter(Boolean)
139
+ : undefined;
140
+ const result = await diffUrl(url, {
141
+ render: options.render || false,
142
+ timeout: options.timeout,
143
+ fields,
144
+ });
145
+ if (spinner) {
146
+ spinner.succeed(`Diff completed in ${result.changed ? 'CHANGED' : 'no change'}`);
147
+ }
148
+ if (isJson) {
149
+ await writeStdout(JSON.stringify(result, null, 2) + '\n');
150
+ }
151
+ else {
152
+ // Human-readable output
153
+ const ago = result.previousTimestamp
154
+ ? formatRelativeTime(new Date(result.previousTimestamp))
155
+ : 'unknown';
156
+ console.log(`\nComparing ${result.url} (now vs ${ago})\n`);
157
+ if (!result.changed) {
158
+ console.log(' No changes detected.');
159
+ }
160
+ else {
161
+ for (const change of result.changes) {
162
+ const label = change.field ?? change.path ?? '(unknown)';
163
+ if (change.type === 'modified') {
164
+ console.log(` Modified: ${label} ${change.before} → ${change.after}`);
165
+ }
166
+ else if (change.type === 'added') {
167
+ console.log(` Added: ${label} ${change.after}`);
168
+ }
169
+ else if (change.type === 'removed') {
170
+ console.log(` Removed: ${label} ${change.before}`);
171
+ }
172
+ }
173
+ }
174
+ console.log(`\nSummary: ${result.summary}`);
175
+ }
176
+ await cleanup();
177
+ process.exit(0);
178
+ }
179
+ catch (error) {
180
+ if (spinner)
181
+ spinner.fail('Diff failed');
182
+ if (isJson) {
183
+ await writeStdout(JSON.stringify({
184
+ error: error instanceof Error ? error.message : 'Unknown error',
185
+ code: 'FETCH_FAILED',
186
+ }) + '\n');
187
+ }
188
+ else {
189
+ console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
190
+ }
191
+ await cleanup();
192
+ process.exit(1);
193
+ }
194
+ });
195
+ // ── track command ─────────────────────────────────────────────────────────
196
+ program
197
+ .command('track <url>')
198
+ .description('Track changes on a URL (saves snapshot for use with `webpeel diff`)')
199
+ .option('-s, --silent', 'Silent mode (no spinner)')
200
+ .option('--json', 'Output as JSON')
201
+ .option('-r, --render', 'Use browser rendering')
202
+ .action(async (url, options) => {
203
+ const spinner = options.silent ? null : ora('Fetching and tracking...').start();
204
+ try {
205
+ // changeTracking: true saves the snapshot to ~/.webpeel/snapshots/ so that
206
+ // `webpeel diff` can compare against it later.
207
+ const result = await peel(url, {
208
+ render: options.render || false,
209
+ changeTracking: true,
210
+ });
211
+ if (spinner) {
212
+ spinner.succeed(`Tracked in ${result.elapsed}ms`);
213
+ }
214
+ const changeStatus = result.changeTracking?.changeStatus ?? 'new';
215
+ const previousScrapeAt = result.changeTracking?.previousScrapeAt ?? null;
216
+ if (options.json) {
217
+ await writeStdout(JSON.stringify({
218
+ url: result.url,
219
+ title: result.title,
220
+ fingerprint: result.fingerprint,
221
+ tokens: result.tokens,
222
+ contentType: result.contentType,
223
+ changeStatus,
224
+ previousScrapeAt,
225
+ lastChecked: new Date().toISOString(),
226
+ }, null, 2) + '\n');
227
+ }
228
+ else {
229
+ console.log(`URL: ${result.url}`);
230
+ console.log(`Title: ${result.title}`);
231
+ console.log(`Fingerprint: ${result.fingerprint}`);
232
+ console.log(`Tokens: ${result.tokens}`);
233
+ console.log(`Status: ${changeStatus}`);
234
+ if (previousScrapeAt)
235
+ console.log(`Previous check: ${previousScrapeAt}`);
236
+ console.log(`Last checked: ${new Date().toISOString()}`);
237
+ console.log('\nSnapshot saved. Run `webpeel diff <url> --last` to compare future changes.');
238
+ }
239
+ await cleanup();
240
+ process.exit(0);
241
+ }
242
+ catch (error) {
243
+ if (spinner)
244
+ spinner.fail('Tracking failed');
245
+ console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
246
+ await cleanup();
247
+ process.exit(1);
248
+ }
249
+ });
250
+ // ── summarize command ─────────────────────────────────────────────────────
251
+ program
252
+ .command('summarize <url>')
253
+ .description('Generate an AI-powered summary of a URL')
254
+ .option('--llm-key <key>', 'LLM API key (or use OPENAI_API_KEY env var)')
255
+ .option('--llm-model <model>', 'LLM model to use (default: gpt-4o-mini)')
256
+ .option('--llm-base-url <url>', 'LLM API base URL (default: https://api.openai.com/v1)')
257
+ .option('--prompt <prompt>', 'Custom summary prompt')
258
+ .option('-s, --silent', 'Silent mode (no spinner)')
259
+ .option('--json', 'Output as JSON')
260
+ .action(async (url, options) => {
261
+ const llmApiKey = options.llmKey || process.env.OPENAI_API_KEY;
262
+ if (!llmApiKey) {
263
+ console.error('Error: --llm-key or OPENAI_API_KEY environment variable is required');
264
+ process.exit(1);
265
+ }
266
+ const spinner = options.silent ? null : ora('Fetching and summarizing...').start();
267
+ try {
268
+ const result = await peel(url, {
269
+ extract: {
270
+ prompt: options.prompt || 'Summarize this webpage in 2-3 sentences.',
271
+ llmApiKey,
272
+ llmModel: options.llmModel || 'gpt-4o-mini',
273
+ llmBaseUrl: options.llmBaseUrl || 'https://api.openai.com/v1',
274
+ },
275
+ });
276
+ if (spinner) {
277
+ spinner.succeed(`Summarized in ${result.elapsed}ms`);
278
+ }
279
+ if (options.json) {
280
+ console.log(JSON.stringify({
281
+ url: result.url,
282
+ title: result.title,
283
+ summary: result.extracted,
284
+ }, null, 2));
285
+ }
286
+ else {
287
+ console.log(`\n${result.title}\n`);
288
+ console.log(result.extracted);
289
+ }
290
+ await cleanup();
291
+ process.exit(0);
292
+ }
293
+ catch (error) {
294
+ if (spinner)
295
+ spinner.fail('Summary generation failed');
296
+ console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
297
+ await cleanup();
298
+ process.exit(1);
299
+ }
300
+ });
301
+ // ── agent command ─────────────────────────────────────────────────────────
302
+ program
303
+ .command('agent <prompt>')
304
+ .description('Web research agent — LLM-free by default, add --llm-key for AI synthesis')
305
+ .option('--llm-key <key>', 'LLM API key (or use OPENAI_API_KEY env var)')
306
+ .option('--llm-model <model>', 'LLM model to use (default: gpt-4o-mini)')
307
+ .option('--llm-base-url <url>', 'LLM API base URL')
308
+ .option('--urls <urls>', 'Comma-separated starting URLs')
309
+ .option('--max-pages <n>', 'Maximum pages to visit (default: 10)', '10')
310
+ .option('--schema <json>', 'Schema template name (e.g. product, article) or JSON schema for structured output')
311
+ .option('-s, --silent', 'Silent mode (no spinner)')
312
+ .option('--json', 'Output as JSON')
313
+ .action(async (prompt, options) => {
314
+ const llmApiKey = options.llmKey || process.env.OPENAI_API_KEY;
315
+ const urls = options.urls ? options.urls.split(',').map((u) => u.trim()) : undefined;
316
+ // Parse schema (support templates)
317
+ let schema;
318
+ if (options.schema) {
319
+ const template = getSchemaTemplate(options.schema);
320
+ if (template) {
321
+ schema = template.fields;
322
+ }
323
+ else {
324
+ try {
325
+ schema = JSON.parse(options.schema);
326
+ }
327
+ catch {
328
+ console.error(`Error: --schema must be a template name (${listSchemaTemplates().join(', ')}) or valid JSON`);
329
+ process.exit(1);
330
+ }
331
+ }
332
+ }
333
+ if (llmApiKey) {
334
+ // Full LLM agent mode (existing code)
335
+ const spinner = options.silent ? null : ora('Running agent research...').start();
336
+ try {
337
+ const { runAgent } = await import('../../core/agent.js');
338
+ const result = await runAgent({
339
+ prompt,
340
+ urls,
341
+ schema,
342
+ llmApiKey,
343
+ llmModel: options.llmModel,
344
+ llmApiBase: options.llmBaseUrl,
345
+ maxPages: parseInt(options.maxPages, 10),
346
+ onProgress: (progress) => {
347
+ if (spinner)
348
+ spinner.text = progress.message;
349
+ },
350
+ });
351
+ if (spinner)
352
+ spinner.succeed(`Agent finished: ${result.pagesVisited} pages`);
353
+ if (options.json) {
354
+ console.log(JSON.stringify(result, null, 2));
355
+ }
356
+ else {
357
+ console.log(`\nSources (${result.sources.length}):`);
358
+ result.sources.forEach(s => console.log(` • ${s}`));
359
+ console.log(`\nResults:`);
360
+ console.log(JSON.stringify(result.data, null, 2));
361
+ }
362
+ await cleanup();
363
+ process.exit(0);
364
+ }
365
+ catch (e) {
366
+ if (spinner)
367
+ spinner.fail('Agent failed');
368
+ console.error(e instanceof Error ? e.message : e);
369
+ await cleanup();
370
+ process.exit(1);
371
+ }
372
+ }
373
+ else {
374
+ // LLM-free mode: search + fetch + BM25 extraction
375
+ const spinner = options.silent ? null : ora('Running LLM-free research...').start();
376
+ try {
377
+ // Import needed modules
378
+ const { quickAnswer } = await import('../../core/quick-answer.js');
379
+ // Step 1: Get URLs to process
380
+ let targetUrls = urls || [];
381
+ // If no URLs, search the web
382
+ if (targetUrls.length === 0) {
383
+ if (spinner)
384
+ spinner.text = 'Searching the web...';
385
+ try {
386
+ const { getBestSearchProvider } = await import('../../core/search-provider.js');
387
+ const { provider, apiKey: searchApiKey } = getBestSearchProvider();
388
+ const searchResults = await provider.searchWeb(prompt, {
389
+ count: Math.min(parseInt(options.maxPages, 10) || 5, 10),
390
+ apiKey: searchApiKey,
391
+ });
392
+ targetUrls = searchResults.map((r) => r.url);
393
+ }
394
+ catch {
395
+ // Fallback: try DuckDuckGo HTML
396
+ if (spinner)
397
+ spinner.text = 'Searching via DuckDuckGo...';
398
+ try {
399
+ const duckUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(prompt)}`;
400
+ const searchResult = await peel(duckUrl, { budget: 4000 });
401
+ // Extract URLs from search results content
402
+ const urlMatches = searchResult.content.match(/https?:\/\/[^\s\)]+/g) || [];
403
+ targetUrls = urlMatches
404
+ .filter((u) => !u.includes('duckduckgo.com'))
405
+ .slice(0, parseInt(options.maxPages, 10) || 5);
406
+ }
407
+ catch {
408
+ // No search results
409
+ }
410
+ }
411
+ }
412
+ if (targetUrls.length === 0) {
413
+ if (spinner)
414
+ spinner.fail('No URLs found. Provide --urls or a more specific prompt.');
415
+ process.exit(1);
416
+ }
417
+ if (spinner)
418
+ spinner.text = `Processing ${targetUrls.length} pages...`;
419
+ // Step 2: Fetch and extract from each URL
420
+ const results = [];
421
+ for (const url of targetUrls) {
422
+ try {
423
+ if (spinner)
424
+ spinner.text = `Fetching: ${url.substring(0, 60)}...`;
425
+ const pageResult = await peel(url, { budget: 4000 });
426
+ let extracted = null;
427
+ let confidence = 0;
428
+ if (schema) {
429
+ // Extract each schema field using smartExtractSchemaFields
430
+ const { smartExtractSchemaFields: smartExtractResearch } = await import('../../core/schema-postprocess.js');
431
+ extracted = smartExtractResearch(pageResult.content, schema, quickAnswer, {
432
+ pageTitle: pageResult.title,
433
+ pageUrl: url,
434
+ metadata: pageResult.metadata,
435
+ });
436
+ // Calculate confidence from quickAnswer for any field
437
+ for (const question of Object.values(schema)) {
438
+ try {
439
+ const qa = quickAnswer({ content: pageResult.content, question: typeof question === 'string' ? question : '' });
440
+ confidence = Math.max(confidence, qa.confidence || 0);
441
+ }
442
+ catch { /* ignore */ }
443
+ break; // just need one confidence estimate
444
+ }
445
+ }
446
+ else {
447
+ // Answer the prompt directly
448
+ try {
449
+ const qa = quickAnswer({ content: pageResult.content, question: prompt });
450
+ extracted = { answer: qa.answer || '' };
451
+ confidence = qa.confidence || 0;
452
+ }
453
+ catch {
454
+ extracted = null;
455
+ }
456
+ }
457
+ results.push({
458
+ url,
459
+ title: pageResult.metadata?.title || url,
460
+ extracted,
461
+ content: pageResult.content.substring(0, 500),
462
+ confidence,
463
+ });
464
+ }
465
+ catch (e) {
466
+ // Skip failed URLs
467
+ if (process.env.DEBUG) {
468
+ console.debug('[webpeel]', `Failed to fetch ${url}:`, e instanceof Error ? e.message : e);
469
+ }
470
+ }
471
+ }
472
+ if (spinner)
473
+ spinner.succeed(`Processed ${results.length}/${targetUrls.length} pages (LLM-free)`);
474
+ if (options.json) {
475
+ console.log(JSON.stringify({
476
+ mode: 'llm-free',
477
+ prompt,
478
+ schema: schema || null,
479
+ results,
480
+ sources: results.map(r => r.url),
481
+ pagesVisited: results.length,
482
+ }, null, 2));
483
+ }
484
+ else {
485
+ console.log(`\nšŸ“Š Results (${results.length} pages, LLM-free):\n`);
486
+ for (const r of results) {
487
+ console.log(`── ${r.title} ──`);
488
+ console.log(` ${r.url}`);
489
+ if (r.extracted) {
490
+ for (const [k, v] of Object.entries(r.extracted)) {
491
+ if (v)
492
+ console.log(` ${k}: ${v}`);
493
+ }
494
+ }
495
+ console.log(` Confidence: ${(r.confidence * 100).toFixed(0)}%\n`);
496
+ }
497
+ }
498
+ await cleanup();
499
+ process.exit(0);
500
+ }
501
+ catch (e) {
502
+ if (spinner)
503
+ spinner.fail('Research failed');
504
+ console.error(e instanceof Error ? e.message : e);
505
+ await cleanup();
506
+ process.exit(1);
507
+ }
508
+ }
509
+ });
510
+ // ── webask command ────────────────────────────────────────────────────────
511
+ program
512
+ .command('webask <question>')
513
+ .alias('ask-web')
514
+ .description('Search the web and get a direct answer (no LLM key required)')
515
+ .option('-n, --sources <n>', 'Number of sources to check (1-5, default 3)', '3')
516
+ .option('--json', 'Output as JSON')
517
+ .option('-s, --silent', 'Silent mode')
518
+ .action(async (question, options) => {
519
+ const isJson = !!options.json;
520
+ const isSilent = !!options.silent;
521
+ const numSources = Math.min(Math.max(parseInt(options.sources) || 3, 1), 5);
522
+ const askCfg = loadConfig();
523
+ const askApiKey = askCfg.apiKey || process.env.WEBPEEL_API_KEY;
524
+ const askApiUrl = process.env.WEBPEEL_API_URL || 'https://api.webpeel.dev';
525
+ if (!askApiKey) {
526
+ console.error('No API key configured. Run: webpeel auth <your-key>');
527
+ console.error('Get a free key at: https://app.webpeel.dev/keys');
528
+ process.exit(2);
529
+ }
530
+ let spinner = null;
531
+ if (!isSilent && !isJson) {
532
+ const { default: oraModule } = await import('ora');
533
+ spinner = oraModule(`Searching for: ${question}`).start();
534
+ }
535
+ try {
536
+ const params = new URLSearchParams({ q: question, sources: String(numSources) });
537
+ const res = await fetch(`${askApiUrl}/v1/ask?${params}`, {
538
+ headers: { Authorization: `Bearer ${askApiKey}` },
539
+ signal: AbortSignal.timeout(60000),
540
+ });
541
+ if (res.status === 401) {
542
+ if (spinner)
543
+ spinner.fail('API key invalid or expired. Run: webpeel auth <new-key>');
544
+ process.exit(2);
545
+ }
546
+ if (res.status === 404) {
547
+ if (spinner)
548
+ spinner.fail('Ask endpoint not available on this server version');
549
+ process.exit(1);
550
+ }
551
+ if (!res.ok) {
552
+ const body = await res.text().catch(() => '');
553
+ if (spinner)
554
+ spinner.fail(`API error ${res.status}: ${body.slice(0, 100)}`);
555
+ process.exit(1);
556
+ }
557
+ const data = await res.json();
558
+ if (spinner) {
559
+ if (data.answer) {
560
+ spinner.succeed(`Found answer (confidence: ${Math.round((data.confidence || 0) * 100)}%)`);
561
+ }
562
+ else {
563
+ spinner.warn('No confident answer found');
564
+ }
565
+ }
566
+ if (isJson) {
567
+ console.log(JSON.stringify(data, null, 2));
568
+ }
569
+ else {
570
+ if (data.answer) {
571
+ console.log('\n' + data.answer);
572
+ if (data.sources?.length && !isSilent) {
573
+ console.log('\nSources:');
574
+ data.sources.slice(0, 3).forEach((s) => console.log(` • ${s.title || s.url} — ${s.url}`));
575
+ }
576
+ }
577
+ else {
578
+ console.log('\nNo confident answer found for:', question);
579
+ }
580
+ if (data.elapsed && !isSilent)
581
+ console.log(`\n⚔ ${data.elapsed}ms`);
582
+ }
583
+ }
584
+ catch (err) {
585
+ if (spinner)
586
+ spinner.fail(err.message);
587
+ process.exit(1);
588
+ }
589
+ });
590
+ // ── answer command ────────────────────────────────────────────────────────
591
+ program
592
+ .command('answer <question>')
593
+ .description('Ask a question, search the web, and get an AI-generated answer with citations (BYOK)')
594
+ .option('--provider <provider>', 'Search provider: duckduckgo (default) or brave')
595
+ .option('--search-api-key <key>', 'Search provider API key (or env WEBPEEL_BRAVE_API_KEY)')
596
+ .option('--llm <provider>', 'LLM provider: openai, anthropic, or google (required)')
597
+ .option('--llm-api-key <key>', 'LLM API key (or env OPENAI_API_KEY / ANTHROPIC_API_KEY / GOOGLE_API_KEY)')
598
+ .option('--llm-model <model>', 'LLM model name (optional, uses provider default)')
599
+ .option('--max-sources <n>', 'Maximum sources to fetch (1-10, default 5)', '5')
600
+ .option('--json', 'Output as JSON')
601
+ .option('-s, --silent', 'Silent mode')
602
+ .action(async (question, options) => {
603
+ const spinner = options.silent ? null : ora('Thinking...').start();
604
+ try {
605
+ const { answerQuestion } = await import('../../core/answer.js');
606
+ const config = loadConfig();
607
+ const llmProvider = options.llm;
608
+ if (!llmProvider || !['openai', 'anthropic', 'google'].includes(llmProvider)) {
609
+ console.error('Error: --llm is required (openai, anthropic, or google)');
610
+ process.exit(1);
611
+ }
612
+ const llmApiKey = options.llmApiKey
613
+ || process.env.OPENAI_API_KEY
614
+ || process.env.ANTHROPIC_API_KEY
615
+ || process.env.GOOGLE_API_KEY
616
+ || '';
617
+ if (!llmApiKey) {
618
+ console.error('Error: --llm-api-key is required (or set OPENAI_API_KEY / ANTHROPIC_API_KEY / GOOGLE_API_KEY)');
619
+ process.exit(1);
620
+ }
621
+ const searchProvider = (options.provider || 'duckduckgo');
622
+ const searchApiKey = options.searchApiKey
623
+ || process.env.WEBPEEL_BRAVE_API_KEY
624
+ || config.braveApiKey
625
+ || undefined;
626
+ const maxSources = Math.min(Math.max(parseInt(options.maxSources) || 5, 1), 10);
627
+ if (spinner)
628
+ spinner.text = 'Searching the web...';
629
+ const result = await answerQuestion({
630
+ question,
631
+ searchProvider,
632
+ searchApiKey,
633
+ llmProvider,
634
+ llmApiKey,
635
+ llmModel: options.llmModel,
636
+ maxSources,
637
+ stream: false,
638
+ });
639
+ if (spinner)
640
+ spinner.succeed('Done');
641
+ if (options.json) {
642
+ const jsonStr = JSON.stringify(result, null, 2);
643
+ await new Promise((resolve, reject) => {
644
+ process.stdout.write(jsonStr + '\n', (err) => {
645
+ if (err)
646
+ reject(err);
647
+ else
648
+ resolve();
649
+ });
650
+ });
651
+ }
652
+ else {
653
+ console.log(`\n${result.answer}`);
654
+ console.log(`\nSources:`);
655
+ result.citations.forEach((c, i) => {
656
+ console.log(` [${i + 1}] ${c.title}`);
657
+ console.log(` ${c.url}`);
658
+ });
659
+ console.log(`\nModel: ${result.llmModel} (${result.llmProvider})`);
660
+ }
661
+ await cleanup();
662
+ process.exit(0);
663
+ }
664
+ catch (error) {
665
+ if (spinner)
666
+ spinner.fail('Answer generation failed');
667
+ console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
668
+ await cleanup();
669
+ process.exit(1);
670
+ }
671
+ });
672
+ // ── research command ──────────────────────────────────────────────────────
673
+ program
674
+ .command('research <query>')
675
+ .description('Conduct autonomous multi-step web research on a topic and synthesize a report')
676
+ .option('--max-sources <n>', 'Maximum sources to consult (default: 5)', '5')
677
+ .option('--max-depth <n>', 'Link-following depth (default: 1)', '1')
678
+ .option('--format <f>', 'Output format: report (default) or sources', 'report')
679
+ .option('--llm-key <key>', 'LLM API key for synthesis (or env OPENAI_API_KEY)')
680
+ .option('--llm-model <model>', 'LLM model for synthesis (default: gpt-4o-mini)')
681
+ .option('--llm-base-url <url>', 'LLM API base URL (default: https://api.openai.com/v1)')
682
+ .option('--timeout <ms>', 'Max research time in ms (default: 40000)', '60000')
683
+ .option('--json', 'Output result as JSON')
684
+ .option('-s, --silent', 'Suppress progress output')
685
+ .action(async (query, options) => {
686
+ const isSilent = !!options.silent;
687
+ const isJson = !!options.json;
688
+ const maxSources = parseInt(options.maxSources) || 5;
689
+ const maxDepth = parseInt(options.maxDepth) || 1;
690
+ const timeout = parseInt(options.timeout) || 60000;
691
+ const outputFormat = options.format === 'sources' ? 'sources' : 'report';
692
+ const apiKey = options.llmKey || process.env.OPENAI_API_KEY;
693
+ const model = options.llmModel;
694
+ const baseUrl = options.llmBaseUrl;
695
+ const phaseIcons = {
696
+ searching: 'šŸ”',
697
+ fetching: 'šŸ“„',
698
+ extracting: '🧠',
699
+ following: 'šŸ”—',
700
+ synthesizing: 'āœļø',
701
+ };
702
+ try {
703
+ const { research } = await import('../../core/research.js');
704
+ const result = await research({
705
+ query,
706
+ maxSources,
707
+ maxDepth,
708
+ timeout,
709
+ outputFormat: outputFormat,
710
+ apiKey,
711
+ model,
712
+ baseUrl,
713
+ onProgress: (step) => {
714
+ if (!isSilent && !isJson) {
715
+ const icon = phaseIcons[step.phase] ?? 'āš™ļø';
716
+ const extra = step.sourcesFound !== undefined
717
+ ? ` (found ${step.sourcesFound})`
718
+ : step.sourcesFetched !== undefined
719
+ ? ` (${step.sourcesFetched} fetched)`
720
+ : '';
721
+ process.stderr.write(`${icon} ${step.message}${extra}...\n`);
722
+ }
723
+ },
724
+ });
725
+ if (isJson) {
726
+ await writeStdout(JSON.stringify(result, null, 2) + '\n');
727
+ }
728
+ else {
729
+ await writeStdout(result.report + '\n');
730
+ if (!isSilent) {
731
+ const elapsed = (result.elapsed / 1000).toFixed(1);
732
+ const cost = result.cost !== undefined ? ` | cost: $${result.cost.toFixed(4)}` : '';
733
+ process.stderr.write(`\nšŸ“Š ${result.sourcesConsulted} sources consulted (${result.totalSourcesFound} found) | ${elapsed}s${cost}\n`);
734
+ }
735
+ }
736
+ await cleanup();
737
+ process.exit(0);
738
+ }
739
+ catch (error) {
740
+ const msg = error instanceof Error ? error.message : 'Unknown error';
741
+ if (isJson) {
742
+ await writeStdout(JSON.stringify({ success: false, error: { type: 'fetch_failed', message: msg } }) + '\n');
743
+ }
744
+ else {
745
+ console.error(`\nError: ${msg}`);
746
+ }
747
+ await cleanup();
748
+ process.exit(1);
749
+ }
750
+ });
751
+ // ── do command — natural language intent routing ──────────────────────────
752
+ program
753
+ .command('do <task...>')
754
+ .description('Do anything — describe what you want in plain English')
755
+ .option('-s, --silent', 'Silent mode')
756
+ .option('--json', 'JSON output')
757
+ .action(async (taskParts, options) => {
758
+ const task = taskParts.join(' ');
759
+ const cfg = loadConfig();
760
+ const apiKey = cfg.apiKey || process.env.WEBPEEL_API_KEY;
761
+ const apiUrl = process.env.WEBPEEL_API_URL || 'https://api.webpeel.dev';
762
+ if (!apiKey) {
763
+ console.error('No API key. Run: webpeel auth <key>');
764
+ process.exit(1);
765
+ }
766
+ let spinner = null;
767
+ if (!options.silent && !options.json) {
768
+ const { default: oraModule } = await import('ora');
769
+ spinner = oraModule(`Doing: ${task}`).start();
770
+ }
771
+ try {
772
+ const res = await fetch(`${apiUrl}/v1/do`, {
773
+ method: 'POST',
774
+ headers: {
775
+ Authorization: `Bearer ${apiKey}`,
776
+ 'Content-Type': 'application/json',
777
+ },
778
+ body: JSON.stringify({ task }),
779
+ signal: AbortSignal.timeout(60000),
780
+ });
781
+ const data = await res.json();
782
+ if (spinner) {
783
+ if (data.error) {
784
+ spinner.fail(`Failed: ${data.message || data.error}`);
785
+ }
786
+ else {
787
+ spinner.succeed(`Done (${data.elapsed}ms) — intent: ${data.intent}`);
788
+ }
789
+ }
790
+ if (options.json) {
791
+ console.log(JSON.stringify(data, null, 2));
792
+ }
793
+ else {
794
+ if (data.error) {
795
+ console.error(`Error: ${data.message || data.error}`);
796
+ process.exit(1);
797
+ }
798
+ console.log(`Intent: ${data.intent}`);
799
+ if (data.url)
800
+ console.log(`URL: ${data.url}`);
801
+ if (data.query)
802
+ console.log(`Query: ${data.query}`);
803
+ console.log(`Elapsed: ${data.elapsed}ms`);
804
+ console.log('');
805
+ // Pretty-print the result
806
+ const result = data.result || {};
807
+ if (result.content)
808
+ console.log(result.content.slice(0, 2000));
809
+ else if (result.answer)
810
+ console.log(`Answer: ${result.answer}\nConfidence: ${Math.round((result.confidence || 0) * 100)}%`);
811
+ else if (result.screenshot)
812
+ console.log(`Screenshot: ${result.screenshot.length} bytes (base64)`);
813
+ else
814
+ console.log(JSON.stringify(result, null, 2).slice(0, 2000));
815
+ }
816
+ }
817
+ catch (err) {
818
+ if (spinner)
819
+ spinner.fail(err.message);
820
+ if (!options.silent)
821
+ console.error(`Error: ${err.message}`);
822
+ process.exit(1);
823
+ }
824
+ });
825
+ // ── schemas command ───────────────────────────────────────────────────────
826
+ program
827
+ .command('schemas')
828
+ .description('List available extraction schema templates')
829
+ .action(() => {
830
+ console.log('\nAvailable schema templates:\n');
831
+ for (const [key, template] of Object.entries(SCHEMA_TEMPLATES)) {
832
+ console.log(` ${key.padEnd(12)} ${template.description}`);
833
+ console.log(` ${''.padEnd(12)} Fields: ${Object.keys(template.fields).join(', ')}`);
834
+ console.log('');
835
+ }
836
+ console.log('Usage: webpeel "https://example.com" --schema product');
837
+ console.log(' webpeel "https://example.com" --schema \'{"field":"description"}\'');
838
+ });
839
+ }