@zenalexa/unicli 0.219.0 → 0.220.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 (430) hide show
  1. package/AGENTS.md +9 -9
  2. package/README.md +55 -249
  3. package/README.zh-CN.md +55 -249
  4. package/dist/adapters/1point3acres/forum.d.ts +58 -0
  5. package/dist/adapters/1point3acres/forum.d.ts.map +1 -0
  6. package/dist/adapters/1point3acres/forum.js +708 -0
  7. package/dist/adapters/1point3acres/forum.js.map +1 -0
  8. package/dist/adapters/aibase/news.d.ts +21 -0
  9. package/dist/adapters/aibase/news.d.ts.map +1 -0
  10. package/dist/adapters/aibase/news.js +96 -0
  11. package/dist/adapters/aibase/news.js.map +1 -0
  12. package/dist/adapters/arxiv/papers.d.ts +27 -0
  13. package/dist/adapters/arxiv/papers.d.ts.map +1 -0
  14. package/dist/adapters/arxiv/papers.js +193 -0
  15. package/dist/adapters/arxiv/papers.js.map +1 -0
  16. package/dist/adapters/bbc/topic.d.ts +24 -0
  17. package/dist/adapters/bbc/topic.d.ts.map +1 -0
  18. package/dist/adapters/bbc/topic.js +122 -0
  19. package/dist/adapters/bbc/topic.js.map +1 -0
  20. package/dist/adapters/chatgpt/web.d.ts +24 -0
  21. package/dist/adapters/chatgpt/web.d.ts.map +1 -0
  22. package/dist/adapters/chatgpt/web.js +242 -0
  23. package/dist/adapters/chatgpt/web.js.map +1 -0
  24. package/dist/adapters/claude/web.d.ts +24 -0
  25. package/dist/adapters/claude/web.d.ts.map +1 -0
  26. package/dist/adapters/claude/web.js +575 -0
  27. package/dist/adapters/claude/web.js.map +1 -0
  28. package/dist/adapters/codex/projects.d.ts +27 -0
  29. package/dist/adapters/codex/projects.d.ts.map +1 -0
  30. package/dist/adapters/codex/projects.js +147 -0
  31. package/dist/adapters/codex/projects.js.map +1 -0
  32. package/dist/adapters/coingecko/markets.d.ts +19 -0
  33. package/dist/adapters/coingecko/markets.d.ts.map +1 -0
  34. package/dist/adapters/coingecko/markets.js +474 -0
  35. package/dist/adapters/coingecko/markets.js.map +1 -0
  36. package/dist/adapters/coupang/product.d.ts +27 -0
  37. package/dist/adapters/coupang/product.d.ts.map +1 -0
  38. package/dist/adapters/coupang/product.js +211 -0
  39. package/dist/adapters/coupang/product.js.map +1 -0
  40. package/dist/adapters/crates/registry.d.ts +44 -0
  41. package/dist/adapters/crates/registry.d.ts.map +1 -0
  42. package/dist/adapters/crates/registry.js +186 -0
  43. package/dist/adapters/crates/registry.js.map +1 -0
  44. package/dist/adapters/ctrip/travel.d.ts +83 -0
  45. package/dist/adapters/ctrip/travel.d.ts.map +1 -0
  46. package/dist/adapters/ctrip/travel.js +630 -0
  47. package/dist/adapters/ctrip/travel.js.map +1 -0
  48. package/dist/adapters/dblp/publications.d.ts +41 -0
  49. package/dist/adapters/dblp/publications.d.ts.map +1 -0
  50. package/dist/adapters/dblp/publications.js +409 -0
  51. package/dist/adapters/dblp/publications.js.map +1 -0
  52. package/dist/adapters/deepseek/web.d.ts +1 -1
  53. package/dist/adapters/deepseek/web.d.ts.map +1 -1
  54. package/dist/adapters/deepseek/web.js +66 -1
  55. package/dist/adapters/deepseek/web.js.map +1 -1
  56. package/dist/adapters/defillama/protocols.d.ts +13 -0
  57. package/dist/adapters/defillama/protocols.d.ts.map +1 -0
  58. package/dist/adapters/defillama/protocols.js +218 -0
  59. package/dist/adapters/defillama/protocols.js.map +1 -0
  60. package/dist/adapters/devto/read.d.ts +26 -0
  61. package/dist/adapters/devto/read.d.ts.map +1 -0
  62. package/dist/adapters/devto/read.js +110 -0
  63. package/dist/adapters/devto/read.js.map +1 -0
  64. package/dist/adapters/dianping/shop.d.ts +38 -0
  65. package/dist/adapters/dianping/shop.d.ts.map +1 -0
  66. package/dist/adapters/dianping/shop.js +194 -0
  67. package/dist/adapters/dianping/shop.js.map +1 -0
  68. package/dist/adapters/dockerhub/registry.d.ts +36 -0
  69. package/dist/adapters/dockerhub/registry.d.ts.map +1 -0
  70. package/dist/adapters/dockerhub/registry.js +172 -0
  71. package/dist/adapters/dockerhub/registry.js.map +1 -0
  72. package/dist/adapters/endoflife/product.d.ts +11 -0
  73. package/dist/adapters/endoflife/product.d.ts.map +1 -0
  74. package/dist/adapters/endoflife/product.js +113 -0
  75. package/dist/adapters/endoflife/product.js.map +1 -0
  76. package/dist/adapters/facebook/marketplace-extra.d.ts +9 -0
  77. package/dist/adapters/facebook/marketplace-extra.d.ts.map +1 -0
  78. package/dist/adapters/facebook/marketplace-extra.js +170 -0
  79. package/dist/adapters/facebook/marketplace-extra.js.map +1 -0
  80. package/dist/adapters/flathub/apps.d.ts +17 -0
  81. package/dist/adapters/flathub/apps.d.ts.map +1 -0
  82. package/dist/adapters/flathub/apps.js +220 -0
  83. package/dist/adapters/flathub/apps.js.map +1 -0
  84. package/dist/adapters/goproxy/module.d.ts +24 -0
  85. package/dist/adapters/goproxy/module.d.ts.map +1 -0
  86. package/dist/adapters/goproxy/module.js +221 -0
  87. package/dist/adapters/goproxy/module.js.map +1 -0
  88. package/dist/adapters/grok/web.d.ts +29 -0
  89. package/dist/adapters/grok/web.d.ts.map +1 -0
  90. package/dist/adapters/grok/web.js +553 -0
  91. package/dist/adapters/grok/web.js.map +1 -0
  92. package/dist/adapters/hackernews/read.d.ts +31 -0
  93. package/dist/adapters/hackernews/read.d.ts.map +1 -0
  94. package/dist/adapters/hackernews/read.js +201 -0
  95. package/dist/adapters/hackernews/read.js.map +1 -0
  96. package/dist/adapters/hf/paper.d.ts +22 -0
  97. package/dist/adapters/hf/paper.d.ts.map +1 -0
  98. package/dist/adapters/hf/paper.js +112 -0
  99. package/dist/adapters/hf/paper.js.map +1 -0
  100. package/dist/adapters/homebrew/packages.d.ts +52 -0
  101. package/dist/adapters/homebrew/packages.d.ts.map +1 -0
  102. package/dist/adapters/homebrew/packages.js +240 -0
  103. package/dist/adapters/homebrew/packages.js.map +1 -0
  104. package/dist/adapters/indeed/jobs.d.ts +38 -0
  105. package/dist/adapters/indeed/jobs.d.ts.map +1 -0
  106. package/dist/adapters/indeed/jobs.js +300 -0
  107. package/dist/adapters/indeed/jobs.js.map +1 -0
  108. package/dist/adapters/instagram/collections.d.ts +9 -0
  109. package/dist/adapters/instagram/collections.d.ts.map +1 -0
  110. package/dist/adapters/instagram/collections.js +174 -0
  111. package/dist/adapters/instagram/collections.js.map +1 -0
  112. package/dist/adapters/lichess/players.d.ts +46 -0
  113. package/dist/adapters/lichess/players.d.ts.map +1 -0
  114. package/dist/adapters/lichess/players.js +221 -0
  115. package/dist/adapters/lichess/players.js.map +1 -0
  116. package/dist/adapters/lobsters/read-domain.d.ts +35 -0
  117. package/dist/adapters/lobsters/read-domain.d.ts.map +1 -0
  118. package/dist/adapters/lobsters/read-domain.js +306 -0
  119. package/dist/adapters/lobsters/read-domain.js.map +1 -0
  120. package/dist/adapters/maven/artifact.d.ts +30 -0
  121. package/dist/adapters/maven/artifact.d.ts.map +1 -0
  122. package/dist/adapters/maven/artifact.js +121 -0
  123. package/dist/adapters/maven/artifact.js.map +1 -0
  124. package/dist/adapters/mdn/search.d.ts +11 -0
  125. package/dist/adapters/mdn/search.d.ts.map +1 -0
  126. package/dist/adapters/mdn/search.js +115 -0
  127. package/dist/adapters/mdn/search.js.map +1 -0
  128. package/dist/adapters/medium/tag.d.ts +15 -0
  129. package/dist/adapters/medium/tag.d.ts.map +1 -0
  130. package/dist/adapters/medium/tag.js +148 -0
  131. package/dist/adapters/medium/tag.js.map +1 -0
  132. package/dist/adapters/npm/package.d.ts +32 -0
  133. package/dist/adapters/npm/package.d.ts.map +1 -0
  134. package/dist/adapters/npm/package.js +141 -0
  135. package/dist/adapters/npm/package.js.map +1 -0
  136. package/dist/adapters/nuget/package.d.ts +34 -0
  137. package/dist/adapters/nuget/package.d.ts.map +1 -0
  138. package/dist/adapters/nuget/package.js +135 -0
  139. package/dist/adapters/nuget/package.js.map +1 -0
  140. package/dist/adapters/nvd/cve.d.ts +42 -0
  141. package/dist/adapters/nvd/cve.d.ts.map +1 -0
  142. package/dist/adapters/nvd/cve.js +132 -0
  143. package/dist/adapters/nvd/cve.js.map +1 -0
  144. package/dist/adapters/oeis/sequences.d.ts +14 -0
  145. package/dist/adapters/oeis/sequences.d.ts.map +1 -0
  146. package/dist/adapters/oeis/sequences.js +219 -0
  147. package/dist/adapters/oeis/sequences.js.map +1 -0
  148. package/dist/adapters/openalex/works.d.ts +43 -0
  149. package/dist/adapters/openalex/works.d.ts.map +1 -0
  150. package/dist/adapters/openalex/works.js +267 -0
  151. package/dist/adapters/openalex/works.js.map +1 -0
  152. package/dist/adapters/openfda/records.d.ts +18 -0
  153. package/dist/adapters/openfda/records.d.ts.map +1 -0
  154. package/dist/adapters/openfda/records.js +209 -0
  155. package/dist/adapters/openfda/records.js.map +1 -0
  156. package/dist/adapters/openreview/papers.d.ts +34 -0
  157. package/dist/adapters/openreview/papers.d.ts.map +1 -0
  158. package/dist/adapters/openreview/papers.js +463 -0
  159. package/dist/adapters/openreview/papers.js.map +1 -0
  160. package/dist/adapters/osv/security.d.ts +36 -0
  161. package/dist/adapters/osv/security.d.ts.map +1 -0
  162. package/dist/adapters/osv/security.js +247 -0
  163. package/dist/adapters/osv/security.js.map +1 -0
  164. package/dist/adapters/packagist/package.d.ts +31 -0
  165. package/dist/adapters/packagist/package.d.ts.map +1 -0
  166. package/dist/adapters/packagist/package.js +108 -0
  167. package/dist/adapters/packagist/package.js.map +1 -0
  168. package/dist/adapters/pubmed/articles.d.ts +31 -0
  169. package/dist/adapters/pubmed/articles.d.ts.map +1 -0
  170. package/dist/adapters/pubmed/articles.js +385 -0
  171. package/dist/adapters/pubmed/articles.js.map +1 -0
  172. package/dist/adapters/pypi/package.d.ts +38 -0
  173. package/dist/adapters/pypi/package.d.ts.map +1 -0
  174. package/dist/adapters/pypi/package.js +235 -0
  175. package/dist/adapters/pypi/package.js.map +1 -0
  176. package/dist/adapters/qwen/web.d.ts +26 -0
  177. package/dist/adapters/qwen/web.d.ts.map +1 -0
  178. package/dist/adapters/qwen/web.js +672 -0
  179. package/dist/adapters/qwen/web.js.map +1 -0
  180. package/dist/adapters/reddit/account.d.ts +12 -0
  181. package/dist/adapters/reddit/account.d.ts.map +1 -0
  182. package/dist/adapters/reddit/account.js +409 -0
  183. package/dist/adapters/reddit/account.js.map +1 -0
  184. package/dist/adapters/rednote/web.d.ts +30 -0
  185. package/dist/adapters/rednote/web.d.ts.map +1 -0
  186. package/dist/adapters/rednote/web.js +858 -0
  187. package/dist/adapters/rednote/web.js.map +1 -0
  188. package/dist/adapters/rest-countries/countries.d.ts +14 -0
  189. package/dist/adapters/rest-countries/countries.d.ts.map +1 -0
  190. package/dist/adapters/rest-countries/countries.js +231 -0
  191. package/dist/adapters/rest-countries/countries.js.map +1 -0
  192. package/dist/adapters/reuters/article-detail.d.ts +37 -0
  193. package/dist/adapters/reuters/article-detail.d.ts.map +1 -0
  194. package/dist/adapters/reuters/article-detail.js +139 -0
  195. package/dist/adapters/reuters/article-detail.js.map +1 -0
  196. package/dist/adapters/rfc/rfc.d.ts +11 -0
  197. package/dist/adapters/rfc/rfc.d.ts.map +1 -0
  198. package/dist/adapters/rfc/rfc.js +121 -0
  199. package/dist/adapters/rfc/rfc.js.map +1 -0
  200. package/dist/adapters/rubygems/gem.d.ts +26 -0
  201. package/dist/adapters/rubygems/gem.d.ts.map +1 -0
  202. package/dist/adapters/rubygems/gem.js +96 -0
  203. package/dist/adapters/rubygems/gem.js.map +1 -0
  204. package/dist/adapters/stackoverflow/questions.d.ts +79 -0
  205. package/dist/adapters/stackoverflow/questions.d.ts.map +1 -0
  206. package/dist/adapters/stackoverflow/questions.js +504 -0
  207. package/dist/adapters/stackoverflow/questions.js.map +1 -0
  208. package/dist/adapters/steam/app.d.ts +39 -0
  209. package/dist/adapters/steam/app.d.ts.map +1 -0
  210. package/dist/adapters/steam/app.js +165 -0
  211. package/dist/adapters/steam/app.js.map +1 -0
  212. package/dist/adapters/tiktok/creator-videos.d.ts +52 -0
  213. package/dist/adapters/tiktok/creator-videos.d.ts.map +1 -0
  214. package/dist/adapters/tiktok/creator-videos.js +267 -0
  215. package/dist/adapters/tiktok/creator-videos.js.map +1 -0
  216. package/dist/adapters/tvmaze/shows.d.ts +13 -0
  217. package/dist/adapters/tvmaze/shows.d.ts.map +1 -0
  218. package/dist/adapters/tvmaze/shows.js +240 -0
  219. package/dist/adapters/tvmaze/shows.js.map +1 -0
  220. package/dist/adapters/twitter/bookmark-folders.d.ts +33 -0
  221. package/dist/adapters/twitter/bookmark-folders.d.ts.map +1 -0
  222. package/dist/adapters/twitter/bookmark-folders.js +290 -0
  223. package/dist/adapters/twitter/bookmark-folders.js.map +1 -0
  224. package/dist/adapters/twitter/quote.d.ts +18 -0
  225. package/dist/adapters/twitter/quote.d.ts.map +1 -0
  226. package/dist/adapters/twitter/quote.js +285 -0
  227. package/dist/adapters/twitter/quote.js.map +1 -0
  228. package/dist/adapters/twitter/tweet-actions.d.ts +12 -0
  229. package/dist/adapters/twitter/tweet-actions.d.ts.map +1 -0
  230. package/dist/adapters/twitter/tweet-actions.js +145 -0
  231. package/dist/adapters/twitter/tweet-actions.js.map +1 -0
  232. package/dist/adapters/twitter/tweet-url.d.ts +15 -0
  233. package/dist/adapters/twitter/tweet-url.d.ts.map +1 -0
  234. package/dist/adapters/twitter/tweet-url.js +57 -0
  235. package/dist/adapters/twitter/tweet-url.js.map +1 -0
  236. package/dist/adapters/uisdc/news.d.ts +22 -0
  237. package/dist/adapters/uisdc/news.d.ts.map +1 -0
  238. package/dist/adapters/uisdc/news.js +91 -0
  239. package/dist/adapters/uisdc/news.js.map +1 -0
  240. package/dist/adapters/weibo/favorites-publish.d.ts +28 -0
  241. package/dist/adapters/weibo/favorites-publish.d.ts.map +1 -0
  242. package/dist/adapters/weibo/favorites-publish.js +356 -0
  243. package/dist/adapters/weibo/favorites-publish.js.map +1 -0
  244. package/dist/adapters/wikidata/entities.d.ts +15 -0
  245. package/dist/adapters/wikidata/entities.d.ts.map +1 -0
  246. package/dist/adapters/wikidata/entities.js +219 -0
  247. package/dist/adapters/wikidata/entities.js.map +1 -0
  248. package/dist/adapters/wikipedia/page.d.ts +21 -0
  249. package/dist/adapters/wikipedia/page.d.ts.map +1 -0
  250. package/dist/adapters/wikipedia/page.js +116 -0
  251. package/dist/adapters/wikipedia/page.js.map +1 -0
  252. package/dist/adapters/wttr/weather.d.ts +12 -0
  253. package/dist/adapters/wttr/weather.d.ts.map +1 -0
  254. package/dist/adapters/wttr/weather.js +207 -0
  255. package/dist/adapters/wttr/weather.js.map +1 -0
  256. package/dist/adapters/xianyu/publish.d.ts +31 -0
  257. package/dist/adapters/xianyu/publish.d.ts.map +1 -0
  258. package/dist/adapters/xianyu/publish.js +349 -0
  259. package/dist/adapters/xianyu/publish.js.map +1 -0
  260. package/dist/adapters/xiaohongshu/user-helpers.d.ts +2 -2
  261. package/dist/adapters/xiaohongshu/user-helpers.d.ts.map +1 -1
  262. package/dist/adapters/xiaohongshu/user-helpers.js +5 -4
  263. package/dist/adapters/xiaohongshu/user-helpers.js.map +1 -1
  264. package/dist/adapters/yuanbao/web.d.ts +27 -0
  265. package/dist/adapters/yuanbao/web.d.ts.map +1 -0
  266. package/dist/adapters/yuanbao/web.js +365 -0
  267. package/dist/adapters/yuanbao/web.js.map +1 -0
  268. package/dist/adapters/zhihu/collection.d.ts +33 -0
  269. package/dist/adapters/zhihu/collection.d.ts.map +1 -0
  270. package/dist/adapters/zhihu/collection.js +185 -0
  271. package/dist/adapters/zhihu/collection.js.map +1 -0
  272. package/dist/adapters/zlibrary/web.d.ts +19 -0
  273. package/dist/adapters/zlibrary/web.d.ts.map +1 -0
  274. package/dist/adapters/zlibrary/web.js +153 -0
  275. package/dist/adapters/zlibrary/web.js.map +1 -0
  276. package/dist/browser/daemon-client.js +2 -2
  277. package/dist/browser/daemon-client.js.map +1 -1
  278. package/dist/discovery/macos-dynamic.d.ts.map +1 -1
  279. package/dist/discovery/macos-dynamic.js +17 -3
  280. package/dist/discovery/macos-dynamic.js.map +1 -1
  281. package/dist/manifest-compact.txt +10 -10
  282. package/dist/manifest-search.json +1 -1
  283. package/dist/manifest.json +5130 -112
  284. package/dist/transport/refs.d.ts +5 -3
  285. package/dist/transport/refs.d.ts.map +1 -1
  286. package/dist/transport/refs.js +8 -1
  287. package/dist/transport/refs.js.map +1 -1
  288. package/dist/transport/sidecar-binary.d.ts +7 -0
  289. package/dist/transport/sidecar-binary.d.ts.map +1 -1
  290. package/dist/transport/sidecar-binary.js +28 -8
  291. package/dist/transport/sidecar-binary.js.map +1 -1
  292. package/package.json +4 -3
  293. package/server.json +3 -3
  294. package/skills/unicli/SKILL.md +1 -1
  295. package/skills/unicli-claude-code/SKILL.md +1 -1
  296. package/skills/unicli-hermes/SKILL.md +1 -1
  297. package/src/adapters/1point3acres/forum.test.ts +300 -0
  298. package/src/adapters/1point3acres/forum.ts +852 -0
  299. package/src/adapters/aibase/news.test.ts +42 -0
  300. package/src/adapters/aibase/news.ts +118 -0
  301. package/src/adapters/arxiv/papers.test.ts +59 -0
  302. package/src/adapters/arxiv/papers.ts +226 -0
  303. package/src/adapters/bbc/topic.test.ts +52 -0
  304. package/src/adapters/bbc/topic.ts +149 -0
  305. package/src/adapters/chatgpt/web.test.ts +121 -0
  306. package/src/adapters/chatgpt/web.ts +286 -0
  307. package/src/adapters/claude/web.test.ts +206 -0
  308. package/src/adapters/claude/web.ts +684 -0
  309. package/src/adapters/codex/projects.test.ts +77 -0
  310. package/src/adapters/codex/projects.ts +178 -0
  311. package/src/adapters/coingecko/markets.test.ts +156 -0
  312. package/src/adapters/coingecko/markets.ts +574 -0
  313. package/src/adapters/coupang/product.test.ts +111 -0
  314. package/src/adapters/coupang/product.ts +256 -0
  315. package/src/adapters/crates/registry.test.ts +89 -0
  316. package/src/adapters/crates/registry.ts +247 -0
  317. package/src/adapters/ctrip/travel.test.ts +359 -0
  318. package/src/adapters/ctrip/travel.ts +792 -0
  319. package/src/adapters/dblp/publications.test.ts +123 -0
  320. package/src/adapters/dblp/publications.ts +494 -0
  321. package/src/adapters/deepseek/web.test.ts +69 -0
  322. package/src/adapters/deepseek/web.ts +78 -1
  323. package/src/adapters/defillama/protocols.test.ts +75 -0
  324. package/src/adapters/defillama/protocols.ts +253 -0
  325. package/src/adapters/devto/read.test.ts +49 -0
  326. package/src/adapters/devto/read.ts +145 -0
  327. package/src/adapters/dianping/shop.test.ts +134 -0
  328. package/src/adapters/dianping/shop.ts +261 -0
  329. package/src/adapters/dockerhub/registry.test.ts +97 -0
  330. package/src/adapters/dockerhub/registry.ts +223 -0
  331. package/src/adapters/endoflife/product.test.ts +50 -0
  332. package/src/adapters/endoflife/product.ts +128 -0
  333. package/src/adapters/facebook/marketplace-extra.test.ts +132 -0
  334. package/src/adapters/facebook/marketplace-extra.ts +213 -0
  335. package/src/adapters/flathub/apps.test.ts +85 -0
  336. package/src/adapters/flathub/apps.ts +254 -0
  337. package/src/adapters/goproxy/module.test.ts +72 -0
  338. package/src/adapters/goproxy/module.ts +258 -0
  339. package/src/adapters/grok/web.test.ts +181 -0
  340. package/src/adapters/grok/web.ts +640 -0
  341. package/src/adapters/hackernews/read.test.ts +68 -0
  342. package/src/adapters/hackernews/read.ts +265 -0
  343. package/src/adapters/hf/paper.test.ts +48 -0
  344. package/src/adapters/hf/paper.ts +138 -0
  345. package/src/adapters/homebrew/packages.test.ts +109 -0
  346. package/src/adapters/homebrew/packages.ts +304 -0
  347. package/src/adapters/indeed/jobs.test.ts +230 -0
  348. package/src/adapters/indeed/jobs.ts +375 -0
  349. package/src/adapters/instagram/collections.test.ts +94 -0
  350. package/src/adapters/instagram/collections.ts +206 -0
  351. package/src/adapters/lichess/players.test.ts +99 -0
  352. package/src/adapters/lichess/players.ts +277 -0
  353. package/src/adapters/lobsters/read-domain.test.ts +121 -0
  354. package/src/adapters/lobsters/read-domain.ts +400 -0
  355. package/src/adapters/maven/artifact.test.ts +67 -0
  356. package/src/adapters/maven/artifact.ts +155 -0
  357. package/src/adapters/mdn/search.test.ts +39 -0
  358. package/src/adapters/mdn/search.ts +133 -0
  359. package/src/adapters/medium/tag.test.ts +64 -0
  360. package/src/adapters/medium/tag.ts +164 -0
  361. package/src/adapters/npm/package.test.ts +53 -0
  362. package/src/adapters/npm/package.ts +177 -0
  363. package/src/adapters/nuget/package.test.ts +102 -0
  364. package/src/adapters/nuget/package.ts +193 -0
  365. package/src/adapters/nvd/cve.test.ts +66 -0
  366. package/src/adapters/nvd/cve.ts +182 -0
  367. package/src/adapters/oeis/sequences.test.ts +71 -0
  368. package/src/adapters/oeis/sequences.ts +234 -0
  369. package/src/adapters/openalex/works.test.ts +99 -0
  370. package/src/adapters/openalex/works.ts +319 -0
  371. package/src/adapters/openfda/records.test.ts +90 -0
  372. package/src/adapters/openfda/records.ts +239 -0
  373. package/src/adapters/openreview/papers.test.ts +139 -0
  374. package/src/adapters/openreview/papers.ts +560 -0
  375. package/src/adapters/osv/security.test.ts +91 -0
  376. package/src/adapters/osv/security.ts +298 -0
  377. package/src/adapters/packagist/package.test.ts +62 -0
  378. package/src/adapters/packagist/package.ts +146 -0
  379. package/src/adapters/pubmed/articles.test.ts +96 -0
  380. package/src/adapters/pubmed/articles.ts +497 -0
  381. package/src/adapters/pypi/package.test.ts +131 -0
  382. package/src/adapters/pypi/package.ts +297 -0
  383. package/src/adapters/qwen/web.test.ts +176 -0
  384. package/src/adapters/qwen/web.ts +758 -0
  385. package/src/adapters/reddit/account.test.ts +56 -0
  386. package/src/adapters/reddit/account.ts +493 -0
  387. package/src/adapters/rednote/web.test.ts +354 -0
  388. package/src/adapters/rednote/web.ts +968 -0
  389. package/src/adapters/rest-countries/countries.test.ts +80 -0
  390. package/src/adapters/rest-countries/countries.ts +271 -0
  391. package/src/adapters/reuters/article-detail.test.ts +65 -0
  392. package/src/adapters/reuters/article-detail.ts +186 -0
  393. package/src/adapters/rfc/rfc.test.ts +37 -0
  394. package/src/adapters/rfc/rfc.ts +133 -0
  395. package/src/adapters/rubygems/gem.test.ts +43 -0
  396. package/src/adapters/rubygems/gem.ts +126 -0
  397. package/src/adapters/stackoverflow/questions.test.ts +207 -0
  398. package/src/adapters/stackoverflow/questions.ts +765 -0
  399. package/src/adapters/steam/app.test.ts +68 -0
  400. package/src/adapters/steam/app.ts +218 -0
  401. package/src/adapters/tiktok/creator-videos.test.ts +158 -0
  402. package/src/adapters/tiktok/creator-videos.ts +370 -0
  403. package/src/adapters/tvmaze/shows.test.ts +93 -0
  404. package/src/adapters/tvmaze/shows.ts +271 -0
  405. package/src/adapters/twitter/bookmark-folders.test.ts +164 -0
  406. package/src/adapters/twitter/bookmark-folders.ts +366 -0
  407. package/src/adapters/twitter/quote.test.ts +157 -0
  408. package/src/adapters/twitter/quote.ts +332 -0
  409. package/src/adapters/twitter/tweet-actions.test.ts +51 -0
  410. package/src/adapters/twitter/tweet-actions.ts +187 -0
  411. package/src/adapters/twitter/tweet-url.ts +65 -0
  412. package/src/adapters/uisdc/news.test.ts +46 -0
  413. package/src/adapters/uisdc/news.ts +111 -0
  414. package/src/adapters/weibo/favorites-publish.test.ts +177 -0
  415. package/src/adapters/weibo/favorites-publish.ts +426 -0
  416. package/src/adapters/wikidata/entities.test.ts +103 -0
  417. package/src/adapters/wikidata/entities.ts +253 -0
  418. package/src/adapters/wikipedia/page.test.ts +49 -0
  419. package/src/adapters/wikipedia/page.ts +158 -0
  420. package/src/adapters/wttr/weather.test.ts +99 -0
  421. package/src/adapters/wttr/weather.ts +239 -0
  422. package/src/adapters/xianyu/publish.test.ts +210 -0
  423. package/src/adapters/xianyu/publish.ts +420 -0
  424. package/src/adapters/xiaohongshu/user-helpers.ts +5 -2
  425. package/src/adapters/yuanbao/web.test.ts +144 -0
  426. package/src/adapters/yuanbao/web.ts +435 -0
  427. package/src/adapters/zhihu/collection.test.ts +96 -0
  428. package/src/adapters/zhihu/collection.ts +239 -0
  429. package/src/adapters/zlibrary/web.test.ts +104 -0
  430. package/src/adapters/zlibrary/web.ts +192 -0
@@ -0,0 +1,147 @@
1
+ /**
2
+ * @owner src/adapters/codex/projects.ts
3
+ * @does Register agent-facing Codex projects sidebar reader.
4
+ * @needs Codex Electron DOM sidebar markers, project filtering, bounded conversation flattening.
5
+ * @feeds surface coverage ledger, Codex project inventory workflows, visible thread selection context.
6
+ * @breaks Codex sidebar DOM marker drift or weak filtering can hide visible projects.
7
+ */
8
+ import { cli, Strategy } from "../../registry.js";
9
+ import { connectElectronApp } from "../_electron/shared.js";
10
+ function cleanText(value) {
11
+ return String(value ?? "")
12
+ .replace(/\s+/g, " ")
13
+ .trim();
14
+ }
15
+ function normalized(value) {
16
+ return cleanText(value).toLowerCase();
17
+ }
18
+ function matchesProject(project, query) {
19
+ const needle = normalized(query);
20
+ if (!needle)
21
+ return true;
22
+ const label = normalized(project.project);
23
+ const projectPath = normalized(project.projectPath);
24
+ return (label === needle ||
25
+ label.includes(needle) ||
26
+ projectPath === needle ||
27
+ projectPath.endsWith(`/${needle}`));
28
+ }
29
+ export function parseCodexProjectLimit(value) {
30
+ if (value === undefined || value === null || cleanText(value) === "")
31
+ return null;
32
+ const raw = cleanText(value);
33
+ if (!/^\d+$/.test(raw))
34
+ throw new Error("codex projects limit must be a positive integer.");
35
+ const n = Number.parseInt(raw, 10);
36
+ if (!Number.isSafeInteger(n) || n < 1) {
37
+ throw new Error("codex projects limit must be a positive integer.");
38
+ }
39
+ return n;
40
+ }
41
+ export function flattenCodexProjectRows(projects, options = {}) {
42
+ const limit = parseCodexProjectLimit(options.limit);
43
+ const rows = [];
44
+ for (const project of projects) {
45
+ if (!matchesProject(project, options.project))
46
+ continue;
47
+ const conversations = limit
48
+ ? project.conversations.slice(0, limit)
49
+ : project.conversations;
50
+ if (conversations.length === 0) {
51
+ rows.push({
52
+ Project: project.project,
53
+ Index: 0,
54
+ Title: project.collapsed ? "(collapsed)" : "(no visible conversations)",
55
+ Updated: "",
56
+ Active: "",
57
+ ProjectPath: project.projectPath,
58
+ ThreadId: "",
59
+ });
60
+ continue;
61
+ }
62
+ for (const conversation of conversations) {
63
+ rows.push({
64
+ Project: project.project,
65
+ Index: conversation.index,
66
+ Title: conversation.title,
67
+ Updated: conversation.updated,
68
+ Active: conversation.active ? "yes" : "",
69
+ ProjectPath: project.projectPath,
70
+ ThreadId: conversation.threadId,
71
+ });
72
+ }
73
+ }
74
+ return rows;
75
+ }
76
+ function collectCodexProjectsScript() {
77
+ return `(() => {
78
+ const projectRows = Array.from(document.querySelectorAll('[data-app-action-sidebar-project-row]'));
79
+ const visibleText = (el) => (el?.innerText || el?.textContent || '').replace(/\\s+/g, ' ').trim();
80
+ const isRelativeTime = (text) => /^(?:(?:\\d+\\s*)?(?:刚刚|秒|分钟|小时|天|周|个月|年|sec|min|hr|hour|day|week|month|year|s|m|h|d|w)|.*\\bago)$/i.test(String(text || '').trim());
81
+ const updatedText = (row, title) => {
82
+ const candidates = Array.from(row.querySelectorAll('.tabular-nums, [class*="tabular-nums"], [class*="description"]')).map(visibleText).filter(Boolean);
83
+ const direct = candidates.find(isRelativeTime);
84
+ if (direct) return direct;
85
+ const suffix = visibleText(row).replace(title, '').trim();
86
+ return isRelativeTime(suffix) ? suffix : '';
87
+ };
88
+ return projectRows.map((projectRow, projectIndex) => {
89
+ const project = projectRow.getAttribute('data-app-action-sidebar-project-label') || projectRow.getAttribute('aria-label') || visibleText(projectRow);
90
+ const projectPath = projectRow.getAttribute('data-app-action-sidebar-project-id') || '';
91
+ const projectItem = projectRow.closest('[role="listitem"][aria-label]') || projectRow.parentElement;
92
+ const threadRows = projectItem ? Array.from(projectItem.querySelectorAll('[data-app-action-sidebar-thread-row]')) : [];
93
+ return {
94
+ index: projectIndex + 1,
95
+ project,
96
+ projectPath,
97
+ collapsed: projectRow.getAttribute('data-app-action-sidebar-project-collapsed') === 'true' || projectRow.getAttribute('aria-expanded') === 'false',
98
+ conversations: threadRows.map((row, index) => {
99
+ const title = row.getAttribute('data-app-action-sidebar-thread-title') || visibleText(row);
100
+ return {
101
+ index: index + 1,
102
+ title,
103
+ updated: updatedText(row, title),
104
+ active: row.getAttribute('data-app-action-sidebar-thread-active') === 'true',
105
+ threadId: row.getAttribute('data-app-action-sidebar-thread-id') || ''
106
+ };
107
+ })
108
+ };
109
+ });
110
+ })()`;
111
+ }
112
+ cli({
113
+ site: "codex",
114
+ name: "projects",
115
+ description: "List Codex projects and visible conversations from the sidebar",
116
+ domain: "localhost",
117
+ strategy: Strategy.PUBLIC,
118
+ browser: false,
119
+ args: [
120
+ {
121
+ name: "project",
122
+ type: "str",
123
+ description: "Filter by project label or path",
124
+ },
125
+ {
126
+ name: "limit",
127
+ type: "int",
128
+ description: "Max conversations per project",
129
+ },
130
+ ],
131
+ columns: ["Project", "Index", "Title", "Updated", "Active"],
132
+ func: async (_page, kwargs) => {
133
+ const page = await connectElectronApp("codex");
134
+ const projects = (await page.evaluate(collectCodexProjectsScript()));
135
+ if (!Array.isArray(projects)) {
136
+ throw new Error("Codex sidebar project extraction returned an invalid payload.");
137
+ }
138
+ const rows = flattenCodexProjectRows(projects, kwargs);
139
+ if (rows.length === 0) {
140
+ throw new Error(kwargs.project
141
+ ? `No Codex projects matched "${String(kwargs.project)}".`
142
+ : "No Codex projects were visible.");
143
+ }
144
+ return rows;
145
+ },
146
+ });
147
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../../src/adapters/codex/projects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @owner src/adapters/coingecko/markets.ts
3
+ * @does Register agent-facing CoinGecko market, coin, exchange, derivative, category, and global commands.
4
+ * @needs Public CoinGecko API, TypeScript adapter loader, bounded market argument parsing.
5
+ * @feeds surface coverage ledger, crypto market command surface, agent-readable market rows.
6
+ * @breaks CoinGecko API drift, weak slug validation, or silent empty rows hide market data failures.
7
+ */
8
+ export declare function requireCoinGeckoCurrency(value: unknown): string;
9
+ export declare function requireCoinGeckoLimit(value: unknown, fallback: number, max: number, label?: string): number;
10
+ export declare function mapCoinRow(data: Record<string, unknown>, currency: string): Record<string, unknown>;
11
+ export declare function mapTopRows(rows: Array<Record<string, unknown>>): Array<Record<string, unknown>>;
12
+ export declare function mapTrendingRows(coins: Array<{
13
+ item?: Record<string, unknown>;
14
+ }>): Array<Record<string, unknown>>;
15
+ export declare function mapCategoryRows(rows: Array<Record<string, unknown>>, limit: number): Array<Record<string, unknown>>;
16
+ export declare function mapExchangeRows(rows: Array<Record<string, unknown>>, page: number, limit: number): Array<Record<string, unknown>>;
17
+ export declare function mapDerivativeRows(rows: Array<Record<string, unknown>>, limit: number, symbolFilter?: string): Array<Record<string, unknown>>;
18
+ export declare function mapGlobalRow(body: Record<string, unknown>, currency: string): Record<string, unknown>;
19
+ //# sourceMappingURL=markets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markets.d.ts","sourceRoot":"","sources":["../../../src/adapters/coingecko/markets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAuCH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQ/D;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,SAAU,GACd,MAAM,CASR;AAYD,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoCzB;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACnC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAYhC;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GAC/C,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAgBhC;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACpC,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAYhC;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACpC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAWhC;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACpC,KAAK,EAAE,MAAM,EACb,YAAY,SAAK,GAChB,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAyBhC;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA6BzB"}
@@ -0,0 +1,474 @@
1
+ /**
2
+ * @owner src/adapters/coingecko/markets.ts
3
+ * @does Register agent-facing CoinGecko market, coin, exchange, derivative, category, and global commands.
4
+ * @needs Public CoinGecko API, TypeScript adapter loader, bounded market argument parsing.
5
+ * @feeds surface coverage ledger, crypto market command surface, agent-readable market rows.
6
+ * @breaks CoinGecko API drift, weak slug validation, or silent empty rows hide market data failures.
7
+ */
8
+ import { cli, Strategy } from "../../registry.js";
9
+ const API_BASE = "https://api.coingecko.com/api/v3";
10
+ const CATEGORY_SORTS = new Set([
11
+ "market_cap_desc",
12
+ "market_cap_asc",
13
+ "name_desc",
14
+ "name_asc",
15
+ "market_cap_change_24h_desc",
16
+ "market_cap_change_24h_asc",
17
+ ]);
18
+ function stringField(value) {
19
+ return typeof value === "string" ? value : "";
20
+ }
21
+ function numberField(value) {
22
+ const n = typeof value === "number"
23
+ ? value
24
+ : typeof value === "string" && value.trim()
25
+ ? Number(value)
26
+ : NaN;
27
+ return Number.isFinite(n) ? n : null;
28
+ }
29
+ function slug(value, label) {
30
+ const text = String(value ?? "")
31
+ .trim()
32
+ .toLowerCase();
33
+ if (!text)
34
+ throw new Error(`coingecko ${label} cannot be empty.`);
35
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(text)) {
36
+ throw new Error(`coingecko ${label} must be a lowercase slug.`);
37
+ }
38
+ return text;
39
+ }
40
+ export function requireCoinGeckoCurrency(value) {
41
+ const currency = String(value ?? "usd")
42
+ .trim()
43
+ .toLowerCase();
44
+ if (!/^[a-z0-9-]{2,20}$/.test(currency)) {
45
+ throw new Error(`coingecko currency must look like a currency slug.`);
46
+ }
47
+ return currency;
48
+ }
49
+ export function requireCoinGeckoLimit(value, fallback, max, label = "limit") {
50
+ if (value === undefined || value === null || value === "")
51
+ return fallback;
52
+ const n = Number(value);
53
+ if (!Number.isInteger(n) || n < 1 || n > max) {
54
+ throw new Error(`coingecko ${label} must be an integer in [1, ${max}]. Got: ${String(value)}`);
55
+ }
56
+ return n;
57
+ }
58
+ function isoDate(value) {
59
+ return value ? String(value).slice(0, 10) : "";
60
+ }
61
+ function pickCurrency(map, currency) {
62
+ return map && typeof map === "object"
63
+ ? map[currency]
64
+ : null;
65
+ }
66
+ export function mapCoinRow(data, currency) {
67
+ const market = (data.market_data ?? {});
68
+ const price = pickCurrency(market.current_price, currency);
69
+ const marketCap = pickCurrency(market.market_cap, currency);
70
+ const volume24h = pickCurrency(market.total_volume, currency);
71
+ if (price == null && marketCap == null && volume24h == null) {
72
+ throw new Error(`coingecko returned no market data for currency "${currency}".`);
73
+ }
74
+ const homepage = Array.isArray(data.links?.homepage)
75
+ ? (data.links.homepage ?? []).find(Boolean)
76
+ : "";
77
+ return {
78
+ id: stringField(data.id),
79
+ symbol: stringField(data.symbol).toUpperCase(),
80
+ name: stringField(data.name),
81
+ rank: numberField(data.market_cap_rank),
82
+ price,
83
+ marketCap,
84
+ volume24h,
85
+ change24hPct: numberField(market.price_change_percentage_24h),
86
+ change7dPct: numberField(market.price_change_percentage_7d),
87
+ change30dPct: numberField(market.price_change_percentage_30d),
88
+ ath: pickCurrency(market.ath, currency),
89
+ athDate: isoDate(pickCurrency(market.ath_date, currency)),
90
+ atl: pickCurrency(market.atl, currency),
91
+ atlDate: isoDate(pickCurrency(market.atl_date, currency)),
92
+ circulatingSupply: numberField(market.circulating_supply),
93
+ totalSupply: numberField(market.total_supply),
94
+ maxSupply: numberField(market.max_supply),
95
+ genesisDate: stringField(data.genesis_date),
96
+ homepage: homepage ? String(homepage) : "",
97
+ };
98
+ }
99
+ export function mapTopRows(rows) {
100
+ return rows.map((coin) => ({
101
+ rank: numberField(coin.market_cap_rank),
102
+ symbol: stringField(coin.symbol).toUpperCase(),
103
+ name: stringField(coin.name),
104
+ price: numberField(coin.current_price),
105
+ change24hPct: numberField(coin.price_change_percentage_24h),
106
+ marketCap: numberField(coin.market_cap),
107
+ volume24h: numberField(coin.total_volume),
108
+ high24h: numberField(coin.high_24h),
109
+ low24h: numberField(coin.low_24h),
110
+ }));
111
+ }
112
+ export function mapTrendingRows(coins) {
113
+ return coins.map((entry, index) => {
114
+ const coin = entry.item ?? {};
115
+ return {
116
+ rank: index + 1,
117
+ id: stringField(coin.id),
118
+ symbol: stringField(coin.symbol).toUpperCase(),
119
+ name: stringField(coin.name),
120
+ marketCapRank: numberField(coin.market_cap_rank),
121
+ priceBtc: numberField(coin.price_btc),
122
+ thumb: stringField(coin.thumb) ||
123
+ stringField(coin.small) ||
124
+ stringField(coin.large),
125
+ };
126
+ });
127
+ }
128
+ export function mapCategoryRows(rows, limit) {
129
+ return rows.slice(0, limit).map((category, index) => ({
130
+ rank: index + 1,
131
+ id: stringField(category.id),
132
+ name: stringField(category.name),
133
+ marketCap: numberField(category.market_cap),
134
+ volume24h: numberField(category.volume_24h),
135
+ marketCapChange24hPct: numberField(category.market_cap_change_24h),
136
+ top3Coins: Array.isArray(category.top_3_coins_id)
137
+ ? category.top_3_coins_id.join(", ")
138
+ : "",
139
+ }));
140
+ }
141
+ export function mapExchangeRows(rows, page, limit) {
142
+ return rows.map((exchange, index) => ({
143
+ rank: (page - 1) * limit + index + 1,
144
+ id: stringField(exchange.id),
145
+ name: stringField(exchange.name),
146
+ trustScore: numberField(exchange.trust_score),
147
+ volume24hBtc: numberField(exchange.trade_volume_24h_btc),
148
+ country: stringField(exchange.country),
149
+ yearEstablished: numberField(exchange.year_established),
150
+ url: stringField(exchange.url),
151
+ }));
152
+ }
153
+ export function mapDerivativeRows(rows, limit, symbolFilter = "") {
154
+ const filter = symbolFilter.trim().toUpperCase();
155
+ const filtered = filter
156
+ ? rows.filter((row) => stringField(row.symbol).toUpperCase().includes(filter) ||
157
+ stringField(row.index_id).toUpperCase().includes(filter))
158
+ : rows;
159
+ if (filtered.length === 0) {
160
+ throw new Error(`No derivative tickers matched symbol="${filter}".`);
161
+ }
162
+ return filtered.slice(0, limit).map((row, index) => ({
163
+ rank: index + 1,
164
+ market: stringField(row.market),
165
+ symbol: stringField(row.symbol),
166
+ indexId: stringField(row.index_id),
167
+ contractType: stringField(row.contract_type),
168
+ price: numberField(row.price),
169
+ change24hPct: numberField(row.price_percentage_change_24h),
170
+ fundingRate: numberField(row.funding_rate),
171
+ openInterestUsd: numberField(row.open_interest),
172
+ volume24hUsd: numberField(row.volume_24h),
173
+ expired: row.expired_at ? String(row.expired_at) : "",
174
+ }));
175
+ }
176
+ export function mapGlobalRow(body, currency) {
177
+ const data = (body.data ?? {});
178
+ const totalMarketCap = pickCurrency(data.total_market_cap, currency);
179
+ const totalVolume = pickCurrency(data.total_volume, currency);
180
+ if (totalMarketCap == null && totalVolume == null) {
181
+ throw new Error(`coingecko has no market totals for currency "${currency}".`);
182
+ }
183
+ const dominance = (data.market_cap_percentage ?? {});
184
+ return {
185
+ currency: currency.toUpperCase(),
186
+ totalMarketCap: numberField(totalMarketCap),
187
+ totalVolume24h: numberField(totalVolume),
188
+ marketCapChange24hPct: numberField(data.market_cap_change_percentage_24h_usd),
189
+ btcDominancePct: numberField(dominance.btc),
190
+ ethDominancePct: numberField(dominance.eth),
191
+ activeCryptocurrencies: numberField(data.active_cryptocurrencies),
192
+ markets: numberField(data.markets),
193
+ ongoingIcos: numberField(data.ongoing_icos),
194
+ updatedAt: data.updated_at
195
+ ? new Date(Number(data.updated_at) * 1000).toISOString()
196
+ : "",
197
+ };
198
+ }
199
+ async function fetchJson(url, label) {
200
+ const response = await fetch(url, {
201
+ headers: { "User-Agent": "unicli (https://github.com/olo-dot-io/Uni-CLI)" },
202
+ });
203
+ if (response.status === 404)
204
+ throw new Error(`${label} returned no result.`);
205
+ if (response.status === 429)
206
+ throw new Error(`${label} returned HTTP 429.`);
207
+ if (!response.ok)
208
+ throw new Error(`${label} returned HTTP ${response.status}.`);
209
+ return response.json();
210
+ }
211
+ cli({
212
+ site: "coingecko",
213
+ name: "coin",
214
+ description: "Fetch a single cryptocurrency's market data by CoinGecko id",
215
+ domain: "api.coingecko.com",
216
+ strategy: Strategy.PUBLIC,
217
+ args: [
218
+ {
219
+ name: "id",
220
+ type: "str",
221
+ required: true,
222
+ positional: true,
223
+ description: "CoinGecko coin id",
224
+ },
225
+ {
226
+ name: "currency",
227
+ type: "str",
228
+ default: "usd",
229
+ description: "Quote currency",
230
+ },
231
+ ],
232
+ columns: [
233
+ "id",
234
+ "symbol",
235
+ "name",
236
+ "rank",
237
+ "price",
238
+ "marketCap",
239
+ "volume24h",
240
+ "change24hPct",
241
+ "change7dPct",
242
+ "change30dPct",
243
+ "ath",
244
+ "athDate",
245
+ "atl",
246
+ "atlDate",
247
+ "circulatingSupply",
248
+ "totalSupply",
249
+ "maxSupply",
250
+ "genesisDate",
251
+ "homepage",
252
+ ],
253
+ func: async (_page, kwargs) => {
254
+ const id = slug(kwargs.id, "coin id");
255
+ const currency = requireCoinGeckoCurrency(kwargs.currency);
256
+ const url = new URL(`${API_BASE}/coins/${id}`);
257
+ url.searchParams.set("localization", "false");
258
+ url.searchParams.set("tickers", "false");
259
+ url.searchParams.set("market_data", "true");
260
+ url.searchParams.set("community_data", "false");
261
+ url.searchParams.set("developer_data", "false");
262
+ url.searchParams.set("sparkline", "false");
263
+ return [
264
+ mapCoinRow((await fetchJson(url, "coingecko coin")), currency),
265
+ ];
266
+ },
267
+ });
268
+ cli({
269
+ site: "coingecko",
270
+ name: "top",
271
+ description: "Top coins by market cap",
272
+ domain: "api.coingecko.com",
273
+ strategy: Strategy.PUBLIC,
274
+ args: [
275
+ {
276
+ name: "currency",
277
+ type: "str",
278
+ default: "usd",
279
+ description: "Quote currency",
280
+ },
281
+ { name: "limit", type: "int", default: 10, description: "Number of coins" },
282
+ ],
283
+ columns: [
284
+ "rank",
285
+ "symbol",
286
+ "name",
287
+ "price",
288
+ "change24hPct",
289
+ "marketCap",
290
+ "volume24h",
291
+ "high24h",
292
+ "low24h",
293
+ ],
294
+ func: async (_page, kwargs) => {
295
+ const currency = requireCoinGeckoCurrency(kwargs.currency);
296
+ const limit = requireCoinGeckoLimit(kwargs.limit, 10, 250);
297
+ const url = new URL(`${API_BASE}/coins/markets`);
298
+ url.searchParams.set("vs_currency", currency);
299
+ url.searchParams.set("order", "market_cap_desc");
300
+ url.searchParams.set("per_page", String(limit));
301
+ url.searchParams.set("page", "1");
302
+ url.searchParams.set("sparkline", "false");
303
+ const rows = mapTopRows((await fetchJson(url, "coingecko top")));
304
+ if (rows.length === 0)
305
+ throw new Error("coingecko returned no market data.");
306
+ return rows;
307
+ },
308
+ });
309
+ cli({
310
+ site: "coingecko",
311
+ name: "trending",
312
+ description: "Top trending cryptocurrencies on CoinGecko",
313
+ domain: "api.coingecko.com",
314
+ strategy: Strategy.PUBLIC,
315
+ args: [],
316
+ columns: [
317
+ "rank",
318
+ "id",
319
+ "symbol",
320
+ "name",
321
+ "marketCapRank",
322
+ "priceBtc",
323
+ "thumb",
324
+ ],
325
+ func: async () => {
326
+ const body = (await fetchJson(`${API_BASE}/search/trending`, "coingecko trending"));
327
+ const rows = mapTrendingRows(Array.isArray(body.coins) ? body.coins : []);
328
+ if (rows.length === 0)
329
+ throw new Error("coingecko returned no trending coins.");
330
+ return rows;
331
+ },
332
+ });
333
+ cli({
334
+ site: "coingecko",
335
+ name: "categories",
336
+ description: "Crypto categories ranked by aggregated market cap",
337
+ domain: "api.coingecko.com",
338
+ strategy: Strategy.PUBLIC,
339
+ args: [
340
+ {
341
+ name: "sort",
342
+ type: "str",
343
+ default: "market_cap_desc",
344
+ description: "Sort order",
345
+ },
346
+ {
347
+ name: "limit",
348
+ type: "int",
349
+ default: 20,
350
+ description: "Number of categories",
351
+ },
352
+ ],
353
+ columns: [
354
+ "rank",
355
+ "id",
356
+ "name",
357
+ "marketCap",
358
+ "volume24h",
359
+ "marketCapChange24hPct",
360
+ "top3Coins",
361
+ ],
362
+ func: async (_page, kwargs) => {
363
+ const sort = String(kwargs.sort ?? "market_cap_desc")
364
+ .trim()
365
+ .toLowerCase();
366
+ if (!CATEGORY_SORTS.has(sort))
367
+ throw new Error(`coingecko sort "${String(kwargs.sort)}" is not supported.`);
368
+ const limit = requireCoinGeckoLimit(kwargs.limit, 20, 100);
369
+ const rows = mapCategoryRows((await fetchJson(`${API_BASE}/coins/categories?order=${encodeURIComponent(sort)}`, "coingecko categories")), limit);
370
+ if (rows.length === 0)
371
+ throw new Error("CoinGecko returned no category data.");
372
+ return rows;
373
+ },
374
+ });
375
+ cli({
376
+ site: "coingecko",
377
+ name: "exchanges",
378
+ description: "Top crypto exchanges by 24h BTC trading volume",
379
+ domain: "api.coingecko.com",
380
+ strategy: Strategy.PUBLIC,
381
+ args: [
382
+ {
383
+ name: "limit",
384
+ type: "int",
385
+ default: 20,
386
+ description: "Number of exchanges",
387
+ },
388
+ { name: "page", type: "int", default: 1, description: "Page number" },
389
+ ],
390
+ columns: [
391
+ "rank",
392
+ "id",
393
+ "name",
394
+ "trustScore",
395
+ "volume24hBtc",
396
+ "country",
397
+ "yearEstablished",
398
+ "url",
399
+ ],
400
+ func: async (_page, kwargs) => {
401
+ const limit = requireCoinGeckoLimit(kwargs.limit, 20, 250);
402
+ const page = requireCoinGeckoLimit(kwargs.page, 1, 10_000, "page");
403
+ const url = new URL(`${API_BASE}/exchanges`);
404
+ url.searchParams.set("per_page", String(limit));
405
+ url.searchParams.set("page", String(page));
406
+ const rows = mapExchangeRows((await fetchJson(url, "coingecko exchanges")), page, limit);
407
+ if (rows.length === 0)
408
+ throw new Error("CoinGecko returned no exchange data.");
409
+ return rows;
410
+ },
411
+ });
412
+ cli({
413
+ site: "coingecko",
414
+ name: "derivatives",
415
+ description: "Top crypto derivative markets by 24h volume",
416
+ domain: "api.coingecko.com",
417
+ strategy: Strategy.PUBLIC,
418
+ args: [
419
+ { name: "limit", type: "int", default: 20, description: "Max rows" },
420
+ {
421
+ name: "symbol",
422
+ type: "str",
423
+ description: "Optional symbol substring filter",
424
+ },
425
+ ],
426
+ columns: [
427
+ "rank",
428
+ "market",
429
+ "symbol",
430
+ "indexId",
431
+ "contractType",
432
+ "price",
433
+ "change24hPct",
434
+ "fundingRate",
435
+ "openInterestUsd",
436
+ "volume24hUsd",
437
+ "expired",
438
+ ],
439
+ func: async (_page, kwargs) => {
440
+ const limit = requireCoinGeckoLimit(kwargs.limit, 20, 500);
441
+ return mapDerivativeRows((await fetchJson(`${API_BASE}/derivatives`, "coingecko derivatives")), limit, String(kwargs.symbol ?? ""));
442
+ },
443
+ });
444
+ cli({
445
+ site: "coingecko",
446
+ name: "global",
447
+ description: "Aggregate crypto market stats",
448
+ domain: "api.coingecko.com",
449
+ strategy: Strategy.PUBLIC,
450
+ args: [
451
+ {
452
+ name: "currency",
453
+ type: "str",
454
+ default: "usd",
455
+ description: "Quote currency",
456
+ },
457
+ ],
458
+ columns: [
459
+ "currency",
460
+ "totalMarketCap",
461
+ "totalVolume24h",
462
+ "marketCapChange24hPct",
463
+ "btcDominancePct",
464
+ "ethDominancePct",
465
+ "activeCryptocurrencies",
466
+ "markets",
467
+ "ongoingIcos",
468
+ "updatedAt",
469
+ ],
470
+ func: async (_page, kwargs) => [
471
+ mapGlobalRow((await fetchJson(`${API_BASE}/global`, "coingecko global")), requireCoinGeckoCurrency(kwargs.currency)),
472
+ ],
473
+ });
474
+ //# sourceMappingURL=markets.js.map