@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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import type { IPage } from '../../types.js';
|
|
3
|
+
import { DOUBAO_DOMAIN, getDoubaoConversationList } from './utils.js';
|
|
4
|
+
|
|
5
|
+
export const historyCommand = cli({
|
|
6
|
+
site: 'doubao',
|
|
7
|
+
name: 'history',
|
|
8
|
+
description: 'List conversation history from Doubao sidebar',
|
|
9
|
+
domain: DOUBAO_DOMAIN,
|
|
10
|
+
strategy: Strategy.COOKIE,
|
|
11
|
+
browser: true,
|
|
12
|
+
navigateBefore: false,
|
|
13
|
+
args: [
|
|
14
|
+
{ name: 'limit', required: false, help: 'Max number of conversations to show', default: '50' },
|
|
15
|
+
],
|
|
16
|
+
columns: ['Index', 'Id', 'Title', 'Url'],
|
|
17
|
+
func: async (page: IPage, kwargs: Record<string, unknown>) => {
|
|
18
|
+
const limit = parseInt(kwargs.limit as string, 10) || 50;
|
|
19
|
+
const conversations = await getDoubaoConversationList(page);
|
|
20
|
+
|
|
21
|
+
if (conversations.length === 0) {
|
|
22
|
+
return [{ Index: 0, Id: '', Title: 'No conversation history found. Make sure you are logged in.', Url: '' }];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return conversations.slice(0, limit).map((conv, i) => ({
|
|
26
|
+
Index: i + 1,
|
|
27
|
+
Id: conv.Id,
|
|
28
|
+
Title: conv.Title,
|
|
29
|
+
Url: conv.Url,
|
|
30
|
+
}));
|
|
31
|
+
},
|
|
32
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import type { IPage } from '../../types.js';
|
|
3
|
+
import {
|
|
4
|
+
DOUBAO_DOMAIN,
|
|
5
|
+
openMeetingPanel,
|
|
6
|
+
getMeetingSummary,
|
|
7
|
+
getMeetingChapters,
|
|
8
|
+
parseDoubaoConversationId,
|
|
9
|
+
} from './utils.js';
|
|
10
|
+
|
|
11
|
+
export const meetingSummaryCommand = cli({
|
|
12
|
+
site: 'doubao',
|
|
13
|
+
name: 'meeting-summary',
|
|
14
|
+
description: 'Get meeting summary and chapters from a Doubao conversation',
|
|
15
|
+
domain: DOUBAO_DOMAIN,
|
|
16
|
+
strategy: Strategy.COOKIE,
|
|
17
|
+
browser: true,
|
|
18
|
+
navigateBefore: false,
|
|
19
|
+
args: [
|
|
20
|
+
{ name: 'id', required: true, positional: true, help: 'Conversation ID (numeric or full URL)' },
|
|
21
|
+
{ name: 'chapters', required: false, help: 'Also include AI chapters', default: 'false' },
|
|
22
|
+
],
|
|
23
|
+
columns: ['Section', 'Content'],
|
|
24
|
+
func: async (page: IPage, kwargs: Record<string, unknown>) => {
|
|
25
|
+
const conversationId = parseDoubaoConversationId(kwargs.id as string);
|
|
26
|
+
const includeChapters = kwargs.chapters === 'true' || kwargs.chapters === true;
|
|
27
|
+
|
|
28
|
+
const opened = await openMeetingPanel(page, conversationId);
|
|
29
|
+
if (!opened) {
|
|
30
|
+
return [{ Section: 'Error', Content: 'No meeting card found in this conversation.' }];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const summary = await getMeetingSummary(page);
|
|
34
|
+
const result: Array<{ Section: string; Content: string }> = [];
|
|
35
|
+
|
|
36
|
+
if (summary) {
|
|
37
|
+
result.push({ Section: 'Summary', Content: summary });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (includeChapters) {
|
|
41
|
+
const chapters = await getMeetingChapters(page);
|
|
42
|
+
if (chapters) {
|
|
43
|
+
result.push({ Section: 'Chapters', Content: chapters });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (result.length === 0) {
|
|
48
|
+
return [{ Section: 'Info', Content: 'Meeting panel opened but no content found yet. Try again.' }];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return result;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import type { IPage } from '../../types.js';
|
|
3
|
+
import {
|
|
4
|
+
DOUBAO_DOMAIN,
|
|
5
|
+
openMeetingPanel,
|
|
6
|
+
getMeetingTranscript,
|
|
7
|
+
parseDoubaoConversationId,
|
|
8
|
+
triggerTranscriptDownload,
|
|
9
|
+
} from './utils.js';
|
|
10
|
+
|
|
11
|
+
export const meetingTranscriptCommand = cli({
|
|
12
|
+
site: 'doubao',
|
|
13
|
+
name: 'meeting-transcript',
|
|
14
|
+
description: 'Get or download the meeting transcript from a Doubao conversation',
|
|
15
|
+
domain: DOUBAO_DOMAIN,
|
|
16
|
+
strategy: Strategy.COOKIE,
|
|
17
|
+
browser: true,
|
|
18
|
+
navigateBefore: false,
|
|
19
|
+
args: [
|
|
20
|
+
{ name: 'id', required: true, positional: true, help: 'Conversation ID (numeric or full URL)' },
|
|
21
|
+
{ name: 'download', required: false, help: 'Trigger browser file download instead of reading text', default: 'false' },
|
|
22
|
+
],
|
|
23
|
+
columns: ['Section', 'Content'],
|
|
24
|
+
func: async (page: IPage, kwargs: Record<string, unknown>) => {
|
|
25
|
+
const conversationId = parseDoubaoConversationId(kwargs.id as string);
|
|
26
|
+
const shouldDownload = kwargs.download === 'true' || kwargs.download === true;
|
|
27
|
+
|
|
28
|
+
const opened = await openMeetingPanel(page, conversationId);
|
|
29
|
+
if (!opened) {
|
|
30
|
+
return [{ Section: 'Error', Content: 'No meeting card found in this conversation.' }];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (shouldDownload) {
|
|
34
|
+
const ok = await triggerTranscriptDownload(page);
|
|
35
|
+
if (!ok) {
|
|
36
|
+
return [{ Section: 'Error', Content: 'Failed to trigger transcript download.' }];
|
|
37
|
+
}
|
|
38
|
+
return [{ Section: 'Download', Content: 'Transcript download triggered in browser. Check your Downloads folder.' }];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const transcript = await getMeetingTranscript(page);
|
|
42
|
+
if (!transcript) {
|
|
43
|
+
return [{ Section: 'Info', Content: 'No transcript content found. The meeting may not have a text record.' }];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return [{ Section: 'Transcript', Content: transcript }];
|
|
47
|
+
},
|
|
48
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { mergeTranscriptSnapshots, parseDoubaoConversationId } from './utils.js';
|
|
3
|
+
|
|
4
|
+
describe('parseDoubaoConversationId', () => {
|
|
5
|
+
it('extracts the numeric id from a full conversation URL', () => {
|
|
6
|
+
expect(parseDoubaoConversationId('https://www.doubao.com/chat/1234567890123')).toBe('1234567890123');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('keeps a raw id unchanged', () => {
|
|
10
|
+
expect(parseDoubaoConversationId('1234567890123')).toBe('1234567890123');
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe('mergeTranscriptSnapshots', () => {
|
|
15
|
+
it('extends the transcript when the next snapshot overlaps with the tail', () => {
|
|
16
|
+
const merged = mergeTranscriptSnapshots(
|
|
17
|
+
'Alice 00:00\nHello team\nBob 00:05\nHi',
|
|
18
|
+
'Bob 00:05\nHi\nAlice 00:10\nNext topic',
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
expect(merged).toBe(
|
|
22
|
+
'Alice 00:00\nHello team\nBob 00:05\nHi\nAlice 00:10\nNext topic',
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('does not duplicate a snapshot that is already contained in the transcript', () => {
|
|
27
|
+
const merged = mergeTranscriptSnapshots(
|
|
28
|
+
'Alice 00:00\nHello team\nBob 00:05\nHi',
|
|
29
|
+
'Bob 00:05\nHi',
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(merged).toBe('Alice 00:00\nHello team\nBob 00:05\nHi');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('keeps both windows when a virtualized panel returns adjacent chunks without full history', () => {
|
|
36
|
+
const merged = mergeTranscriptSnapshots(
|
|
37
|
+
'Alice 00:00\nHello team\nBob 00:05\nHi',
|
|
38
|
+
'Alice 00:10\nNext topic\nBob 00:15\nAction items',
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
expect(merged).toBe(
|
|
42
|
+
'Alice 00:00\nHello team\nBob 00:05\nHi\nAlice 00:10\nNext topic\nBob 00:15\nAction items',
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
});
|
package/src/clis/doubao/utils.ts
CHANGED
|
@@ -4,6 +4,12 @@ export const DOUBAO_DOMAIN = 'www.doubao.com';
|
|
|
4
4
|
export const DOUBAO_CHAT_URL = 'https://www.doubao.com/chat';
|
|
5
5
|
export const DOUBAO_NEW_CHAT_URL = 'https://www.doubao.com/chat/new-thread/create-by-msg';
|
|
6
6
|
|
|
7
|
+
export interface DoubaoConversation {
|
|
8
|
+
Id: string;
|
|
9
|
+
Title: string;
|
|
10
|
+
Url: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
export interface DoubaoTurn {
|
|
8
14
|
Role: 'User' | 'Assistant' | 'System';
|
|
9
15
|
Text: string;
|
|
@@ -605,6 +611,371 @@ export async function waitForDoubaoResponse(
|
|
|
605
611
|
return lastCandidate;
|
|
606
612
|
}
|
|
607
613
|
|
|
614
|
+
function getConversationListScript(): string {
|
|
615
|
+
return `
|
|
616
|
+
(() => {
|
|
617
|
+
const sidebar = document.querySelector('[data-testid="flow_chat_sidebar"]');
|
|
618
|
+
if (!sidebar) return [];
|
|
619
|
+
|
|
620
|
+
const items = Array.from(
|
|
621
|
+
sidebar.querySelectorAll('a[data-testid="chat_list_thread_item"]')
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
return items
|
|
625
|
+
.map(a => {
|
|
626
|
+
const href = a.getAttribute('href') || '';
|
|
627
|
+
const match = href.match(/\\/chat\\/(\\d{10,})/);
|
|
628
|
+
if (!match) return null;
|
|
629
|
+
const id = match[1];
|
|
630
|
+
const textContent = (a.textContent || a.innerText || '').trim();
|
|
631
|
+
const title = textContent
|
|
632
|
+
.replace(/\\s+/g, ' ')
|
|
633
|
+
.substring(0, 200);
|
|
634
|
+
return { id, title, href };
|
|
635
|
+
})
|
|
636
|
+
.filter(Boolean);
|
|
637
|
+
})()
|
|
638
|
+
`;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
export async function getDoubaoConversationList(page: IPage): Promise<DoubaoConversation[]> {
|
|
642
|
+
await ensureDoubaoChatPage(page);
|
|
643
|
+
const raw = await page.evaluate(getConversationListScript()) as
|
|
644
|
+
Array<{ id: string; title: string; href: string }>;
|
|
645
|
+
|
|
646
|
+
if (!Array.isArray(raw)) return [];
|
|
647
|
+
|
|
648
|
+
return raw.map((item) => ({
|
|
649
|
+
Id: item.id,
|
|
650
|
+
Title: item.title,
|
|
651
|
+
Url: `${DOUBAO_CHAT_URL}/${item.id}`,
|
|
652
|
+
}));
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// ---------------------------------------------------------------------------
|
|
656
|
+
// Conversation detail helpers
|
|
657
|
+
// ---------------------------------------------------------------------------
|
|
658
|
+
|
|
659
|
+
export interface DoubaoMessage {
|
|
660
|
+
Role: 'User' | 'Assistant' | 'System';
|
|
661
|
+
Text: string;
|
|
662
|
+
HasMeetingCard: boolean;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
export interface DoubaoMeetingInfo {
|
|
666
|
+
title: string;
|
|
667
|
+
time: string;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
export function parseDoubaoConversationId(input: string): string {
|
|
671
|
+
const match = input.match(/(\d{10,})/);
|
|
672
|
+
return match ? match[1] : input;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
function getConversationDetailScript(): string {
|
|
676
|
+
return `
|
|
677
|
+
(() => {
|
|
678
|
+
const clean = (v) => (v || '').replace(/\\u00a0/g, ' ').replace(/\\n{3,}/g, '\\n\\n').trim();
|
|
679
|
+
|
|
680
|
+
const messageList = document.querySelector('[data-testid="message-list"]');
|
|
681
|
+
if (!messageList) return { messages: [], meeting: null };
|
|
682
|
+
|
|
683
|
+
const meetingCard = messageList.querySelector('[data-testid="meeting-minutes-card"]');
|
|
684
|
+
let meeting = null;
|
|
685
|
+
if (meetingCard) {
|
|
686
|
+
const raw = clean(meetingCard.textContent || '');
|
|
687
|
+
const match = raw.match(/^(.+?)(?:会议时间:|\\s*$)(.*)/);
|
|
688
|
+
meeting = {
|
|
689
|
+
title: match ? match[1].trim() : raw,
|
|
690
|
+
time: match && match[2] ? match[2].trim() : '',
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
const unions = Array.from(messageList.querySelectorAll('[data-testid="union_message"]'));
|
|
695
|
+
const messages = unions.map(u => {
|
|
696
|
+
const isSend = !!u.querySelector('[data-testid="send_message"]');
|
|
697
|
+
const isReceive = !!u.querySelector('[data-testid="receive_message"]');
|
|
698
|
+
const textEl = u.querySelector('[data-testid="message_text_content"]');
|
|
699
|
+
const text = textEl ? clean(textEl.innerText || textEl.textContent || '') : '';
|
|
700
|
+
return {
|
|
701
|
+
role: isSend ? 'User' : isReceive ? 'Assistant' : 'System',
|
|
702
|
+
text,
|
|
703
|
+
hasMeetingCard: !!u.querySelector('[data-testid="meeting-minutes-card"]'),
|
|
704
|
+
};
|
|
705
|
+
}).filter(m => m.text);
|
|
706
|
+
|
|
707
|
+
return { messages, meeting };
|
|
708
|
+
})()
|
|
709
|
+
`;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
export async function navigateToConversation(page: IPage, conversationId: string): Promise<void> {
|
|
713
|
+
const url = `${DOUBAO_CHAT_URL}/${conversationId}`;
|
|
714
|
+
const currentUrl = await page.evaluate('window.location.href').catch(() => '');
|
|
715
|
+
if (typeof currentUrl === 'string' && currentUrl.includes(`/chat/${conversationId}`)) {
|
|
716
|
+
await page.wait(1);
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
await page.goto(url, { waitUntil: 'load', settleMs: 3000 });
|
|
720
|
+
await page.wait(2);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
export async function getConversationDetail(
|
|
724
|
+
page: IPage,
|
|
725
|
+
conversationId: string,
|
|
726
|
+
): Promise<{ messages: DoubaoMessage[]; meeting: DoubaoMeetingInfo | null }> {
|
|
727
|
+
await navigateToConversation(page, conversationId);
|
|
728
|
+
const raw = await page.evaluate(getConversationDetailScript()) as {
|
|
729
|
+
messages: Array<{ role: string; text: string; hasMeetingCard: boolean }>;
|
|
730
|
+
meeting: { title: string; time: string } | null;
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
const messages: DoubaoMessage[] = (raw.messages || []).map((m) => ({
|
|
734
|
+
Role: m.role as 'User' | 'Assistant' | 'System',
|
|
735
|
+
Text: m.text,
|
|
736
|
+
HasMeetingCard: m.hasMeetingCard,
|
|
737
|
+
}));
|
|
738
|
+
|
|
739
|
+
return { messages, meeting: raw.meeting };
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// ---------------------------------------------------------------------------
|
|
743
|
+
// Meeting minutes panel helpers
|
|
744
|
+
// ---------------------------------------------------------------------------
|
|
745
|
+
|
|
746
|
+
function clickMeetingCardScript(): string {
|
|
747
|
+
return `
|
|
748
|
+
(() => {
|
|
749
|
+
const card = document.querySelector('[data-testid="meeting-minutes-card"]');
|
|
750
|
+
if (!card) return false;
|
|
751
|
+
card.click();
|
|
752
|
+
return true;
|
|
753
|
+
})()
|
|
754
|
+
`;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
function readMeetingSummaryScript(): string {
|
|
758
|
+
return `
|
|
759
|
+
(() => {
|
|
760
|
+
const panel = document.querySelector('[data-testid="canvas_panel_container"]');
|
|
761
|
+
if (!panel) return { error: 'no panel' };
|
|
762
|
+
|
|
763
|
+
const summary = panel.querySelector('[data-testid="meeting-summary-todos"]');
|
|
764
|
+
const summaryText = summary
|
|
765
|
+
? (summary.innerText || summary.textContent || '').trim()
|
|
766
|
+
: '';
|
|
767
|
+
|
|
768
|
+
return { summary: summaryText };
|
|
769
|
+
})()
|
|
770
|
+
`;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
function clickTextNotesTabScript(): string {
|
|
774
|
+
return `
|
|
775
|
+
(() => {
|
|
776
|
+
const panel = document.querySelector('[data-testid="canvas_panel_container"]');
|
|
777
|
+
if (!panel) return false;
|
|
778
|
+
const tabs = panel.querySelectorAll('[role="tab"], .semi-tabs-tab');
|
|
779
|
+
for (const tab of tabs) {
|
|
780
|
+
if ((tab.textContent || '').trim().includes('文字')) {
|
|
781
|
+
tab.click();
|
|
782
|
+
return true;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
return false;
|
|
786
|
+
})()
|
|
787
|
+
`;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
function readTextNotesScript(): string {
|
|
791
|
+
return `
|
|
792
|
+
(() => {
|
|
793
|
+
const panel = document.querySelector('[data-testid="canvas_panel_container"]');
|
|
794
|
+
if (!panel) return '';
|
|
795
|
+
const textNotes = panel.querySelector('[data-testid="meeting-text-notes"]');
|
|
796
|
+
if (!textNotes) return '';
|
|
797
|
+
return (textNotes.innerText || textNotes.textContent || '').trim();
|
|
798
|
+
})()
|
|
799
|
+
`;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
function normalizeTranscriptLines(text: string): string[] {
|
|
803
|
+
return text
|
|
804
|
+
.split('\n')
|
|
805
|
+
.map(line => line.trim())
|
|
806
|
+
.filter(Boolean);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
function containsLineSequence(haystack: string[], needle: string[]): boolean {
|
|
810
|
+
if (needle.length === 0) return true;
|
|
811
|
+
if (needle.length > haystack.length) return false;
|
|
812
|
+
|
|
813
|
+
for (let start = 0; start <= haystack.length - needle.length; start += 1) {
|
|
814
|
+
let matched = true;
|
|
815
|
+
for (let offset = 0; offset < needle.length; offset += 1) {
|
|
816
|
+
if (haystack[start + offset] !== needle[offset]) {
|
|
817
|
+
matched = false;
|
|
818
|
+
break;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (matched) return true;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
return false;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
export function mergeTranscriptSnapshots(existing: string, incoming: string): string {
|
|
828
|
+
const currentLines = normalizeTranscriptLines(existing);
|
|
829
|
+
const nextLines = normalizeTranscriptLines(incoming);
|
|
830
|
+
|
|
831
|
+
if (nextLines.length === 0) return currentLines.join('\n');
|
|
832
|
+
if (currentLines.length === 0) return nextLines.join('\n');
|
|
833
|
+
if (containsLineSequence(currentLines, nextLines)) return currentLines.join('\n');
|
|
834
|
+
|
|
835
|
+
const maxOverlap = Math.min(currentLines.length, nextLines.length);
|
|
836
|
+
for (let overlap = maxOverlap; overlap > 0; overlap -= 1) {
|
|
837
|
+
let matched = true;
|
|
838
|
+
for (let index = 0; index < overlap; index += 1) {
|
|
839
|
+
if (currentLines[currentLines.length - overlap + index] !== nextLines[index]) {
|
|
840
|
+
matched = false;
|
|
841
|
+
break;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
if (matched) {
|
|
845
|
+
return [...currentLines, ...nextLines.slice(overlap)].join('\n');
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
return [...currentLines, ...nextLines].join('\n');
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
function clickChapterTabScript(): string {
|
|
853
|
+
return `
|
|
854
|
+
(() => {
|
|
855
|
+
const panel = document.querySelector('[data-testid="canvas_panel_container"]');
|
|
856
|
+
if (!panel) return false;
|
|
857
|
+
const tabs = panel.querySelectorAll('[role="tab"], .semi-tabs-tab');
|
|
858
|
+
for (const tab of tabs) {
|
|
859
|
+
if ((tab.textContent || '').trim().includes('章节')) {
|
|
860
|
+
tab.click();
|
|
861
|
+
return true;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
return false;
|
|
865
|
+
})()
|
|
866
|
+
`;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
function readChapterScript(): string {
|
|
870
|
+
return `
|
|
871
|
+
(() => {
|
|
872
|
+
const panel = document.querySelector('[data-testid="canvas_panel_container"]');
|
|
873
|
+
if (!panel) return '';
|
|
874
|
+
const chapter = panel.querySelector('[data-testid="meeting-ai-chapter"]');
|
|
875
|
+
if (!chapter) return '';
|
|
876
|
+
return (chapter.innerText || chapter.textContent || '').trim();
|
|
877
|
+
})()
|
|
878
|
+
`;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
function triggerTranscriptDownloadScript(): string {
|
|
882
|
+
return `
|
|
883
|
+
(() => {
|
|
884
|
+
const panel = document.querySelector('[data-testid="canvas_panel_container"]');
|
|
885
|
+
if (!panel) return { error: 'no panel' };
|
|
886
|
+
|
|
887
|
+
const downloadIcon = panel.querySelector('[class*="DownloadMeetingAudio"] span[role="img"]');
|
|
888
|
+
if (!downloadIcon) return { error: 'no download icon' };
|
|
889
|
+
|
|
890
|
+
downloadIcon.click();
|
|
891
|
+
return { clicked: 'icon' };
|
|
892
|
+
})()
|
|
893
|
+
`;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
function clickTranscriptDownloadBtnScript(): string {
|
|
897
|
+
return `
|
|
898
|
+
(() => {
|
|
899
|
+
const btn = document.querySelector('[data-testid="minutes-download-text-btn"]');
|
|
900
|
+
if (!btn) return { error: 'no download text btn' };
|
|
901
|
+
btn.click();
|
|
902
|
+
return { clicked: 'transcript' };
|
|
903
|
+
})()
|
|
904
|
+
`;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
export async function openMeetingPanel(page: IPage, conversationId: string): Promise<boolean> {
|
|
908
|
+
await navigateToConversation(page, conversationId);
|
|
909
|
+
const clicked = await page.evaluate(clickMeetingCardScript()) as boolean;
|
|
910
|
+
if (!clicked) return false;
|
|
911
|
+
await page.wait(2);
|
|
912
|
+
return true;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
export async function getMeetingSummary(page: IPage): Promise<string> {
|
|
916
|
+
const result = await page.evaluate(readMeetingSummaryScript()) as { summary?: string; error?: string };
|
|
917
|
+
return result.summary || '';
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
export async function getMeetingChapters(page: IPage): Promise<string> {
|
|
921
|
+
await page.evaluate(clickChapterTabScript());
|
|
922
|
+
await page.wait(1.5);
|
|
923
|
+
return await page.evaluate(readChapterScript()) as string;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
function scrollTextNotesPanelScript(): string {
|
|
927
|
+
return `
|
|
928
|
+
(() => {
|
|
929
|
+
const panel = document.querySelector('[data-testid="canvas_panel_container"]');
|
|
930
|
+
if (!panel) return 0;
|
|
931
|
+
const textNotes = panel.querySelector('[data-testid="meeting-text-notes"]');
|
|
932
|
+
if (!textNotes) return 0;
|
|
933
|
+
|
|
934
|
+
const scrollable = textNotes.closest('[class*="overflow"]')
|
|
935
|
+
|| textNotes.parentElement
|
|
936
|
+
|| textNotes;
|
|
937
|
+
const maxScroll = scrollable.scrollHeight - scrollable.clientHeight;
|
|
938
|
+
if (maxScroll > 0) {
|
|
939
|
+
scrollable.scrollTop = scrollable.scrollHeight;
|
|
940
|
+
}
|
|
941
|
+
return maxScroll;
|
|
942
|
+
})()
|
|
943
|
+
`;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
export async function getMeetingTranscript(page: IPage): Promise<string> {
|
|
947
|
+
await page.evaluate(clickTextNotesTabScript());
|
|
948
|
+
await page.wait(2);
|
|
949
|
+
|
|
950
|
+
let merged = '';
|
|
951
|
+
let stableRounds = 0;
|
|
952
|
+
for (let i = 0; i < 10; i++) {
|
|
953
|
+
await page.evaluate(scrollTextNotesPanelScript());
|
|
954
|
+
await page.wait(1);
|
|
955
|
+
const snapshot = await page.evaluate(readTextNotesScript()) as string;
|
|
956
|
+
const nextMerged = mergeTranscriptSnapshots(merged, snapshot);
|
|
957
|
+
|
|
958
|
+
if (nextMerged === merged && snapshot.length > 0) {
|
|
959
|
+
stableRounds += 1;
|
|
960
|
+
if (stableRounds >= 2) break;
|
|
961
|
+
} else {
|
|
962
|
+
stableRounds = 0;
|
|
963
|
+
merged = nextMerged;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
return merged;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
export async function triggerTranscriptDownload(page: IPage): Promise<boolean> {
|
|
971
|
+
const iconResult = await page.evaluate(triggerTranscriptDownloadScript()) as { clicked?: string; error?: string };
|
|
972
|
+
if (iconResult.error) return false;
|
|
973
|
+
await page.wait(1);
|
|
974
|
+
|
|
975
|
+
const btnResult = await page.evaluate(clickTranscriptDownloadBtnScript()) as { clicked?: string; error?: string };
|
|
976
|
+
return !btnResult.error;
|
|
977
|
+
}
|
|
978
|
+
|
|
608
979
|
export async function startNewDoubaoChat(page: IPage): Promise<string> {
|
|
609
980
|
await ensureDoubaoChatPage(page);
|
|
610
981
|
const clickedLabel = await page.evaluate(clickNewChatScript()) as string;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { IPage } from '../../../types.js';
|
|
2
|
+
import { browserFetch } from './browser-fetch.js';
|
|
3
|
+
|
|
4
|
+
export interface DouyinComment {
|
|
5
|
+
text?: string;
|
|
6
|
+
digg_count?: number;
|
|
7
|
+
user?: {
|
|
8
|
+
nickname?: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface DouyinVideo {
|
|
13
|
+
aweme_id: string;
|
|
14
|
+
desc?: string;
|
|
15
|
+
video?: {
|
|
16
|
+
duration?: number;
|
|
17
|
+
play_addr?: {
|
|
18
|
+
url_list?: string[];
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
statistics?: {
|
|
22
|
+
digg_count?: number;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface DouyinVideoListResponse {
|
|
27
|
+
aweme_list?: DouyinVideo[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface DouyinCommentListResponse {
|
|
31
|
+
comments?: DouyinComment[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function fetchDouyinUserVideos(
|
|
35
|
+
page: IPage,
|
|
36
|
+
secUid: string,
|
|
37
|
+
count: number,
|
|
38
|
+
): Promise<DouyinVideo[]> {
|
|
39
|
+
const params = new URLSearchParams({
|
|
40
|
+
sec_user_id: secUid,
|
|
41
|
+
max_cursor: '0',
|
|
42
|
+
count: String(count),
|
|
43
|
+
aid: '6383',
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const data = await browserFetch(
|
|
47
|
+
page,
|
|
48
|
+
'GET',
|
|
49
|
+
`https://www.douyin.com/aweme/v1/web/aweme/post/?${params.toString()}`,
|
|
50
|
+
{
|
|
51
|
+
headers: { referer: 'https://www.douyin.com/' },
|
|
52
|
+
},
|
|
53
|
+
) as DouyinVideoListResponse;
|
|
54
|
+
|
|
55
|
+
return data.aweme_list || [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function fetchDouyinComments(
|
|
59
|
+
page: IPage,
|
|
60
|
+
awemeId: string,
|
|
61
|
+
count: number,
|
|
62
|
+
): Promise<Array<{ text: string; digg_count: number; nickname: string }>> {
|
|
63
|
+
const params = new URLSearchParams({
|
|
64
|
+
aweme_id: awemeId,
|
|
65
|
+
count: String(count),
|
|
66
|
+
cursor: '0',
|
|
67
|
+
aid: '6383',
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const data = await browserFetch(
|
|
71
|
+
page,
|
|
72
|
+
'GET',
|
|
73
|
+
`https://www.douyin.com/aweme/v1/web/comment/list/?${params.toString()}`,
|
|
74
|
+
{
|
|
75
|
+
headers: { referer: 'https://www.douyin.com/' },
|
|
76
|
+
},
|
|
77
|
+
) as DouyinCommentListResponse;
|
|
78
|
+
|
|
79
|
+
return (data.comments || []).slice(0, count).map((comment) => ({
|
|
80
|
+
text: comment.text || '',
|
|
81
|
+
digg_count: comment.digg_count ?? 0,
|
|
82
|
+
nickname: comment.user?.nickname || '',
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { AuthRequiredError } from '../../../errors.js';
|
|
3
|
+
import { getSts2Credentials } from './sts2.js';
|
|
4
|
+
|
|
5
|
+
describe('douyin sts2 credentials', () => {
|
|
6
|
+
it('accepts top-level credential fields returned by creator center', async () => {
|
|
7
|
+
const page = {
|
|
8
|
+
evaluate: async () => ({
|
|
9
|
+
access_key_id: 'ak',
|
|
10
|
+
secret_access_key: 'sk',
|
|
11
|
+
session_token: 'token',
|
|
12
|
+
expired_time: 1_234_567_890,
|
|
13
|
+
}),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
await expect(getSts2Credentials(page as never)).resolves.toEqual({
|
|
17
|
+
access_key_id: 'ak',
|
|
18
|
+
secret_access_key: 'sk',
|
|
19
|
+
session_token: 'token',
|
|
20
|
+
expired_time: 1_234_567_890,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('still rejects responses without credential fields', async () => {
|
|
25
|
+
const page = {
|
|
26
|
+
evaluate: async () => ({ status_code: 8 }),
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
await expect(getSts2Credentials(page as never)).rejects.toBeInstanceOf(AuthRequiredError);
|
|
30
|
+
});
|
|
31
|
+
});
|