@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,29 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { bindCurrentTab } from '../../browser/daemon-client.js';
|
|
3
|
+
import { NOTEBOOKLM_DOMAIN, NOTEBOOKLM_SITE } from './shared.js';
|
|
4
|
+
import { parseNotebooklmIdFromUrl } from './utils.js';
|
|
5
|
+
cli({
|
|
6
|
+
site: NOTEBOOKLM_SITE,
|
|
7
|
+
name: 'bind-current',
|
|
8
|
+
aliases: ['use'],
|
|
9
|
+
description: 'Bind the current active NotebookLM notebook tab into the site:notebooklm workspace',
|
|
10
|
+
domain: NOTEBOOKLM_DOMAIN,
|
|
11
|
+
strategy: Strategy.COOKIE,
|
|
12
|
+
browser: true,
|
|
13
|
+
navigateBefore: false,
|
|
14
|
+
args: [],
|
|
15
|
+
columns: ['workspace', 'tab_id', 'notebook_id', 'title', 'url'],
|
|
16
|
+
func: async () => {
|
|
17
|
+
const result = await bindCurrentTab(`site:${NOTEBOOKLM_SITE}`, {
|
|
18
|
+
matchDomain: NOTEBOOKLM_DOMAIN,
|
|
19
|
+
matchPathPrefix: '/notebook/',
|
|
20
|
+
});
|
|
21
|
+
return [{
|
|
22
|
+
workspace: result.workspace ?? `site:${NOTEBOOKLM_SITE}`,
|
|
23
|
+
tab_id: result.tabId ?? null,
|
|
24
|
+
notebook_id: result.url ? parseNotebooklmIdFromUrl(result.url) : '',
|
|
25
|
+
title: result.title ?? '',
|
|
26
|
+
url: result.url ?? '',
|
|
27
|
+
}];
|
|
28
|
+
},
|
|
29
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './bind-current.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
const { mockBindCurrentTab } = vi.hoisted(() => ({
|
|
3
|
+
mockBindCurrentTab: vi.fn(),
|
|
4
|
+
}));
|
|
5
|
+
vi.mock('../../browser/daemon-client.js', () => ({
|
|
6
|
+
bindCurrentTab: mockBindCurrentTab,
|
|
7
|
+
}));
|
|
8
|
+
import { getRegistry } from '../../registry.js';
|
|
9
|
+
import './bind-current.js';
|
|
10
|
+
describe('notebooklm bind-current', () => {
|
|
11
|
+
const command = getRegistry().get('notebooklm/bind-current');
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
mockBindCurrentTab.mockReset();
|
|
14
|
+
});
|
|
15
|
+
it('binds the current notebook tab into site:notebooklm', async () => {
|
|
16
|
+
mockBindCurrentTab.mockResolvedValue({
|
|
17
|
+
workspace: 'site:notebooklm',
|
|
18
|
+
tabId: 123,
|
|
19
|
+
title: 'Bound Notebook',
|
|
20
|
+
url: 'https://notebooklm.google.com/notebook/nb-live',
|
|
21
|
+
});
|
|
22
|
+
const result = await command.func({}, {});
|
|
23
|
+
expect(mockBindCurrentTab).toHaveBeenCalledWith('site:notebooklm', {
|
|
24
|
+
matchDomain: 'notebooklm.google.com',
|
|
25
|
+
matchPathPrefix: '/notebook/',
|
|
26
|
+
});
|
|
27
|
+
expect(result).toEqual([{
|
|
28
|
+
workspace: 'site:notebooklm',
|
|
29
|
+
tab_id: 123,
|
|
30
|
+
notebook_id: 'nb-live',
|
|
31
|
+
title: 'Bound Notebook',
|
|
32
|
+
url: 'https://notebooklm.google.com/notebook/nb-live',
|
|
33
|
+
}]);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
const { mockBindCurrentTab } = vi.hoisted(() => ({
|
|
3
|
+
mockBindCurrentTab: vi.fn(),
|
|
4
|
+
}));
|
|
5
|
+
vi.mock('../../browser/daemon-client.js', () => ({
|
|
6
|
+
bindCurrentTab: mockBindCurrentTab,
|
|
7
|
+
}));
|
|
8
|
+
import { ensureNotebooklmNotebookBinding } from './utils.js';
|
|
9
|
+
describe('notebooklm automatic binding', () => {
|
|
10
|
+
const originalEndpoint = process.env.OPENCLI_CDP_ENDPOINT;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
mockBindCurrentTab.mockReset();
|
|
13
|
+
if (originalEndpoint === undefined)
|
|
14
|
+
delete process.env.OPENCLI_CDP_ENDPOINT;
|
|
15
|
+
else
|
|
16
|
+
process.env.OPENCLI_CDP_ENDPOINT = originalEndpoint;
|
|
17
|
+
});
|
|
18
|
+
it('does nothing when the current page is already a notebook page', async () => {
|
|
19
|
+
const page = {
|
|
20
|
+
getCurrentUrl: async () => 'https://notebooklm.google.com/notebook/nb-demo',
|
|
21
|
+
};
|
|
22
|
+
await expect(ensureNotebooklmNotebookBinding(page)).resolves.toBe(false);
|
|
23
|
+
expect(mockBindCurrentTab).not.toHaveBeenCalled();
|
|
24
|
+
});
|
|
25
|
+
it('best-effort binds a notebook page through the browser bridge when currently on home', async () => {
|
|
26
|
+
const page = {
|
|
27
|
+
getCurrentUrl: async () => 'https://notebooklm.google.com/',
|
|
28
|
+
};
|
|
29
|
+
mockBindCurrentTab.mockResolvedValue({});
|
|
30
|
+
await expect(ensureNotebooklmNotebookBinding(page)).resolves.toBe(true);
|
|
31
|
+
expect(mockBindCurrentTab).toHaveBeenCalledWith('site:notebooklm', {
|
|
32
|
+
matchDomain: 'notebooklm.google.com',
|
|
33
|
+
matchPathPrefix: '/notebook/',
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
it('skips daemon binding in direct CDP mode', async () => {
|
|
37
|
+
process.env.OPENCLI_CDP_ENDPOINT = 'ws://127.0.0.1:9222/devtools/page/1';
|
|
38
|
+
const page = {
|
|
39
|
+
getCurrentUrl: async () => 'https://notebooklm.google.com/',
|
|
40
|
+
};
|
|
41
|
+
await expect(ensureNotebooklmNotebookBinding(page)).resolves.toBe(false);
|
|
42
|
+
expect(mockBindCurrentTab).not.toHaveBeenCalled();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { getRegistry } from '../../registry.js';
|
|
3
|
+
import './bind-current.js';
|
|
4
|
+
import './get.js';
|
|
5
|
+
import './note-list.js';
|
|
6
|
+
describe('notebooklm compatibility aliases', () => {
|
|
7
|
+
it('registers use as a compatibility alias for bind-current', () => {
|
|
8
|
+
expect(getRegistry().get('notebooklm/use')).toBe(getRegistry().get('notebooklm/bind-current'));
|
|
9
|
+
});
|
|
10
|
+
it('registers metadata as a compatibility alias for get', () => {
|
|
11
|
+
expect(getRegistry().get('notebooklm/metadata')).toBe(getRegistry().get('notebooklm/get'));
|
|
12
|
+
});
|
|
13
|
+
it('registers notes-list as a compatibility alias for note-list', () => {
|
|
14
|
+
expect(getRegistry().get('notebooklm/notes-list')).toBe(getRegistry().get('notebooklm/note-list'));
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { EmptyResultError } from '../../errors.js';
|
|
3
|
+
import { NOTEBOOKLM_DOMAIN, NOTEBOOKLM_SITE } from './shared.js';
|
|
4
|
+
import { ensureNotebooklmNotebookBinding, getNotebooklmPageState, readCurrentNotebooklm, requireNotebooklmSession } from './utils.js';
|
|
5
|
+
cli({
|
|
6
|
+
site: NOTEBOOKLM_SITE,
|
|
7
|
+
name: 'current',
|
|
8
|
+
description: 'Show metadata for the currently opened NotebookLM notebook tab',
|
|
9
|
+
domain: NOTEBOOKLM_DOMAIN,
|
|
10
|
+
strategy: Strategy.COOKIE,
|
|
11
|
+
browser: true,
|
|
12
|
+
navigateBefore: false,
|
|
13
|
+
args: [],
|
|
14
|
+
columns: ['id', 'title', 'url', 'source'],
|
|
15
|
+
func: async (page) => {
|
|
16
|
+
await ensureNotebooklmNotebookBinding(page);
|
|
17
|
+
await requireNotebooklmSession(page);
|
|
18
|
+
const state = await getNotebooklmPageState(page);
|
|
19
|
+
if (state.kind !== 'notebook') {
|
|
20
|
+
throw new EmptyResultError('opencli notebooklm current', 'Open a specific NotebookLM notebook tab first, then retry.');
|
|
21
|
+
}
|
|
22
|
+
const current = await readCurrentNotebooklm(page);
|
|
23
|
+
if (!current) {
|
|
24
|
+
throw new EmptyResultError('opencli notebooklm current', 'NotebookLM notebook metadata was not found on the current page.');
|
|
25
|
+
}
|
|
26
|
+
return [current];
|
|
27
|
+
},
|
|
28
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { EmptyResultError } from '../../errors.js';
|
|
3
|
+
import { NOTEBOOKLM_DOMAIN, NOTEBOOKLM_SITE } from './shared.js';
|
|
4
|
+
import { ensureNotebooklmNotebookBinding, getNotebooklmDetailViaRpc, getNotebooklmPageState, readCurrentNotebooklm, requireNotebooklmSession, } from './utils.js';
|
|
5
|
+
cli({
|
|
6
|
+
site: NOTEBOOKLM_SITE,
|
|
7
|
+
name: 'get',
|
|
8
|
+
aliases: ['metadata'],
|
|
9
|
+
description: 'Get rich metadata for the currently opened NotebookLM notebook',
|
|
10
|
+
domain: NOTEBOOKLM_DOMAIN,
|
|
11
|
+
strategy: Strategy.COOKIE,
|
|
12
|
+
browser: true,
|
|
13
|
+
navigateBefore: false,
|
|
14
|
+
args: [],
|
|
15
|
+
columns: ['id', 'title', 'emoji', 'source_count', 'created_at', 'updated_at', 'url', 'source'],
|
|
16
|
+
func: async (page) => {
|
|
17
|
+
await ensureNotebooklmNotebookBinding(page);
|
|
18
|
+
await requireNotebooklmSession(page);
|
|
19
|
+
const state = await getNotebooklmPageState(page);
|
|
20
|
+
if (state.kind !== 'notebook') {
|
|
21
|
+
throw new EmptyResultError('opencli notebooklm get', 'Open a specific NotebookLM notebook tab first, then retry.');
|
|
22
|
+
}
|
|
23
|
+
const rpcRow = await getNotebooklmDetailViaRpc(page).catch(() => null);
|
|
24
|
+
if (rpcRow)
|
|
25
|
+
return [rpcRow];
|
|
26
|
+
const current = await readCurrentNotebooklm(page);
|
|
27
|
+
if (!current) {
|
|
28
|
+
throw new EmptyResultError('opencli notebooklm get', 'NotebookLM notebook metadata was not found on the current page.');
|
|
29
|
+
}
|
|
30
|
+
return [{
|
|
31
|
+
...current,
|
|
32
|
+
emoji: null,
|
|
33
|
+
source_count: null,
|
|
34
|
+
updated_at: null,
|
|
35
|
+
}];
|
|
36
|
+
},
|
|
37
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { EmptyResultError } from '../../errors.js';
|
|
3
|
+
import { NOTEBOOKLM_DOMAIN, NOTEBOOKLM_SITE } from './shared.js';
|
|
4
|
+
import { ensureNotebooklmNotebookBinding, getNotebooklmPageState, listNotebooklmHistoryViaRpc, requireNotebooklmSession, } from './utils.js';
|
|
5
|
+
cli({
|
|
6
|
+
site: NOTEBOOKLM_SITE,
|
|
7
|
+
name: 'history',
|
|
8
|
+
description: 'List NotebookLM conversation history threads in the current notebook',
|
|
9
|
+
domain: NOTEBOOKLM_DOMAIN,
|
|
10
|
+
strategy: Strategy.COOKIE,
|
|
11
|
+
browser: true,
|
|
12
|
+
navigateBefore: false,
|
|
13
|
+
args: [],
|
|
14
|
+
columns: ['thread_id', 'item_count', 'preview', 'source', 'notebook_id', 'url'],
|
|
15
|
+
func: async (page) => {
|
|
16
|
+
await ensureNotebooklmNotebookBinding(page);
|
|
17
|
+
await requireNotebooklmSession(page);
|
|
18
|
+
const state = await getNotebooklmPageState(page);
|
|
19
|
+
if (state.kind !== 'notebook') {
|
|
20
|
+
throw new EmptyResultError('opencli notebooklm history', 'Open a specific NotebookLM notebook tab first, then retry.');
|
|
21
|
+
}
|
|
22
|
+
const rows = await listNotebooklmHistoryViaRpc(page);
|
|
23
|
+
return rows;
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './history.js';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
const { mockListNotebooklmHistoryViaRpc, mockGetNotebooklmPageState, mockRequireNotebooklmSession, } = vi.hoisted(() => ({
|
|
3
|
+
mockListNotebooklmHistoryViaRpc: vi.fn(),
|
|
4
|
+
mockGetNotebooklmPageState: vi.fn(),
|
|
5
|
+
mockRequireNotebooklmSession: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
vi.mock('./utils.js', async () => {
|
|
8
|
+
const actual = await vi.importActual('./utils.js');
|
|
9
|
+
return {
|
|
10
|
+
...actual,
|
|
11
|
+
getNotebooklmPageState: mockGetNotebooklmPageState,
|
|
12
|
+
listNotebooklmHistoryViaRpc: mockListNotebooklmHistoryViaRpc,
|
|
13
|
+
requireNotebooklmSession: mockRequireNotebooklmSession,
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
import { getRegistry } from '../../registry.js';
|
|
17
|
+
import './history.js';
|
|
18
|
+
describe('notebooklm history', () => {
|
|
19
|
+
const history = getRegistry().get('notebooklm/history');
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
mockListNotebooklmHistoryViaRpc.mockReset();
|
|
22
|
+
mockGetNotebooklmPageState.mockReset();
|
|
23
|
+
mockRequireNotebooklmSession.mockReset();
|
|
24
|
+
mockRequireNotebooklmSession.mockResolvedValue(undefined);
|
|
25
|
+
mockGetNotebooklmPageState.mockResolvedValue({
|
|
26
|
+
url: 'https://notebooklm.google.com/notebook/nb-demo',
|
|
27
|
+
title: 'Browser Automation',
|
|
28
|
+
hostname: 'notebooklm.google.com',
|
|
29
|
+
kind: 'notebook',
|
|
30
|
+
notebookId: 'nb-demo',
|
|
31
|
+
loginRequired: false,
|
|
32
|
+
notebookCount: 1,
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
it('lists notebook history threads from the browser rpc', async () => {
|
|
36
|
+
mockListNotebooklmHistoryViaRpc.mockResolvedValue([
|
|
37
|
+
{
|
|
38
|
+
notebook_id: 'nb-demo',
|
|
39
|
+
thread_id: '28e0f2cb-4591-45a3-a661-7653666f7c78',
|
|
40
|
+
item_count: 0,
|
|
41
|
+
preview: 'Summarize this notebook',
|
|
42
|
+
url: 'https://notebooklm.google.com/notebook/nb-demo',
|
|
43
|
+
source: 'rpc',
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
const result = await history.func({}, {});
|
|
47
|
+
expect(result).toEqual([
|
|
48
|
+
{
|
|
49
|
+
notebook_id: 'nb-demo',
|
|
50
|
+
thread_id: '28e0f2cb-4591-45a3-a661-7653666f7c78',
|
|
51
|
+
item_count: 0,
|
|
52
|
+
preview: 'Summarize this notebook',
|
|
53
|
+
url: 'https://notebooklm.google.com/notebook/nb-demo',
|
|
54
|
+
source: 'rpc',
|
|
55
|
+
},
|
|
56
|
+
]);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { AuthRequiredError } from '../../errors.js';
|
|
3
|
+
import { NOTEBOOKLM_DOMAIN, NOTEBOOKLM_SITE } from './shared.js';
|
|
4
|
+
import { ensureNotebooklmHome, listNotebooklmLinks, listNotebooklmViaRpc, readCurrentNotebooklm, requireNotebooklmSession, } from './utils.js';
|
|
5
|
+
cli({
|
|
6
|
+
site: NOTEBOOKLM_SITE,
|
|
7
|
+
name: 'list',
|
|
8
|
+
description: 'List NotebookLM notebooks via in-page batchexecute RPC in the current logged-in session',
|
|
9
|
+
domain: NOTEBOOKLM_DOMAIN,
|
|
10
|
+
strategy: Strategy.COOKIE,
|
|
11
|
+
browser: true,
|
|
12
|
+
navigateBefore: false,
|
|
13
|
+
args: [],
|
|
14
|
+
columns: ['title', 'id', 'is_owner', 'created_at', 'source', 'url'],
|
|
15
|
+
func: async (page) => {
|
|
16
|
+
const currentFallback = await readCurrentNotebooklm(page).catch(() => null);
|
|
17
|
+
await ensureNotebooklmHome(page);
|
|
18
|
+
await requireNotebooklmSession(page);
|
|
19
|
+
try {
|
|
20
|
+
const rpcRows = await listNotebooklmViaRpc(page);
|
|
21
|
+
if (rpcRows.length > 0)
|
|
22
|
+
return rpcRows;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error instanceof AuthRequiredError)
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
const domRows = await listNotebooklmLinks(page);
|
|
29
|
+
if (domRows.length > 0)
|
|
30
|
+
return domRows;
|
|
31
|
+
if (currentFallback)
|
|
32
|
+
return [currentFallback];
|
|
33
|
+
return [];
|
|
34
|
+
},
|
|
35
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { EmptyResultError } from '../../errors.js';
|
|
3
|
+
import { NOTEBOOKLM_DOMAIN, NOTEBOOKLM_SITE } from './shared.js';
|
|
4
|
+
import { ensureNotebooklmNotebookBinding, getNotebooklmPageState, listNotebooklmNotesFromPage, requireNotebooklmSession, } from './utils.js';
|
|
5
|
+
cli({
|
|
6
|
+
site: NOTEBOOKLM_SITE,
|
|
7
|
+
name: 'note-list',
|
|
8
|
+
aliases: ['notes-list'],
|
|
9
|
+
description: 'List saved notes from the Studio panel of the current NotebookLM notebook',
|
|
10
|
+
domain: NOTEBOOKLM_DOMAIN,
|
|
11
|
+
strategy: Strategy.COOKIE,
|
|
12
|
+
browser: true,
|
|
13
|
+
navigateBefore: false,
|
|
14
|
+
args: [],
|
|
15
|
+
columns: ['title', 'created_at', 'source', 'url'],
|
|
16
|
+
func: async (page) => {
|
|
17
|
+
await ensureNotebooklmNotebookBinding(page);
|
|
18
|
+
await requireNotebooklmSession(page);
|
|
19
|
+
const state = await getNotebooklmPageState(page);
|
|
20
|
+
if (state.kind !== 'notebook') {
|
|
21
|
+
throw new EmptyResultError('opencli notebooklm note-list', 'Open a specific NotebookLM notebook tab first, then retry.');
|
|
22
|
+
}
|
|
23
|
+
const rows = await listNotebooklmNotesFromPage(page);
|
|
24
|
+
if (rows.length > 0)
|
|
25
|
+
return rows;
|
|
26
|
+
throw new EmptyResultError('opencli notebooklm note-list', 'No NotebookLM notes are visible in the Studio panel. Reload the notebook page or close the note editor and retry.');
|
|
27
|
+
},
|
|
28
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './note-list.js';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
const { mockListNotebooklmNotesFromPage, mockGetNotebooklmPageState, mockRequireNotebooklmSession } = vi.hoisted(() => ({
|
|
3
|
+
mockListNotebooklmNotesFromPage: vi.fn(),
|
|
4
|
+
mockGetNotebooklmPageState: vi.fn(),
|
|
5
|
+
mockRequireNotebooklmSession: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
vi.mock('./utils.js', async () => {
|
|
8
|
+
const actual = await vi.importActual('./utils.js');
|
|
9
|
+
return {
|
|
10
|
+
...actual,
|
|
11
|
+
getNotebooklmPageState: mockGetNotebooklmPageState,
|
|
12
|
+
listNotebooklmNotesFromPage: mockListNotebooklmNotesFromPage,
|
|
13
|
+
requireNotebooklmSession: mockRequireNotebooklmSession,
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
import { getRegistry } from '../../registry.js';
|
|
17
|
+
import './note-list.js';
|
|
18
|
+
describe('notebooklm note-list', () => {
|
|
19
|
+
const command = getRegistry().get('notebooklm/note-list');
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
mockListNotebooklmNotesFromPage.mockReset();
|
|
22
|
+
mockGetNotebooklmPageState.mockReset();
|
|
23
|
+
mockRequireNotebooklmSession.mockReset();
|
|
24
|
+
mockRequireNotebooklmSession.mockResolvedValue(undefined);
|
|
25
|
+
mockGetNotebooklmPageState.mockResolvedValue({
|
|
26
|
+
url: 'https://notebooklm.google.com/notebook/nb-demo',
|
|
27
|
+
title: 'Browser Automation',
|
|
28
|
+
hostname: 'notebooklm.google.com',
|
|
29
|
+
kind: 'notebook',
|
|
30
|
+
notebookId: 'nb-demo',
|
|
31
|
+
loginRequired: false,
|
|
32
|
+
notebookCount: 1,
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
it('lists notebook notes from the Studio panel', async () => {
|
|
36
|
+
mockListNotebooklmNotesFromPage.mockResolvedValue([
|
|
37
|
+
{
|
|
38
|
+
notebook_id: 'nb-demo',
|
|
39
|
+
title: '新建笔记',
|
|
40
|
+
created_at: '6 分钟前',
|
|
41
|
+
url: 'https://notebooklm.google.com/notebook/nb-demo',
|
|
42
|
+
source: 'studio-list',
|
|
43
|
+
},
|
|
44
|
+
]);
|
|
45
|
+
const result = await command.func({}, {});
|
|
46
|
+
expect(result).toEqual([
|
|
47
|
+
{
|
|
48
|
+
notebook_id: 'nb-demo',
|
|
49
|
+
title: '新建笔记',
|
|
50
|
+
created_at: '6 分钟前',
|
|
51
|
+
url: 'https://notebooklm.google.com/notebook/nb-demo',
|
|
52
|
+
source: 'studio-list',
|
|
53
|
+
},
|
|
54
|
+
]);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { EmptyResultError } from '../../errors.js';
|
|
3
|
+
import { NOTEBOOKLM_DOMAIN, NOTEBOOKLM_SITE } from './shared.js';
|
|
4
|
+
import { ensureNotebooklmNotebookBinding, findNotebooklmNoteRow, getNotebooklmPageState, listNotebooklmNotesFromPage, readNotebooklmVisibleNoteFromPage, requireNotebooklmSession, } from './utils.js';
|
|
5
|
+
function matchesNoteTitle(title, query) {
|
|
6
|
+
const needle = query.trim().toLowerCase();
|
|
7
|
+
if (!needle)
|
|
8
|
+
return false;
|
|
9
|
+
const normalized = title.trim().toLowerCase();
|
|
10
|
+
return normalized === needle || normalized.includes(needle);
|
|
11
|
+
}
|
|
12
|
+
cli({
|
|
13
|
+
site: NOTEBOOKLM_SITE,
|
|
14
|
+
name: 'notes-get',
|
|
15
|
+
description: 'Get one note from the current NotebookLM notebook by title from the visible note editor',
|
|
16
|
+
domain: NOTEBOOKLM_DOMAIN,
|
|
17
|
+
strategy: Strategy.COOKIE,
|
|
18
|
+
browser: true,
|
|
19
|
+
navigateBefore: false,
|
|
20
|
+
args: [
|
|
21
|
+
{
|
|
22
|
+
name: 'note',
|
|
23
|
+
positional: true,
|
|
24
|
+
required: true,
|
|
25
|
+
help: 'Note title or id from the current notebook',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
columns: ['title', 'content', 'source', 'url'],
|
|
29
|
+
func: async (page, kwargs) => {
|
|
30
|
+
await ensureNotebooklmNotebookBinding(page);
|
|
31
|
+
await requireNotebooklmSession(page);
|
|
32
|
+
const state = await getNotebooklmPageState(page);
|
|
33
|
+
if (state.kind !== 'notebook') {
|
|
34
|
+
throw new EmptyResultError('opencli notebooklm notes-get', 'Open a specific NotebookLM notebook tab first, then retry.');
|
|
35
|
+
}
|
|
36
|
+
const query = typeof kwargs.note === 'string' ? kwargs.note : String(kwargs.note ?? '');
|
|
37
|
+
const visible = await readNotebooklmVisibleNoteFromPage(page);
|
|
38
|
+
if (visible && matchesNoteTitle(visible.title, query))
|
|
39
|
+
return [visible];
|
|
40
|
+
const rows = await listNotebooklmNotesFromPage(page);
|
|
41
|
+
const listed = findNotebooklmNoteRow(rows, query);
|
|
42
|
+
if (listed) {
|
|
43
|
+
throw new EmptyResultError('opencli notebooklm notes-get', `Note "${query}" is listed in Studio, but opencli currently reads note content only from the visible note editor. Open that note in NotebookLM, then retry.`);
|
|
44
|
+
}
|
|
45
|
+
throw new EmptyResultError('opencli notebooklm notes-get', `Note "${query}" was not found in the current notebook.`);
|
|
46
|
+
},
|
|
47
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './notes-get.js';
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
const { mockListNotebooklmNotesFromPage, mockReadNotebooklmVisibleNoteFromPage, mockGetNotebooklmPageState, mockRequireNotebooklmSession, } = vi.hoisted(() => ({
|
|
3
|
+
mockListNotebooklmNotesFromPage: vi.fn(),
|
|
4
|
+
mockReadNotebooklmVisibleNoteFromPage: vi.fn(),
|
|
5
|
+
mockGetNotebooklmPageState: vi.fn(),
|
|
6
|
+
mockRequireNotebooklmSession: vi.fn(),
|
|
7
|
+
}));
|
|
8
|
+
vi.mock('./utils.js', async () => {
|
|
9
|
+
const actual = await vi.importActual('./utils.js');
|
|
10
|
+
return {
|
|
11
|
+
...actual,
|
|
12
|
+
listNotebooklmNotesFromPage: mockListNotebooklmNotesFromPage,
|
|
13
|
+
readNotebooklmVisibleNoteFromPage: mockReadNotebooklmVisibleNoteFromPage,
|
|
14
|
+
getNotebooklmPageState: mockGetNotebooklmPageState,
|
|
15
|
+
requireNotebooklmSession: mockRequireNotebooklmSession,
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
import { getRegistry } from '../../registry.js';
|
|
19
|
+
import './notes-get.js';
|
|
20
|
+
describe('notebooklm notes-get', () => {
|
|
21
|
+
const command = getRegistry().get('notebooklm/notes-get');
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
mockListNotebooklmNotesFromPage.mockReset();
|
|
24
|
+
mockReadNotebooklmVisibleNoteFromPage.mockReset();
|
|
25
|
+
mockGetNotebooklmPageState.mockReset();
|
|
26
|
+
mockRequireNotebooklmSession.mockReset();
|
|
27
|
+
mockRequireNotebooklmSession.mockResolvedValue(undefined);
|
|
28
|
+
mockGetNotebooklmPageState.mockResolvedValue({
|
|
29
|
+
url: 'https://notebooklm.google.com/notebook/nb-demo',
|
|
30
|
+
title: 'Browser Automation',
|
|
31
|
+
hostname: 'notebooklm.google.com',
|
|
32
|
+
kind: 'notebook',
|
|
33
|
+
notebookId: 'nb-demo',
|
|
34
|
+
loginRequired: false,
|
|
35
|
+
notebookCount: 1,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it('returns the currently visible note editor content when the title matches', async () => {
|
|
39
|
+
mockReadNotebooklmVisibleNoteFromPage.mockResolvedValue({
|
|
40
|
+
notebook_id: 'nb-demo',
|
|
41
|
+
title: '新建笔记',
|
|
42
|
+
content: '第一段\\n第二段',
|
|
43
|
+
url: 'https://notebooklm.google.com/notebook/nb-demo',
|
|
44
|
+
source: 'studio-editor',
|
|
45
|
+
});
|
|
46
|
+
const result = await command.func({}, { note: '新建笔记' });
|
|
47
|
+
expect(result).toEqual([
|
|
48
|
+
{
|
|
49
|
+
notebook_id: 'nb-demo',
|
|
50
|
+
title: '新建笔记',
|
|
51
|
+
content: '第一段\\n第二段',
|
|
52
|
+
url: 'https://notebooklm.google.com/notebook/nb-demo',
|
|
53
|
+
source: 'studio-editor',
|
|
54
|
+
},
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
it('explains the current visible-note limitation when the target note is listed but not open', async () => {
|
|
58
|
+
mockReadNotebooklmVisibleNoteFromPage.mockResolvedValue(null);
|
|
59
|
+
mockListNotebooklmNotesFromPage.mockResolvedValue([
|
|
60
|
+
{
|
|
61
|
+
notebook_id: 'nb-demo',
|
|
62
|
+
title: '新建笔记',
|
|
63
|
+
created_at: '6 分钟前',
|
|
64
|
+
url: 'https://notebooklm.google.com/notebook/nb-demo',
|
|
65
|
+
source: 'studio-list',
|
|
66
|
+
},
|
|
67
|
+
]);
|
|
68
|
+
await expect(command.func({}, { note: '新建笔记' })).rejects.toMatchObject({
|
|
69
|
+
hint: expect.stringMatching(/currently reads note content only from the visible note editor/i),
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { IPage } from '../../types.js';
|
|
2
|
+
export type NotebooklmPageAuth = {
|
|
3
|
+
csrfToken: string;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
sourcePath: string;
|
|
6
|
+
};
|
|
7
|
+
export type NotebooklmFetchResponse = {
|
|
8
|
+
ok: boolean;
|
|
9
|
+
status: number;
|
|
10
|
+
body: string;
|
|
11
|
+
finalUrl: string;
|
|
12
|
+
};
|
|
13
|
+
export type NotebooklmRpcCallResult = {
|
|
14
|
+
auth: NotebooklmPageAuth;
|
|
15
|
+
url: string;
|
|
16
|
+
requestBody: string;
|
|
17
|
+
response: NotebooklmFetchResponse;
|
|
18
|
+
result: unknown;
|
|
19
|
+
};
|
|
20
|
+
export declare function extractNotebooklmPageAuthFromHtml(html: string, sourcePath?: string, preferredTokens?: {
|
|
21
|
+
csrfToken?: string;
|
|
22
|
+
sessionId?: string;
|
|
23
|
+
}): NotebooklmPageAuth;
|
|
24
|
+
export declare function getNotebooklmPageAuth(page: IPage): Promise<NotebooklmPageAuth>;
|
|
25
|
+
export declare function buildNotebooklmRpcBody(rpcId: string, params: unknown[] | Record<string, unknown> | null, csrfToken: string): string;
|
|
26
|
+
export declare function stripNotebooklmAntiXssi(rawBody: string): string;
|
|
27
|
+
export declare function parseNotebooklmChunkedResponse(rawBody: string): unknown[];
|
|
28
|
+
export declare function extractNotebooklmRpcResult(rawBody: string, rpcId: string): unknown;
|
|
29
|
+
export declare function fetchNotebooklmInPage(page: IPage, url: string, options?: {
|
|
30
|
+
method?: 'GET' | 'POST';
|
|
31
|
+
headers?: Record<string, string>;
|
|
32
|
+
body?: string;
|
|
33
|
+
}): Promise<NotebooklmFetchResponse>;
|
|
34
|
+
export declare function callNotebooklmRpc(page: IPage, rpcId: string, params: unknown[] | Record<string, unknown> | null, options?: {
|
|
35
|
+
hl?: string;
|
|
36
|
+
}): Promise<NotebooklmRpcCallResult>;
|