@jackwener/opencli 1.3.3 → 1.4.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/.github/pull_request_template.md +3 -1
- package/.github/workflows/build-extension.yml +7 -1
- package/.github/workflows/ci.yml +29 -3
- package/.github/workflows/docs.yml +1 -1
- package/.github/workflows/e2e-headed.yml +20 -0
- package/.github/workflows/release.yml +1 -1
- package/.github/workflows/security.yml +0 -3
- package/CHANGELOG.md +55 -0
- package/CONTRIBUTING.md +6 -3
- package/README.md +30 -3
- package/README.zh-CN.md +30 -3
- package/SKILL.md +7 -1
- package/TESTING.md +1 -0
- package/chatwise-opencli.ps1 +82 -0
- package/dist/analysis.d.ts +38 -0
- package/dist/analysis.js +166 -0
- package/dist/browser/cdp.d.ts +0 -4
- package/dist/browser/cdp.js +53 -41
- package/dist/browser/cdp.test.d.ts +1 -0
- package/dist/browser/cdp.test.js +52 -0
- package/dist/browser/dom-snapshot.d.ts +2 -2
- package/dist/browser/dom-snapshot.js +54 -1
- package/dist/browser/dom-snapshot.test.js +36 -0
- package/dist/browser/index.d.ts +2 -2
- package/dist/browser/index.js +1 -1
- package/dist/browser/mcp.d.ts +0 -2
- package/dist/browser/mcp.js +2 -3
- package/dist/browser/page.d.ts +4 -3
- package/dist/browser/page.js +34 -37
- package/dist/browser/stealth.d.ts +0 -2
- package/dist/browser/stealth.js +24 -9
- package/dist/browser.test.js +2 -2
- package/dist/build-manifest.js +15 -9
- package/dist/build-manifest.test.js +12 -0
- package/dist/cascade.js +4 -2
- package/dist/cli-manifest.json +639 -258
- package/dist/cli.js +57 -29
- package/dist/clis/_shared/desktop-commands.d.ts +22 -0
- package/dist/clis/_shared/desktop-commands.js +108 -0
- package/dist/clis/antigravity/serve.js +5 -2
- package/dist/clis/arxiv/search.js +1 -1
- package/dist/clis/bilibili/dynamic.test.d.ts +1 -0
- package/dist/clis/bilibili/dynamic.test.js +68 -0
- package/dist/clis/bilibili/favorite.js +4 -2
- package/dist/clis/bilibili/following.js +3 -2
- package/dist/clis/bilibili/subtitle.js +8 -7
- package/dist/clis/bilibili/utils.js +2 -2
- package/dist/clis/boss/batchgreet.js +1 -1
- package/dist/clis/boss/chatlist.js +1 -1
- package/dist/clis/boss/chatmsg.js +1 -1
- package/dist/clis/boss/detail.js +1 -1
- package/dist/clis/boss/exchange.js +1 -1
- package/dist/clis/boss/greet.js +1 -1
- package/dist/clis/boss/invite.js +1 -1
- package/dist/clis/boss/joblist.js +1 -1
- package/dist/clis/boss/mark.js +4 -3
- package/dist/clis/boss/recommend.js +1 -1
- package/dist/clis/boss/resume.js +1 -1
- package/dist/clis/boss/search.js +1 -1
- package/dist/clis/boss/send.js +5 -4
- package/dist/clis/boss/stats.js +1 -1
- package/dist/clis/chatgpt/ask.js +4 -0
- package/dist/clis/chatgpt/new.js +5 -1
- package/dist/clis/chatgpt/read.js +5 -1
- package/dist/clis/chatgpt/send.js +2 -1
- package/dist/clis/chatgpt/status.js +5 -1
- package/dist/clis/chatwise/ask.js +8 -2
- package/dist/clis/chatwise/export.js +2 -0
- package/dist/clis/chatwise/history.js +2 -0
- package/dist/clis/chatwise/model.js +8 -3
- package/dist/clis/chatwise/new.js +3 -18
- package/dist/clis/chatwise/read.js +2 -0
- package/dist/clis/chatwise/screenshot.js +3 -27
- package/dist/clis/chatwise/send.js +8 -2
- package/dist/clis/chatwise/shared.d.ts +2 -0
- package/dist/clis/chatwise/shared.js +6 -0
- package/dist/clis/chatwise/status.js +3 -22
- package/dist/clis/codex/ask.js +6 -2
- package/dist/clis/codex/dump.js +2 -25
- package/dist/clis/codex/new.js +2 -25
- package/dist/clis/codex/screenshot.js +2 -27
- package/dist/clis/codex/send.js +6 -4
- package/dist/clis/codex/status.js +2 -22
- package/dist/clis/cursor/ask.js +2 -1
- package/dist/clis/cursor/composer.js +2 -1
- package/dist/clis/cursor/dump.js +2 -25
- package/dist/clis/cursor/new.js +2 -18
- package/dist/clis/cursor/read.js +2 -1
- package/dist/clis/cursor/screenshot.js +1 -30
- package/dist/clis/cursor/send.js +2 -1
- package/dist/clis/cursor/status.js +2 -21
- package/dist/clis/dictionary/examples.yaml +25 -0
- package/dist/clis/dictionary/search.yaml +27 -0
- package/dist/clis/dictionary/synonyms.yaml +25 -0
- package/dist/clis/douban/book-hot.js +1 -1
- package/dist/clis/douban/movie-hot.js +1 -1
- package/dist/clis/douban/search.js +1 -1
- package/dist/clis/douban/utils.d.ts +4 -1
- package/dist/clis/douban/utils.js +156 -1
- package/dist/clis/doubao/ask.js +1 -1
- package/dist/clis/doubao/new.js +1 -1
- package/dist/clis/doubao/read.js +1 -1
- package/dist/clis/doubao/send.js +1 -1
- package/dist/clis/doubao/status.js +1 -1
- package/dist/clis/doubao-app/ask.js +1 -1
- package/dist/clis/doubao-app/new.js +1 -1
- package/dist/clis/doubao-app/read.js +1 -1
- package/dist/clis/doubao-app/send.js +1 -1
- package/dist/clis/grok/ask.d.ts +4 -0
- package/dist/clis/grok/ask.js +28 -10
- package/dist/clis/grok/ask.test.js +18 -0
- package/dist/clis/jd/item.d.ts +1 -0
- package/dist/clis/jd/item.js +96 -0
- package/dist/clis/jd/item.test.d.ts +1 -0
- package/dist/clis/jd/item.test.js +28 -0
- package/dist/clis/jike/feed.js +1 -1
- package/dist/clis/jike/search.js +1 -1
- package/dist/clis/linkedin/search.js +5 -4
- package/dist/clis/linkedin/timeline.d.ts +21 -0
- package/dist/clis/linkedin/timeline.js +503 -0
- package/dist/clis/linkedin/timeline.test.d.ts +1 -0
- package/dist/clis/linkedin/timeline.test.js +81 -0
- package/dist/clis/medium/feed.js +1 -1
- package/dist/clis/medium/search.js +1 -1
- package/dist/clis/medium/user.js +1 -1
- package/dist/clis/medium/{shared.js → utils.js} +2 -1
- package/dist/clis/pixiv/detail.yaml +49 -0
- package/dist/clis/pixiv/download.d.ts +7 -0
- package/dist/clis/pixiv/download.js +78 -0
- package/dist/clis/pixiv/download.test.d.ts +1 -0
- package/dist/clis/pixiv/download.test.js +87 -0
- package/dist/clis/pixiv/illusts.d.ts +8 -0
- package/dist/clis/pixiv/illusts.js +65 -0
- package/dist/clis/pixiv/illusts.test.d.ts +1 -0
- package/dist/clis/pixiv/illusts.test.js +99 -0
- package/dist/clis/pixiv/ranking.yaml +53 -0
- package/dist/clis/pixiv/search.d.ts +6 -0
- package/dist/clis/pixiv/search.js +43 -0
- package/dist/clis/pixiv/search.test.d.ts +1 -0
- package/dist/clis/pixiv/search.test.js +83 -0
- package/dist/clis/pixiv/test-utils.d.ts +12 -0
- package/dist/clis/pixiv/test-utils.js +23 -0
- package/dist/clis/pixiv/user.yaml +46 -0
- package/dist/clis/pixiv/utils.d.ts +27 -0
- package/dist/clis/pixiv/utils.js +49 -0
- package/dist/clis/reddit/comment.js +2 -1
- package/dist/clis/reddit/read.js +4 -3
- package/dist/clis/reddit/read.test.d.ts +1 -0
- package/dist/clis/reddit/read.test.js +28 -0
- package/dist/clis/reddit/save.js +2 -1
- package/dist/clis/reddit/saved.js +7 -3
- package/dist/clis/reddit/subscribe.js +2 -1
- package/dist/clis/reddit/upvote.js +2 -1
- package/dist/clis/reddit/upvoted.js +7 -3
- package/dist/clis/sinablog/article.js +1 -1
- package/dist/clis/sinablog/hot.js +1 -1
- package/dist/clis/sinablog/user.js +1 -1
- package/dist/clis/substack/feed.js +1 -1
- package/dist/clis/substack/publication.js +1 -1
- package/dist/clis/substack/search.js +3 -2
- package/dist/clis/substack/{shared.js → utils.js} +3 -2
- package/dist/clis/tiktok/search.yaml +2 -1
- package/dist/clis/twitter/accept.js +2 -1
- package/dist/clis/twitter/article.js +4 -1
- package/dist/clis/twitter/block.js +2 -1
- package/dist/clis/twitter/bookmark.js +2 -1
- package/dist/clis/twitter/bookmarks.js +3 -2
- package/dist/clis/twitter/delete.js +2 -1
- package/dist/clis/twitter/follow.js +2 -1
- package/dist/clis/twitter/followers.js +3 -2
- package/dist/clis/twitter/following.js +3 -2
- package/dist/clis/twitter/hide-reply.js +2 -1
- package/dist/clis/twitter/like.js +2 -1
- package/dist/clis/twitter/notifications.js +2 -1
- package/dist/clis/twitter/post.js +2 -1
- package/dist/clis/twitter/profile.js +5 -2
- package/dist/clis/twitter/reply-dm.js +2 -1
- package/dist/clis/twitter/reply.js +2 -1
- package/dist/clis/twitter/search.js +30 -13
- package/dist/clis/twitter/search.test.d.ts +1 -0
- package/dist/clis/twitter/search.test.js +104 -0
- package/dist/clis/twitter/thread.js +2 -2
- package/dist/clis/twitter/timeline.js +3 -2
- package/dist/clis/twitter/trending.js +3 -2
- package/dist/clis/twitter/unblock.js +2 -1
- package/dist/clis/twitter/unbookmark.js +2 -1
- package/dist/clis/twitter/unfollow.js +2 -1
- package/dist/clis/v2ex/daily.js +3 -2
- package/dist/clis/v2ex/me.js +3 -2
- package/dist/clis/v2ex/notifications.js +4 -4
- package/dist/clis/web/read.d.ts +16 -0
- package/dist/clis/web/read.js +202 -0
- package/dist/clis/xueqiu/danjuan-utils.d.ts +55 -0
- package/dist/clis/xueqiu/danjuan-utils.js +126 -0
- package/dist/clis/xueqiu/danjuan-utils.test.d.ts +1 -0
- package/dist/clis/xueqiu/danjuan-utils.test.js +41 -0
- package/dist/clis/xueqiu/fund-holdings.d.ts +1 -0
- package/dist/clis/xueqiu/fund-holdings.js +28 -0
- package/dist/clis/xueqiu/fund-snapshot.d.ts +1 -0
- package/dist/clis/xueqiu/fund-snapshot.js +25 -0
- package/dist/clis/youtube/transcript.js +5 -4
- package/dist/clis/youtube/video.js +3 -2
- package/dist/daemon.js +7 -3
- package/dist/discovery.js +11 -10
- package/dist/doctor.js +2 -1
- package/dist/download/index.d.ts +4 -12
- package/dist/download/index.js +33 -12
- package/dist/download/index.test.js +79 -2
- package/dist/download/media-download.js +4 -2
- package/dist/engine.test.js +76 -4
- package/dist/execution.d.ts +1 -9
- package/dist/execution.js +56 -46
- package/dist/explore.js +12 -111
- package/dist/external-clis.yaml +0 -8
- package/dist/external.js +7 -5
- package/dist/external.test.js +4 -0
- package/dist/generate.d.ts +0 -9
- package/dist/generate.js +4 -20
- package/dist/hooks.d.ts +46 -0
- package/dist/hooks.js +56 -0
- package/dist/hooks.test.d.ts +4 -0
- package/dist/hooks.test.js +92 -0
- package/dist/interceptor.js +70 -23
- package/dist/main.js +2 -0
- package/dist/output.js +12 -6
- package/dist/pipeline/executor.js +1 -1
- package/dist/pipeline/steps/browser.js +1 -3
- package/dist/pipeline/steps/download.js +42 -26
- package/dist/pipeline/steps/download.test.d.ts +1 -0
- package/dist/pipeline/steps/download.test.js +101 -0
- package/dist/pipeline/steps/fetch.js +40 -22
- package/dist/pipeline/steps/fetch.test.d.ts +1 -0
- package/dist/pipeline/steps/fetch.test.js +123 -0
- package/dist/pipeline/steps/transform.js +2 -6
- package/dist/pipeline/template.js +66 -52
- package/dist/pipeline/template.test.js +28 -0
- package/dist/pipeline/transform.test.js +18 -0
- package/dist/plugin.d.ts +40 -1
- package/dist/plugin.js +214 -17
- package/dist/plugin.test.d.ts +1 -1
- package/dist/plugin.test.js +219 -3
- package/dist/record.js +6 -98
- package/dist/registry-api.d.ts +2 -0
- package/dist/registry-api.js +1 -0
- package/dist/registry.d.ts +5 -2
- package/dist/registry.js +1 -2
- package/dist/runtime.d.ts +0 -1
- package/dist/runtime.js +14 -4
- package/dist/snapshotFormatter.d.ts +7 -14
- package/dist/snapshotFormatter.js +38 -78
- package/dist/utils.d.ts +9 -0
- package/dist/utils.js +29 -0
- package/dist/validate.js +3 -5
- package/dist/yaml-schema.d.ts +26 -0
- package/dist/yaml-schema.js +5 -0
- package/docs/.vitepress/config.mts +3 -0
- package/docs/adapters/browser/dictionary.md +27 -0
- package/docs/adapters/browser/jd.md +27 -0
- package/docs/adapters/browser/linkedin.md +6 -0
- package/docs/adapters/browser/pixiv.md +92 -0
- package/docs/adapters/browser/web.md +30 -0
- package/docs/adapters/browser/xueqiu.md +27 -9
- package/docs/adapters/index.md +3 -1
- package/docs/comparison.md +125 -0
- package/docs/developer/contributing.md +21 -2
- package/docs/developer/testing.md +14 -8
- package/docs/developer/ts-adapter.md +18 -0
- package/docs/developer/yaml-adapter.md +16 -0
- package/docs/guide/plugins.md +10 -0
- package/docs/zh/guide/plugins.md +10 -0
- package/extension/dist/background.js +519 -444
- package/extension/manifest.json +1 -1
- package/extension/package.json +1 -1
- package/extension/src/background.test.ts +46 -1
- package/extension/src/background.ts +108 -33
- package/extension/src/cdp.ts +9 -9
- package/package.json +3 -2
- package/scripts/check-doc-coverage.sh +2 -0
- package/src/analysis.ts +170 -0
- package/src/browser/cdp.test.ts +66 -0
- package/src/browser/cdp.ts +59 -44
- package/src/browser/dom-snapshot.test.ts +42 -0
- package/src/browser/dom-snapshot.ts +56 -3
- package/src/browser/index.ts +2 -2
- package/src/browser/mcp.ts +2 -4
- package/src/browser/page.ts +34 -37
- package/src/browser/stealth.ts +24 -10
- package/src/browser.test.ts +2 -2
- package/src/build-manifest.test.ts +14 -0
- package/src/build-manifest.ts +13 -31
- package/src/cascade.ts +5 -3
- package/src/cli.ts +66 -34
- package/src/clis/_shared/desktop-commands.ts +121 -0
- package/src/clis/antigravity/serve.ts +6 -3
- package/src/clis/arxiv/search.ts +1 -1
- package/src/clis/bilibili/dynamic.test.ts +79 -0
- package/src/clis/bilibili/favorite.ts +5 -2
- package/src/clis/bilibili/following.ts +3 -2
- package/src/clis/bilibili/subtitle.ts +8 -7
- package/src/clis/bilibili/utils.ts +2 -2
- package/src/clis/boss/batchgreet.ts +1 -1
- package/src/clis/boss/chatlist.ts +1 -1
- package/src/clis/boss/chatmsg.ts +1 -1
- package/src/clis/boss/detail.ts +1 -1
- package/src/clis/boss/exchange.ts +1 -1
- package/src/clis/boss/greet.ts +1 -1
- package/src/clis/boss/invite.ts +1 -1
- package/src/clis/boss/joblist.ts +1 -1
- package/src/clis/boss/mark.ts +4 -3
- package/src/clis/boss/recommend.ts +1 -1
- package/src/clis/boss/resume.ts +1 -1
- package/src/clis/boss/search.ts +1 -1
- package/src/clis/boss/send.ts +5 -4
- package/src/clis/boss/stats.ts +1 -1
- package/src/clis/chatgpt/ask.ts +5 -0
- package/src/clis/chatgpt/new.ts +7 -2
- package/src/clis/chatgpt/read.ts +7 -2
- package/src/clis/chatgpt/send.ts +3 -2
- package/src/clis/chatgpt/status.ts +6 -1
- package/src/clis/chatwise/ask.ts +7 -2
- package/src/clis/chatwise/export.ts +2 -0
- package/src/clis/chatwise/history.ts +2 -0
- package/src/clis/chatwise/model.ts +7 -3
- package/src/clis/chatwise/new.ts +3 -20
- package/src/clis/chatwise/read.ts +2 -0
- package/src/clis/chatwise/screenshot.ts +3 -32
- package/src/clis/chatwise/send.ts +7 -2
- package/src/clis/chatwise/shared.ts +8 -0
- package/src/clis/chatwise/status.ts +3 -24
- package/src/clis/codex/ask.ts +5 -2
- package/src/clis/codex/dump.ts +2 -27
- package/src/clis/codex/new.ts +2 -28
- package/src/clis/codex/screenshot.ts +2 -32
- package/src/clis/codex/send.ts +5 -4
- package/src/clis/codex/status.ts +2 -24
- package/src/clis/cursor/ask.ts +2 -1
- package/src/clis/cursor/composer.ts +2 -1
- package/src/clis/cursor/dump.ts +2 -27
- package/src/clis/cursor/new.ts +2 -20
- package/src/clis/cursor/read.ts +2 -1
- package/src/clis/cursor/screenshot.ts +1 -36
- package/src/clis/cursor/send.ts +2 -1
- package/src/clis/cursor/status.ts +2 -22
- package/src/clis/dictionary/examples.yaml +25 -0
- package/src/clis/dictionary/search.yaml +27 -0
- package/src/clis/dictionary/synonyms.yaml +25 -0
- package/src/clis/douban/book-hot.ts +1 -1
- package/src/clis/douban/movie-hot.ts +1 -1
- package/src/clis/douban/search.ts +1 -1
- package/src/clis/douban/utils.ts +165 -1
- package/src/clis/doubao/ask.ts +1 -1
- package/src/clis/doubao/new.ts +1 -1
- package/src/clis/doubao/read.ts +1 -1
- package/src/clis/doubao/send.ts +1 -1
- package/src/clis/doubao/status.ts +1 -1
- package/src/clis/doubao-app/ask.ts +1 -1
- package/src/clis/doubao-app/new.ts +1 -1
- package/src/clis/doubao-app/read.ts +1 -1
- package/src/clis/doubao-app/send.ts +1 -1
- package/src/clis/grok/ask.test.ts +25 -0
- package/src/clis/grok/ask.ts +25 -12
- package/src/clis/jd/item.test.ts +35 -0
- package/src/clis/jd/item.ts +101 -0
- package/src/clis/jike/feed.ts +1 -1
- package/src/clis/jike/search.ts +1 -1
- package/src/clis/linkedin/search.ts +5 -4
- package/src/clis/linkedin/timeline.test.ts +99 -0
- package/src/clis/linkedin/timeline.ts +532 -0
- package/src/clis/medium/feed.ts +1 -1
- package/src/clis/medium/search.ts +1 -1
- package/src/clis/medium/user.ts +1 -1
- package/src/clis/medium/{shared.ts → utils.ts} +2 -1
- package/src/clis/pixiv/detail.yaml +49 -0
- package/src/clis/pixiv/download.test.ts +114 -0
- package/src/clis/pixiv/download.ts +91 -0
- package/src/clis/pixiv/illusts.test.ts +115 -0
- package/src/clis/pixiv/illusts.ts +78 -0
- package/src/clis/pixiv/ranking.yaml +53 -0
- package/src/clis/pixiv/search.test.ts +97 -0
- package/src/clis/pixiv/search.ts +53 -0
- package/src/clis/pixiv/test-utils.ts +29 -0
- package/src/clis/pixiv/user.yaml +46 -0
- package/src/clis/pixiv/utils.ts +62 -0
- package/src/clis/reddit/comment.ts +2 -1
- package/src/clis/reddit/read.test.ts +34 -0
- package/src/clis/reddit/read.ts +4 -3
- package/src/clis/reddit/save.ts +2 -1
- package/src/clis/reddit/saved.ts +6 -2
- package/src/clis/reddit/subscribe.ts +2 -1
- package/src/clis/reddit/upvote.ts +2 -1
- package/src/clis/reddit/upvoted.ts +6 -2
- package/src/clis/sinablog/article.ts +1 -1
- package/src/clis/sinablog/hot.ts +1 -1
- package/src/clis/sinablog/user.ts +1 -1
- package/src/clis/substack/feed.ts +1 -1
- package/src/clis/substack/publication.ts +1 -1
- package/src/clis/substack/search.ts +3 -2
- package/src/clis/substack/{shared.ts → utils.ts} +3 -2
- package/src/clis/tiktok/search.yaml +2 -1
- package/src/clis/twitter/accept.ts +2 -1
- package/src/clis/twitter/article.ts +3 -1
- package/src/clis/twitter/block.ts +2 -1
- package/src/clis/twitter/bookmark.ts +2 -1
- package/src/clis/twitter/bookmarks.ts +3 -2
- package/src/clis/twitter/delete.ts +2 -1
- package/src/clis/twitter/follow.ts +2 -1
- package/src/clis/twitter/followers.ts +3 -2
- package/src/clis/twitter/following.ts +3 -2
- package/src/clis/twitter/hide-reply.ts +2 -1
- package/src/clis/twitter/like.ts +2 -1
- package/src/clis/twitter/notifications.ts +2 -1
- package/src/clis/twitter/post.ts +2 -1
- package/src/clis/twitter/profile.ts +4 -2
- package/src/clis/twitter/reply-dm.ts +2 -1
- package/src/clis/twitter/reply.ts +2 -1
- package/src/clis/twitter/search.test.ts +113 -0
- package/src/clis/twitter/search.ts +38 -14
- package/src/clis/twitter/thread.ts +2 -2
- package/src/clis/twitter/timeline.ts +3 -2
- package/src/clis/twitter/trending.ts +3 -2
- package/src/clis/twitter/unblock.ts +2 -1
- package/src/clis/twitter/unbookmark.ts +2 -1
- package/src/clis/twitter/unfollow.ts +2 -1
- package/src/clis/v2ex/daily.ts +3 -2
- package/src/clis/v2ex/me.ts +3 -2
- package/src/clis/v2ex/notifications.ts +3 -4
- package/src/clis/web/read.ts +210 -0
- package/src/clis/xueqiu/danjuan-utils.test.ts +49 -0
- package/src/clis/xueqiu/danjuan-utils.ts +176 -0
- package/src/clis/xueqiu/fund-holdings.ts +32 -0
- package/src/clis/xueqiu/fund-snapshot.ts +27 -0
- package/src/clis/youtube/transcript.ts +5 -4
- package/src/clis/youtube/video.ts +3 -2
- package/src/daemon.ts +5 -4
- package/src/discovery.ts +12 -34
- package/src/doctor.ts +3 -2
- package/src/download/index.test.ts +93 -2
- package/src/download/index.ts +44 -23
- package/src/download/media-download.ts +5 -3
- package/src/engine.test.ts +84 -3
- package/src/execution.ts +62 -46
- package/src/explore.ts +21 -90
- package/src/external-clis.yaml +0 -8
- package/src/external.test.ts +9 -0
- package/src/external.ts +12 -10
- package/src/generate.ts +4 -41
- package/src/hooks.test.ts +126 -0
- package/src/hooks.ts +90 -0
- package/src/interceptor.ts +73 -23
- package/src/main.ts +2 -0
- package/src/output.ts +14 -6
- package/src/pipeline/executor.ts +1 -1
- package/src/pipeline/steps/browser.ts +1 -3
- package/src/pipeline/steps/download.test.ts +136 -0
- package/src/pipeline/steps/download.ts +47 -34
- package/src/pipeline/steps/fetch.test.ts +179 -0
- package/src/pipeline/steps/fetch.ts +39 -23
- package/src/pipeline/steps/transform.ts +2 -6
- package/src/pipeline/template.test.ts +28 -0
- package/src/pipeline/template.ts +67 -79
- package/src/pipeline/transform.test.ts +20 -0
- package/src/plugin.test.ts +251 -3
- package/src/plugin.ts +265 -21
- package/src/record.ts +12 -84
- package/src/registry-api.ts +2 -0
- package/src/registry.ts +7 -4
- package/src/runtime.ts +14 -4
- package/src/snapshotFormatter.ts +43 -121
- package/src/utils.ts +39 -0
- package/src/validate.ts +3 -5
- package/src/yaml-schema.ts +28 -0
- package/tests/e2e/browser-auth.test.ts +25 -0
- package/tests/e2e/plugin-management.test.ts +137 -0
- package/tests/e2e/public-commands.test.ts +34 -1
- package/vitest.config.ts +19 -1
- package/.github/workflows/pkg-pr-new.yml +0 -30
- package/dist/clis/douban/shared.d.ts +0 -4
- package/dist/clis/douban/shared.js +0 -155
- package/src/clis/douban/shared.ts +0 -165
- /package/dist/clis/boss/{common.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/boss/{common.js → utils.js} +0 -0
- /package/dist/clis/doubao/{common.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/doubao/{common.js → utils.js} +0 -0
- /package/dist/clis/doubao-app/{common.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/doubao-app/{common.js → utils.js} +0 -0
- /package/dist/clis/jike/{shared.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/jike/{shared.js → utils.js} +0 -0
- /package/dist/clis/medium/{shared.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/sinablog/{shared.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/sinablog/{shared.js → utils.js} +0 -0
- /package/dist/clis/substack/{shared.d.ts → utils.d.ts} +0 -0
- /package/src/clis/boss/{common.ts → utils.ts} +0 -0
- /package/src/clis/doubao/{common.ts → utils.ts} +0 -0
- /package/src/clis/doubao-app/{common.ts → utils.ts} +0 -0
- /package/src/clis/jike/{shared.ts → utils.ts} +0 -0
- /package/src/clis/sinablog/{shared.ts → utils.ts} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { AuthRequiredError, CommandExecutionError, EmptyResultError, SelectorError } from '../../errors.js';
|
|
2
3
|
import type { IPage } from '../../types.js';
|
|
3
4
|
import { apiGet } from './utils.js';
|
|
4
5
|
|
|
@@ -13,7 +14,7 @@ cli({
|
|
|
13
14
|
],
|
|
14
15
|
columns: ['index', 'from', 'to', 'content'],
|
|
15
16
|
func: async (page: IPage | null, kwargs: any) => {
|
|
16
|
-
if (!page) throw new
|
|
17
|
+
if (!page) throw new CommandExecutionError('Browser session required for bilibili subtitle');
|
|
17
18
|
// 1. 先前往视频详情页 (建立有鉴权的 Session,且这里不需要加载完整个视频)
|
|
18
19
|
await page.goto(`https://www.bilibili.com/video/${kwargs.bvid}/`);
|
|
19
20
|
|
|
@@ -24,7 +25,7 @@ cli({
|
|
|
24
25
|
})()`);
|
|
25
26
|
|
|
26
27
|
if (!cid) {
|
|
27
|
-
throw new
|
|
28
|
+
throw new SelectorError('videoData.cid', '无法在页面中提取到当前视频的 CID,请检查页面是否正常加载。');
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
// 3. 在 Node 端使用 apiGet 获取带 Wbi 签名的字幕列表
|
|
@@ -35,12 +36,12 @@ cli({
|
|
|
35
36
|
});
|
|
36
37
|
|
|
37
38
|
if (payload.code !== 0) {
|
|
38
|
-
throw new
|
|
39
|
+
throw new CommandExecutionError(`获取视频播放信息失败: ${payload.message} (${payload.code})`);
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
const subtitles = payload.data?.subtitle?.subtitles || [];
|
|
42
43
|
if (subtitles.length === 0) {
|
|
43
|
-
throw new
|
|
44
|
+
throw new EmptyResultError('bilibili subtitle', '此视频没有发现外挂或智能字幕。');
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
// 4. 选择目标字幕语言
|
|
@@ -50,7 +51,7 @@ cli({
|
|
|
50
51
|
|
|
51
52
|
const targetSubUrl = target.subtitle_url;
|
|
52
53
|
if (!targetSubUrl || targetSubUrl === '') {
|
|
53
|
-
throw new
|
|
54
|
+
throw new AuthRequiredError('bilibili.com', '[风控拦截/未登录] 获取到的 subtitle_url 为空!请确保 CLI 已成功登录且风控未封锁此账号。');
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
const finalUrl = targetSubUrl.startsWith('//') ? 'https:' + targetSubUrl : targetSubUrl;
|
|
@@ -81,12 +82,12 @@ cli({
|
|
|
81
82
|
const items = await page.evaluate(fetchJs);
|
|
82
83
|
|
|
83
84
|
if (items?.error) {
|
|
84
|
-
throw new
|
|
85
|
+
throw new CommandExecutionError(`字幕获取失败: ${items.error}${items.text ? ' — ' + items.text : ''}`);
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
const finalItems = items?.data || [];
|
|
88
89
|
if (!Array.isArray(finalItems)) {
|
|
89
|
-
throw new
|
|
90
|
+
throw new CommandExecutionError('解析到的字幕列表对象不符合数组格式');
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
// 6. 数据映射
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type { IPage } from '../../types.js';
|
|
6
|
-
import { AuthRequiredError } from '../../errors.js';
|
|
6
|
+
import { AuthRequiredError, EmptyResultError } from '../../errors.js';
|
|
7
7
|
|
|
8
8
|
const MIXIN_KEY_ENC_TAB = [
|
|
9
9
|
46,47,18,2,53,8,23,32,15,50,10,31,58,3,45,35,27,43,5,49,
|
|
@@ -112,5 +112,5 @@ export async function resolveUid(page: IPage, input: string): Promise<string> {
|
|
|
112
112
|
});
|
|
113
113
|
const results = payload?.data?.result ?? [];
|
|
114
114
|
if (results.length > 0) return String(results[0].mid);
|
|
115
|
-
throw new
|
|
115
|
+
throw new EmptyResultError(`bilibili user search: ${input}`, 'User may not exist or username may have changed.');
|
|
116
116
|
}
|
package/src/clis/boss/chatmsg.ts
CHANGED
package/src/clis/boss/detail.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* BOSS直聘 job detail — fetch full job posting details via browser cookie API.
|
|
3
3
|
*/
|
|
4
4
|
import { cli, Strategy } from '../../registry.js';
|
|
5
|
-
import { requirePage, navigateTo, bossFetch, verbose } from './
|
|
5
|
+
import { requirePage, navigateTo, bossFetch, verbose } from './utils.js';
|
|
6
6
|
|
|
7
7
|
cli({
|
|
8
8
|
site: 'boss',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* BOSS直聘 exchange — request phone/wechat exchange with a candidate.
|
|
3
3
|
*/
|
|
4
4
|
import { cli, Strategy } from '../../registry.js';
|
|
5
|
-
import { requirePage, navigateToChat, bossFetch, findFriendByUid, verbose } from './
|
|
5
|
+
import { requirePage, navigateToChat, bossFetch, findFriendByUid, verbose } from './utils.js';
|
|
6
6
|
|
|
7
7
|
cli({
|
|
8
8
|
site: 'boss',
|
package/src/clis/boss/greet.ts
CHANGED
package/src/clis/boss/invite.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* BOSS直聘 invite — send interview invitation to a candidate.
|
|
3
3
|
*/
|
|
4
4
|
import { cli, Strategy } from '../../registry.js';
|
|
5
|
-
import { requirePage, navigateToChat, bossFetch, findFriendByUid, verbose } from './
|
|
5
|
+
import { requirePage, navigateToChat, bossFetch, findFriendByUid, verbose } from './utils.js';
|
|
6
6
|
|
|
7
7
|
cli({
|
|
8
8
|
site: 'boss',
|
package/src/clis/boss/joblist.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* BOSS直聘 job list — list my published jobs via boss API.
|
|
3
3
|
*/
|
|
4
4
|
import { cli, Strategy } from '../../registry.js';
|
|
5
|
-
import { requirePage, navigateToChat, bossFetch, verbose } from './
|
|
5
|
+
import { requirePage, navigateToChat, bossFetch, verbose } from './utils.js';
|
|
6
6
|
|
|
7
7
|
cli({
|
|
8
8
|
site: 'boss',
|
package/src/clis/boss/mark.ts
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* 6=已交换微信, 7=不合适, 8=牛人发起, 11=收藏
|
|
7
7
|
*/
|
|
8
8
|
import { cli, Strategy } from '../../registry.js';
|
|
9
|
-
import { requirePage, navigateToChat, bossFetch, findFriendByUid, verbose } from './
|
|
9
|
+
import { requirePage, navigateToChat, bossFetch, findFriendByUid, verbose } from './utils.js';
|
|
10
|
+
import { ArgumentError, EmptyResultError } from '../../errors.js';
|
|
10
11
|
|
|
11
12
|
const LABEL_MAP: Record<string, number> = {
|
|
12
13
|
'新招呼': 1, '沟通中': 2, '已约面': 3, '已获取简历': 4,
|
|
@@ -44,7 +45,7 @@ cli({
|
|
|
44
45
|
if (entry) {
|
|
45
46
|
labelId = entry[1];
|
|
46
47
|
} else {
|
|
47
|
-
throw new
|
|
48
|
+
throw new ArgumentError(`未知标签: ${labelInput}。可用标签: ${Object.keys(LABEL_MAP).join(', ')}`);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -53,7 +54,7 @@ cli({
|
|
|
53
54
|
await navigateToChat(page);
|
|
54
55
|
|
|
55
56
|
const friend = await findFriendByUid(page, kwargs.uid, { checkGreetList: true });
|
|
56
|
-
if (!friend) throw new
|
|
57
|
+
if (!friend) throw new EmptyResultError('boss candidate search');
|
|
57
58
|
|
|
58
59
|
const friendName = friend.name || '候选人';
|
|
59
60
|
const action = remove ? 'deleteMark' : 'addMark';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* BOSS直聘 recommend — view recommended candidates (新招呼/greet sort list).
|
|
3
3
|
*/
|
|
4
4
|
import { cli, Strategy } from '../../registry.js';
|
|
5
|
-
import { requirePage, navigateToChat, bossFetch, fetchRecommendList, verbose } from './
|
|
5
|
+
import { requirePage, navigateToChat, bossFetch, fetchRecommendList, verbose } from './utils.js';
|
|
6
6
|
|
|
7
7
|
cli({
|
|
8
8
|
site: 'boss',
|
package/src/clis/boss/resume.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* .position-content → job being discussed + expectation
|
|
11
11
|
*/
|
|
12
12
|
import { cli, Strategy } from '../../registry.js';
|
|
13
|
-
import { requirePage, navigateToChat, findFriendByUid, clickCandidateInList } from './
|
|
13
|
+
import { requirePage, navigateToChat, findFriendByUid, clickCandidateInList } from './utils.js';
|
|
14
14
|
|
|
15
15
|
cli({
|
|
16
16
|
site: 'boss',
|
package/src/clis/boss/search.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* BOSS直聘 job search — browser cookie API.
|
|
3
3
|
*/
|
|
4
4
|
import { cli, Strategy } from '../../registry.js';
|
|
5
|
-
import { requirePage, navigateTo, bossFetch, assertOk, verbose } from './
|
|
5
|
+
import { requirePage, navigateTo, bossFetch, assertOk, verbose } from './utils.js';
|
|
6
6
|
|
|
7
7
|
/** City name → BOSS Zhipin city code mapping */
|
|
8
8
|
const CITY_CODES: Record<string, string> = {
|
package/src/clis/boss/send.ts
CHANGED
|
@@ -8,7 +8,8 @@ import { cli, Strategy } from '../../registry.js';
|
|
|
8
8
|
import {
|
|
9
9
|
requirePage, navigateToChat, findFriendByUid,
|
|
10
10
|
clickCandidateInList, typeAndSendMessage,
|
|
11
|
-
} from './
|
|
11
|
+
} from './utils.js';
|
|
12
|
+
import { EmptyResultError, SelectorError } from '../../errors.js';
|
|
12
13
|
|
|
13
14
|
cli({
|
|
14
15
|
site: 'boss',
|
|
@@ -29,21 +30,21 @@ cli({
|
|
|
29
30
|
await navigateToChat(page, 3);
|
|
30
31
|
|
|
31
32
|
const friend = await findFriendByUid(page, kwargs.uid, { maxPages: 5 });
|
|
32
|
-
if (!friend) throw new
|
|
33
|
+
if (!friend) throw new EmptyResultError('boss candidate search', '请确认 uid 是否正确');
|
|
33
34
|
|
|
34
35
|
const numericUid = friend.uid;
|
|
35
36
|
const friendName = friend.name || '候选人';
|
|
36
37
|
|
|
37
38
|
const clicked = await clickCandidateInList(page, numericUid);
|
|
38
39
|
if (!clicked) {
|
|
39
|
-
throw new
|
|
40
|
+
throw new SelectorError('聊天列表中的用户', '请确认聊天列表中有此人');
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
await page.wait({ time: 2 });
|
|
43
44
|
|
|
44
45
|
const sent = await typeAndSendMessage(page, kwargs.text);
|
|
45
46
|
if (!sent) {
|
|
46
|
-
throw new
|
|
47
|
+
throw new SelectorError('消息输入框', '聊天页面 UI 可能已改变');
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
await page.wait({ time: 1 });
|
package/src/clis/boss/stats.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* BOSS直聘 stats — job statistics overview.
|
|
3
3
|
*/
|
|
4
4
|
import { cli, Strategy } from '../../registry.js';
|
|
5
|
-
import { requirePage, navigateToChat, bossFetch, fetchFriendList, verbose } from './
|
|
5
|
+
import { requirePage, navigateToChat, bossFetch, fetchFriendList, verbose } from './utils.js';
|
|
6
6
|
|
|
7
7
|
cli({
|
|
8
8
|
site: 'boss',
|
package/src/clis/chatgpt/ask.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execSync, spawnSync } from 'node:child_process';
|
|
2
2
|
import { cli, Strategy } from '../../registry.js';
|
|
3
|
+
import { ConfigError } from '../../errors.js';
|
|
3
4
|
import type { IPage } from '../../types.js';
|
|
4
5
|
import { getVisibleChatMessages } from './ax.js';
|
|
5
6
|
|
|
@@ -16,6 +17,10 @@ export const askCommand = cli({
|
|
|
16
17
|
],
|
|
17
18
|
columns: ['Role', 'Text'],
|
|
18
19
|
func: async (page: IPage | null, kwargs: any) => {
|
|
20
|
+
if (process.platform !== 'darwin') {
|
|
21
|
+
throw new ConfigError('ChatGPT Desktop integration requires macOS (osascript is not available on this platform)');
|
|
22
|
+
}
|
|
23
|
+
|
|
19
24
|
const text = kwargs.text as string;
|
|
20
25
|
const timeout = parseInt(kwargs.timeout as string, 10) || 30;
|
|
21
26
|
|
package/src/clis/chatgpt/new.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { cli, Strategy } from '../../registry.js';
|
|
3
|
+
import { ConfigError, getErrorMessage } from '../../errors.js';
|
|
3
4
|
import type { IPage } from '../../types.js';
|
|
4
5
|
|
|
5
6
|
export const newCommand = cli({
|
|
@@ -12,13 +13,17 @@ export const newCommand = cli({
|
|
|
12
13
|
args: [],
|
|
13
14
|
columns: ['Status'],
|
|
14
15
|
func: async (page: IPage | null) => {
|
|
16
|
+
if (process.platform !== 'darwin') {
|
|
17
|
+
throw new ConfigError('ChatGPT Desktop integration requires macOS (osascript is not available on this platform)');
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
try {
|
|
16
21
|
execSync("osascript -e 'tell application \"ChatGPT\" to activate'");
|
|
17
22
|
execSync("osascript -e 'delay 0.5'");
|
|
18
23
|
execSync("osascript -e 'tell application \"System Events\" to keystroke \"n\" using command down'");
|
|
19
24
|
return [{ Status: 'Success' }];
|
|
20
|
-
} catch (err
|
|
21
|
-
return [{ Status: "Error: " + err
|
|
25
|
+
} catch (err) {
|
|
26
|
+
return [{ Status: "Error: " + getErrorMessage(err) }];
|
|
22
27
|
}
|
|
23
28
|
},
|
|
24
29
|
});
|
package/src/clis/chatgpt/read.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { cli, Strategy } from '../../registry.js';
|
|
3
|
+
import { CommandExecutionError, ConfigError, getErrorMessage } from '../../errors.js';
|
|
3
4
|
import type { IPage } from '../../types.js';
|
|
4
5
|
import { getVisibleChatMessages } from './ax.js';
|
|
5
6
|
|
|
@@ -13,6 +14,10 @@ export const readCommand = cli({
|
|
|
13
14
|
args: [],
|
|
14
15
|
columns: ['Role', 'Text'],
|
|
15
16
|
func: async (page: IPage | null) => {
|
|
17
|
+
if (process.platform !== 'darwin') {
|
|
18
|
+
throw new ConfigError('ChatGPT Desktop integration requires macOS (osascript is not available on this platform)');
|
|
19
|
+
}
|
|
20
|
+
|
|
16
21
|
try {
|
|
17
22
|
execSync("osascript -e 'tell application \"ChatGPT\" to activate'");
|
|
18
23
|
execSync("osascript -e 'delay 0.3'");
|
|
@@ -23,8 +28,8 @@ export const readCommand = cli({
|
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
return [{ Role: 'Assistant', Text: messages[messages.length - 1] }];
|
|
26
|
-
} catch (err
|
|
27
|
-
throw new
|
|
31
|
+
} catch (err) {
|
|
32
|
+
throw new CommandExecutionError("Failed to read from ChatGPT: " + getErrorMessage(err));
|
|
28
33
|
}
|
|
29
34
|
},
|
|
30
35
|
});
|
package/src/clis/chatgpt/send.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { execSync, spawnSync } from 'node:child_process';
|
|
2
2
|
import { cli, Strategy } from '../../registry.js';
|
|
3
3
|
import type { IPage } from '../../types.js';
|
|
4
|
+
import { getErrorMessage } from '../../errors.js';
|
|
4
5
|
|
|
5
6
|
export const sendCommand = cli({
|
|
6
7
|
site: 'chatgpt',
|
|
@@ -41,8 +42,8 @@ export const sendCommand = cli({
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
return [{ Status: 'Success' }];
|
|
44
|
-
} catch (err
|
|
45
|
-
return [{ Status: "Error: " + err
|
|
45
|
+
} catch (err) {
|
|
46
|
+
return [{ Status: "Error: " + getErrorMessage(err) }];
|
|
46
47
|
}
|
|
47
48
|
},
|
|
48
49
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { cli, Strategy } from '../../registry.js';
|
|
3
|
+
import { CommandExecutionError, ConfigError } from '../../errors.js';
|
|
3
4
|
import type { IPage } from '../../types.js';
|
|
4
5
|
|
|
5
6
|
export const statusCommand = cli({
|
|
@@ -12,11 +13,15 @@ export const statusCommand = cli({
|
|
|
12
13
|
args: [],
|
|
13
14
|
columns: ['Status'],
|
|
14
15
|
func: async (page: IPage | null) => {
|
|
16
|
+
if (process.platform !== 'darwin') {
|
|
17
|
+
throw new ConfigError('ChatGPT Desktop integration requires macOS (osascript is not available on this platform)');
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
try {
|
|
16
21
|
const output = execSync("osascript -e 'application \"ChatGPT\" is running'", { encoding: 'utf-8' }).trim();
|
|
17
22
|
return [{ Status: output === 'true' ? 'Running' : 'Stopped' }];
|
|
18
23
|
} catch {
|
|
19
|
-
|
|
24
|
+
throw new CommandExecutionError('Error querying ChatGPT application state');
|
|
20
25
|
}
|
|
21
26
|
},
|
|
22
27
|
});
|
package/src/clis/chatwise/ask.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { SelectorError } from '../../errors.js';
|
|
2
3
|
import type { IPage } from '../../types.js';
|
|
4
|
+
import { chatwiseRequiredEnv } from './shared.js';
|
|
3
5
|
|
|
4
6
|
export const askCommand = cli({
|
|
5
7
|
site: 'chatwise',
|
|
@@ -8,6 +10,7 @@ export const askCommand = cli({
|
|
|
8
10
|
domain: 'localhost',
|
|
9
11
|
strategy: Strategy.UI,
|
|
10
12
|
browser: true,
|
|
13
|
+
requiredEnv: chatwiseRequiredEnv,
|
|
11
14
|
args: [
|
|
12
15
|
{ name: 'text', required: true, positional: true, help: 'Prompt to send' },
|
|
13
16
|
{ name: 'timeout', required: false, help: 'Max seconds to wait (default: 30)', default: '30' },
|
|
@@ -26,14 +29,14 @@ export const askCommand = cli({
|
|
|
26
29
|
`);
|
|
27
30
|
|
|
28
31
|
// Send message
|
|
29
|
-
await page.evaluate(`
|
|
32
|
+
const injected = await page.evaluate(`
|
|
30
33
|
(function(text) {
|
|
31
34
|
let composer = document.querySelector('textarea');
|
|
32
35
|
if (!composer) {
|
|
33
36
|
const editables = Array.from(document.querySelectorAll('[contenteditable="true"]'));
|
|
34
37
|
composer = editables.length > 0 ? editables[editables.length - 1] : null;
|
|
35
38
|
}
|
|
36
|
-
if (!composer)
|
|
39
|
+
if (!composer) return false;
|
|
37
40
|
composer.focus();
|
|
38
41
|
if (composer.tagName === 'TEXTAREA') {
|
|
39
42
|
const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
|
|
@@ -42,8 +45,10 @@ export const askCommand = cli({
|
|
|
42
45
|
} else {
|
|
43
46
|
document.execCommand('insertText', false, text);
|
|
44
47
|
}
|
|
48
|
+
return true;
|
|
45
49
|
})(${JSON.stringify(text)})
|
|
46
50
|
`);
|
|
51
|
+
if (!injected) throw new SelectorError('ChatWise input element');
|
|
47
52
|
|
|
48
53
|
await page.wait(0.5);
|
|
49
54
|
await page.pressKey('Enter');
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import { cli, Strategy } from '../../registry.js';
|
|
3
3
|
import type { IPage } from '../../types.js';
|
|
4
|
+
import { chatwiseRequiredEnv } from './shared.js';
|
|
4
5
|
|
|
5
6
|
export const exportCommand = cli({
|
|
6
7
|
site: 'chatwise',
|
|
@@ -9,6 +10,7 @@ export const exportCommand = cli({
|
|
|
9
10
|
domain: 'localhost',
|
|
10
11
|
strategy: Strategy.UI,
|
|
11
12
|
browser: true,
|
|
13
|
+
requiredEnv: chatwiseRequiredEnv,
|
|
12
14
|
args: [
|
|
13
15
|
{ name: 'output', required: false, help: 'Output file (default: /tmp/chatwise-export.md)' },
|
|
14
16
|
],
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cli, Strategy } from '../../registry.js';
|
|
2
2
|
import type { IPage } from '../../types.js';
|
|
3
|
+
import { chatwiseRequiredEnv } from './shared.js';
|
|
3
4
|
|
|
4
5
|
export const historyCommand = cli({
|
|
5
6
|
site: 'chatwise',
|
|
@@ -8,6 +9,7 @@ export const historyCommand = cli({
|
|
|
8
9
|
domain: 'localhost',
|
|
9
10
|
strategy: Strategy.UI,
|
|
10
11
|
browser: true,
|
|
12
|
+
requiredEnv: chatwiseRequiredEnv,
|
|
11
13
|
args: [],
|
|
12
14
|
columns: ['Index', 'Title'],
|
|
13
15
|
func: async (page: IPage) => {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { SelectorError } from '../../errors.js';
|
|
2
3
|
import type { IPage } from '../../types.js';
|
|
4
|
+
import { chatwiseRequiredEnv } from './shared.js';
|
|
3
5
|
|
|
4
6
|
export const modelCommand = cli({
|
|
5
7
|
site: 'chatwise',
|
|
@@ -8,6 +10,7 @@ export const modelCommand = cli({
|
|
|
8
10
|
domain: 'localhost',
|
|
9
11
|
strategy: Strategy.UI,
|
|
10
12
|
browser: true,
|
|
13
|
+
requiredEnv: chatwiseRequiredEnv,
|
|
11
14
|
args: [
|
|
12
15
|
{ name: 'model-name', required: false, positional: true, help: 'Model to switch to (e.g. gpt-4, claude-3)' },
|
|
13
16
|
],
|
|
@@ -44,7 +47,7 @@ export const modelCommand = cli({
|
|
|
44
47
|
return [{ Status: 'Active', Model: currentModel }];
|
|
45
48
|
} else {
|
|
46
49
|
// Try to switch model
|
|
47
|
-
await page.evaluate(`
|
|
50
|
+
const opened = await page.evaluate(`
|
|
48
51
|
(function(target) {
|
|
49
52
|
const selectors = [
|
|
50
53
|
'[class*="model"]',
|
|
@@ -54,11 +57,12 @@ export const modelCommand = cli({
|
|
|
54
57
|
|
|
55
58
|
for (const sel of selectors) {
|
|
56
59
|
const el = document.querySelector(sel);
|
|
57
|
-
if (el) { el.click(); return; }
|
|
60
|
+
if (el) { el.click(); return true; }
|
|
58
61
|
}
|
|
59
|
-
|
|
62
|
+
return false;
|
|
60
63
|
})(${JSON.stringify(desiredModel)})
|
|
61
64
|
`);
|
|
65
|
+
if (!opened) throw new SelectorError('ChatWise model selector');
|
|
62
66
|
|
|
63
67
|
await page.wait(0.5);
|
|
64
68
|
|
package/src/clis/chatwise/new.ts
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { makeNewCommand } from '../_shared/desktop-commands.js';
|
|
2
|
+
import { chatwiseRequiredEnv } from './shared.js';
|
|
3
3
|
|
|
4
|
-
export const newCommand =
|
|
5
|
-
site: 'chatwise',
|
|
6
|
-
name: 'new',
|
|
7
|
-
description: 'Start a new conversation in ChatWise',
|
|
8
|
-
domain: 'localhost',
|
|
9
|
-
strategy: Strategy.UI,
|
|
10
|
-
browser: true,
|
|
11
|
-
args: [],
|
|
12
|
-
columns: ['Status'],
|
|
13
|
-
func: async (page: IPage) => {
|
|
14
|
-
// ChatWise uses standard Electron shortcuts
|
|
15
|
-
const isMac = process.platform === 'darwin';
|
|
16
|
-
await page.pressKey(isMac ? 'Meta+N' : 'Control+N');
|
|
17
|
-
await page.wait(1);
|
|
18
|
-
|
|
19
|
-
return [{ Status: 'Success' }];
|
|
20
|
-
},
|
|
21
|
-
});
|
|
4
|
+
export const newCommand = makeNewCommand('chatwise', 'ChatWise conversation', { requiredEnv: chatwiseRequiredEnv });
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cli, Strategy } from '../../registry.js';
|
|
2
2
|
import type { IPage } from '../../types.js';
|
|
3
|
+
import { chatwiseRequiredEnv } from './shared.js';
|
|
3
4
|
|
|
4
5
|
export const readCommand = cli({
|
|
5
6
|
site: 'chatwise',
|
|
@@ -8,6 +9,7 @@ export const readCommand = cli({
|
|
|
8
9
|
domain: 'localhost',
|
|
9
10
|
strategy: Strategy.UI,
|
|
10
11
|
browser: true,
|
|
12
|
+
requiredEnv: chatwiseRequiredEnv,
|
|
11
13
|
args: [],
|
|
12
14
|
columns: ['Content'],
|
|
13
15
|
func: async (page: IPage) => {
|
|
@@ -1,33 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import type { IPage } from '../../types.js';
|
|
1
|
+
import { makeScreenshotCommand } from '../_shared/desktop-commands.js';
|
|
2
|
+
import { chatwiseRequiredEnv } from './shared.js';
|
|
4
3
|
|
|
5
|
-
export const screenshotCommand =
|
|
6
|
-
site: 'chatwise',
|
|
7
|
-
name: 'screenshot',
|
|
8
|
-
description: 'Capture a snapshot of the current ChatWise window (DOM + Accessibility tree)',
|
|
9
|
-
domain: 'localhost',
|
|
10
|
-
strategy: Strategy.UI,
|
|
11
|
-
browser: true,
|
|
12
|
-
args: [
|
|
13
|
-
{ name: 'output', required: false, help: 'Output file path (default: /tmp/chatwise-snapshot)' },
|
|
14
|
-
],
|
|
15
|
-
columns: ['Status', 'File'],
|
|
16
|
-
func: async (page: IPage, kwargs: any) => {
|
|
17
|
-
const basePath = (kwargs.output as string) || '/tmp/chatwise-snapshot';
|
|
18
|
-
|
|
19
|
-
const snap = await page.snapshot({ compact: true });
|
|
20
|
-
const html = await page.evaluate('document.documentElement.outerHTML');
|
|
21
|
-
|
|
22
|
-
const htmlPath = basePath + '-dom.html';
|
|
23
|
-
const snapPath = basePath + '-a11y.txt';
|
|
24
|
-
|
|
25
|
-
fs.writeFileSync(htmlPath, html);
|
|
26
|
-
fs.writeFileSync(snapPath, typeof snap === 'string' ? snap : JSON.stringify(snap, null, 2));
|
|
27
|
-
|
|
28
|
-
return [
|
|
29
|
-
{ Status: 'Success', File: htmlPath },
|
|
30
|
-
{ Status: 'Success', File: snapPath },
|
|
31
|
-
];
|
|
32
|
-
},
|
|
33
|
-
});
|
|
4
|
+
export const screenshotCommand = makeScreenshotCommand('chatwise', 'ChatWise', { requiredEnv: chatwiseRequiredEnv });
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { SelectorError } from '../../errors.js';
|
|
2
3
|
import type { IPage } from '../../types.js';
|
|
4
|
+
import { chatwiseRequiredEnv } from './shared.js';
|
|
3
5
|
|
|
4
6
|
export const sendCommand = cli({
|
|
5
7
|
site: 'chatwise',
|
|
@@ -8,12 +10,13 @@ export const sendCommand = cli({
|
|
|
8
10
|
domain: 'localhost',
|
|
9
11
|
strategy: Strategy.UI,
|
|
10
12
|
browser: true,
|
|
13
|
+
requiredEnv: chatwiseRequiredEnv,
|
|
11
14
|
args: [{ name: 'text', required: true, positional: true, help: 'Message to send' }],
|
|
12
15
|
columns: ['Status', 'InjectedText'],
|
|
13
16
|
func: async (page: IPage, kwargs: any) => {
|
|
14
17
|
const text = kwargs.text as string;
|
|
15
18
|
|
|
16
|
-
await page.evaluate(`
|
|
19
|
+
const injected = await page.evaluate(`
|
|
17
20
|
(function(text) {
|
|
18
21
|
// ChatWise input can be textarea or contenteditable
|
|
19
22
|
let composer = document.querySelector('textarea');
|
|
@@ -22,7 +25,7 @@ export const sendCommand = cli({
|
|
|
22
25
|
composer = editables.length > 0 ? editables[editables.length - 1] : null;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
if (!composer)
|
|
28
|
+
if (!composer) return false;
|
|
26
29
|
|
|
27
30
|
composer.focus();
|
|
28
31
|
|
|
@@ -34,8 +37,10 @@ export const sendCommand = cli({
|
|
|
34
37
|
} else {
|
|
35
38
|
document.execCommand('insertText', false, text);
|
|
36
39
|
}
|
|
40
|
+
return true;
|
|
37
41
|
})(${JSON.stringify(text)})
|
|
38
42
|
`);
|
|
43
|
+
if (!injected) throw new SelectorError('ChatWise input element');
|
|
39
44
|
|
|
40
45
|
await page.wait(0.5);
|
|
41
46
|
await page.pressKey('Enter');
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RequiredEnv } from '../../registry.js';
|
|
2
|
+
|
|
3
|
+
export const chatwiseRequiredEnv: RequiredEnv[] = [
|
|
4
|
+
{
|
|
5
|
+
name: 'OPENCLI_CDP_ENDPOINT',
|
|
6
|
+
help: 'Launch ChatWise with --remote-debugging-port=9228, then run OPENCLI_CDP_ENDPOINT=http://127.0.0.1:9228 opencli chatwise status. If you use a local proxy, also set NO_PROXY=127.0.0.1,localhost.',
|
|
7
|
+
},
|
|
8
|
+
];
|