@iflow-mcp/jakeliume-webpeel 0.22.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 (547) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +313 -0
  3. package/dist/cache.d.ts +30 -0
  4. package/dist/cache.js +139 -0
  5. package/dist/cli/commands/auth.d.ts +5 -0
  6. package/dist/cli/commands/auth.js +411 -0
  7. package/dist/cli/commands/doctor.d.ts +37 -0
  8. package/dist/cli/commands/doctor.js +371 -0
  9. package/dist/cli/commands/fetch.d.ts +6 -0
  10. package/dist/cli/commands/fetch.js +1345 -0
  11. package/dist/cli/commands/guide.d.ts +2 -0
  12. package/dist/cli/commands/guide.js +183 -0
  13. package/dist/cli/commands/interact.d.ts +5 -0
  14. package/dist/cli/commands/interact.js +840 -0
  15. package/dist/cli/commands/jobs.d.ts +5 -0
  16. package/dist/cli/commands/jobs.js +997 -0
  17. package/dist/cli/commands/monitor.d.ts +12 -0
  18. package/dist/cli/commands/monitor.js +197 -0
  19. package/dist/cli/commands/observe.d.ts +12 -0
  20. package/dist/cli/commands/observe.js +158 -0
  21. package/dist/cli/commands/screenshot.d.ts +5 -0
  22. package/dist/cli/commands/screenshot.js +282 -0
  23. package/dist/cli/commands/search.d.ts +5 -0
  24. package/dist/cli/commands/search.js +1021 -0
  25. package/dist/cli/commands/setup.d.ts +13 -0
  26. package/dist/cli/commands/setup.js +244 -0
  27. package/dist/cli/commands/skill.d.ts +15 -0
  28. package/dist/cli/commands/skill.js +195 -0
  29. package/dist/cli/utils.d.ts +84 -0
  30. package/dist/cli/utils.js +806 -0
  31. package/dist/cli-auth.d.ts +75 -0
  32. package/dist/cli-auth.js +369 -0
  33. package/dist/cli.d.ts +17 -0
  34. package/dist/cli.js +99 -0
  35. package/dist/core/actions.d.ts +69 -0
  36. package/dist/core/actions.js +495 -0
  37. package/dist/core/agent.d.ts +98 -0
  38. package/dist/core/agent.js +558 -0
  39. package/dist/core/answer.d.ts +42 -0
  40. package/dist/core/answer.js +395 -0
  41. package/dist/core/application-tracker.d.ts +84 -0
  42. package/dist/core/application-tracker.js +184 -0
  43. package/dist/core/apply.d.ts +162 -0
  44. package/dist/core/apply.js +816 -0
  45. package/dist/core/auth-detection.d.ts +35 -0
  46. package/dist/core/auth-detection.js +358 -0
  47. package/dist/core/auto-extract.d.ts +82 -0
  48. package/dist/core/auto-extract.js +604 -0
  49. package/dist/core/auto-interact.d.ts +23 -0
  50. package/dist/core/auto-interact.js +246 -0
  51. package/dist/core/bm25-filter.d.ts +66 -0
  52. package/dist/core/bm25-filter.js +288 -0
  53. package/dist/core/branding.d.ts +54 -0
  54. package/dist/core/branding.js +234 -0
  55. package/dist/core/browser-fetch.d.ts +323 -0
  56. package/dist/core/browser-fetch.js +1600 -0
  57. package/dist/core/browser-pool.d.ts +91 -0
  58. package/dist/core/browser-pool.js +550 -0
  59. package/dist/core/budget.d.ts +42 -0
  60. package/dist/core/budget.js +324 -0
  61. package/dist/core/business-intel.d.ts +47 -0
  62. package/dist/core/business-intel.js +279 -0
  63. package/dist/core/cache.d.ts +13 -0
  64. package/dist/core/cache.js +121 -0
  65. package/dist/core/cf-worker-proxy.d.ts +32 -0
  66. package/dist/core/cf-worker-proxy.js +87 -0
  67. package/dist/core/challenge-detection.d.ts +26 -0
  68. package/dist/core/challenge-detection.js +468 -0
  69. package/dist/core/change-tracking.d.ts +75 -0
  70. package/dist/core/change-tracking.js +276 -0
  71. package/dist/core/chunker.d.ts +46 -0
  72. package/dist/core/chunker.js +249 -0
  73. package/dist/core/chunking.d.ts +42 -0
  74. package/dist/core/chunking.js +181 -0
  75. package/dist/core/circuit-breaker.d.ts +44 -0
  76. package/dist/core/circuit-breaker.js +85 -0
  77. package/dist/core/content-pruner.d.ts +47 -0
  78. package/dist/core/content-pruner.js +425 -0
  79. package/dist/core/cookie-cache.d.ts +60 -0
  80. package/dist/core/cookie-cache.js +163 -0
  81. package/dist/core/crawl-checkpoint.d.ts +54 -0
  82. package/dist/core/crawl-checkpoint.js +104 -0
  83. package/dist/core/crawler.d.ts +84 -0
  84. package/dist/core/crawler.js +349 -0
  85. package/dist/core/cross-verify.d.ts +27 -0
  86. package/dist/core/cross-verify.js +93 -0
  87. package/dist/core/deep-fetch.d.ts +74 -0
  88. package/dist/core/deep-fetch.js +405 -0
  89. package/dist/core/deep-research.d.ts +141 -0
  90. package/dist/core/deep-research.js +972 -0
  91. package/dist/core/design-analysis.d.ts +70 -0
  92. package/dist/core/design-analysis.js +490 -0
  93. package/dist/core/design-compare.d.ts +38 -0
  94. package/dist/core/design-compare.js +264 -0
  95. package/dist/core/diff.d.ts +61 -0
  96. package/dist/core/diff.js +289 -0
  97. package/dist/core/dns-cache.d.ts +20 -0
  98. package/dist/core/dns-cache.js +198 -0
  99. package/dist/core/documents.d.ts +23 -0
  100. package/dist/core/documents.js +123 -0
  101. package/dist/core/domain-memory.d.ts +66 -0
  102. package/dist/core/domain-memory.js +163 -0
  103. package/dist/core/domain-verify.d.ts +40 -0
  104. package/dist/core/domain-verify.js +379 -0
  105. package/dist/core/engine-ranker.d.ts +112 -0
  106. package/dist/core/engine-ranker.js +395 -0
  107. package/dist/core/extract-inline.d.ts +38 -0
  108. package/dist/core/extract-inline.js +215 -0
  109. package/dist/core/extract-listings.d.ts +38 -0
  110. package/dist/core/extract-listings.js +461 -0
  111. package/dist/core/extract.d.ts +9 -0
  112. package/dist/core/extract.js +139 -0
  113. package/dist/core/fetch-cache.d.ts +57 -0
  114. package/dist/core/fetch-cache.js +95 -0
  115. package/dist/core/fetcher.d.ts +13 -0
  116. package/dist/core/fetcher.js +12 -0
  117. package/dist/core/google-cache.d.ts +29 -0
  118. package/dist/core/google-cache.js +180 -0
  119. package/dist/core/google-serp-parser.d.ts +82 -0
  120. package/dist/core/google-serp-parser.js +287 -0
  121. package/dist/core/hotel-search.d.ts +122 -0
  122. package/dist/core/hotel-search.js +382 -0
  123. package/dist/core/http-fetch.d.ts +72 -0
  124. package/dist/core/http-fetch.js +820 -0
  125. package/dist/core/human.d.ts +175 -0
  126. package/dist/core/human.js +680 -0
  127. package/dist/core/image-caption.d.ts +44 -0
  128. package/dist/core/image-caption.js +271 -0
  129. package/dist/core/jobs.d.ts +75 -0
  130. package/dist/core/jobs.js +634 -0
  131. package/dist/core/json-ld.d.ts +15 -0
  132. package/dist/core/json-ld.js +617 -0
  133. package/dist/core/language-detect.d.ts +18 -0
  134. package/dist/core/language-detect.js +135 -0
  135. package/dist/core/links.d.ts +10 -0
  136. package/dist/core/links.js +44 -0
  137. package/dist/core/llm-extract.d.ts +71 -0
  138. package/dist/core/llm-extract.js +507 -0
  139. package/dist/core/llm-provider.d.ts +100 -0
  140. package/dist/core/llm-provider.js +702 -0
  141. package/dist/core/local-search.d.ts +60 -0
  142. package/dist/core/local-search.js +308 -0
  143. package/dist/core/logger.d.ts +28 -0
  144. package/dist/core/logger.js +104 -0
  145. package/dist/core/map.d.ts +33 -0
  146. package/dist/core/map.js +127 -0
  147. package/dist/core/markdown.d.ts +92 -0
  148. package/dist/core/markdown.js +809 -0
  149. package/dist/core/metadata.d.ts +34 -0
  150. package/dist/core/metadata.js +422 -0
  151. package/dist/core/observe.d.ts +113 -0
  152. package/dist/core/observe.js +395 -0
  153. package/dist/core/ocr.d.ts +12 -0
  154. package/dist/core/ocr.js +33 -0
  155. package/dist/core/paginate.d.ts +31 -0
  156. package/dist/core/paginate.js +106 -0
  157. package/dist/core/pdf.d.ts +8 -0
  158. package/dist/core/pdf.js +25 -0
  159. package/dist/core/peel-tls.d.ts +25 -0
  160. package/dist/core/peel-tls.js +220 -0
  161. package/dist/core/pipeline.d.ts +132 -0
  162. package/dist/core/pipeline.js +1666 -0
  163. package/dist/core/profiles.d.ts +61 -0
  164. package/dist/core/profiles.js +350 -0
  165. package/dist/core/prompt-guard.d.ts +30 -0
  166. package/dist/core/prompt-guard.js +119 -0
  167. package/dist/core/proxy-config.d.ts +90 -0
  168. package/dist/core/proxy-config.js +172 -0
  169. package/dist/core/quick-answer.d.ts +53 -0
  170. package/dist/core/quick-answer.js +833 -0
  171. package/dist/core/rate-governor.d.ts +80 -0
  172. package/dist/core/rate-governor.js +238 -0
  173. package/dist/core/readability.d.ts +57 -0
  174. package/dist/core/readability.js +533 -0
  175. package/dist/core/research.d.ts +66 -0
  176. package/dist/core/research.js +270 -0
  177. package/dist/core/retry.d.ts +60 -0
  178. package/dist/core/retry.js +119 -0
  179. package/dist/core/safe-browsing.d.ts +30 -0
  180. package/dist/core/safe-browsing.js +206 -0
  181. package/dist/core/schema-extraction.d.ts +66 -0
  182. package/dist/core/schema-extraction.js +352 -0
  183. package/dist/core/schema-postprocess.d.ts +32 -0
  184. package/dist/core/schema-postprocess.js +469 -0
  185. package/dist/core/schema-templates.d.ts +19 -0
  186. package/dist/core/schema-templates.js +143 -0
  187. package/dist/core/screenshot.d.ts +224 -0
  188. package/dist/core/screenshot.js +207 -0
  189. package/dist/core/search-engines.d.ts +25 -0
  190. package/dist/core/search-engines.js +182 -0
  191. package/dist/core/search-provider.d.ts +243 -0
  192. package/dist/core/search-provider.js +1629 -0
  193. package/dist/core/searxng-provider.d.ts +35 -0
  194. package/dist/core/searxng-provider.js +105 -0
  195. package/dist/core/selective-evidence.d.ts +151 -0
  196. package/dist/core/selective-evidence.js +389 -0
  197. package/dist/core/site-search.d.ts +44 -0
  198. package/dist/core/site-search.js +252 -0
  199. package/dist/core/sitemap.d.ts +23 -0
  200. package/dist/core/sitemap.js +105 -0
  201. package/dist/core/source-credibility.d.ts +29 -0
  202. package/dist/core/source-credibility.js +584 -0
  203. package/dist/core/source-scoring.d.ts +166 -0
  204. package/dist/core/source-scoring.js +396 -0
  205. package/dist/core/stemmer.d.ts +38 -0
  206. package/dist/core/stemmer.js +509 -0
  207. package/dist/core/strategies.d.ts +104 -0
  208. package/dist/core/strategies.js +1044 -0
  209. package/dist/core/strategy-hooks.d.ts +145 -0
  210. package/dist/core/strategy-hooks.js +74 -0
  211. package/dist/core/structured-extract.d.ts +43 -0
  212. package/dist/core/structured-extract.js +550 -0
  213. package/dist/core/summarize.d.ts +17 -0
  214. package/dist/core/summarize.js +78 -0
  215. package/dist/core/synonyms.d.ts +42 -0
  216. package/dist/core/synonyms.js +184 -0
  217. package/dist/core/system-monitor.d.ts +61 -0
  218. package/dist/core/system-monitor.js +133 -0
  219. package/dist/core/table-format.d.ts +30 -0
  220. package/dist/core/table-format.js +146 -0
  221. package/dist/core/threat-feeds.d.ts +23 -0
  222. package/dist/core/threat-feeds.js +104 -0
  223. package/dist/core/timing.d.ts +21 -0
  224. package/dist/core/timing.js +33 -0
  225. package/dist/core/transcript-export.d.ts +47 -0
  226. package/dist/core/transcript-export.js +107 -0
  227. package/dist/core/user-agents.d.ts +82 -0
  228. package/dist/core/user-agents.js +239 -0
  229. package/dist/core/vertical-search.d.ts +54 -0
  230. package/dist/core/vertical-search.js +158 -0
  231. package/dist/core/watch-manager.d.ts +175 -0
  232. package/dist/core/watch-manager.js +416 -0
  233. package/dist/core/watch.d.ts +101 -0
  234. package/dist/core/watch.js +389 -0
  235. package/dist/core/youtube.d.ts +130 -0
  236. package/dist/core/youtube.js +1175 -0
  237. package/dist/ee/challenge-re-export.d.ts +1 -0
  238. package/dist/ee/challenge-re-export.js +1 -0
  239. package/dist/ee/challenge-solver.d.ts +72 -0
  240. package/dist/ee/challenge-solver.js +720 -0
  241. package/dist/ee/domain-extractors.d.ts +8 -0
  242. package/dist/ee/domain-extractors.js +8 -0
  243. package/dist/ee/domain-intel.d.ts +16 -0
  244. package/dist/ee/domain-intel.js +133 -0
  245. package/dist/ee/extractors/allrecipes.d.ts +2 -0
  246. package/dist/ee/extractors/allrecipes.js +120 -0
  247. package/dist/ee/extractors/amazon.d.ts +2 -0
  248. package/dist/ee/extractors/amazon.js +78 -0
  249. package/dist/ee/extractors/arxiv.d.ts +2 -0
  250. package/dist/ee/extractors/arxiv.js +137 -0
  251. package/dist/ee/extractors/bestbuy.d.ts +2 -0
  252. package/dist/ee/extractors/bestbuy.js +78 -0
  253. package/dist/ee/extractors/carscom.d.ts +2 -0
  254. package/dist/ee/extractors/carscom.js +121 -0
  255. package/dist/ee/extractors/coingecko.d.ts +2 -0
  256. package/dist/ee/extractors/coingecko.js +134 -0
  257. package/dist/ee/extractors/craigslist.d.ts +2 -0
  258. package/dist/ee/extractors/craigslist.js +92 -0
  259. package/dist/ee/extractors/devto.d.ts +2 -0
  260. package/dist/ee/extractors/devto.js +135 -0
  261. package/dist/ee/extractors/ebay.d.ts +2 -0
  262. package/dist/ee/extractors/ebay.js +90 -0
  263. package/dist/ee/extractors/espn.d.ts +2 -0
  264. package/dist/ee/extractors/espn.js +260 -0
  265. package/dist/ee/extractors/etsy.d.ts +2 -0
  266. package/dist/ee/extractors/etsy.js +52 -0
  267. package/dist/ee/extractors/facebook.d.ts +2 -0
  268. package/dist/ee/extractors/facebook.js +46 -0
  269. package/dist/ee/extractors/github.d.ts +2 -0
  270. package/dist/ee/extractors/github.js +196 -0
  271. package/dist/ee/extractors/google-flights.d.ts +2 -0
  272. package/dist/ee/extractors/google-flights.js +176 -0
  273. package/dist/ee/extractors/hackernews.d.ts +2 -0
  274. package/dist/ee/extractors/hackernews.js +147 -0
  275. package/dist/ee/extractors/imdb.d.ts +2 -0
  276. package/dist/ee/extractors/imdb.js +172 -0
  277. package/dist/ee/extractors/index.d.ts +26 -0
  278. package/dist/ee/extractors/index.js +247 -0
  279. package/dist/ee/extractors/instagram.d.ts +2 -0
  280. package/dist/ee/extractors/instagram.js +102 -0
  281. package/dist/ee/extractors/kalshi.d.ts +2 -0
  282. package/dist/ee/extractors/kalshi.js +121 -0
  283. package/dist/ee/extractors/kayak-cars.d.ts +2 -0
  284. package/dist/ee/extractors/kayak-cars.js +270 -0
  285. package/dist/ee/extractors/linkedin.d.ts +2 -0
  286. package/dist/ee/extractors/linkedin.js +113 -0
  287. package/dist/ee/extractors/medium.d.ts +2 -0
  288. package/dist/ee/extractors/medium.js +130 -0
  289. package/dist/ee/extractors/news.d.ts +4 -0
  290. package/dist/ee/extractors/news.js +173 -0
  291. package/dist/ee/extractors/npm.d.ts +2 -0
  292. package/dist/ee/extractors/npm.js +86 -0
  293. package/dist/ee/extractors/pdf.d.ts +2 -0
  294. package/dist/ee/extractors/pdf.js +108 -0
  295. package/dist/ee/extractors/pinterest.d.ts +2 -0
  296. package/dist/ee/extractors/pinterest.js +34 -0
  297. package/dist/ee/extractors/polymarket.d.ts +2 -0
  298. package/dist/ee/extractors/polymarket.js +358 -0
  299. package/dist/ee/extractors/producthunt.d.ts +2 -0
  300. package/dist/ee/extractors/producthunt.js +88 -0
  301. package/dist/ee/extractors/pubmed.d.ts +2 -0
  302. package/dist/ee/extractors/pubmed.js +162 -0
  303. package/dist/ee/extractors/pypi.d.ts +2 -0
  304. package/dist/ee/extractors/pypi.js +80 -0
  305. package/dist/ee/extractors/reddit.d.ts +2 -0
  306. package/dist/ee/extractors/reddit.js +438 -0
  307. package/dist/ee/extractors/redfin.d.ts +2 -0
  308. package/dist/ee/extractors/redfin.js +156 -0
  309. package/dist/ee/extractors/semanticscholar.d.ts +2 -0
  310. package/dist/ee/extractors/semanticscholar.js +131 -0
  311. package/dist/ee/extractors/shared.d.ts +12 -0
  312. package/dist/ee/extractors/shared.js +76 -0
  313. package/dist/ee/extractors/soundcloud.d.ts +2 -0
  314. package/dist/ee/extractors/soundcloud.js +34 -0
  315. package/dist/ee/extractors/sportsbetting.d.ts +2 -0
  316. package/dist/ee/extractors/sportsbetting.js +37 -0
  317. package/dist/ee/extractors/spotify.d.ts +2 -0
  318. package/dist/ee/extractors/spotify.js +34 -0
  319. package/dist/ee/extractors/stackoverflow.d.ts +2 -0
  320. package/dist/ee/extractors/stackoverflow.js +61 -0
  321. package/dist/ee/extractors/substack.d.ts +2 -0
  322. package/dist/ee/extractors/substack.js +115 -0
  323. package/dist/ee/extractors/substackroot.d.ts +2 -0
  324. package/dist/ee/extractors/substackroot.js +46 -0
  325. package/dist/ee/extractors/tiktok.d.ts +2 -0
  326. package/dist/ee/extractors/tiktok.js +29 -0
  327. package/dist/ee/extractors/tradingview.d.ts +2 -0
  328. package/dist/ee/extractors/tradingview.js +182 -0
  329. package/dist/ee/extractors/twitch.d.ts +2 -0
  330. package/dist/ee/extractors/twitch.js +36 -0
  331. package/dist/ee/extractors/twitter.d.ts +2 -0
  332. package/dist/ee/extractors/twitter.js +327 -0
  333. package/dist/ee/extractors/types.d.ts +14 -0
  334. package/dist/ee/extractors/types.js +1 -0
  335. package/dist/ee/extractors/walmart.d.ts +2 -0
  336. package/dist/ee/extractors/walmart.js +50 -0
  337. package/dist/ee/extractors/weather.d.ts +2 -0
  338. package/dist/ee/extractors/weather.js +133 -0
  339. package/dist/ee/extractors/wikipedia.d.ts +4 -0
  340. package/dist/ee/extractors/wikipedia.js +235 -0
  341. package/dist/ee/extractors/yelp.d.ts +2 -0
  342. package/dist/ee/extractors/yelp.js +216 -0
  343. package/dist/ee/extractors/youtube.d.ts +2 -0
  344. package/dist/ee/extractors/youtube.js +189 -0
  345. package/dist/ee/extractors/zillow.d.ts +54 -0
  346. package/dist/ee/extractors/zillow.js +247 -0
  347. package/dist/ee/extractors-re-export.d.ts +1 -0
  348. package/dist/ee/extractors-re-export.js +1 -0
  349. package/dist/ee/premium-hooks.d.ts +20 -0
  350. package/dist/ee/premium-hooks.js +50 -0
  351. package/dist/ee/spa-detection.d.ts +2 -0
  352. package/dist/ee/spa-detection.js +2 -0
  353. package/dist/ee/stability.d.ts +4 -0
  354. package/dist/ee/stability.js +29 -0
  355. package/dist/ee/swr-cache.d.ts +14 -0
  356. package/dist/ee/swr-cache.js +34 -0
  357. package/dist/index.d.ts +143 -0
  358. package/dist/index.js +291 -0
  359. package/dist/integrations/index.d.ts +2 -0
  360. package/dist/integrations/index.js +2 -0
  361. package/dist/integrations/langchain.d.ts +64 -0
  362. package/dist/integrations/langchain.js +115 -0
  363. package/dist/integrations/llamaindex.d.ts +50 -0
  364. package/dist/integrations/llamaindex.js +91 -0
  365. package/dist/mcp/handlers/act.d.ts +5 -0
  366. package/dist/mcp/handlers/act.js +34 -0
  367. package/dist/mcp/handlers/definitions.d.ts +6 -0
  368. package/dist/mcp/handlers/definitions.js +395 -0
  369. package/dist/mcp/handlers/extract.d.ts +7 -0
  370. package/dist/mcp/handlers/extract.js +135 -0
  371. package/dist/mcp/handlers/fetch.d.ts +6 -0
  372. package/dist/mcp/handlers/fetch.js +98 -0
  373. package/dist/mcp/handlers/find.d.ts +5 -0
  374. package/dist/mcp/handlers/find.js +137 -0
  375. package/dist/mcp/handlers/index.d.ts +13 -0
  376. package/dist/mcp/handlers/index.js +63 -0
  377. package/dist/mcp/handlers/legacy.d.ts +25 -0
  378. package/dist/mcp/handlers/legacy.js +450 -0
  379. package/dist/mcp/handlers/meta.d.ts +6 -0
  380. package/dist/mcp/handlers/meta.js +40 -0
  381. package/dist/mcp/handlers/monitor.d.ts +5 -0
  382. package/dist/mcp/handlers/monitor.js +41 -0
  383. package/dist/mcp/handlers/observe.d.ts +8 -0
  384. package/dist/mcp/handlers/observe.js +37 -0
  385. package/dist/mcp/handlers/read.d.ts +6 -0
  386. package/dist/mcp/handlers/read.js +78 -0
  387. package/dist/mcp/handlers/see.d.ts +5 -0
  388. package/dist/mcp/handlers/see.js +75 -0
  389. package/dist/mcp/handlers/types.d.ts +29 -0
  390. package/dist/mcp/handlers/types.js +28 -0
  391. package/dist/mcp/server.d.ts +7 -0
  392. package/dist/mcp/server.js +108 -0
  393. package/dist/mcp/smart-router.d.ts +23 -0
  394. package/dist/mcp/smart-router.js +178 -0
  395. package/dist/server/app.d.ts +14 -0
  396. package/dist/server/app.js +632 -0
  397. package/dist/server/auth-store.d.ts +28 -0
  398. package/dist/server/auth-store.js +88 -0
  399. package/dist/server/bull-queues.d.ts +60 -0
  400. package/dist/server/bull-queues.js +90 -0
  401. package/dist/server/email-service.d.ts +55 -0
  402. package/dist/server/email-service.js +291 -0
  403. package/dist/server/job-queue.d.ts +100 -0
  404. package/dist/server/job-queue.js +145 -0
  405. package/dist/server/logger.d.ts +10 -0
  406. package/dist/server/logger.js +37 -0
  407. package/dist/server/middleware/audit-log.d.ts +14 -0
  408. package/dist/server/middleware/audit-log.js +73 -0
  409. package/dist/server/middleware/auth.d.ts +35 -0
  410. package/dist/server/middleware/auth.js +225 -0
  411. package/dist/server/middleware/rate-limit.d.ts +50 -0
  412. package/dist/server/middleware/rate-limit.js +270 -0
  413. package/dist/server/middleware/scope-guard.d.ts +25 -0
  414. package/dist/server/middleware/scope-guard.js +45 -0
  415. package/dist/server/middleware/url-validator.d.ts +15 -0
  416. package/dist/server/middleware/url-validator.js +201 -0
  417. package/dist/server/openapi.yaml +6418 -0
  418. package/dist/server/pg-auth-store.d.ts +146 -0
  419. package/dist/server/pg-auth-store.js +576 -0
  420. package/dist/server/pg-job-queue.d.ts +59 -0
  421. package/dist/server/pg-job-queue.js +375 -0
  422. package/dist/server/routes/activity.d.ts +6 -0
  423. package/dist/server/routes/activity.js +79 -0
  424. package/dist/server/routes/admin-active.d.ts +7 -0
  425. package/dist/server/routes/admin-active.js +120 -0
  426. package/dist/server/routes/admin-stats.d.ts +7 -0
  427. package/dist/server/routes/admin-stats.js +176 -0
  428. package/dist/server/routes/agent.d.ts +24 -0
  429. package/dist/server/routes/agent.js +480 -0
  430. package/dist/server/routes/answer.d.ts +5 -0
  431. package/dist/server/routes/answer.js +125 -0
  432. package/dist/server/routes/ask.d.ts +28 -0
  433. package/dist/server/routes/ask.js +295 -0
  434. package/dist/server/routes/batch.d.ts +6 -0
  435. package/dist/server/routes/batch.js +493 -0
  436. package/dist/server/routes/cache-warm.d.ts +25 -0
  437. package/dist/server/routes/cache-warm.js +212 -0
  438. package/dist/server/routes/cli-usage.d.ts +6 -0
  439. package/dist/server/routes/cli-usage.js +127 -0
  440. package/dist/server/routes/compat.d.ts +23 -0
  441. package/dist/server/routes/compat.js +652 -0
  442. package/dist/server/routes/crawl.d.ts +13 -0
  443. package/dist/server/routes/crawl.js +287 -0
  444. package/dist/server/routes/deep-fetch.d.ts +8 -0
  445. package/dist/server/routes/deep-fetch.js +57 -0
  446. package/dist/server/routes/deep-research.d.ts +11 -0
  447. package/dist/server/routes/deep-research.js +232 -0
  448. package/dist/server/routes/demo.d.ts +24 -0
  449. package/dist/server/routes/demo.js +517 -0
  450. package/dist/server/routes/do.d.ts +8 -0
  451. package/dist/server/routes/do.js +72 -0
  452. package/dist/server/routes/extract.d.ts +14 -0
  453. package/dist/server/routes/extract.js +325 -0
  454. package/dist/server/routes/feed.d.ts +15 -0
  455. package/dist/server/routes/feed.js +311 -0
  456. package/dist/server/routes/fetch-queue.d.ts +13 -0
  457. package/dist/server/routes/fetch-queue.js +357 -0
  458. package/dist/server/routes/fetch.d.ts +7 -0
  459. package/dist/server/routes/fetch.js +1274 -0
  460. package/dist/server/routes/go.d.ts +14 -0
  461. package/dist/server/routes/go.js +81 -0
  462. package/dist/server/routes/health.d.ts +11 -0
  463. package/dist/server/routes/health.js +141 -0
  464. package/dist/server/routes/jobs.d.ts +7 -0
  465. package/dist/server/routes/jobs.js +574 -0
  466. package/dist/server/routes/map.d.ts +11 -0
  467. package/dist/server/routes/map.js +116 -0
  468. package/dist/server/routes/mcp.d.ts +14 -0
  469. package/dist/server/routes/mcp.js +197 -0
  470. package/dist/server/routes/metrics.d.ts +37 -0
  471. package/dist/server/routes/metrics.js +149 -0
  472. package/dist/server/routes/oauth.d.ts +9 -0
  473. package/dist/server/routes/oauth.js +396 -0
  474. package/dist/server/routes/playground.d.ts +17 -0
  475. package/dist/server/routes/playground.js +283 -0
  476. package/dist/server/routes/reader.d.ts +18 -0
  477. package/dist/server/routes/reader.js +192 -0
  478. package/dist/server/routes/research.d.ts +14 -0
  479. package/dist/server/routes/research.js +482 -0
  480. package/dist/server/routes/screenshot.d.ts +22 -0
  481. package/dist/server/routes/screenshot.js +820 -0
  482. package/dist/server/routes/search.d.ts +6 -0
  483. package/dist/server/routes/search.js +874 -0
  484. package/dist/server/routes/session.d.ts +17 -0
  485. package/dist/server/routes/session.js +548 -0
  486. package/dist/server/routes/share.d.ts +18 -0
  487. package/dist/server/routes/share.js +462 -0
  488. package/dist/server/routes/smart-search/handlers/cars.d.ts +2 -0
  489. package/dist/server/routes/smart-search/handlers/cars.js +102 -0
  490. package/dist/server/routes/smart-search/handlers/flights.d.ts +2 -0
  491. package/dist/server/routes/smart-search/handlers/flights.js +72 -0
  492. package/dist/server/routes/smart-search/handlers/general.d.ts +13 -0
  493. package/dist/server/routes/smart-search/handlers/general.js +717 -0
  494. package/dist/server/routes/smart-search/handlers/hotels.d.ts +2 -0
  495. package/dist/server/routes/smart-search/handlers/hotels.js +88 -0
  496. package/dist/server/routes/smart-search/handlers/products.d.ts +2 -0
  497. package/dist/server/routes/smart-search/handlers/products.js +1309 -0
  498. package/dist/server/routes/smart-search/handlers/rental.d.ts +2 -0
  499. package/dist/server/routes/smart-search/handlers/rental.js +154 -0
  500. package/dist/server/routes/smart-search/handlers/restaurants.d.ts +2 -0
  501. package/dist/server/routes/smart-search/handlers/restaurants.js +225 -0
  502. package/dist/server/routes/smart-search/handlers/transit-verdict.d.ts +41 -0
  503. package/dist/server/routes/smart-search/handlers/transit-verdict.js +224 -0
  504. package/dist/server/routes/smart-search/index.d.ts +19 -0
  505. package/dist/server/routes/smart-search/index.js +546 -0
  506. package/dist/server/routes/smart-search/intent.d.ts +3 -0
  507. package/dist/server/routes/smart-search/intent.js +264 -0
  508. package/dist/server/routes/smart-search/llm.d.ts +16 -0
  509. package/dist/server/routes/smart-search/llm.js +70 -0
  510. package/dist/server/routes/smart-search/sources/reddit.d.ts +18 -0
  511. package/dist/server/routes/smart-search/sources/reddit.js +34 -0
  512. package/dist/server/routes/smart-search/sources/yelp.d.ts +25 -0
  513. package/dist/server/routes/smart-search/sources/yelp.js +171 -0
  514. package/dist/server/routes/smart-search/sources/youtube.d.ts +8 -0
  515. package/dist/server/routes/smart-search/sources/youtube.js +9 -0
  516. package/dist/server/routes/smart-search/types.d.ts +81 -0
  517. package/dist/server/routes/smart-search/types.js +1 -0
  518. package/dist/server/routes/smart-search/utils.d.ts +20 -0
  519. package/dist/server/routes/smart-search/utils.js +146 -0
  520. package/dist/server/routes/stats.d.ts +6 -0
  521. package/dist/server/routes/stats.js +71 -0
  522. package/dist/server/routes/stripe.d.ts +15 -0
  523. package/dist/server/routes/stripe.js +296 -0
  524. package/dist/server/routes/transcript-export.d.ts +10 -0
  525. package/dist/server/routes/transcript-export.js +178 -0
  526. package/dist/server/routes/usage.d.ts +9 -0
  527. package/dist/server/routes/usage.js +279 -0
  528. package/dist/server/routes/users.d.ts +8 -0
  529. package/dist/server/routes/users.js +1867 -0
  530. package/dist/server/routes/watch.d.ts +15 -0
  531. package/dist/server/routes/watch.js +309 -0
  532. package/dist/server/routes/webhooks.d.ts +26 -0
  533. package/dist/server/routes/webhooks.js +170 -0
  534. package/dist/server/routes/youtube.d.ts +6 -0
  535. package/dist/server/routes/youtube.js +130 -0
  536. package/dist/server/sentry.d.ts +14 -0
  537. package/dist/server/sentry.js +104 -0
  538. package/dist/server/types.d.ts +15 -0
  539. package/dist/server/types.js +7 -0
  540. package/dist/server/utils/response.d.ts +44 -0
  541. package/dist/server/utils/response.js +69 -0
  542. package/dist/server/utils/sse.d.ts +22 -0
  543. package/dist/server/utils/sse.js +38 -0
  544. package/dist/types.d.ts +552 -0
  545. package/dist/types.js +39 -0
  546. package/llms.txt +105 -0
  547. package/package.json +189 -0
@@ -0,0 +1,358 @@
1
+ import { fetchJson } from './shared.js';
2
+ // ---------------------------------------------------------------------------
3
+ // 33. Polymarket extractor โ€” prediction market data via public APIs
4
+ // Supports: events, markets, profiles (@username), activity
5
+ // ---------------------------------------------------------------------------
6
+ // โ”€โ”€ Shared helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
7
+ const fmtPct = (p) => {
8
+ const n = typeof p === 'string' ? parseFloat(p) : p;
9
+ if (isNaN(n))
10
+ return '?%';
11
+ return (n * 100).toFixed(1) + '%';
12
+ };
13
+ const fmtVol = (v) => {
14
+ const n = typeof v === 'string' ? parseFloat(v) : v;
15
+ if (isNaN(n) || n === 0)
16
+ return '$0';
17
+ if (n >= 1_000_000)
18
+ return `$${(n / 1_000_000).toFixed(1)}M`;
19
+ if (n >= 1_000)
20
+ return `$${(n / 1_000).toFixed(1)}K`;
21
+ return `$${n.toFixed(2)}`;
22
+ };
23
+ const fmtDate = (d) => {
24
+ if (!d)
25
+ return '?';
26
+ return d.slice(0, 10);
27
+ };
28
+ const fmtNum = (n) => {
29
+ if (n >= 1_000_000)
30
+ return `${(n / 1_000_000).toFixed(1)}M`;
31
+ if (n >= 1_000)
32
+ return `${(n / 1_000).toFixed(1)}K`;
33
+ return n.toLocaleString('en-US');
34
+ };
35
+ function timeAgo(timestamp) {
36
+ const diff = Math.floor(Date.now() / 1000) - timestamp;
37
+ if (diff < 60)
38
+ return 'just now';
39
+ if (diff < 3600)
40
+ return `${Math.floor(diff / 60)}m ago`;
41
+ if (diff < 86400)
42
+ return `${Math.floor(diff / 3600)}h ago`;
43
+ if (diff < 604800)
44
+ return `${Math.floor(diff / 86400)}d ago`;
45
+ return new Date(timestamp * 1000).toISOString().slice(0, 10);
46
+ }
47
+ // โ”€โ”€ Main extractor โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
48
+ export async function polymarketExtractor(_html, url) {
49
+ const urlObj = new URL(url);
50
+ const path = urlObj.pathname;
51
+ const domain = 'polymarket.com';
52
+ // --- Profile: /@username or /profile/@username ---
53
+ const profileUsernameMatch = path.match(/^\/(profile\/)?@([a-zA-Z0-9_.-]+)/);
54
+ const profileAddressMatch = path.match(/^\/(profile\/)?(0x[a-fA-F0-9]{40})/);
55
+ if (profileUsernameMatch || profileAddressMatch) {
56
+ try {
57
+ return await extractProfile(domain, profileUsernameMatch?.[2] || null, profileAddressMatch?.[2] || null);
58
+ }
59
+ catch (e) {
60
+ if (process.env.DEBUG)
61
+ console.debug('[webpeel]', 'Polymarket profile fetch failed:', e instanceof Error ? e.message : e);
62
+ return null; // Fall through to browser
63
+ }
64
+ }
65
+ // --- Event page: /event/<slug> ---
66
+ const eventMatch = path.match(/^\/event\/([^/?#]+)/);
67
+ if (eventMatch) {
68
+ return extractEvent(eventMatch[1], domain);
69
+ }
70
+ // --- Main/markets page ---
71
+ const isRootOrMarkets = path === '/' || path === '' || path === '/markets' || path.startsWith('/markets?');
72
+ if (isRootOrMarkets) {
73
+ return extractMarkets(domain);
74
+ }
75
+ return null;
76
+ }
77
+ // โ”€โ”€ Profile extractor โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
78
+ async function resolveWallet(username) {
79
+ // Fetch the SSR HTML to extract proxyWallet from embedded Next.js data
80
+ const controller = new AbortController();
81
+ const timer = setTimeout(() => controller.abort(), 10_000);
82
+ try {
83
+ const resp = await fetch(`https://polymarket.com/@${encodeURIComponent(username)}`, {
84
+ headers: {
85
+ 'User-Agent': 'webpeel/0.21 (https://webpeel.dev)',
86
+ 'Accept': 'text/html',
87
+ },
88
+ signal: controller.signal,
89
+ redirect: 'follow',
90
+ });
91
+ clearTimeout(timer);
92
+ if (!resp.ok)
93
+ return null;
94
+ const html = await resp.text();
95
+ const match = html.match(/"proxyWallet":"(0x[a-fA-F0-9]{40})"/);
96
+ return match?.[1] || null;
97
+ }
98
+ catch {
99
+ clearTimeout(timer);
100
+ return null;
101
+ }
102
+ }
103
+ async function fetchAllActivity(wallet, maxTrades = 5000) {
104
+ const allTrades = [];
105
+ let offset = 0;
106
+ const limit = 500;
107
+ while (offset < maxTrades) {
108
+ const batch = await fetchJson(`https://data-api.polymarket.com/activity?user=${wallet}&limit=${limit}&offset=${offset}`);
109
+ if (!Array.isArray(batch) || batch.length === 0)
110
+ break;
111
+ allTrades.push(...batch);
112
+ if (batch.length < limit)
113
+ break;
114
+ offset += limit;
115
+ }
116
+ return allTrades;
117
+ }
118
+ async function extractProfile(domain, username, walletAddress) {
119
+ // Step 1: Resolve wallet
120
+ let wallet = walletAddress;
121
+ if (!wallet && username) {
122
+ wallet = await resolveWallet(username);
123
+ }
124
+ if (!wallet)
125
+ return null;
126
+ // Step 2: Parallel API calls
127
+ const [profileData, statsData, leaderboardData, valueData, tradedData] = await Promise.all([
128
+ fetchJson(`https://polymarket.com/api/profile/userData?address=${wallet}`).catch(() => null),
129
+ fetchJson(`https://data-api.polymarket.com/v1/user-stats?proxyAddress=${wallet}`).catch(() => null),
130
+ fetchJson(`https://data-api.polymarket.com/v1/leaderboard?timePeriod=all&orderBy=VOL&limit=1&user=${wallet}`).catch(() => null),
131
+ fetchJson(`https://data-api.polymarket.com/value?user=${wallet}`).catch(() => null),
132
+ fetchJson(`https://data-api.polymarket.com/traded?user=${wallet}`).catch(() => null),
133
+ ]);
134
+ // Step 3: Fetch positions + activity in parallel
135
+ const [positions, activity] = await Promise.all([
136
+ fetchJson(`https://data-api.polymarket.com/positions?user=${wallet}&sortBy=CURRENT&sortDirection=DESC&sizeThreshold=.1&limit=100&offset=0`).catch(() => []),
137
+ fetchAllActivity(wallet).catch(() => []),
138
+ ]);
139
+ // Extract data
140
+ const lb = Array.isArray(leaderboardData) && leaderboardData.length > 0 ? leaderboardData[0] : null;
141
+ const displayName = username || lb?.userName || profileData?.pseudonym || wallet.slice(0, 10) + 'โ€ฆ';
142
+ const xUsername = lb?.xUsername || null;
143
+ const rank = lb?.rank ? `#${Number(lb.rank).toLocaleString('en-US')}` : '?';
144
+ const totalVol = lb?.vol ? fmtVol(lb.vol) : '?';
145
+ const pnl = lb?.pnl != null ? (lb.pnl >= 0 ? `+${fmtVol(lb.pnl)}` : `-${fmtVol(Math.abs(lb.pnl))}`) : '?';
146
+ const trades = statsData?.trades ?? tradedData?.traded ?? '?';
147
+ const largestWin = statsData?.largestWin ? fmtVol(statsData.largestWin) : '?';
148
+ const views = statsData?.views ? fmtNum(statsData.views) : '?';
149
+ const joinDate = statsData?.joinDate
150
+ ? new Date(statsData.joinDate).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })
151
+ : '?';
152
+ // Build positions markdown
153
+ let positionsMd = '';
154
+ const posArr = Array.isArray(positions) ? positions : [];
155
+ if (posArr.length > 0) {
156
+ const posRows = posArr.slice(0, 30).map((p) => {
157
+ const title = (p.title || p.eventTitle || '?').substring(0, 50);
158
+ const side = p.outcome || '?';
159
+ const shares = p.size != null ? Number(p.size).toFixed(1) : '?';
160
+ const avgPrice = p.avgPrice != null ? `$${Number(p.avgPrice).toFixed(2)}` : '?';
161
+ const curVal = p.currentValue != null ? fmtVol(p.currentValue) : (p.size && p.curPrice ? fmtVol(p.size * p.curPrice) : '?');
162
+ return `| ${title} | ${side} | ${shares} | ${avgPrice} | ${curVal} |`;
163
+ }).join('\n');
164
+ positionsMd = `\n## Current Positions (${posArr.length})\n\n| Market | Side | Shares | Avg Price | Value |\n|--------|------|--------|-----------|-------|\n${posRows}\n`;
165
+ }
166
+ // Build activity markdown (last 50 for display)
167
+ let activityMd = '';
168
+ const actArr = Array.isArray(activity) ? activity : [];
169
+ if (actArr.length > 0) {
170
+ const actRows = actArr.slice(0, 50).map((t) => {
171
+ const time = t.timestamp ? timeAgo(t.timestamp) : '?';
172
+ const type = t.type === 'TRADE' ? (t.side === 'BUY' ? 'Buy' : 'Sell') : t.type || '?';
173
+ const title = (t.title || '?').substring(0, 50);
174
+ const amount = t.usdcSize != null ? fmtVol(t.usdcSize) : '?';
175
+ return `| ${time} | ${type} | ${title} | ${amount} |`;
176
+ }).join('\n');
177
+ activityMd = `\n## Recent Activity (showing ${Math.min(actArr.length, 50)} of ${actArr.length} trades)\n\n| Time | Type | Market | Amount |\n|------|------|--------|--------|\n${actRows}\n`;
178
+ }
179
+ // Build activity summary
180
+ let summaryMd = '';
181
+ if (actArr.length > 0) {
182
+ const timestamps = actArr.map((t) => t.timestamp).filter(Boolean);
183
+ const oldest = timestamps.length ? new Date(Math.min(...timestamps) * 1000).toISOString().slice(0, 10) : '?';
184
+ const newest = timestamps.length ? new Date(Math.max(...timestamps) * 1000).toISOString().slice(0, 10) : '?';
185
+ const actVolume = actArr.reduce((sum, t) => sum + (Number(t.usdcSize) || 0), 0);
186
+ // Volume by day
187
+ const byDay = {};
188
+ actArr.forEach((t) => {
189
+ if (!t.timestamp)
190
+ return;
191
+ const day = new Date(t.timestamp * 1000).toISOString().slice(0, 10);
192
+ byDay[day] = (byDay[day] || 0) + (Number(t.usdcSize) || 0);
193
+ });
194
+ const sortedDays = Object.entries(byDay).sort(([a], [b]) => b.localeCompare(a));
195
+ const topDays = sortedDays.slice(0, 7).map(([day, vol]) => `${day}: ${fmtVol(vol)}`).join(' ยท ');
196
+ // Type breakdown
197
+ const types = {};
198
+ actArr.forEach((t) => { types[t.type || 'UNKNOWN'] = (types[t.type || 'UNKNOWN'] || 0) + 1; });
199
+ const typeStr = Object.entries(types).map(([k, v]) => `${k}: ${v}`).join(', ');
200
+ summaryMd = `\n## Activity Summary\n\n- **Trades fetched:** ${actArr.length.toLocaleString('en-US')} (${typeStr})\n- **Date range:** ${oldest} โ†’ ${newest}\n- **Volume (fetched trades):** ${fmtVol(actVolume)}\n- **Recent days:** ${topDays}\n`;
201
+ }
202
+ // X/Twitter line
203
+ const xLine = xUsername ? ` | **X:** [@${xUsername}](https://x.com/${xUsername})` : '';
204
+ const cleanContent = `# ๐Ÿ“Š Polymarket Profile: @${displayName}
205
+
206
+ **Rank:** ${rank} | **Total Volume:** ${totalVol} | **P&L:** ${pnl}
207
+ **Trades:** ${typeof trades === 'number' ? trades.toLocaleString('en-US') : trades} | **Largest Win:** ${largestWin} | **Views:** ${views}
208
+ **Joined:** ${joinDate}${xLine}
209
+ ${positionsMd}${activityMd}${summaryMd}
210
+ ---
211
+ *Source: [Polymarket](https://polymarket.com/@${displayName}) ยท Data via Polymarket APIs*`;
212
+ // Structured data: ALL raw data for programmatic use
213
+ const structured = {
214
+ username: displayName,
215
+ wallet,
216
+ profile: profileData || {},
217
+ stats: statsData || {},
218
+ leaderboard: lb || {},
219
+ value: valueData || {},
220
+ positions: posArr,
221
+ activity: actArr,
222
+ summary: {
223
+ totalTrades: trades,
224
+ totalVolume: lb?.vol ?? null,
225
+ pnl: lb?.pnl ?? null,
226
+ rank: lb?.rank ?? null,
227
+ dateRange: actArr.length > 0 ? {
228
+ from: new Date(Math.min(...actArr.map((t) => t.timestamp || Infinity)) * 1000).toISOString().slice(0, 10),
229
+ to: new Date(Math.max(...actArr.map((t) => t.timestamp || 0)) * 1000).toISOString().slice(0, 10),
230
+ } : null,
231
+ volumeByDay: (() => {
232
+ const byDay = {};
233
+ actArr.forEach((t) => {
234
+ if (!t.timestamp)
235
+ return;
236
+ const day = new Date(t.timestamp * 1000).toISOString().slice(0, 10);
237
+ byDay[day] = (byDay[day] || 0) + (Number(t.usdcSize) || 0);
238
+ });
239
+ return byDay;
240
+ })(),
241
+ },
242
+ fetchedAt: new Date().toISOString(),
243
+ };
244
+ return { domain, type: 'profile', structured, cleanContent };
245
+ }
246
+ // โ”€โ”€ Event extractor โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
247
+ async function extractEvent(slug, domain) {
248
+ try {
249
+ const events = await fetchJson(`https://gamma-api.polymarket.com/events?slug=${encodeURIComponent(slug)}&limit=1`);
250
+ if (Array.isArray(events) && events.length > 0) {
251
+ const event = events[0];
252
+ const markets = event.markets || [];
253
+ const structured = {
254
+ title: event.title || slug,
255
+ slug: event.slug,
256
+ volume: event.volume,
257
+ volume24hr: event.volume24hr,
258
+ endDate: event.endDate,
259
+ markets: markets.map((m) => ({
260
+ question: m.question,
261
+ outcomes: m.outcomes,
262
+ outcomePrices: m.outcomePrices,
263
+ volume: m.volume,
264
+ volume24hr: m.volume24hr,
265
+ endDate: m.endDate,
266
+ bestBid: m.bestBid,
267
+ bestAsk: m.bestAsk,
268
+ lastTradePrice: m.lastTradePrice,
269
+ })),
270
+ };
271
+ const marketsMd = markets.map((m) => {
272
+ const outcomes = JSON.parse(m.outcomes || '[]');
273
+ const prices = JSON.parse(m.outcomePrices || '[]');
274
+ const priceStr = outcomes.map((o, i) => `${o}: **${fmtPct(prices[i] ?? 0)}**`).join(' | ');
275
+ const vol24 = m.volume24hr ? ` | Vol 24h: ${fmtVol(m.volume24hr)}` : '';
276
+ const endDate = m.endDate ? ` | Ends: ${fmtDate(m.endDate)}` : '';
277
+ return `- **${m.question}**\n ${priceStr}${vol24}${endDate}`;
278
+ }).join('\n\n');
279
+ const totalVol24 = fmtVol(event.volume24hr || 0);
280
+ const totalVol = fmtVol(event.volume || 0);
281
+ const cleanContent = `# ๐Ÿ“Š Polymarket: ${event.title || slug}
282
+
283
+ **Volume (24h):** ${totalVol24} | **Total Volume:** ${totalVol} | **Ends:** ${fmtDate(event.endDate)}
284
+
285
+ ## Markets
286
+
287
+ ${marketsMd || '*No active markets found.*'}
288
+
289
+ ---
290
+ *Source: [Polymarket](https://polymarket.com/event/${slug}) ยท Data via Polymarket Gamma API*`;
291
+ return { domain, type: 'event', structured, cleanContent };
292
+ }
293
+ // Fallback: keyword search
294
+ const markets = await fetchJson(`https://gamma-api.polymarket.com/markets?closed=false&limit=10&order=volume24hr&ascending=false&q=${encodeURIComponent(slug.replace(/-/g, ' '))}`);
295
+ if (Array.isArray(markets) && markets.length > 0) {
296
+ return buildPolymarketMarketList(markets, domain, `Search: ${slug}`);
297
+ }
298
+ }
299
+ catch (e) {
300
+ if (process.env.DEBUG)
301
+ console.debug('[webpeel]', 'Polymarket event fetch failed:', e instanceof Error ? e.message : e);
302
+ }
303
+ return null;
304
+ }
305
+ // โ”€โ”€ Markets list โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
306
+ async function extractMarkets(domain) {
307
+ try {
308
+ const markets = await fetchJson('https://gamma-api.polymarket.com/markets?closed=false&limit=20&order=volume24hr&ascending=false');
309
+ if (Array.isArray(markets)) {
310
+ return buildPolymarketMarketList(markets, domain, 'Top Markets');
311
+ }
312
+ }
313
+ catch (e) {
314
+ if (process.env.DEBUG)
315
+ console.debug('[webpeel]', 'Polymarket markets fetch failed:', e instanceof Error ? e.message : e);
316
+ }
317
+ return null;
318
+ }
319
+ function buildPolymarketMarketList(markets, domain, title) {
320
+ const rows = markets.slice(0, 15).map((m) => {
321
+ const outcomes = (() => { try {
322
+ return JSON.parse(m.outcomes || '[]');
323
+ }
324
+ catch {
325
+ return [];
326
+ } })();
327
+ const prices = (() => { try {
328
+ return JSON.parse(m.outcomePrices || '[]');
329
+ }
330
+ catch {
331
+ return [];
332
+ } })();
333
+ const yesPrice = outcomes[0] ? fmtPct(prices[0] ?? 0) : '?%';
334
+ const vol24 = fmtVol(m.volume24hr || 0);
335
+ const end = m.endDate ? m.endDate.slice(0, 10) : '?';
336
+ return `| ${m.question} | ${yesPrice} | ${vol24} | ${end} |`;
337
+ }).join('\n');
338
+ const structured = {
339
+ markets: markets.slice(0, 15).map((m) => ({
340
+ question: m.question,
341
+ slug: m.slug,
342
+ outcomePrices: m.outcomePrices,
343
+ outcomes: m.outcomes,
344
+ volume24hr: m.volume24hr,
345
+ endDate: m.endDate,
346
+ })),
347
+ fetchedAt: new Date().toISOString(),
348
+ };
349
+ const cleanContent = `# ๐Ÿ“Š Polymarket โ€” ${title}
350
+
351
+ | Question | Yes Price | Vol 24h | End Date |
352
+ |----------|-----------|---------|----------|
353
+ ${rows}
354
+
355
+ ---
356
+ *Source: [Polymarket](https://polymarket.com) ยท Data via Polymarket Gamma API*`;
357
+ return { domain, type: 'markets', structured, cleanContent };
358
+ }
@@ -0,0 +1,2 @@
1
+ import type { DomainExtractResult } from './types.js';
2
+ export declare function productHuntExtractor(_html: string, _url: string): Promise<DomainExtractResult | null>;
@@ -0,0 +1,88 @@
1
+ import { simpleFetch } from '../../core/fetcher.js';
2
+ import { stripHtml } from './shared.js';
3
+ // ---------------------------------------------------------------------------
4
+ // 31. Product Hunt extractor (RSS/Atom feed)
5
+ // ---------------------------------------------------------------------------
6
+ export async function productHuntExtractor(_html, _url) {
7
+ try {
8
+ // Fetch the public Atom feed โ€” no auth required
9
+ const feedResult = await simpleFetch('https://www.producthunt.com/feed', 'WebPeel/0.17.1 (web data platform; https://webpeel.dev) Node.js', 15000, { Accept: 'application/xml, text/xml, */*' });
10
+ if (!feedResult?.html)
11
+ return null;
12
+ const xml = feedResult.html;
13
+ // Parse Atom entries (Product Hunt uses Atom, not RSS)
14
+ const entryMatches = [...xml.matchAll(/<entry>([\s\S]*?)<\/entry>/g)];
15
+ if (!entryMatches.length)
16
+ return null;
17
+ const products = [];
18
+ for (const match of entryMatches) {
19
+ const entry = match[1];
20
+ const titleMatch = entry.match(/<title>([\s\S]*?)<\/title>/);
21
+ const linkMatch = entry.match(/<link[^>]+href="([^"]+)"/);
22
+ const publishedMatch = entry.match(/<published>([\s\S]*?)<\/published>/);
23
+ const authorMatch = entry.match(/<name>([\s\S]*?)<\/name>/);
24
+ const contentMatch = entry.match(/<content[^>]*>([\s\S]*?)<\/content>/);
25
+ if (!titleMatch)
26
+ continue;
27
+ const title = stripHtml(titleMatch[1]).trim();
28
+ const link = linkMatch?.[1] || '';
29
+ const published = publishedMatch?.[1]?.trim() || '';
30
+ const author = authorMatch ? stripHtml(authorMatch[1]).trim() : '';
31
+ // Extract tagline from encoded HTML in <content>
32
+ // Content is HTML-encoded: &lt;p&gt;tagline&lt;/p&gt;...
33
+ let tagline = '';
34
+ let directLink = '';
35
+ if (contentMatch) {
36
+ const decoded = contentMatch[1]
37
+ .replace(/&lt;/g, '<')
38
+ .replace(/&gt;/g, '>')
39
+ .replace(/&amp;/g, '&')
40
+ .replace(/&quot;/g, '"')
41
+ .replace(/&#39;/g, "'");
42
+ // First <p> is the tagline
43
+ const taglineMatch = decoded.match(/<p[^>]*>\s*([\s\S]*?)\s*<\/p>/);
44
+ if (taglineMatch) {
45
+ tagline = stripHtml(taglineMatch[1]).trim();
46
+ }
47
+ // Extract direct product link (the "Link" href, not the discussion link)
48
+ const linkHrefMatch = decoded.match(/href="(https:\/\/www\.producthunt\.com\/r\/p\/[^"]+)"/);
49
+ directLink = linkHrefMatch?.[1] || link;
50
+ }
51
+ // Format published date nicely
52
+ let dateStr = '';
53
+ if (published) {
54
+ try {
55
+ const d = new Date(published);
56
+ dateStr = d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
57
+ }
58
+ catch {
59
+ dateStr = published.split('T')[0];
60
+ }
61
+ }
62
+ products.push({ title, link, published: dateStr, tagline, author, directLink });
63
+ }
64
+ if (!products.length)
65
+ return null;
66
+ // Build clean markdown output
67
+ const today = new Date().toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });
68
+ const productList = products.map((p, i) => {
69
+ const taglinePart = p.tagline ? ` โ€” ${p.tagline}` : '';
70
+ const datePart = p.published ? `\n ๐Ÿ“… ${p.published}` : '';
71
+ const authorPart = p.author ? ` by ${p.author}` : '';
72
+ return `${i + 1}. **[${p.title}](${p.link})**${taglinePart}${datePart}${authorPart}`;
73
+ }).join('\n\n');
74
+ const structured = {
75
+ products,
76
+ total: products.length,
77
+ fetchedAt: new Date().toISOString(),
78
+ feedUrl: 'https://www.producthunt.com/feed',
79
+ };
80
+ const cleanContent = `# ๐Ÿš€ Product Hunt โ€” Featured Products\n\n*Fetched ${today} ยท ${products.length} products*\n\n${productList}\n\n---\n*Source: [Product Hunt Feed](https://www.producthunt.com/feed)*`;
81
+ return { domain: 'producthunt.com', type: 'feed', structured, cleanContent };
82
+ }
83
+ catch (e) {
84
+ if (process.env.DEBUG)
85
+ console.debug('[webpeel]', 'Product Hunt extractor failed:', e instanceof Error ? e.message : e);
86
+ return null;
87
+ }
88
+ }
@@ -0,0 +1,2 @@
1
+ import type { DomainExtractResult } from './types.js';
2
+ export declare function pubmedExtractor(_html: string, url: string): Promise<DomainExtractResult | null>;
@@ -0,0 +1,162 @@
1
+ import { simpleFetch } from '../../core/fetcher.js';
2
+ import { stripHtml, fetchJson } from './shared.js';
3
+ // ---------------------------------------------------------------------------
4
+ // PubMed extractor (NCBI E-utilities API โ€” free, no key needed)
5
+ // ---------------------------------------------------------------------------
6
+ export async function pubmedExtractor(_html, url) {
7
+ const urlObj = new URL(url);
8
+ const path = urlObj.pathname;
9
+ const domain = 'pubmed.ncbi.nlm.nih.gov';
10
+ // --- Article page: /XXXXXX/ or /XXXXXX ---
11
+ const pmidMatch = path.match(/^\/(\d+)\/?$/);
12
+ if (pmidMatch) {
13
+ const pmid = pmidMatch[1];
14
+ try {
15
+ // Fetch summary
16
+ const summaryUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=${pmid}&retmode=json`;
17
+ const summaryData = await fetchJson(summaryUrl);
18
+ if (!summaryData?.result)
19
+ return null;
20
+ const result = summaryData.result;
21
+ const article = result[pmid];
22
+ if (!article)
23
+ return null;
24
+ // Fetch abstract via efetch
25
+ let abstract = '';
26
+ try {
27
+ const efetchUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=${pmid}&retmode=xml&rettype=abstract`;
28
+ const efetchResult = await simpleFetch(efetchUrl, 'WebPeel/0.21', 15000, { Accept: 'application/xml' });
29
+ if (efetchResult?.html) {
30
+ const abstractMatch = efetchResult.html.match(/<AbstractText[^>]*>([\s\S]*?)<\/AbstractText>/g);
31
+ if (abstractMatch) {
32
+ abstract = abstractMatch.map((m) => {
33
+ const labelMatch = m.match(/Label="([^"]+)"/);
34
+ const textMatch = m.match(/<AbstractText[^>]*>([\s\S]*?)<\/AbstractText>/);
35
+ const text = textMatch ? stripHtml(textMatch[1]).trim() : '';
36
+ return labelMatch ? `**${labelMatch[1]}:** ${text}` : text;
37
+ }).join('\n\n');
38
+ }
39
+ }
40
+ }
41
+ catch { /* abstract is optional */ }
42
+ const authors = article.authors || [];
43
+ const authorNames = authors.filter(a => a.authtype !== 'CollectiveName').map(a => a.name);
44
+ const authorLine = authorNames.length <= 6
45
+ ? authorNames.join(', ')
46
+ : `${authorNames.slice(0, 6).join(', ')} et al.`;
47
+ const doi = article.elocationid?.replace(/^doi:\s*/i, '') || null;
48
+ const pubDate = article.pubdate || '?';
49
+ const journal = article.source || '?';
50
+ const volume = article.volume ? ` ${article.volume}` : '';
51
+ const issue = article.issue ? `(${article.issue})` : '';
52
+ const pages = article.pages ? `:${article.pages}` : '';
53
+ const structured = {
54
+ pmid,
55
+ title: article.title,
56
+ authors: authorNames,
57
+ journal,
58
+ pubDate,
59
+ volume: article.volume,
60
+ issue: article.issue,
61
+ pages: article.pages,
62
+ doi,
63
+ abstract: abstract || undefined,
64
+ url: `https://pubmed.ncbi.nlm.nih.gov/${pmid}/`,
65
+ };
66
+ const lines = [
67
+ `# ๐Ÿงฌ ${article.title}`,
68
+ '',
69
+ `**Authors:** ${authorLine}`,
70
+ `**Journal:** *${journal}*${volume}${issue}${pages} (${pubDate})`,
71
+ `**PMID:** ${pmid}`,
72
+ ];
73
+ if (doi)
74
+ lines.push(`**DOI:** [${doi}](https://doi.org/${doi})`);
75
+ if (abstract) {
76
+ lines.push('', '## Abstract', '', abstract);
77
+ }
78
+ lines.push('', `**Link:** [PubMed](https://pubmed.ncbi.nlm.nih.gov/${pmid}/)`);
79
+ return {
80
+ domain,
81
+ type: 'article',
82
+ structured,
83
+ cleanContent: lines.join('\n'),
84
+ };
85
+ }
86
+ catch (e) {
87
+ if (process.env.DEBUG)
88
+ console.debug('[webpeel]', 'PubMed article API failed:', e instanceof Error ? e.message : e);
89
+ return null;
90
+ }
91
+ }
92
+ // --- Search page: /?term=... or /?query=... ---
93
+ const term = urlObj.searchParams.get('term') || urlObj.searchParams.get('query');
94
+ if (term) {
95
+ try {
96
+ // Step 1: search for IDs
97
+ const searchUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=${encodeURIComponent(term)}&retmode=json&retmax=10`;
98
+ const searchData = await fetchJson(searchUrl);
99
+ if (!searchData?.esearchresult)
100
+ return null;
101
+ const esearch = searchData.esearchresult;
102
+ const ids = esearch.idlist || [];
103
+ const total = parseInt(esearch.count || '0', 10);
104
+ if (ids.length === 0) {
105
+ return {
106
+ domain,
107
+ type: 'search',
108
+ structured: { query: term, total: 0, articles: [] },
109
+ cleanContent: `# ๐Ÿ” PubMed โ€” "${term}"\n\n*No results found.*`,
110
+ };
111
+ }
112
+ // Step 2: fetch summaries
113
+ const summaryUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=${ids.join(',')}&retmode=json`;
114
+ const summaryData = await fetchJson(summaryUrl);
115
+ if (!summaryData?.result)
116
+ return null;
117
+ const result = summaryData.result;
118
+ const articles = (result.uids || ids).map((id) => {
119
+ const a = result[id];
120
+ if (!a)
121
+ return null;
122
+ const authors = a.authors || [];
123
+ return {
124
+ pmid: id,
125
+ title: a.title,
126
+ journal: a.source,
127
+ pubDate: a.pubdate,
128
+ authors: authors.map(x => x.name),
129
+ doi: a.elocationid?.replace(/^doi:\s*/i, '') || null,
130
+ };
131
+ }).filter(Boolean);
132
+ const rows = articles.map((a, i) => {
133
+ const authorLine = a.authors.length === 0 ? 'โ€”'
134
+ : a.authors.length === 1 ? a.authors[0]
135
+ : `${a.authors[0]} et al.`;
136
+ const link = `https://pubmed.ncbi.nlm.nih.gov/${a.pmid}/`;
137
+ return `| ${i + 1} | [${a.title}](${link}) | *${a.journal}* | ${a.pubDate} | ${authorLine} |`;
138
+ }).join('\n');
139
+ const cleanContent = [
140
+ `# ๐Ÿ” PubMed โ€” "${term}"`,
141
+ '',
142
+ '| # | Article | Journal | Date | Authors |',
143
+ '|---|---------|---------|------|---------|',
144
+ rows,
145
+ '',
146
+ `*Source: NCBI PubMed E-utilities ยท Total results: ${total.toLocaleString()}*`,
147
+ ].join('\n');
148
+ return {
149
+ domain,
150
+ type: 'search',
151
+ structured: { query: term, total, articles },
152
+ cleanContent,
153
+ };
154
+ }
155
+ catch (e) {
156
+ if (process.env.DEBUG)
157
+ console.debug('[webpeel]', 'PubMed search API failed:', e instanceof Error ? e.message : e);
158
+ return null;
159
+ }
160
+ }
161
+ return null;
162
+ }
@@ -0,0 +1,2 @@
1
+ import type { DomainExtractResult } from './types.js';
2
+ export declare function pypiExtractor(_html: string, url: string): Promise<DomainExtractResult | null>;