@jackwener/opencli 1.7.11 → 1.7.13
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/README.md +8 -7
- package/README.zh-CN.md +11 -9
- package/cli-manifest.json +12952 -6208
- package/clis/1688/assets.js +1 -0
- package/clis/1688/download.js +1 -0
- package/clis/1688/item.js +1 -0
- package/clis/1688/search.js +2 -1
- package/clis/1688/store.js +1 -0
- package/clis/1point3acres/digest.js +35 -0
- package/clis/1point3acres/forum.js +51 -0
- package/clis/1point3acres/forums.js +44 -0
- package/clis/1point3acres/hot.js +35 -0
- package/clis/1point3acres/latest.js +35 -0
- package/clis/1point3acres/notifications.js +64 -0
- package/clis/1point3acres/search.js +71 -0
- package/clis/1point3acres/thread.js +117 -0
- package/clis/1point3acres/user.js +77 -0
- package/clis/1point3acres/utils.js +247 -0
- package/clis/36kr/article.js +1 -0
- package/clis/36kr/hot.js +1 -0
- package/clis/36kr/news.js +1 -0
- package/clis/36kr/search.js +1 -0
- package/clis/51job/company.js +1 -0
- package/clis/51job/detail.js +1 -0
- package/clis/51job/hot.js +1 -0
- package/clis/51job/search.js +1 -0
- package/clis/_shared/desktop-commands.js +4 -0
- package/clis/aibase/news.js +110 -0
- package/clis/aibase/news.test.js +59 -0
- package/clis/amazon/bestsellers.js +1 -0
- package/clis/amazon/discussion.js +1 -0
- package/clis/amazon/discussion.test.js +1 -28
- package/clis/amazon/movers-shakers.js +1 -0
- package/clis/amazon/new-releases.js +1 -0
- package/clis/amazon/offer.js +1 -0
- package/clis/amazon/product.js +1 -0
- package/clis/amazon/rankings.js +1 -0
- package/clis/amazon/search.js +1 -0
- package/clis/antigravity/dump.js +1 -0
- package/clis/antigravity/extract-code.js +1 -0
- package/clis/antigravity/model.js +1 -0
- package/clis/antigravity/new.js +1 -0
- package/clis/antigravity/read.js +1 -0
- package/clis/antigravity/send.js +1 -0
- package/clis/antigravity/status.js +1 -0
- package/clis/antigravity/watch.js +4 -2
- package/clis/apple-podcasts/episodes.js +1 -0
- package/clis/apple-podcasts/search.js +1 -0
- package/clis/apple-podcasts/top.js +1 -0
- package/clis/arxiv/arxiv.test.js +112 -0
- package/clis/arxiv/author.js +44 -0
- package/clis/arxiv/paper.js +4 -3
- package/clis/arxiv/recent.js +33 -0
- package/clis/arxiv/search.js +19 -7
- package/clis/arxiv/utils.js +68 -5
- package/clis/baidu-scholar/search.js +1 -1
- package/clis/band/bands.js +1 -0
- package/clis/band/mentions.js +1 -0
- package/clis/band/post.js +1 -0
- package/clis/band/posts.js +1 -0
- package/clis/barchart/flow.js +1 -0
- package/clis/barchart/greeks.js +1 -0
- package/clis/barchart/options.js +1 -0
- package/clis/barchart/quote.js +1 -0
- package/clis/bbc/news.js +1 -0
- package/clis/bbc/topic.js +57 -0
- package/clis/bbc/utils.js +79 -0
- package/clis/bilibili/comments.js +1 -0
- package/clis/bilibili/download.js +1 -0
- package/clis/bilibili/dynamic.js +1 -0
- package/clis/bilibili/favorite.js +1 -0
- package/clis/bilibili/feed.js +2 -0
- package/clis/bilibili/following.js +1 -0
- package/clis/bilibili/history.js +1 -0
- package/clis/bilibili/hot.js +6 -1
- package/clis/bilibili/hot.test.js +17 -0
- package/clis/bilibili/me.js +1 -1
- package/clis/bilibili/ranking.js +1 -0
- package/clis/bilibili/search.js +1 -1
- package/clis/bilibili/subtitle.js +1 -0
- package/clis/bilibili/user-videos.js +1 -0
- package/clis/bilibili/video.js +1 -0
- package/clis/binance/asks.js +1 -0
- package/clis/binance/depth.js +1 -0
- package/clis/binance/gainers.js +1 -0
- package/clis/binance/klines.js +1 -0
- package/clis/binance/losers.js +1 -0
- package/clis/binance/pairs.js +1 -0
- package/clis/binance/price.js +1 -0
- package/clis/binance/prices.js +1 -0
- package/clis/binance/ticker.js +1 -0
- package/clis/binance/top.js +1 -0
- package/clis/binance/trades.js +1 -0
- package/clis/bloomberg/businessweek.js +1 -0
- package/clis/bloomberg/economics.js +1 -0
- package/clis/bloomberg/feeds.js +1 -0
- package/clis/bloomberg/industries.js +1 -0
- package/clis/bloomberg/main.js +1 -0
- package/clis/bloomberg/markets.js +1 -0
- package/clis/bloomberg/news.js +1 -0
- package/clis/bloomberg/opinions.js +1 -0
- package/clis/bloomberg/politics.js +1 -0
- package/clis/bloomberg/tech.js +1 -0
- package/clis/bluesky/feeds.js +1 -0
- package/clis/bluesky/followers.js +1 -0
- package/clis/bluesky/following.js +1 -0
- package/clis/bluesky/profile.js +1 -0
- package/clis/bluesky/search.js +1 -0
- package/clis/bluesky/starter-packs.js +1 -0
- package/clis/bluesky/thread.js +1 -0
- package/clis/bluesky/trending.js +1 -0
- package/clis/bluesky/user.js +3 -1
- package/clis/boss/batchgreet.js +1 -0
- package/clis/boss/chatlist.js +1 -0
- package/clis/boss/chatmsg.js +1 -0
- package/clis/boss/detail.js +1 -0
- package/clis/boss/exchange.js +1 -0
- package/clis/boss/greet.js +1 -0
- package/clis/boss/invite.js +1 -0
- package/clis/boss/joblist.js +1 -0
- package/clis/boss/mark.js +1 -0
- package/clis/boss/recommend.js +1 -0
- package/clis/boss/resume.js +1 -0
- package/clis/boss/search.js +1 -0
- package/clis/boss/send.js +1 -0
- package/clis/boss/stats.js +1 -0
- package/clis/chaoxing/assignments.js +2 -1
- package/clis/chaoxing/exams.js +2 -1
- package/clis/chatgpt/ask.js +57 -0
- package/clis/chatgpt/commands.test.js +45 -0
- package/clis/chatgpt/detail.js +46 -0
- package/clis/chatgpt/history.js +39 -0
- package/clis/chatgpt/image.js +13 -11
- package/clis/chatgpt/image.test.js +23 -0
- package/clis/chatgpt/new.js +25 -0
- package/clis/chatgpt/read.js +43 -0
- package/clis/chatgpt/send.js +46 -0
- package/clis/chatgpt/status.js +29 -0
- package/clis/chatgpt/utils.js +294 -4
- package/clis/chatgpt/utils.test.js +13 -0
- package/clis/chatgpt-app/ask.js +7 -3
- package/clis/chatgpt-app/model.js +1 -0
- package/clis/chatgpt-app/new.js +1 -0
- package/clis/chatgpt-app/read.js +1 -0
- package/clis/chatgpt-app/send.js +1 -0
- package/clis/chatgpt-app/status.js +1 -0
- package/clis/chatwise/ask.js +17 -43
- package/clis/chatwise/composer.test.js +186 -0
- package/clis/chatwise/export.js +1 -0
- package/clis/chatwise/history.js +1 -0
- package/clis/chatwise/model.js +1 -0
- package/clis/chatwise/read.js +1 -0
- package/clis/chatwise/send.js +3 -24
- package/clis/chatwise/utils.js +143 -0
- package/clis/claude/ask.js +2 -1
- package/clis/claude/detail.js +2 -0
- package/clis/claude/history.js +2 -0
- package/clis/claude/new.js +2 -0
- package/clis/claude/read.js +2 -0
- package/clis/claude/send.js +2 -0
- package/clis/claude/status.js +2 -0
- package/clis/cnki/search.js +1 -0
- package/clis/codex/ask.js +16 -9
- package/clis/codex/export.js +1 -0
- package/clis/codex/extract-diff.js +1 -0
- package/clis/codex/history.js +17 -33
- package/clis/codex/model.js +1 -0
- package/clis/codex/projects.js +28 -0
- package/clis/codex/read.js +11 -4
- package/clis/codex/send.js +11 -3
- package/clis/codex/sidebar.js +356 -0
- package/clis/codex/sidebar.test.js +329 -0
- package/clis/coingecko/categories.js +75 -0
- package/clis/coingecko/coin.js +107 -0
- package/clis/coingecko/coingecko.test.js +109 -0
- package/clis/coingecko/derivatives.js +84 -0
- package/clis/coingecko/exchanges.js +74 -0
- package/clis/coingecko/global.js +71 -0
- package/clis/coingecko/top.js +64 -0
- package/clis/coingecko/trending.js +55 -0
- package/clis/coupang/add-to-cart.js +22 -13
- package/clis/coupang/coupang.test.js +159 -0
- package/clis/coupang/product.js +257 -0
- package/clis/coupang/search.js +39 -16
- package/clis/coupang/utils.js +55 -1
- package/clis/crates/crate.js +62 -0
- package/clis/crates/search.js +44 -0
- package/clis/crates/utils.js +72 -0
- package/clis/ctrip/ctrip.test.js +234 -0
- package/clis/ctrip/hotel-suggest.js +45 -0
- package/clis/ctrip/search.js +23 -68
- package/clis/ctrip/utils.js +175 -0
- package/clis/cursor/ask.js +7 -3
- package/clis/cursor/composer.js +1 -0
- package/clis/cursor/export.js +1 -0
- package/clis/cursor/extract-code.js +1 -0
- package/clis/cursor/history.js +1 -0
- package/clis/cursor/model.js +1 -0
- package/clis/cursor/read.js +1 -0
- package/clis/cursor/send.js +1 -0
- package/clis/dblp/author.js +133 -0
- package/clis/dblp/dblp.test.js +397 -0
- package/clis/dblp/paper.js +40 -0
- package/clis/dblp/search.js +45 -0
- package/clis/dblp/utils.js +290 -0
- package/clis/dblp/venue.js +64 -0
- package/clis/deepseek/ask.js +13 -7
- package/clis/deepseek/ask.test.js +13 -13
- package/clis/deepseek/detail.js +38 -0
- package/clis/deepseek/detail.test.js +81 -0
- package/clis/deepseek/history.js +2 -0
- package/clis/deepseek/new.js +2 -0
- package/clis/deepseek/read.js +2 -0
- package/clis/deepseek/send.js +140 -0
- package/clis/deepseek/send.test.js +107 -0
- package/clis/deepseek/status.js +2 -0
- package/clis/deepseek/utils.js +66 -0
- package/clis/deepseek/utils.test.js +107 -1
- package/clis/defillama/defillama.test.js +99 -0
- package/clis/defillama/protocol.js +84 -0
- package/clis/defillama/protocols.js +55 -0
- package/clis/defillama/utils.js +99 -0
- package/clis/devto/devto.test.js +236 -0
- package/clis/devto/latest.js +74 -0
- package/clis/devto/read.js +103 -0
- package/clis/devto/tag.js +5 -1
- package/clis/devto/top.js +5 -1
- package/clis/devto/user.js +5 -1
- package/clis/dianping/__fixtures__/search.html +168 -0
- package/clis/dianping/__fixtures__/shop.html +6 -0
- package/clis/dianping/dianping.test.js +424 -0
- package/clis/dianping/search.js +154 -0
- package/clis/dianping/shop.js +173 -0
- package/clis/dianping/utils.js +157 -0
- package/clis/dictionary/examples.js +1 -0
- package/clis/dictionary/search.js +1 -0
- package/clis/dictionary/synonyms.js +1 -0
- package/clis/discord-app/channels.js +1 -0
- package/clis/discord-app/delete.js +1 -0
- package/clis/discord-app/members.js +1 -0
- package/clis/discord-app/read.js +1 -0
- package/clis/discord-app/search.js +1 -0
- package/clis/discord-app/send.js +1 -0
- package/clis/discord-app/servers.js +1 -0
- package/clis/discord-app/status.js +1 -0
- package/clis/dockerhub/image.js +52 -0
- package/clis/dockerhub/search.js +47 -0
- package/clis/dockerhub/utils.js +100 -0
- package/clis/douban/book-hot.js +1 -0
- package/clis/douban/download.js +1 -0
- package/clis/douban/marks.js +1 -0
- package/clis/douban/movie-hot.js +2 -1
- package/clis/douban/movie-hot.test.js +14 -0
- package/clis/douban/photos.js +2 -1
- package/clis/douban/reviews.js +1 -0
- package/clis/douban/search.js +1 -0
- package/clis/douban/subject.js +1 -0
- package/clis/douban/top250.js +1 -0
- package/clis/douban/utils.js +11 -13
- package/clis/douban/utils.test.js +79 -0
- package/clis/doubao/ask.js +8 -3
- package/clis/doubao/detail.js +2 -0
- package/clis/doubao/history.js +2 -0
- package/clis/doubao/meeting-summary.js +2 -0
- package/clis/doubao/meeting-transcript.js +2 -0
- package/clis/doubao/new.js +2 -0
- package/clis/doubao/read.js +2 -0
- package/clis/doubao/send.js +2 -0
- package/clis/doubao/status.js +2 -0
- package/clis/doubao-app/ask.js +1 -0
- package/clis/doubao-app/dump.js +1 -0
- package/clis/doubao-app/new.js +1 -0
- package/clis/doubao-app/read.js +1 -0
- package/clis/doubao-app/screenshot.js +1 -0
- package/clis/doubao-app/send.js +1 -0
- package/clis/doubao-app/status.js +1 -0
- package/clis/douyin/activities.js +1 -0
- package/clis/douyin/collections.js +1 -0
- package/clis/douyin/delete.js +1 -0
- package/clis/douyin/draft.js +1 -0
- package/clis/douyin/draft.test.js +1 -30
- package/clis/douyin/drafts.js +1 -0
- package/clis/douyin/hashtag.js +1 -0
- package/clis/douyin/location.js +1 -0
- package/clis/douyin/profile.js +1 -0
- package/clis/douyin/publish.js +1 -0
- package/clis/douyin/stats.js +1 -0
- package/clis/douyin/update.js +1 -0
- package/clis/douyin/user-videos.js +1 -0
- package/clis/douyin/videos.js +1 -0
- package/clis/eastmoney/announcement.js +1 -0
- package/clis/eastmoney/convertible.js +1 -0
- package/clis/eastmoney/etf.js +1 -0
- package/clis/eastmoney/holders.js +1 -0
- package/clis/eastmoney/hot-rank.js +1 -0
- package/clis/eastmoney/index-board.js +1 -0
- package/clis/eastmoney/kline.js +1 -0
- package/clis/eastmoney/kuaixun.js +1 -0
- package/clis/eastmoney/longhu.js +1 -0
- package/clis/eastmoney/money-flow.js +1 -0
- package/clis/eastmoney/northbound.js +1 -0
- package/clis/eastmoney/quote.js +1 -0
- package/clis/eastmoney/rank.js +1 -0
- package/clis/eastmoney/sectors.js +1 -0
- package/clis/endoflife/endoflife.test.js +51 -0
- package/clis/endoflife/product.js +55 -0
- package/clis/endoflife/utils.js +89 -0
- package/clis/facebook/__fixtures__/notifications-page.html +13 -0
- package/clis/facebook/add-friend.js +1 -0
- package/clis/facebook/events.js +1 -0
- package/clis/facebook/feed.js +1 -0
- package/clis/facebook/friends.js +1 -0
- package/clis/facebook/groups.js +1 -0
- package/clis/facebook/join-group.js +1 -0
- package/clis/facebook/marketplace-inbox.js +1 -0
- package/clis/facebook/marketplace-listings.js +1 -0
- package/clis/facebook/memories.js +1 -0
- package/clis/facebook/notifications.js +327 -30
- package/clis/facebook/notifications.test.js +458 -0
- package/clis/facebook/profile.js +1 -0
- package/clis/facebook/search.js +1 -0
- package/clis/flathub/app.js +71 -0
- package/clis/flathub/flathub.test.js +90 -0
- package/clis/flathub/search.js +80 -0
- package/clis/flathub/utils.js +114 -0
- package/clis/gemini/ask.js +8 -3
- package/clis/gemini/ask.test.js +2 -2
- package/clis/gemini/deep-research-result.js +7 -2
- package/clis/gemini/deep-research-result.test.js +15 -14
- package/clis/gemini/deep-research.js +9 -4
- package/clis/gemini/deep-research.test.js +15 -18
- package/clis/gemini/image.js +8 -2
- package/clis/gemini/new.js +2 -0
- package/clis/gemini/utils.js +0 -4
- package/clis/gitee/search.js +1 -0
- package/clis/gitee/trending.js +1 -0
- package/clis/gitee/user.js +1 -0
- package/clis/google/news.js +1 -0
- package/clis/google/search.js +1 -0
- package/clis/google/suggest.js +1 -0
- package/clis/google/trends.js +1 -0
- package/clis/google-scholar/cite.js +1 -1
- package/clis/google-scholar/profile.js +1 -1
- package/clis/google-scholar/search.js +1 -1
- package/clis/goproxy/goproxy.test.js +103 -0
- package/clis/goproxy/module.js +47 -0
- package/clis/goproxy/utils.js +165 -0
- package/clis/goproxy/versions.js +59 -0
- package/clis/gov-law/recent.js +1 -1
- package/clis/gov-law/search.js +1 -1
- package/clis/gov-policy/__fixtures__/recent.html +16 -0
- package/clis/gov-policy/__fixtures__/search.html +41 -0
- package/clis/gov-policy/gov-policy.test.js +224 -0
- package/clis/gov-policy/recent.js +67 -24
- package/clis/gov-policy/search.js +66 -23
- package/clis/gov-policy/utils.js +54 -0
- package/clis/grok/ask.js +50 -265
- package/clis/grok/ask.test.js +21 -46
- package/clis/grok/detail.js +60 -0
- package/clis/grok/history.js +48 -0
- package/clis/grok/{image.ts → image.js} +57 -70
- package/clis/grok/image.test.ts +20 -0
- package/clis/grok/new.js +20 -0
- package/clis/grok/read.js +39 -0
- package/clis/grok/send.js +50 -0
- package/clis/grok/status.js +41 -0
- package/clis/grok/utils.js +326 -0
- package/clis/grok/utils.test.js +103 -0
- package/clis/hackernews/ask.js +3 -1
- package/clis/hackernews/best.js +3 -1
- package/clis/hackernews/hackernews.test.js +132 -0
- package/clis/hackernews/jobs.js +3 -1
- package/clis/hackernews/new.js +3 -1
- package/clis/hackernews/read.js +188 -0
- package/clis/hackernews/search.js +3 -1
- package/clis/hackernews/show.js +3 -1
- package/clis/hackernews/top.js +3 -1
- package/clis/hackernews/user.js +1 -0
- package/clis/hf/datasets.js +88 -0
- package/clis/hf/hf.test.js +16 -0
- package/clis/hf/models.js +91 -0
- package/clis/hf/paper.js +79 -0
- package/clis/hf/spaces.js +101 -0
- package/clis/hf/top.js +2 -0
- package/clis/homebrew/cask.js +39 -0
- package/clis/homebrew/formula.js +41 -0
- package/clis/homebrew/popular.js +54 -0
- package/clis/homebrew/utils.js +100 -0
- package/clis/hupu/__fixtures__/hot-home.html +64 -0
- package/clis/hupu/detail.js +1 -1
- package/clis/hupu/hot.js +157 -34
- package/clis/hupu/hot.test.js +224 -0
- package/clis/hupu/like.js +1 -0
- package/clis/hupu/mentions.js +2 -1
- package/clis/hupu/reply.js +1 -0
- package/clis/hupu/search.js +3 -2
- package/clis/hupu/unlike.js +1 -0
- package/clis/imdb/person.js +1 -0
- package/clis/imdb/reviews.js +1 -0
- package/clis/imdb/search.js +1 -0
- package/clis/imdb/title.js +1 -0
- package/clis/imdb/top.js +1 -0
- package/clis/imdb/trending.js +1 -0
- package/clis/indeed/indeed.test.js +375 -0
- package/clis/indeed/job.js +86 -0
- package/clis/indeed/search.js +110 -0
- package/clis/indeed/utils.js +152 -0
- package/clis/instagram/collection-create.js +1 -0
- package/clis/instagram/collection-delete.js +1 -0
- package/clis/instagram/comment.js +1 -0
- package/clis/instagram/download.js +1 -0
- package/clis/instagram/explore.js +1 -0
- package/clis/instagram/follow.js +1 -0
- package/clis/instagram/followers.js +1 -0
- package/clis/instagram/following.js +1 -0
- package/clis/instagram/like.js +1 -0
- package/clis/instagram/note.js +2 -1
- package/clis/instagram/note.test.js +1 -29
- package/clis/instagram/post.js +2 -1
- package/clis/instagram/post.test.js +1 -1
- package/clis/instagram/profile.js +1 -0
- package/clis/instagram/reel.js +2 -1
- package/clis/instagram/save.js +1 -0
- package/clis/instagram/saved.js +1 -0
- package/clis/instagram/search.js +1 -0
- package/clis/instagram/story.js +2 -1
- package/clis/instagram/story.test.js +1 -34
- package/clis/instagram/unfollow.js +1 -0
- package/clis/instagram/unlike.js +1 -0
- package/clis/instagram/unsave.js +1 -0
- package/clis/instagram/user.js +1 -0
- package/clis/jd/add-cart.js +1 -0
- package/clis/jd/cart.js +1 -0
- package/clis/jd/commands.test.js +1 -24
- package/clis/jd/detail.js +1 -0
- package/clis/jd/item.js +1 -0
- package/clis/jd/reviews.js +1 -0
- package/clis/jd/search.js +1 -0
- package/clis/jianyu/detail.js +1 -0
- package/clis/jianyu/search.js +1 -0
- package/clis/jike/comment.js +1 -0
- package/clis/jike/create.js +1 -0
- package/clis/jike/feed.js +3 -1
- package/clis/jike/like.js +1 -0
- package/clis/jike/notifications.js +1 -0
- package/clis/jike/post.js +1 -0
- package/clis/jike/repost.js +1 -0
- package/clis/jike/search.js +3 -1
- package/clis/jike/topic.js +1 -0
- package/clis/jike/user.js +3 -1
- package/clis/jimeng/generate.js +1 -0
- package/clis/jimeng/history.js +1 -0
- package/clis/jimeng/new.js +1 -0
- package/clis/jimeng/workspaces.js +1 -0
- package/clis/ke/chengjiao.js +1 -0
- package/clis/ke/ershoufang.js +1 -0
- package/clis/ke/xiaoqu.js +1 -0
- package/clis/ke/zufang.js +1 -0
- package/clis/lesswrong/comments.js +1 -0
- package/clis/lesswrong/curated.js +1 -0
- package/clis/lesswrong/frontpage.js +1 -0
- package/clis/lesswrong/new.js +1 -0
- package/clis/lesswrong/read.js +1 -0
- package/clis/lesswrong/sequences.js +1 -0
- package/clis/lesswrong/shortform.js +1 -0
- package/clis/lesswrong/tag.js +1 -0
- package/clis/lesswrong/tags.js +1 -0
- package/clis/lesswrong/top-month.js +1 -0
- package/clis/lesswrong/top-week.js +1 -0
- package/clis/lesswrong/top-year.js +1 -0
- package/clis/lesswrong/top.js +1 -0
- package/clis/lesswrong/user-posts.js +1 -0
- package/clis/lesswrong/user.js +1 -0
- package/clis/lichess/lichess.test.js +85 -0
- package/clis/lichess/top.js +46 -0
- package/clis/lichess/user.js +91 -0
- package/clis/lichess/utils.js +97 -0
- package/clis/linkedin/search.js +108 -10
- package/clis/linkedin/search.test.js +222 -0
- package/clis/linkedin/timeline.js +1 -0
- package/clis/linux-do/categories.js +1 -0
- package/clis/linux-do/feed.js +3 -5
- package/clis/linux-do/feed.test.js +35 -0
- package/clis/linux-do/search.js +1 -0
- package/clis/linux-do/tags.js +2 -1
- package/clis/linux-do/topic-content.js +1 -0
- package/clis/linux-do/topic.js +1 -0
- package/clis/linux-do/user-posts.js +1 -0
- package/clis/linux-do/user-topics.js +1 -0
- package/clis/lobsters/active.js +4 -1
- package/clis/lobsters/domain.js +92 -0
- package/clis/lobsters/hot.js +4 -1
- package/clis/lobsters/lobsters.test.js +169 -0
- package/clis/lobsters/newest.js +4 -1
- package/clis/lobsters/read.js +196 -0
- package/clis/lobsters/tag.js +4 -1
- package/clis/maimai/search-talents.js +1 -0
- package/clis/maven/artifact.js +49 -0
- package/clis/maven/search.js +51 -0
- package/clis/maven/utils.js +110 -0
- package/clis/mdn/search.js +97 -0
- package/clis/medium/feed.js +1 -0
- package/clis/medium/search.js +1 -0
- package/clis/medium/tag.js +135 -0
- package/clis/medium/user.js +1 -0
- package/clis/mubu/doc.js +1 -0
- package/clis/mubu/docs.js +1 -0
- package/clis/mubu/notes.js +1 -0
- package/clis/mubu/recent.js +1 -0
- package/clis/mubu/search.js +1 -0
- package/clis/notebooklm/current.js +1 -0
- package/clis/notebooklm/get.js +1 -0
- package/clis/notebooklm/history.js +1 -0
- package/clis/notebooklm/list.js +1 -0
- package/clis/notebooklm/note-list.js +1 -0
- package/clis/notebooklm/notes-get.js +1 -0
- package/clis/notebooklm/open.js +1 -0
- package/clis/notebooklm/source-fulltext.js +1 -0
- package/clis/notebooklm/source-get.js +1 -0
- package/clis/notebooklm/source-guide.js +1 -0
- package/clis/notebooklm/source-list.js +1 -0
- package/clis/notebooklm/status.js +1 -0
- package/clis/notebooklm/summary.js +1 -0
- package/clis/notion/export.js +1 -0
- package/clis/notion/favorites.js +1 -0
- package/clis/notion/new.js +1 -0
- package/clis/notion/read.js +1 -0
- package/clis/notion/search.js +1 -0
- package/clis/notion/sidebar.js +1 -0
- package/clis/notion/status.js +1 -0
- package/clis/notion/write.js +1 -0
- package/clis/nowcoder/companies.js +1 -0
- package/clis/nowcoder/creators.js +1 -0
- package/clis/nowcoder/detail.js +1 -0
- package/clis/nowcoder/experience.js +1 -0
- package/clis/nowcoder/hot.js +1 -0
- package/clis/nowcoder/jobs.js +1 -0
- package/clis/nowcoder/notifications.js +1 -0
- package/clis/nowcoder/papers.js +1 -0
- package/clis/nowcoder/practice.js +1 -0
- package/clis/nowcoder/recommend.js +1 -0
- package/clis/nowcoder/referral.js +1 -0
- package/clis/nowcoder/salary.js +1 -0
- package/clis/nowcoder/search.js +1 -0
- package/clis/nowcoder/suggest.js +1 -0
- package/clis/nowcoder/topics.js +1 -0
- package/clis/nowcoder/trending.js +1 -0
- package/clis/npm/downloads.js +59 -0
- package/clis/npm/package.js +70 -0
- package/clis/npm/search.js +49 -0
- package/clis/npm/utils.js +76 -0
- package/clis/nuget/nuget.test.js +111 -0
- package/clis/nuget/package.js +101 -0
- package/clis/nuget/search.js +69 -0
- package/clis/nuget/utils.js +87 -0
- package/clis/nvd/cve.js +121 -0
- package/clis/oeis/oeis.test.js +88 -0
- package/clis/oeis/search.js +63 -0
- package/clis/oeis/sequence.js +71 -0
- package/clis/oeis/utils.js +88 -0
- package/clis/ones/login.js +1 -0
- package/clis/ones/logout.js +1 -0
- package/clis/ones/me.js +1 -0
- package/clis/ones/my-tasks.js +1 -0
- package/clis/ones/task.js +1 -0
- package/clis/ones/tasks.js +1 -0
- package/clis/ones/token-info.js +1 -0
- package/clis/ones/worklog.js +1 -0
- package/clis/openalex/search.js +69 -0
- package/clis/openalex/utils.js +160 -0
- package/clis/openalex/work.js +65 -0
- package/clis/openfda/drug-label.js +74 -0
- package/clis/openfda/food-recall.js +65 -0
- package/clis/openfda/openfda.test.js +114 -0
- package/clis/openfda/utils.js +67 -0
- package/clis/openreview/openreview.test.js +345 -0
- package/clis/openreview/paper.js +43 -0
- package/clis/openreview/reviews.js +131 -0
- package/clis/openreview/search.js +46 -0
- package/clis/openreview/utils.js +158 -0
- package/clis/openreview/venue.js +63 -0
- package/clis/osv/osv.test.js +97 -0
- package/clis/osv/query.js +72 -0
- package/clis/osv/utils.js +169 -0
- package/clis/osv/vulnerability.js +54 -0
- package/clis/packagist/package.js +49 -0
- package/clis/packagist/search.js +43 -0
- package/clis/packagist/utils.js +113 -0
- package/clis/paperreview/feedback.js +2 -1
- package/clis/paperreview/review.js +2 -1
- package/clis/paperreview/submit.js +2 -1
- package/clis/pixiv/detail.js +1 -0
- package/clis/pixiv/download.js +1 -0
- package/clis/pixiv/download.test.js +1 -1
- package/clis/pixiv/illusts.js +2 -1
- package/clis/pixiv/illusts.test.js +1 -1
- package/clis/pixiv/ranking.js +2 -1
- package/clis/pixiv/search.js +2 -1
- package/clis/pixiv/search.test.js +1 -1
- package/clis/pixiv/user.js +2 -0
- package/clis/powerchina/search.js +1 -0
- package/clis/producthunt/browse.js +1 -0
- package/clis/producthunt/hot.js +1 -0
- package/clis/producthunt/posts.js +1 -0
- package/clis/producthunt/today.js +1 -0
- package/clis/pubmed/article.js +50 -0
- package/clis/pubmed/author.js +64 -0
- package/clis/pubmed/citations.js +36 -0
- package/clis/pubmed/pubmed.test.js +276 -0
- package/clis/pubmed/related.js +45 -0
- package/clis/pubmed/search.js +75 -0
- package/clis/pubmed/utils.js +309 -0
- package/clis/pypi/downloads.js +66 -0
- package/clis/pypi/package.js +79 -0
- package/clis/pypi/utils.js +55 -0
- package/clis/quark/ls.js +1 -0
- package/clis/quark/mkdir.js +1 -0
- package/clis/quark/mv.js +2 -1
- package/clis/quark/rename.js +1 -0
- package/clis/quark/rm.js +1 -0
- package/clis/quark/save.js +2 -1
- package/clis/quark/share-tree.js +1 -0
- package/clis/qwen/ask.js +85 -0
- package/clis/qwen/detail.js +62 -0
- package/clis/qwen/history.js +61 -0
- package/clis/qwen/image.js +179 -0
- package/clis/qwen/new.js +23 -0
- package/clis/qwen/read.js +41 -0
- package/clis/qwen/send.js +55 -0
- package/clis/qwen/status.js +37 -0
- package/clis/qwen/utils.js +409 -0
- package/clis/qwen/utils.test.js +45 -0
- package/clis/reddit/comment.js +1 -0
- package/clis/reddit/frontpage.js +1 -0
- package/clis/reddit/hot.js +6 -1
- package/clis/reddit/hot.test.js +18 -0
- package/clis/reddit/popular.js +1 -0
- package/clis/reddit/read.js +1 -0
- package/clis/reddit/save.js +1 -0
- package/clis/reddit/saved.js +1 -0
- package/clis/reddit/search.js +1 -0
- package/clis/reddit/subreddit.js +1 -0
- package/clis/reddit/subscribe.js +1 -0
- package/clis/reddit/upvote.js +1 -0
- package/clis/reddit/upvoted.js +1 -0
- package/clis/reddit/user-comments.js +1 -0
- package/clis/reddit/user-posts.js +1 -0
- package/clis/reddit/user.js +1 -0
- package/clis/rest-countries/country.js +65 -0
- package/clis/rest-countries/region.js +64 -0
- package/clis/rest-countries/rest-countries.test.js +83 -0
- package/clis/rest-countries/utils.js +126 -0
- package/clis/reuters/article-detail.js +53 -0
- package/clis/reuters/reuters.test.js +299 -0
- package/clis/reuters/search.js +46 -34
- package/clis/reuters/utils.js +159 -0
- package/clis/rfc/rfc.js +52 -0
- package/clis/rfc/rfc.test.js +74 -0
- package/clis/rfc/utils.js +72 -0
- package/clis/rubygems/gem.js +42 -0
- package/clis/rubygems/search.js +47 -0
- package/clis/rubygems/utils.js +86 -0
- package/clis/sinablog/article.js +1 -0
- package/clis/sinablog/hot.js +1 -0
- package/clis/sinablog/search.js +1 -0
- package/clis/sinablog/user.js +1 -0
- package/clis/sinafinance/news.js +1 -0
- package/clis/sinafinance/rolling-news.js +1 -0
- package/clis/sinafinance/stock-rank.js +1 -0
- package/clis/sinafinance/stock.js +1 -0
- package/clis/smzdm/search.js +1 -0
- package/clis/spotify/spotify.js +11 -0
- package/clis/stackoverflow/bounties.js +11 -3
- package/clis/stackoverflow/hot.js +10 -2
- package/clis/stackoverflow/read.js +314 -0
- package/clis/stackoverflow/related.js +66 -0
- package/clis/stackoverflow/search.js +10 -2
- package/clis/stackoverflow/stackoverflow.test.js +404 -0
- package/clis/stackoverflow/tag.js +60 -0
- package/clis/stackoverflow/unanswered.js +9 -2
- package/clis/stackoverflow/user.js +50 -0
- package/clis/stackoverflow/utils.js +118 -0
- package/clis/steam/app.js +67 -0
- package/clis/steam/search.js +58 -0
- package/clis/steam/steam.test.js +46 -0
- package/clis/steam/top-sellers.js +1 -0
- package/clis/steam/utils.js +107 -0
- package/clis/substack/feed.js +1 -0
- package/clis/substack/publication.js +1 -0
- package/clis/substack/search.js +1 -0
- package/clis/taobao/add-cart.js +1 -0
- package/clis/taobao/cart.js +1 -0
- package/clis/taobao/commands.test.js +1 -24
- package/clis/taobao/detail.js +1 -0
- package/clis/taobao/reviews.js +1 -0
- package/clis/taobao/search.js +1 -0
- package/clis/tdx/hot-rank.js +1 -0
- package/clis/test-utils.js +61 -0
- package/clis/ths/hot-rank.js +1 -0
- package/clis/tieba/hot.js +2 -2
- package/clis/tieba/posts.js +1 -0
- package/clis/tieba/read.js +1 -0
- package/clis/tieba/search.js +2 -1
- package/clis/tiktok/comment.js +128 -40
- package/clis/tiktok/creator-videos.js +270 -0
- package/clis/tiktok/creator-videos.test.js +113 -0
- package/clis/tiktok/explore.js +138 -29
- package/clis/tiktok/follow.js +116 -33
- package/clis/tiktok/following.js +157 -35
- package/clis/tiktok/friends.js +140 -37
- package/clis/tiktok/like.js +1 -0
- package/clis/tiktok/live.js +138 -41
- package/clis/tiktok/notifications.js +142 -38
- package/clis/tiktok/profile.js +1 -0
- package/clis/tiktok/refactor.test.js +389 -0
- package/clis/tiktok/save.js +1 -0
- package/clis/tiktok/search.js +1 -0
- package/clis/tiktok/unfollow.js +125 -38
- package/clis/tiktok/unlike.js +1 -0
- package/clis/tiktok/unsave.js +1 -0
- package/clis/tiktok/user.js +204 -29
- package/clis/tiktok/utils.js +505 -0
- package/clis/tiktok/write-refactor.test.js +370 -0
- package/clis/toutiao/articles.js +37 -62
- package/clis/toutiao/hot.js +63 -0
- package/clis/toutiao/toutiao.test.js +378 -0
- package/clis/toutiao/utils.js +161 -0
- package/clis/tvmaze/search.js +61 -0
- package/clis/tvmaze/show.js +60 -0
- package/clis/tvmaze/tvmaze.test.js +93 -0
- package/clis/tvmaze/utils.js +110 -0
- package/clis/twitter/accept.js +2 -1
- package/clis/twitter/article.js +1 -0
- package/clis/twitter/block.js +1 -0
- package/clis/twitter/bookmark.js +1 -0
- package/clis/twitter/bookmarks.js +2 -1
- package/clis/twitter/delete.js +1 -0
- package/clis/twitter/download.js +1 -0
- package/clis/twitter/follow.js +1 -0
- package/clis/twitter/followers.js +135 -69
- package/clis/twitter/following.js +1 -0
- package/clis/twitter/hide-reply.js +1 -0
- package/clis/twitter/like.js +1 -0
- package/clis/twitter/likes.js +2 -1
- package/clis/twitter/list-add.js +1 -0
- package/clis/twitter/list-remove.js +1 -0
- package/clis/twitter/list-tweets.js +1 -0
- package/clis/twitter/lists.js +1 -0
- package/clis/twitter/notifications.js +1 -0
- package/clis/twitter/post.js +1 -0
- package/clis/twitter/profile.js +1 -0
- package/clis/twitter/reply-dm.js +2 -1
- package/clis/twitter/reply.js +1 -0
- package/clis/twitter/reply.test.js +1 -29
- package/clis/twitter/search.js +1 -0
- package/clis/twitter/thread.js +1 -0
- package/clis/twitter/timeline.js +1 -0
- package/clis/twitter/trending.js +11 -12
- package/clis/twitter/trending.test.js +15 -0
- package/clis/twitter/tweets.js +2 -1
- package/clis/twitter/tweets.test.js +2 -2
- package/clis/twitter/unblock.js +1 -0
- package/clis/twitter/unbookmark.js +1 -0
- package/clis/twitter/unfollow.js +1 -0
- package/clis/uisdc/news.js +105 -0
- package/clis/uisdc/news.test.js +66 -0
- package/clis/uiverse/code.js +1 -0
- package/clis/uiverse/preview.js +1 -0
- package/clis/v2ex/daily.js +1 -0
- package/clis/v2ex/hot.js +1 -0
- package/clis/v2ex/latest.js +1 -0
- package/clis/v2ex/me.js +1 -0
- package/clis/v2ex/member.js +1 -0
- package/clis/v2ex/node.js +1 -0
- package/clis/v2ex/nodes.js +1 -0
- package/clis/v2ex/notifications.js +1 -0
- package/clis/v2ex/replies.js +1 -0
- package/clis/v2ex/topic.js +1 -0
- package/clis/v2ex/user.js +1 -0
- package/clis/wanfang/search.js +1 -1
- package/clis/web/read.js +48 -17
- package/clis/web/read.test.js +101 -1
- package/clis/weibo/comments.js +1 -0
- package/clis/weibo/favorites.js +1 -0
- package/clis/weibo/feed.js +3 -1
- package/clis/weibo/hot.js +1 -0
- package/clis/weibo/me.js +1 -0
- package/clis/weibo/post.js +1 -0
- package/clis/weibo/publish.js +1 -0
- package/clis/weibo/search.js +8 -2
- package/clis/weibo/user.js +1 -0
- package/clis/weixin/create-draft.js +2 -1
- package/clis/weixin/download.js +1 -0
- package/clis/weixin/drafts.js +2 -1
- package/clis/weixin/drafts.test.js +5 -1
- package/clis/weixin/search.js +157 -0
- package/clis/weixin/search.test.js +227 -0
- package/clis/weread/ai-outline.js +1 -0
- package/clis/weread/book.js +1 -0
- package/clis/weread/highlights.js +1 -0
- package/clis/weread/notebooks.js +1 -0
- package/clis/weread/notes.js +1 -0
- package/clis/weread/ranking.js +1 -0
- package/clis/weread/search.js +1 -0
- package/clis/weread/shelf.js +1 -0
- package/clis/wikidata/entity.js +60 -0
- package/clis/wikidata/search.js +50 -0
- package/clis/wikidata/utils.js +117 -0
- package/clis/wikidata/wikidata.test.js +83 -0
- package/clis/wikipedia/page.js +95 -0
- package/clis/wikipedia/random.js +1 -0
- package/clis/wikipedia/search.js +1 -0
- package/clis/wikipedia/summary.js +1 -0
- package/clis/wikipedia/trending.js +1 -0
- package/clis/wttr/current.js +63 -0
- package/clis/wttr/forecast.js +71 -0
- package/clis/wttr/utils.js +50 -0
- package/clis/wttr/wttr.test.js +84 -0
- package/clis/xianyu/chat.js +17 -4
- package/clis/xianyu/chat.test.js +64 -0
- package/clis/xianyu/item.js +1 -0
- package/clis/xianyu/publish.js +485 -0
- package/clis/xianyu/publish.test.js +220 -0
- package/clis/xianyu/search.js +1 -0
- package/clis/xiaoe/catalog.js +105 -39
- package/clis/xiaoe/content.js +165 -29
- package/clis/xiaoe/courses.js +86 -28
- package/clis/xiaoe/detail.js +1 -0
- package/clis/xiaoe/play-url.js +1 -0
- package/clis/xiaoe/xiaoe.test.js +486 -0
- package/clis/xiaohongshu/comments.js +1 -0
- package/clis/xiaohongshu/creator-note-detail.js +1 -0
- package/clis/xiaohongshu/creator-notes-summary.js +2 -1
- package/clis/xiaohongshu/creator-notes.js +1 -0
- package/clis/xiaohongshu/creator-profile.js +1 -0
- package/clis/xiaohongshu/creator-stats.js +1 -0
- package/clis/xiaohongshu/download.js +1 -0
- package/clis/xiaohongshu/feed.js +2 -1
- package/clis/xiaohongshu/note.js +1 -0
- package/clis/xiaohongshu/notifications.js +1 -0
- package/clis/xiaohongshu/publish.js +17 -3
- package/clis/xiaohongshu/publish.test.js +46 -1
- package/clis/xiaohongshu/search.js +1 -0
- package/clis/xiaohongshu/user.js +1 -0
- package/clis/xiaoyuzhou/download.js +1 -0
- package/clis/xiaoyuzhou/episode.js +1 -0
- package/clis/xiaoyuzhou/podcast-episodes.js +1 -0
- package/clis/xiaoyuzhou/podcast.js +1 -0
- package/clis/xiaoyuzhou/transcript.js +1 -0
- package/clis/xueqiu/comments.js +1 -0
- package/clis/xueqiu/earnings-date.js +1 -0
- package/clis/xueqiu/feed.js +1 -0
- package/clis/xueqiu/fund-holdings.js +1 -0
- package/clis/xueqiu/fund-snapshot.js +1 -0
- package/clis/xueqiu/groups.js +1 -0
- package/clis/xueqiu/hot-stock.js +1 -0
- package/clis/xueqiu/hot.js +1 -0
- package/clis/xueqiu/kline.js +1 -0
- package/clis/xueqiu/search.js +1 -0
- package/clis/xueqiu/stock.js +1 -0
- package/clis/xueqiu/watchlist.js +1 -0
- package/clis/yahoo-finance/quote.js +1 -0
- package/clis/yollomi/background.js +1 -0
- package/clis/yollomi/edit.js +1 -0
- package/clis/yollomi/face-swap.js +1 -0
- package/clis/yollomi/generate.js +1 -0
- package/clis/yollomi/models.js +1 -0
- package/clis/yollomi/object-remover.js +1 -0
- package/clis/yollomi/remove-bg.js +1 -0
- package/clis/yollomi/restore.js +1 -0
- package/clis/yollomi/try-on.js +1 -0
- package/clis/yollomi/upload.js +1 -0
- package/clis/yollomi/upscale.js +1 -0
- package/clis/yollomi/video.js +1 -0
- package/clis/youtube/channel.js +1 -0
- package/clis/youtube/comments.js +1 -0
- package/clis/youtube/feed.js +8 -7
- package/clis/youtube/feed.test.js +131 -0
- package/clis/youtube/history.js +1 -0
- package/clis/youtube/like.js +1 -0
- package/clis/youtube/playlist.js +1 -0
- package/clis/youtube/search.js +1 -0
- package/clis/youtube/subscribe.js +1 -0
- package/clis/youtube/subscriptions.js +1 -0
- package/clis/youtube/transcript.js +14 -19
- package/clis/youtube/transcript.test.js +17 -0
- package/clis/youtube/unlike.js +1 -0
- package/clis/youtube/unsubscribe.js +1 -0
- package/clis/youtube/video.js +1 -0
- package/clis/youtube/watch-later.js +1 -0
- package/clis/yuanbao/ask.js +18 -66
- package/clis/yuanbao/ask.test.js +5 -5
- package/clis/yuanbao/detail.js +65 -0
- package/clis/yuanbao/history.js +51 -0
- package/clis/yuanbao/new.js +2 -0
- package/clis/yuanbao/read.js +38 -0
- package/clis/yuanbao/send.js +57 -0
- package/clis/yuanbao/shared.js +297 -5
- package/clis/yuanbao/shared.test.js +80 -0
- package/clis/yuanbao/status.js +44 -0
- package/clis/zhihu/answer.js +1 -0
- package/clis/zhihu/collection.js +1 -0
- package/clis/zhihu/collections.js +1 -0
- package/clis/zhihu/comment.js +1 -0
- package/clis/zhihu/download.js +1 -0
- package/clis/zhihu/favorite.js +1 -0
- package/clis/zhihu/follow.js +1 -0
- package/clis/zhihu/hot.js +1 -0
- package/clis/zhihu/like.js +1 -0
- package/clis/zhihu/question.js +1 -0
- package/clis/zhihu/search.js +1 -0
- package/clis/zlibrary/commands.test.js +1 -11
- package/clis/zlibrary/info.js +1 -0
- package/clis/zlibrary/search.js +1 -0
- package/clis/zsxq/dynamics.js +1 -0
- package/clis/zsxq/groups.js +1 -0
- package/clis/zsxq/search.js +1 -0
- package/clis/zsxq/topic.js +1 -0
- package/clis/zsxq/topics.js +1 -0
- package/dist/src/adapter-source.test.js +1 -1
- package/dist/src/browser/analyze.test.js +2 -0
- package/dist/src/browser/base-page.d.ts +18 -0
- package/dist/src/browser/base-page.js +116 -4
- package/dist/src/browser/base-page.test.js +108 -0
- package/dist/src/browser/cdp.d.ts +1 -0
- package/dist/src/browser/cdp.js +57 -9
- package/dist/src/browser/cdp.test.js +3 -0
- package/dist/src/browser/daemon-client.d.ts +4 -0
- package/dist/src/browser/errors.js +1 -1
- package/dist/src/browser/page.d.ts +2 -1
- package/dist/src/browser/page.js +9 -1
- package/dist/src/browser/page.test.js +46 -0
- package/dist/src/browser/target-errors.d.ts +2 -1
- package/dist/src/browser/target-errors.js +1 -0
- package/dist/src/browser/target-resolver.d.ts +35 -3
- package/dist/src/browser/target-resolver.js +59 -10
- package/dist/src/browser/verify-fixture.d.ts +6 -1
- package/dist/src/browser/verify-fixture.js +87 -0
- package/dist/src/browser/verify-fixture.test.js +44 -1
- package/dist/src/build-manifest.js +12 -4
- package/dist/src/build-manifest.test.js +20 -20
- package/dist/src/capabilityRouting.d.ts +16 -1
- package/dist/src/capabilityRouting.js +24 -1
- package/dist/src/capabilityRouting.test.js +20 -2
- package/dist/src/cli.js +213 -12
- package/dist/src/cli.test.js +329 -0
- package/dist/src/commanderAdapter.d.ts +1 -1
- package/dist/src/commanderAdapter.js +17 -12
- package/dist/src/commanderAdapter.test.js +7 -7
- package/dist/src/convention-audit.d.ts +50 -0
- package/dist/src/convention-audit.js +546 -0
- package/dist/src/convention-audit.test.d.ts +1 -0
- package/dist/src/convention-audit.test.js +226 -0
- package/dist/src/discovery.js +4 -5
- package/dist/src/doctor.js +0 -1
- package/dist/src/doctor.test.js +1 -1
- package/dist/src/engine.test.js +10 -10
- package/dist/src/errors.js +1 -1
- package/dist/src/execution.d.ts +1 -1
- package/dist/src/execution.js +111 -27
- package/dist/src/execution.test.js +334 -25
- package/dist/src/help.d.ts +36 -0
- package/dist/src/help.js +171 -0
- package/dist/src/help.test.d.ts +1 -0
- package/dist/src/help.test.js +54 -0
- package/dist/src/main.js +27 -8
- package/dist/src/manifest-types.d.ts +7 -3
- package/dist/src/pipeline/executor.js +1 -1
- package/dist/src/pipeline/executor.test.js +8 -0
- package/dist/src/pipeline/registry.d.ts +9 -0
- package/dist/src/pipeline/registry.js +13 -1
- package/dist/src/pipeline/steps/browser.d.ts +1 -0
- package/dist/src/pipeline/steps/browser.js +10 -0
- package/dist/src/pipeline/steps/download.test.js +1 -0
- package/dist/src/plugin.test.js +26 -26
- package/dist/src/registry-api.d.ts +1 -1
- package/dist/src/registry.d.ts +17 -11
- package/dist/src/registry.js +24 -6
- package/dist/src/registry.test.js +29 -22
- package/dist/src/runtime.d.ts +2 -1
- package/dist/src/runtime.js +1 -1
- package/dist/src/serialization.d.ts +6 -2
- package/dist/src/serialization.js +31 -7
- package/dist/src/serialization.test.js +41 -2
- package/dist/src/types.d.ts +19 -0
- package/dist/src/validate.js +15 -11
- package/dist/src/validate.test.d.ts +9 -0
- package/dist/src/validate.test.js +90 -0
- package/package.json +4 -1
- package/scripts/check-listing-id-pairing.mjs +193 -0
- package/scripts/check-silent-column-drop.mjs +105 -0
- package/scripts/check-typed-error-lint.mjs +118 -0
- package/scripts/fetch-adapters.js +1 -1
- package/scripts/silent-column-drop-baseline.json +962 -0
- package/scripts/typed-error-lint-baseline.json +1514 -0
- package/clis/ctrip/search.test.js +0 -64
- package/clis/gov-policy/commands.test.js +0 -27
- package/clis/linux-do/category.js +0 -36
- package/clis/linux-do/hot.js +0 -25
- package/clis/linux-do/latest.js +0 -18
- package/clis/pixiv/test-utils.js +0 -23
- package/clis/toutiao/articles.test.js +0 -30
- package/dist/src/analysis.d.ts +0 -40
- package/dist/src/analysis.js +0 -172
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* - selector_not_found: 0 matches
|
|
16
16
|
* - selector_ambiguous: >1 matches for a write op without --nth
|
|
17
17
|
* - selector_nth_out_of_range: --nth beyond matches_n
|
|
18
|
+
* - not_editable: target exists but cannot accept text input
|
|
18
19
|
*/
|
|
19
20
|
export class TargetError extends Error {
|
|
20
21
|
code;
|
|
@@ -72,11 +72,32 @@ export declare function resolveTargetJs(ref: string, opts?: ResolveOptions): str
|
|
|
72
72
|
* Generate JS for click that uses the unified resolver.
|
|
73
73
|
* Assumes resolveTargetJs has been called and __resolved is set.
|
|
74
74
|
*/
|
|
75
|
-
export declare function clickResolvedJs(
|
|
75
|
+
export declare function clickResolvedJs(opts?: {
|
|
76
|
+
skipScroll?: boolean;
|
|
77
|
+
}): string;
|
|
76
78
|
/**
|
|
77
79
|
* Generate JS for type that uses the unified resolver.
|
|
78
80
|
*/
|
|
79
81
|
export declare function typeResolvedJs(text: string): string;
|
|
82
|
+
export type FillResolvedResult = {
|
|
83
|
+
ok: true;
|
|
84
|
+
actual: string;
|
|
85
|
+
expected: string;
|
|
86
|
+
length: number;
|
|
87
|
+
mode: 'input' | 'textarea' | 'contenteditable';
|
|
88
|
+
} | {
|
|
89
|
+
ok: false;
|
|
90
|
+
actual: string;
|
|
91
|
+
expected: string;
|
|
92
|
+
length: number;
|
|
93
|
+
mode: 'input' | 'textarea' | 'contenteditable';
|
|
94
|
+
} | {
|
|
95
|
+
ok: false;
|
|
96
|
+
reason: string;
|
|
97
|
+
tag?: string;
|
|
98
|
+
type?: string;
|
|
99
|
+
role?: string;
|
|
100
|
+
};
|
|
80
101
|
/**
|
|
81
102
|
* Prepare the resolved element for native CDP Input.insertText.
|
|
82
103
|
*
|
|
@@ -84,12 +105,23 @@ export declare function typeResolvedJs(text: string): string;
|
|
|
84
105
|
* focus the editable target, select its current contents, then let CDP insert
|
|
85
106
|
* real browser text input so rich editors can update their internal state.
|
|
86
107
|
*/
|
|
87
|
-
export declare function prepareNativeTypeResolvedJs(
|
|
108
|
+
export declare function prepareNativeTypeResolvedJs(opts?: {
|
|
109
|
+
skipScroll?: boolean;
|
|
110
|
+
skipFocus?: boolean;
|
|
111
|
+
}): string;
|
|
112
|
+
/**
|
|
113
|
+
* Verify the exact value/text currently held by the resolved editable target.
|
|
114
|
+
* Assumes resolveTargetJs and prepareNativeTypeResolvedJs have already set
|
|
115
|
+
* `window.__resolved` to the normalized editable host.
|
|
116
|
+
*/
|
|
117
|
+
export declare function verifyFilledResolvedJs(expected: string): string;
|
|
88
118
|
/**
|
|
89
119
|
* Generate JS for scrollTo that uses the unified resolver.
|
|
90
120
|
* Assumes resolveTargetJs has been called and __resolved is set.
|
|
91
121
|
*/
|
|
92
|
-
export declare function scrollResolvedJs(
|
|
122
|
+
export declare function scrollResolvedJs(opts?: {
|
|
123
|
+
skipScroll?: boolean;
|
|
124
|
+
}): string;
|
|
93
125
|
/**
|
|
94
126
|
* Generate JS to get text content of resolved element.
|
|
95
127
|
*/
|
|
@@ -277,12 +277,13 @@ export function resolveTargetJs(ref, opts = {}) {
|
|
|
277
277
|
* Generate JS for click that uses the unified resolver.
|
|
278
278
|
* Assumes resolveTargetJs has been called and __resolved is set.
|
|
279
279
|
*/
|
|
280
|
-
export function clickResolvedJs() {
|
|
280
|
+
export function clickResolvedJs(opts = {}) {
|
|
281
|
+
const shouldScroll = opts.skipScroll ? 'false' : 'true';
|
|
281
282
|
return `
|
|
282
283
|
(() => {
|
|
283
284
|
const el = window.__resolved;
|
|
284
285
|
if (!el) throw new Error('No resolved element');
|
|
285
|
-
el.scrollIntoView({ behavior: 'instant', block: 'center' });
|
|
286
|
+
if (${shouldScroll}) el.scrollIntoView({ behavior: 'instant', block: 'center' });
|
|
286
287
|
const rect = el.getBoundingClientRect();
|
|
287
288
|
const x = Math.round(rect.left + rect.width / 2);
|
|
288
289
|
const y = Math.round(rect.top + rect.height / 2);
|
|
@@ -338,7 +339,9 @@ export function typeResolvedJs(text) {
|
|
|
338
339
|
* focus the editable target, select its current contents, then let CDP insert
|
|
339
340
|
* real browser text input so rich editors can update their internal state.
|
|
340
341
|
*/
|
|
341
|
-
export function prepareNativeTypeResolvedJs() {
|
|
342
|
+
export function prepareNativeTypeResolvedJs(opts = {}) {
|
|
343
|
+
const shouldScroll = opts.skipScroll ? 'false' : 'true';
|
|
344
|
+
const shouldFocus = opts.skipFocus ? 'false' : 'true';
|
|
342
345
|
return `
|
|
343
346
|
(() => {
|
|
344
347
|
const original = window.__resolved;
|
|
@@ -369,11 +372,13 @@ export function prepareNativeTypeResolvedJs() {
|
|
|
369
372
|
}
|
|
370
373
|
|
|
371
374
|
window.__resolved = el;
|
|
372
|
-
el.scrollIntoView({ behavior: 'instant', block: 'center', inline: 'nearest' });
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
375
|
+
if (${shouldScroll}) el.scrollIntoView({ behavior: 'instant', block: 'center', inline: 'nearest' });
|
|
376
|
+
if (${shouldFocus}) {
|
|
377
|
+
try {
|
|
378
|
+
el.focus({ preventScroll: true });
|
|
379
|
+
} catch (_) {
|
|
380
|
+
el.focus();
|
|
381
|
+
}
|
|
377
382
|
}
|
|
378
383
|
|
|
379
384
|
if (editableHost) {
|
|
@@ -406,16 +411,60 @@ export function prepareNativeTypeResolvedJs() {
|
|
|
406
411
|
})()
|
|
407
412
|
`;
|
|
408
413
|
}
|
|
414
|
+
/**
|
|
415
|
+
* Verify the exact value/text currently held by the resolved editable target.
|
|
416
|
+
* Assumes resolveTargetJs and prepareNativeTypeResolvedJs have already set
|
|
417
|
+
* `window.__resolved` to the normalized editable host.
|
|
418
|
+
*/
|
|
419
|
+
export function verifyFilledResolvedJs(expected) {
|
|
420
|
+
const safeText = JSON.stringify(expected);
|
|
421
|
+
return `
|
|
422
|
+
(() => {
|
|
423
|
+
const el = window.__resolved;
|
|
424
|
+
if (!el) return { ok: false, reason: 'no_resolved_element' };
|
|
425
|
+
|
|
426
|
+
const tag = el.tagName ? el.tagName.toLowerCase() : '';
|
|
427
|
+
const isInput = el instanceof HTMLInputElement;
|
|
428
|
+
const isTextarea = el instanceof HTMLTextAreaElement;
|
|
429
|
+
const mode = el.isContentEditable
|
|
430
|
+
? 'contenteditable'
|
|
431
|
+
: isTextarea
|
|
432
|
+
? 'textarea'
|
|
433
|
+
: isInput
|
|
434
|
+
? 'input'
|
|
435
|
+
: '';
|
|
436
|
+
|
|
437
|
+
if (!mode) {
|
|
438
|
+
return {
|
|
439
|
+
ok: false,
|
|
440
|
+
reason: 'not_editable',
|
|
441
|
+
tag,
|
|
442
|
+
role: el.getAttribute ? (el.getAttribute('role') || '') : '',
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const actual = mode === 'contenteditable' ? (el.innerText || '') : String(el.value || '');
|
|
447
|
+
return {
|
|
448
|
+
ok: actual === ${safeText},
|
|
449
|
+
actual,
|
|
450
|
+
expected: ${safeText},
|
|
451
|
+
length: actual.length,
|
|
452
|
+
mode,
|
|
453
|
+
};
|
|
454
|
+
})()
|
|
455
|
+
`;
|
|
456
|
+
}
|
|
409
457
|
/**
|
|
410
458
|
* Generate JS for scrollTo that uses the unified resolver.
|
|
411
459
|
* Assumes resolveTargetJs has been called and __resolved is set.
|
|
412
460
|
*/
|
|
413
|
-
export function scrollResolvedJs() {
|
|
461
|
+
export function scrollResolvedJs(opts = {}) {
|
|
462
|
+
const shouldScroll = opts.skipScroll ? 'false' : 'true';
|
|
414
463
|
return `
|
|
415
464
|
(() => {
|
|
416
465
|
const el = window.__resolved;
|
|
417
466
|
if (!el) throw new Error('No resolved element');
|
|
418
|
-
el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
|
|
467
|
+
if (${shouldScroll}) el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
|
|
419
468
|
return { scrolled: true, tag: el.tagName.toLowerCase(), text: (el.textContent || '').trim().slice(0, 80) };
|
|
420
469
|
})()
|
|
421
470
|
`;
|
|
@@ -31,11 +31,15 @@ export type Fixture = {
|
|
|
31
31
|
expect?: FixtureExpect;
|
|
32
32
|
};
|
|
33
33
|
export type ValidationFailure = {
|
|
34
|
-
rule: 'rowCount' | 'column' | 'type' | 'pattern' | 'notEmpty' | 'mustNotContain' | 'mustBeTruthy';
|
|
34
|
+
rule: 'rowCount' | 'column' | 'type' | 'pattern' | 'notEmpty' | 'mustNotContain' | 'mustBeTruthy' | 'shapeKeyCount' | 'shapeDepth' | 'shapeNestedId';
|
|
35
35
|
detail: string;
|
|
36
36
|
rowIndex?: number;
|
|
37
37
|
};
|
|
38
38
|
export type Row = Record<string, unknown>;
|
|
39
|
+
export type RowShapeOptions = {
|
|
40
|
+
maxTopLevelKeys?: number;
|
|
41
|
+
maxNestedDepth?: number;
|
|
42
|
+
};
|
|
39
43
|
export declare function fixturePath(site: string, command: string): string;
|
|
40
44
|
export declare function loadFixture(site: string, command: string): Fixture | null;
|
|
41
45
|
export declare function writeFixture(site: string, command: string, fixture: Fixture): string;
|
|
@@ -51,6 +55,7 @@ export declare function writeFixture(site: string, command: string, fixture: Fix
|
|
|
51
55
|
*/
|
|
52
56
|
export declare function deriveFixture(rows: Row[], args?: FixtureArgs): Fixture;
|
|
53
57
|
export declare function validateRows(rows: Row[], fixture: Fixture): ValidationFailure[];
|
|
58
|
+
export declare function validateRowShape(rows: Row[], opts?: RowShapeOptions): ValidationFailure[];
|
|
54
59
|
/**
|
|
55
60
|
* Convert fixture args into argv tokens appended after the command name.
|
|
56
61
|
* - Array form is passed through verbatim (stringified), supporting positional subjects.
|
|
@@ -30,6 +30,26 @@
|
|
|
30
30
|
import * as fs from 'node:fs';
|
|
31
31
|
import * as os from 'node:os';
|
|
32
32
|
import * as path from 'node:path';
|
|
33
|
+
const DEFAULT_MAX_TOP_LEVEL_KEYS = 12;
|
|
34
|
+
const DEFAULT_MAX_NESTED_DEPTH = 1;
|
|
35
|
+
const ID_SHAPED_KEY_PATTERNS = [
|
|
36
|
+
/^id$/i,
|
|
37
|
+
/_id$/i,
|
|
38
|
+
/Id$/,
|
|
39
|
+
/^short_id$/i,
|
|
40
|
+
/^bvid$/i,
|
|
41
|
+
/^aid$/i,
|
|
42
|
+
/^tid$/i,
|
|
43
|
+
/^asin$/i,
|
|
44
|
+
/^sku$/i,
|
|
45
|
+
/^isbn$/i,
|
|
46
|
+
/^doi$/i,
|
|
47
|
+
/^slug$/i,
|
|
48
|
+
/^hn_id$/i,
|
|
49
|
+
/^username$/i,
|
|
50
|
+
/^handle$/i,
|
|
51
|
+
/^uri$/i,
|
|
52
|
+
];
|
|
33
53
|
export function fixturePath(site, command) {
|
|
34
54
|
return path.join(os.homedir(), '.opencli', 'sites', site, 'verify', `${command}.json`);
|
|
35
55
|
}
|
|
@@ -180,6 +200,39 @@ export function validateRows(rows, fixture) {
|
|
|
180
200
|
});
|
|
181
201
|
return failures;
|
|
182
202
|
}
|
|
203
|
+
export function validateRowShape(rows, opts = {}) {
|
|
204
|
+
const failures = [];
|
|
205
|
+
const maxTopLevelKeys = opts.maxTopLevelKeys ?? DEFAULT_MAX_TOP_LEVEL_KEYS;
|
|
206
|
+
const maxNestedDepth = opts.maxNestedDepth ?? DEFAULT_MAX_NESTED_DEPTH;
|
|
207
|
+
rows.forEach((row, i) => {
|
|
208
|
+
const keys = Object.keys(row);
|
|
209
|
+
if (keys.length > maxTopLevelKeys) {
|
|
210
|
+
failures.push({
|
|
211
|
+
rule: 'shapeKeyCount',
|
|
212
|
+
detail: `row has ${keys.length} top-level keys, expected at most ${maxTopLevelKeys}`,
|
|
213
|
+
rowIndex: i,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
for (const [key, value] of Object.entries(row)) {
|
|
217
|
+
const depth = nestedDepth(value);
|
|
218
|
+
if (depth > maxNestedDepth) {
|
|
219
|
+
failures.push({
|
|
220
|
+
rule: 'shapeDepth',
|
|
221
|
+
detail: `"${key}" nesting depth is ${depth}, expected at most ${maxNestedDepth}`,
|
|
222
|
+
rowIndex: i,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
for (const path of nestedIdPaths(value, key)) {
|
|
226
|
+
failures.push({
|
|
227
|
+
rule: 'shapeNestedId',
|
|
228
|
+
detail: `id-shaped field "${path}" must be a top-level row key`,
|
|
229
|
+
rowIndex: i,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
return failures;
|
|
235
|
+
}
|
|
183
236
|
/**
|
|
184
237
|
* Convert fixture args into argv tokens appended after the command name.
|
|
185
238
|
* - Array form is passed through verbatim (stringified), supporting positional subjects.
|
|
@@ -221,6 +274,40 @@ function jsType(v) {
|
|
|
221
274
|
return 'array';
|
|
222
275
|
return typeof v;
|
|
223
276
|
}
|
|
277
|
+
function nestedDepth(value) {
|
|
278
|
+
if (value === null || value === undefined || typeof value !== 'object')
|
|
279
|
+
return 0;
|
|
280
|
+
if (Array.isArray(value)) {
|
|
281
|
+
if (value.length === 0)
|
|
282
|
+
return 1;
|
|
283
|
+
return 1 + Math.max(...value.map(nestedDepth));
|
|
284
|
+
}
|
|
285
|
+
const values = Object.values(value);
|
|
286
|
+
if (values.length === 0)
|
|
287
|
+
return 1;
|
|
288
|
+
return 1 + Math.max(...values.map(nestedDepth));
|
|
289
|
+
}
|
|
290
|
+
function nestedIdPaths(value, prefix) {
|
|
291
|
+
if (value === null || value === undefined || typeof value !== 'object')
|
|
292
|
+
return [];
|
|
293
|
+
const paths = [];
|
|
294
|
+
if (Array.isArray(value)) {
|
|
295
|
+
value.forEach((item, index) => {
|
|
296
|
+
paths.push(...nestedIdPaths(item, `${prefix}[${index}]`));
|
|
297
|
+
});
|
|
298
|
+
return paths;
|
|
299
|
+
}
|
|
300
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
301
|
+
const childPath = `${prefix}.${key}`;
|
|
302
|
+
if (isIdShapedKey(key))
|
|
303
|
+
paths.push(childPath);
|
|
304
|
+
paths.push(...nestedIdPaths(nested, childPath));
|
|
305
|
+
}
|
|
306
|
+
return paths;
|
|
307
|
+
}
|
|
308
|
+
function isIdShapedKey(key) {
|
|
309
|
+
return ID_SHAPED_KEY_PATTERNS.some((pattern) => pattern.test(key));
|
|
310
|
+
}
|
|
224
311
|
function typeMatches(actual, declared) {
|
|
225
312
|
const allowed = declared.split('|').map((s) => s.trim()).filter(Boolean);
|
|
226
313
|
if (allowed.length === 0)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { deriveFixture, expandFixtureArgs, parseSeedArgs, validateRows } from './verify-fixture.js';
|
|
2
|
+
import { deriveFixture, expandFixtureArgs, parseSeedArgs, validateRows, validateRowShape } from './verify-fixture.js';
|
|
3
3
|
describe('validateRows', () => {
|
|
4
4
|
it('passes when rows meet all expectations', () => {
|
|
5
5
|
const fixture = {
|
|
@@ -98,6 +98,49 @@ describe('validateRows', () => {
|
|
|
98
98
|
expect(failures.map((f) => f.rowIndex)).toEqual([1, 2, 3, 4]);
|
|
99
99
|
});
|
|
100
100
|
});
|
|
101
|
+
describe('validateRowShape', () => {
|
|
102
|
+
it('passes flat rows with a compact key set', () => {
|
|
103
|
+
const failures = validateRowShape([
|
|
104
|
+
{ id: '1', title: 'A', author: { name: 'Ada' }, tags: ['ai', 'web'] },
|
|
105
|
+
]);
|
|
106
|
+
expect(failures).toEqual([]);
|
|
107
|
+
});
|
|
108
|
+
it('reports rows with too many top-level keys', () => {
|
|
109
|
+
const row = Object.fromEntries(Array.from({ length: 13 }, (_, i) => [`k${i}`, i]));
|
|
110
|
+
const failures = validateRowShape([row]);
|
|
111
|
+
expect(failures).toEqual([
|
|
112
|
+
{
|
|
113
|
+
rule: 'shapeKeyCount',
|
|
114
|
+
detail: 'row has 13 top-level keys, expected at most 12',
|
|
115
|
+
rowIndex: 0,
|
|
116
|
+
},
|
|
117
|
+
]);
|
|
118
|
+
});
|
|
119
|
+
it('reports nesting deeper than one level', () => {
|
|
120
|
+
const failures = validateRowShape([
|
|
121
|
+
{ title: 'A', stats: { author: { name: 'Ada' } } },
|
|
122
|
+
]);
|
|
123
|
+
expect(failures).toEqual([
|
|
124
|
+
{
|
|
125
|
+
rule: 'shapeDepth',
|
|
126
|
+
detail: '"stats" nesting depth is 2, expected at most 1',
|
|
127
|
+
rowIndex: 0,
|
|
128
|
+
},
|
|
129
|
+
]);
|
|
130
|
+
});
|
|
131
|
+
it('reports nested id-shaped fields even when one-level nesting is otherwise allowed', () => {
|
|
132
|
+
const failures = validateRowShape([
|
|
133
|
+
{ title: 'A', author: { user_id: 'u1', name: 'Ada' } },
|
|
134
|
+
]);
|
|
135
|
+
expect(failures).toEqual([
|
|
136
|
+
{
|
|
137
|
+
rule: 'shapeNestedId',
|
|
138
|
+
detail: 'id-shaped field "author.user_id" must be a top-level row key',
|
|
139
|
+
rowIndex: 0,
|
|
140
|
+
},
|
|
141
|
+
]);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
101
144
|
describe('deriveFixture', () => {
|
|
102
145
|
it('returns rowCount.min=0 when rows are empty', () => {
|
|
103
146
|
expect(deriveFixture([])).toEqual({ expect: { rowCount: { min: 0 } } });
|
|
@@ -32,7 +32,13 @@ const PACKAGE_ROOT = findPackageRoot(fileURLToPath(import.meta.url));
|
|
|
32
32
|
const CLIS_DIR = path.join(PACKAGE_ROOT, 'clis');
|
|
33
33
|
// Write manifest next to clis/ so both dev and installed runtime can find it.
|
|
34
34
|
const OUTPUT = getCliManifestPath(CLIS_DIR);
|
|
35
|
-
|
|
35
|
+
// Module is treated as a CLI command source if it either:
|
|
36
|
+
// 1. Calls `cli(...)` directly (the common case), or
|
|
37
|
+
// 2. Calls a factory `make<Pascal>Command(...)` from clis/_shared/ that
|
|
38
|
+
// wraps `cli(...)`. Without (2), shared-factory adapters
|
|
39
|
+
// (codex/cursor/chatwise new/status/dump/screenshot) match no `cli(`
|
|
40
|
+
// token at the top level and silently drop out of the manifest.
|
|
41
|
+
const CLI_MODULE_PATTERN = /\bcli\s*\(|\bmake[A-Z]\w*Command\s*\(/;
|
|
36
42
|
/**
|
|
37
43
|
* Thrown by `loadManifestEntries` when an adapter file looks like a CLI
|
|
38
44
|
* module (matches CLI_MODULE_PATTERN) but cannot be imported. Callers
|
|
@@ -75,6 +81,7 @@ function isCliCommandValue(value, site) {
|
|
|
75
81
|
&& typeof value.site === 'string'
|
|
76
82
|
&& value.site === site
|
|
77
83
|
&& typeof value.name === 'string'
|
|
84
|
+
&& (value.access === 'read' || value.access === 'write')
|
|
78
85
|
&& Array.isArray(value.args);
|
|
79
86
|
}
|
|
80
87
|
function toManifestEntry(cmd, modulePath, sourceFile) {
|
|
@@ -83,18 +90,19 @@ function toManifestEntry(cmd, modulePath, sourceFile) {
|
|
|
83
90
|
name: cmd.name,
|
|
84
91
|
aliases: cmd.aliases,
|
|
85
92
|
description: cmd.description ?? '',
|
|
93
|
+
access: cmd.access,
|
|
94
|
+
example: cmd.example,
|
|
86
95
|
domain: cmd.domain,
|
|
87
96
|
strategy: (cmd.strategy ?? 'public').toString().toLowerCase(),
|
|
88
97
|
browser: cmd.browser ?? true,
|
|
89
98
|
args: toManifestArgs(cmd.args),
|
|
90
99
|
columns: cmd.columns,
|
|
91
|
-
|
|
92
|
-
deprecated: cmd.deprecated,
|
|
93
|
-
replacedBy: cmd.replacedBy,
|
|
100
|
+
defaultFormat: cmd.defaultFormat,
|
|
94
101
|
type: 'js',
|
|
95
102
|
modulePath,
|
|
96
103
|
sourceFile,
|
|
97
104
|
navigateBefore: cmd.navigateBefore,
|
|
105
|
+
browserSession: cmd.browserSession,
|
|
98
106
|
};
|
|
99
107
|
}
|
|
100
108
|
/**
|
|
@@ -24,11 +24,12 @@ describe('manifest helper rules', () => {
|
|
|
24
24
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-manifest-'));
|
|
25
25
|
tempDirs.push(dir);
|
|
26
26
|
const file = path.join(dir, `${site}.ts`);
|
|
27
|
-
fs.writeFileSync(file, `export const command = cli({ site: '${site}', name: 'dynamic' });`);
|
|
27
|
+
fs.writeFileSync(file, `export const command = cli({ site: '${site}', name: 'dynamic', access: 'read' });`);
|
|
28
28
|
const entries = await loadManifestEntries(file, site, async () => ({
|
|
29
29
|
command: cli({
|
|
30
30
|
site,
|
|
31
31
|
name: 'dynamic',
|
|
32
|
+
access: 'read',
|
|
32
33
|
description: 'dynamic command',
|
|
33
34
|
strategy: Strategy.PUBLIC,
|
|
34
35
|
browser: false,
|
|
@@ -45,14 +46,14 @@ describe('manifest helper rules', () => {
|
|
|
45
46
|
],
|
|
46
47
|
domain: 'localhost',
|
|
47
48
|
navigateBefore: 'https://example.com/session',
|
|
48
|
-
|
|
49
|
-
replacedBy: 'opencli demo new',
|
|
49
|
+
defaultFormat: 'plain',
|
|
50
50
|
}),
|
|
51
51
|
}));
|
|
52
52
|
expect(entries).toMatchObject([
|
|
53
53
|
{
|
|
54
54
|
site,
|
|
55
55
|
name: 'dynamic',
|
|
56
|
+
access: 'read',
|
|
56
57
|
description: 'dynamic command',
|
|
57
58
|
domain: 'localhost',
|
|
58
59
|
strategy: 'public',
|
|
@@ -72,8 +73,7 @@ describe('manifest helper rules', () => {
|
|
|
72
73
|
type: 'js',
|
|
73
74
|
modulePath: `${site}/${site}.js`,
|
|
74
75
|
navigateBefore: 'https://example.com/session',
|
|
75
|
-
|
|
76
|
-
replacedBy: 'opencli demo new',
|
|
76
|
+
defaultFormat: 'plain',
|
|
77
77
|
},
|
|
78
78
|
]);
|
|
79
79
|
// Verify sourceFile is included and stable for manifest consumers.
|
|
@@ -87,14 +87,13 @@ describe('manifest helper rules', () => {
|
|
|
87
87
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-manifest-'));
|
|
88
88
|
tempDirs.push(dir);
|
|
89
89
|
const file = path.join(dir, `${site}.ts`);
|
|
90
|
-
fs.writeFileSync(file, `cli({ site: '${site}', name: 'legacy' });`);
|
|
90
|
+
fs.writeFileSync(file, `cli({ site: '${site}', name: 'legacy', access: 'read' });`);
|
|
91
91
|
const entries = await loadManifestEntries(file, site, async () => {
|
|
92
92
|
cli({
|
|
93
93
|
site,
|
|
94
94
|
name: 'legacy',
|
|
95
|
+
access: 'read',
|
|
95
96
|
description: 'legacy command',
|
|
96
|
-
deprecated: 'legacy is deprecated',
|
|
97
|
-
replacedBy: 'opencli demo new',
|
|
98
97
|
});
|
|
99
98
|
return {};
|
|
100
99
|
});
|
|
@@ -102,14 +101,13 @@ describe('manifest helper rules', () => {
|
|
|
102
101
|
{
|
|
103
102
|
site,
|
|
104
103
|
name: 'legacy',
|
|
104
|
+
access: 'read',
|
|
105
105
|
description: 'legacy command',
|
|
106
106
|
strategy: 'cookie',
|
|
107
107
|
browser: true,
|
|
108
108
|
args: [],
|
|
109
109
|
type: 'js',
|
|
110
110
|
modulePath: `${site}/${site}.js`,
|
|
111
|
-
deprecated: 'legacy is deprecated',
|
|
112
|
-
replacedBy: 'opencli demo new',
|
|
113
111
|
},
|
|
114
112
|
]);
|
|
115
113
|
// Verify sourceFile is included
|
|
@@ -123,16 +121,18 @@ describe('manifest helper rules', () => {
|
|
|
123
121
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-manifest-'));
|
|
124
122
|
tempDirs.push(dir);
|
|
125
123
|
const file = path.join(dir, `${site}.ts`);
|
|
126
|
-
fs.writeFileSync(file, `export const screen = cli({ site: '${site}', name: 'screen' });`);
|
|
124
|
+
fs.writeFileSync(file, `export const screen = cli({ site: '${site}', name: 'screen', access: 'read' });`);
|
|
127
125
|
const entries = await loadManifestEntries(file, site, async () => ({
|
|
128
126
|
screen: cli({
|
|
129
127
|
site,
|
|
130
128
|
name: 'screen',
|
|
129
|
+
access: 'read',
|
|
131
130
|
description: 'capture screen',
|
|
132
131
|
}),
|
|
133
132
|
status: cli({
|
|
134
133
|
site,
|
|
135
134
|
name: 'status',
|
|
135
|
+
access: 'read',
|
|
136
136
|
description: 'show status',
|
|
137
137
|
}),
|
|
138
138
|
}));
|
|
@@ -147,7 +147,7 @@ describe('manifest helper rules', () => {
|
|
|
147
147
|
it('serializes manifest json with a trailing newline', () => {
|
|
148
148
|
const serialized = serializeManifest([{
|
|
149
149
|
site: 'demo',
|
|
150
|
-
name: 'status',
|
|
150
|
+
name: 'status', access: 'read',
|
|
151
151
|
description: '',
|
|
152
152
|
strategy: 'public',
|
|
153
153
|
browser: false,
|
|
@@ -164,7 +164,7 @@ describe('manifest helper rules', () => {
|
|
|
164
164
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-manifest-fail-'));
|
|
165
165
|
tempDirs.push(dir);
|
|
166
166
|
const file = path.join(dir, 'broken.ts');
|
|
167
|
-
fs.writeFileSync(file, `export const command = cli({ site: 'demo', name: 'broken' });`);
|
|
167
|
+
fs.writeFileSync(file, `export const command = cli({ site: 'demo', name: 'broken', access: 'read' });`);
|
|
168
168
|
const importer = async () => { throw new Error('boom: stale dist'); };
|
|
169
169
|
await expect(loadManifestEntries(file, 'demo', importer))
|
|
170
170
|
.rejects.toBeInstanceOf(ManifestImportError);
|
|
@@ -194,12 +194,12 @@ describe('manifest helper rules', () => {
|
|
|
194
194
|
tempDirs.push(root);
|
|
195
195
|
const siteDir = path.join(root, 'demo');
|
|
196
196
|
fs.mkdirSync(siteDir);
|
|
197
|
-
fs.writeFileSync(path.join(siteDir, 'good.js'), `export const cmd = cli({ site: 'demo', name: 'good' });`);
|
|
198
|
-
fs.writeFileSync(path.join(siteDir, 'broken.js'), `export const cmd = cli({ site: 'demo', name: 'broken' });`);
|
|
197
|
+
fs.writeFileSync(path.join(siteDir, 'good.js'), `export const cmd = cli({ site: 'demo', name: 'good', access: 'read' });`);
|
|
198
|
+
fs.writeFileSync(path.join(siteDir, 'broken.js'), `export const cmd = cli({ site: 'demo', name: 'broken', access: 'read' });`);
|
|
199
199
|
const importer = async (href) => {
|
|
200
200
|
if (href.endsWith('broken.js'))
|
|
201
201
|
throw new Error('stale dist drops broken');
|
|
202
|
-
return { cmd: cli({ site: 'demo', name: 'good', description: 'ok' }) };
|
|
202
|
+
return { cmd: cli({ site: 'demo', name: 'good', access: 'read', description: 'ok' }) };
|
|
203
203
|
};
|
|
204
204
|
const result = await scanClisDir(root, importer);
|
|
205
205
|
expect(result.failures).toHaveLength(1);
|
|
@@ -211,12 +211,12 @@ describe('manifest helper rules', () => {
|
|
|
211
211
|
});
|
|
212
212
|
it('diffRemovedEntries returns site/name keys present only in prev', () => {
|
|
213
213
|
const prev = [
|
|
214
|
-
{ site: 'a', name: '1', description: '', strategy: 'public', browser: false, args: [], type: 'js' },
|
|
215
|
-
{ site: 'a', name: '2', description: '', strategy: 'public', browser: false, args: [], type: 'js' },
|
|
216
|
-
{ site: 'b', name: '3', description: '', strategy: 'public', browser: false, args: [], type: 'js' },
|
|
214
|
+
{ site: 'a', name: '1', access: 'read', description: '', strategy: 'public', browser: false, args: [], type: 'js' },
|
|
215
|
+
{ site: 'a', name: '2', access: 'read', description: '', strategy: 'public', browser: false, args: [], type: 'js' },
|
|
216
|
+
{ site: 'b', name: '3', access: 'read', description: '', strategy: 'public', browser: false, args: [], type: 'js' },
|
|
217
217
|
];
|
|
218
218
|
const next = [
|
|
219
|
-
{ site: 'a', name: '1', description: '', strategy: 'public', browser: false, args: [], type: 'js' },
|
|
219
|
+
{ site: 'a', name: '1', access: 'read', description: '', strategy: 'public', browser: false, args: [], type: 'js' },
|
|
220
220
|
];
|
|
221
221
|
expect(diffRemovedEntries(prev, next)).toEqual(['a/2', 'b/3']);
|
|
222
222
|
expect(diffRemovedEntries(prev, prev)).toEqual([]);
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import type { CliCommand } from './registry.js';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Pipeline steps that require a live browser session.
|
|
4
|
+
*
|
|
5
|
+
* Note: this is the *subset* of registered pipeline steps that need a page;
|
|
6
|
+
* non-browser steps (fetch, select, map, filter, sort, limit, download)
|
|
7
|
+
* deliberately stay out. The full registered-step list lives in
|
|
8
|
+
* `src/pipeline/registry.ts` and is re-derived elsewhere via
|
|
9
|
+
* `getRegisteredStepNames()` (e.g. in `validate.ts`). When you add a new
|
|
10
|
+
* pipeline step, decide whether it belongs here based on whether its handler
|
|
11
|
+
* touches the IPage object — and `src/capabilityRouting.test.ts` verifies the
|
|
12
|
+
* subset relationship is intact.
|
|
13
|
+
*/
|
|
3
14
|
export declare const BROWSER_ONLY_STEPS: Set<string>;
|
|
15
|
+
/** Internal helper: ensure BROWSER_ONLY_STEPS is a subset of registered pipeline steps. */
|
|
16
|
+
export declare function _validateBrowserOnlyStepsAgainstRegistry(): {
|
|
17
|
+
extras: string[];
|
|
18
|
+
};
|
|
4
19
|
export declare function shouldUseBrowserSession(cmd: CliCommand): boolean;
|
|
@@ -1,8 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import { getRegisteredStepNames } from './pipeline/registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* Pipeline steps that require a live browser session.
|
|
4
|
+
*
|
|
5
|
+
* Note: this is the *subset* of registered pipeline steps that need a page;
|
|
6
|
+
* non-browser steps (fetch, select, map, filter, sort, limit, download)
|
|
7
|
+
* deliberately stay out. The full registered-step list lives in
|
|
8
|
+
* `src/pipeline/registry.ts` and is re-derived elsewhere via
|
|
9
|
+
* `getRegisteredStepNames()` (e.g. in `validate.ts`). When you add a new
|
|
10
|
+
* pipeline step, decide whether it belongs here based on whether its handler
|
|
11
|
+
* touches the IPage object — and `src/capabilityRouting.test.ts` verifies the
|
|
12
|
+
* subset relationship is intact.
|
|
13
|
+
*/
|
|
2
14
|
export const BROWSER_ONLY_STEPS = new Set([
|
|
3
15
|
'navigate',
|
|
4
16
|
'click',
|
|
5
17
|
'type',
|
|
18
|
+
'fill',
|
|
6
19
|
'wait',
|
|
7
20
|
'press',
|
|
8
21
|
'snapshot',
|
|
@@ -10,6 +23,16 @@ export const BROWSER_ONLY_STEPS = new Set([
|
|
|
10
23
|
'intercept',
|
|
11
24
|
'tap',
|
|
12
25
|
]);
|
|
26
|
+
/** Internal helper: ensure BROWSER_ONLY_STEPS is a subset of registered pipeline steps. */
|
|
27
|
+
export function _validateBrowserOnlyStepsAgainstRegistry() {
|
|
28
|
+
const registered = new Set(getRegisteredStepNames());
|
|
29
|
+
const extras = [];
|
|
30
|
+
for (const step of BROWSER_ONLY_STEPS) {
|
|
31
|
+
if (!registered.has(step))
|
|
32
|
+
extras.push(step);
|
|
33
|
+
}
|
|
34
|
+
return { extras };
|
|
35
|
+
}
|
|
13
36
|
function pipelineNeedsBrowserSession(pipeline) {
|
|
14
37
|
return pipeline.some((step) => {
|
|
15
38
|
if (!step || typeof step !== 'object')
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import { Strategy } from './registry.js';
|
|
3
|
-
import { shouldUseBrowserSession } from './capabilityRouting.js';
|
|
3
|
+
import { BROWSER_ONLY_STEPS, _validateBrowserOnlyStepsAgainstRegistry, shouldUseBrowserSession } from './capabilityRouting.js';
|
|
4
|
+
import { getRegisteredStepNames } from './pipeline/registry.js';
|
|
4
5
|
function makeCmd(partial) {
|
|
5
6
|
return {
|
|
6
7
|
site: 'test',
|
|
7
|
-
name: 'command',
|
|
8
|
+
name: 'command', access: 'read',
|
|
8
9
|
description: '',
|
|
9
10
|
args: [],
|
|
10
11
|
...partial,
|
|
@@ -42,4 +43,21 @@ describe('shouldUseBrowserSession', () => {
|
|
|
42
43
|
func: async () => [],
|
|
43
44
|
}))).toBe(true);
|
|
44
45
|
});
|
|
46
|
+
it('routes pipelines containing the fill step into a browser session', () => {
|
|
47
|
+
expect(shouldUseBrowserSession(makeCmd({
|
|
48
|
+
browser: true,
|
|
49
|
+
strategy: Strategy.PUBLIC,
|
|
50
|
+
pipeline: [{ navigate: 'https://example.com' }, { fill: { ref: '#q', text: 'hello' } }],
|
|
51
|
+
}))).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe('BROWSER_ONLY_STEPS / pipeline registry alignment', () => {
|
|
55
|
+
it('is a subset of registered pipeline step names', () => {
|
|
56
|
+
const { extras } = _validateBrowserOnlyStepsAgainstRegistry();
|
|
57
|
+
expect(extras).toEqual([]);
|
|
58
|
+
});
|
|
59
|
+
it('includes fill (DOM-touching step added in PR #1222)', () => {
|
|
60
|
+
expect(BROWSER_ONLY_STEPS.has('fill')).toBe(true);
|
|
61
|
+
expect(getRegisteredStepNames()).toContain('fill');
|
|
62
|
+
});
|
|
45
63
|
});
|