@jackwener/opencli 1.5.5 → 1.5.7
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/CHANGELOG.md +26 -0
- package/README.md +31 -4
- package/README.zh-CN.md +40 -5
- package/SKILL.md +1 -1
- package/dist/browser/cdp.d.ts +1 -0
- package/dist/browser/cdp.js +30 -27
- package/dist/browser/daemon-client.d.ts +11 -1
- package/dist/browser/daemon-client.js +3 -0
- package/dist/browser/dom-helpers.js +1 -0
- package/dist/browser/dom-helpers.test.js +14 -1
- package/dist/browser/mcp.js +18 -13
- package/dist/browser/page.d.ts +6 -0
- package/dist/browser/page.js +37 -2
- package/dist/browser/page.test.d.ts +1 -0
- package/dist/browser/page.test.js +44 -0
- package/dist/browser/stealth.js +198 -0
- package/dist/browser/stealth.test.d.ts +1 -0
- package/dist/browser/stealth.test.js +134 -0
- package/dist/browser.test.js +1 -1
- package/dist/build-manifest.d.ts +1 -0
- package/dist/build-manifest.js +5 -1
- package/dist/build-manifest.test.js +2 -0
- package/dist/cli-manifest.json +1821 -252
- package/dist/cli.js +20 -3
- package/dist/clis/antigravity/serve.d.ts +1 -1
- package/dist/clis/antigravity/serve.js +5 -8
- package/dist/clis/band/bands.d.ts +1 -0
- package/dist/clis/band/bands.js +72 -0
- package/dist/clis/band/mentions.d.ts +1 -0
- package/dist/clis/band/mentions.js +127 -0
- package/dist/clis/band/post.d.ts +1 -0
- package/dist/clis/band/post.js +175 -0
- package/dist/clis/band/posts.d.ts +1 -0
- package/dist/clis/band/posts.js +94 -0
- package/dist/clis/bilibili/subtitle.js +4 -0
- package/dist/clis/bilibili/subtitle.test.d.ts +1 -0
- package/dist/clis/bilibili/subtitle.test.js +48 -0
- package/dist/clis/chatwise/ask.js +0 -2
- package/dist/clis/chatwise/export.js +0 -2
- package/dist/clis/chatwise/history.js +0 -2
- package/dist/clis/chatwise/model.js +0 -2
- package/dist/clis/chatwise/new.js +1 -2
- package/dist/clis/chatwise/read.js +0 -2
- package/dist/clis/chatwise/screenshot.js +1 -2
- package/dist/clis/chatwise/send.js +0 -2
- package/dist/clis/chatwise/status.js +1 -2
- package/dist/clis/ctrip/search.d.ts +13 -0
- package/dist/clis/ctrip/search.js +73 -48
- package/dist/clis/ctrip/search.test.d.ts +1 -0
- package/dist/clis/ctrip/search.test.js +64 -0
- package/dist/clis/doubao/detail.d.ts +1 -0
- package/dist/clis/doubao/detail.js +33 -0
- package/dist/clis/doubao/detail.test.d.ts +1 -0
- package/dist/clis/doubao/detail.test.js +42 -0
- package/dist/clis/doubao/history.d.ts +1 -0
- package/dist/clis/doubao/history.js +28 -0
- package/dist/clis/doubao/history.test.d.ts +1 -0
- package/dist/clis/doubao/history.test.js +37 -0
- package/dist/clis/doubao/meeting-summary.d.ts +1 -0
- package/dist/clis/doubao/meeting-summary.js +39 -0
- package/dist/clis/doubao/meeting-transcript.d.ts +1 -0
- package/dist/clis/doubao/meeting-transcript.js +36 -0
- package/dist/clis/doubao/utils.d.ts +27 -0
- package/dist/clis/doubao/utils.js +317 -0
- package/dist/clis/doubao/utils.test.d.ts +1 -0
- package/dist/clis/doubao/utils.test.js +24 -0
- package/dist/clis/douyin/_shared/public-api.d.ts +33 -0
- package/dist/clis/douyin/_shared/public-api.js +29 -0
- package/dist/clis/douyin/_shared/sts2.js +8 -2
- package/dist/clis/douyin/_shared/sts2.test.d.ts +1 -0
- package/dist/clis/douyin/_shared/sts2.test.js +27 -0
- package/dist/clis/douyin/activities.js +4 -2
- package/dist/clis/douyin/activities.test.js +34 -1
- package/dist/clis/douyin/collections.js +1 -1
- package/dist/clis/douyin/collections.test.js +24 -2
- package/dist/clis/douyin/draft.d.ts +8 -11
- package/dist/clis/douyin/draft.js +302 -185
- package/dist/clis/douyin/draft.test.d.ts +1 -1
- package/dist/clis/douyin/draft.test.js +357 -2
- package/dist/clis/douyin/hashtag.js +9 -2
- package/dist/clis/douyin/hashtag.test.js +35 -2
- package/dist/clis/douyin/profile.js +1 -1
- package/dist/clis/douyin/profile.test.js +36 -1
- package/dist/clis/douyin/user-videos.d.ts +5 -0
- package/dist/clis/douyin/user-videos.js +74 -0
- package/dist/clis/douyin/user-videos.test.d.ts +1 -0
- package/dist/clis/douyin/user-videos.test.js +108 -0
- package/dist/clis/douyin/videos.js +22 -5
- package/dist/clis/douyin/videos.test.js +45 -2
- package/dist/clis/facebook/search.test.d.ts +5 -0
- package/dist/clis/facebook/search.test.js +60 -0
- package/dist/clis/facebook/search.yaml +4 -3
- package/dist/clis/instagram/download.d.ts +16 -0
- package/dist/clis/instagram/download.js +225 -0
- package/dist/clis/instagram/download.test.d.ts +1 -0
- package/dist/clis/instagram/download.test.js +118 -0
- package/dist/clis/notebooklm/bind-current.d.ts +1 -0
- package/dist/clis/notebooklm/bind-current.js +29 -0
- package/dist/clis/notebooklm/bind-current.test.d.ts +1 -0
- package/dist/clis/notebooklm/bind-current.test.js +35 -0
- package/dist/clis/notebooklm/binding.test.d.ts +1 -0
- package/dist/clis/notebooklm/binding.test.js +44 -0
- package/dist/clis/notebooklm/compat.test.d.ts +3 -0
- package/dist/clis/notebooklm/compat.test.js +16 -0
- package/dist/clis/notebooklm/current.d.ts +1 -0
- package/dist/clis/notebooklm/current.js +28 -0
- package/dist/clis/notebooklm/get.d.ts +1 -0
- package/dist/clis/notebooklm/get.js +37 -0
- package/dist/clis/notebooklm/history.d.ts +1 -0
- package/dist/clis/notebooklm/history.js +25 -0
- package/dist/clis/notebooklm/history.test.d.ts +1 -0
- package/dist/clis/notebooklm/history.test.js +58 -0
- package/dist/clis/notebooklm/list.d.ts +1 -0
- package/dist/clis/notebooklm/list.js +35 -0
- package/dist/clis/notebooklm/note-list.d.ts +1 -0
- package/dist/clis/notebooklm/note-list.js +28 -0
- package/dist/clis/notebooklm/note-list.test.d.ts +1 -0
- package/dist/clis/notebooklm/note-list.test.js +56 -0
- package/dist/clis/notebooklm/notes-get.d.ts +1 -0
- package/dist/clis/notebooklm/notes-get.js +47 -0
- package/dist/clis/notebooklm/notes-get.test.d.ts +1 -0
- package/dist/clis/notebooklm/notes-get.test.js +72 -0
- package/dist/clis/notebooklm/rpc.d.ts +36 -0
- package/dist/clis/notebooklm/rpc.js +189 -0
- package/dist/clis/notebooklm/rpc.test.d.ts +1 -0
- package/dist/clis/notebooklm/rpc.test.js +105 -0
- package/dist/clis/notebooklm/shared.d.ts +87 -0
- package/dist/clis/notebooklm/shared.js +3 -0
- package/dist/clis/notebooklm/source-fulltext.d.ts +1 -0
- package/dist/clis/notebooklm/source-fulltext.js +44 -0
- package/dist/clis/notebooklm/source-fulltext.test.d.ts +1 -0
- package/dist/clis/notebooklm/source-fulltext.test.js +106 -0
- package/dist/clis/notebooklm/source-get.d.ts +1 -0
- package/dist/clis/notebooklm/source-get.js +40 -0
- package/dist/clis/notebooklm/source-get.test.d.ts +1 -0
- package/dist/clis/notebooklm/source-get.test.js +84 -0
- package/dist/clis/notebooklm/source-guide.d.ts +1 -0
- package/dist/clis/notebooklm/source-guide.js +44 -0
- package/dist/clis/notebooklm/source-guide.test.d.ts +1 -0
- package/dist/clis/notebooklm/source-guide.test.js +104 -0
- package/dist/clis/notebooklm/source-list.d.ts +1 -0
- package/dist/clis/notebooklm/source-list.js +30 -0
- package/dist/clis/notebooklm/status.d.ts +1 -0
- package/dist/clis/notebooklm/status.js +31 -0
- package/dist/clis/notebooklm/summary.d.ts +1 -0
- package/dist/clis/notebooklm/summary.js +30 -0
- package/dist/clis/notebooklm/summary.test.d.ts +1 -0
- package/dist/clis/notebooklm/summary.test.js +78 -0
- package/dist/clis/notebooklm/utils.d.ts +37 -0
- package/dist/clis/notebooklm/utils.js +739 -0
- package/dist/clis/notebooklm/utils.test.d.ts +1 -0
- package/dist/clis/notebooklm/utils.test.js +390 -0
- package/dist/clis/ones/common.d.ts +32 -0
- package/dist/clis/ones/common.js +144 -0
- package/dist/clis/ones/enrich-tasks.d.ts +5 -0
- package/dist/clis/ones/enrich-tasks.js +37 -0
- package/dist/clis/ones/login.d.ts +1 -0
- package/dist/clis/ones/login.js +80 -0
- package/dist/clis/ones/logout.d.ts +1 -0
- package/dist/clis/ones/logout.js +17 -0
- package/dist/clis/ones/me.d.ts +1 -0
- package/dist/clis/ones/me.js +30 -0
- package/dist/clis/ones/my-tasks.d.ts +1 -0
- package/dist/clis/ones/my-tasks.js +120 -0
- package/dist/clis/ones/resolve-labels.d.ts +10 -0
- package/dist/clis/ones/resolve-labels.js +64 -0
- package/dist/clis/ones/task-helpers.d.ts +29 -0
- package/dist/clis/ones/task-helpers.js +212 -0
- package/dist/clis/ones/task-helpers.test.d.ts +1 -0
- package/dist/clis/ones/task-helpers.test.js +12 -0
- package/dist/clis/ones/task.d.ts +1 -0
- package/dist/clis/ones/task.js +66 -0
- package/dist/clis/ones/tasks.d.ts +1 -0
- package/dist/clis/ones/tasks.js +79 -0
- package/dist/clis/ones/token-info.d.ts +1 -0
- package/dist/clis/ones/token-info.js +42 -0
- package/dist/clis/ones/worklog.d.ts +11 -0
- package/dist/clis/ones/worklog.js +267 -0
- package/dist/clis/ones/worklog.test.d.ts +1 -0
- package/dist/clis/ones/worklog.test.js +20 -0
- package/dist/clis/spotify/spotify.d.ts +1 -0
- package/dist/clis/spotify/spotify.js +316 -0
- package/dist/clis/spotify/utils.d.ts +21 -0
- package/dist/clis/spotify/utils.js +66 -0
- package/dist/clis/spotify/utils.test.d.ts +1 -0
- package/dist/clis/spotify/utils.test.js +67 -0
- package/dist/clis/substack/utils.d.ts +4 -0
- package/dist/clis/substack/utils.js +8 -2
- package/dist/clis/substack/utils.test.d.ts +1 -0
- package/dist/clis/substack/utils.test.js +46 -0
- package/dist/clis/tieba/commands.test.d.ts +4 -0
- package/dist/clis/tieba/commands.test.js +79 -0
- package/dist/clis/tieba/hot.d.ts +1 -0
- package/dist/clis/tieba/hot.js +48 -0
- package/dist/clis/tieba/posts.d.ts +1 -0
- package/dist/clis/tieba/posts.js +85 -0
- package/dist/clis/tieba/read.d.ts +1 -0
- package/dist/clis/tieba/read.js +140 -0
- package/dist/clis/tieba/search.d.ts +1 -0
- package/dist/clis/tieba/search.js +108 -0
- package/dist/clis/tieba/utils.d.ts +101 -0
- package/dist/clis/tieba/utils.js +240 -0
- package/dist/clis/tieba/utils.test.d.ts +1 -0
- package/dist/clis/tieba/utils.test.js +290 -0
- package/dist/clis/v2ex/hot.yaml +4 -1
- package/dist/clis/v2ex/latest.yaml +4 -1
- package/dist/clis/v2ex/topic.yaml +6 -1
- package/dist/clis/weixin/download.d.ts +9 -0
- package/dist/clis/weixin/download.js +76 -6
- package/dist/clis/weread/book.js +206 -13
- package/dist/clis/weread/commands.test.js +331 -0
- package/dist/clis/weread/private-api-regression.test.d.ts +1 -0
- package/dist/{weread-private-api-regression.test.js → clis/weread/private-api-regression.test.js} +92 -30
- package/dist/clis/weread/search-regression.test.d.ts +1 -0
- package/dist/clis/weread/search-regression.test.js +407 -0
- package/dist/clis/weread/search.js +143 -7
- package/dist/clis/weread/shelf.js +13 -95
- package/dist/clis/weread/utils.d.ts +56 -0
- package/dist/clis/weread/utils.js +234 -7
- package/dist/clis/weread/utils.test.js +71 -1
- package/dist/clis/xiaohongshu/comments.d.ts +3 -0
- package/dist/clis/xiaohongshu/comments.js +76 -17
- package/dist/clis/xiaohongshu/comments.test.js +70 -9
- package/dist/clis/xiaohongshu/download.d.ts +4 -1
- package/dist/clis/xiaohongshu/download.js +83 -22
- package/dist/clis/xiaohongshu/download.test.d.ts +1 -0
- package/dist/clis/xiaohongshu/download.test.js +75 -0
- package/dist/clis/xiaohongshu/note-helpers.d.ts +12 -0
- package/dist/clis/xiaohongshu/note-helpers.js +23 -0
- package/dist/clis/xiaohongshu/note.d.ts +7 -0
- package/dist/clis/xiaohongshu/note.js +76 -0
- package/dist/clis/xiaohongshu/note.test.d.ts +1 -0
- package/dist/clis/xiaohongshu/note.test.js +136 -0
- package/dist/clis/xiaohongshu/publish.d.ts +1 -1
- package/dist/clis/xiaohongshu/publish.js +78 -31
- package/dist/clis/xiaohongshu/publish.test.js +66 -1
- package/dist/clis/xiaohongshu/search.js +9 -0
- package/dist/clis/xiaohongshu/search.test.js +10 -4
- package/dist/clis/xiaohongshu/user-helpers.d.ts +1 -0
- package/dist/clis/xiaohongshu/user-helpers.js +2 -0
- package/dist/clis/xiaohongshu/user-helpers.test.js +18 -0
- package/dist/clis/xueqiu/comments.d.ts +118 -0
- package/dist/clis/xueqiu/comments.js +354 -0
- package/dist/clis/xueqiu/comments.test.d.ts +1 -0
- package/dist/clis/xueqiu/comments.test.js +696 -0
- package/dist/clis/youtube/search.js +57 -17
- package/dist/clis/youtube/transcript.js +2 -4
- package/dist/clis/youtube/utils.d.ts +9 -0
- package/dist/clis/youtube/utils.js +67 -3
- package/dist/clis/youtube/utils.test.d.ts +1 -0
- package/dist/clis/youtube/utils.test.js +37 -0
- package/dist/clis/youtube/video.js +16 -15
- package/dist/clis/zhihu/question.js +19 -17
- package/dist/clis/zhihu/question.test.d.ts +1 -0
- package/dist/clis/zhihu/question.test.js +54 -0
- package/dist/clis/zsxq/dynamics.d.ts +1 -0
- package/dist/clis/zsxq/dynamics.js +47 -0
- package/dist/clis/zsxq/groups.d.ts +1 -0
- package/dist/clis/zsxq/groups.js +32 -0
- package/dist/clis/zsxq/search.d.ts +1 -0
- package/dist/clis/zsxq/search.js +43 -0
- package/dist/clis/zsxq/search.test.d.ts +1 -0
- package/dist/clis/zsxq/search.test.js +24 -0
- package/dist/clis/zsxq/topic.d.ts +1 -0
- package/dist/clis/zsxq/topic.js +47 -0
- package/dist/clis/zsxq/topic.test.d.ts +1 -0
- package/dist/clis/zsxq/topic.test.js +29 -0
- package/dist/clis/zsxq/topics.d.ts +1 -0
- package/dist/clis/zsxq/topics.js +25 -0
- package/dist/clis/zsxq/topics.test.d.ts +1 -0
- package/dist/clis/zsxq/topics.test.js +24 -0
- package/dist/clis/zsxq/utils.d.ts +97 -0
- package/dist/clis/zsxq/utils.js +230 -0
- package/dist/commanderAdapter.js +10 -1
- package/dist/commanderAdapter.test.js +64 -0
- package/dist/commands/daemon.d.ts +9 -0
- package/dist/commands/daemon.js +124 -0
- package/dist/commands/daemon.test.d.ts +1 -0
- package/dist/commands/daemon.test.js +185 -0
- package/dist/completion.js +3 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/daemon.d.ts +1 -1
- package/dist/daemon.js +25 -14
- package/dist/daemon.test.d.ts +1 -0
- package/dist/daemon.test.js +65 -0
- package/dist/discovery.d.ts +9 -0
- package/dist/discovery.js +47 -2
- package/dist/electron-apps.d.ts +29 -0
- package/dist/electron-apps.js +65 -0
- package/dist/electron-apps.test.d.ts +1 -0
- package/dist/electron-apps.test.js +43 -0
- package/dist/engine.test.js +41 -9
- package/dist/execution.js +20 -16
- package/dist/external-clis.yaml +17 -0
- package/dist/idle-manager.d.ts +19 -0
- package/dist/idle-manager.js +54 -0
- package/dist/launcher.d.ts +36 -0
- package/dist/launcher.js +152 -0
- package/dist/launcher.test.d.ts +1 -0
- package/dist/launcher.test.js +57 -0
- package/dist/main.js +3 -3
- package/dist/registry.d.ts +1 -0
- package/dist/registry.js +31 -3
- package/dist/registry.test.js +13 -0
- package/dist/runtime.d.ts +5 -3
- package/dist/runtime.js +12 -5
- package/dist/serialization.d.ts +1 -0
- package/dist/serialization.js +3 -0
- package/dist/serialization.test.js +17 -1
- package/dist/tui.d.ts +7 -0
- package/dist/tui.js +52 -0
- package/dist/tui.test.d.ts +1 -0
- package/dist/tui.test.js +19 -0
- package/dist/types.d.ts +5 -0
- package/dist/weixin-download.test.js +14 -0
- package/docs/.vitepress/config.mts +4 -0
- package/docs/adapters/browser/band.md +63 -0
- package/docs/adapters/browser/notebooklm.md +69 -0
- package/docs/adapters/browser/ones.md +59 -0
- package/docs/adapters/browser/spotify.md +62 -0
- package/docs/adapters/browser/tieba.md +45 -0
- package/docs/adapters/browser/xiaohongshu.md +19 -10
- package/docs/adapters/browser/xueqiu.md +5 -0
- package/docs/adapters/browser/zsxq.md +49 -0
- package/docs/adapters/index.md +67 -63
- package/docs/adapters-doc/ones.md +32 -0
- package/docs/guide/browser-bridge.md +12 -0
- package/docs/guide/troubleshooting.md +9 -4
- package/docs/superpowers/plans/2026-03-31-daemon-lifecycle-redesign.md +857 -0
- package/docs/superpowers/specs/2026-03-31-daemon-lifecycle-redesign.md +208 -0
- package/docs/zh/guide/browser-bridge.md +12 -0
- package/extension/dist/background.js +794 -513
- package/extension/src/background.test.ts +202 -2
- package/extension/src/background.ts +189 -10
- package/extension/src/cdp.ts +54 -0
- package/extension/src/protocol.ts +11 -5
- package/package.json +1 -1
- package/scripts/postinstall.js +16 -0
- package/src/browser/cdp.ts +24 -17
- package/src/browser/daemon-client.ts +11 -1
- package/src/browser/dom-helpers.test.ts +15 -1
- package/src/browser/dom-helpers.ts +1 -0
- package/src/browser/mcp.ts +18 -13
- package/src/browser/page.test.ts +58 -0
- package/src/browser/page.ts +34 -2
- package/src/browser/stealth.test.ts +153 -0
- package/src/browser/stealth.ts +198 -0
- package/src/browser.test.ts +1 -1
- package/src/build-manifest.test.ts +2 -0
- package/src/build-manifest.ts +6 -1
- package/src/cli.ts +21 -3
- package/src/clis/antigravity/SKILL.md +3 -12
- package/src/clis/antigravity/serve.ts +5 -10
- package/src/clis/band/bands.ts +76 -0
- package/src/clis/band/mentions.ts +134 -0
- package/src/clis/band/post.ts +187 -0
- package/src/clis/band/posts.ts +106 -0
- package/src/clis/bilibili/subtitle.test.ts +60 -0
- package/src/clis/bilibili/subtitle.ts +4 -0
- package/src/clis/chatwise/ask.ts +0 -2
- package/src/clis/chatwise/export.ts +0 -2
- package/src/clis/chatwise/history.ts +0 -2
- package/src/clis/chatwise/model.ts +0 -2
- package/src/clis/chatwise/new.ts +1 -2
- package/src/clis/chatwise/read.ts +0 -2
- package/src/clis/chatwise/screenshot.ts +1 -2
- package/src/clis/chatwise/send.ts +0 -2
- package/src/clis/chatwise/status.ts +1 -2
- package/src/clis/ctrip/search.test.ts +73 -0
- package/src/clis/ctrip/search.ts +97 -47
- package/src/clis/doubao/detail.test.ts +53 -0
- package/src/clis/doubao/detail.ts +41 -0
- package/src/clis/doubao/history.test.ts +45 -0
- package/src/clis/doubao/history.ts +32 -0
- package/src/clis/doubao/meeting-summary.ts +53 -0
- package/src/clis/doubao/meeting-transcript.ts +48 -0
- package/src/clis/doubao/utils.test.ts +45 -0
- package/src/clis/doubao/utils.ts +371 -0
- package/src/clis/douyin/_shared/public-api.ts +84 -0
- package/src/clis/douyin/_shared/sts2.test.ts +31 -0
- package/src/clis/douyin/_shared/sts2.ts +11 -3
- package/src/clis/douyin/activities.test.ts +41 -1
- package/src/clis/douyin/activities.ts +12 -3
- package/src/clis/douyin/collections.test.ts +35 -2
- package/src/clis/douyin/collections.ts +1 -1
- package/src/clis/douyin/draft.test.ts +444 -2
- package/src/clis/douyin/draft.ts +382 -218
- package/src/clis/douyin/hashtag.test.ts +42 -2
- package/src/clis/douyin/hashtag.ts +11 -3
- package/src/clis/douyin/profile.test.ts +43 -1
- package/src/clis/douyin/profile.ts +9 -2
- package/src/clis/douyin/user-videos.test.ts +122 -0
- package/src/clis/douyin/user-videos.ts +101 -0
- package/src/clis/douyin/videos.test.ts +52 -2
- package/src/clis/douyin/videos.ts +49 -15
- package/src/clis/facebook/search.test.ts +70 -0
- package/src/clis/facebook/search.yaml +4 -3
- package/src/clis/instagram/download.test.ts +159 -0
- package/src/clis/instagram/download.ts +286 -0
- package/src/clis/notebooklm/bind-current.test.ts +43 -0
- package/src/clis/notebooklm/bind-current.ts +36 -0
- package/src/clis/notebooklm/binding.test.ts +53 -0
- package/src/clis/notebooklm/compat.test.ts +19 -0
- package/src/clis/notebooklm/current.ts +38 -0
- package/src/clis/notebooklm/get.ts +53 -0
- package/src/clis/notebooklm/history.test.ts +70 -0
- package/src/clis/notebooklm/history.ts +36 -0
- package/src/clis/notebooklm/list.ts +40 -0
- package/src/clis/notebooklm/note-list.test.ts +64 -0
- package/src/clis/notebooklm/note-list.ts +42 -0
- package/src/clis/notebooklm/notes-get.test.ts +88 -0
- package/src/clis/notebooklm/notes-get.ts +67 -0
- package/src/clis/notebooklm/rpc.test.ts +126 -0
- package/src/clis/notebooklm/rpc.ts +286 -0
- package/src/clis/notebooklm/shared.ts +98 -0
- package/src/clis/notebooklm/source-fulltext.test.ts +123 -0
- package/src/clis/notebooklm/source-fulltext.ts +69 -0
- package/src/clis/notebooklm/source-get.test.ts +100 -0
- package/src/clis/notebooklm/source-get.ts +60 -0
- package/src/clis/notebooklm/source-guide.test.ts +121 -0
- package/src/clis/notebooklm/source-guide.ts +69 -0
- package/src/clis/notebooklm/source-list.ts +45 -0
- package/src/clis/notebooklm/status.ts +34 -0
- package/src/clis/notebooklm/summary.test.ts +94 -0
- package/src/clis/notebooklm/summary.ts +45 -0
- package/src/clis/notebooklm/utils.test.ts +446 -0
- package/src/clis/notebooklm/utils.ts +893 -0
- package/src/clis/ones/common.ts +187 -0
- package/src/clis/ones/enrich-tasks.ts +47 -0
- package/src/clis/ones/login.ts +103 -0
- package/src/clis/ones/logout.ts +19 -0
- package/src/clis/ones/me.ts +34 -0
- package/src/clis/ones/my-tasks.ts +148 -0
- package/src/clis/ones/resolve-labels.ts +80 -0
- package/src/clis/ones/task-helpers.test.ts +14 -0
- package/src/clis/ones/task-helpers.ts +214 -0
- package/src/clis/ones/task.ts +79 -0
- package/src/clis/ones/tasks.ts +92 -0
- package/src/clis/ones/token-info.ts +46 -0
- package/src/clis/ones/worklog.test.ts +24 -0
- package/src/clis/ones/worklog.ts +306 -0
- package/src/clis/spotify/spotify.ts +328 -0
- package/src/clis/spotify/utils.test.ts +87 -0
- package/src/clis/spotify/utils.ts +92 -0
- package/src/clis/substack/utils.test.ts +54 -0
- package/src/clis/substack/utils.ts +10 -2
- package/src/clis/tieba/commands.test.ts +86 -0
- package/src/clis/tieba/hot.ts +52 -0
- package/src/clis/tieba/posts.ts +108 -0
- package/src/clis/tieba/read.ts +158 -0
- package/src/clis/tieba/search.ts +119 -0
- package/src/clis/tieba/utils.test.ts +322 -0
- package/src/clis/tieba/utils.ts +348 -0
- package/src/clis/v2ex/hot.yaml +4 -1
- package/src/clis/v2ex/latest.yaml +4 -1
- package/src/clis/v2ex/topic.yaml +6 -1
- package/src/clis/weixin/download.ts +95 -6
- package/src/clis/weread/book.ts +256 -13
- package/src/clis/weread/commands.test.ts +409 -0
- package/src/{weread-private-api-regression.test.ts → clis/weread/private-api-regression.test.ts} +108 -30
- package/src/clis/weread/search-regression.test.ts +440 -0
- package/src/clis/weread/search.ts +189 -9
- package/src/clis/weread/shelf.ts +20 -122
- package/src/clis/weread/utils.test.ts +81 -1
- package/src/clis/weread/utils.ts +293 -7
- package/src/clis/xiaohongshu/comments.test.ts +85 -9
- package/src/clis/xiaohongshu/comments.ts +76 -17
- package/src/clis/xiaohongshu/download.test.ts +96 -0
- package/src/clis/xiaohongshu/download.ts +83 -22
- package/src/clis/xiaohongshu/note-helpers.ts +25 -0
- package/src/clis/xiaohongshu/note.test.ts +164 -0
- package/src/clis/xiaohongshu/note.ts +86 -0
- package/src/clis/xiaohongshu/publish.test.ts +79 -1
- package/src/clis/xiaohongshu/publish.ts +84 -30
- package/src/clis/xiaohongshu/search.test.ts +11 -4
- package/src/clis/xiaohongshu/search.ts +13 -0
- package/src/clis/xiaohongshu/user-helpers.test.ts +23 -0
- package/src/clis/xiaohongshu/user-helpers.ts +4 -0
- package/src/clis/xueqiu/comments.test.ts +823 -0
- package/src/clis/xueqiu/comments.ts +461 -0
- package/src/clis/youtube/search.ts +57 -17
- package/src/clis/youtube/transcript.ts +2 -4
- package/src/clis/youtube/utils.test.ts +43 -0
- package/src/clis/youtube/utils.ts +69 -0
- package/src/clis/youtube/video.ts +16 -15
- package/src/clis/zhihu/question.test.ts +71 -0
- package/src/clis/zhihu/question.ts +27 -15
- package/src/clis/zsxq/dynamics.ts +60 -0
- package/src/clis/zsxq/groups.ts +41 -0
- package/src/clis/zsxq/search.test.ts +29 -0
- package/src/clis/zsxq/search.ts +54 -0
- package/src/clis/zsxq/topic.test.ts +34 -0
- package/src/clis/zsxq/topic.ts +68 -0
- package/src/clis/zsxq/topics.test.ts +29 -0
- package/src/clis/zsxq/topics.ts +36 -0
- package/src/clis/zsxq/utils.ts +351 -0
- package/src/commanderAdapter.test.ts +77 -0
- package/src/commanderAdapter.ts +8 -1
- package/src/commands/daemon.test.ts +238 -0
- package/src/commands/daemon.ts +135 -0
- package/src/completion.ts +2 -1
- package/src/constants.ts +3 -0
- package/src/daemon.test.ts +88 -0
- package/src/daemon.ts +26 -14
- package/src/discovery.ts +52 -2
- package/src/electron-apps.test.ts +50 -0
- package/src/electron-apps.ts +89 -0
- package/src/engine.test.ts +45 -9
- package/src/execution.ts +24 -19
- package/src/external-clis.yaml +17 -0
- package/src/idle-manager.ts +60 -0
- package/src/launcher.test.ts +67 -0
- package/src/launcher.ts +185 -0
- package/src/main.ts +3 -2
- package/src/registry.test.ts +15 -0
- package/src/registry.ts +32 -3
- package/src/runtime.ts +13 -7
- package/src/serialization.test.ts +19 -1
- package/src/serialization.ts +2 -0
- package/src/tui.test.ts +23 -0
- package/src/tui.ts +65 -0
- package/src/types.ts +5 -0
- package/src/weixin-download.test.ts +27 -0
- package/tests/e2e/band-auth.test.ts +20 -0
- package/tests/e2e/browser-auth-helpers.ts +18 -0
- package/tests/e2e/browser-auth.test.ts +35 -47
- package/tests/e2e/browser-public-extended.test.ts +6 -2
- package/tests/e2e/browser-public.test.ts +288 -0
- package/tests/e2e/management.test.ts +1 -1
- package/tests/e2e/plugin-management.test.ts +1 -1
- package/vitest.config.ts +1 -0
- package/chatwise-opencli.ps1 +0 -82
- package/dist/clis/chatwise/shared.d.ts +0 -2
- package/dist/clis/chatwise/shared.js +0 -6
- package/dist/weread-private-api-regression.test.d.ts +0 -1
- package/dist/weread-search-regression.test.d.ts +0 -1
- package/dist/weread-search-regression.test.js +0 -39
- package/src/clis/chatwise/shared.ts +0 -8
- package/src/weread-search-regression.test.ts +0 -44
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.5.7](https://github.com/jackwener/opencli/compare/v1.5.6...v1.5.7) (2026-04-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **daemon:** replace 5min idle timeout with long-lived daemon model (4h default, dual-condition exit) ([#641](https://github.com/jackwener/opencli/issues/641))
|
|
9
|
+
* **daemon:** add `opencli daemon status/stop/restart` CLI commands ([#641](https://github.com/jackwener/opencli/issues/641))
|
|
10
|
+
* **youtube:** add search filters — `--type` shorts/video/channel, `--upload`, `--sort` ([#616](https://github.com/jackwener/opencli/issues/616))
|
|
11
|
+
* **notebooklm:** add read commands and compatibility layer ([#622](https://github.com/jackwener/opencli/issues/622))
|
|
12
|
+
* **instagram:** add media download command ([#623](https://github.com/jackwener/opencli/issues/623))
|
|
13
|
+
* **stealth:** harden CDP debugger detection countermeasures ([#644](https://github.com/jackwener/opencli/issues/644))
|
|
14
|
+
* **v2ex:** add id, node, url, content, member fields to topic output ([#646](https://github.com/jackwener/opencli/issues/646), [#648](https://github.com/jackwener/opencli/issues/648))
|
|
15
|
+
* **electron:** auto-launcher — zero-config CDP connection ([#653](https://github.com/jackwener/opencli/issues/653))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **douyin:** repair creator draft flow — switch from broken API pipeline to UI-driven approach ([#640](https://github.com/jackwener/opencli/issues/640))
|
|
21
|
+
* **douyin:** support current creator API response shapes for activities, profile, collections, hashtag, videos ([#618](https://github.com/jackwener/opencli/issues/618))
|
|
22
|
+
* **bilibili:** distinguish login-gated subtitles from empty results ([#645](https://github.com/jackwener/opencli/issues/645))
|
|
23
|
+
* **facebook:** avoid in-page redirect in search — use navigate step instead of window.location.href ([#642](https://github.com/jackwener/opencli/issues/642))
|
|
24
|
+
* **substack:** update selectors for DOM redesign ([#624](https://github.com/jackwener/opencli/issues/624))
|
|
25
|
+
* **weread:** recover book details from cached shelf fallback ([#628](https://github.com/jackwener/opencli/issues/628))
|
|
26
|
+
* **docs:** use relative links in adapter index ([#629](https://github.com/jackwener/opencli/issues/629))
|
|
27
|
+
|
|
28
|
+
|
|
3
29
|
## [1.4.1](https://github.com/jackwener/opencli/compare/v1.4.0...v1.4.1) (2026-03-25)
|
|
4
30
|
|
|
5
31
|
|
package/README.md
CHANGED
|
@@ -72,7 +72,8 @@ npm install -g @jackwener/opencli
|
|
|
72
72
|
### 3. Verify & Try
|
|
73
73
|
|
|
74
74
|
```bash
|
|
75
|
-
opencli doctor
|
|
75
|
+
opencli doctor # Check extension + daemon connectivity
|
|
76
|
+
opencli daemon status # Check daemon state (PID, uptime, memory)
|
|
76
77
|
```
|
|
77
78
|
|
|
78
79
|
**Try it out:**
|
|
@@ -117,12 +118,15 @@ git clone git@github.com:jackwener/opencli.git && cd opencli && npm install && n
|
|
|
117
118
|
|
|
118
119
|
| Site | Commands |
|
|
119
120
|
|------|----------|
|
|
120
|
-
| **xiaohongshu** | `search` `feed` `user` `download` `publish` `
|
|
121
|
+
| **xiaohongshu** | `search` `note` `comments` `feed` `user` `download` `publish` `notifications` `creator-notes` `creator-notes-summary` `creator-note-detail` `creator-profile` `creator-stats` |
|
|
121
122
|
| **bilibili** | `hot` `search` `history` `feed` `ranking` `download` `comments` `dynamic` `favorite` `following` `me` `subtitle` `user-videos` |
|
|
123
|
+
| **tieba** | `hot` `posts` `search` `read` |
|
|
122
124
|
| **twitter** | `trending` `search` `timeline` `bookmarks` `post` `download` `profile` `article` `like` `likes` `notifications` `reply` `reply-dm` `thread` `follow` `unfollow` `followers` `following` `block` `unblock` `bookmark` `unbookmark` `delete` `hide-reply` `accept` |
|
|
123
125
|
| **reddit** | `hot` `frontpage` `popular` `search` `subreddit` `user` `user-posts` `user-comments` `read` `save` `saved` `subscribe` `upvote` `upvoted` `comment` |
|
|
126
|
+
| **notebooklm** | `status` `list` `current` `get` `metadata` `bind-current` `use` `source-list` `source-get` `source-fulltext` `source-guide` `history` `note-list` `notes-list` `notes-get` `summary` |
|
|
127
|
+
| **spotify** | `auth` `status` `play` `pause` `next` `prev` `volume` `search` `queue` `shuffle` `repeat` |
|
|
124
128
|
|
|
125
|
-
|
|
129
|
+
66+ adapters in total — **[→ see all supported sites & commands](./docs/adapters/index.md)**
|
|
126
130
|
|
|
127
131
|
## CLI Hub
|
|
128
132
|
|
|
@@ -133,8 +137,9 @@ OpenCLI acts as a universal hub for your existing command-line tools — unified
|
|
|
133
137
|
| **gh** | GitHub CLI | `opencli gh pr list --limit 5` |
|
|
134
138
|
| **obsidian** | Obsidian vault management | `opencli obsidian search query="AI"` |
|
|
135
139
|
| **docker** | Docker | `opencli docker ps` |
|
|
136
|
-
| **gws** | Google Workspace CLI | `opencli gws docs list` |
|
|
137
140
|
| **lark-cli** | Lark/Feishu — messages, docs, calendar, tasks, 200+ commands | `opencli lark-cli calendar +agenda` |
|
|
141
|
+
| **dingtalk** | DingTalk — cross-platform CLI for DingTalk's full suite, designed for humans and AI agents | `opencli dingtalk msg send --to user "hello"` |
|
|
142
|
+
| **wecom** | WeCom/企业微信 — CLI for WeCom open platform, for humans and AI agents | `opencli wecom msg send --to user "hello"` |
|
|
138
143
|
| **vercel** | Vercel — deploy projects, manage domains, env vars, logs | `opencli vercel deploy --prod` |
|
|
139
144
|
|
|
140
145
|
**Register your own** — add any local CLI so AI agents can discover it via `opencli list`:
|
|
@@ -192,6 +197,28 @@ opencli bilibili hot -f csv # Spreadsheet-friendly
|
|
|
192
197
|
opencli bilibili hot -v # Verbose: show pipeline debug steps
|
|
193
198
|
```
|
|
194
199
|
|
|
200
|
+
## Exit Codes
|
|
201
|
+
|
|
202
|
+
opencli follows Unix `sysexits.h` conventions so it integrates naturally with shell pipelines and CI scripts:
|
|
203
|
+
|
|
204
|
+
| Code | Meaning | When |
|
|
205
|
+
|------|---------|------|
|
|
206
|
+
| `0` | Success | Command completed normally |
|
|
207
|
+
| `1` | Generic error | Unexpected / unclassified failure |
|
|
208
|
+
| `2` | Usage error | Bad arguments or unknown command |
|
|
209
|
+
| `66` | Empty result | No data returned (`EX_NOINPUT`) |
|
|
210
|
+
| `69` | Service unavailable | Browser Bridge not connected (`EX_UNAVAILABLE`) |
|
|
211
|
+
| `75` | Temporary failure | Command timed out — retry (`EX_TEMPFAIL`) |
|
|
212
|
+
| `77` | Auth required | Not logged in to target site (`EX_NOPERM`) |
|
|
213
|
+
| `78` | Config error | Missing credentials or bad config (`EX_CONFIG`) |
|
|
214
|
+
| `130` | Interrupted | Ctrl-C / SIGINT |
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
opencli spotify status || echo "exit $?" # 69 if browser not running
|
|
218
|
+
opencli github issues 2>/dev/null
|
|
219
|
+
[ $? -eq 77 ] && opencli github auth # auto-auth if not logged in
|
|
220
|
+
```
|
|
221
|
+
|
|
195
222
|
## Plugins
|
|
196
223
|
|
|
197
224
|
Extend OpenCLI with community-contributed adapters:
|
package/README.zh-CN.md
CHANGED
|
@@ -73,9 +73,11 @@ OpenCLI 通过轻量化的 **Browser Bridge** Chrome 扩展 + 微型 daemon 与
|
|
|
73
73
|
|
|
74
74
|
完成!运行任何 opencli 浏览器命令时,后台微型 daemon 会自动启动与浏览器通信。无需配 API Token,零代码配置。
|
|
75
75
|
|
|
76
|
-
> **Tip
|
|
76
|
+
> **Tip**:后续诊断和 daemon 管理:
|
|
77
77
|
> ```bash
|
|
78
78
|
> opencli doctor # 检查扩展和 daemon 连通性
|
|
79
|
+
> opencli daemon status # 查看 daemon 状态
|
|
80
|
+
> opencli daemon stop # 停止 daemon
|
|
79
81
|
> ```
|
|
80
82
|
|
|
81
83
|
## 快速开始
|
|
@@ -122,16 +124,17 @@ npm install -g @jackwener/opencli@latest
|
|
|
122
124
|
|------|------|------|
|
|
123
125
|
| **twitter** | `trending` `bookmarks` `profile` `search` `timeline` `thread` `following` `followers` `notifications` `post` `reply` `delete` `like` `article` `follow` `unfollow` `bookmark` `unbookmark` `download` `accept` `reply-dm` `block` `unblock` `hide-reply` | 浏览器 |
|
|
124
126
|
| **reddit** | `hot` `frontpage` `popular` `search` `subreddit` `read` `user` `user-posts` `user-comments` `upvote` `save` `comment` `subscribe` `saved` `upvoted` | 浏览器 |
|
|
127
|
+
| **tieba** | `hot` `posts` `search` `read` | 浏览器 |
|
|
125
128
|
| **cursor** | `status` `send` `read` `new` `dump` `composer` `model` `extract-code` `ask` `screenshot` `history` `export` | 桌面端 |
|
|
126
129
|
| **bilibili** | `hot` `search` `me` `favorite` `history` `feed` `subtitle` `dynamic` `ranking` `following` `user-videos` `download` | 浏览器 |
|
|
127
130
|
| **codex** | `status` `send` `read` `new` `dump` `extract-diff` `model` `ask` `screenshot` `history` `export` | 桌面端 |
|
|
128
131
|
| **chatwise** | `status` `new` `send` `read` `ask` `model` `history` `export` `screenshot` | 桌面端 |
|
|
129
|
-
| **doubao** | `status` `new` `send` `read` `ask` | 浏览器 |
|
|
132
|
+
| **doubao** | `status` `new` `send` `read` `ask` `history` `detail` `meeting-summary` `meeting-transcript` | 浏览器 |
|
|
130
133
|
| **doubao-app** | `status` `new` `send` `read` `ask` `screenshot` `dump` | 桌面端 |
|
|
131
134
|
| **notion** | `status` `search` `read` `new` `write` `sidebar` `favorites` `export` | 桌面端 |
|
|
132
135
|
| **discord-app** | `status` `send` `read` `channels` `servers` `search` `members` | 桌面端 |
|
|
133
136
|
| **v2ex** | `hot` `latest` `topic` `node` `user` `member` `replies` `nodes` `daily` `me` `notifications` | 公开 / 浏览器 |
|
|
134
|
-
| **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` `earnings-date` `fund-holdings` `fund-snapshot` | 浏览器 |
|
|
137
|
+
| **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `comments` `watchlist` `earnings-date` `fund-holdings` `fund-snapshot` | 浏览器 |
|
|
135
138
|
| **antigravity** | `status` `send` `read` `new` `dump` `extract-code` `model` `watch` | 桌面端 |
|
|
136
139
|
| **chatgpt** | `status` `new` `send` `read` `ask` `model` | 桌面端 |
|
|
137
140
|
| **xiaohongshu** | `search` `notifications` `feed` `user` `download` `publish` `creator-notes` `creator-note-detail` `creator-notes-summary` `creator-profile` `creator-stats` | 浏览器 |
|
|
@@ -173,6 +176,8 @@ npm install -g @jackwener/opencli@latest
|
|
|
173
176
|
| **douban** | `search` `top250` `subject` `photos` `download` `marks` `reviews` `movie-hot` `book-hot` | 浏览器 |
|
|
174
177
|
| **facebook** | `feed` `profile` `search` `friends` `groups` `events` `notifications` `memories` `add-friend` `join-group` | 浏览器 |
|
|
175
178
|
| **google** | `news` `search` `suggest` `trends` | 公开 |
|
|
179
|
+
| **spotify** | `auth` `status` `play` `pause` `next` `prev` `volume` `search` `queue` `shuffle` `repeat` | OAuth API |
|
|
180
|
+
| **notebooklm** | `status` `list` `current` `get` `metadata` `bind-current` `use` `source-list` `source-get` `source-fulltext` `source-guide` `history` `note-list` `notes-list` `notes-get` `summary` | 浏览器 |
|
|
176
181
|
| **36kr** | `news` `hot` `search` `article` | 公开 / 浏览器 |
|
|
177
182
|
| **imdb** | `search` `title` `top` `trending` `person` `reviews` | 公开 |
|
|
178
183
|
| **producthunt** | `posts` `today` `hot` `browse` | 公开 / 浏览器 |
|
|
@@ -183,7 +188,10 @@ npm install -g @jackwener/opencli@latest
|
|
|
183
188
|
| **substack** | `feed` `search` `publication` | 浏览器 |
|
|
184
189
|
| **pixiv** | `ranking` `search` `user` `illusts` `detail` `download` | 浏览器 |
|
|
185
190
|
| **tiktok** | `explore` `search` `profile` `user` `following` `follow` `unfollow` `like` `unlike` `comment` `save` `unsave` `live` `notifications` `friends` | 浏览器 |
|
|
191
|
+
| **bluesky** | `search` `trending` `user` `profile` `thread` `feeds` `followers` `following` `starter-packs` | 公开 |
|
|
192
|
+
| **douyin** | `videos` `publish` `drafts` `draft` `delete` `stats` `profile` `update` `hashtag` `location` `activities` `collections` | 浏览器 |
|
|
186
193
|
|
|
194
|
+
66+ 适配器 — **[→ 查看完整命令列表](./docs/adapters/index.md)**
|
|
187
195
|
|
|
188
196
|
### 外部 CLI 枢纽
|
|
189
197
|
|
|
@@ -194,8 +202,10 @@ OpenCLI 也可以作为你现有命令行工具的统一入口,负责发现、
|
|
|
194
202
|
| **gh** | GitHub CLI | `opencli gh pr list --limit 5` |
|
|
195
203
|
| **obsidian** | Obsidian 仓库管理 | `opencli obsidian search query="AI"` |
|
|
196
204
|
| **docker** | Docker 命令行工具 | `opencli docker ps` |
|
|
197
|
-
| **
|
|
198
|
-
| **
|
|
205
|
+
| **lark-cli** | 飞书 CLI — 消息、文档、日历、任务,200+ 命令 | `opencli lark-cli calendar +agenda` |
|
|
206
|
+
| **dingtalk** | 钉钉 CLI — 钉钉全套产品能力的跨平台命令行工具,支持人类和 AI Agent 使用 | `opencli dingtalk msg send --to user "hello"` |
|
|
207
|
+
| **wecom** | 企业微信 CLI — 企业微信开放平台命令行工具,支持人类和 AI Agent 使用 | `opencli wecom msg send --to user "hello"` |
|
|
208
|
+
| **vercel** | Vercel — 部署项目、管理域名、环境变量、日志 | `opencli vercel deploy --prod` |
|
|
199
209
|
|
|
200
210
|
**零配置透传**:OpenCLI 会把你的输入原样转发给底层二进制,保留原生 stdout / stderr 行为。
|
|
201
211
|
|
|
@@ -295,6 +305,31 @@ opencli bilibili hot -f csv # CSV
|
|
|
295
305
|
opencli bilibili hot -v # 详细模式:展示管线执行步骤调试信息
|
|
296
306
|
```
|
|
297
307
|
|
|
308
|
+
## 退出码
|
|
309
|
+
|
|
310
|
+
opencli 遵循 Unix `sysexits.h` 惯例,可无缝接入 shell 管道和 CI 脚本:
|
|
311
|
+
|
|
312
|
+
| 退出码 | 含义 | 触发场景 |
|
|
313
|
+
|--------|------|----------|
|
|
314
|
+
| `0` | 成功 | 命令正常完成 |
|
|
315
|
+
| `1` | 通用错误 | 未分类的意外错误 |
|
|
316
|
+
| `2` | 用法错误 | 参数错误或未知命令 |
|
|
317
|
+
| `66` | 无数据 | 命令返回空结果(`EX_NOINPUT`) |
|
|
318
|
+
| `69` | 服务不可用 | Browser Bridge 未连接(`EX_UNAVAILABLE`) |
|
|
319
|
+
| `75` | 临时失败 | 命令超时,可重试(`EX_TEMPFAIL`) |
|
|
320
|
+
| `77` | 需要认证 | 未登录目标网站(`EX_NOPERM`) |
|
|
321
|
+
| `78` | 配置错误 | 凭证缺失或配置有误(`EX_CONFIG`) |
|
|
322
|
+
| `130` | 中断 | Ctrl-C / SIGINT |
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
opencli bilibili hot 2>/dev/null
|
|
326
|
+
case $? in
|
|
327
|
+
0) echo "ok" ;;
|
|
328
|
+
69) echo "请先启动 Browser Bridge" ;;
|
|
329
|
+
77) echo "请先登录 bilibili.com" ;;
|
|
330
|
+
esac
|
|
331
|
+
```
|
|
332
|
+
|
|
298
333
|
## 插件
|
|
299
334
|
|
|
300
335
|
通过社区贡献的插件扩展 OpenCLI。插件使用与内置命令相同的 YAML/TS 格式,启动时自动发现。
|
package/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: opencli
|
|
3
3
|
description: "OpenCLI — Make any website or Electron App your CLI. Zero risk, AI-powered, reuse Chrome login."
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.5.6
|
|
5
5
|
author: jackwener
|
|
6
6
|
tags: [cli, browser, web, chrome-extension, cdp, bilibili, zhihu, twitter, github, v2ex, hackernews, reddit, xiaohongshu, xueqiu, youtube, boss, coupang, yollomi, AI, agent]
|
|
7
7
|
---
|
package/dist/browser/cdp.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export declare class CDPBridge implements IBrowserFactory {
|
|
|
23
23
|
connect(opts?: {
|
|
24
24
|
timeout?: number;
|
|
25
25
|
workspace?: string;
|
|
26
|
+
cdpEndpoint?: string;
|
|
26
27
|
}): Promise<IPage>;
|
|
27
28
|
close(): Promise<void>;
|
|
28
29
|
send(method: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
|
package/dist/browser/cdp.js
CHANGED
|
@@ -15,6 +15,7 @@ import { generateSnapshotJs, scrollToRefJs, getFormStateJs } from './dom-snapsho
|
|
|
15
15
|
import { generateStealthJs } from './stealth.js';
|
|
16
16
|
import { clickJs, typeTextJs, pressKeyJs, waitForTextJs, scrollJs, autoScrollJs, networkRequestsJs, waitForDomStableJs, waitForCaptureJs, waitForSelectorJs, } from './dom-helpers.js';
|
|
17
17
|
import { isRecord, saveBase64ToFile } from '../utils.js';
|
|
18
|
+
import { getAllElectronApps } from '../electron-apps.js';
|
|
18
19
|
const CDP_SEND_TIMEOUT = 30_000;
|
|
19
20
|
export class CDPBridge {
|
|
20
21
|
_ws = null;
|
|
@@ -24,9 +25,9 @@ export class CDPBridge {
|
|
|
24
25
|
async connect(opts) {
|
|
25
26
|
if (this._ws)
|
|
26
27
|
throw new Error('CDPBridge is already connected. Call close() before reconnecting.');
|
|
27
|
-
const endpoint = process.env.OPENCLI_CDP_ENDPOINT;
|
|
28
|
+
const endpoint = opts?.cdpEndpoint ?? process.env.OPENCLI_CDP_ENDPOINT;
|
|
28
29
|
if (!endpoint)
|
|
29
|
-
throw new Error('
|
|
30
|
+
throw new Error('CDP endpoint not provided (pass cdpEndpoint or set OPENCLI_CDP_ENDPOINT)');
|
|
30
31
|
let wsUrl = endpoint;
|
|
31
32
|
if (endpoint.startsWith('http')) {
|
|
32
33
|
const targets = await fetchJsonDirect(`${endpoint.replace(/\/$/, '')}/json`);
|
|
@@ -269,7 +270,19 @@ class CDPPage {
|
|
|
269
270
|
return [];
|
|
270
271
|
}
|
|
271
272
|
async getCurrentUrl() {
|
|
272
|
-
|
|
273
|
+
if (this._lastUrl)
|
|
274
|
+
return this._lastUrl;
|
|
275
|
+
try {
|
|
276
|
+
const current = await this.evaluate('window.location.href');
|
|
277
|
+
if (typeof current === 'string' && current) {
|
|
278
|
+
this._lastUrl = current;
|
|
279
|
+
return current;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
// Best-effort: direct CDP sessions may not have a ready page yet.
|
|
284
|
+
}
|
|
285
|
+
return null;
|
|
273
286
|
}
|
|
274
287
|
async installInterceptor(pattern) {
|
|
275
288
|
const { generateInterceptorJs } = await import('../interceptor.js');
|
|
@@ -346,30 +359,20 @@ function scoreCDPTarget(target, preferredPattern) {
|
|
|
346
359
|
score -= 40;
|
|
347
360
|
if (title && title !== 'devtools')
|
|
348
361
|
score += 25;
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
if (url.includes('codex'))
|
|
364
|
-
score += 100;
|
|
365
|
-
if (url.includes('cursor'))
|
|
366
|
-
score += 100;
|
|
367
|
-
if (url.includes('chatwise'))
|
|
368
|
-
score += 100;
|
|
369
|
-
if (url.includes('notion'))
|
|
370
|
-
score += 100;
|
|
371
|
-
if (url.includes('discord'))
|
|
372
|
-
score += 100;
|
|
362
|
+
// Boost score for known Electron app names from the registry (builtin + user-defined)
|
|
363
|
+
const appNames = Object.values(getAllElectronApps()).map(a => (a.displayName ?? a.processName).toLowerCase());
|
|
364
|
+
for (const name of appNames) {
|
|
365
|
+
if (title.includes(name)) {
|
|
366
|
+
score += 120;
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
for (const name of appNames) {
|
|
371
|
+
if (url.includes(name)) {
|
|
372
|
+
score += 100;
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
373
376
|
return score;
|
|
374
377
|
}
|
|
375
378
|
function compilePreferredPattern(raw) {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type { BrowserSessionInfo } from '../types.js';
|
|
7
7
|
export interface DaemonCommand {
|
|
8
8
|
id: string;
|
|
9
|
-
action: 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window' | 'sessions';
|
|
9
|
+
action: 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window' | 'sessions' | 'set-file-input' | 'bind-current';
|
|
10
10
|
tabId?: number;
|
|
11
11
|
code?: string;
|
|
12
12
|
workspace?: string;
|
|
@@ -14,9 +14,15 @@ export interface DaemonCommand {
|
|
|
14
14
|
op?: string;
|
|
15
15
|
index?: number;
|
|
16
16
|
domain?: string;
|
|
17
|
+
matchDomain?: string;
|
|
18
|
+
matchPathPrefix?: string;
|
|
17
19
|
format?: 'png' | 'jpeg';
|
|
18
20
|
quality?: number;
|
|
19
21
|
fullPage?: boolean;
|
|
22
|
+
/** Local file paths for set-file-input action */
|
|
23
|
+
files?: string[];
|
|
24
|
+
/** CSS selector for file input element (set-file-input action) */
|
|
25
|
+
selector?: string;
|
|
20
26
|
}
|
|
21
27
|
export interface DaemonResult {
|
|
22
28
|
id: string;
|
|
@@ -39,3 +45,7 @@ export declare function isExtensionConnected(): Promise<boolean>;
|
|
|
39
45
|
*/
|
|
40
46
|
export declare function sendCommand(action: DaemonCommand['action'], params?: Omit<DaemonCommand, 'id' | 'action'>): Promise<unknown>;
|
|
41
47
|
export declare function listSessions(): Promise<BrowserSessionInfo[]>;
|
|
48
|
+
export declare function bindCurrentTab(workspace: string, opts?: {
|
|
49
|
+
matchDomain?: string;
|
|
50
|
+
matchPathPrefix?: string;
|
|
51
|
+
}): Promise<unknown>;
|
|
@@ -105,3 +105,6 @@ export async function listSessions() {
|
|
|
105
105
|
const result = await sendCommand('sessions');
|
|
106
106
|
return Array.isArray(result) ? result : [];
|
|
107
107
|
}
|
|
108
|
+
export async function bindCurrentTab(workspace, opts = {}) {
|
|
109
|
+
return sendCommand('bind-current', { workspace, ...opts });
|
|
110
|
+
}
|
|
@@ -103,6 +103,7 @@ export function scrollJs(direction, amount) {
|
|
|
103
103
|
export function autoScrollJs(times, delayMs) {
|
|
104
104
|
return `
|
|
105
105
|
(async () => {
|
|
106
|
+
if (!document.body) return;
|
|
106
107
|
for (let i = 0; i < ${times}; i++) {
|
|
107
108
|
const lastHeight = document.body.scrollHeight;
|
|
108
109
|
window.scrollTo(0, lastHeight);
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { waitForCaptureJs, waitForSelectorJs } from './dom-helpers.js';
|
|
2
|
+
import { autoScrollJs, waitForCaptureJs, waitForSelectorJs } from './dom-helpers.js';
|
|
3
|
+
describe('autoScrollJs', () => {
|
|
4
|
+
it('returns early without error when document.body is null', async () => {
|
|
5
|
+
const g = globalThis;
|
|
6
|
+
const origDoc = g.document;
|
|
7
|
+
g.document = { body: null, documentElement: {} };
|
|
8
|
+
g.window = g;
|
|
9
|
+
const code = autoScrollJs(3, 500);
|
|
10
|
+
// Should resolve without throwing
|
|
11
|
+
await expect(eval(code)).resolves.not.toThrow();
|
|
12
|
+
g.document = origDoc;
|
|
13
|
+
delete g.window;
|
|
14
|
+
});
|
|
15
|
+
});
|
|
3
16
|
describe('waitForCaptureJs', () => {
|
|
4
17
|
it('returns a non-empty string', () => {
|
|
5
18
|
const code = waitForCaptureJs(1000);
|
package/dist/browser/mcp.js
CHANGED
|
@@ -50,29 +50,36 @@ export class BrowserBridge {
|
|
|
50
50
|
this._state = 'closed';
|
|
51
51
|
}
|
|
52
52
|
async _ensureDaemon(timeoutSeconds) {
|
|
53
|
-
// Use default if not provided, zero, or negative
|
|
54
53
|
const effectiveSeconds = (timeoutSeconds && timeoutSeconds > 0) ? timeoutSeconds : Math.ceil(DAEMON_SPAWN_TIMEOUT / 1000);
|
|
55
54
|
const timeoutMs = effectiveSeconds * 1000;
|
|
55
|
+
// Fast path: extension already connected
|
|
56
56
|
if (await isExtensionConnected())
|
|
57
57
|
return;
|
|
58
|
+
// Daemon running but no extension — wait for extension with progress
|
|
58
59
|
if (await isDaemonRunning()) {
|
|
60
|
+
if (process.env.OPENCLI_VERBOSE || process.stderr.isTTY) {
|
|
61
|
+
process.stderr.write('⏳ Waiting for Chrome extension to connect...\n');
|
|
62
|
+
process.stderr.write(' Make sure Chrome is open and the OpenCLI extension is enabled.\n');
|
|
63
|
+
}
|
|
64
|
+
const deadline = Date.now() + timeoutMs;
|
|
65
|
+
while (Date.now() < deadline) {
|
|
66
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
67
|
+
if (await isExtensionConnected())
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
59
70
|
throw new Error('Daemon is running but the Browser Extension is not connected.\n' +
|
|
60
71
|
'Please install and enable the opencli Browser Bridge extension in Chrome.');
|
|
61
72
|
}
|
|
62
|
-
//
|
|
63
|
-
// npx tsx src/main.ts → src/browser/mcp.ts → src/daemon.ts
|
|
64
|
-
// node dist/main.js → dist/browser/mcp.js → dist/daemon.js
|
|
73
|
+
// No daemon — spawn one
|
|
65
74
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
66
75
|
const parentDir = path.resolve(__dirname, '..');
|
|
67
76
|
const daemonTs = path.join(parentDir, 'daemon.ts');
|
|
68
77
|
const daemonJs = path.join(parentDir, 'daemon.js');
|
|
69
78
|
const isTs = fs.existsSync(daemonTs);
|
|
70
79
|
const daemonPath = isTs ? daemonTs : daemonJs;
|
|
71
|
-
if (process.env.OPENCLI_VERBOSE) {
|
|
72
|
-
|
|
80
|
+
if (process.env.OPENCLI_VERBOSE || process.stderr.isTTY) {
|
|
81
|
+
process.stderr.write('⏳ Starting daemon...\n');
|
|
73
82
|
}
|
|
74
|
-
// For compiled .js, use the current node binary directly (fast).
|
|
75
|
-
// For .ts dev mode, node can't run .ts files — use tsx via --import.
|
|
76
83
|
const spawnArgs = isTs
|
|
77
84
|
? [process.execPath, '--import', 'tsx/esm', daemonPath]
|
|
78
85
|
: [process.execPath, daemonPath];
|
|
@@ -82,15 +89,13 @@ export class BrowserBridge {
|
|
|
82
89
|
env: { ...process.env },
|
|
83
90
|
});
|
|
84
91
|
this._daemonProc.unref();
|
|
85
|
-
// Wait for daemon
|
|
86
|
-
const backoffs = [50, 100, 200, 400, 800, 1500, 3000];
|
|
92
|
+
// Wait for daemon + extension with faster polling
|
|
87
93
|
const deadline = Date.now() + timeoutMs;
|
|
88
|
-
|
|
89
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
94
|
+
while (Date.now() < deadline) {
|
|
95
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
90
96
|
if (await isExtensionConnected())
|
|
91
97
|
return;
|
|
92
98
|
}
|
|
93
|
-
// Daemon might be up but extension not connected — give a useful error
|
|
94
99
|
if (await isDaemonRunning()) {
|
|
95
100
|
throw new Error('Daemon is running but the Browser Extension is not connected.\n' +
|
|
96
101
|
'Please install and enable the opencli Browser Bridge extension in Chrome.');
|
package/dist/browser/page.d.ts
CHANGED
|
@@ -72,5 +72,11 @@ export declare class Page implements IPage {
|
|
|
72
72
|
}): Promise<void>;
|
|
73
73
|
installInterceptor(pattern: string): Promise<void>;
|
|
74
74
|
getInterceptedRequests(): Promise<unknown[]>;
|
|
75
|
+
/**
|
|
76
|
+
* Set local file paths on a file input element via CDP DOM.setFileInputFiles.
|
|
77
|
+
* Chrome reads the files directly from the local filesystem, avoiding the
|
|
78
|
+
* payload size limits of base64-in-evaluate.
|
|
79
|
+
*/
|
|
80
|
+
setFileInput(files: string[], selector?: string): Promise<void>;
|
|
75
81
|
waitForCapture(timeout?: number): Promise<void>;
|
|
76
82
|
}
|
package/dist/browser/page.js
CHANGED
|
@@ -96,7 +96,19 @@ export class Page {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
async getCurrentUrl() {
|
|
99
|
-
|
|
99
|
+
if (this._lastUrl)
|
|
100
|
+
return this._lastUrl;
|
|
101
|
+
try {
|
|
102
|
+
const current = await this.evaluate('window.location.href');
|
|
103
|
+
if (typeof current === 'string' && current) {
|
|
104
|
+
this._lastUrl = current;
|
|
105
|
+
return current;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Best-effort: some commands may run before a debuggable tab is ready.
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
100
112
|
}
|
|
101
113
|
/** Close the automation window in the extension */
|
|
102
114
|
async closeWindow() {
|
|
@@ -109,7 +121,15 @@ export class Page {
|
|
|
109
121
|
}
|
|
110
122
|
async evaluate(js) {
|
|
111
123
|
const code = wrapForEval(js);
|
|
112
|
-
|
|
124
|
+
try {
|
|
125
|
+
return await sendCommand('exec', { code, ...this._cmdOpts() });
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
if (!isRetryableSettleError(err))
|
|
129
|
+
throw err;
|
|
130
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
131
|
+
return sendCommand('exec', { code, ...this._cmdOpts() });
|
|
132
|
+
}
|
|
113
133
|
}
|
|
114
134
|
async getCookies(opts = {}) {
|
|
115
135
|
const result = await sendCommand('cookies', { ...this._wsOpt(), ...opts });
|
|
@@ -308,6 +328,21 @@ export class Page {
|
|
|
308
328
|
const result = await this.evaluate(generateReadInterceptedJs('__opencli_xhr'));
|
|
309
329
|
return Array.isArray(result) ? result : [];
|
|
310
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* Set local file paths on a file input element via CDP DOM.setFileInputFiles.
|
|
333
|
+
* Chrome reads the files directly from the local filesystem, avoiding the
|
|
334
|
+
* payload size limits of base64-in-evaluate.
|
|
335
|
+
*/
|
|
336
|
+
async setFileInput(files, selector) {
|
|
337
|
+
const result = await sendCommand('set-file-input', {
|
|
338
|
+
files,
|
|
339
|
+
selector,
|
|
340
|
+
...this._cmdOpts(),
|
|
341
|
+
});
|
|
342
|
+
if (!result?.count) {
|
|
343
|
+
throw new Error('setFileInput returned no count — command may not be supported by the extension');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
311
346
|
async waitForCapture(timeout = 10) {
|
|
312
347
|
const maxMs = timeout * 1000;
|
|
313
348
|
await sendCommand('exec', {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
const { sendCommandMock } = vi.hoisted(() => ({
|
|
3
|
+
sendCommandMock: vi.fn(),
|
|
4
|
+
}));
|
|
5
|
+
vi.mock('./daemon-client.js', () => ({
|
|
6
|
+
sendCommand: sendCommandMock,
|
|
7
|
+
}));
|
|
8
|
+
import { Page } from './page.js';
|
|
9
|
+
describe('Page.getCurrentUrl', () => {
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
sendCommandMock.mockReset();
|
|
12
|
+
});
|
|
13
|
+
it('reads the real browser URL when no local navigation cache exists', async () => {
|
|
14
|
+
sendCommandMock.mockResolvedValueOnce('https://notebooklm.google.com/notebook/nb-live');
|
|
15
|
+
const page = new Page('site:notebooklm');
|
|
16
|
+
const url = await page.getCurrentUrl();
|
|
17
|
+
expect(url).toBe('https://notebooklm.google.com/notebook/nb-live');
|
|
18
|
+
expect(sendCommandMock).toHaveBeenCalledTimes(1);
|
|
19
|
+
expect(sendCommandMock).toHaveBeenCalledWith('exec', expect.objectContaining({
|
|
20
|
+
workspace: 'site:notebooklm',
|
|
21
|
+
}));
|
|
22
|
+
});
|
|
23
|
+
it('caches the discovered browser URL for later reads', async () => {
|
|
24
|
+
sendCommandMock.mockResolvedValueOnce('https://notebooklm.google.com/notebook/nb-live');
|
|
25
|
+
const page = new Page('site:notebooklm');
|
|
26
|
+
expect(await page.getCurrentUrl()).toBe('https://notebooklm.google.com/notebook/nb-live');
|
|
27
|
+
expect(await page.getCurrentUrl()).toBe('https://notebooklm.google.com/notebook/nb-live');
|
|
28
|
+
expect(sendCommandMock).toHaveBeenCalledTimes(1);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe('Page.evaluate', () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
sendCommandMock.mockReset();
|
|
34
|
+
});
|
|
35
|
+
it('retries once when the inspected target navigated during exec', async () => {
|
|
36
|
+
sendCommandMock
|
|
37
|
+
.mockRejectedValueOnce(new Error('{"code":-32000,"message":"Inspected target navigated or closed"}'))
|
|
38
|
+
.mockResolvedValueOnce(42);
|
|
39
|
+
const page = new Page('site:notebooklm');
|
|
40
|
+
const value = await page.evaluate('21 + 21');
|
|
41
|
+
expect(value).toBe(42);
|
|
42
|
+
expect(sendCommandMock).toHaveBeenCalledTimes(2);
|
|
43
|
+
});
|
|
44
|
+
});
|