@jackwener/opencli 1.1.1 → 1.2.1
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/.github/workflows/build-extension.yml +3 -3
- package/.github/workflows/ci.yml +6 -6
- package/.github/workflows/doc-check.yml +3 -3
- package/.github/workflows/e2e-headed.yml +2 -2
- package/.github/workflows/pkg-pr-new.yml +2 -2
- package/.github/workflows/release.yml +3 -3
- package/.github/workflows/security.yml +2 -2
- package/CONTRIBUTING.md +39 -1
- package/README.md +13 -10
- package/README.zh-CN.md +43 -17
- package/SKILL.md +10 -5
- package/dist/browser/cdp.d.ts +4 -4
- package/dist/browser/cdp.js +39 -16
- package/dist/browser/daemon-client.d.ts +4 -2
- package/dist/browser/daemon-client.js +17 -4
- 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/mcp.js +3 -1
- package/dist/browser/page.d.ts +14 -24
- package/dist/browser/page.js +46 -6
- package/dist/build-manifest.d.ts +11 -4
- package/dist/build-manifest.js +59 -21
- package/dist/build-manifest.test.js +58 -2
- package/dist/cli-manifest.json +3856 -1509
- package/dist/cli.js +66 -0
- 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/following.js +1 -1
- package/dist/clis/bilibili/subtitle.js +1 -1
- package/dist/clis/bilibili/user-videos.js +1 -1
- package/dist/clis/boss/batchgreet.js +10 -97
- package/dist/clis/boss/chatlist.js +8 -25
- 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 +7 -49
- package/dist/clis/boss/exchange.js +13 -79
- package/dist/clis/boss/greet.js +18 -145
- 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 +12 -60
- package/dist/clis/boss/send.js +17 -151
- package/dist/clis/boss/stats.js +18 -69
- package/dist/clis/coupang/add-to-cart.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/repost.js +1 -1
- package/dist/clis/jimeng/generate.yaml +1 -0
- package/dist/clis/linux-do/category.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/reddit/comment.js +1 -1
- package/dist/clis/reddit/read.js +1 -1
- package/dist/clis/reddit/save.js +1 -1
- package/dist/clis/reddit/subreddit.yaml +1 -0
- package/dist/clis/reddit/subscribe.js +1 -1
- package/dist/clis/reddit/upvote.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/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/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/thread.js +1 -1
- 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/wikipedia/random.d.ts +1 -0
- package/dist/clis/wikipedia/random.js +19 -0
- package/dist/clis/wikipedia/search.js +3 -3
- 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.js +1 -1
- package/dist/clis/xiaohongshu/creator-note-detail.test.js +2 -0
- package/dist/clis/xiaohongshu/creator-notes.test.js +2 -0
- package/dist/clis/xiaohongshu/download.js +1 -1
- 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 -1
- package/dist/commanderAdapter.js +13 -7
- package/dist/daemon.js +21 -0
- package/dist/discovery.d.ts +8 -0
- package/dist/discovery.js +105 -19
- package/dist/doctor.js +3 -1
- package/dist/doctor.test.js +46 -2
- package/dist/engine.test.d.ts +0 -3
- package/dist/engine.test.js +74 -6
- package/dist/execution.d.ts +4 -2
- package/dist/execution.js +31 -7
- package/dist/explore.d.ts +76 -3
- package/dist/explore.js +11 -4
- 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 +4 -2
- package/dist/pipeline/executor.js +54 -15
- 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 +15 -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 +11 -0
- package/dist/registry.js +6 -1
- package/dist/synthesize.d.ts +94 -4
- package/dist/synthesize.js +5 -4
- package/dist/types.d.ts +39 -26
- package/dist/validate.js +8 -2
- package/docs/.vitepress/config.mts +6 -4
- package/docs/adapters/browser/barchart.md +6 -5
- package/docs/adapters/browser/bilibili.md +9 -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 +26 -8
- package/docs/adapters/browser/instagram.md +46 -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/substack.md +38 -0
- package/docs/adapters/browser/tiktok.md +68 -0
- package/docs/adapters/browser/wikipedia.md +11 -2
- 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 +2 -1
- 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 +1 -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/dist/background.js +91 -23
- package/extension/src/background.ts +82 -29
- package/extension/src/cdp.ts +42 -1
- package/package.json +10 -5
- package/scripts/clean-dist.cjs +13 -0
- package/src/browser/cdp.ts +71 -31
- package/src/browser/daemon-client.ts +21 -5
- 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/mcp.ts +3 -1
- package/src/browser/page.ts +57 -21
- package/src/build-manifest.test.ts +70 -2
- package/src/build-manifest.ts +94 -26
- package/src/cli.ts +71 -2
- 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/following.ts +1 -1
- package/src/clis/bilibili/subtitle.ts +1 -1
- package/src/clis/bilibili/user-videos.ts +1 -1
- package/src/clis/boss/batchgreet.ts +14 -106
- package/src/clis/boss/chatlist.ts +12 -26
- package/src/clis/boss/chatmsg.ts +16 -40
- package/src/clis/boss/common.ts +287 -0
- package/src/clis/boss/detail.ts +8 -54
- package/src/clis/boss/exchange.ts +15 -89
- package/src/clis/boss/greet.ts +23 -160
- 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 +13 -66
- package/src/clis/boss/send.ts +21 -161
- package/src/clis/boss/stats.ts +19 -74
- package/src/clis/coupang/add-to-cart.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/repost.ts +1 -1
- package/src/clis/jimeng/generate.yaml +1 -0
- package/src/clis/linux-do/category.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/reddit/comment.ts +1 -1
- package/src/clis/reddit/read.ts +1 -1
- package/src/clis/reddit/save.ts +1 -1
- package/src/clis/reddit/subreddit.yaml +1 -0
- package/src/clis/reddit/subscribe.ts +1 -1
- package/src/clis/reddit/upvote.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/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/download.ts +3 -3
- package/src/clis/twitter/followers.ts +1 -1
- package/src/clis/twitter/following.ts +1 -1
- package/src/clis/twitter/thread.ts +1 -1
- package/src/clis/twitter/timeline.test.ts +109 -0
- package/src/clis/twitter/timeline.ts +59 -19
- package/src/clis/wikipedia/random.ts +19 -0
- package/src/clis/wikipedia/search.ts +10 -4
- 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 +2 -0
- package/src/clis/xiaohongshu/creator-note-detail.ts +1 -1
- package/src/clis/xiaohongshu/creator-notes.test.ts +2 -0
- package/src/clis/xiaohongshu/download.ts +1 -1
- 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 -1
- package/src/commanderAdapter.ts +17 -10
- package/src/daemon.ts +23 -0
- package/src/discovery.ts +134 -24
- package/src/doctor.test.ts +59 -2
- package/src/doctor.ts +4 -2
- package/src/engine.test.ts +79 -6
- package/src/execution.ts +42 -16
- package/src/explore.ts +77 -9
- 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 +68 -19
- package/src/pipeline/registry.ts +3 -3
- package/src/pipeline/steps/browser.ts +24 -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 +19 -1
- package/src/synthesize.ts +102 -21
- package/src/types.ts +44 -12
- package/src/validate.ts +19 -4
- package/tests/e2e/browser-public.test.ts +11 -0
- package/tests/e2e/public-commands.test.ts +64 -0
- 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/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/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/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/pipeline.ts +0 -8
|
@@ -5,8 +5,33 @@ const WS_RECONNECT_BASE_DELAY = 2e3;
|
|
|
5
5
|
const WS_RECONNECT_MAX_DELAY = 6e4;
|
|
6
6
|
|
|
7
7
|
const attached = /* @__PURE__ */ new Set();
|
|
8
|
+
function isDebuggableUrl$1(url) {
|
|
9
|
+
if (!url) return false;
|
|
10
|
+
return !url.startsWith("chrome://") && !url.startsWith("chrome-extension://");
|
|
11
|
+
}
|
|
8
12
|
async function ensureAttached(tabId) {
|
|
9
|
-
|
|
13
|
+
try {
|
|
14
|
+
const tab = await chrome.tabs.get(tabId);
|
|
15
|
+
if (!isDebuggableUrl$1(tab.url)) {
|
|
16
|
+
attached.delete(tabId);
|
|
17
|
+
throw new Error(`Cannot debug tab ${tabId}: URL is ${tab.url ?? "unknown"}`);
|
|
18
|
+
}
|
|
19
|
+
} catch (e) {
|
|
20
|
+
if (e instanceof Error && e.message.startsWith("Cannot debug tab")) throw e;
|
|
21
|
+
attached.delete(tabId);
|
|
22
|
+
throw new Error(`Tab ${tabId} no longer exists`);
|
|
23
|
+
}
|
|
24
|
+
if (attached.has(tabId)) {
|
|
25
|
+
try {
|
|
26
|
+
await chrome.debugger.sendCommand({ tabId }, "Runtime.evaluate", {
|
|
27
|
+
expression: "1",
|
|
28
|
+
returnByValue: true
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
} catch {
|
|
32
|
+
attached.delete(tabId);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
10
35
|
try {
|
|
11
36
|
await chrome.debugger.attach({ tabId }, "1.3");
|
|
12
37
|
} catch (e) {
|
|
@@ -89,6 +114,17 @@ function registerListeners() {
|
|
|
89
114
|
chrome.debugger.onDetach.addListener((source) => {
|
|
90
115
|
if (source.tabId) attached.delete(source.tabId);
|
|
91
116
|
});
|
|
117
|
+
chrome.tabs.onUpdated.addListener((tabId, info) => {
|
|
118
|
+
if (info.url && !isDebuggableUrl$1(info.url)) {
|
|
119
|
+
if (attached.has(tabId)) {
|
|
120
|
+
attached.delete(tabId);
|
|
121
|
+
try {
|
|
122
|
+
chrome.debugger.detach({ tabId });
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
92
128
|
}
|
|
93
129
|
|
|
94
130
|
let ws = null;
|
|
@@ -161,7 +197,7 @@ function scheduleReconnect() {
|
|
|
161
197
|
}, delay);
|
|
162
198
|
}
|
|
163
199
|
const automationSessions = /* @__PURE__ */ new Map();
|
|
164
|
-
const WINDOW_IDLE_TIMEOUT =
|
|
200
|
+
const WINDOW_IDLE_TIMEOUT = 12e4;
|
|
165
201
|
function getWorkspaceKey(workspace) {
|
|
166
202
|
return workspace?.trim() || "default";
|
|
167
203
|
}
|
|
@@ -265,17 +301,30 @@ async function handleCommand(cmd) {
|
|
|
265
301
|
};
|
|
266
302
|
}
|
|
267
303
|
}
|
|
268
|
-
function
|
|
304
|
+
function isDebuggableUrl(url) {
|
|
269
305
|
if (!url) return false;
|
|
270
306
|
return !url.startsWith("chrome://") && !url.startsWith("chrome-extension://");
|
|
271
307
|
}
|
|
272
308
|
async function resolveTabId(tabId, workspace) {
|
|
273
|
-
if (tabId !== void 0)
|
|
309
|
+
if (tabId !== void 0) {
|
|
310
|
+
try {
|
|
311
|
+
const tab = await chrome.tabs.get(tabId);
|
|
312
|
+
if (isDebuggableUrl(tab.url)) return tabId;
|
|
313
|
+
console.warn(`[opencli] Tab ${tabId} URL is not debuggable (${tab.url}), re-resolving`);
|
|
314
|
+
} catch {
|
|
315
|
+
console.warn(`[opencli] Tab ${tabId} no longer exists, re-resolving`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
274
318
|
const windowId = await getAutomationWindow(workspace);
|
|
275
319
|
const tabs = await chrome.tabs.query({ windowId });
|
|
276
|
-
const
|
|
277
|
-
if (
|
|
278
|
-
|
|
320
|
+
const debuggableTab = tabs.find((t) => t.id && isDebuggableUrl(t.url));
|
|
321
|
+
if (debuggableTab?.id) return debuggableTab.id;
|
|
322
|
+
const reuseTab = tabs.find((t) => t.id);
|
|
323
|
+
if (reuseTab?.id) {
|
|
324
|
+
await chrome.tabs.update(reuseTab.id, { url: "about:blank" });
|
|
325
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
326
|
+
return reuseTab.id;
|
|
327
|
+
}
|
|
279
328
|
const newTab = await chrome.tabs.create({ windowId, url: "about:blank", active: true });
|
|
280
329
|
if (!newTab.id) throw new Error("Failed to create tab in automation window");
|
|
281
330
|
return newTab.id;
|
|
@@ -292,7 +341,7 @@ async function listAutomationTabs(workspace) {
|
|
|
292
341
|
}
|
|
293
342
|
async function listAutomationWebTabs(workspace) {
|
|
294
343
|
const tabs = await listAutomationTabs(workspace);
|
|
295
|
-
return tabs.filter((tab) =>
|
|
344
|
+
return tabs.filter((tab) => isDebuggableUrl(tab.url));
|
|
296
345
|
}
|
|
297
346
|
async function handleExec(cmd, workspace) {
|
|
298
347
|
if (!cmd.code) return { id: cmd.id, ok: false, error: "Missing code" };
|
|
@@ -307,28 +356,47 @@ async function handleExec(cmd, workspace) {
|
|
|
307
356
|
async function handleNavigate(cmd, workspace) {
|
|
308
357
|
if (!cmd.url) return { id: cmd.id, ok: false, error: "Missing url" };
|
|
309
358
|
const tabId = await resolveTabId(cmd.tabId, workspace);
|
|
310
|
-
await chrome.tabs.
|
|
359
|
+
const beforeTab = await chrome.tabs.get(tabId);
|
|
360
|
+
const beforeUrl = beforeTab.url ?? "";
|
|
361
|
+
const targetUrl = cmd.url;
|
|
362
|
+
await chrome.tabs.update(tabId, { url: targetUrl });
|
|
363
|
+
let timedOut = false;
|
|
311
364
|
await new Promise((resolve) => {
|
|
312
|
-
|
|
313
|
-
|
|
365
|
+
let urlChanged = false;
|
|
366
|
+
const listener = (id, info, tab2) => {
|
|
367
|
+
if (id !== tabId) return;
|
|
368
|
+
if (info.url && info.url !== beforeUrl) {
|
|
369
|
+
urlChanged = true;
|
|
370
|
+
}
|
|
371
|
+
if (urlChanged && info.status === "complete") {
|
|
372
|
+
chrome.tabs.onUpdated.removeListener(listener);
|
|
314
373
|
resolve();
|
|
315
|
-
return;
|
|
316
374
|
}
|
|
317
|
-
|
|
318
|
-
|
|
375
|
+
};
|
|
376
|
+
chrome.tabs.onUpdated.addListener(listener);
|
|
377
|
+
setTimeout(async () => {
|
|
378
|
+
try {
|
|
379
|
+
const currentTab = await chrome.tabs.get(tabId);
|
|
380
|
+
if (currentTab.url !== beforeUrl && currentTab.status === "complete") {
|
|
319
381
|
chrome.tabs.onUpdated.removeListener(listener);
|
|
320
382
|
resolve();
|
|
321
383
|
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
384
|
+
} catch {
|
|
385
|
+
}
|
|
386
|
+
}, 100);
|
|
387
|
+
setTimeout(() => {
|
|
388
|
+
chrome.tabs.onUpdated.removeListener(listener);
|
|
389
|
+
timedOut = true;
|
|
390
|
+
console.warn(`[opencli] Navigate to ${targetUrl} timed out after 15s`);
|
|
391
|
+
resolve();
|
|
392
|
+
}, 15e3);
|
|
329
393
|
});
|
|
330
394
|
const tab = await chrome.tabs.get(tabId);
|
|
331
|
-
return {
|
|
395
|
+
return {
|
|
396
|
+
id: cmd.id,
|
|
397
|
+
ok: true,
|
|
398
|
+
data: { title: tab.title, url: tab.url, tabId, timedOut }
|
|
399
|
+
};
|
|
332
400
|
}
|
|
333
401
|
async function handleTabs(cmd, workspace) {
|
|
334
402
|
switch (cmd.op) {
|
|
@@ -425,7 +493,7 @@ async function handleSessions(cmd) {
|
|
|
425
493
|
const data = await Promise.all([...automationSessions.entries()].map(async ([workspace, session]) => ({
|
|
426
494
|
workspace,
|
|
427
495
|
windowId: session.windowId,
|
|
428
|
-
tabCount: (await chrome.tabs.query({ windowId: session.windowId })).filter((tab) =>
|
|
496
|
+
tabCount: (await chrome.tabs.query({ windowId: session.windowId })).filter((tab) => isDebuggableUrl(tab.url)).length,
|
|
429
497
|
idleMsRemaining: Math.max(0, session.idleDeadlineAt - now)
|
|
430
498
|
})));
|
|
431
499
|
return { id: cmd.id, ok: true, data };
|
|
@@ -97,7 +97,7 @@ type AutomationSession = {
|
|
|
97
97
|
};
|
|
98
98
|
|
|
99
99
|
const automationSessions = new Map<string, AutomationSession>();
|
|
100
|
-
const WINDOW_IDLE_TIMEOUT =
|
|
100
|
+
const WINDOW_IDLE_TIMEOUT = 120000; // 120s — longer to survive slow pipelines
|
|
101
101
|
|
|
102
102
|
function getWorkspaceKey(workspace?: string): string {
|
|
103
103
|
return workspace?.trim() || 'default';
|
|
@@ -226,8 +226,8 @@ async function handleCommand(cmd: Command): Promise<Result> {
|
|
|
226
226
|
|
|
227
227
|
// ─── Action handlers ─────────────────────────────────────────────────
|
|
228
228
|
|
|
229
|
-
/** Check if a URL
|
|
230
|
-
function
|
|
229
|
+
/** Check if a URL can be attached via CDP (not chrome:// or chrome-extension://) */
|
|
230
|
+
function isDebuggableUrl(url?: string): boolean {
|
|
231
231
|
if (!url) return false;
|
|
232
232
|
return !url.startsWith('chrome://') && !url.startsWith('chrome-extension://');
|
|
233
233
|
}
|
|
@@ -238,20 +238,42 @@ function isWebUrl(url?: string): boolean {
|
|
|
238
238
|
* Otherwise, find or create a tab in the dedicated automation window.
|
|
239
239
|
*/
|
|
240
240
|
async function resolveTabId(tabId: number | undefined, workspace: string): Promise<number> {
|
|
241
|
-
|
|
241
|
+
// Even when an explicit tabId is provided, validate it is still debuggable.
|
|
242
|
+
// This prevents issues when extensions hijack the tab URL to chrome-extension://
|
|
243
|
+
// or when the tab has been closed by the user.
|
|
244
|
+
if (tabId !== undefined) {
|
|
245
|
+
try {
|
|
246
|
+
const tab = await chrome.tabs.get(tabId);
|
|
247
|
+
if (isDebuggableUrl(tab.url)) return tabId;
|
|
248
|
+
// Tab exists but URL is not debuggable — fall through to auto-resolve
|
|
249
|
+
console.warn(`[opencli] Tab ${tabId} URL is not debuggable (${tab.url}), re-resolving`);
|
|
250
|
+
} catch {
|
|
251
|
+
// Tab was closed — fall through to auto-resolve
|
|
252
|
+
console.warn(`[opencli] Tab ${tabId} no longer exists, re-resolving`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
242
255
|
|
|
243
256
|
// Get (or create) the automation window
|
|
244
257
|
const windowId = await getAutomationWindow(workspace);
|
|
245
258
|
|
|
246
|
-
//
|
|
259
|
+
// Prefer an existing debuggable tab (about:blank, http://, https://, etc.)
|
|
247
260
|
const tabs = await chrome.tabs.query({ windowId });
|
|
248
|
-
const
|
|
249
|
-
if (
|
|
250
|
-
|
|
251
|
-
//
|
|
252
|
-
|
|
261
|
+
const debuggableTab = tabs.find(t => t.id && isDebuggableUrl(t.url));
|
|
262
|
+
if (debuggableTab?.id) return debuggableTab.id;
|
|
263
|
+
|
|
264
|
+
// No debuggable tab found — this typically happens when a "New Tab Override"
|
|
265
|
+
// extension replaces about:blank with a chrome-extension:// page.
|
|
266
|
+
// Reuse the first existing tab by navigating it to about:blank (avoids
|
|
267
|
+
// accumulating orphan tabs if chrome.tabs.create is also intercepted).
|
|
268
|
+
const reuseTab = tabs.find(t => t.id);
|
|
269
|
+
if (reuseTab?.id) {
|
|
270
|
+
await chrome.tabs.update(reuseTab.id, { url: 'about:blank' });
|
|
271
|
+
// Wait briefly for the navigation to take effect
|
|
272
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
273
|
+
return reuseTab.id;
|
|
274
|
+
}
|
|
253
275
|
|
|
254
|
-
//
|
|
276
|
+
// Window has no tabs at all — create one
|
|
255
277
|
const newTab = await chrome.tabs.create({ windowId, url: 'about:blank', active: true });
|
|
256
278
|
if (!newTab.id) throw new Error('Failed to create tab in automation window');
|
|
257
279
|
return newTab.id;
|
|
@@ -270,7 +292,7 @@ async function listAutomationTabs(workspace: string): Promise<chrome.tabs.Tab[]>
|
|
|
270
292
|
|
|
271
293
|
async function listAutomationWebTabs(workspace: string): Promise<chrome.tabs.Tab[]> {
|
|
272
294
|
const tabs = await listAutomationTabs(workspace);
|
|
273
|
-
return tabs.filter((tab) =>
|
|
295
|
+
return tabs.filter((tab) => isDebuggableUrl(tab.url));
|
|
274
296
|
}
|
|
275
297
|
|
|
276
298
|
async function handleExec(cmd: Command, workspace: string): Promise<Result> {
|
|
@@ -287,31 +309,62 @@ async function handleExec(cmd: Command, workspace: string): Promise<Result> {
|
|
|
287
309
|
async function handleNavigate(cmd: Command, workspace: string): Promise<Result> {
|
|
288
310
|
if (!cmd.url) return { id: cmd.id, ok: false, error: 'Missing url' };
|
|
289
311
|
const tabId = await resolveTabId(cmd.tabId, workspace);
|
|
290
|
-
await chrome.tabs.update(tabId, { url: cmd.url });
|
|
291
312
|
|
|
292
|
-
//
|
|
313
|
+
// Capture the current URL before navigation to detect actual URL change
|
|
314
|
+
const beforeTab = await chrome.tabs.get(tabId);
|
|
315
|
+
const beforeUrl = beforeTab.url ?? '';
|
|
316
|
+
const targetUrl = cmd.url;
|
|
317
|
+
|
|
318
|
+
await chrome.tabs.update(tabId, { url: targetUrl });
|
|
319
|
+
|
|
320
|
+
// Wait for: 1) URL to change from the old URL, 2) tab.status === 'complete'
|
|
321
|
+
// This avoids the race where 'complete' fires for the OLD URL (e.g. about:blank)
|
|
322
|
+
let timedOut = false;
|
|
293
323
|
await new Promise<void>((resolve) => {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
324
|
+
let urlChanged = false;
|
|
325
|
+
|
|
326
|
+
const listener = (id: number, info: chrome.tabs.TabChangeInfo, tab: chrome.tabs.Tab) => {
|
|
327
|
+
if (id !== tabId) return;
|
|
328
|
+
|
|
329
|
+
// Track URL change (new URL differs from the one before navigation)
|
|
330
|
+
if (info.url && info.url !== beforeUrl) {
|
|
331
|
+
urlChanged = true;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Only resolve when both URL has changed AND status is complete
|
|
335
|
+
if (urlChanged && info.status === 'complete') {
|
|
336
|
+
chrome.tabs.onUpdated.removeListener(listener);
|
|
337
|
+
resolve();
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
chrome.tabs.onUpdated.addListener(listener);
|
|
297
341
|
|
|
298
|
-
|
|
299
|
-
|
|
342
|
+
// Also check if the tab already navigated (e.g. instant cache hit)
|
|
343
|
+
setTimeout(async () => {
|
|
344
|
+
try {
|
|
345
|
+
const currentTab = await chrome.tabs.get(tabId);
|
|
346
|
+
if (currentTab.url !== beforeUrl && currentTab.status === 'complete') {
|
|
300
347
|
chrome.tabs.onUpdated.removeListener(listener);
|
|
301
348
|
resolve();
|
|
302
349
|
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
350
|
+
} catch { /* tab gone */ }
|
|
351
|
+
}, 100);
|
|
352
|
+
|
|
353
|
+
// Timeout fallback with warning
|
|
354
|
+
setTimeout(() => {
|
|
355
|
+
chrome.tabs.onUpdated.removeListener(listener);
|
|
356
|
+
timedOut = true;
|
|
357
|
+
console.warn(`[opencli] Navigate to ${targetUrl} timed out after 15s`);
|
|
358
|
+
resolve();
|
|
359
|
+
}, 15000);
|
|
311
360
|
});
|
|
312
361
|
|
|
313
362
|
const tab = await chrome.tabs.get(tabId);
|
|
314
|
-
return {
|
|
363
|
+
return {
|
|
364
|
+
id: cmd.id,
|
|
365
|
+
ok: true,
|
|
366
|
+
data: { title: tab.title, url: tab.url, tabId, timedOut },
|
|
367
|
+
};
|
|
315
368
|
}
|
|
316
369
|
|
|
317
370
|
async function handleTabs(cmd: Command, workspace: string): Promise<Result> {
|
|
@@ -415,7 +468,7 @@ async function handleSessions(cmd: Command): Promise<Result> {
|
|
|
415
468
|
const data = await Promise.all([...automationSessions.entries()].map(async ([workspace, session]) => ({
|
|
416
469
|
workspace,
|
|
417
470
|
windowId: session.windowId,
|
|
418
|
-
tabCount: (await chrome.tabs.query({ windowId: session.windowId })).filter((tab) =>
|
|
471
|
+
tabCount: (await chrome.tabs.query({ windowId: session.windowId })).filter((tab) => isDebuggableUrl(tab.url)).length,
|
|
419
472
|
idleMsRemaining: Math.max(0, session.idleDeadlineAt - now),
|
|
420
473
|
})));
|
|
421
474
|
return { id: cmd.id, ok: true, data };
|
package/extension/src/cdp.ts
CHANGED
|
@@ -8,8 +8,40 @@
|
|
|
8
8
|
|
|
9
9
|
const attached = new Set<number>();
|
|
10
10
|
|
|
11
|
+
/** Check if a URL can be attached via CDP */
|
|
12
|
+
function isDebuggableUrl(url?: string): boolean {
|
|
13
|
+
if (!url) return false;
|
|
14
|
+
return !url.startsWith('chrome://') && !url.startsWith('chrome-extension://');
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
async function ensureAttached(tabId: number): Promise<void> {
|
|
12
|
-
|
|
18
|
+
// Verify the tab URL is debuggable before attempting attach
|
|
19
|
+
try {
|
|
20
|
+
const tab = await chrome.tabs.get(tabId);
|
|
21
|
+
if (!isDebuggableUrl(tab.url)) {
|
|
22
|
+
// Invalidate cache if previously attached
|
|
23
|
+
attached.delete(tabId);
|
|
24
|
+
throw new Error(`Cannot debug tab ${tabId}: URL is ${tab.url ?? 'unknown'}`);
|
|
25
|
+
}
|
|
26
|
+
} catch (e) {
|
|
27
|
+
// Re-throw our own error, catch only chrome.tabs.get failures
|
|
28
|
+
if (e instanceof Error && e.message.startsWith('Cannot debug tab')) throw e;
|
|
29
|
+
attached.delete(tabId);
|
|
30
|
+
throw new Error(`Tab ${tabId} no longer exists`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (attached.has(tabId)) {
|
|
34
|
+
// Verify the debugger is still actually attached by sending a harmless command
|
|
35
|
+
try {
|
|
36
|
+
await chrome.debugger.sendCommand({ tabId }, 'Runtime.evaluate', {
|
|
37
|
+
expression: '1', returnByValue: true,
|
|
38
|
+
});
|
|
39
|
+
return; // Still attached and working
|
|
40
|
+
} catch {
|
|
41
|
+
// Stale cache entry — need to re-attach
|
|
42
|
+
attached.delete(tabId);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
13
45
|
|
|
14
46
|
try {
|
|
15
47
|
await chrome.debugger.attach({ tabId }, '1.3');
|
|
@@ -122,4 +154,13 @@ export function registerListeners(): void {
|
|
|
122
154
|
chrome.debugger.onDetach.addListener((source) => {
|
|
123
155
|
if (source.tabId) attached.delete(source.tabId);
|
|
124
156
|
});
|
|
157
|
+
// Invalidate attached cache when tab URL changes to non-debuggable
|
|
158
|
+
chrome.tabs.onUpdated.addListener((tabId, info) => {
|
|
159
|
+
if (info.url && !isDebuggableUrl(info.url)) {
|
|
160
|
+
if (attached.has(tabId)) {
|
|
161
|
+
attached.delete(tabId);
|
|
162
|
+
try { chrome.debugger.detach({ tabId }); } catch { /* ignore */ }
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
});
|
|
125
166
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jackwener/opencli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -13,10 +13,15 @@
|
|
|
13
13
|
"bin": {
|
|
14
14
|
"opencli": "dist/main.js"
|
|
15
15
|
},
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./dist/main.js",
|
|
18
|
+
"./registry": "./dist/registry-api.js"
|
|
19
|
+
},
|
|
16
20
|
"scripts": {
|
|
17
21
|
"dev": "tsx src/main.ts",
|
|
18
|
-
"build": "tsc && npm run clean-yaml && npm run copy-yaml && npm run build-manifest",
|
|
22
|
+
"build": "npm run clean-dist && tsc && npm run clean-yaml && npm run copy-yaml && npm run build-manifest",
|
|
19
23
|
"build-manifest": "node dist/build-manifest.js",
|
|
24
|
+
"clean-dist": "node scripts/clean-dist.cjs",
|
|
20
25
|
"clean-yaml": "node scripts/clean-yaml.cjs",
|
|
21
26
|
"copy-yaml": "node scripts/copy-yaml.cjs",
|
|
22
27
|
"start": "node dist/main.js",
|
|
@@ -24,9 +29,9 @@
|
|
|
24
29
|
"typecheck": "tsc --noEmit",
|
|
25
30
|
"lint": "tsc --noEmit",
|
|
26
31
|
"prepublishOnly": "npm run build",
|
|
27
|
-
"test": "vitest run",
|
|
28
|
-
"test:
|
|
29
|
-
"test:
|
|
32
|
+
"test": "vitest run --project unit",
|
|
33
|
+
"test:all": "vitest run",
|
|
34
|
+
"test:e2e": "vitest run --project e2e",
|
|
30
35
|
"docs:dev": "vitepress dev docs",
|
|
31
36
|
"docs:build": "vitepress build docs",
|
|
32
37
|
"docs:preview": "vitepress preview docs"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove dist/ before a fresh build so deleted adapters do not leave stale
|
|
3
|
+
* compiled files behind in dist/clis/.
|
|
4
|
+
*/
|
|
5
|
+
const { existsSync, rmSync } = require('fs');
|
|
6
|
+
|
|
7
|
+
if (existsSync('dist')) {
|
|
8
|
+
rmSync('dist', { recursive: true, force: true });
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (existsSync('tsconfig.tsbuildinfo')) {
|
|
12
|
+
rmSync('tsconfig.tsbuildinfo', { force: true });
|
|
13
|
+
}
|