@jackwener/opencli 1.6.8 → 1.6.10
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 +117 -59
- package/README.zh-CN.md +123 -79
- package/dist/clis/_shared/common.d.ts +3 -0
- package/dist/clis/_shared/common.js +22 -0
- package/dist/clis/bilibili/hot.d.ts +1 -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/search.d.ts +14 -0
- package/dist/clis/jianyu/search.js +135 -0
- package/dist/clis/jianyu/search.test.d.ts +1 -0
- package/dist/clis/jianyu/search.test.js +23 -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/quark/ls.d.ts +1 -0
- package/dist/clis/quark/ls.js +63 -0
- package/dist/clis/quark/mkdir.d.ts +1 -0
- package/dist/clis/quark/mkdir.js +36 -0
- package/dist/clis/quark/mv.d.ts +1 -0
- package/dist/clis/quark/mv.js +53 -0
- package/dist/clis/quark/rename.d.ts +1 -0
- package/dist/clis/quark/rename.js +26 -0
- package/dist/clis/quark/rm.d.ts +1 -0
- package/dist/clis/quark/rm.js +24 -0
- package/dist/clis/quark/save.d.ts +1 -0
- package/dist/clis/quark/save.js +80 -0
- package/dist/clis/quark/share-tree.d.ts +1 -0
- package/dist/clis/quark/share-tree.js +45 -0
- package/dist/clis/quark/utils.d.ts +50 -0
- package/dist/clis/quark/utils.js +146 -0
- package/dist/clis/quark/utils.test.d.ts +1 -0
- package/dist/clis/quark/utils.test.js +58 -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/twitter/reply.js +3 -8
- package/dist/clis/twitter/reply.test.js +5 -5
- 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 +125 -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/note.js +8 -3
- package/dist/clis/xiaohongshu/note.test.js +11 -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/answer.d.ts +1 -0
- package/dist/clis/zhihu/answer.js +194 -0
- package/dist/clis/zhihu/answer.test.d.ts +1 -0
- package/dist/clis/zhihu/answer.test.js +81 -0
- package/dist/clis/zhihu/comment.d.ts +1 -0
- package/dist/clis/zhihu/comment.js +335 -0
- package/dist/clis/zhihu/comment.test.d.ts +1 -0
- package/dist/clis/zhihu/comment.test.js +54 -0
- package/dist/clis/zhihu/favorite.d.ts +1 -0
- package/dist/clis/zhihu/favorite.js +224 -0
- package/dist/clis/zhihu/favorite.test.d.ts +1 -0
- package/dist/clis/zhihu/favorite.test.js +196 -0
- package/dist/clis/zhihu/follow.d.ts +1 -0
- package/dist/clis/zhihu/follow.js +80 -0
- package/dist/clis/zhihu/follow.test.d.ts +1 -0
- package/dist/clis/zhihu/follow.test.js +45 -0
- package/dist/clis/zhihu/hot.d.ts +1 -0
- package/dist/clis/zhihu/hot.js +43 -0
- package/dist/clis/zhihu/like.d.ts +1 -0
- package/dist/clis/zhihu/like.js +91 -0
- package/dist/clis/zhihu/like.test.d.ts +1 -0
- package/dist/clis/zhihu/like.test.js +64 -0
- package/dist/clis/zhihu/search.d.ts +1 -0
- package/dist/clis/zhihu/search.js +52 -0
- package/dist/clis/zhihu/target.d.ts +24 -0
- package/dist/clis/zhihu/target.js +91 -0
- package/dist/clis/zhihu/target.test.d.ts +1 -0
- package/dist/clis/zhihu/target.test.js +77 -0
- package/dist/clis/zhihu/write-shared.d.ts +32 -0
- package/dist/clis/zhihu/write-shared.js +221 -0
- package/dist/clis/zhihu/write-shared.test.d.ts +1 -0
- package/dist/clis/zhihu/write-shared.test.js +175 -0
- package/dist/src/browser/bridge.d.ts +2 -0
- package/dist/src/browser/bridge.js +30 -24
- package/dist/src/browser/daemon-client.d.ts +30 -10
- package/dist/src/browser/daemon-client.js +42 -27
- package/dist/src/browser/daemon-client.test.js +32 -25
- 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/index.d.ts +2 -1
- package/dist/src/browser/index.js +1 -1
- package/dist/src/browser/page.d.ts +9 -8
- package/dist/src/browser/page.js +33 -31
- package/dist/src/browser.test.js +27 -8
- 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 +73 -65
- 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 -0
- package/dist/src/clis/binance/commands.test.js +58 -0
- 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/commanderAdapter.js +19 -6
- 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/diagnostic.d.ts +1 -0
- package/dist/src/diagnostic.js +64 -2
- package/dist/src/diagnostic.test.js +93 -3
- package/dist/src/discovery.d.ts +3 -3
- package/dist/src/discovery.js +34 -97
- package/dist/src/doctor.d.ts +2 -0
- package/dist/src/doctor.js +59 -31
- package/dist/src/doctor.test.js +89 -16
- package/dist/src/download/index.d.ts +1 -1
- package/dist/src/engine.test.js +4 -19
- package/dist/src/execution.js +1 -13
- package/dist/src/explore.js +1 -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 +11 -6
- package/dist/src/generate.js +4 -7
- 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 +3 -2
- package/dist/src/plugin.js +29 -14
- package/dist/src/plugin.test.js +47 -32
- 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 +5 -5
- 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/browser/discover.d.ts +0 -15
- package/dist/src/browser/discover.js +0 -19
- package/dist/src/yaml-schema.d.ts +0 -29
- package/dist/src/yaml-schema.js +0 -22
package/dist/src/plugin.test.js
CHANGED
|
@@ -12,7 +12,7 @@ const { mockExecFileSync, mockExecSync } = vi.hoisted(() => ({
|
|
|
12
12
|
mockExecFileSync: vi.fn(),
|
|
13
13
|
mockExecSync: vi.fn(),
|
|
14
14
|
}));
|
|
15
|
-
const { _getCommitHash, _installDependencies, _postInstallMonorepoLifecycle, _promoteDir, _replaceDir, installPlugin, listPlugins, _readLockFile, _readLockFileWithWriter, _resolveEsbuildBin, uninstallPlugin, updatePlugin, _parseSource, _updateAllPlugins, _validatePluginStructure, _writeLockFile, _writeLockFileWithFs, _isSymlinkSync, _getMonoreposDir, getLockFilePath, _installLocalPlugin, _isLocalPluginSource, _moveDir, _resolvePluginSource, _resolveStoredPluginSource, _toStoredPluginSource, _toLocalPluginSource, } = pluginModule;
|
|
15
|
+
const { _getCommitHash, _installDependencies, _postInstallMonorepoLifecycle, _promoteDir, _replaceDir, installPlugin, listPlugins, _readLockFile, _readLockFileWithWriter, _resolveEsbuildBin, _resolveHostOpencliRoot, uninstallPlugin, updatePlugin, _parseSource, _updateAllPlugins, _validatePluginStructure, _writeLockFile, _writeLockFileWithFs, _isSymlinkSync, _getMonoreposDir, getLockFilePath, _installLocalPlugin, _isLocalPluginSource, _moveDir, _resolvePluginSource, _resolveStoredPluginSource, _toStoredPluginSource, _toLocalPluginSource, } = pluginModule;
|
|
16
16
|
describe('parseSource', () => {
|
|
17
17
|
it('parses github:user/repo format', () => {
|
|
18
18
|
const result = _parseSource('github:ByteYue/opencli-plugin-github-trending');
|
|
@@ -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");');
|
|
@@ -336,6 +336,21 @@ describe('resolveEsbuildBin', () => {
|
|
|
336
336
|
expect(binPath).toMatch(/esbuild(\.cmd)?$/);
|
|
337
337
|
});
|
|
338
338
|
});
|
|
339
|
+
describe('resolveHostOpencliRoot', () => {
|
|
340
|
+
let tmpDir;
|
|
341
|
+
beforeEach(() => {
|
|
342
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-host-root-test-'));
|
|
343
|
+
});
|
|
344
|
+
afterEach(() => {
|
|
345
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
346
|
+
});
|
|
347
|
+
it('walks up from compiled dist/src files to the package root', () => {
|
|
348
|
+
fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify({ name: '@jackwener/opencli' }));
|
|
349
|
+
const distSrcDir = path.join(tmpDir, 'dist', 'src');
|
|
350
|
+
fs.mkdirSync(distSrcDir, { recursive: true });
|
|
351
|
+
expect(_resolveHostOpencliRoot(path.join(distSrcDir, 'plugin.js'))).toBe(tmpDir);
|
|
352
|
+
});
|
|
353
|
+
});
|
|
339
354
|
describe('listPlugins', () => {
|
|
340
355
|
const testDir = path.join(PLUGINS_DIR, '__test-list-plugin__');
|
|
341
356
|
afterEach(() => {
|
|
@@ -346,7 +361,7 @@ describe('listPlugins', () => {
|
|
|
346
361
|
});
|
|
347
362
|
it('lists installed plugins', () => {
|
|
348
363
|
fs.mkdirSync(testDir, { recursive: true });
|
|
349
|
-
fs.writeFileSync(path.join(testDir, 'hello.
|
|
364
|
+
fs.writeFileSync(path.join(testDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
350
365
|
const plugins = listPlugins();
|
|
351
366
|
const found = plugins.find(p => p.name === '__test-list-plugin__');
|
|
352
367
|
expect(found).toBeDefined();
|
|
@@ -354,7 +369,7 @@ describe('listPlugins', () => {
|
|
|
354
369
|
});
|
|
355
370
|
it('includes version metadata from the lock file', () => {
|
|
356
371
|
fs.mkdirSync(testDir, { recursive: true });
|
|
357
|
-
fs.writeFileSync(path.join(testDir, 'hello.
|
|
372
|
+
fs.writeFileSync(path.join(testDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
358
373
|
const lock = _readLockFile();
|
|
359
374
|
lock['__test-list-plugin__'] = {
|
|
360
375
|
source: { kind: 'git', url: 'https://github.com/user/repo.git' },
|
|
@@ -378,7 +393,7 @@ describe('listPlugins', () => {
|
|
|
378
393
|
const localTarget = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-list-'));
|
|
379
394
|
const linkPath = path.join(PLUGINS_DIR, '__test-list-plugin__');
|
|
380
395
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
381
|
-
fs.writeFileSync(path.join(localTarget, 'hello.
|
|
396
|
+
fs.writeFileSync(path.join(localTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
382
397
|
try {
|
|
383
398
|
fs.unlinkSync(linkPath);
|
|
384
399
|
}
|
|
@@ -420,13 +435,13 @@ describe('uninstallPlugin', () => {
|
|
|
420
435
|
});
|
|
421
436
|
it('removes plugin directory', () => {
|
|
422
437
|
fs.mkdirSync(testDir, { recursive: true });
|
|
423
|
-
fs.writeFileSync(path.join(testDir, 'test.
|
|
438
|
+
fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test" })');
|
|
424
439
|
uninstallPlugin('__test-uninstall__');
|
|
425
440
|
expect(fs.existsSync(testDir)).toBe(false);
|
|
426
441
|
});
|
|
427
442
|
it('removes lock entry on uninstall', () => {
|
|
428
443
|
fs.mkdirSync(testDir, { recursive: true });
|
|
429
|
-
fs.writeFileSync(path.join(testDir, 'test.
|
|
444
|
+
fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test" })');
|
|
430
445
|
const lock = _readLockFile();
|
|
431
446
|
lock['__test-uninstall__'] = {
|
|
432
447
|
source: { kind: 'git', url: 'https://github.com/user/repo.git' },
|
|
@@ -449,7 +464,7 @@ describe('updatePlugin', () => {
|
|
|
449
464
|
const localTarget = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-update-'));
|
|
450
465
|
const linkPath = path.join(PLUGINS_DIR, '__test-local-update__');
|
|
451
466
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
452
|
-
fs.writeFileSync(path.join(localTarget, 'hello.
|
|
467
|
+
fs.writeFileSync(path.join(localTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
453
468
|
fs.symlinkSync(localTarget, linkPath, 'dir');
|
|
454
469
|
const lock = _readLockFile();
|
|
455
470
|
lock['__test-local-update__'] = {
|
|
@@ -525,7 +540,7 @@ describe('postInstallMonorepoLifecycle', () => {
|
|
|
525
540
|
private: true,
|
|
526
541
|
workspaces: ['packages/*'],
|
|
527
542
|
}));
|
|
528
|
-
fs.writeFileSync(path.join(subDir, 'hello.
|
|
543
|
+
fs.writeFileSync(path.join(subDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
529
544
|
});
|
|
530
545
|
afterEach(() => {
|
|
531
546
|
fs.rmSync(repoDir, { recursive: true, force: true });
|
|
@@ -546,9 +561,9 @@ describe('updateAllPlugins', () => {
|
|
|
546
561
|
fs.mkdirSync(testDirA, { recursive: true });
|
|
547
562
|
fs.mkdirSync(testDirB, { recursive: true });
|
|
548
563
|
fs.mkdirSync(testDirC, { recursive: true });
|
|
549
|
-
fs.writeFileSync(path.join(testDirA, 'cmd.
|
|
550
|
-
fs.writeFileSync(path.join(testDirB, 'cmd.
|
|
551
|
-
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" })');
|
|
552
567
|
const lock = _readLockFile();
|
|
553
568
|
lock['plugin-a'] = {
|
|
554
569
|
source: { kind: 'git', url: 'https://github.com/user/plugin-a.git' },
|
|
@@ -593,7 +608,7 @@ describe('updateAllPlugins', () => {
|
|
|
593
608
|
const cloneUrl = String(args[3]);
|
|
594
609
|
const cloneDir = String(args[4]);
|
|
595
610
|
fs.mkdirSync(cloneDir, { recursive: true });
|
|
596
|
-
fs.writeFileSync(path.join(cloneDir, 'cmd.
|
|
611
|
+
fs.writeFileSync(path.join(cloneDir, 'cmd.js'), 'cli({ site: "test", name: "hello" })');
|
|
597
612
|
if (cloneUrl.includes('plugin-b')) {
|
|
598
613
|
fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: 'plugin-b' }));
|
|
599
614
|
}
|
|
@@ -680,7 +695,7 @@ describe('monorepo uninstall with symlink', () => {
|
|
|
680
695
|
monoDir = path.join(_getMonoreposDir(), '__test-mono__');
|
|
681
696
|
const subDir = path.join(monoDir, 'packages', 'sub');
|
|
682
697
|
fs.mkdirSync(subDir, { recursive: true });
|
|
683
|
-
fs.writeFileSync(path.join(subDir, 'cmd.
|
|
698
|
+
fs.writeFileSync(path.join(subDir, 'cmd.js'), 'cli({ site: "test", name: "cmd" })');
|
|
684
699
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
685
700
|
fs.symlinkSync(subDir, pluginDir, 'dir');
|
|
686
701
|
const lock = _readLockFile();
|
|
@@ -747,7 +762,7 @@ describe('listPlugins with monorepo metadata', () => {
|
|
|
747
762
|
const testLink = path.join(PLUGINS_DIR, '__test-mono-list__');
|
|
748
763
|
beforeEach(() => {
|
|
749
764
|
fs.mkdirSync(testSymlinkTarget, { recursive: true });
|
|
750
|
-
fs.writeFileSync(path.join(testSymlinkTarget, 'hello.
|
|
765
|
+
fs.writeFileSync(path.join(testSymlinkTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
751
766
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
752
767
|
try {
|
|
753
768
|
fs.unlinkSync(testLink);
|
|
@@ -794,7 +809,7 @@ describe('installLocalPlugin', () => {
|
|
|
794
809
|
const pluginName = '__test-local-plugin__';
|
|
795
810
|
beforeEach(() => {
|
|
796
811
|
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-install-'));
|
|
797
|
-
fs.writeFileSync(path.join(tmpDir, 'hello.
|
|
812
|
+
fs.writeFileSync(path.join(tmpDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
798
813
|
});
|
|
799
814
|
afterEach(() => {
|
|
800
815
|
const linkPath = path.join(PLUGINS_DIR, pluginName);
|
|
@@ -992,7 +1007,7 @@ describe('installPlugin transactional staging', () => {
|
|
|
992
1007
|
if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
|
|
993
1008
|
const cloneDir = String(args[args.length - 1]);
|
|
994
1009
|
fs.mkdirSync(cloneDir, { recursive: true });
|
|
995
|
-
fs.writeFileSync(path.join(cloneDir, 'hello.
|
|
1010
|
+
fs.writeFileSync(path.join(cloneDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
996
1011
|
fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: standaloneName }));
|
|
997
1012
|
return '';
|
|
998
1013
|
}
|
|
@@ -1023,7 +1038,7 @@ describe('installPlugin transactional staging', () => {
|
|
|
1023
1038
|
alpha: { path: 'packages/alpha' },
|
|
1024
1039
|
},
|
|
1025
1040
|
}));
|
|
1026
|
-
fs.writeFileSync(path.join(alphaDir, 'hello.
|
|
1041
|
+
fs.writeFileSync(path.join(alphaDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1027
1042
|
return '';
|
|
1028
1043
|
}
|
|
1029
1044
|
if (cmd === 'npm' && Array.isArray(args) && args[0] === 'install') {
|
|
@@ -1080,7 +1095,7 @@ describe('installPlugin with existing monorepo', () => {
|
|
|
1080
1095
|
[pluginName]: { path: `packages/${pluginName}` },
|
|
1081
1096
|
},
|
|
1082
1097
|
}));
|
|
1083
|
-
fs.writeFileSync(path.join(subDir, 'hello.
|
|
1098
|
+
fs.writeFileSync(path.join(subDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1084
1099
|
mockExecFileSync.mockImplementation((cmd, args) => {
|
|
1085
1100
|
if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
|
|
1086
1101
|
const cloneDir = String(args[4]);
|
|
@@ -1139,7 +1154,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1139
1154
|
});
|
|
1140
1155
|
it('keeps the existing standalone plugin when staged update preparation fails', () => {
|
|
1141
1156
|
fs.mkdirSync(standaloneDir, { recursive: true });
|
|
1142
|
-
fs.writeFileSync(path.join(standaloneDir, 'old.
|
|
1157
|
+
fs.writeFileSync(path.join(standaloneDir, 'old.js'), 'cli({ site: "old", name: "old" })');
|
|
1143
1158
|
const lock = _readLockFile();
|
|
1144
1159
|
lock[standaloneName] = {
|
|
1145
1160
|
source: {
|
|
@@ -1154,7 +1169,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1154
1169
|
if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
|
|
1155
1170
|
const cloneDir = String(args[4]);
|
|
1156
1171
|
fs.mkdirSync(cloneDir, { recursive: true });
|
|
1157
|
-
fs.writeFileSync(path.join(cloneDir, 'hello.
|
|
1172
|
+
fs.writeFileSync(path.join(cloneDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1158
1173
|
fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: standaloneName }));
|
|
1159
1174
|
return '';
|
|
1160
1175
|
}
|
|
@@ -1168,13 +1183,13 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1168
1183
|
});
|
|
1169
1184
|
expect(() => updatePlugin(standaloneName)).toThrow('npm install failed');
|
|
1170
1185
|
expect(fs.existsSync(standaloneDir)).toBe(true);
|
|
1171
|
-
expect(fs.readFileSync(path.join(standaloneDir, 'old.
|
|
1186
|
+
expect(fs.readFileSync(path.join(standaloneDir, 'old.js'), 'utf-8')).toContain('site: "old"');
|
|
1172
1187
|
expect(_readLockFile()[standaloneName]?.commitHash).toBe('oldhasholdhasholdhasholdhasholdhasholdh');
|
|
1173
1188
|
});
|
|
1174
1189
|
it('keeps the existing monorepo repo and link when staged update preparation fails', () => {
|
|
1175
1190
|
const subDir = path.join(monorepoRepoDir, 'packages', monorepoPluginName);
|
|
1176
1191
|
fs.mkdirSync(subDir, { recursive: true });
|
|
1177
|
-
fs.writeFileSync(path.join(subDir, 'old.
|
|
1192
|
+
fs.writeFileSync(path.join(subDir, 'old.js'), 'cli({ site: "old", name: "old" })');
|
|
1178
1193
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
1179
1194
|
fs.symlinkSync(subDir, monorepoLink, 'dir');
|
|
1180
1195
|
const lock = _readLockFile();
|
|
@@ -1203,7 +1218,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1203
1218
|
[monorepoPluginName]: { path: `packages/${monorepoPluginName}` },
|
|
1204
1219
|
},
|
|
1205
1220
|
}));
|
|
1206
|
-
fs.writeFileSync(path.join(alphaDir, 'hello.
|
|
1221
|
+
fs.writeFileSync(path.join(alphaDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1207
1222
|
return '';
|
|
1208
1223
|
}
|
|
1209
1224
|
if (cmd === 'npm' && Array.isArray(args) && args[0] === 'install') {
|
|
@@ -1217,13 +1232,13 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1217
1232
|
expect(() => updatePlugin(monorepoPluginName)).toThrow('npm install failed');
|
|
1218
1233
|
expect(fs.existsSync(monorepoRepoDir)).toBe(true);
|
|
1219
1234
|
expect(fs.existsSync(monorepoLink)).toBe(true);
|
|
1220
|
-
expect(fs.readFileSync(path.join(subDir, 'old.
|
|
1235
|
+
expect(fs.readFileSync(path.join(subDir, 'old.js'), 'utf-8')).toContain('site: "old"');
|
|
1221
1236
|
expect(_readLockFile()[monorepoPluginName]?.commitHash).toBe('oldmonooldmonooldmonooldmonooldmonoold');
|
|
1222
1237
|
});
|
|
1223
1238
|
it('relinks monorepo plugins when the updated manifest moves their subPath', () => {
|
|
1224
1239
|
const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
|
|
1225
1240
|
fs.mkdirSync(oldSubDir, { recursive: true });
|
|
1226
|
-
fs.writeFileSync(path.join(oldSubDir, 'old.
|
|
1241
|
+
fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old" })');
|
|
1227
1242
|
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
1228
1243
|
fs.symlinkSync(oldSubDir, monorepoLink, 'dir');
|
|
1229
1244
|
const lock = _readLockFile();
|
|
@@ -1248,7 +1263,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1248
1263
|
[monorepoPluginName]: { path: 'packages/moved-alpha' },
|
|
1249
1264
|
},
|
|
1250
1265
|
}));
|
|
1251
|
-
fs.writeFileSync(path.join(movedDir, 'hello.
|
|
1266
|
+
fs.writeFileSync(path.join(movedDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1252
1267
|
return '';
|
|
1253
1268
|
}
|
|
1254
1269
|
if (cmd === 'git' && Array.isArray(args) && args[0] === 'rev-parse' && args[1] === 'HEAD') {
|
|
@@ -1267,7 +1282,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1267
1282
|
it('rolls back the monorepo repo swap when relinking fails', () => {
|
|
1268
1283
|
const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
|
|
1269
1284
|
fs.mkdirSync(oldSubDir, { recursive: true });
|
|
1270
|
-
fs.writeFileSync(path.join(oldSubDir, 'old.
|
|
1285
|
+
fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old" })');
|
|
1271
1286
|
fs.mkdirSync(monorepoLink, { recursive: true });
|
|
1272
1287
|
fs.writeFileSync(path.join(monorepoLink, 'blocker.txt'), 'not a symlink');
|
|
1273
1288
|
const lock = _readLockFile();
|
|
@@ -1292,7 +1307,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1292
1307
|
[monorepoPluginName]: { path: 'packages/moved-alpha' },
|
|
1293
1308
|
},
|
|
1294
1309
|
}));
|
|
1295
|
-
fs.writeFileSync(path.join(movedDir, 'hello.
|
|
1310
|
+
fs.writeFileSync(path.join(movedDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
|
|
1296
1311
|
return '';
|
|
1297
1312
|
}
|
|
1298
1313
|
if (cmd === 'git' && Array.isArray(args) && args[0] === 'rev-parse' && args[1] === 'HEAD') {
|
|
@@ -1301,7 +1316,7 @@ describe('updatePlugin transactional staging', () => {
|
|
|
1301
1316
|
return '';
|
|
1302
1317
|
});
|
|
1303
1318
|
expect(() => updatePlugin(monorepoPluginName)).toThrow('to be a symlink');
|
|
1304
|
-
expect(fs.existsSync(path.join(monorepoRepoDir, 'packages', 'old-alpha', 'old.
|
|
1319
|
+
expect(fs.existsSync(path.join(monorepoRepoDir, 'packages', 'old-alpha', 'old.js'))).toBe(true);
|
|
1305
1320
|
expect(fs.existsSync(path.join(monorepoRepoDir, 'packages', 'moved-alpha'))).toBe(false);
|
|
1306
1321
|
expect(fs.readFileSync(path.join(monorepoLink, 'blocker.txt'), 'utf-8')).toBe('not a symlink');
|
|
1307
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 {};
|