@jackwener/opencli 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/cross-project-adapter-migration/SKILL.md +2 -2
- package/.github/pull_request_template.md +7 -0
- package/.github/workflows/doc-check.yml +36 -0
- package/.github/workflows/docs.yml +7 -42
- package/CHANGELOG.md +23 -0
- package/CLI-EXPLORER.md +9 -8
- package/CONTRIBUTING.md +39 -1
- package/README.md +33 -19
- package/README.zh-CN.md +64 -27
- package/SKILL.md +102 -33
- package/dist/browser/cdp.d.ts +4 -4
- package/dist/browser/cdp.js +45 -17
- package/dist/browser/daemon-client.d.ts +2 -1
- package/dist/browser/dom-helpers.js +38 -7
- package/dist/browser/dom-snapshot.d.ts +86 -0
- package/dist/browser/dom-snapshot.js +729 -0
- package/dist/browser/dom-snapshot.test.d.ts +11 -0
- package/dist/browser/dom-snapshot.test.js +212 -0
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.js +1 -0
- package/dist/browser/page.d.ts +18 -25
- package/dist/browser/page.js +44 -5
- package/dist/build-manifest.d.ts +11 -4
- package/dist/build-manifest.js +79 -34
- package/dist/build-manifest.test.js +58 -2
- package/dist/cli-manifest.json +4273 -1771
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +255 -162
- package/dist/clis/apple-podcasts/commands.test.d.ts +2 -0
- package/dist/clis/apple-podcasts/commands.test.js +76 -0
- package/dist/clis/apple-podcasts/search.js +2 -2
- package/dist/clis/apple-podcasts/top.js +9 -2
- package/dist/clis/arxiv/search.js +1 -1
- package/dist/clis/barchart/greeks.js +1 -1
- package/dist/clis/barchart/options.js +1 -1
- package/dist/clis/barchart/quote.js +1 -1
- package/dist/clis/bilibili/download.js +1 -1
- package/dist/clis/bilibili/dynamic.js +1 -1
- package/dist/clis/bilibili/favorite.js +1 -1
- package/dist/clis/bilibili/feed.js +1 -1
- package/dist/clis/bilibili/following.js +2 -2
- package/dist/clis/bilibili/history.js +1 -1
- package/dist/clis/bilibili/me.js +1 -1
- package/dist/clis/bilibili/ranking.js +1 -1
- package/dist/clis/bilibili/search.js +3 -3
- package/dist/clis/bilibili/subtitle.js +2 -2
- package/dist/clis/bilibili/user-videos.js +2 -2
- package/dist/{bilibili.d.ts → clis/bilibili/utils.d.ts} +1 -1
- package/dist/clis/bloomberg/businessweek.js +17 -0
- package/dist/clis/bloomberg/economics.js +17 -0
- package/dist/clis/bloomberg/feeds.d.ts +1 -0
- package/dist/clis/bloomberg/feeds.js +15 -0
- package/dist/clis/bloomberg/industries.d.ts +1 -0
- package/dist/clis/bloomberg/industries.js +17 -0
- package/dist/clis/bloomberg/main.d.ts +1 -0
- package/dist/clis/bloomberg/main.js +17 -0
- package/dist/clis/bloomberg/markets.d.ts +1 -0
- package/dist/clis/bloomberg/markets.js +17 -0
- package/dist/clis/bloomberg/news.d.ts +1 -0
- package/dist/clis/bloomberg/news.js +105 -0
- package/dist/clis/bloomberg/opinions.d.ts +1 -0
- package/dist/clis/bloomberg/opinions.js +17 -0
- package/dist/clis/bloomberg/politics.d.ts +1 -0
- package/dist/clis/bloomberg/politics.js +17 -0
- package/dist/clis/bloomberg/tech.d.ts +1 -0
- package/dist/clis/bloomberg/tech.js +17 -0
- package/dist/clis/bloomberg/utils.d.ts +34 -0
- package/dist/clis/bloomberg/utils.js +364 -0
- package/dist/clis/bloomberg/utils.test.d.ts +1 -0
- package/dist/clis/bloomberg/utils.test.js +129 -0
- package/dist/clis/boss/batchgreet.js +12 -99
- package/dist/clis/boss/chatlist.js +9 -26
- package/dist/clis/boss/chatmsg.js +11 -42
- package/dist/clis/boss/common.d.ts +92 -0
- package/dist/clis/boss/common.js +223 -0
- package/dist/clis/boss/detail.js +8 -50
- package/dist/clis/boss/exchange.js +13 -79
- package/dist/clis/boss/greet.js +20 -147
- package/dist/clis/boss/invite.js +26 -121
- package/dist/clis/boss/joblist.js +6 -31
- package/dist/clis/boss/mark.js +12 -85
- package/dist/clis/boss/recommend.js +10 -49
- package/dist/clis/boss/resume.js +18 -118
- package/dist/clis/boss/search.js +13 -61
- package/dist/clis/boss/send.js +18 -152
- package/dist/clis/boss/stats.js +20 -71
- package/dist/clis/chaoxing/assignments.js +1 -1
- package/dist/clis/chaoxing/exams.js +1 -1
- package/dist/{chaoxing.d.ts → clis/chaoxing/utils.d.ts} +1 -1
- package/dist/{chaoxing.js → clis/chaoxing/utils.js} +0 -2
- package/dist/clis/chaoxing/utils.test.d.ts +1 -0
- package/dist/{chaoxing.test.js → clis/chaoxing/utils.test.js} +1 -1
- package/dist/clis/chatgpt/read.js +1 -1
- package/dist/clis/chatwise/export.js +1 -1
- package/dist/clis/chatwise/model.js +2 -2
- package/dist/clis/chatwise/screenshot.js +1 -1
- package/dist/clis/codex/export.js +1 -1
- package/dist/clis/codex/model.js +2 -2
- package/dist/clis/codex/screenshot.js +1 -1
- package/dist/clis/coupang/add-to-cart.js +3 -4
- package/dist/clis/coupang/search.js +2 -4
- package/dist/clis/coupang/utils.test.d.ts +1 -0
- package/dist/{coupang.test.js → clis/coupang/utils.test.js} +1 -1
- package/dist/clis/ctrip/search.js +1 -1
- package/dist/clis/cursor/export.js +1 -1
- package/dist/clis/cursor/model.js +2 -2
- package/dist/clis/cursor/screenshot.js +1 -1
- package/dist/clis/devto/tag.yaml +34 -0
- package/dist/clis/devto/top.yaml +29 -0
- package/dist/clis/devto/user.yaml +33 -0
- package/dist/clis/douban/book-hot.d.ts +1 -0
- package/dist/clis/douban/book-hot.js +14 -0
- package/dist/clis/douban/marks.d.ts +1 -0
- package/dist/clis/douban/marks.js +115 -0
- package/dist/clis/douban/movie-hot.d.ts +1 -0
- package/dist/clis/douban/movie-hot.js +14 -0
- package/dist/clis/douban/reviews.d.ts +1 -0
- package/dist/clis/douban/reviews.js +106 -0
- package/dist/clis/douban/search.d.ts +1 -0
- package/dist/clis/douban/search.js +16 -0
- package/dist/clis/douban/shared.d.ts +4 -0
- package/dist/clis/douban/shared.js +155 -0
- package/dist/clis/douban/subject.yaml +76 -0
- package/dist/clis/douban/top250.yaml +70 -0
- package/dist/clis/douban/utils.d.ts +35 -0
- package/dist/clis/douban/utils.js +48 -0
- package/dist/clis/facebook/add-friend.yaml +43 -0
- package/dist/clis/facebook/events.yaml +44 -0
- package/dist/clis/facebook/feed.yaml +63 -0
- package/dist/clis/facebook/friends.yaml +42 -0
- package/dist/clis/facebook/groups.yaml +50 -0
- package/dist/clis/facebook/join-group.yaml +44 -0
- package/dist/clis/facebook/memories.yaml +39 -0
- package/dist/clis/facebook/notifications.yaml +40 -0
- package/dist/clis/facebook/profile.yaml +37 -0
- package/dist/clis/facebook/search.yaml +46 -0
- package/dist/clis/google/news.d.ts +5 -0
- package/dist/clis/google/news.js +58 -0
- package/dist/clis/google/search.d.ts +10 -0
- package/dist/clis/google/search.js +127 -0
- package/dist/clis/google/suggest.d.ts +5 -0
- package/dist/clis/google/suggest.js +34 -0
- package/dist/clis/google/trends.d.ts +5 -0
- package/dist/clis/google/trends.js +38 -0
- package/dist/clis/google/utils.d.ts +9 -0
- package/dist/clis/google/utils.js +23 -0
- package/dist/clis/google/utils.test.d.ts +1 -0
- package/dist/clis/google/utils.test.js +75 -0
- package/dist/clis/grok/ask.d.ts +14 -0
- package/dist/clis/grok/ask.js +257 -65
- package/dist/clis/grok/ask.test.d.ts +1 -0
- package/dist/clis/grok/ask.test.js +36 -0
- package/dist/clis/instagram/comment.yaml +52 -0
- package/dist/clis/instagram/explore.yaml +43 -0
- package/dist/clis/instagram/follow.yaml +41 -0
- package/dist/clis/instagram/followers.yaml +51 -0
- package/dist/clis/instagram/following.yaml +51 -0
- package/dist/clis/instagram/like.yaml +46 -0
- package/dist/clis/instagram/profile.yaml +42 -0
- package/dist/clis/instagram/save.yaml +46 -0
- package/dist/clis/instagram/saved.yaml +40 -0
- package/dist/clis/instagram/search.yaml +43 -0
- package/dist/clis/instagram/unfollow.yaml +38 -0
- package/dist/clis/instagram/unlike.yaml +46 -0
- package/dist/clis/instagram/unsave.yaml +46 -0
- package/dist/clis/instagram/user.yaml +54 -0
- package/dist/clis/jike/comment.js +2 -3
- package/dist/clis/jike/create.js +1 -2
- package/dist/clis/jike/feed.js +0 -1
- package/dist/clis/jike/like.js +1 -2
- package/dist/clis/jike/notifications.js +0 -1
- package/dist/clis/jike/post.yaml +1 -0
- package/dist/clis/jike/repost.js +2 -3
- package/dist/clis/jike/search.js +2 -3
- package/dist/clis/jike/topic.yaml +1 -0
- package/dist/clis/jike/user.yaml +1 -0
- package/dist/clis/jimeng/generate.yaml +1 -0
- package/dist/clis/jimeng/history.yaml +0 -1
- package/dist/clis/linkedin/search.js +7 -7
- package/dist/clis/linux-do/category.yaml +2 -0
- package/dist/clis/linux-do/search.yaml +4 -3
- package/dist/clis/linux-do/topic.yaml +1 -0
- package/dist/clis/lobsters/active.yaml +29 -0
- package/dist/clis/lobsters/hot.yaml +29 -0
- package/dist/clis/lobsters/newest.yaml +29 -0
- package/dist/clis/lobsters/tag.yaml +34 -0
- package/dist/clis/medium/feed.d.ts +1 -0
- package/dist/clis/medium/feed.js +15 -0
- package/dist/clis/medium/search.d.ts +1 -0
- package/dist/clis/medium/search.js +15 -0
- package/dist/clis/medium/shared.d.ts +5 -0
- package/dist/clis/medium/shared.js +78 -0
- package/dist/clis/medium/user.d.ts +1 -0
- package/dist/clis/medium/user.js +15 -0
- package/dist/clis/notion/export.js +1 -1
- package/dist/clis/reddit/comment.js +3 -4
- package/dist/clis/reddit/read.js +4 -5
- package/dist/clis/reddit/save.js +2 -3
- package/dist/clis/reddit/saved.js +0 -1
- package/dist/clis/reddit/search.yaml +1 -0
- package/dist/clis/reddit/subreddit.yaml +1 -0
- package/dist/clis/reddit/subscribe.js +1 -2
- package/dist/clis/reddit/upvote.js +2 -3
- package/dist/clis/reddit/upvoted.js +0 -1
- package/dist/clis/reddit/user-comments.yaml +1 -0
- package/dist/clis/reddit/user-posts.yaml +1 -0
- package/dist/clis/reddit/user.yaml +1 -0
- package/dist/clis/reuters/search.js +1 -1
- package/dist/clis/sinablog/article.d.ts +1 -0
- package/dist/clis/sinablog/article.js +14 -0
- package/dist/clis/sinablog/hot.d.ts +1 -0
- package/dist/clis/sinablog/hot.js +14 -0
- package/dist/clis/sinablog/search.d.ts +1 -0
- package/dist/clis/sinablog/search.js +51 -0
- package/dist/clis/sinablog/shared.d.ts +7 -0
- package/dist/clis/sinablog/shared.js +187 -0
- package/dist/clis/sinablog/user.d.ts +1 -0
- package/dist/clis/sinablog/user.js +15 -0
- package/dist/clis/smzdm/search.js +2 -3
- package/dist/clis/stackoverflow/search.yaml +1 -0
- package/dist/clis/steam/top-sellers.yaml +29 -0
- package/dist/clis/substack/feed.d.ts +1 -0
- package/dist/clis/substack/feed.js +15 -0
- package/dist/clis/substack/publication.d.ts +1 -0
- package/dist/clis/substack/publication.js +15 -0
- package/dist/clis/substack/search.d.ts +1 -0
- package/dist/clis/substack/search.js +77 -0
- package/dist/clis/substack/shared.d.ts +4 -0
- package/dist/clis/substack/shared.js +129 -0
- package/dist/clis/tiktok/comment.yaml +66 -0
- package/dist/clis/tiktok/explore.yaml +39 -0
- package/dist/clis/tiktok/follow.yaml +39 -0
- package/dist/clis/tiktok/following.yaml +46 -0
- package/dist/clis/tiktok/friends.yaml +47 -0
- package/dist/clis/tiktok/like.yaml +38 -0
- package/dist/clis/tiktok/live.yaml +51 -0
- package/dist/clis/tiktok/notifications.yaml +52 -0
- package/dist/clis/tiktok/profile.yaml +45 -0
- package/dist/clis/tiktok/save.yaml +34 -0
- package/dist/clis/tiktok/search.yaml +46 -0
- package/dist/clis/tiktok/unfollow.yaml +44 -0
- package/dist/clis/tiktok/unlike.yaml +38 -0
- package/dist/clis/tiktok/unsave.yaml +36 -0
- package/dist/clis/tiktok/user.yaml +44 -0
- package/dist/clis/twitter/accept.js +2 -2
- package/dist/clis/twitter/article.js +2 -2
- package/dist/clis/twitter/block.d.ts +1 -0
- package/dist/clis/twitter/block.js +88 -0
- package/dist/clis/twitter/delete.js +1 -1
- package/dist/clis/twitter/download.d.ts +1 -1
- package/dist/clis/twitter/download.js +3 -3
- package/dist/clis/twitter/followers.js +1 -1
- package/dist/clis/twitter/following.js +1 -1
- package/dist/clis/twitter/hide-reply.d.ts +1 -0
- package/dist/clis/twitter/hide-reply.js +66 -0
- package/dist/clis/twitter/like.js +1 -1
- package/dist/clis/twitter/post.js +1 -1
- package/dist/clis/twitter/reply-dm.js +1 -1
- package/dist/clis/twitter/reply.js +2 -2
- package/dist/clis/twitter/search.js +1 -1
- package/dist/clis/twitter/thread.js +2 -2
- package/dist/clis/twitter/timeline.d.ts +23 -0
- package/dist/clis/twitter/timeline.js +42 -14
- package/dist/clis/twitter/timeline.test.d.ts +1 -0
- package/dist/clis/twitter/timeline.test.js +102 -0
- package/dist/clis/twitter/trending.d.ts +1 -0
- package/dist/clis/twitter/trending.js +91 -0
- package/dist/clis/twitter/unblock.d.ts +1 -0
- package/dist/clis/twitter/unblock.js +71 -0
- package/dist/clis/v2ex/topic.yaml +1 -0
- package/dist/clis/weibo/hot.js +0 -1
- package/dist/clis/weread/book.js +1 -1
- package/dist/clis/weread/highlights.js +1 -1
- package/dist/clis/weread/notes.js +1 -1
- package/dist/clis/weread/search.js +1 -1
- package/dist/clis/wikipedia/random.d.ts +1 -0
- package/dist/clis/wikipedia/random.js +19 -0
- package/dist/clis/wikipedia/search.js +4 -4
- package/dist/clis/wikipedia/summary.js +4 -9
- package/dist/clis/wikipedia/trending.d.ts +1 -0
- package/dist/clis/wikipedia/trending.js +35 -0
- package/dist/clis/wikipedia/utils.d.ts +28 -0
- package/dist/clis/wikipedia/utils.js +13 -0
- package/dist/clis/xiaohongshu/creator-note-detail.d.ts +15 -0
- package/dist/clis/xiaohongshu/creator-note-detail.js +69 -5
- package/dist/clis/xiaohongshu/creator-note-detail.test.js +82 -33
- package/dist/clis/xiaohongshu/creator-notes.js +35 -5
- package/dist/clis/xiaohongshu/creator-notes.test.js +37 -6
- package/dist/clis/xiaohongshu/creator-profile.js +0 -1
- package/dist/clis/xiaohongshu/creator-stats.js +0 -1
- package/dist/clis/xiaohongshu/download.js +2 -3
- package/dist/clis/xiaohongshu/feed.yaml +0 -1
- package/dist/clis/xiaohongshu/notifications.yaml +0 -1
- package/dist/clis/xiaohongshu/search.js +2 -2
- package/dist/clis/xiaohongshu/user.js +1 -2
- package/dist/clis/xueqiu/earnings-date.yaml +69 -0
- package/dist/clis/xueqiu/search.yaml +2 -1
- package/dist/clis/xueqiu/stock.yaml +2 -0
- package/dist/clis/yahoo-finance/quote.js +1 -2
- package/dist/clis/youtube/search.js +1 -1
- package/dist/clis/youtube/transcript.js +1 -1
- package/dist/clis/youtube/video.js +1 -1
- package/dist/clis/zhihu/download.js +1 -2
- package/dist/clis/zhihu/question.js +1 -1
- package/dist/clis/zhihu/search.yaml +4 -3
- package/dist/commanderAdapter.d.ts +21 -0
- package/dist/commanderAdapter.js +117 -0
- package/dist/{engine.d.ts → discovery.d.ts} +6 -4
- package/dist/{engine.js → discovery.js} +93 -104
- package/dist/doctor.js +3 -1
- package/dist/doctor.test.js +46 -2
- package/dist/download/index.d.ts +2 -6
- package/dist/download/index.js +19 -46
- package/dist/engine.test.d.ts +0 -3
- package/dist/engine.test.js +80 -11
- package/dist/execution.d.ts +24 -0
- package/dist/execution.js +153 -0
- package/dist/explore.d.ts +76 -3
- package/dist/explore.js +132 -111
- package/dist/external-clis.yaml +48 -0
- package/dist/external.d.ts +7 -2
- package/dist/external.js +11 -14
- package/dist/generate.d.ts +41 -2
- package/dist/generate.js +5 -4
- package/dist/main.js +2 -1
- package/dist/pipeline/executor.d.ts +2 -2
- package/dist/pipeline/executor.js +2 -2
- package/dist/pipeline/executor.test.js +33 -6
- package/dist/pipeline/registry.d.ts +1 -1
- package/dist/pipeline/steps/browser.d.ts +7 -7
- package/dist/pipeline/steps/browser.js +21 -7
- package/dist/pipeline/steps/fetch.d.ts +1 -1
- package/dist/pipeline/steps/fetch.js +11 -7
- package/dist/pipeline/steps/transform.d.ts +6 -5
- package/dist/pipeline/steps/transform.js +30 -9
- package/dist/pipeline/template.d.ts +6 -6
- package/dist/pipeline/template.js +43 -5
- package/dist/pipeline/template.test.js +18 -0
- package/dist/pipeline/transform.test.js +11 -0
- package/dist/plugin.d.ts +31 -0
- package/dist/plugin.js +216 -0
- package/dist/plugin.test.d.ts +4 -0
- package/dist/plugin.test.js +76 -0
- package/dist/registry-api.d.ts +11 -0
- package/dist/registry-api.js +9 -0
- package/dist/registry.d.ts +13 -0
- package/dist/registry.js +8 -1
- package/dist/runtime.d.ts +5 -0
- package/dist/runtime.js +8 -0
- package/dist/serialization.d.ts +34 -0
- package/dist/serialization.js +63 -0
- package/dist/synthesize.d.ts +94 -4
- package/dist/synthesize.js +5 -4
- package/dist/types.d.ts +43 -27
- package/dist/validate.js +8 -2
- package/docs/.vitepress/config.mts +20 -7
- package/docs/adapters/browser/arxiv.md +27 -0
- package/docs/adapters/browser/barchart.md +33 -0
- package/docs/adapters/browser/bilibili.md +9 -0
- package/docs/adapters/browser/bloomberg.md +70 -0
- package/docs/adapters/browser/chaoxing.md +39 -0
- package/docs/adapters/browser/devto.md +35 -0
- package/docs/adapters/browser/douban.md +38 -0
- package/docs/adapters/browser/facebook.md +36 -0
- package/docs/adapters/browser/google.md +62 -0
- package/docs/adapters/browser/grok.md +53 -0
- package/docs/adapters/browser/hf.md +42 -0
- package/docs/adapters/browser/instagram.md +46 -0
- package/docs/adapters/browser/jike.md +45 -0
- package/docs/adapters/browser/jimeng.md +39 -0
- package/docs/adapters/browser/linux-do.md +45 -0
- package/docs/adapters/browser/lobsters.md +32 -0
- package/docs/adapters/browser/medium.md +32 -0
- package/docs/adapters/browser/reddit.md +9 -0
- package/docs/adapters/browser/sinablog.md +36 -0
- package/docs/adapters/browser/sinafinance.md +35 -0
- package/docs/adapters/browser/stackoverflow.md +35 -0
- package/docs/adapters/browser/steam.md +26 -0
- package/docs/adapters/browser/substack.md +38 -0
- package/docs/adapters/browser/tiktok.md +68 -0
- package/docs/adapters/browser/twitter.md +3 -0
- package/docs/adapters/browser/weread.md +48 -0
- package/docs/adapters/browser/wikipedia.md +39 -0
- package/docs/adapters/browser/xiaohongshu.md +5 -1
- package/docs/adapters/browser/xueqiu.md +10 -0
- package/docs/adapters/browser/yahoo-finance.md +6 -5
- package/docs/adapters/desktop/antigravity.md +6 -0
- package/docs/adapters/desktop/chatgpt.md +5 -4
- package/docs/adapters/desktop/codex.md +5 -1
- package/docs/adapters/desktop/cursor.md +4 -0
- package/docs/adapters/desktop/discord.md +7 -7
- package/docs/adapters/index.md +14 -4
- package/docs/advanced/download.md +4 -4
- package/docs/developer/architecture.md +17 -4
- package/docs/guide/getting-started.md +1 -0
- package/docs/guide/plugins.md +153 -0
- package/docs/zh/guide/plugins.md +107 -0
- package/extension/src/background.ts +18 -11
- package/package.json +10 -5
- package/scripts/check-doc-coverage.sh +69 -0
- package/scripts/clean-dist.cjs +13 -0
- package/scripts/copy-yaml.cjs +7 -0
- package/src/browser/cdp.ts +77 -32
- package/src/browser/daemon-client.ts +2 -1
- package/src/browser/dom-helpers.ts +38 -7
- package/src/browser/dom-snapshot.test.ts +249 -0
- package/src/browser/dom-snapshot.ts +770 -0
- package/src/browser/index.ts +2 -0
- package/src/browser/page.ts +57 -20
- package/src/build-manifest.test.ts +70 -2
- package/src/build-manifest.ts +114 -40
- package/src/cli.ts +287 -139
- package/src/clis/apple-podcasts/commands.test.ts +95 -0
- package/src/clis/apple-podcasts/search.ts +2 -2
- package/src/clis/apple-podcasts/top.ts +12 -2
- package/src/clis/arxiv/search.ts +1 -1
- package/src/clis/barchart/greeks.ts +1 -1
- package/src/clis/barchart/options.ts +1 -1
- package/src/clis/barchart/quote.ts +1 -1
- package/src/clis/bilibili/download.ts +1 -1
- package/src/clis/bilibili/dynamic.ts +1 -1
- package/src/clis/bilibili/favorite.ts +1 -1
- package/src/clis/bilibili/feed.ts +1 -1
- package/src/clis/bilibili/following.ts +2 -2
- package/src/clis/bilibili/history.ts +1 -1
- package/src/clis/bilibili/me.ts +1 -1
- package/src/clis/bilibili/ranking.ts +1 -1
- package/src/clis/bilibili/search.ts +3 -3
- package/src/clis/bilibili/subtitle.ts +2 -2
- package/src/clis/bilibili/user-videos.ts +2 -2
- package/src/{bilibili.ts → clis/bilibili/utils.ts} +1 -1
- package/src/clis/bloomberg/businessweek.ts +18 -0
- package/src/clis/bloomberg/economics.ts +18 -0
- package/src/clis/bloomberg/feeds.ts +16 -0
- package/src/clis/bloomberg/industries.ts +18 -0
- package/src/clis/bloomberg/main.ts +18 -0
- package/src/clis/bloomberg/markets.ts +18 -0
- package/src/clis/bloomberg/news.ts +136 -0
- package/src/clis/bloomberg/opinions.ts +18 -0
- package/src/clis/bloomberg/politics.ts +18 -0
- package/src/clis/bloomberg/tech.ts +18 -0
- package/src/clis/bloomberg/utils.test.ts +135 -0
- package/src/clis/bloomberg/utils.ts +429 -0
- package/src/clis/boss/batchgreet.ts +16 -108
- package/src/clis/boss/chatlist.ts +13 -27
- package/src/clis/boss/chatmsg.ts +16 -40
- package/src/clis/boss/common.ts +287 -0
- package/src/clis/boss/detail.ts +9 -55
- package/src/clis/boss/exchange.ts +15 -89
- package/src/clis/boss/greet.ts +25 -162
- package/src/clis/boss/invite.ts +36 -133
- package/src/clis/boss/joblist.ts +7 -36
- package/src/clis/boss/mark.ts +13 -94
- package/src/clis/boss/recommend.ts +12 -57
- package/src/clis/boss/resume.ts +19 -124
- package/src/clis/boss/search.ts +14 -67
- package/src/clis/boss/send.ts +22 -162
- package/src/clis/boss/stats.ts +21 -76
- package/src/clis/chaoxing/assignments.ts +1 -1
- package/src/clis/chaoxing/exams.ts +1 -1
- package/src/{chaoxing.test.ts → clis/chaoxing/utils.test.ts} +1 -1
- package/src/{chaoxing.ts → clis/chaoxing/utils.ts} +1 -3
- package/src/clis/chatgpt/read.ts +1 -1
- package/src/clis/chatwise/export.ts +1 -1
- package/src/clis/chatwise/model.ts +2 -2
- package/src/clis/chatwise/screenshot.ts +1 -1
- package/src/clis/codex/export.ts +1 -1
- package/src/clis/codex/model.ts +2 -2
- package/src/clis/codex/screenshot.ts +1 -1
- package/src/clis/coupang/add-to-cart.ts +3 -4
- package/src/clis/coupang/search.ts +2 -4
- package/src/{coupang.test.ts → clis/coupang/utils.test.ts} +1 -1
- package/src/clis/ctrip/search.ts +1 -1
- package/src/clis/cursor/export.ts +1 -1
- package/src/clis/cursor/model.ts +2 -2
- package/src/clis/cursor/screenshot.ts +1 -1
- package/src/clis/devto/tag.yaml +34 -0
- package/src/clis/devto/top.yaml +29 -0
- package/src/clis/devto/user.yaml +33 -0
- package/src/clis/douban/book-hot.ts +15 -0
- package/src/clis/douban/marks.ts +135 -0
- package/src/clis/douban/movie-hot.ts +15 -0
- package/src/clis/douban/reviews.ts +127 -0
- package/src/clis/douban/search.ts +17 -0
- package/src/clis/douban/shared.ts +165 -0
- package/src/clis/douban/subject.yaml +76 -0
- package/src/clis/douban/top250.yaml +70 -0
- package/src/clis/douban/utils.ts +81 -0
- package/src/clis/facebook/add-friend.yaml +43 -0
- package/src/clis/facebook/events.yaml +44 -0
- package/src/clis/facebook/feed.yaml +63 -0
- package/src/clis/facebook/friends.yaml +42 -0
- package/src/clis/facebook/groups.yaml +50 -0
- package/src/clis/facebook/join-group.yaml +44 -0
- package/src/clis/facebook/memories.yaml +39 -0
- package/src/clis/facebook/notifications.yaml +40 -0
- package/src/clis/facebook/profile.yaml +37 -0
- package/src/clis/facebook/search.yaml +46 -0
- package/src/clis/google/news.ts +66 -0
- package/src/clis/google/search.ts +133 -0
- package/src/clis/google/suggest.ts +40 -0
- package/src/clis/google/trends.ts +44 -0
- package/src/clis/google/utils.test.ts +82 -0
- package/src/clis/google/utils.ts +24 -0
- package/src/clis/grok/ask.test.ts +53 -0
- package/src/clis/grok/ask.ts +300 -69
- package/src/clis/instagram/comment.yaml +52 -0
- package/src/clis/instagram/explore.yaml +43 -0
- package/src/clis/instagram/follow.yaml +41 -0
- package/src/clis/instagram/followers.yaml +51 -0
- package/src/clis/instagram/following.yaml +51 -0
- package/src/clis/instagram/like.yaml +46 -0
- package/src/clis/instagram/profile.yaml +42 -0
- package/src/clis/instagram/save.yaml +46 -0
- package/src/clis/instagram/saved.yaml +40 -0
- package/src/clis/instagram/search.yaml +43 -0
- package/src/clis/instagram/unfollow.yaml +38 -0
- package/src/clis/instagram/unlike.yaml +46 -0
- package/src/clis/instagram/unsave.yaml +46 -0
- package/src/clis/instagram/user.yaml +54 -0
- package/src/clis/jike/comment.ts +2 -3
- package/src/clis/jike/create.ts +1 -2
- package/src/clis/jike/feed.ts +0 -1
- package/src/clis/jike/like.ts +1 -2
- package/src/clis/jike/notifications.ts +0 -1
- package/src/clis/jike/post.yaml +1 -0
- package/src/clis/jike/repost.ts +2 -3
- package/src/clis/jike/search.ts +2 -3
- package/src/clis/jike/topic.yaml +1 -0
- package/src/clis/jike/user.yaml +1 -0
- package/src/clis/jimeng/generate.yaml +1 -0
- package/src/clis/jimeng/history.yaml +0 -1
- package/src/clis/linkedin/search.ts +7 -7
- package/src/clis/linux-do/category.yaml +2 -0
- package/src/clis/linux-do/search.yaml +4 -3
- package/src/clis/linux-do/topic.yaml +1 -0
- package/src/clis/lobsters/active.yaml +29 -0
- package/src/clis/lobsters/hot.yaml +29 -0
- package/src/clis/lobsters/newest.yaml +29 -0
- package/src/clis/lobsters/tag.yaml +34 -0
- package/src/clis/medium/feed.ts +16 -0
- package/src/clis/medium/search.ts +16 -0
- package/src/clis/medium/shared.ts +83 -0
- package/src/clis/medium/user.ts +16 -0
- package/src/clis/notion/export.ts +1 -1
- package/src/clis/reddit/comment.ts +3 -4
- package/src/clis/reddit/read.ts +4 -5
- package/src/clis/reddit/save.ts +2 -3
- package/src/clis/reddit/saved.ts +0 -1
- package/src/clis/reddit/search.yaml +1 -0
- package/src/clis/reddit/subreddit.yaml +1 -0
- package/src/clis/reddit/subscribe.ts +1 -2
- package/src/clis/reddit/upvote.ts +2 -3
- package/src/clis/reddit/upvoted.ts +0 -1
- package/src/clis/reddit/user-comments.yaml +1 -0
- package/src/clis/reddit/user-posts.yaml +1 -0
- package/src/clis/reddit/user.yaml +1 -0
- package/src/clis/reuters/search.ts +1 -1
- package/src/clis/sinablog/article.ts +15 -0
- package/src/clis/sinablog/hot.ts +15 -0
- package/src/clis/sinablog/search.ts +56 -0
- package/src/clis/sinablog/shared.ts +198 -0
- package/src/clis/sinablog/user.ts +16 -0
- package/src/clis/smzdm/search.ts +2 -3
- package/src/clis/stackoverflow/search.yaml +1 -0
- package/src/clis/steam/top-sellers.yaml +29 -0
- package/src/clis/substack/feed.ts +16 -0
- package/src/clis/substack/publication.ts +16 -0
- package/src/clis/substack/search.ts +91 -0
- package/src/clis/substack/shared.ts +132 -0
- package/src/clis/tiktok/comment.yaml +66 -0
- package/src/clis/tiktok/explore.yaml +39 -0
- package/src/clis/tiktok/follow.yaml +39 -0
- package/src/clis/tiktok/following.yaml +46 -0
- package/src/clis/tiktok/friends.yaml +47 -0
- package/src/clis/tiktok/like.yaml +38 -0
- package/src/clis/tiktok/live.yaml +51 -0
- package/src/clis/tiktok/notifications.yaml +52 -0
- package/src/clis/tiktok/profile.yaml +45 -0
- package/src/clis/tiktok/save.yaml +34 -0
- package/src/clis/tiktok/search.yaml +46 -0
- package/src/clis/tiktok/unfollow.yaml +44 -0
- package/src/clis/tiktok/unlike.yaml +38 -0
- package/src/clis/tiktok/unsave.yaml +36 -0
- package/src/clis/tiktok/user.yaml +44 -0
- package/src/clis/twitter/accept.ts +2 -2
- package/src/clis/twitter/article.ts +2 -2
- package/src/clis/twitter/block.ts +92 -0
- package/src/clis/twitter/delete.ts +1 -1
- package/src/clis/twitter/download.ts +3 -3
- package/src/clis/twitter/followers.ts +1 -1
- package/src/clis/twitter/following.ts +1 -1
- package/src/clis/twitter/hide-reply.ts +70 -0
- package/src/clis/twitter/like.ts +1 -1
- package/src/clis/twitter/post.ts +1 -1
- package/src/clis/twitter/reply-dm.ts +1 -1
- package/src/clis/twitter/reply.ts +2 -2
- package/src/clis/twitter/search.ts +1 -1
- package/src/clis/twitter/thread.ts +2 -2
- package/src/clis/twitter/timeline.test.ts +109 -0
- package/src/clis/twitter/timeline.ts +59 -19
- package/src/clis/twitter/trending.ts +113 -0
- package/src/clis/twitter/unblock.ts +75 -0
- package/src/clis/v2ex/topic.yaml +1 -0
- package/src/clis/weibo/hot.ts +0 -1
- package/src/clis/weread/book.ts +1 -1
- package/src/clis/weread/highlights.ts +1 -1
- package/src/clis/weread/notes.ts +1 -1
- package/src/clis/weread/search.ts +1 -1
- package/src/clis/wikipedia/random.ts +19 -0
- package/src/clis/wikipedia/search.ts +11 -5
- package/src/clis/wikipedia/summary.ts +4 -9
- package/src/clis/wikipedia/trending.ts +41 -0
- package/src/clis/wikipedia/utils.ts +31 -0
- package/src/clis/xiaohongshu/creator-note-detail.test.ts +84 -33
- package/src/clis/xiaohongshu/creator-note-detail.ts +89 -5
- package/src/clis/xiaohongshu/creator-notes.test.ts +41 -6
- package/src/clis/xiaohongshu/creator-notes.ts +44 -5
- package/src/clis/xiaohongshu/creator-profile.ts +0 -1
- package/src/clis/xiaohongshu/creator-stats.ts +0 -1
- package/src/clis/xiaohongshu/download.ts +2 -3
- package/src/clis/xiaohongshu/feed.yaml +0 -1
- package/src/clis/xiaohongshu/notifications.yaml +0 -1
- package/src/clis/xiaohongshu/search.ts +2 -2
- package/src/clis/xiaohongshu/user.ts +1 -2
- package/src/clis/xueqiu/earnings-date.yaml +69 -0
- package/src/clis/xueqiu/search.yaml +2 -1
- package/src/clis/xueqiu/stock.yaml +2 -0
- package/src/clis/yahoo-finance/quote.ts +1 -2
- package/src/clis/youtube/search.ts +1 -1
- package/src/clis/youtube/transcript.ts +1 -1
- package/src/clis/youtube/video.ts +1 -1
- package/src/clis/zhihu/download.ts +1 -2
- package/src/clis/zhihu/question.ts +1 -1
- package/src/clis/zhihu/search.yaml +4 -3
- package/src/commanderAdapter.ts +120 -0
- package/src/discovery.ts +277 -0
- package/src/doctor.test.ts +59 -2
- package/src/doctor.ts +4 -2
- package/src/download/index.ts +21 -54
- package/src/engine.test.ts +85 -11
- package/src/execution.ts +164 -0
- package/src/explore.ts +211 -117
- package/src/external-clis.yaml +9 -0
- package/src/external.ts +15 -12
- package/src/generate.ts +58 -9
- package/src/main.ts +2 -1
- package/src/pipeline/executor.test.ts +35 -6
- package/src/pipeline/executor.ts +11 -7
- package/src/pipeline/registry.ts +3 -3
- package/src/pipeline/steps/browser.ts +29 -15
- package/src/pipeline/steps/fetch.ts +18 -13
- package/src/pipeline/steps/transform.ts +40 -15
- package/src/pipeline/template.test.ts +18 -0
- package/src/pipeline/template.ts +86 -13
- package/src/pipeline/transform.test.ts +15 -2
- package/src/plugin.test.ts +86 -0
- package/src/plugin.ts +254 -0
- package/src/registry-api.ts +12 -0
- package/src/registry.ts +24 -1
- package/src/runtime.ts +9 -0
- package/src/serialization.ts +79 -0
- package/src/synthesize.ts +102 -21
- package/src/types.ts +45 -13
- package/src/validate.ts +19 -4
- package/tests/e2e/browser-public.test.ts +36 -0
- package/tests/e2e/public-commands.test.ts +119 -1
- package/dist/clis/feishu/new.d.ts +0 -1
- package/dist/clis/feishu/new.js +0 -27
- package/dist/clis/feishu/read.d.ts +0 -1
- package/dist/clis/feishu/read.js +0 -40
- package/dist/clis/feishu/search.d.ts +0 -1
- package/dist/clis/feishu/search.js +0 -30
- package/dist/clis/feishu/send.d.ts +0 -1
- package/dist/clis/feishu/send.js +0 -39
- package/dist/clis/feishu/status.d.ts +0 -1
- package/dist/clis/feishu/status.js +0 -28
- package/dist/clis/neteasemusic/like.d.ts +0 -1
- package/dist/clis/neteasemusic/like.js +0 -25
- package/dist/clis/neteasemusic/lyrics.d.ts +0 -1
- package/dist/clis/neteasemusic/lyrics.js +0 -47
- package/dist/clis/neteasemusic/next.d.ts +0 -1
- package/dist/clis/neteasemusic/next.js +0 -26
- package/dist/clis/neteasemusic/play.d.ts +0 -1
- package/dist/clis/neteasemusic/play.js +0 -26
- package/dist/clis/neteasemusic/playing.d.ts +0 -1
- package/dist/clis/neteasemusic/playing.js +0 -59
- package/dist/clis/neteasemusic/playlist.d.ts +0 -1
- package/dist/clis/neteasemusic/playlist.js +0 -46
- package/dist/clis/neteasemusic/prev.d.ts +0 -1
- package/dist/clis/neteasemusic/prev.js +0 -25
- package/dist/clis/neteasemusic/search.d.ts +0 -1
- package/dist/clis/neteasemusic/search.js +0 -52
- package/dist/clis/neteasemusic/status.d.ts +0 -1
- package/dist/clis/neteasemusic/status.js +0 -16
- package/dist/clis/neteasemusic/volume.d.ts +0 -1
- package/dist/clis/neteasemusic/volume.js +0 -54
- package/dist/clis/twitter/trending.yaml +0 -46
- package/dist/clis/wechat/chats.d.ts +0 -1
- package/dist/clis/wechat/chats.js +0 -28
- package/dist/clis/wechat/contacts.d.ts +0 -1
- package/dist/clis/wechat/contacts.js +0 -28
- package/dist/clis/wechat/read.d.ts +0 -1
- package/dist/clis/wechat/read.js +0 -58
- package/dist/clis/wechat/search.d.ts +0 -1
- package/dist/clis/wechat/search.js +0 -31
- package/dist/clis/wechat/send.d.ts +0 -1
- package/dist/clis/wechat/send.js +0 -42
- package/dist/clis/wechat/status.d.ts +0 -1
- package/dist/clis/wechat/status.js +0 -29
- package/dist/pipeline.d.ts +0 -7
- package/dist/pipeline.js +0 -7
- package/docs/adapters/browser/github.md +0 -26
- package/docs/adapters/desktop/feishu.md +0 -20
- package/docs/adapters/desktop/neteasemusic.md +0 -31
- package/docs/adapters/desktop/wechat.md +0 -28
- package/docs/public/CNAME +0 -1
- package/src/clis/antigravity/README.md +0 -5
- package/src/clis/antigravity/README.zh-CN.md +0 -51
- package/src/clis/chaoxing/README.md +0 -14
- package/src/clis/chaoxing/README.zh-CN.md +0 -35
- package/src/clis/chatgpt/README.md +0 -5
- package/src/clis/chatgpt/README.zh-CN.md +0 -44
- package/src/clis/chatwise/README.md +0 -5
- package/src/clis/chatwise/README.zh-CN.md +0 -38
- package/src/clis/codex/README.md +0 -5
- package/src/clis/codex/README.zh-CN.md +0 -33
- package/src/clis/cursor/README.md +0 -5
- package/src/clis/cursor/README.zh-CN.md +0 -33
- package/src/clis/discord-app/README.md +0 -5
- package/src/clis/discord-app/README.zh-CN.md +0 -28
- package/src/clis/feishu/README.md +0 -5
- package/src/clis/feishu/README.zh-CN.md +0 -20
- package/src/clis/feishu/new.ts +0 -32
- package/src/clis/feishu/read.ts +0 -48
- package/src/clis/feishu/search.ts +0 -35
- package/src/clis/feishu/send.ts +0 -46
- package/src/clis/feishu/status.ts +0 -34
- package/src/clis/neteasemusic/README.md +0 -5
- package/src/clis/neteasemusic/README.zh-CN.md +0 -31
- package/src/clis/neteasemusic/like.ts +0 -28
- package/src/clis/neteasemusic/lyrics.ts +0 -53
- package/src/clis/neteasemusic/next.ts +0 -30
- package/src/clis/neteasemusic/play.ts +0 -30
- package/src/clis/neteasemusic/playing.ts +0 -62
- package/src/clis/neteasemusic/playlist.ts +0 -51
- package/src/clis/neteasemusic/prev.ts +0 -29
- package/src/clis/neteasemusic/search.ts +0 -58
- package/src/clis/neteasemusic/status.ts +0 -18
- package/src/clis/neteasemusic/volume.ts +0 -61
- package/src/clis/notion/README.md +0 -5
- package/src/clis/notion/README.zh-CN.md +0 -29
- package/src/clis/twitter/trending.yaml +0 -46
- package/src/clis/wechat/README.md +0 -5
- package/src/clis/wechat/README.zh-CN.md +0 -28
- package/src/clis/wechat/chats.ts +0 -33
- package/src/clis/wechat/contacts.ts +0 -33
- package/src/clis/wechat/read.ts +0 -72
- package/src/clis/wechat/search.ts +0 -36
- package/src/clis/wechat/send.ts +0 -49
- package/src/clis/wechat/status.ts +0 -35
- package/src/engine.ts +0 -274
- package/src/pipeline.ts +0 -8
- /package/dist/{bilibili.js → clis/bilibili/utils.js} +0 -0
- /package/dist/{chaoxing.test.d.ts → clis/bloomberg/businessweek.d.ts} +0 -0
- /package/dist/{coupang.test.d.ts → clis/bloomberg/economics.d.ts} +0 -0
- /package/dist/{coupang.d.ts → clis/coupang/utils.d.ts} +0 -0
- /package/dist/{coupang.js → clis/coupang/utils.js} +0 -0
- /package/src/{coupang.ts → clis/coupang/utils.ts} +0 -0
package/src/doctor.test.ts
CHANGED
|
@@ -1,9 +1,36 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
const { mockCheckDaemonStatus, mockListSessions, mockConnect, mockClose } = vi.hoisted(() => ({
|
|
4
|
+
mockCheckDaemonStatus: vi.fn(),
|
|
5
|
+
mockListSessions: vi.fn(),
|
|
6
|
+
mockConnect: vi.fn(),
|
|
7
|
+
mockClose: vi.fn(),
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
vi.mock('./browser/discover.js', () => ({
|
|
11
|
+
checkDaemonStatus: mockCheckDaemonStatus,
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
vi.mock('./browser/daemon-client.js', () => ({
|
|
15
|
+
listSessions: mockListSessions,
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
vi.mock('./browser/index.js', () => ({
|
|
19
|
+
BrowserBridge: class {
|
|
20
|
+
connect = mockConnect;
|
|
21
|
+
close = mockClose;
|
|
22
|
+
},
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
import { renderBrowserDoctorReport, runBrowserDoctor } from './doctor.js';
|
|
3
26
|
|
|
4
27
|
describe('doctor report rendering', () => {
|
|
5
28
|
const strip = (s: string) => s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
6
29
|
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
vi.clearAllMocks();
|
|
32
|
+
});
|
|
33
|
+
|
|
7
34
|
it('renders OK-style report when daemon and extension connected', () => {
|
|
8
35
|
const text = strip(renderBrowserDoctorReport({
|
|
9
36
|
daemonRunning: true,
|
|
@@ -59,4 +86,34 @@ describe('doctor report rendering', () => {
|
|
|
59
86
|
|
|
60
87
|
expect(text).toContain('[SKIP] Connectivity: not tested (use --live)');
|
|
61
88
|
});
|
|
89
|
+
|
|
90
|
+
it('reports consistent status when live check auto-starts the daemon', async () => {
|
|
91
|
+
// With the reordered flow, checkDaemonStatus is called only ONCE — after
|
|
92
|
+
// the connectivity check that may auto-start the daemon.
|
|
93
|
+
mockCheckDaemonStatus.mockResolvedValueOnce({ running: true, extensionConnected: false });
|
|
94
|
+
mockConnect.mockRejectedValueOnce(new Error(
|
|
95
|
+
'Daemon is running but the Browser Extension is not connected.\n' +
|
|
96
|
+
'Please install and enable the opencli Browser Bridge extension in Chrome.',
|
|
97
|
+
));
|
|
98
|
+
|
|
99
|
+
const report = await runBrowserDoctor({ live: true });
|
|
100
|
+
|
|
101
|
+
// Status reflects the post-connectivity state (daemon running)
|
|
102
|
+
expect(report.daemonRunning).toBe(true);
|
|
103
|
+
expect(report.extensionConnected).toBe(false);
|
|
104
|
+
// checkDaemonStatus should only be called once
|
|
105
|
+
expect(mockCheckDaemonStatus).toHaveBeenCalledTimes(1);
|
|
106
|
+
// Should NOT report "daemon not running" since it IS running after live check
|
|
107
|
+
expect(report.issues).not.toContain(
|
|
108
|
+
expect.stringContaining('Daemon is not running'),
|
|
109
|
+
);
|
|
110
|
+
// Should report extension not connected
|
|
111
|
+
expect(report.issues).toEqual(expect.arrayContaining([
|
|
112
|
+
expect.stringContaining('Chrome extension is not connected'),
|
|
113
|
+
]));
|
|
114
|
+
// Should report connectivity failure
|
|
115
|
+
expect(report.issues).toEqual(expect.arrayContaining([
|
|
116
|
+
expect.stringContaining('Browser connectivity test failed'),
|
|
117
|
+
]));
|
|
118
|
+
});
|
|
62
119
|
});
|
package/src/doctor.ts
CHANGED
|
@@ -51,12 +51,14 @@ export async function checkConnectivity(opts?: { timeout?: number }): Promise<Co
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export async function runBrowserDoctor(opts: DoctorOptions = {}): Promise<DoctorReport> {
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
// Run the live connectivity check first — it may auto-start the daemon as a
|
|
55
|
+
// side-effect, so we read daemon status only *after* all side-effects settle.
|
|
56
56
|
let connectivity: ConnectivityResult | undefined;
|
|
57
57
|
if (opts.live) {
|
|
58
58
|
connectivity = await checkConnectivity();
|
|
59
59
|
}
|
|
60
|
+
|
|
61
|
+
const status = await checkDaemonStatus();
|
|
60
62
|
const sessions = opts.sessions && status.running && status.extensionConnected
|
|
61
63
|
? await listSessions() as Array<{ workspace: string; windowId: number; tabCount: number; idleMsRemaining: number }>
|
|
62
64
|
: undefined;
|
package/src/download/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Download utilities: HTTP downloads, yt-dlp wrapper, format conversion.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { spawn
|
|
5
|
+
import { spawn } from 'node:child_process';
|
|
6
6
|
import * as fs from 'node:fs';
|
|
7
7
|
import * as path from 'node:path';
|
|
8
8
|
import * as https from 'node:https';
|
|
@@ -10,6 +10,7 @@ import * as http from 'node:http';
|
|
|
10
10
|
import * as os from 'node:os';
|
|
11
11
|
import { URL } from 'node:url';
|
|
12
12
|
import type { ProgressBar } from './progress.js';
|
|
13
|
+
import { isBinaryInstalled } from '../external.js';
|
|
13
14
|
|
|
14
15
|
export interface DownloadOptions {
|
|
15
16
|
cookies?: string;
|
|
@@ -36,68 +37,43 @@ export interface BrowserCookie {
|
|
|
36
37
|
expirationDate?: number;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
/**
|
|
40
|
-
* Check if yt-dlp is available in PATH.
|
|
41
|
-
*/
|
|
40
|
+
/** Check if yt-dlp is available in PATH. */
|
|
42
41
|
export function checkYtdlp(): boolean {
|
|
43
|
-
|
|
44
|
-
execSync('yt-dlp --version', { encoding: 'utf-8', stdio: 'pipe' });
|
|
45
|
-
return true;
|
|
46
|
-
} catch {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
42
|
+
return isBinaryInstalled('yt-dlp');
|
|
49
43
|
}
|
|
50
44
|
|
|
51
|
-
/**
|
|
52
|
-
* Check if ffmpeg is available in PATH.
|
|
53
|
-
*/
|
|
45
|
+
/** Check if ffmpeg is available in PATH. */
|
|
54
46
|
export function checkFfmpeg(): boolean {
|
|
55
|
-
|
|
56
|
-
execSync('ffmpeg -version', { encoding: 'utf-8', stdio: 'pipe' });
|
|
57
|
-
return true;
|
|
58
|
-
} catch {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
47
|
+
return isBinaryInstalled('ffmpeg');
|
|
61
48
|
}
|
|
62
49
|
|
|
50
|
+
/** Domains that host video content and can be downloaded via yt-dlp. */
|
|
51
|
+
const VIDEO_PLATFORM_DOMAINS = [
|
|
52
|
+
'youtube.com', 'youtu.be', 'bilibili.com', 'twitter.com',
|
|
53
|
+
'x.com', 'tiktok.com', 'vimeo.com', 'twitch.tv',
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
const IMAGE_EXTENSIONS = new Set(['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.ico', '.bmp', '.avif']);
|
|
57
|
+
const VIDEO_EXTENSIONS = new Set(['.mp4', '.webm', '.avi', '.mov', '.mkv', '.flv', '.m3u8', '.ts']);
|
|
58
|
+
const DOC_EXTENSIONS = new Set(['.html', '.htm', '.json', '.xml', '.txt', '.md', '.markdown']);
|
|
59
|
+
|
|
63
60
|
/**
|
|
64
61
|
* Detect content type from URL and optional headers.
|
|
65
62
|
*/
|
|
66
63
|
export function detectContentType(url: string, contentType?: string): 'image' | 'video' | 'document' | 'binary' {
|
|
67
|
-
// Check content-type header first
|
|
68
64
|
if (contentType) {
|
|
69
65
|
if (contentType.startsWith('image/')) return 'image';
|
|
70
66
|
if (contentType.startsWith('video/')) return 'video';
|
|
71
67
|
if (contentType.startsWith('text/') || contentType.includes('json') || contentType.includes('xml')) return 'document';
|
|
72
68
|
}
|
|
73
69
|
|
|
74
|
-
// Detect from URL
|
|
75
70
|
const urlLower = url.toLowerCase();
|
|
76
71
|
const ext = path.extname(new URL(url).pathname).toLowerCase();
|
|
77
72
|
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// Video extensions
|
|
84
|
-
if (['.mp4', '.webm', '.avi', '.mov', '.mkv', '.flv', '.m3u8', '.ts'].includes(ext)) {
|
|
85
|
-
return 'video';
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Video platforms (need yt-dlp)
|
|
89
|
-
if (urlLower.includes('youtube.com') || urlLower.includes('youtu.be') ||
|
|
90
|
-
urlLower.includes('bilibili.com') || urlLower.includes('twitter.com') ||
|
|
91
|
-
urlLower.includes('x.com') || urlLower.includes('tiktok.com') ||
|
|
92
|
-
urlLower.includes('vimeo.com') || urlLower.includes('twitch.tv')) {
|
|
93
|
-
return 'video';
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Document extensions
|
|
97
|
-
if (['.html', '.htm', '.json', '.xml', '.txt', '.md', '.markdown'].includes(ext)) {
|
|
98
|
-
return 'document';
|
|
99
|
-
}
|
|
100
|
-
|
|
73
|
+
if (IMAGE_EXTENSIONS.has(ext)) return 'image';
|
|
74
|
+
if (VIDEO_EXTENSIONS.has(ext)) return 'video';
|
|
75
|
+
if (VIDEO_PLATFORM_DOMAINS.some(d => urlLower.includes(d))) return 'video';
|
|
76
|
+
if (DOC_EXTENSIONS.has(ext)) return 'document';
|
|
101
77
|
return 'binary';
|
|
102
78
|
}
|
|
103
79
|
|
|
@@ -106,16 +82,7 @@ export function detectContentType(url: string, contentType?: string): 'image' |
|
|
|
106
82
|
*/
|
|
107
83
|
export function requiresYtdlp(url: string): boolean {
|
|
108
84
|
const urlLower = url.toLowerCase();
|
|
109
|
-
return (
|
|
110
|
-
urlLower.includes('youtube.com') ||
|
|
111
|
-
urlLower.includes('youtu.be') ||
|
|
112
|
-
urlLower.includes('bilibili.com/video') ||
|
|
113
|
-
urlLower.includes('twitter.com') ||
|
|
114
|
-
urlLower.includes('x.com') ||
|
|
115
|
-
urlLower.includes('tiktok.com') ||
|
|
116
|
-
urlLower.includes('vimeo.com') ||
|
|
117
|
-
urlLower.includes('twitch.tv')
|
|
118
|
-
);
|
|
85
|
+
return VIDEO_PLATFORM_DOMAINS.some(d => urlLower.includes(d));
|
|
119
86
|
}
|
|
120
87
|
|
|
121
88
|
/**
|
package/src/engine.test.ts
CHANGED
|
@@ -1,16 +1,90 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
6
|
-
import { discoverClis, executeCommand } from './engine.js';
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { discoverClis, discoverPlugins, PLUGINS_DIR } from './discovery.js';
|
|
3
|
+
import { executeCommand } from './execution.js';
|
|
7
4
|
import { getRegistry, cli, Strategy } from './registry.js';
|
|
5
|
+
import * as fs from 'node:fs';
|
|
6
|
+
import * as path from 'node:path';
|
|
8
7
|
|
|
9
8
|
describe('discoverClis', () => {
|
|
10
9
|
it('handles non-existent directories gracefully', async () => {
|
|
11
10
|
// Should not throw for missing directories
|
|
12
11
|
await expect(discoverClis('/tmp/nonexistent-opencli-test-dir')).resolves.not.toThrow();
|
|
13
12
|
});
|
|
13
|
+
|
|
14
|
+
it('imports only CLI command modules during filesystem discovery', async () => {
|
|
15
|
+
const tempRoot = await fs.promises.mkdtemp(path.join('/tmp', 'opencli-discovery-'));
|
|
16
|
+
const siteDir = path.join(tempRoot, 'temp-site');
|
|
17
|
+
const helperPath = path.join(siteDir, 'helper.ts');
|
|
18
|
+
const commandPath = path.join(siteDir, 'hello.ts');
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
await fs.promises.mkdir(siteDir, { recursive: true });
|
|
22
|
+
await fs.promises.writeFile(helperPath, `
|
|
23
|
+
globalThis.__opencli_helper_loaded__ = true;
|
|
24
|
+
export const helper = true;
|
|
25
|
+
`);
|
|
26
|
+
await fs.promises.writeFile(commandPath, `
|
|
27
|
+
import { cli, Strategy } from '${path.join(process.cwd(), 'src', 'registry.ts')}';
|
|
28
|
+
cli({
|
|
29
|
+
site: 'temp-site',
|
|
30
|
+
name: 'hello',
|
|
31
|
+
description: 'hello command',
|
|
32
|
+
strategy: Strategy.PUBLIC,
|
|
33
|
+
browser: false,
|
|
34
|
+
func: async () => [{ ok: true }],
|
|
35
|
+
});
|
|
36
|
+
`);
|
|
37
|
+
|
|
38
|
+
delete (globalThis as any).__opencli_helper_loaded__;
|
|
39
|
+
await discoverClis(tempRoot);
|
|
40
|
+
|
|
41
|
+
expect((globalThis as any).__opencli_helper_loaded__).toBeUndefined();
|
|
42
|
+
expect(getRegistry().get('temp-site/hello')).toBeDefined();
|
|
43
|
+
} finally {
|
|
44
|
+
delete (globalThis as any).__opencli_helper_loaded__;
|
|
45
|
+
await fs.promises.rm(tempRoot, { recursive: true, force: true });
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('discoverPlugins', () => {
|
|
51
|
+
const testPluginDir = path.join(PLUGINS_DIR, '__test-plugin__');
|
|
52
|
+
const yamlPath = path.join(testPluginDir, 'greeting.yaml');
|
|
53
|
+
|
|
54
|
+
afterEach(async () => {
|
|
55
|
+
try { await fs.promises.rm(testPluginDir, { recursive: true }); } catch {}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('discovers YAML plugins from ~/.opencli/plugins/', async () => {
|
|
59
|
+
// Create a simple YAML adapter in the plugins directory
|
|
60
|
+
await fs.promises.mkdir(testPluginDir, { recursive: true });
|
|
61
|
+
await fs.promises.writeFile(yamlPath, `
|
|
62
|
+
site: __test-plugin__
|
|
63
|
+
name: greeting
|
|
64
|
+
description: Test plugin greeting
|
|
65
|
+
strategy: public
|
|
66
|
+
browser: false
|
|
67
|
+
|
|
68
|
+
pipeline:
|
|
69
|
+
- evaluate: "() => [{ message: 'hello from plugin' }]"
|
|
70
|
+
|
|
71
|
+
columns: [message]
|
|
72
|
+
`);
|
|
73
|
+
|
|
74
|
+
await discoverPlugins();
|
|
75
|
+
|
|
76
|
+
const registry = getRegistry();
|
|
77
|
+
const cmd = registry.get('__test-plugin__/greeting');
|
|
78
|
+
expect(cmd).toBeDefined();
|
|
79
|
+
expect(cmd!.site).toBe('__test-plugin__');
|
|
80
|
+
expect(cmd!.name).toBe('greeting');
|
|
81
|
+
expect(cmd!.description).toBe('Test plugin greeting');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('handles non-existent plugins directory gracefully', async () => {
|
|
85
|
+
// discoverPlugins should not throw if ~/.opencli/plugins/ does not exist
|
|
86
|
+
await expect(discoverPlugins()).resolves.not.toThrow();
|
|
87
|
+
});
|
|
14
88
|
});
|
|
15
89
|
|
|
16
90
|
describe('executeCommand', () => {
|
|
@@ -27,7 +101,7 @@ describe('executeCommand', () => {
|
|
|
27
101
|
func: async (_page, kwargs) => [{ noteId: kwargs['note-id'] }],
|
|
28
102
|
});
|
|
29
103
|
|
|
30
|
-
const result = await executeCommand(cmd,
|
|
104
|
+
const result = await executeCommand(cmd, { 'note-id': 'abc123' });
|
|
31
105
|
expect(result).toEqual([{ noteId: 'abc123' }]);
|
|
32
106
|
});
|
|
33
107
|
|
|
@@ -43,7 +117,7 @@ describe('executeCommand', () => {
|
|
|
43
117
|
},
|
|
44
118
|
});
|
|
45
119
|
|
|
46
|
-
const result = await executeCommand(cmd,
|
|
120
|
+
const result = await executeCommand(cmd, { query: 'hello' });
|
|
47
121
|
expect(result).toEqual([{ title: 'hello' }]);
|
|
48
122
|
});
|
|
49
123
|
|
|
@@ -61,7 +135,7 @@ describe('executeCommand', () => {
|
|
|
61
135
|
});
|
|
62
136
|
|
|
63
137
|
// Pipeline commands require page for evaluate step, so we'll test the error path
|
|
64
|
-
await expect(executeCommand(cmd,
|
|
138
|
+
await expect(executeCommand(cmd, {})).rejects.toThrow();
|
|
65
139
|
});
|
|
66
140
|
|
|
67
141
|
it('throws for command with no func or pipeline', async () => {
|
|
@@ -72,7 +146,7 @@ describe('executeCommand', () => {
|
|
|
72
146
|
browser: false,
|
|
73
147
|
});
|
|
74
148
|
|
|
75
|
-
await expect(executeCommand(cmd,
|
|
149
|
+
await expect(executeCommand(cmd, {})).rejects.toThrow('has no func or pipeline');
|
|
76
150
|
});
|
|
77
151
|
|
|
78
152
|
it('passes debug flag to func', async () => {
|
|
@@ -88,7 +162,7 @@ describe('executeCommand', () => {
|
|
|
88
162
|
},
|
|
89
163
|
});
|
|
90
164
|
|
|
91
|
-
await executeCommand(cmd,
|
|
165
|
+
await executeCommand(cmd, {}, true);
|
|
92
166
|
expect(receivedDebug).toBe(true);
|
|
93
167
|
});
|
|
94
168
|
});
|
package/src/execution.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command execution: validates args, manages browser sessions, runs commands.
|
|
3
|
+
*
|
|
4
|
+
* This is the single entry point for executing any CLI command. It handles:
|
|
5
|
+
* 1. Argument validation and coercion
|
|
6
|
+
* 2. Browser session lifecycle (if needed)
|
|
7
|
+
* 3. Domain pre-navigation for cookie/header strategies
|
|
8
|
+
* 4. Timeout enforcement
|
|
9
|
+
* 5. Lazy-loading of TS modules from manifest
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { type CliCommand, type InternalCliCommand, type Arg, Strategy, getRegistry, fullName } from './registry.js';
|
|
13
|
+
import type { IPage } from './types.js';
|
|
14
|
+
import { pathToFileURL } from 'node:url';
|
|
15
|
+
import { executePipeline } from './pipeline/index.js';
|
|
16
|
+
import { AdapterLoadError } from './errors.js';
|
|
17
|
+
import { shouldUseBrowserSession } from './capabilityRouting.js';
|
|
18
|
+
import { getBrowserFactory, browserSession, runWithTimeout, DEFAULT_BROWSER_COMMAND_TIMEOUT } from './runtime.js';
|
|
19
|
+
|
|
20
|
+
/** Set of TS module paths that have been loaded */
|
|
21
|
+
const _loadedModules = new Set<string>();
|
|
22
|
+
type CommandArgs = Record<string, unknown>;
|
|
23
|
+
|
|
24
|
+
function getErrorMessage(error: unknown): string {
|
|
25
|
+
return error instanceof Error ? error.message : String(error);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Validates and coerces arguments based on the command's Arg definitions.
|
|
30
|
+
*/
|
|
31
|
+
export function coerceAndValidateArgs(cmdArgs: Arg[], kwargs: CommandArgs): CommandArgs {
|
|
32
|
+
const result: CommandArgs = { ...kwargs };
|
|
33
|
+
|
|
34
|
+
for (const argDef of cmdArgs) {
|
|
35
|
+
const val = result[argDef.name];
|
|
36
|
+
|
|
37
|
+
// 1. Check required
|
|
38
|
+
if (argDef.required && (val === undefined || val === null || val === '')) {
|
|
39
|
+
throw new Error(`Argument "${argDef.name}" is required.\n${argDef.help ? `Hint: ${argDef.help}` : ''}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (val !== undefined && val !== null) {
|
|
43
|
+
// 2. Type coercion
|
|
44
|
+
if (argDef.type === 'int' || argDef.type === 'number') {
|
|
45
|
+
const num = Number(val);
|
|
46
|
+
if (Number.isNaN(num)) {
|
|
47
|
+
throw new Error(`Argument "${argDef.name}" must be a valid number. Received: "${val}"`);
|
|
48
|
+
}
|
|
49
|
+
result[argDef.name] = num;
|
|
50
|
+
} else if (argDef.type === 'boolean' || argDef.type === 'bool') {
|
|
51
|
+
if (typeof val === 'string') {
|
|
52
|
+
const lower = val.toLowerCase();
|
|
53
|
+
if (lower === 'true' || lower === '1') result[argDef.name] = true;
|
|
54
|
+
else if (lower === 'false' || lower === '0') result[argDef.name] = false;
|
|
55
|
+
else throw new Error(`Argument "${argDef.name}" must be a boolean (true/false). Received: "${val}"`);
|
|
56
|
+
} else {
|
|
57
|
+
result[argDef.name] = Boolean(val);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 3. Choices validation
|
|
62
|
+
const coercedVal = result[argDef.name];
|
|
63
|
+
if (argDef.choices && argDef.choices.length > 0) {
|
|
64
|
+
if (!argDef.choices.map(String).includes(String(coercedVal))) {
|
|
65
|
+
throw new Error(`Argument "${argDef.name}" must be one of: ${argDef.choices.join(', ')}. Received: "${coercedVal}"`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} else if (argDef.default !== undefined) {
|
|
69
|
+
result[argDef.name] = argDef.default;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Run a command's func or pipeline against a page.
|
|
77
|
+
*/
|
|
78
|
+
async function runCommand(
|
|
79
|
+
cmd: CliCommand,
|
|
80
|
+
page: IPage | null,
|
|
81
|
+
kwargs: CommandArgs,
|
|
82
|
+
debug: boolean,
|
|
83
|
+
): Promise<unknown> {
|
|
84
|
+
// Lazy-load TS module on first execution (manifest fast-path)
|
|
85
|
+
const internal = cmd as InternalCliCommand;
|
|
86
|
+
if (internal._lazy && internal._modulePath) {
|
|
87
|
+
const modulePath = internal._modulePath;
|
|
88
|
+
if (!_loadedModules.has(modulePath)) {
|
|
89
|
+
try {
|
|
90
|
+
await import(pathToFileURL(modulePath).href);
|
|
91
|
+
_loadedModules.add(modulePath);
|
|
92
|
+
} catch (err) {
|
|
93
|
+
throw new AdapterLoadError(
|
|
94
|
+
`Failed to load adapter module ${modulePath}: ${getErrorMessage(err)}`,
|
|
95
|
+
'Check that the adapter file exists and has no syntax errors.',
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// After loading, the module's cli() call will have updated the registry.
|
|
100
|
+
const updated = getRegistry().get(fullName(cmd));
|
|
101
|
+
if (updated?.func) return updated.func(page!, kwargs, debug);
|
|
102
|
+
if (updated?.pipeline) return executePipeline(page, updated.pipeline, { args: kwargs, debug });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (cmd.func) return cmd.func(page!, kwargs, debug);
|
|
106
|
+
if (cmd.pipeline) return executePipeline(page, cmd.pipeline, { args: kwargs, debug });
|
|
107
|
+
throw new Error(`Command ${fullName(cmd)} has no func or pipeline`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Resolve the pre-navigation URL for a command, or null to skip.
|
|
112
|
+
*
|
|
113
|
+
* COOKIE/HEADER strategies need the browser on the target domain so
|
|
114
|
+
* `fetch(url, { credentials: 'include' })` carries cookies.
|
|
115
|
+
* Adapters that handle their own navigation set `navigateBefore: false`.
|
|
116
|
+
*/
|
|
117
|
+
function resolvePreNav(cmd: CliCommand): string | null {
|
|
118
|
+
if (cmd.navigateBefore === false) return null;
|
|
119
|
+
if (typeof cmd.navigateBefore === 'string') return cmd.navigateBefore;
|
|
120
|
+
|
|
121
|
+
// Default: pre-navigate for COOKIE/HEADER strategies with a domain
|
|
122
|
+
if ((cmd.strategy === Strategy.COOKIE || cmd.strategy === Strategy.HEADER) && cmd.domain) {
|
|
123
|
+
return `https://${cmd.domain}`;
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Execute a CLI command. Automatically manages browser sessions when needed.
|
|
130
|
+
*
|
|
131
|
+
* This is the unified entry point — callers don't need to care about
|
|
132
|
+
* whether the command requires a browser or not.
|
|
133
|
+
*/
|
|
134
|
+
export async function executeCommand(
|
|
135
|
+
cmd: CliCommand,
|
|
136
|
+
rawKwargs: CommandArgs,
|
|
137
|
+
debug: boolean = false,
|
|
138
|
+
): Promise<unknown> {
|
|
139
|
+
let kwargs: CommandArgs;
|
|
140
|
+
try {
|
|
141
|
+
kwargs = coerceAndValidateArgs(cmd.args, rawKwargs);
|
|
142
|
+
} catch (err) {
|
|
143
|
+
throw new Error(`[Argument Validation Error]\n${getErrorMessage(err)}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (shouldUseBrowserSession(cmd)) {
|
|
147
|
+
const BrowserFactory = getBrowserFactory();
|
|
148
|
+
return browserSession(BrowserFactory, async (page) => {
|
|
149
|
+
// Pre-navigate to target domain for cookie/header context if needed.
|
|
150
|
+
// Each adapter controls this via `navigateBefore` (see CliCommand docs).
|
|
151
|
+
const preNavUrl = resolvePreNav(cmd);
|
|
152
|
+
if (preNavUrl) {
|
|
153
|
+
try { await page.goto(preNavUrl); await page.wait(2); } catch {}
|
|
154
|
+
}
|
|
155
|
+
return runWithTimeout(runCommand(cmd, page, kwargs, debug), {
|
|
156
|
+
timeout: cmd.timeoutSeconds ?? DEFAULT_BROWSER_COMMAND_TIMEOUT,
|
|
157
|
+
label: fullName(cmd),
|
|
158
|
+
});
|
|
159
|
+
}, { workspace: `site:${cmd.site}` });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Non-browser commands run directly
|
|
163
|
+
return runCommand(cmd, null, kwargs, debug);
|
|
164
|
+
}
|