@jackwener/opencli 1.6.9 → 1.7.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/README.md +128 -59
- package/README.zh-CN.md +134 -78
- package/dist/clis/_shared/common.d.ts +3 -0
- package/dist/clis/_shared/common.js +22 -0
- package/dist/clis/bilibili/hot.js +35 -0
- package/dist/clis/bluesky/feeds.d.ts +1 -0
- package/dist/clis/bluesky/feeds.js +27 -0
- package/dist/clis/bluesky/followers.d.ts +1 -0
- package/dist/clis/bluesky/followers.js +27 -0
- package/dist/clis/bluesky/following.d.ts +1 -0
- package/dist/clis/bluesky/following.js +27 -0
- package/dist/clis/bluesky/profile.d.ts +1 -0
- package/dist/clis/bluesky/profile.js +29 -0
- package/dist/clis/bluesky/search.d.ts +1 -0
- package/dist/clis/bluesky/search.js +28 -0
- package/dist/clis/bluesky/starter-packs.d.ts +1 -0
- package/dist/clis/bluesky/starter-packs.js +28 -0
- package/dist/clis/bluesky/thread.d.ts +1 -0
- package/dist/clis/bluesky/thread.js +30 -0
- package/dist/clis/bluesky/trending.d.ts +1 -0
- package/dist/clis/bluesky/trending.js +19 -0
- package/dist/clis/bluesky/user.d.ts +1 -0
- package/dist/clis/bluesky/user.js +33 -0
- package/dist/clis/cnki/search.d.ts +1 -0
- package/dist/clis/cnki/search.js +60 -0
- package/dist/clis/cnki/search.test.d.ts +1 -0
- package/dist/clis/cnki/search.test.js +18 -0
- package/dist/clis/devto/tag.d.ts +1 -0
- package/dist/clis/devto/tag.js +32 -0
- package/dist/clis/devto/top.d.ts +1 -0
- package/dist/clis/devto/top.js +26 -0
- package/dist/clis/devto/user.d.ts +1 -0
- package/dist/clis/devto/user.js +31 -0
- package/dist/clis/dictionary/examples.d.ts +1 -0
- package/dist/clis/dictionary/examples.js +27 -0
- package/dist/clis/dictionary/search.d.ts +1 -0
- package/dist/clis/dictionary/search.js +29 -0
- package/dist/clis/dictionary/synonyms.d.ts +1 -0
- package/dist/clis/dictionary/synonyms.js +27 -0
- package/dist/clis/douban/subject.d.ts +1 -0
- package/dist/clis/douban/subject.js +118 -0
- package/dist/clis/douban/top250.d.ts +1 -0
- package/dist/clis/douban/top250.js +67 -0
- package/dist/clis/facebook/add-friend.d.ts +1 -0
- package/dist/clis/facebook/add-friend.js +43 -0
- package/dist/clis/facebook/events.d.ts +1 -0
- package/dist/clis/facebook/events.js +40 -0
- package/dist/clis/facebook/feed.d.ts +1 -0
- package/dist/clis/facebook/feed.js +59 -0
- package/dist/clis/facebook/friends.d.ts +1 -0
- package/dist/clis/facebook/friends.js +38 -0
- package/dist/clis/facebook/groups.d.ts +1 -0
- package/dist/clis/facebook/groups.js +46 -0
- package/dist/clis/facebook/join-group.d.ts +1 -0
- package/dist/clis/facebook/join-group.js +44 -0
- package/dist/clis/facebook/memories.d.ts +1 -0
- package/dist/clis/facebook/memories.js +35 -0
- package/dist/clis/facebook/notifications.d.ts +1 -0
- package/dist/clis/facebook/notifications.js +36 -0
- package/dist/clis/facebook/profile.d.ts +1 -0
- package/dist/clis/facebook/profile.js +37 -0
- package/dist/clis/facebook/search.d.ts +1 -0
- package/dist/clis/facebook/search.js +38 -0
- package/dist/clis/facebook/search.test.d.ts +1 -1
- package/dist/clis/facebook/search.test.js +6 -9
- package/dist/clis/gitee/index.d.ts +3 -0
- package/dist/clis/gitee/index.js +3 -0
- package/dist/clis/gitee/search.d.ts +1 -0
- package/dist/clis/gitee/search.js +136 -0
- package/dist/clis/gitee/trending.d.ts +1 -0
- package/dist/clis/gitee/trending.js +567 -0
- package/dist/clis/gitee/user.d.ts +1 -0
- package/dist/clis/gitee/user.js +199 -0
- package/dist/clis/gitee/user.test.d.ts +1 -0
- package/dist/clis/gitee/user.test.js +63 -0
- package/dist/clis/hackernews/ask.d.ts +1 -0
- package/dist/clis/hackernews/ask.js +29 -0
- package/dist/clis/hackernews/best.d.ts +1 -0
- package/dist/clis/hackernews/best.js +29 -0
- package/dist/clis/hackernews/jobs.d.ts +1 -0
- package/dist/clis/hackernews/jobs.js +27 -0
- package/dist/clis/hackernews/new.d.ts +1 -0
- package/dist/clis/hackernews/new.js +29 -0
- package/dist/clis/hackernews/search.d.ts +1 -0
- package/dist/clis/hackernews/search.js +36 -0
- package/dist/clis/hackernews/show.d.ts +1 -0
- package/dist/clis/hackernews/show.js +29 -0
- package/dist/clis/hackernews/top.d.ts +1 -0
- package/dist/clis/hackernews/top.js +29 -0
- package/dist/clis/hackernews/user.d.ts +1 -0
- package/dist/clis/hackernews/user.js +22 -0
- package/dist/clis/hupu/hot.d.ts +1 -0
- package/dist/clis/hupu/hot.js +40 -0
- package/dist/clis/instagram/comment.d.ts +1 -0
- package/dist/clis/instagram/comment.js +47 -0
- package/dist/clis/instagram/explore.d.ts +1 -0
- package/dist/clis/instagram/explore.js +41 -0
- package/dist/clis/instagram/follow.d.ts +1 -0
- package/dist/clis/instagram/follow.js +43 -0
- package/dist/clis/instagram/followers.d.ts +1 -0
- package/dist/clis/instagram/followers.js +45 -0
- package/dist/clis/instagram/following.d.ts +1 -0
- package/dist/clis/instagram/following.js +45 -0
- package/dist/clis/instagram/like.d.ts +1 -0
- package/dist/clis/instagram/like.js +45 -0
- package/dist/clis/instagram/profile.d.ts +1 -0
- package/dist/clis/instagram/profile.js +39 -0
- package/dist/clis/instagram/save.d.ts +1 -0
- package/dist/clis/instagram/save.js +45 -0
- package/dist/clis/instagram/saved.d.ts +1 -0
- package/dist/clis/instagram/saved.js +38 -0
- package/dist/clis/instagram/search.d.ts +1 -0
- package/dist/clis/instagram/search.js +38 -0
- package/dist/clis/instagram/unfollow.d.ts +1 -0
- package/dist/clis/instagram/unfollow.js +40 -0
- package/dist/clis/instagram/unlike.d.ts +1 -0
- package/dist/clis/instagram/unlike.js +45 -0
- package/dist/clis/instagram/unsave.d.ts +1 -0
- package/dist/clis/instagram/unsave.js +45 -0
- package/dist/clis/instagram/user.d.ts +1 -0
- package/dist/clis/instagram/user.js +48 -0
- package/dist/clis/jd/add-cart.d.ts +1 -0
- package/dist/clis/jd/add-cart.js +71 -0
- package/dist/clis/jd/cart.d.ts +1 -0
- package/dist/clis/jd/cart.js +79 -0
- package/dist/clis/jd/commands.test.d.ts +5 -0
- package/dist/clis/jd/commands.test.js +64 -0
- package/dist/clis/jd/detail.d.ts +1 -0
- package/dist/clis/jd/detail.js +62 -0
- package/dist/clis/jd/reviews.d.ts +1 -0
- package/dist/clis/jd/reviews.js +54 -0
- package/dist/clis/jd/search.d.ts +1 -0
- package/dist/clis/jd/search.js +65 -0
- package/dist/clis/jianyu/detail.d.ts +1 -0
- package/dist/clis/jianyu/detail.js +20 -0
- package/dist/clis/jianyu/search.d.ts +41 -4
- package/dist/clis/jianyu/search.js +458 -96
- package/dist/clis/jianyu/search.test.js +105 -0
- package/dist/clis/jianyu/shared/china-bid-search.d.ts +12 -0
- package/dist/clis/jianyu/shared/china-bid-search.js +165 -0
- package/dist/clis/jianyu/shared/procurement-contract.d.ts +68 -0
- package/dist/clis/jianyu/shared/procurement-contract.js +324 -0
- package/dist/clis/jianyu/shared/procurement-contract.test.d.ts +1 -0
- package/dist/clis/jianyu/shared/procurement-contract.test.js +72 -0
- package/dist/clis/jianyu/shared/procurement-detail.d.ts +6 -0
- package/dist/clis/jianyu/shared/procurement-detail.js +92 -0
- package/dist/clis/jianyu/shared/procurement-detail.test.d.ts +1 -0
- package/dist/clis/jianyu/shared/procurement-detail.test.js +72 -0
- package/dist/clis/jike/post.d.ts +1 -0
- package/dist/clis/jike/post.js +61 -0
- package/dist/clis/jike/topic.d.ts +1 -0
- package/dist/clis/jike/topic.js +51 -0
- package/dist/clis/jike/user.d.ts +1 -0
- package/dist/clis/jike/user.js +50 -0
- package/dist/clis/jimeng/generate.d.ts +1 -0
- package/dist/clis/jimeng/generate.js +83 -0
- package/dist/clis/jimeng/history.d.ts +1 -0
- package/dist/clis/jimeng/history.js +47 -0
- package/dist/clis/jimeng/new.d.ts +1 -0
- package/dist/clis/jimeng/new.js +43 -0
- package/dist/clis/jimeng/workspaces.d.ts +1 -0
- package/dist/clis/jimeng/workspaces.js +41 -0
- package/dist/clis/linux-do/categories.d.ts +1 -0
- package/dist/clis/linux-do/categories.js +65 -0
- package/dist/clis/linux-do/search.d.ts +1 -0
- package/dist/clis/linux-do/search.js +41 -0
- package/dist/clis/linux-do/tags.d.ts +1 -0
- package/dist/clis/linux-do/tags.js +39 -0
- package/dist/clis/linux-do/topic-content.test.js +5 -5
- package/dist/clis/linux-do/topic.d.ts +1 -0
- package/dist/clis/linux-do/topic.js +56 -0
- package/dist/clis/linux-do/user-posts.d.ts +1 -0
- package/dist/clis/linux-do/user-posts.js +61 -0
- package/dist/clis/linux-do/user-topics.d.ts +1 -0
- package/dist/clis/linux-do/user-topics.js +48 -0
- package/dist/clis/lobsters/active.d.ts +1 -0
- package/dist/clis/lobsters/active.js +26 -0
- package/dist/clis/lobsters/hot.d.ts +1 -0
- package/dist/clis/lobsters/hot.js +26 -0
- package/dist/clis/lobsters/newest.d.ts +1 -0
- package/dist/clis/lobsters/newest.js +26 -0
- package/dist/clis/lobsters/tag.d.ts +1 -0
- package/dist/clis/lobsters/tag.js +32 -0
- package/dist/clis/pixiv/detail.d.ts +1 -0
- package/dist/clis/pixiv/detail.js +58 -0
- package/dist/clis/pixiv/ranking.d.ts +1 -0
- package/dist/clis/pixiv/ranking.js +59 -0
- package/dist/clis/pixiv/user.d.ts +1 -0
- package/dist/clis/pixiv/user.js +52 -0
- package/dist/clis/reddit/frontpage.d.ts +1 -0
- package/dist/clis/reddit/frontpage.js +31 -0
- package/dist/clis/reddit/hot.d.ts +1 -0
- package/dist/clis/reddit/hot.js +45 -0
- package/dist/clis/reddit/popular.d.ts +1 -0
- package/dist/clis/reddit/popular.js +41 -0
- package/dist/clis/reddit/search.d.ts +1 -0
- package/dist/clis/reddit/search.js +65 -0
- package/dist/clis/reddit/subreddit.d.ts +1 -0
- package/dist/clis/reddit/subreddit.js +52 -0
- package/dist/clis/reddit/user-comments.d.ts +1 -0
- package/dist/clis/reddit/user-comments.js +44 -0
- package/dist/clis/reddit/user-posts.d.ts +1 -0
- package/dist/clis/reddit/user-posts.js +42 -0
- package/dist/clis/reddit/user.d.ts +1 -0
- package/dist/clis/reddit/user.js +37 -0
- package/dist/clis/stackoverflow/bounties.d.ts +1 -0
- package/dist/clis/stackoverflow/bounties.js +27 -0
- package/dist/clis/stackoverflow/hot.d.ts +1 -0
- package/dist/clis/stackoverflow/hot.js +24 -0
- package/dist/clis/stackoverflow/search.d.ts +1 -0
- package/dist/clis/stackoverflow/search.js +27 -0
- package/dist/clis/stackoverflow/unanswered.d.ts +1 -0
- package/dist/clis/stackoverflow/unanswered.js +26 -0
- package/dist/clis/steam/top-sellers.d.ts +1 -0
- package/dist/clis/steam/top-sellers.js +25 -0
- package/dist/clis/taobao/add-cart.d.ts +1 -0
- package/dist/clis/taobao/add-cart.js +149 -0
- package/dist/clis/taobao/cart.d.ts +1 -0
- package/dist/clis/taobao/cart.js +95 -0
- package/dist/clis/taobao/commands.test.d.ts +5 -0
- package/dist/clis/taobao/commands.test.js +64 -0
- package/dist/clis/taobao/detail.d.ts +1 -0
- package/dist/clis/taobao/detail.js +70 -0
- package/dist/clis/taobao/reviews.d.ts +1 -0
- package/dist/clis/taobao/reviews.js +76 -0
- package/dist/clis/taobao/search.d.ts +1 -0
- package/dist/clis/taobao/search.js +96 -0
- package/dist/clis/tiktok/comment.d.ts +1 -0
- package/dist/clis/tiktok/comment.js +57 -0
- package/dist/clis/tiktok/explore.d.ts +1 -0
- package/dist/clis/tiktok/explore.js +35 -0
- package/dist/clis/tiktok/follow.d.ts +1 -0
- package/dist/clis/tiktok/follow.js +39 -0
- package/dist/clis/tiktok/following.d.ts +1 -0
- package/dist/clis/tiktok/following.js +42 -0
- package/dist/clis/tiktok/friends.d.ts +1 -0
- package/dist/clis/tiktok/friends.js +43 -0
- package/dist/clis/tiktok/like.d.ts +1 -0
- package/dist/clis/tiktok/like.js +33 -0
- package/dist/clis/tiktok/live.d.ts +1 -0
- package/dist/clis/tiktok/live.js +47 -0
- package/dist/clis/tiktok/notifications.d.ts +1 -0
- package/dist/clis/tiktok/notifications.js +49 -0
- package/dist/clis/tiktok/profile.d.ts +1 -0
- package/dist/clis/tiktok/profile.js +54 -0
- package/dist/clis/tiktok/save.d.ts +1 -0
- package/dist/clis/tiktok/save.js +29 -0
- package/dist/clis/tiktok/search.d.ts +1 -0
- package/dist/clis/tiktok/search.js +39 -0
- package/dist/clis/tiktok/unfollow.d.ts +1 -0
- package/dist/clis/tiktok/unfollow.js +44 -0
- package/dist/clis/tiktok/unlike.d.ts +1 -0
- package/dist/clis/tiktok/unlike.js +33 -0
- package/dist/clis/tiktok/unsave.d.ts +1 -0
- package/dist/clis/tiktok/unsave.js +31 -0
- package/dist/clis/tiktok/user.d.ts +1 -0
- package/dist/clis/tiktok/user.js +41 -0
- package/dist/clis/v2ex/hot.d.ts +1 -0
- package/dist/clis/v2ex/hot.js +25 -0
- package/dist/clis/v2ex/latest.d.ts +1 -0
- package/dist/clis/v2ex/latest.js +25 -0
- package/dist/clis/v2ex/member.d.ts +1 -0
- package/dist/clis/v2ex/member.js +27 -0
- package/dist/clis/v2ex/node.d.ts +1 -0
- package/dist/clis/v2ex/node.js +38 -0
- package/dist/clis/v2ex/nodes.d.ts +1 -0
- package/dist/clis/v2ex/nodes.js +25 -0
- package/dist/clis/v2ex/replies.d.ts +1 -0
- package/dist/clis/v2ex/replies.js +26 -0
- package/dist/clis/v2ex/topic.d.ts +1 -0
- package/dist/clis/v2ex/topic.js +30 -0
- package/dist/clis/v2ex/user.d.ts +1 -0
- package/dist/clis/v2ex/user.js +33 -0
- package/dist/clis/xiaoe/catalog.d.ts +1 -0
- package/dist/clis/xiaoe/catalog.js +161 -0
- package/dist/clis/xiaoe/content.d.ts +1 -0
- package/dist/clis/xiaoe/content.js +39 -0
- package/dist/clis/xiaoe/courses.d.ts +1 -0
- package/dist/clis/xiaoe/courses.js +69 -0
- package/dist/clis/xiaoe/detail.d.ts +1 -0
- package/dist/clis/xiaoe/detail.js +35 -0
- package/dist/clis/xiaoe/play-url.d.ts +1 -0
- package/dist/clis/xiaoe/play-url.js +120 -0
- package/dist/clis/xiaohongshu/feed.d.ts +1 -0
- package/dist/clis/xiaohongshu/feed.js +32 -0
- package/dist/clis/xiaohongshu/notifications.d.ts +1 -0
- package/dist/clis/xiaohongshu/notifications.js +38 -0
- package/dist/clis/xueqiu/earnings-date.d.ts +1 -0
- package/dist/clis/xueqiu/earnings-date.js +61 -0
- package/dist/clis/xueqiu/feed.d.ts +1 -0
- package/dist/clis/xueqiu/feed.js +48 -0
- package/dist/clis/xueqiu/groups.d.ts +1 -0
- package/dist/clis/xueqiu/groups.js +25 -0
- package/dist/clis/xueqiu/hot-stock.d.ts +1 -0
- package/dist/clis/xueqiu/hot-stock.js +44 -0
- package/dist/clis/xueqiu/hot.d.ts +1 -0
- package/dist/clis/xueqiu/hot.js +44 -0
- package/dist/clis/xueqiu/kline.d.ts +1 -0
- package/dist/clis/xueqiu/kline.js +64 -0
- package/dist/clis/xueqiu/search.d.ts +1 -0
- package/dist/clis/xueqiu/search.js +49 -0
- package/dist/clis/xueqiu/stock.d.ts +1 -0
- package/dist/clis/xueqiu/stock.js +72 -0
- package/dist/clis/xueqiu/watchlist.d.ts +1 -0
- package/dist/clis/xueqiu/watchlist.js +45 -0
- package/dist/clis/zhihu/hot.d.ts +1 -0
- package/dist/clis/zhihu/hot.js +43 -0
- package/dist/clis/zhihu/search.d.ts +1 -0
- package/dist/clis/zhihu/search.js +52 -0
- package/dist/src/browser/bridge.js +1 -1
- package/dist/src/browser/daemon-client.d.ts +16 -4
- package/dist/src/browser/daemon-client.js +33 -15
- package/dist/src/browser/daemon-client.test.js +0 -3
- package/dist/src/browser/dom-helpers.test.js +3 -2
- package/dist/src/browser/errors.d.ts +26 -1
- package/dist/src/browser/errors.js +40 -7
- package/dist/src/browser/errors.test.d.ts +1 -0
- package/dist/src/browser/errors.test.js +51 -0
- package/dist/src/browser/page.d.ts +9 -8
- package/dist/src/browser/page.js +33 -31
- package/dist/src/browser.test.js +25 -6
- package/dist/src/build-manifest.d.ts +5 -11
- package/dist/src/build-manifest.js +6 -75
- package/dist/src/build-manifest.test.js +1 -39
- package/dist/src/cascade.js +3 -2
- package/dist/src/cli.d.ts +3 -3
- package/dist/src/cli.js +71 -71
- package/dist/src/cli.test.js +20 -15
- package/dist/src/clis/binance/asks.d.ts +1 -0
- package/dist/src/clis/binance/asks.js +20 -0
- package/dist/src/clis/binance/commands.test.d.ts +3 -1
- package/dist/src/clis/binance/commands.test.js +10 -6
- package/dist/src/clis/binance/depth.d.ts +1 -0
- package/dist/src/clis/binance/depth.js +20 -0
- package/dist/src/clis/binance/gainers.d.ts +1 -0
- package/dist/src/clis/binance/gainers.js +21 -0
- package/dist/src/clis/binance/klines.d.ts +1 -0
- package/dist/src/clis/binance/klines.js +20 -0
- package/dist/src/clis/binance/losers.d.ts +1 -0
- package/dist/src/clis/binance/losers.js +21 -0
- package/dist/src/clis/binance/pairs.d.ts +1 -0
- package/dist/src/clis/binance/pairs.js +20 -0
- package/dist/src/clis/binance/price.d.ts +1 -0
- package/dist/src/clis/binance/price.js +17 -0
- package/dist/src/clis/binance/prices.d.ts +1 -0
- package/dist/src/clis/binance/prices.js +18 -0
- package/dist/src/clis/binance/ticker.d.ts +1 -0
- package/dist/src/clis/binance/ticker.js +20 -0
- package/dist/src/clis/binance/top.d.ts +1 -0
- package/dist/src/clis/binance/top.js +20 -0
- package/dist/src/clis/binance/trades.d.ts +1 -0
- package/dist/src/clis/binance/trades.js +19 -0
- package/dist/src/commands/daemon.d.ts +2 -6
- package/dist/src/commands/daemon.js +2 -58
- package/dist/src/commands/daemon.test.js +24 -120
- package/dist/src/completion-fast.d.ts +25 -0
- package/dist/src/completion-fast.js +140 -0
- package/dist/src/completion.d.ts +1 -0
- package/dist/src/completion.js +1 -0
- package/dist/src/constants.d.ts +0 -2
- package/dist/src/constants.js +0 -2
- package/dist/src/daemon.d.ts +1 -1
- package/dist/src/daemon.js +2 -15
- package/dist/src/diagnostic.test.js +2 -2
- package/dist/src/discovery.d.ts +3 -3
- package/dist/src/discovery.js +34 -97
- package/dist/src/download/index.d.ts +1 -1
- package/dist/src/engine.test.js +4 -19
- package/dist/src/execution.js +5 -1
- package/dist/src/generate-verified.d.ts +105 -0
- package/dist/src/generate-verified.js +696 -0
- package/dist/src/generate-verified.test.d.ts +1 -0
- package/dist/src/generate-verified.test.js +925 -0
- package/dist/src/generate.d.ts +9 -1
- package/dist/src/generate.js +2 -2
- package/dist/src/main.js +65 -12
- package/dist/src/pipeline/steps/download.d.ts +1 -17
- package/dist/src/pipeline/steps/download.js +20 -31
- package/dist/src/pipeline/steps/intercept.d.ts +1 -1
- package/dist/src/pipeline/steps/intercept.js +1 -1
- package/dist/src/pipeline/steps/tap.d.ts +1 -1
- package/dist/src/pipeline/steps/tap.js +1 -1
- package/dist/src/plugin-scaffold.d.ts +2 -2
- package/dist/src/plugin-scaffold.js +24 -21
- package/dist/src/plugin-scaffold.test.js +1 -1
- package/dist/src/plugin.d.ts +1 -1
- package/dist/src/plugin.js +4 -6
- package/dist/src/plugin.test.js +31 -31
- package/dist/src/record.js +26 -25
- package/dist/src/runtime-detect.js +3 -7
- package/dist/src/scripts/framework.d.ts +3 -0
- package/dist/src/scripts/framework.js +8 -4
- package/dist/src/scripts/store.d.ts +5 -1
- package/dist/src/scripts/store.js +5 -1
- package/dist/src/skill-generate.d.ts +30 -0
- package/dist/src/skill-generate.js +75 -0
- package/dist/src/skill-generate.test.d.ts +1 -0
- package/dist/src/skill-generate.test.js +173 -0
- package/dist/src/synthesize.d.ts +1 -1
- package/dist/src/synthesize.js +7 -8
- package/dist/src/types.d.ts +3 -1
- package/package.json +4 -3
- package/dist/clis/bilibili/hot.yaml +0 -38
- package/dist/clis/bluesky/feeds.yaml +0 -29
- package/dist/clis/bluesky/followers.yaml +0 -33
- package/dist/clis/bluesky/following.yaml +0 -33
- package/dist/clis/bluesky/profile.yaml +0 -27
- package/dist/clis/bluesky/search.yaml +0 -34
- package/dist/clis/bluesky/starter-packs.yaml +0 -34
- package/dist/clis/bluesky/thread.yaml +0 -32
- package/dist/clis/bluesky/trending.yaml +0 -27
- package/dist/clis/bluesky/user.yaml +0 -34
- package/dist/clis/devto/tag.yaml +0 -34
- package/dist/clis/devto/top.yaml +0 -29
- package/dist/clis/devto/user.yaml +0 -33
- package/dist/clis/dictionary/examples.yaml +0 -25
- package/dist/clis/dictionary/search.yaml +0 -27
- package/dist/clis/dictionary/synonyms.yaml +0 -25
- package/dist/clis/douban/subject.yaml +0 -107
- package/dist/clis/douban/top250.yaml +0 -70
- package/dist/clis/facebook/add-friend.yaml +0 -43
- package/dist/clis/facebook/events.yaml +0 -44
- package/dist/clis/facebook/feed.yaml +0 -63
- package/dist/clis/facebook/friends.yaml +0 -42
- package/dist/clis/facebook/groups.yaml +0 -50
- package/dist/clis/facebook/join-group.yaml +0 -44
- package/dist/clis/facebook/memories.yaml +0 -39
- package/dist/clis/facebook/notifications.yaml +0 -40
- package/dist/clis/facebook/profile.yaml +0 -37
- package/dist/clis/facebook/search.yaml +0 -47
- package/dist/clis/hackernews/ask.yaml +0 -38
- package/dist/clis/hackernews/best.yaml +0 -38
- package/dist/clis/hackernews/jobs.yaml +0 -36
- package/dist/clis/hackernews/new.yaml +0 -38
- package/dist/clis/hackernews/search.yaml +0 -44
- package/dist/clis/hackernews/show.yaml +0 -38
- package/dist/clis/hackernews/top.yaml +0 -38
- package/dist/clis/hackernews/user.yaml +0 -25
- package/dist/clis/hupu/hot.yaml +0 -43
- package/dist/clis/instagram/comment.yaml +0 -52
- package/dist/clis/instagram/explore.yaml +0 -43
- package/dist/clis/instagram/follow.yaml +0 -41
- package/dist/clis/instagram/followers.yaml +0 -51
- package/dist/clis/instagram/following.yaml +0 -51
- package/dist/clis/instagram/like.yaml +0 -46
- package/dist/clis/instagram/profile.yaml +0 -42
- package/dist/clis/instagram/save.yaml +0 -46
- package/dist/clis/instagram/saved.yaml +0 -40
- package/dist/clis/instagram/search.yaml +0 -44
- package/dist/clis/instagram/unfollow.yaml +0 -38
- package/dist/clis/instagram/unlike.yaml +0 -46
- package/dist/clis/instagram/unsave.yaml +0 -46
- package/dist/clis/instagram/user.yaml +0 -54
- package/dist/clis/jike/post.yaml +0 -59
- package/dist/clis/jike/topic.yaml +0 -53
- package/dist/clis/jike/user.yaml +0 -52
- package/dist/clis/jimeng/generate.yaml +0 -85
- package/dist/clis/jimeng/history.yaml +0 -46
- package/dist/clis/linux-do/categories.yaml +0 -70
- package/dist/clis/linux-do/search.yaml +0 -48
- package/dist/clis/linux-do/tags.yaml +0 -41
- package/dist/clis/linux-do/topic.yaml +0 -62
- package/dist/clis/linux-do/user-posts.yaml +0 -67
- package/dist/clis/linux-do/user-topics.yaml +0 -54
- package/dist/clis/lobsters/active.yaml +0 -29
- package/dist/clis/lobsters/hot.yaml +0 -29
- package/dist/clis/lobsters/newest.yaml +0 -29
- package/dist/clis/lobsters/tag.yaml +0 -34
- package/dist/clis/pixiv/detail.yaml +0 -49
- package/dist/clis/pixiv/ranking.yaml +0 -53
- package/dist/clis/pixiv/user.yaml +0 -46
- package/dist/clis/reddit/frontpage.yaml +0 -30
- package/dist/clis/reddit/hot.yaml +0 -47
- package/dist/clis/reddit/popular.yaml +0 -40
- package/dist/clis/reddit/search.yaml +0 -61
- package/dist/clis/reddit/subreddit.yaml +0 -50
- package/dist/clis/reddit/user-comments.yaml +0 -46
- package/dist/clis/reddit/user-posts.yaml +0 -44
- package/dist/clis/reddit/user.yaml +0 -40
- package/dist/clis/stackoverflow/bounties.yaml +0 -29
- package/dist/clis/stackoverflow/hot.yaml +0 -28
- package/dist/clis/stackoverflow/search.yaml +0 -33
- package/dist/clis/stackoverflow/unanswered.yaml +0 -28
- package/dist/clis/steam/top-sellers.yaml +0 -29
- package/dist/clis/tiktok/comment.yaml +0 -66
- package/dist/clis/tiktok/explore.yaml +0 -39
- package/dist/clis/tiktok/follow.yaml +0 -39
- package/dist/clis/tiktok/following.yaml +0 -46
- package/dist/clis/tiktok/friends.yaml +0 -47
- package/dist/clis/tiktok/like.yaml +0 -38
- package/dist/clis/tiktok/live.yaml +0 -51
- package/dist/clis/tiktok/notifications.yaml +0 -52
- package/dist/clis/tiktok/profile.yaml +0 -45
- package/dist/clis/tiktok/save.yaml +0 -34
- package/dist/clis/tiktok/search.yaml +0 -47
- package/dist/clis/tiktok/unfollow.yaml +0 -44
- package/dist/clis/tiktok/unlike.yaml +0 -38
- package/dist/clis/tiktok/unsave.yaml +0 -36
- package/dist/clis/tiktok/user.yaml +0 -44
- package/dist/clis/v2ex/hot.yaml +0 -28
- package/dist/clis/v2ex/latest.yaml +0 -28
- package/dist/clis/v2ex/member.yaml +0 -29
- package/dist/clis/v2ex/node.yaml +0 -34
- package/dist/clis/v2ex/nodes.yaml +0 -31
- package/dist/clis/v2ex/replies.yaml +0 -32
- package/dist/clis/v2ex/topic.yaml +0 -33
- package/dist/clis/v2ex/user.yaml +0 -34
- package/dist/clis/xiaoe/catalog.yaml +0 -129
- package/dist/clis/xiaoe/content.yaml +0 -43
- package/dist/clis/xiaoe/courses.yaml +0 -73
- package/dist/clis/xiaoe/detail.yaml +0 -39
- package/dist/clis/xiaoe/play-url.yaml +0 -124
- package/dist/clis/xiaohongshu/feed.yaml +0 -31
- package/dist/clis/xiaohongshu/notifications.yaml +0 -37
- package/dist/clis/xueqiu/earnings-date.yaml +0 -69
- package/dist/clis/xueqiu/feed.yaml +0 -53
- package/dist/clis/xueqiu/groups.yaml +0 -23
- package/dist/clis/xueqiu/hot-stock.yaml +0 -49
- package/dist/clis/xueqiu/hot.yaml +0 -46
- package/dist/clis/xueqiu/kline.yaml +0 -65
- package/dist/clis/xueqiu/search.yaml +0 -55
- package/dist/clis/xueqiu/stock.yaml +0 -69
- package/dist/clis/xueqiu/watchlist.yaml +0 -46
- package/dist/clis/zhihu/hot.yaml +0 -46
- package/dist/clis/zhihu/search.yaml +0 -59
- package/dist/src/daemon.test.js +0 -65
- package/dist/src/idle-manager.d.ts +0 -19
- package/dist/src/idle-manager.js +0 -54
- package/dist/src/yaml-schema.d.ts +0 -29
- package/dist/src/yaml-schema.js +0 -22
- /package/dist/{src/daemon.test.d.ts → clis/bilibili/hot.d.ts} +0 -0
package/dist/src/plugin.test.js
CHANGED
|
@@ -146,11 +146,11 @@ describe('validatePluginStructure', () => {
|
|
|
146
146
|
expect(res.valid).toBe(false);
|
|
147
147
|
expect(res.errors[0]).toContain('No command files found');
|
|
148
148
|
});
|
|
149
|
-
it('returns
|
|
149
|
+
it('returns invalid for YAML-only plugin (YAML no longer supported)', () => {
|
|
150
150
|
fs.writeFileSync(path.join(testDir, 'cmd.yaml'), 'site: test');
|
|
151
151
|
const res = _validatePluginStructure(testDir);
|
|
152
|
-
expect(res.valid).toBe(
|
|
153
|
-
expect(res.errors).
|
|
152
|
+
expect(res.valid).toBe(false);
|
|
153
|
+
expect(res.errors[0]).toContain('No command files found');
|
|
154
154
|
});
|
|
155
155
|
it('returns valid for JS plugin', () => {
|
|
156
156
|
fs.writeFileSync(path.join(testDir, 'cmd.js'), 'console.log("hi");');
|
|
@@ -361,7 +361,7 @@ describe('listPlugins', () => {
|
|
|
361
361
|
});
|
|
362
362
|
it('lists installed plugins', () => {
|
|
363
363
|
fs.mkdirSync(testDir, { recursive: true });
|
|
364
|
-
fs.writeFileSync(path.join(testDir, 'hello.
|
|
364
|
+
fs.writeFileSync(path.join(testDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
365
365
|
const plugins = listPlugins();
|
|
366
366
|
const found = plugins.find(p => p.name === '__test-list-plugin__');
|
|
367
367
|
expect(found).toBeDefined();
|
|
@@ -369,7 +369,7 @@ describe('listPlugins', () => {
|
|
|
369
369
|
});
|
|
370
370
|
it('includes version metadata from the lock file', () => {
|
|
371
371
|
fs.mkdirSync(testDir, { recursive: true });
|
|
372
|
-
fs.writeFileSync(path.join(testDir, 'hello.
|
|
372
|
+
fs.writeFileSync(path.join(testDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
373
373
|
const lock = _readLockFile();
|
|
374
374
|
lock['__test-list-plugin__'] = {
|
|
375
375
|
source: { kind: 'git', url: 'https://github.com/user/repo.git' },
|
|
@@ -393,7 +393,7 @@ describe('listPlugins', () => {
|
|
|
393
393
|
const localTarget = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-list-'));
|
|
394
394
|
const linkPath = path.join(PLUGINS_DIR, '__test-list-plugin__');
|
|
395
395
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
396
|
-
fs.writeFileSync(path.join(localTarget, 'hello.
|
|
396
|
+
fs.writeFileSync(path.join(localTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
397
397
|
try {
|
|
398
398
|
fs.unlinkSync(linkPath);
|
|
399
399
|
}
|
|
@@ -435,13 +435,13 @@ describe('uninstallPlugin', () => {
|
|
|
435
435
|
});
|
|
436
436
|
it('removes plugin directory', () => {
|
|
437
437
|
fs.mkdirSync(testDir, { recursive: true });
|
|
438
|
-
fs.writeFileSync(path.join(testDir, 'test.
|
|
438
|
+
fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test" })');
|
|
439
439
|
uninstallPlugin('__test-uninstall__');
|
|
440
440
|
expect(fs.existsSync(testDir)).toBe(false);
|
|
441
441
|
});
|
|
442
442
|
it('removes lock entry on uninstall', () => {
|
|
443
443
|
fs.mkdirSync(testDir, { recursive: true });
|
|
444
|
-
fs.writeFileSync(path.join(testDir, 'test.
|
|
444
|
+
fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test" })');
|
|
445
445
|
const lock = _readLockFile();
|
|
446
446
|
lock['__test-uninstall__'] = {
|
|
447
447
|
source: { kind: 'git', url: 'https://github.com/user/repo.git' },
|
|
@@ -464,7 +464,7 @@ describe('updatePlugin', () => {
|
|
|
464
464
|
const localTarget = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-update-'));
|
|
465
465
|
const linkPath = path.join(PLUGINS_DIR, '__test-local-update__');
|
|
466
466
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
467
|
-
fs.writeFileSync(path.join(localTarget, 'hello.
|
|
467
|
+
fs.writeFileSync(path.join(localTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
468
468
|
fs.symlinkSync(localTarget, linkPath, 'dir');
|
|
469
469
|
const lock = _readLockFile();
|
|
470
470
|
lock['__test-local-update__'] = {
|
|
@@ -540,7 +540,7 @@ describe('postInstallMonorepoLifecycle', () => {
|
|
|
540
540
|
private: true,
|
|
541
541
|
workspaces: ['packages/*'],
|
|
542
542
|
}));
|
|
543
|
-
fs.writeFileSync(path.join(subDir, 'hello.
|
|
543
|
+
fs.writeFileSync(path.join(subDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
544
544
|
});
|
|
545
545
|
afterEach(() => {
|
|
546
546
|
fs.rmSync(repoDir, { recursive: true, force: true });
|
|
@@ -561,9 +561,9 @@ describe('updateAllPlugins', () => {
|
|
|
561
561
|
fs.mkdirSync(testDirA, { recursive: true });
|
|
562
562
|
fs.mkdirSync(testDirB, { recursive: true });
|
|
563
563
|
fs.mkdirSync(testDirC, { recursive: true });
|
|
564
|
-
fs.writeFileSync(path.join(testDirA, 'cmd.
|
|
565
|
-
fs.writeFileSync(path.join(testDirB, 'cmd.
|
|
566
|
-
fs.writeFileSync(path.join(testDirC, 'cmd.
|
|
564
|
+
fs.writeFileSync(path.join(testDirA, 'cmd.js'), 'cli({ site: "a", name: "cmd" })');
|
|
565
|
+
fs.writeFileSync(path.join(testDirB, 'cmd.js'), 'cli({ site: "b", name: "cmd" })');
|
|
566
|
+
fs.writeFileSync(path.join(testDirC, 'cmd.js'), 'cli({ site: "c", name: "cmd" })');
|
|
567
567
|
const lock = _readLockFile();
|
|
568
568
|
lock['plugin-a'] = {
|
|
569
569
|
source: { kind: 'git', url: 'https://github.com/user/plugin-a.git' },
|
|
@@ -608,7 +608,7 @@ describe('updateAllPlugins', () => {
|
|
|
608
608
|
const cloneUrl = String(args[3]);
|
|
609
609
|
const cloneDir = String(args[4]);
|
|
610
610
|
fs.mkdirSync(cloneDir, { recursive: true });
|
|
611
|
-
fs.writeFileSync(path.join(cloneDir, 'cmd.
|
|
611
|
+
fs.writeFileSync(path.join(cloneDir, 'cmd.js'), 'cli({ site: "test", name: "hello" })');
|
|
612
612
|
if (cloneUrl.includes('plugin-b')) {
|
|
613
613
|
fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: 'plugin-b' }));
|
|
614
614
|
}
|
|
@@ -695,7 +695,7 @@ describe('monorepo uninstall with symlink', () => {
|
|
|
695
695
|
monoDir = path.join(_getMonoreposDir(), '__test-mono__');
|
|
696
696
|
const subDir = path.join(monoDir, 'packages', 'sub');
|
|
697
697
|
fs.mkdirSync(subDir, { recursive: true });
|
|
698
|
-
fs.writeFileSync(path.join(subDir, 'cmd.
|
|
698
|
+
fs.writeFileSync(path.join(subDir, 'cmd.js'), 'cli({ site: "test", name: "cmd" })');
|
|
699
699
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
700
700
|
fs.symlinkSync(subDir, pluginDir, 'dir');
|
|
701
701
|
const lock = _readLockFile();
|
|
@@ -762,7 +762,7 @@ describe('listPlugins with monorepo metadata', () => {
|
|
|
762
762
|
const testLink = path.join(PLUGINS_DIR, '__test-mono-list__');
|
|
763
763
|
beforeEach(() => {
|
|
764
764
|
fs.mkdirSync(testSymlinkTarget, { recursive: true });
|
|
765
|
-
fs.writeFileSync(path.join(testSymlinkTarget, 'hello.
|
|
765
|
+
fs.writeFileSync(path.join(testSymlinkTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
766
766
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
767
767
|
try {
|
|
768
768
|
fs.unlinkSync(testLink);
|
|
@@ -809,7 +809,7 @@ describe('installLocalPlugin', () => {
|
|
|
809
809
|
const pluginName = '__test-local-plugin__';
|
|
810
810
|
beforeEach(() => {
|
|
811
811
|
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-install-'));
|
|
812
|
-
fs.writeFileSync(path.join(tmpDir, 'hello.
|
|
812
|
+
fs.writeFileSync(path.join(tmpDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
813
813
|
});
|
|
814
814
|
afterEach(() => {
|
|
815
815
|
const linkPath = path.join(PLUGINS_DIR, pluginName);
|
|
@@ -1007,7 +1007,7 @@ describe('installPlugin transactional staging', () => {
|
|
|
1007
1007
|
if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
|
|
1008
1008
|
const cloneDir = String(args[args.length - 1]);
|
|
1009
1009
|
fs.mkdirSync(cloneDir, { recursive: true });
|
|
1010
|
-
fs.writeFileSync(path.join(cloneDir, 'hello.
|
|
1010
|
+
fs.writeFileSync(path.join(cloneDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1011
1011
|
fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: standaloneName }));
|
|
1012
1012
|
return '';
|
|
1013
1013
|
}
|
|
@@ -1038,7 +1038,7 @@ describe('installPlugin transactional staging', () => {
|
|
|
1038
1038
|
alpha: { path: 'packages/alpha' },
|
|
1039
1039
|
},
|
|
1040
1040
|
}));
|
|
1041
|
-
fs.writeFileSync(path.join(alphaDir, 'hello.
|
|
1041
|
+
fs.writeFileSync(path.join(alphaDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1042
1042
|
return '';
|
|
1043
1043
|
}
|
|
1044
1044
|
if (cmd === 'npm' && Array.isArray(args) && args[0] === 'install') {
|
|
@@ -1095,7 +1095,7 @@ describe('installPlugin with existing monorepo', () => {
|
|
|
1095
1095
|
[pluginName]: { path: `packages/${pluginName}` },
|
|
1096
1096
|
},
|
|
1097
1097
|
}));
|
|
1098
|
-
fs.writeFileSync(path.join(subDir, 'hello.
|
|
1098
|
+
fs.writeFileSync(path.join(subDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1099
1099
|
mockExecFileSync.mockImplementation((cmd, args) => {
|
|
1100
1100
|
if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
|
|
1101
1101
|
const cloneDir = String(args[4]);
|
|
@@ -1154,7 +1154,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1154
1154
|
});
|
|
1155
1155
|
it('keeps the existing standalone plugin when staged update preparation fails', () => {
|
|
1156
1156
|
fs.mkdirSync(standaloneDir, { recursive: true });
|
|
1157
|
-
fs.writeFileSync(path.join(standaloneDir, 'old.
|
|
1157
|
+
fs.writeFileSync(path.join(standaloneDir, 'old.js'), 'cli({ site: "old", name: "old" })');
|
|
1158
1158
|
const lock = _readLockFile();
|
|
1159
1159
|
lock[standaloneName] = {
|
|
1160
1160
|
source: {
|
|
@@ -1169,7 +1169,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1169
1169
|
if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
|
|
1170
1170
|
const cloneDir = String(args[4]);
|
|
1171
1171
|
fs.mkdirSync(cloneDir, { recursive: true });
|
|
1172
|
-
fs.writeFileSync(path.join(cloneDir, 'hello.
|
|
1172
|
+
fs.writeFileSync(path.join(cloneDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1173
1173
|
fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: standaloneName }));
|
|
1174
1174
|
return '';
|
|
1175
1175
|
}
|
|
@@ -1183,13 +1183,13 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1183
1183
|
});
|
|
1184
1184
|
expect(() => updatePlugin(standaloneName)).toThrow('npm install failed');
|
|
1185
1185
|
expect(fs.existsSync(standaloneDir)).toBe(true);
|
|
1186
|
-
expect(fs.readFileSync(path.join(standaloneDir, 'old.
|
|
1186
|
+
expect(fs.readFileSync(path.join(standaloneDir, 'old.js'), 'utf-8')).toContain('site: "old"');
|
|
1187
1187
|
expect(_readLockFile()[standaloneName]?.commitHash).toBe('oldhasholdhasholdhasholdhasholdhasholdh');
|
|
1188
1188
|
});
|
|
1189
1189
|
it('keeps the existing monorepo repo and link when staged update preparation fails', () => {
|
|
1190
1190
|
const subDir = path.join(monorepoRepoDir, 'packages', monorepoPluginName);
|
|
1191
1191
|
fs.mkdirSync(subDir, { recursive: true });
|
|
1192
|
-
fs.writeFileSync(path.join(subDir, 'old.
|
|
1192
|
+
fs.writeFileSync(path.join(subDir, 'old.js'), 'cli({ site: "old", name: "old" })');
|
|
1193
1193
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
1194
1194
|
fs.symlinkSync(subDir, monorepoLink, 'dir');
|
|
1195
1195
|
const lock = _readLockFile();
|
|
@@ -1218,7 +1218,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1218
1218
|
[monorepoPluginName]: { path: `packages/${monorepoPluginName}` },
|
|
1219
1219
|
},
|
|
1220
1220
|
}));
|
|
1221
|
-
fs.writeFileSync(path.join(alphaDir, 'hello.
|
|
1221
|
+
fs.writeFileSync(path.join(alphaDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1222
1222
|
return '';
|
|
1223
1223
|
}
|
|
1224
1224
|
if (cmd === 'npm' && Array.isArray(args) && args[0] === 'install') {
|
|
@@ -1232,13 +1232,13 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1232
1232
|
expect(() => updatePlugin(monorepoPluginName)).toThrow('npm install failed');
|
|
1233
1233
|
expect(fs.existsSync(monorepoRepoDir)).toBe(true);
|
|
1234
1234
|
expect(fs.existsSync(monorepoLink)).toBe(true);
|
|
1235
|
-
expect(fs.readFileSync(path.join(subDir, 'old.
|
|
1235
|
+
expect(fs.readFileSync(path.join(subDir, 'old.js'), 'utf-8')).toContain('site: "old"');
|
|
1236
1236
|
expect(_readLockFile()[monorepoPluginName]?.commitHash).toBe('oldmonooldmonooldmonooldmonooldmonoold');
|
|
1237
1237
|
});
|
|
1238
1238
|
it('relinks monorepo plugins when the updated manifest moves their subPath', () => {
|
|
1239
1239
|
const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
|
|
1240
1240
|
fs.mkdirSync(oldSubDir, { recursive: true });
|
|
1241
|
-
fs.writeFileSync(path.join(oldSubDir, 'old.
|
|
1241
|
+
fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old" })');
|
|
1242
1242
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
1243
1243
|
fs.symlinkSync(oldSubDir, monorepoLink, 'dir');
|
|
1244
1244
|
const lock = _readLockFile();
|
|
@@ -1263,7 +1263,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1263
1263
|
[monorepoPluginName]: { path: 'packages/moved-alpha' },
|
|
1264
1264
|
},
|
|
1265
1265
|
}));
|
|
1266
|
-
fs.writeFileSync(path.join(movedDir, 'hello.
|
|
1266
|
+
fs.writeFileSync(path.join(movedDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1267
1267
|
return '';
|
|
1268
1268
|
}
|
|
1269
1269
|
if (cmd === 'git' && Array.isArray(args) && args[0] === 'rev-parse' && args[1] === 'HEAD') {
|
|
@@ -1282,7 +1282,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1282
1282
|
it('rolls back the monorepo repo swap when relinking fails', () => {
|
|
1283
1283
|
const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
|
|
1284
1284
|
fs.mkdirSync(oldSubDir, { recursive: true });
|
|
1285
|
-
fs.writeFileSync(path.join(oldSubDir, 'old.
|
|
1285
|
+
fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old" })');
|
|
1286
1286
|
fs.mkdirSync(monorepoLink, { recursive: true });
|
|
1287
1287
|
fs.writeFileSync(path.join(monorepoLink, 'blocker.txt'), 'not a symlink');
|
|
1288
1288
|
const lock = _readLockFile();
|
|
@@ -1307,7 +1307,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1307
1307
|
[monorepoPluginName]: { path: 'packages/moved-alpha' },
|
|
1308
1308
|
},
|
|
1309
1309
|
}));
|
|
1310
|
-
fs.writeFileSync(path.join(movedDir, 'hello.
|
|
1310
|
+
fs.writeFileSync(path.join(movedDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1311
1311
|
return '';
|
|
1312
1312
|
}
|
|
1313
1313
|
if (cmd === 'git' && Array.isArray(args) && args[0] === 'rev-parse' && args[1] === 'HEAD') {
|
|
@@ -1316,7 +1316,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1316
1316
|
return '';
|
|
1317
1317
|
});
|
|
1318
1318
|
expect(() => updatePlugin(monorepoPluginName)).toThrow('to be a symlink');
|
|
1319
|
-
expect(fs.existsSync(path.join(monorepoRepoDir, 'packages', 'old-alpha', 'old.
|
|
1319
|
+
expect(fs.existsSync(path.join(monorepoRepoDir, 'packages', 'old-alpha', 'old.js'))).toBe(true);
|
|
1320
1320
|
expect(fs.existsSync(path.join(monorepoRepoDir, 'packages', 'moved-alpha'))).toBe(false);
|
|
1321
1321
|
expect(fs.readFileSync(path.join(monorepoLink, 'blocker.txt'), 'utf-8')).toBe('not a symlink');
|
|
1322
1322
|
expect(_readLockFile()[monorepoPluginName]?.source).toMatchObject({
|
package/dist/src/record.js
CHANGED
|
@@ -15,7 +15,6 @@ import * as fs from 'node:fs';
|
|
|
15
15
|
import * as path from 'node:path';
|
|
16
16
|
import * as readline from 'node:readline';
|
|
17
17
|
import chalk from 'chalk';
|
|
18
|
-
import yaml from 'js-yaml';
|
|
19
18
|
import { sendCommand } from './browser/daemon-client.js';
|
|
20
19
|
import { SEARCH_PARAMS, PAGINATION_PARAMS, FIELD_ROLES } from './constants.js';
|
|
21
20
|
import { urlToPattern, findArrayPath, inferCapabilityName, inferStrategy, detectAuthFromContent, classifyQueryParams, isNoiseUrl, } from './analysis.js';
|
|
@@ -454,8 +453,8 @@ export async function recordSession(opts) {
|
|
|
454
453
|
const pollMs = opts.pollMs ?? 2000;
|
|
455
454
|
const timeoutMs = opts.timeoutMs ?? 60_000;
|
|
456
455
|
const allRequests = [];
|
|
457
|
-
// Track which
|
|
458
|
-
const
|
|
456
|
+
// Track which pages (targetIds) have already had the interceptor injected
|
|
457
|
+
const injectedPages = new Set();
|
|
459
458
|
// Infer site name from URL
|
|
460
459
|
const site = opts.site ?? (() => {
|
|
461
460
|
try {
|
|
@@ -479,9 +478,10 @@ export async function recordSession(opts) {
|
|
|
479
478
|
// Inject into initial tab
|
|
480
479
|
const initialTabs = await listTabs(workspace);
|
|
481
480
|
for (const tab of initialTabs) {
|
|
482
|
-
|
|
481
|
+
if (tab.page)
|
|
482
|
+
await injectIntoPage(workspace, tab.page, injectedPages);
|
|
483
483
|
}
|
|
484
|
-
console.log(chalk.bold('\n Recording.
|
|
484
|
+
console.log(chalk.bold('\n Recording. Use the page in the browser automation window.'));
|
|
485
485
|
console.log(chalk.dim(` Will auto-stop after ${timeoutMs / 1000}s, or press Enter to stop now.\n`));
|
|
486
486
|
// Race: Enter key vs timeout
|
|
487
487
|
let stopped = false;
|
|
@@ -500,15 +500,16 @@ export async function recordSession(opts) {
|
|
|
500
500
|
// Discover and inject into any new tabs
|
|
501
501
|
const tabs = await listTabs(workspace);
|
|
502
502
|
for (const tab of tabs) {
|
|
503
|
-
|
|
503
|
+
if (tab.page)
|
|
504
|
+
await injectIntoPage(workspace, tab.page, injectedPages);
|
|
504
505
|
}
|
|
505
|
-
// Drain captured data from all known
|
|
506
|
-
for (const
|
|
507
|
-
const batch = await
|
|
506
|
+
// Drain captured data from all known pages
|
|
507
|
+
for (const page of injectedPages) {
|
|
508
|
+
const batch = await execOnPage(workspace, page, generateReadRecordedJs());
|
|
508
509
|
if (Array.isArray(batch) && batch.length > 0) {
|
|
509
510
|
for (const r of batch)
|
|
510
511
|
allRequests.push(r);
|
|
511
|
-
console.log(chalk.dim(` [
|
|
512
|
+
console.log(chalk.dim(` [page:${page.slice(0, 8)}] +${batch.length} captured — total: ${allRequests.length}`));
|
|
512
513
|
}
|
|
513
514
|
}
|
|
514
515
|
}
|
|
@@ -519,10 +520,10 @@ export async function recordSession(opts) {
|
|
|
519
520
|
await Promise.race([enterPromise, timeoutPromise]);
|
|
520
521
|
cleanupEnter(); // Always clean up readline to prevent process from hanging
|
|
521
522
|
clearInterval(pollInterval);
|
|
522
|
-
// Final drain from all known
|
|
523
|
-
for (const
|
|
523
|
+
// Final drain from all known pages
|
|
524
|
+
for (const page of injectedPages) {
|
|
524
525
|
try {
|
|
525
|
-
const last = await
|
|
526
|
+
const last = await execOnPage(workspace, page, generateReadRecordedJs());
|
|
526
527
|
if (Array.isArray(last) && last.length > 0) {
|
|
527
528
|
for (const r of last)
|
|
528
529
|
allRequests.push(r);
|
|
@@ -543,25 +544,25 @@ export async function recordSession(opts) {
|
|
|
543
544
|
async function listTabs(workspace) {
|
|
544
545
|
try {
|
|
545
546
|
const result = await sendCommand('tabs', { op: 'list', workspace });
|
|
546
|
-
return Array.isArray(result) ? result.filter(t => t.
|
|
547
|
+
return Array.isArray(result) ? result.filter(t => t.page != null) : [];
|
|
547
548
|
}
|
|
548
549
|
catch {
|
|
549
550
|
return [];
|
|
550
551
|
}
|
|
551
552
|
}
|
|
552
|
-
async function
|
|
553
|
-
return sendCommand('exec', { code, workspace,
|
|
553
|
+
async function execOnPage(workspace, page, code) {
|
|
554
|
+
return sendCommand('exec', { code, workspace, page });
|
|
554
555
|
}
|
|
555
|
-
async function
|
|
556
|
+
async function injectIntoPage(workspace, page, injectedPages) {
|
|
556
557
|
try {
|
|
557
|
-
await
|
|
558
|
-
if (!
|
|
559
|
-
|
|
560
|
-
console.log(chalk.green(` ✓ Interceptor injected into
|
|
558
|
+
await execOnPage(workspace, page, generateFullCaptureInterceptorJs());
|
|
559
|
+
if (!injectedPages.has(page)) {
|
|
560
|
+
injectedPages.add(page);
|
|
561
|
+
console.log(chalk.green(` ✓ Interceptor injected into page:${page.slice(0, 8)}`));
|
|
561
562
|
}
|
|
562
563
|
}
|
|
563
564
|
catch {
|
|
564
|
-
//
|
|
565
|
+
// Page not debuggable (e.g. chrome:// pages) — skip silently
|
|
565
566
|
}
|
|
566
567
|
}
|
|
567
568
|
/**
|
|
@@ -619,10 +620,10 @@ function analyzeAndWrite(site, pageUrl, requests, outDir) {
|
|
|
619
620
|
if (usedNames.has(entry.name))
|
|
620
621
|
continue;
|
|
621
622
|
usedNames.add(entry.name);
|
|
622
|
-
const filePath = path.join(candidatesDir, `${entry.name}.
|
|
623
|
-
fs.writeFileSync(filePath,
|
|
623
|
+
const filePath = path.join(candidatesDir, `${entry.name}.json`);
|
|
624
|
+
fs.writeFileSync(filePath, JSON.stringify(entry.yaml, null, 2));
|
|
624
625
|
candidates.push({ name: entry.name, path: filePath, strategy: entry.strategy });
|
|
625
|
-
console.log(chalk.green(` ✓ Generated: ${chalk.bold(entry.name)}.
|
|
626
|
+
console.log(chalk.green(` ✓ Generated: ${chalk.bold(entry.name)}.json [${entry.strategy}]`));
|
|
626
627
|
console.log(chalk.dim(` → ${filePath}`));
|
|
627
628
|
}
|
|
628
629
|
if (candidates.length === 0) {
|
|
@@ -10,19 +10,15 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export function detectRuntime() {
|
|
12
12
|
// Bun always exposes globalThis.Bun (including Bun.version)
|
|
13
|
-
|
|
14
|
-
return 'bun';
|
|
15
|
-
return 'node';
|
|
13
|
+
return globalThis.Bun !== undefined ? 'bun' : 'node';
|
|
16
14
|
}
|
|
17
15
|
/**
|
|
18
16
|
* Return a human-readable version string for the current runtime.
|
|
19
17
|
* Examples: "v22.13.0" (Node), "1.1.42" (Bun)
|
|
20
18
|
*/
|
|
21
19
|
export function getRuntimeVersion() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
return process.version; // e.g. "v22.13.0"
|
|
20
|
+
const bun = globalThis.Bun;
|
|
21
|
+
return bun ? bun.version : process.version;
|
|
26
22
|
}
|
|
27
23
|
/**
|
|
28
24
|
* Return a combined label like "node v22.13.0" or "bun 1.1.42".
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Injected script for detecting frontend frameworks (Vue, React, Next, Nuxt, etc.)
|
|
3
|
+
*
|
|
4
|
+
* Serialized via `.toString()` and evaluated in the page context. Types here are
|
|
5
|
+
* only for the TS boundary — see scripts/store.ts for the same pattern.
|
|
3
6
|
*/
|
|
4
7
|
export declare function detectFramework(): Record<string, boolean>;
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Injected script for detecting frontend frameworks (Vue, React, Next, Nuxt, etc.)
|
|
3
|
+
*
|
|
4
|
+
* Serialized via `.toString()` and evaluated in the page context. Types here are
|
|
5
|
+
* only for the TS boundary — see scripts/store.ts for the same pattern.
|
|
3
6
|
*/
|
|
4
7
|
export function detectFramework() {
|
|
5
8
|
const r = {};
|
|
6
9
|
try {
|
|
7
10
|
const app = document.querySelector('#app');
|
|
11
|
+
const w = window;
|
|
8
12
|
r.vue3 = !!(app && app.__vue_app__);
|
|
9
13
|
r.vue2 = !!(app && app.__vue__);
|
|
10
|
-
r.react = !!
|
|
11
|
-
r.nextjs = !!
|
|
12
|
-
r.nuxt = !!
|
|
13
|
-
if (r.vue3 && app
|
|
14
|
+
r.react = !!w.__REACT_DEVTOOLS_GLOBAL_HOOK__ || !!document.querySelector('[data-reactroot]');
|
|
15
|
+
r.nextjs = !!w.__NEXT_DATA__;
|
|
16
|
+
r.nuxt = !!w.__NUXT__;
|
|
17
|
+
if (r.vue3 && app?.__vue_app__) {
|
|
14
18
|
const gp = app.__vue_app__.config?.globalProperties;
|
|
15
19
|
r.pinia = !!(gp && gp.$pinia);
|
|
16
20
|
r.vuex = !!(gp && gp.$store);
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Injected script for discovering Pinia or Vuex stores and their actions/state representations
|
|
2
|
+
* Injected script for discovering Pinia or Vuex stores and their actions/state representations.
|
|
3
|
+
*
|
|
4
|
+
* This function is serialized via `.toString()` and evaluated inside the page context,
|
|
5
|
+
* so the types below only exist at the TS boundary — the runtime shapes are whatever
|
|
6
|
+
* Pinia/Vuex put on the Vue app. We use narrow structural types for the fields we touch.
|
|
3
7
|
*/
|
|
4
8
|
export declare function discoverStores(): {
|
|
5
9
|
type: string;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Injected script for discovering Pinia or Vuex stores and their actions/state representations
|
|
2
|
+
* Injected script for discovering Pinia or Vuex stores and their actions/state representations.
|
|
3
|
+
*
|
|
4
|
+
* This function is serialized via `.toString()` and evaluated inside the page context,
|
|
5
|
+
* so the types below only exist at the TS boundary — the runtime shapes are whatever
|
|
6
|
+
* Pinia/Vuex put on the Vue app. We use narrow structural types for the fields we touch.
|
|
3
7
|
*/
|
|
4
8
|
export function discoverStores() {
|
|
5
9
|
const stores = [];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate skill: thin wrapper over generateVerifiedFromUrl.
|
|
3
|
+
*
|
|
4
|
+
* Maps GenerateOutcome → SkillOutput.
|
|
5
|
+
* Used by `opencli generate <url>` (automated path in opencli-explorer workflow).
|
|
6
|
+
*
|
|
7
|
+
* Design:
|
|
8
|
+
* - Input: url + goal? (user intent, not execution strategy)
|
|
9
|
+
* - Output: machine-readable decision fields + human-readable message
|
|
10
|
+
* - Single source of truth: P1 GenerateOutcome
|
|
11
|
+
* - No re-orchestration, no auto-escalation to browser
|
|
12
|
+
*/
|
|
13
|
+
import { type GenerateOutcome, type StopReason, type EscalationReason, type SuggestedAction, type Reusability } from './generate-verified.js';
|
|
14
|
+
import type { IBrowserFactory } from './runtime.js';
|
|
15
|
+
export interface SkillInput {
|
|
16
|
+
url: string;
|
|
17
|
+
goal?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SkillOutput {
|
|
20
|
+
conclusion: 'success' | 'blocked' | 'needs-human-check';
|
|
21
|
+
reason?: StopReason | EscalationReason;
|
|
22
|
+
suggested_action?: SuggestedAction;
|
|
23
|
+
reusability?: Reusability;
|
|
24
|
+
command?: string;
|
|
25
|
+
strategy?: string;
|
|
26
|
+
path?: string;
|
|
27
|
+
message: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function mapOutcomeToSkillOutput(outcome: GenerateOutcome): SkillOutput;
|
|
30
|
+
export declare function executeGenerateSkill(input: SkillInput, BrowserFactory: new () => IBrowserFactory): Promise<SkillOutput>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate skill: thin wrapper over generateVerifiedFromUrl.
|
|
3
|
+
*
|
|
4
|
+
* Maps GenerateOutcome → SkillOutput.
|
|
5
|
+
* Used by `opencli generate <url>` (automated path in opencli-explorer workflow).
|
|
6
|
+
*
|
|
7
|
+
* Design:
|
|
8
|
+
* - Input: url + goal? (user intent, not execution strategy)
|
|
9
|
+
* - Output: machine-readable decision fields + human-readable message
|
|
10
|
+
* - Single source of truth: P1 GenerateOutcome
|
|
11
|
+
* - No re-orchestration, no auto-escalation to browser
|
|
12
|
+
*/
|
|
13
|
+
import { generateVerifiedFromUrl, } from './generate-verified.js';
|
|
14
|
+
// ── Message Templates ────────────────────────────────────────────────────────
|
|
15
|
+
const BLOCKED_MESSAGES = {
|
|
16
|
+
'no-viable-api-surface': '该站点没有发现可用的 JSON API 接口,无法自动生成 CLI',
|
|
17
|
+
'auth-too-complex': '所有接口都需要超出自动化能力的认证方式(如 signature/bearer),无法自动生成',
|
|
18
|
+
'no-viable-candidate': '发现了 API 接口,但未能合成有效的 CLI 候选',
|
|
19
|
+
'execution-environment-unavailable': '浏览器未连接,请先运行 opencli doctor 检查环境',
|
|
20
|
+
};
|
|
21
|
+
const ESCALATION_MESSAGES = {
|
|
22
|
+
'unsupported-required-args': () => '候选需要用户提供必填参数的示例值后重试',
|
|
23
|
+
'empty-result': () => '候选验证返回空结果,建议用 opencli-browser 检查',
|
|
24
|
+
'sparse-fields': () => '候选验证结果字段不足,建议人工检查',
|
|
25
|
+
'non-array-result': () => '返回结果不是数组格式,建议用 opencli-browser 检查接口返回结构',
|
|
26
|
+
'timeout': () => '验证超时,建议用 opencli-browser 手动检查接口响应',
|
|
27
|
+
'selector-mismatch': () => '数据路径不匹配,建议用 opencli-browser 检查实际返回结构',
|
|
28
|
+
'verify-inconclusive': (ctx) => ctx?.path
|
|
29
|
+
? `验证结果不确定,候选已保存在 ${ctx.path},需要人工审查`
|
|
30
|
+
: '验证结果不确定,需要人工审查',
|
|
31
|
+
};
|
|
32
|
+
// ── Core Mapping ─────────────────────────────────────────────────────────────
|
|
33
|
+
export function mapOutcomeToSkillOutput(outcome) {
|
|
34
|
+
switch (outcome.status) {
|
|
35
|
+
case 'success':
|
|
36
|
+
return {
|
|
37
|
+
conclusion: 'success',
|
|
38
|
+
reusability: outcome.reusability ?? 'verified-artifact',
|
|
39
|
+
command: outcome.adapter?.command,
|
|
40
|
+
strategy: outcome.adapter?.strategy,
|
|
41
|
+
path: outcome.adapter?.path,
|
|
42
|
+
message: `已生成 ${outcome.adapter?.command ?? 'unknown'},可直接使用。策略: ${outcome.adapter?.strategy ?? 'unknown'}`,
|
|
43
|
+
};
|
|
44
|
+
case 'blocked':
|
|
45
|
+
return {
|
|
46
|
+
conclusion: 'blocked',
|
|
47
|
+
reason: outcome.reason,
|
|
48
|
+
message: BLOCKED_MESSAGES[outcome.reason] ?? outcome.message ?? '生成被阻断',
|
|
49
|
+
};
|
|
50
|
+
case 'needs-human-check': {
|
|
51
|
+
const escalation = outcome.escalation;
|
|
52
|
+
const reason = escalation?.reason;
|
|
53
|
+
const candidatePath = escalation?.candidate?.path ?? undefined;
|
|
54
|
+
const messageFn = reason ? ESCALATION_MESSAGES[reason] : undefined;
|
|
55
|
+
return {
|
|
56
|
+
conclusion: 'needs-human-check',
|
|
57
|
+
reason,
|
|
58
|
+
suggested_action: escalation?.suggested_action,
|
|
59
|
+
reusability: outcome.reusability,
|
|
60
|
+
path: candidatePath ?? undefined,
|
|
61
|
+
message: outcome.message ?? messageFn?.({ path: candidatePath ?? undefined }) ?? '需要人工检查',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// ── Skill Entry Point ────────────────────────────────────────────────────────
|
|
67
|
+
export async function executeGenerateSkill(input, BrowserFactory) {
|
|
68
|
+
const opts = {
|
|
69
|
+
url: input.url,
|
|
70
|
+
BrowserFactory,
|
|
71
|
+
goal: input.goal ?? null,
|
|
72
|
+
};
|
|
73
|
+
const outcome = await generateVerifiedFromUrl(opts);
|
|
74
|
+
return mapOutcomeToSkillOutput(outcome);
|
|
75
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|