@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.
- package/AGENTS.md +9 -9
- package/README.md +55 -249
- package/README.zh-CN.md +55 -249
- package/dist/adapters/1point3acres/forum.d.ts +58 -0
- package/dist/adapters/1point3acres/forum.d.ts.map +1 -0
- package/dist/adapters/1point3acres/forum.js +708 -0
- package/dist/adapters/1point3acres/forum.js.map +1 -0
- package/dist/adapters/aibase/news.d.ts +21 -0
- package/dist/adapters/aibase/news.d.ts.map +1 -0
- package/dist/adapters/aibase/news.js +96 -0
- package/dist/adapters/aibase/news.js.map +1 -0
- package/dist/adapters/arxiv/papers.d.ts +27 -0
- package/dist/adapters/arxiv/papers.d.ts.map +1 -0
- package/dist/adapters/arxiv/papers.js +193 -0
- package/dist/adapters/arxiv/papers.js.map +1 -0
- package/dist/adapters/bbc/topic.d.ts +24 -0
- package/dist/adapters/bbc/topic.d.ts.map +1 -0
- package/dist/adapters/bbc/topic.js +122 -0
- package/dist/adapters/bbc/topic.js.map +1 -0
- package/dist/adapters/chatgpt/web.d.ts +24 -0
- package/dist/adapters/chatgpt/web.d.ts.map +1 -0
- package/dist/adapters/chatgpt/web.js +242 -0
- package/dist/adapters/chatgpt/web.js.map +1 -0
- package/dist/adapters/claude/web.d.ts +24 -0
- package/dist/adapters/claude/web.d.ts.map +1 -0
- package/dist/adapters/claude/web.js +575 -0
- package/dist/adapters/claude/web.js.map +1 -0
- package/dist/adapters/codex/projects.d.ts +27 -0
- package/dist/adapters/codex/projects.d.ts.map +1 -0
- package/dist/adapters/codex/projects.js +147 -0
- package/dist/adapters/codex/projects.js.map +1 -0
- package/dist/adapters/coingecko/markets.d.ts +19 -0
- package/dist/adapters/coingecko/markets.d.ts.map +1 -0
- package/dist/adapters/coingecko/markets.js +474 -0
- package/dist/adapters/coingecko/markets.js.map +1 -0
- package/dist/adapters/coupang/product.d.ts +27 -0
- package/dist/adapters/coupang/product.d.ts.map +1 -0
- package/dist/adapters/coupang/product.js +211 -0
- package/dist/adapters/coupang/product.js.map +1 -0
- package/dist/adapters/crates/registry.d.ts +44 -0
- package/dist/adapters/crates/registry.d.ts.map +1 -0
- package/dist/adapters/crates/registry.js +186 -0
- package/dist/adapters/crates/registry.js.map +1 -0
- package/dist/adapters/ctrip/travel.d.ts +83 -0
- package/dist/adapters/ctrip/travel.d.ts.map +1 -0
- package/dist/adapters/ctrip/travel.js +630 -0
- package/dist/adapters/ctrip/travel.js.map +1 -0
- package/dist/adapters/dblp/publications.d.ts +41 -0
- package/dist/adapters/dblp/publications.d.ts.map +1 -0
- package/dist/adapters/dblp/publications.js +409 -0
- package/dist/adapters/dblp/publications.js.map +1 -0
- package/dist/adapters/deepseek/web.d.ts +1 -1
- package/dist/adapters/deepseek/web.d.ts.map +1 -1
- package/dist/adapters/deepseek/web.js +66 -1
- package/dist/adapters/deepseek/web.js.map +1 -1
- package/dist/adapters/defillama/protocols.d.ts +13 -0
- package/dist/adapters/defillama/protocols.d.ts.map +1 -0
- package/dist/adapters/defillama/protocols.js +218 -0
- package/dist/adapters/defillama/protocols.js.map +1 -0
- package/dist/adapters/devto/read.d.ts +26 -0
- package/dist/adapters/devto/read.d.ts.map +1 -0
- package/dist/adapters/devto/read.js +110 -0
- package/dist/adapters/devto/read.js.map +1 -0
- package/dist/adapters/dianping/shop.d.ts +38 -0
- package/dist/adapters/dianping/shop.d.ts.map +1 -0
- package/dist/adapters/dianping/shop.js +194 -0
- package/dist/adapters/dianping/shop.js.map +1 -0
- package/dist/adapters/dockerhub/registry.d.ts +36 -0
- package/dist/adapters/dockerhub/registry.d.ts.map +1 -0
- package/dist/adapters/dockerhub/registry.js +172 -0
- package/dist/adapters/dockerhub/registry.js.map +1 -0
- package/dist/adapters/endoflife/product.d.ts +11 -0
- package/dist/adapters/endoflife/product.d.ts.map +1 -0
- package/dist/adapters/endoflife/product.js +113 -0
- package/dist/adapters/endoflife/product.js.map +1 -0
- package/dist/adapters/facebook/marketplace-extra.d.ts +9 -0
- package/dist/adapters/facebook/marketplace-extra.d.ts.map +1 -0
- package/dist/adapters/facebook/marketplace-extra.js +170 -0
- package/dist/adapters/facebook/marketplace-extra.js.map +1 -0
- package/dist/adapters/flathub/apps.d.ts +17 -0
- package/dist/adapters/flathub/apps.d.ts.map +1 -0
- package/dist/adapters/flathub/apps.js +220 -0
- package/dist/adapters/flathub/apps.js.map +1 -0
- package/dist/adapters/goproxy/module.d.ts +24 -0
- package/dist/adapters/goproxy/module.d.ts.map +1 -0
- package/dist/adapters/goproxy/module.js +221 -0
- package/dist/adapters/goproxy/module.js.map +1 -0
- package/dist/adapters/grok/web.d.ts +29 -0
- package/dist/adapters/grok/web.d.ts.map +1 -0
- package/dist/adapters/grok/web.js +553 -0
- package/dist/adapters/grok/web.js.map +1 -0
- package/dist/adapters/hackernews/read.d.ts +31 -0
- package/dist/adapters/hackernews/read.d.ts.map +1 -0
- package/dist/adapters/hackernews/read.js +201 -0
- package/dist/adapters/hackernews/read.js.map +1 -0
- package/dist/adapters/hf/paper.d.ts +22 -0
- package/dist/adapters/hf/paper.d.ts.map +1 -0
- package/dist/adapters/hf/paper.js +112 -0
- package/dist/adapters/hf/paper.js.map +1 -0
- package/dist/adapters/homebrew/packages.d.ts +52 -0
- package/dist/adapters/homebrew/packages.d.ts.map +1 -0
- package/dist/adapters/homebrew/packages.js +240 -0
- package/dist/adapters/homebrew/packages.js.map +1 -0
- package/dist/adapters/indeed/jobs.d.ts +38 -0
- package/dist/adapters/indeed/jobs.d.ts.map +1 -0
- package/dist/adapters/indeed/jobs.js +300 -0
- package/dist/adapters/indeed/jobs.js.map +1 -0
- package/dist/adapters/instagram/collections.d.ts +9 -0
- package/dist/adapters/instagram/collections.d.ts.map +1 -0
- package/dist/adapters/instagram/collections.js +174 -0
- package/dist/adapters/instagram/collections.js.map +1 -0
- package/dist/adapters/lichess/players.d.ts +46 -0
- package/dist/adapters/lichess/players.d.ts.map +1 -0
- package/dist/adapters/lichess/players.js +221 -0
- package/dist/adapters/lichess/players.js.map +1 -0
- package/dist/adapters/lobsters/read-domain.d.ts +35 -0
- package/dist/adapters/lobsters/read-domain.d.ts.map +1 -0
- package/dist/adapters/lobsters/read-domain.js +306 -0
- package/dist/adapters/lobsters/read-domain.js.map +1 -0
- package/dist/adapters/maven/artifact.d.ts +30 -0
- package/dist/adapters/maven/artifact.d.ts.map +1 -0
- package/dist/adapters/maven/artifact.js +121 -0
- package/dist/adapters/maven/artifact.js.map +1 -0
- package/dist/adapters/mdn/search.d.ts +11 -0
- package/dist/adapters/mdn/search.d.ts.map +1 -0
- package/dist/adapters/mdn/search.js +115 -0
- package/dist/adapters/mdn/search.js.map +1 -0
- package/dist/adapters/medium/tag.d.ts +15 -0
- package/dist/adapters/medium/tag.d.ts.map +1 -0
- package/dist/adapters/medium/tag.js +148 -0
- package/dist/adapters/medium/tag.js.map +1 -0
- package/dist/adapters/npm/package.d.ts +32 -0
- package/dist/adapters/npm/package.d.ts.map +1 -0
- package/dist/adapters/npm/package.js +141 -0
- package/dist/adapters/npm/package.js.map +1 -0
- package/dist/adapters/nuget/package.d.ts +34 -0
- package/dist/adapters/nuget/package.d.ts.map +1 -0
- package/dist/adapters/nuget/package.js +135 -0
- package/dist/adapters/nuget/package.js.map +1 -0
- package/dist/adapters/nvd/cve.d.ts +42 -0
- package/dist/adapters/nvd/cve.d.ts.map +1 -0
- package/dist/adapters/nvd/cve.js +132 -0
- package/dist/adapters/nvd/cve.js.map +1 -0
- package/dist/adapters/oeis/sequences.d.ts +14 -0
- package/dist/adapters/oeis/sequences.d.ts.map +1 -0
- package/dist/adapters/oeis/sequences.js +219 -0
- package/dist/adapters/oeis/sequences.js.map +1 -0
- package/dist/adapters/openalex/works.d.ts +43 -0
- package/dist/adapters/openalex/works.d.ts.map +1 -0
- package/dist/adapters/openalex/works.js +267 -0
- package/dist/adapters/openalex/works.js.map +1 -0
- package/dist/adapters/openfda/records.d.ts +18 -0
- package/dist/adapters/openfda/records.d.ts.map +1 -0
- package/dist/adapters/openfda/records.js +209 -0
- package/dist/adapters/openfda/records.js.map +1 -0
- package/dist/adapters/openreview/papers.d.ts +34 -0
- package/dist/adapters/openreview/papers.d.ts.map +1 -0
- package/dist/adapters/openreview/papers.js +463 -0
- package/dist/adapters/openreview/papers.js.map +1 -0
- package/dist/adapters/osv/security.d.ts +36 -0
- package/dist/adapters/osv/security.d.ts.map +1 -0
- package/dist/adapters/osv/security.js +247 -0
- package/dist/adapters/osv/security.js.map +1 -0
- package/dist/adapters/packagist/package.d.ts +31 -0
- package/dist/adapters/packagist/package.d.ts.map +1 -0
- package/dist/adapters/packagist/package.js +108 -0
- package/dist/adapters/packagist/package.js.map +1 -0
- package/dist/adapters/pubmed/articles.d.ts +31 -0
- package/dist/adapters/pubmed/articles.d.ts.map +1 -0
- package/dist/adapters/pubmed/articles.js +385 -0
- package/dist/adapters/pubmed/articles.js.map +1 -0
- package/dist/adapters/pypi/package.d.ts +38 -0
- package/dist/adapters/pypi/package.d.ts.map +1 -0
- package/dist/adapters/pypi/package.js +235 -0
- package/dist/adapters/pypi/package.js.map +1 -0
- package/dist/adapters/qwen/web.d.ts +26 -0
- package/dist/adapters/qwen/web.d.ts.map +1 -0
- package/dist/adapters/qwen/web.js +672 -0
- package/dist/adapters/qwen/web.js.map +1 -0
- package/dist/adapters/reddit/account.d.ts +12 -0
- package/dist/adapters/reddit/account.d.ts.map +1 -0
- package/dist/adapters/reddit/account.js +409 -0
- package/dist/adapters/reddit/account.js.map +1 -0
- package/dist/adapters/rednote/web.d.ts +30 -0
- package/dist/adapters/rednote/web.d.ts.map +1 -0
- package/dist/adapters/rednote/web.js +858 -0
- package/dist/adapters/rednote/web.js.map +1 -0
- package/dist/adapters/rest-countries/countries.d.ts +14 -0
- package/dist/adapters/rest-countries/countries.d.ts.map +1 -0
- package/dist/adapters/rest-countries/countries.js +231 -0
- package/dist/adapters/rest-countries/countries.js.map +1 -0
- package/dist/adapters/reuters/article-detail.d.ts +37 -0
- package/dist/adapters/reuters/article-detail.d.ts.map +1 -0
- package/dist/adapters/reuters/article-detail.js +139 -0
- package/dist/adapters/reuters/article-detail.js.map +1 -0
- package/dist/adapters/rfc/rfc.d.ts +11 -0
- package/dist/adapters/rfc/rfc.d.ts.map +1 -0
- package/dist/adapters/rfc/rfc.js +121 -0
- package/dist/adapters/rfc/rfc.js.map +1 -0
- package/dist/adapters/rubygems/gem.d.ts +26 -0
- package/dist/adapters/rubygems/gem.d.ts.map +1 -0
- package/dist/adapters/rubygems/gem.js +96 -0
- package/dist/adapters/rubygems/gem.js.map +1 -0
- package/dist/adapters/stackoverflow/questions.d.ts +79 -0
- package/dist/adapters/stackoverflow/questions.d.ts.map +1 -0
- package/dist/adapters/stackoverflow/questions.js +504 -0
- package/dist/adapters/stackoverflow/questions.js.map +1 -0
- package/dist/adapters/steam/app.d.ts +39 -0
- package/dist/adapters/steam/app.d.ts.map +1 -0
- package/dist/adapters/steam/app.js +165 -0
- package/dist/adapters/steam/app.js.map +1 -0
- package/dist/adapters/tiktok/creator-videos.d.ts +52 -0
- package/dist/adapters/tiktok/creator-videos.d.ts.map +1 -0
- package/dist/adapters/tiktok/creator-videos.js +267 -0
- package/dist/adapters/tiktok/creator-videos.js.map +1 -0
- package/dist/adapters/tvmaze/shows.d.ts +13 -0
- package/dist/adapters/tvmaze/shows.d.ts.map +1 -0
- package/dist/adapters/tvmaze/shows.js +240 -0
- package/dist/adapters/tvmaze/shows.js.map +1 -0
- package/dist/adapters/twitter/bookmark-folders.d.ts +33 -0
- package/dist/adapters/twitter/bookmark-folders.d.ts.map +1 -0
- package/dist/adapters/twitter/bookmark-folders.js +290 -0
- package/dist/adapters/twitter/bookmark-folders.js.map +1 -0
- package/dist/adapters/twitter/quote.d.ts +18 -0
- package/dist/adapters/twitter/quote.d.ts.map +1 -0
- package/dist/adapters/twitter/quote.js +285 -0
- package/dist/adapters/twitter/quote.js.map +1 -0
- package/dist/adapters/twitter/tweet-actions.d.ts +12 -0
- package/dist/adapters/twitter/tweet-actions.d.ts.map +1 -0
- package/dist/adapters/twitter/tweet-actions.js +145 -0
- package/dist/adapters/twitter/tweet-actions.js.map +1 -0
- package/dist/adapters/twitter/tweet-url.d.ts +15 -0
- package/dist/adapters/twitter/tweet-url.d.ts.map +1 -0
- package/dist/adapters/twitter/tweet-url.js +57 -0
- package/dist/adapters/twitter/tweet-url.js.map +1 -0
- package/dist/adapters/uisdc/news.d.ts +22 -0
- package/dist/adapters/uisdc/news.d.ts.map +1 -0
- package/dist/adapters/uisdc/news.js +91 -0
- package/dist/adapters/uisdc/news.js.map +1 -0
- package/dist/adapters/weibo/favorites-publish.d.ts +28 -0
- package/dist/adapters/weibo/favorites-publish.d.ts.map +1 -0
- package/dist/adapters/weibo/favorites-publish.js +356 -0
- package/dist/adapters/weibo/favorites-publish.js.map +1 -0
- package/dist/adapters/wikidata/entities.d.ts +15 -0
- package/dist/adapters/wikidata/entities.d.ts.map +1 -0
- package/dist/adapters/wikidata/entities.js +219 -0
- package/dist/adapters/wikidata/entities.js.map +1 -0
- package/dist/adapters/wikipedia/page.d.ts +21 -0
- package/dist/adapters/wikipedia/page.d.ts.map +1 -0
- package/dist/adapters/wikipedia/page.js +116 -0
- package/dist/adapters/wikipedia/page.js.map +1 -0
- package/dist/adapters/wttr/weather.d.ts +12 -0
- package/dist/adapters/wttr/weather.d.ts.map +1 -0
- package/dist/adapters/wttr/weather.js +207 -0
- package/dist/adapters/wttr/weather.js.map +1 -0
- package/dist/adapters/xianyu/publish.d.ts +31 -0
- package/dist/adapters/xianyu/publish.d.ts.map +1 -0
- package/dist/adapters/xianyu/publish.js +349 -0
- package/dist/adapters/xianyu/publish.js.map +1 -0
- package/dist/adapters/xiaohongshu/user-helpers.d.ts +2 -2
- package/dist/adapters/xiaohongshu/user-helpers.d.ts.map +1 -1
- package/dist/adapters/xiaohongshu/user-helpers.js +5 -4
- package/dist/adapters/xiaohongshu/user-helpers.js.map +1 -1
- package/dist/adapters/yuanbao/web.d.ts +27 -0
- package/dist/adapters/yuanbao/web.d.ts.map +1 -0
- package/dist/adapters/yuanbao/web.js +365 -0
- package/dist/adapters/yuanbao/web.js.map +1 -0
- package/dist/adapters/zhihu/collection.d.ts +33 -0
- package/dist/adapters/zhihu/collection.d.ts.map +1 -0
- package/dist/adapters/zhihu/collection.js +185 -0
- package/dist/adapters/zhihu/collection.js.map +1 -0
- package/dist/adapters/zlibrary/web.d.ts +19 -0
- package/dist/adapters/zlibrary/web.d.ts.map +1 -0
- package/dist/adapters/zlibrary/web.js +153 -0
- package/dist/adapters/zlibrary/web.js.map +1 -0
- package/dist/browser/daemon-client.js +2 -2
- package/dist/browser/daemon-client.js.map +1 -1
- package/dist/discovery/macos-dynamic.d.ts.map +1 -1
- package/dist/discovery/macos-dynamic.js +17 -3
- package/dist/discovery/macos-dynamic.js.map +1 -1
- package/dist/manifest-compact.txt +10 -10
- package/dist/manifest-search.json +1 -1
- package/dist/manifest.json +5130 -112
- package/dist/transport/refs.d.ts +5 -3
- package/dist/transport/refs.d.ts.map +1 -1
- package/dist/transport/refs.js +8 -1
- package/dist/transport/refs.js.map +1 -1
- package/dist/transport/sidecar-binary.d.ts +7 -0
- package/dist/transport/sidecar-binary.d.ts.map +1 -1
- package/dist/transport/sidecar-binary.js +28 -8
- package/dist/transport/sidecar-binary.js.map +1 -1
- package/package.json +4 -3
- package/server.json +3 -3
- package/skills/unicli/SKILL.md +1 -1
- package/skills/unicli-claude-code/SKILL.md +1 -1
- package/skills/unicli-hermes/SKILL.md +1 -1
- package/src/adapters/1point3acres/forum.test.ts +300 -0
- package/src/adapters/1point3acres/forum.ts +852 -0
- package/src/adapters/aibase/news.test.ts +42 -0
- package/src/adapters/aibase/news.ts +118 -0
- package/src/adapters/arxiv/papers.test.ts +59 -0
- package/src/adapters/arxiv/papers.ts +226 -0
- package/src/adapters/bbc/topic.test.ts +52 -0
- package/src/adapters/bbc/topic.ts +149 -0
- package/src/adapters/chatgpt/web.test.ts +121 -0
- package/src/adapters/chatgpt/web.ts +286 -0
- package/src/adapters/claude/web.test.ts +206 -0
- package/src/adapters/claude/web.ts +684 -0
- package/src/adapters/codex/projects.test.ts +77 -0
- package/src/adapters/codex/projects.ts +178 -0
- package/src/adapters/coingecko/markets.test.ts +156 -0
- package/src/adapters/coingecko/markets.ts +574 -0
- package/src/adapters/coupang/product.test.ts +111 -0
- package/src/adapters/coupang/product.ts +256 -0
- package/src/adapters/crates/registry.test.ts +89 -0
- package/src/adapters/crates/registry.ts +247 -0
- package/src/adapters/ctrip/travel.test.ts +359 -0
- package/src/adapters/ctrip/travel.ts +792 -0
- package/src/adapters/dblp/publications.test.ts +123 -0
- package/src/adapters/dblp/publications.ts +494 -0
- package/src/adapters/deepseek/web.test.ts +69 -0
- package/src/adapters/deepseek/web.ts +78 -1
- package/src/adapters/defillama/protocols.test.ts +75 -0
- package/src/adapters/defillama/protocols.ts +253 -0
- package/src/adapters/devto/read.test.ts +49 -0
- package/src/adapters/devto/read.ts +145 -0
- package/src/adapters/dianping/shop.test.ts +134 -0
- package/src/adapters/dianping/shop.ts +261 -0
- package/src/adapters/dockerhub/registry.test.ts +97 -0
- package/src/adapters/dockerhub/registry.ts +223 -0
- package/src/adapters/endoflife/product.test.ts +50 -0
- package/src/adapters/endoflife/product.ts +128 -0
- package/src/adapters/facebook/marketplace-extra.test.ts +132 -0
- package/src/adapters/facebook/marketplace-extra.ts +213 -0
- package/src/adapters/flathub/apps.test.ts +85 -0
- package/src/adapters/flathub/apps.ts +254 -0
- package/src/adapters/goproxy/module.test.ts +72 -0
- package/src/adapters/goproxy/module.ts +258 -0
- package/src/adapters/grok/web.test.ts +181 -0
- package/src/adapters/grok/web.ts +640 -0
- package/src/adapters/hackernews/read.test.ts +68 -0
- package/src/adapters/hackernews/read.ts +265 -0
- package/src/adapters/hf/paper.test.ts +48 -0
- package/src/adapters/hf/paper.ts +138 -0
- package/src/adapters/homebrew/packages.test.ts +109 -0
- package/src/adapters/homebrew/packages.ts +304 -0
- package/src/adapters/indeed/jobs.test.ts +230 -0
- package/src/adapters/indeed/jobs.ts +375 -0
- package/src/adapters/instagram/collections.test.ts +94 -0
- package/src/adapters/instagram/collections.ts +206 -0
- package/src/adapters/lichess/players.test.ts +99 -0
- package/src/adapters/lichess/players.ts +277 -0
- package/src/adapters/lobsters/read-domain.test.ts +121 -0
- package/src/adapters/lobsters/read-domain.ts +400 -0
- package/src/adapters/maven/artifact.test.ts +67 -0
- package/src/adapters/maven/artifact.ts +155 -0
- package/src/adapters/mdn/search.test.ts +39 -0
- package/src/adapters/mdn/search.ts +133 -0
- package/src/adapters/medium/tag.test.ts +64 -0
- package/src/adapters/medium/tag.ts +164 -0
- package/src/adapters/npm/package.test.ts +53 -0
- package/src/adapters/npm/package.ts +177 -0
- package/src/adapters/nuget/package.test.ts +102 -0
- package/src/adapters/nuget/package.ts +193 -0
- package/src/adapters/nvd/cve.test.ts +66 -0
- package/src/adapters/nvd/cve.ts +182 -0
- package/src/adapters/oeis/sequences.test.ts +71 -0
- package/src/adapters/oeis/sequences.ts +234 -0
- package/src/adapters/openalex/works.test.ts +99 -0
- package/src/adapters/openalex/works.ts +319 -0
- package/src/adapters/openfda/records.test.ts +90 -0
- package/src/adapters/openfda/records.ts +239 -0
- package/src/adapters/openreview/papers.test.ts +139 -0
- package/src/adapters/openreview/papers.ts +560 -0
- package/src/adapters/osv/security.test.ts +91 -0
- package/src/adapters/osv/security.ts +298 -0
- package/src/adapters/packagist/package.test.ts +62 -0
- package/src/adapters/packagist/package.ts +146 -0
- package/src/adapters/pubmed/articles.test.ts +96 -0
- package/src/adapters/pubmed/articles.ts +497 -0
- package/src/adapters/pypi/package.test.ts +131 -0
- package/src/adapters/pypi/package.ts +297 -0
- package/src/adapters/qwen/web.test.ts +176 -0
- package/src/adapters/qwen/web.ts +758 -0
- package/src/adapters/reddit/account.test.ts +56 -0
- package/src/adapters/reddit/account.ts +493 -0
- package/src/adapters/rednote/web.test.ts +354 -0
- package/src/adapters/rednote/web.ts +968 -0
- package/src/adapters/rest-countries/countries.test.ts +80 -0
- package/src/adapters/rest-countries/countries.ts +271 -0
- package/src/adapters/reuters/article-detail.test.ts +65 -0
- package/src/adapters/reuters/article-detail.ts +186 -0
- package/src/adapters/rfc/rfc.test.ts +37 -0
- package/src/adapters/rfc/rfc.ts +133 -0
- package/src/adapters/rubygems/gem.test.ts +43 -0
- package/src/adapters/rubygems/gem.ts +126 -0
- package/src/adapters/stackoverflow/questions.test.ts +207 -0
- package/src/adapters/stackoverflow/questions.ts +765 -0
- package/src/adapters/steam/app.test.ts +68 -0
- package/src/adapters/steam/app.ts +218 -0
- package/src/adapters/tiktok/creator-videos.test.ts +158 -0
- package/src/adapters/tiktok/creator-videos.ts +370 -0
- package/src/adapters/tvmaze/shows.test.ts +93 -0
- package/src/adapters/tvmaze/shows.ts +271 -0
- package/src/adapters/twitter/bookmark-folders.test.ts +164 -0
- package/src/adapters/twitter/bookmark-folders.ts +366 -0
- package/src/adapters/twitter/quote.test.ts +157 -0
- package/src/adapters/twitter/quote.ts +332 -0
- package/src/adapters/twitter/tweet-actions.test.ts +51 -0
- package/src/adapters/twitter/tweet-actions.ts +187 -0
- package/src/adapters/twitter/tweet-url.ts +65 -0
- package/src/adapters/uisdc/news.test.ts +46 -0
- package/src/adapters/uisdc/news.ts +111 -0
- package/src/adapters/weibo/favorites-publish.test.ts +177 -0
- package/src/adapters/weibo/favorites-publish.ts +426 -0
- package/src/adapters/wikidata/entities.test.ts +103 -0
- package/src/adapters/wikidata/entities.ts +253 -0
- package/src/adapters/wikipedia/page.test.ts +49 -0
- package/src/adapters/wikipedia/page.ts +158 -0
- package/src/adapters/wttr/weather.test.ts +99 -0
- package/src/adapters/wttr/weather.ts +239 -0
- package/src/adapters/xianyu/publish.test.ts +210 -0
- package/src/adapters/xianyu/publish.ts +420 -0
- package/src/adapters/xiaohongshu/user-helpers.ts +5 -2
- package/src/adapters/yuanbao/web.test.ts +144 -0
- package/src/adapters/yuanbao/web.ts +435 -0
- package/src/adapters/zhihu/collection.test.ts +96 -0
- package/src/adapters/zhihu/collection.ts +239 -0
- package/src/adapters/zlibrary/web.test.ts +104 -0
- package/src/adapters/zlibrary/web.ts +192 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @owner src/adapters/defillama/protocols.ts
|
|
3
|
+
* @does Register agent-facing DefiLlama protocol list and detail commands.
|
|
4
|
+
* @needs DefiLlama public API, bounded result limits, validated protocol slugs.
|
|
5
|
+
* @feeds surface coverage ledger, DeFi protocol TVL rows, protocol metadata detail.
|
|
6
|
+
* @breaks DefiLlama API drift, weak slug validation, or silent empty rows hide DeFi data failures.
|
|
7
|
+
*/
|
|
8
|
+
import { cli, Strategy } from "../../registry.js";
|
|
9
|
+
const API_BASE = "https://api.llama.fi";
|
|
10
|
+
const SLUG_RE = /^[a-z0-9][a-z0-9._-]{0,99}$/;
|
|
11
|
+
export function requireDefillamaLimit(value) {
|
|
12
|
+
const raw = value === undefined || value === null || value === "" ? 30 : value;
|
|
13
|
+
const limit = Number(raw);
|
|
14
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 500) {
|
|
15
|
+
throw new Error("defillama limit must be an integer in [1, 500].");
|
|
16
|
+
}
|
|
17
|
+
return limit;
|
|
18
|
+
}
|
|
19
|
+
export function requireDefillamaSlug(value) {
|
|
20
|
+
const slug = String(value ?? "").trim();
|
|
21
|
+
if (!slug)
|
|
22
|
+
throw new Error("defillama slug cannot be empty.");
|
|
23
|
+
if (!SLUG_RE.test(slug)) {
|
|
24
|
+
throw new Error(`defillama slug "${String(value)}" is not valid.`);
|
|
25
|
+
}
|
|
26
|
+
return slug;
|
|
27
|
+
}
|
|
28
|
+
export function unixToDate(value) {
|
|
29
|
+
if (value == null)
|
|
30
|
+
return null;
|
|
31
|
+
const n = Number(value);
|
|
32
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
33
|
+
return null;
|
|
34
|
+
const date = new Date(n > 1e12 ? n : n * 1000);
|
|
35
|
+
return Number.isNaN(date.getTime()) ? null : date.toISOString().slice(0, 10);
|
|
36
|
+
}
|
|
37
|
+
function stringField(value) {
|
|
38
|
+
return typeof value === "string" ? value.trim() : "";
|
|
39
|
+
}
|
|
40
|
+
function numberField(value) {
|
|
41
|
+
const n = typeof value === "number"
|
|
42
|
+
? value
|
|
43
|
+
: typeof value === "string" && value.trim()
|
|
44
|
+
? Number(value)
|
|
45
|
+
: NaN;
|
|
46
|
+
return Number.isFinite(n) ? n : null;
|
|
47
|
+
}
|
|
48
|
+
function joinStrings(value) {
|
|
49
|
+
return Array.isArray(value)
|
|
50
|
+
? value.filter((item) => typeof item === "string" && item.trim()).join(", ")
|
|
51
|
+
: "";
|
|
52
|
+
}
|
|
53
|
+
function objectField(value) {
|
|
54
|
+
return value && typeof value === "object"
|
|
55
|
+
? value
|
|
56
|
+
: {};
|
|
57
|
+
}
|
|
58
|
+
export function mapDefillamaProtocolRows(rows, limit) {
|
|
59
|
+
return rows
|
|
60
|
+
.filter((row) => (row.slug || row.name) && numberField(row.tvl) != null)
|
|
61
|
+
.sort((a, b) => (numberField(b.tvl) ?? 0) - (numberField(a.tvl) ?? 0))
|
|
62
|
+
.slice(0, limit)
|
|
63
|
+
.map((row, index) => {
|
|
64
|
+
const slug = stringField(row.slug);
|
|
65
|
+
return {
|
|
66
|
+
rank: index + 1,
|
|
67
|
+
slug,
|
|
68
|
+
name: stringField(row.name),
|
|
69
|
+
category: stringField(row.category),
|
|
70
|
+
tvl: numberField(row.tvl),
|
|
71
|
+
mcap: numberField(row.mcap),
|
|
72
|
+
change_1d: numberField(row.change_1d),
|
|
73
|
+
change_7d: numberField(row.change_7d),
|
|
74
|
+
chains: joinStrings(row.chains),
|
|
75
|
+
listedAt: unixToDate(row.listedAt),
|
|
76
|
+
url: slug ? `https://defillama.com/protocol/${slug}` : "",
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
export function mapDefillamaDetailRow(slug, detail, protocols) {
|
|
81
|
+
const tvlSeries = Array.isArray(detail.tvl)
|
|
82
|
+
? detail.tvl
|
|
83
|
+
: [];
|
|
84
|
+
const lastPoint = tvlSeries[tvlSeries.length - 1] ?? {};
|
|
85
|
+
const isParent = detail.isParentProtocol === true;
|
|
86
|
+
const chains = new Set(Array.isArray(detail.chains) ? detail.chains : []);
|
|
87
|
+
let category = "";
|
|
88
|
+
if (isParent) {
|
|
89
|
+
for (const protocol of protocols) {
|
|
90
|
+
if (protocol.parentProtocol === detail.id &&
|
|
91
|
+
Array.isArray(protocol.chains)) {
|
|
92
|
+
for (const chain of protocol.chains) {
|
|
93
|
+
if (typeof chain === "string")
|
|
94
|
+
chains.add(chain);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const match = protocols.find((protocol) => protocol.slug === slug);
|
|
101
|
+
category = stringField(match?.category);
|
|
102
|
+
if (Array.isArray(match?.chains)) {
|
|
103
|
+
for (const chain of match.chains) {
|
|
104
|
+
if (typeof chain === "string")
|
|
105
|
+
chains.add(chain);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
slug,
|
|
111
|
+
name: stringField(detail.name),
|
|
112
|
+
category,
|
|
113
|
+
isParent,
|
|
114
|
+
tvl: numberField(lastPoint.totalLiquidityUSD),
|
|
115
|
+
tvlAt: unixToDate(lastPoint.date),
|
|
116
|
+
mcap: numberField(detail.mcap),
|
|
117
|
+
chains: [...chains].join(", "),
|
|
118
|
+
twitter: stringField(detail.twitter),
|
|
119
|
+
github: joinStrings(detail.github),
|
|
120
|
+
audits: stringField(detail.audits),
|
|
121
|
+
listedAt: unixToDate(detail.listedAt),
|
|
122
|
+
description: stringField(detail.description),
|
|
123
|
+
website: stringField(detail.url),
|
|
124
|
+
url: `https://defillama.com/protocol/${slug}`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async function fetchJson(url, label) {
|
|
128
|
+
const response = await fetch(url, {
|
|
129
|
+
headers: {
|
|
130
|
+
accept: "application/json",
|
|
131
|
+
"user-agent": "unicli-defillama (https://github.com/olo-dot-io/Uni-CLI)",
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
if (response.status === 404)
|
|
135
|
+
throw new Error(`${label} returned no result.`);
|
|
136
|
+
if (response.status === 400)
|
|
137
|
+
throw new Error(`${label} returned HTTP 400.`);
|
|
138
|
+
if (response.status === 429)
|
|
139
|
+
throw new Error(`${label} returned HTTP 429.`);
|
|
140
|
+
if (!response.ok)
|
|
141
|
+
throw new Error(`${label} returned HTTP ${response.status}.`);
|
|
142
|
+
return response.json();
|
|
143
|
+
}
|
|
144
|
+
cli({
|
|
145
|
+
site: "defillama",
|
|
146
|
+
name: "protocols",
|
|
147
|
+
description: "Top DeFi protocols by current TVL",
|
|
148
|
+
domain: "defillama.com",
|
|
149
|
+
strategy: Strategy.PUBLIC,
|
|
150
|
+
args: [{ name: "limit", type: "int", default: 30, description: "Max rows" }],
|
|
151
|
+
columns: [
|
|
152
|
+
"rank",
|
|
153
|
+
"slug",
|
|
154
|
+
"name",
|
|
155
|
+
"category",
|
|
156
|
+
"tvl",
|
|
157
|
+
"mcap",
|
|
158
|
+
"change_1d",
|
|
159
|
+
"change_7d",
|
|
160
|
+
"chains",
|
|
161
|
+
"listedAt",
|
|
162
|
+
"url",
|
|
163
|
+
],
|
|
164
|
+
func: async (_page, kwargs) => {
|
|
165
|
+
const limit = requireDefillamaLimit(kwargs.limit);
|
|
166
|
+
const body = await fetchJson(`${API_BASE}/protocols`, "defillama protocols");
|
|
167
|
+
const rows = mapDefillamaProtocolRows(Array.isArray(body) ? body : [], limit);
|
|
168
|
+
if (rows.length === 0)
|
|
169
|
+
throw new Error("defillama protocols returned no rows.");
|
|
170
|
+
return rows;
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
cli({
|
|
174
|
+
site: "defillama",
|
|
175
|
+
name: "protocol",
|
|
176
|
+
description: "Fetch DefiLlama protocol detail by slug",
|
|
177
|
+
domain: "defillama.com",
|
|
178
|
+
strategy: Strategy.PUBLIC,
|
|
179
|
+
args: [
|
|
180
|
+
{
|
|
181
|
+
name: "slug",
|
|
182
|
+
type: "str",
|
|
183
|
+
required: true,
|
|
184
|
+
positional: true,
|
|
185
|
+
description: "Protocol slug",
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
columns: [
|
|
189
|
+
"slug",
|
|
190
|
+
"name",
|
|
191
|
+
"category",
|
|
192
|
+
"isParent",
|
|
193
|
+
"tvl",
|
|
194
|
+
"tvlAt",
|
|
195
|
+
"mcap",
|
|
196
|
+
"chains",
|
|
197
|
+
"twitter",
|
|
198
|
+
"github",
|
|
199
|
+
"audits",
|
|
200
|
+
"listedAt",
|
|
201
|
+
"description",
|
|
202
|
+
"website",
|
|
203
|
+
"url",
|
|
204
|
+
],
|
|
205
|
+
func: async (_page, kwargs) => {
|
|
206
|
+
const slug = requireDefillamaSlug(kwargs.slug);
|
|
207
|
+
const detail = objectField(await fetchJson(`${API_BASE}/protocol/${encodeURIComponent(slug)}`, "defillama protocol"));
|
|
208
|
+
if (!detail.name)
|
|
209
|
+
throw new Error(`defillama protocol returned no row for "${slug}".`);
|
|
210
|
+
const protocols = await fetchJson(`${API_BASE}/protocols`, "defillama protocol list");
|
|
211
|
+
return [
|
|
212
|
+
mapDefillamaDetailRow(slug, detail, Array.isArray(protocols)
|
|
213
|
+
? protocols
|
|
214
|
+
: []),
|
|
215
|
+
];
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
//# sourceMappingURL=protocols.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocols.js","sourceRoot":"","sources":["../../../src/adapters/defillama/protocols.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @owner src/adapters/devto/read.ts
|
|
3
|
+
* @does Register agent-facing DEV.to article reader.
|
|
4
|
+
* @needs Public dev.to articles API, numeric article ids, explicit body truncation.
|
|
5
|
+
* @feeds surface coverage ledger, developer article reading workflow.
|
|
6
|
+
* @breaks DEV.to API shape drift or missing body_markdown would silently hide article content.
|
|
7
|
+
*/
|
|
8
|
+
interface DevtoArticle {
|
|
9
|
+
id?: unknown;
|
|
10
|
+
title?: unknown;
|
|
11
|
+
body_markdown?: unknown;
|
|
12
|
+
user?: {
|
|
13
|
+
username?: unknown;
|
|
14
|
+
};
|
|
15
|
+
public_reactions_count?: unknown;
|
|
16
|
+
reading_time_minutes?: unknown;
|
|
17
|
+
tag_list?: unknown;
|
|
18
|
+
tags?: unknown;
|
|
19
|
+
published_at?: unknown;
|
|
20
|
+
url?: unknown;
|
|
21
|
+
}
|
|
22
|
+
export declare function requireDevtoArticleId(value: unknown): string;
|
|
23
|
+
export declare function requireDevtoMaxLength(value: unknown, fallback?: number): number;
|
|
24
|
+
export declare function mapDevtoArticleRow(article: DevtoArticle, requestedId: string, maxLength: number): Record<string, unknown>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/adapters/devto/read.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,UAAU,YAAY;IACpB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAUD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM5D;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,QAAQ,SAAS,GAChB,MAAM,CAOR;AAOD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwBzB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @owner src/adapters/devto/read.ts
|
|
3
|
+
* @does Register agent-facing DEV.to article reader.
|
|
4
|
+
* @needs Public dev.to articles API, numeric article ids, explicit body truncation.
|
|
5
|
+
* @feeds surface coverage ledger, developer article reading workflow.
|
|
6
|
+
* @breaks DEV.to API shape drift or missing body_markdown would silently hide article content.
|
|
7
|
+
*/
|
|
8
|
+
import { cli, Strategy } from "../../registry.js";
|
|
9
|
+
const DEVTO_ARTICLE_BASE = "https://dev.to/api/articles";
|
|
10
|
+
function stringField(value) {
|
|
11
|
+
return typeof value === "string" ? value : "";
|
|
12
|
+
}
|
|
13
|
+
function numberField(value) {
|
|
14
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
15
|
+
}
|
|
16
|
+
export function requireDevtoArticleId(value) {
|
|
17
|
+
const id = String(value ?? "").trim();
|
|
18
|
+
if (!/^\d+$/.test(id)) {
|
|
19
|
+
throw new Error(`Invalid DEV.to article id: ${String(value)}.`);
|
|
20
|
+
}
|
|
21
|
+
return id;
|
|
22
|
+
}
|
|
23
|
+
export function requireDevtoMaxLength(value, fallback = 20_000) {
|
|
24
|
+
if (value === undefined || value === null || value === "")
|
|
25
|
+
return fallback;
|
|
26
|
+
const n = Number(value);
|
|
27
|
+
if (!Number.isInteger(n) || n < 100) {
|
|
28
|
+
throw new Error("devto read max-length must be an integer >= 100.");
|
|
29
|
+
}
|
|
30
|
+
return n;
|
|
31
|
+
}
|
|
32
|
+
function normalizeTags(article) {
|
|
33
|
+
const tags = article.tag_list ?? article.tags ?? "";
|
|
34
|
+
return Array.isArray(tags) ? tags.map(String).join(", ") : String(tags);
|
|
35
|
+
}
|
|
36
|
+
export function mapDevtoArticleRow(article, requestedId, maxLength) {
|
|
37
|
+
if (!article || !article.id) {
|
|
38
|
+
throw new Error(`DEV.to article ${requestedId} returned no article.`);
|
|
39
|
+
}
|
|
40
|
+
const body = stringField(article.body_markdown);
|
|
41
|
+
if (!body.trim()) {
|
|
42
|
+
throw new Error(`DEV.to article ${requestedId} did not include body_markdown.`);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
id: article.id,
|
|
46
|
+
title: stringField(article.title),
|
|
47
|
+
author: stringField(article.user?.username) || "[deleted]",
|
|
48
|
+
reactions: numberField(article.public_reactions_count),
|
|
49
|
+
reading_time: numberField(article.reading_time_minutes),
|
|
50
|
+
tags: normalizeTags(article),
|
|
51
|
+
published_at: stringField(article.published_at),
|
|
52
|
+
body: body.length > maxLength
|
|
53
|
+
? `${body.slice(0, maxLength)}\n\n... [truncated]`
|
|
54
|
+
: body,
|
|
55
|
+
url: stringField(article.url),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
async function fetchDevtoArticle(id) {
|
|
59
|
+
const response = await fetch(`${DEVTO_ARTICLE_BASE}/${id}`, {
|
|
60
|
+
headers: {
|
|
61
|
+
"User-Agent": "unicli-devto/1.0 (https://github.com/olo-dot-io/Uni-CLI)",
|
|
62
|
+
Accept: "application/json",
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
if (response.status === 404)
|
|
66
|
+
throw new Error(`DEV.to article ${id} not found.`);
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
throw new Error(`DEV.to API returned HTTP ${response.status} for article ${id}.`);
|
|
69
|
+
}
|
|
70
|
+
return (await response.json());
|
|
71
|
+
}
|
|
72
|
+
cli({
|
|
73
|
+
site: "devto",
|
|
74
|
+
name: "read",
|
|
75
|
+
description: "Read a DEV.to article body by id",
|
|
76
|
+
domain: "dev.to",
|
|
77
|
+
strategy: Strategy.PUBLIC,
|
|
78
|
+
args: [
|
|
79
|
+
{
|
|
80
|
+
name: "id",
|
|
81
|
+
type: "str",
|
|
82
|
+
required: true,
|
|
83
|
+
positional: true,
|
|
84
|
+
description: "DEV.to numeric article id",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "max-length",
|
|
88
|
+
type: "int",
|
|
89
|
+
default: 20_000,
|
|
90
|
+
description: "Max body characters",
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
columns: [
|
|
94
|
+
"id",
|
|
95
|
+
"title",
|
|
96
|
+
"author",
|
|
97
|
+
"reactions",
|
|
98
|
+
"reading_time",
|
|
99
|
+
"tags",
|
|
100
|
+
"published_at",
|
|
101
|
+
"body",
|
|
102
|
+
"url",
|
|
103
|
+
],
|
|
104
|
+
func: async (_page, kwargs) => {
|
|
105
|
+
const id = requireDevtoArticleId(kwargs.id);
|
|
106
|
+
const maxLength = requireDevtoMaxLength(kwargs["max-length"] ?? kwargs.maxLength);
|
|
107
|
+
return [mapDevtoArticleRow(await fetchDevtoArticle(id), id, maxLength)];
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/adapters/devto/read.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @owner src/adapters/dianping/shop.ts
|
|
3
|
+
* @does Register agent-facing Dianping shop detail extraction implemented with site-specific safety checks.
|
|
4
|
+
* @needs Dianping shop page DOM and a browser profile that can pass Dianping anti-bot checks.
|
|
5
|
+
* @feeds surface coverage ledger and restaurant search-to-detail workflows.
|
|
6
|
+
* @breaks Dianping shop-head DOM drift, login redirects, captcha gates, or deleted shops can hide detail fields.
|
|
7
|
+
*/
|
|
8
|
+
declare const SHOP_FIELDS: readonly ["shop_id", "name", "rating", "reviews", "price", "rank", "taste", "environment", "service", "ingredients", "hours", "address", "subway", "features", "url"];
|
|
9
|
+
type DianpingShopField = (typeof SHOP_FIELDS)[number];
|
|
10
|
+
interface DianpingShopBreakdown {
|
|
11
|
+
口味?: unknown;
|
|
12
|
+
环境?: unknown;
|
|
13
|
+
服务?: unknown;
|
|
14
|
+
食材?: unknown;
|
|
15
|
+
}
|
|
16
|
+
interface DianpingShopData {
|
|
17
|
+
name?: unknown;
|
|
18
|
+
rating?: unknown;
|
|
19
|
+
reviewsRaw?: unknown;
|
|
20
|
+
priceRaw?: unknown;
|
|
21
|
+
rank?: unknown;
|
|
22
|
+
breakdown?: DianpingShopBreakdown;
|
|
23
|
+
hours?: unknown;
|
|
24
|
+
address?: unknown;
|
|
25
|
+
subway?: unknown;
|
|
26
|
+
features?: unknown;
|
|
27
|
+
url?: unknown;
|
|
28
|
+
}
|
|
29
|
+
export declare function normalizeDianpingShopId(value: unknown): string;
|
|
30
|
+
export declare function parseDianpingReviewCount(value: unknown): number | null;
|
|
31
|
+
export declare function parseDianpingPrice(value: unknown): number | null;
|
|
32
|
+
export declare function mapDianpingShopFields(shopId: string, data: DianpingShopData, fallbackUrl: string): Array<{
|
|
33
|
+
field: DianpingShopField;
|
|
34
|
+
value: unknown;
|
|
35
|
+
}>;
|
|
36
|
+
export declare function classifyDianpingShopFailure(sample: unknown, url: string, shopId: string): never;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=shop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shop.d.ts","sourceRoot":"","sources":["../../../src/adapters/dianping/shop.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,QAAA,MAAM,WAAW,uKAgBP,CAAC;AAEX,KAAK,iBAAiB,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,UAAU,qBAAqB;IAC7B,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAOD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAW9D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAYtE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAKhE;AAmBD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,EACtB,WAAW,EAAE,MAAM,GAClB,KAAK,CAAC;IAAE,KAAK,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAqBrD;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,KAAK,CA+BP"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @owner src/adapters/dianping/shop.ts
|
|
3
|
+
* @does Register agent-facing Dianping shop detail extraction implemented with site-specific safety checks.
|
|
4
|
+
* @needs Dianping shop page DOM and a browser profile that can pass Dianping anti-bot checks.
|
|
5
|
+
* @feeds surface coverage ledger and restaurant search-to-detail workflows.
|
|
6
|
+
* @breaks Dianping shop-head DOM drift, login redirects, captcha gates, or deleted shops can hide detail fields.
|
|
7
|
+
*/
|
|
8
|
+
import { cli, Strategy } from "../../registry.js";
|
|
9
|
+
import { str } from "../_shared/browser-tools.js";
|
|
10
|
+
const DIANPING_ORIGIN = "https://www.dianping.com";
|
|
11
|
+
const SHOP_ID_RE = /^[A-Za-z0-9_-]+$/;
|
|
12
|
+
const SHOP_FIELDS = [
|
|
13
|
+
"shop_id",
|
|
14
|
+
"name",
|
|
15
|
+
"rating",
|
|
16
|
+
"reviews",
|
|
17
|
+
"price",
|
|
18
|
+
"rank",
|
|
19
|
+
"taste",
|
|
20
|
+
"environment",
|
|
21
|
+
"service",
|
|
22
|
+
"ingredients",
|
|
23
|
+
"hours",
|
|
24
|
+
"address",
|
|
25
|
+
"subway",
|
|
26
|
+
"features",
|
|
27
|
+
"url",
|
|
28
|
+
];
|
|
29
|
+
export function normalizeDianpingShopId(value) {
|
|
30
|
+
const raw = str(value).trim();
|
|
31
|
+
if (!raw)
|
|
32
|
+
throw new Error("Dianping shop_id must be a non-empty string.");
|
|
33
|
+
const match = raw.match(/\/shop\/([^/?#]+)/);
|
|
34
|
+
const shopId = match?.[1] ?? raw;
|
|
35
|
+
if (!SHOP_ID_RE.test(shopId)) {
|
|
36
|
+
throw new Error(`Dianping shop_id must be an alphanumeric shop ID or /shop/<id> URL.`);
|
|
37
|
+
}
|
|
38
|
+
return shopId;
|
|
39
|
+
}
|
|
40
|
+
export function parseDianpingReviewCount(value) {
|
|
41
|
+
const text = str(value).trim();
|
|
42
|
+
if (!text)
|
|
43
|
+
return null;
|
|
44
|
+
const wan = text.match(/^([\d.]+)\s*万/);
|
|
45
|
+
if (wan) {
|
|
46
|
+
const count = Number(wan[1]);
|
|
47
|
+
return Number.isFinite(count) ? Math.round(count * 10000) : null;
|
|
48
|
+
}
|
|
49
|
+
const plain = text.match(/(\d+(?:\.\d+)?)/);
|
|
50
|
+
if (!plain)
|
|
51
|
+
return null;
|
|
52
|
+
const count = Number(plain[1]);
|
|
53
|
+
return Number.isFinite(count) ? Math.round(count) : null;
|
|
54
|
+
}
|
|
55
|
+
export function parseDianpingPrice(value) {
|
|
56
|
+
const match = str(value).match(/[¥¥]\s*(\d+(?:\.\d+)?)/);
|
|
57
|
+
if (!match)
|
|
58
|
+
return null;
|
|
59
|
+
const price = Number(match[1]);
|
|
60
|
+
return Number.isFinite(price) ? price : null;
|
|
61
|
+
}
|
|
62
|
+
function numberOrNull(value) {
|
|
63
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
64
|
+
return value;
|
|
65
|
+
const text = str(value).trim();
|
|
66
|
+
if (!text)
|
|
67
|
+
return null;
|
|
68
|
+
const valueNumber = Number(text);
|
|
69
|
+
return Number.isFinite(valueNumber) ? valueNumber : null;
|
|
70
|
+
}
|
|
71
|
+
function featuresText(value) {
|
|
72
|
+
if (Array.isArray(value))
|
|
73
|
+
return value
|
|
74
|
+
.map((item) => str(item).trim())
|
|
75
|
+
.filter(Boolean)
|
|
76
|
+
.join(", ");
|
|
77
|
+
return str(value).trim();
|
|
78
|
+
}
|
|
79
|
+
export function mapDianpingShopFields(shopId, data, fallbackUrl) {
|
|
80
|
+
const rating = numberOrNull(data.rating);
|
|
81
|
+
const breakdown = data.breakdown ?? {};
|
|
82
|
+
const values = {
|
|
83
|
+
shop_id: shopId,
|
|
84
|
+
name: str(data.name).trim(),
|
|
85
|
+
rating,
|
|
86
|
+
reviews: parseDianpingReviewCount(data.reviewsRaw),
|
|
87
|
+
price: parseDianpingPrice(data.priceRaw),
|
|
88
|
+
rank: str(data.rank).trim(),
|
|
89
|
+
taste: numberOrNull(breakdown["口味"]),
|
|
90
|
+
environment: numberOrNull(breakdown["环境"]),
|
|
91
|
+
service: numberOrNull(breakdown["服务"]),
|
|
92
|
+
ingredients: numberOrNull(breakdown["食材"]),
|
|
93
|
+
hours: str(data.hours).trim(),
|
|
94
|
+
address: str(data.address).trim(),
|
|
95
|
+
subway: str(data.subway).trim(),
|
|
96
|
+
features: featuresText(data.features),
|
|
97
|
+
url: str(data.url).trim() || fallbackUrl,
|
|
98
|
+
};
|
|
99
|
+
return SHOP_FIELDS.map((field) => ({ field, value: values[field] }));
|
|
100
|
+
}
|
|
101
|
+
export function classifyDianpingShopFailure(sample, url, shopId) {
|
|
102
|
+
const signal = `${url} ${str(sample)}`;
|
|
103
|
+
if (/verify\.meituan\.com|verifyimg|身份核实|请依次点击|美团安全验证|Yoda/i.test(signal)) {
|
|
104
|
+
throw new Error(`Dianping shop ${shopId} is blocked by captcha; solve the Dianping captcha in this browser profile and retry.`);
|
|
105
|
+
}
|
|
106
|
+
if (/login\.dianping\.com|account\.dianping\.com|请先登录|未登录|请登录/.test(signal)) {
|
|
107
|
+
throw new Error(`Dianping shop ${shopId} requires login; sign in to dianping.com in this browser profile and retry.`);
|
|
108
|
+
}
|
|
109
|
+
if (/商户不存在|店铺不存在|店铺已关闭|页面不存在|404|已下线|没有找到相关商户/i.test(signal)) {
|
|
110
|
+
throw new Error(`Dianping shop ${shopId} was not found or is unavailable.`);
|
|
111
|
+
}
|
|
112
|
+
const preview = str(sample).slice(0, 160);
|
|
113
|
+
throw new Error(`Dianping shop ${shopId} did not render expected shop data${preview ? `; sample: ${preview}` : ""}.`);
|
|
114
|
+
}
|
|
115
|
+
function buildDianpingShopEvaluate() {
|
|
116
|
+
return `(() => {
|
|
117
|
+
const clean = (value) => value == null ? '' : String(value).replace(/\\s+/g, ' ').trim();
|
|
118
|
+
const head = document.querySelector('.shop-head');
|
|
119
|
+
if (!head) {
|
|
120
|
+
const sample = clean(document.body?.innerText || document.body?.textContent || '').slice(0, 800);
|
|
121
|
+
return { ok: false, sample, url: location.href };
|
|
122
|
+
}
|
|
123
|
+
const headText = clean(head.textContent);
|
|
124
|
+
const titleEl = document.querySelector('.shop-name, .shop-head h2, .shop-head h1');
|
|
125
|
+
let name = clean(titleEl?.textContent);
|
|
126
|
+
if (!name) {
|
|
127
|
+
const match = String(document.title || '').match(/【([^】]+)】/);
|
|
128
|
+
if (match) name = clean(match[1]);
|
|
129
|
+
}
|
|
130
|
+
const rating = clean(document.querySelector('.star-score')?.textContent);
|
|
131
|
+
const reviewEl = document.querySelector('.reviews, .review-num, .reviewCount, .reviewCountSentence');
|
|
132
|
+
let reviewsRaw = clean(reviewEl?.textContent);
|
|
133
|
+
if (!reviewsRaw) {
|
|
134
|
+
const titleText = clean(document.querySelector('.review-title')?.textContent);
|
|
135
|
+
const titleMatch = titleText.match(/评价\\(([\\d.,万]+)\\)/);
|
|
136
|
+
if (titleMatch) reviewsRaw = titleMatch[1];
|
|
137
|
+
}
|
|
138
|
+
const priceMatch = headText.match(/[¥¥]\\s*\\d+(?:\\.\\d+)?/);
|
|
139
|
+
const breakdown = {};
|
|
140
|
+
for (const key of ['口味', '环境', '服务', '食材']) {
|
|
141
|
+
const match = headText.match(new RegExp(key + '[::]\\\\s*([0-9.]+)'));
|
|
142
|
+
if (match) breakdown[key] = Number(match[1]);
|
|
143
|
+
}
|
|
144
|
+
const features = Array.from(document.querySelectorAll('.shop-feature')).map((node) => clean(node.textContent)).filter(Boolean);
|
|
145
|
+
const subwayMatch = headText.match(/距(?:地铁)?[^\\s]+?步行\\d+m/);
|
|
146
|
+
const hoursMatch = headText.match(/营业中[^\\s]*\\d{1,2}:\\d{2}-(?:次日)?\\d{1,2}:\\d{2}|今日休息|暂停营业/);
|
|
147
|
+
const rankMatch = headText.match(/[^\\s]+?(?:口味|人气|环境|服务)榜\\s*[·•]\\s*第\\d+名/);
|
|
148
|
+
return {
|
|
149
|
+
ok: true,
|
|
150
|
+
name,
|
|
151
|
+
rating,
|
|
152
|
+
reviewsRaw,
|
|
153
|
+
priceRaw: priceMatch?.[0] || '',
|
|
154
|
+
rank: rankMatch?.[0] || '',
|
|
155
|
+
breakdown,
|
|
156
|
+
hours: hoursMatch?.[0] || '',
|
|
157
|
+
address: clean(document.querySelector('.desc-info')?.textContent),
|
|
158
|
+
subway: subwayMatch?.[0] || '',
|
|
159
|
+
features,
|
|
160
|
+
url: location.href,
|
|
161
|
+
};
|
|
162
|
+
})()`;
|
|
163
|
+
}
|
|
164
|
+
cli({
|
|
165
|
+
site: "dianping",
|
|
166
|
+
name: "shop",
|
|
167
|
+
description: "Read Dianping shop details by shop ID or shop URL",
|
|
168
|
+
domain: "www.dianping.com",
|
|
169
|
+
strategy: Strategy.COOKIE,
|
|
170
|
+
browser: true,
|
|
171
|
+
args: [
|
|
172
|
+
{
|
|
173
|
+
name: "shop_id",
|
|
174
|
+
type: "str",
|
|
175
|
+
required: true,
|
|
176
|
+
positional: true,
|
|
177
|
+
description: "Dianping shop ID or https://www.dianping.com/shop/<id> URL",
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
columns: ["field", "value"],
|
|
181
|
+
func: async (page, kwargs) => {
|
|
182
|
+
const shopId = normalizeDianpingShopId(kwargs.shop_id);
|
|
183
|
+
const url = `${DIANPING_ORIGIN}/shop/${shopId}`;
|
|
184
|
+
const p = page;
|
|
185
|
+
await p.goto(url, { waitUntil: "load", settleMs: 3000 });
|
|
186
|
+
await p.wait(3);
|
|
187
|
+
const result = (await p.evaluate(buildDianpingShopEvaluate()));
|
|
188
|
+
if (!result?.ok) {
|
|
189
|
+
classifyDianpingShopFailure(result?.sample, str(result?.url) || url, shopId);
|
|
190
|
+
}
|
|
191
|
+
return mapDianpingShopFields(shopId, result, url);
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
//# sourceMappingURL=shop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shop.js","sourceRoot":"","sources":["../../../src/adapters/dianping/shop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @owner src/adapters/dockerhub/registry.ts
|
|
3
|
+
* @does Register agent-facing Docker Hub search and image metadata commands.
|
|
4
|
+
* @needs Public Docker Hub API, TypeScript adapter loader, bounded argument parsing.
|
|
5
|
+
* @feeds surface coverage ledger, container registry command surface, agent-readable image rows.
|
|
6
|
+
* @breaks Docker Hub API envelope drift, weak image parsing, or silent empty results hide registry lookup failures.
|
|
7
|
+
*/
|
|
8
|
+
interface DockerHubSearchItem {
|
|
9
|
+
repo_owner?: unknown;
|
|
10
|
+
repo_name?: unknown;
|
|
11
|
+
is_official?: unknown;
|
|
12
|
+
star_count?: unknown;
|
|
13
|
+
pull_count?: unknown;
|
|
14
|
+
short_description?: unknown;
|
|
15
|
+
}
|
|
16
|
+
interface DockerHubImageBody {
|
|
17
|
+
namespace?: unknown;
|
|
18
|
+
name?: unknown;
|
|
19
|
+
star_count?: unknown;
|
|
20
|
+
pull_count?: unknown;
|
|
21
|
+
description?: unknown;
|
|
22
|
+
last_updated?: unknown;
|
|
23
|
+
last_modified?: unknown;
|
|
24
|
+
date_registered?: unknown;
|
|
25
|
+
status_description?: unknown;
|
|
26
|
+
}
|
|
27
|
+
export declare function requireDockerHubString(value: unknown, name: string): string;
|
|
28
|
+
export declare function requireDockerHubLimit(value: unknown, fallback: number): number;
|
|
29
|
+
export declare function parseDockerHubImage(value: unknown): {
|
|
30
|
+
owner: string;
|
|
31
|
+
name: string;
|
|
32
|
+
};
|
|
33
|
+
export declare function mapDockerHubSearchRows(items: DockerHubSearchItem[], limit: number): Array<Record<string, unknown>>;
|
|
34
|
+
export declare function mapDockerHubImageRow(body: DockerHubImageBody, fallbackOwner: string, fallbackName: string): Record<string, unknown>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=registry.d.ts.map
|