@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.
Files changed (540) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +31 -4
  3. package/README.zh-CN.md +40 -5
  4. package/SKILL.md +1 -1
  5. package/dist/browser/cdp.d.ts +1 -0
  6. package/dist/browser/cdp.js +30 -27
  7. package/dist/browser/daemon-client.d.ts +11 -1
  8. package/dist/browser/daemon-client.js +3 -0
  9. package/dist/browser/dom-helpers.js +1 -0
  10. package/dist/browser/dom-helpers.test.js +14 -1
  11. package/dist/browser/mcp.js +18 -13
  12. package/dist/browser/page.d.ts +6 -0
  13. package/dist/browser/page.js +37 -2
  14. package/dist/browser/page.test.d.ts +1 -0
  15. package/dist/browser/page.test.js +44 -0
  16. package/dist/browser/stealth.js +198 -0
  17. package/dist/browser/stealth.test.d.ts +1 -0
  18. package/dist/browser/stealth.test.js +134 -0
  19. package/dist/browser.test.js +1 -1
  20. package/dist/build-manifest.d.ts +1 -0
  21. package/dist/build-manifest.js +5 -1
  22. package/dist/build-manifest.test.js +2 -0
  23. package/dist/cli-manifest.json +1821 -252
  24. package/dist/cli.js +20 -3
  25. package/dist/clis/antigravity/serve.d.ts +1 -1
  26. package/dist/clis/antigravity/serve.js +5 -8
  27. package/dist/clis/band/bands.d.ts +1 -0
  28. package/dist/clis/band/bands.js +72 -0
  29. package/dist/clis/band/mentions.d.ts +1 -0
  30. package/dist/clis/band/mentions.js +127 -0
  31. package/dist/clis/band/post.d.ts +1 -0
  32. package/dist/clis/band/post.js +175 -0
  33. package/dist/clis/band/posts.d.ts +1 -0
  34. package/dist/clis/band/posts.js +94 -0
  35. package/dist/clis/bilibili/subtitle.js +4 -0
  36. package/dist/clis/bilibili/subtitle.test.d.ts +1 -0
  37. package/dist/clis/bilibili/subtitle.test.js +48 -0
  38. package/dist/clis/chatwise/ask.js +0 -2
  39. package/dist/clis/chatwise/export.js +0 -2
  40. package/dist/clis/chatwise/history.js +0 -2
  41. package/dist/clis/chatwise/model.js +0 -2
  42. package/dist/clis/chatwise/new.js +1 -2
  43. package/dist/clis/chatwise/read.js +0 -2
  44. package/dist/clis/chatwise/screenshot.js +1 -2
  45. package/dist/clis/chatwise/send.js +0 -2
  46. package/dist/clis/chatwise/status.js +1 -2
  47. package/dist/clis/ctrip/search.d.ts +13 -0
  48. package/dist/clis/ctrip/search.js +73 -48
  49. package/dist/clis/ctrip/search.test.d.ts +1 -0
  50. package/dist/clis/ctrip/search.test.js +64 -0
  51. package/dist/clis/doubao/detail.d.ts +1 -0
  52. package/dist/clis/doubao/detail.js +33 -0
  53. package/dist/clis/doubao/detail.test.d.ts +1 -0
  54. package/dist/clis/doubao/detail.test.js +42 -0
  55. package/dist/clis/doubao/history.d.ts +1 -0
  56. package/dist/clis/doubao/history.js +28 -0
  57. package/dist/clis/doubao/history.test.d.ts +1 -0
  58. package/dist/clis/doubao/history.test.js +37 -0
  59. package/dist/clis/doubao/meeting-summary.d.ts +1 -0
  60. package/dist/clis/doubao/meeting-summary.js +39 -0
  61. package/dist/clis/doubao/meeting-transcript.d.ts +1 -0
  62. package/dist/clis/doubao/meeting-transcript.js +36 -0
  63. package/dist/clis/doubao/utils.d.ts +27 -0
  64. package/dist/clis/doubao/utils.js +317 -0
  65. package/dist/clis/doubao/utils.test.d.ts +1 -0
  66. package/dist/clis/doubao/utils.test.js +24 -0
  67. package/dist/clis/douyin/_shared/public-api.d.ts +33 -0
  68. package/dist/clis/douyin/_shared/public-api.js +29 -0
  69. package/dist/clis/douyin/_shared/sts2.js +8 -2
  70. package/dist/clis/douyin/_shared/sts2.test.d.ts +1 -0
  71. package/dist/clis/douyin/_shared/sts2.test.js +27 -0
  72. package/dist/clis/douyin/activities.js +4 -2
  73. package/dist/clis/douyin/activities.test.js +34 -1
  74. package/dist/clis/douyin/collections.js +1 -1
  75. package/dist/clis/douyin/collections.test.js +24 -2
  76. package/dist/clis/douyin/draft.d.ts +8 -11
  77. package/dist/clis/douyin/draft.js +302 -185
  78. package/dist/clis/douyin/draft.test.d.ts +1 -1
  79. package/dist/clis/douyin/draft.test.js +357 -2
  80. package/dist/clis/douyin/hashtag.js +9 -2
  81. package/dist/clis/douyin/hashtag.test.js +35 -2
  82. package/dist/clis/douyin/profile.js +1 -1
  83. package/dist/clis/douyin/profile.test.js +36 -1
  84. package/dist/clis/douyin/user-videos.d.ts +5 -0
  85. package/dist/clis/douyin/user-videos.js +74 -0
  86. package/dist/clis/douyin/user-videos.test.d.ts +1 -0
  87. package/dist/clis/douyin/user-videos.test.js +108 -0
  88. package/dist/clis/douyin/videos.js +22 -5
  89. package/dist/clis/douyin/videos.test.js +45 -2
  90. package/dist/clis/facebook/search.test.d.ts +5 -0
  91. package/dist/clis/facebook/search.test.js +60 -0
  92. package/dist/clis/facebook/search.yaml +4 -3
  93. package/dist/clis/instagram/download.d.ts +16 -0
  94. package/dist/clis/instagram/download.js +225 -0
  95. package/dist/clis/instagram/download.test.d.ts +1 -0
  96. package/dist/clis/instagram/download.test.js +118 -0
  97. package/dist/clis/notebooklm/bind-current.d.ts +1 -0
  98. package/dist/clis/notebooklm/bind-current.js +29 -0
  99. package/dist/clis/notebooklm/bind-current.test.d.ts +1 -0
  100. package/dist/clis/notebooklm/bind-current.test.js +35 -0
  101. package/dist/clis/notebooklm/binding.test.d.ts +1 -0
  102. package/dist/clis/notebooklm/binding.test.js +44 -0
  103. package/dist/clis/notebooklm/compat.test.d.ts +3 -0
  104. package/dist/clis/notebooklm/compat.test.js +16 -0
  105. package/dist/clis/notebooklm/current.d.ts +1 -0
  106. package/dist/clis/notebooklm/current.js +28 -0
  107. package/dist/clis/notebooklm/get.d.ts +1 -0
  108. package/dist/clis/notebooklm/get.js +37 -0
  109. package/dist/clis/notebooklm/history.d.ts +1 -0
  110. package/dist/clis/notebooklm/history.js +25 -0
  111. package/dist/clis/notebooklm/history.test.d.ts +1 -0
  112. package/dist/clis/notebooklm/history.test.js +58 -0
  113. package/dist/clis/notebooklm/list.d.ts +1 -0
  114. package/dist/clis/notebooklm/list.js +35 -0
  115. package/dist/clis/notebooklm/note-list.d.ts +1 -0
  116. package/dist/clis/notebooklm/note-list.js +28 -0
  117. package/dist/clis/notebooklm/note-list.test.d.ts +1 -0
  118. package/dist/clis/notebooklm/note-list.test.js +56 -0
  119. package/dist/clis/notebooklm/notes-get.d.ts +1 -0
  120. package/dist/clis/notebooklm/notes-get.js +47 -0
  121. package/dist/clis/notebooklm/notes-get.test.d.ts +1 -0
  122. package/dist/clis/notebooklm/notes-get.test.js +72 -0
  123. package/dist/clis/notebooklm/rpc.d.ts +36 -0
  124. package/dist/clis/notebooklm/rpc.js +189 -0
  125. package/dist/clis/notebooklm/rpc.test.d.ts +1 -0
  126. package/dist/clis/notebooklm/rpc.test.js +105 -0
  127. package/dist/clis/notebooklm/shared.d.ts +87 -0
  128. package/dist/clis/notebooklm/shared.js +3 -0
  129. package/dist/clis/notebooklm/source-fulltext.d.ts +1 -0
  130. package/dist/clis/notebooklm/source-fulltext.js +44 -0
  131. package/dist/clis/notebooklm/source-fulltext.test.d.ts +1 -0
  132. package/dist/clis/notebooklm/source-fulltext.test.js +106 -0
  133. package/dist/clis/notebooklm/source-get.d.ts +1 -0
  134. package/dist/clis/notebooklm/source-get.js +40 -0
  135. package/dist/clis/notebooklm/source-get.test.d.ts +1 -0
  136. package/dist/clis/notebooklm/source-get.test.js +84 -0
  137. package/dist/clis/notebooklm/source-guide.d.ts +1 -0
  138. package/dist/clis/notebooklm/source-guide.js +44 -0
  139. package/dist/clis/notebooklm/source-guide.test.d.ts +1 -0
  140. package/dist/clis/notebooklm/source-guide.test.js +104 -0
  141. package/dist/clis/notebooklm/source-list.d.ts +1 -0
  142. package/dist/clis/notebooklm/source-list.js +30 -0
  143. package/dist/clis/notebooklm/status.d.ts +1 -0
  144. package/dist/clis/notebooklm/status.js +31 -0
  145. package/dist/clis/notebooklm/summary.d.ts +1 -0
  146. package/dist/clis/notebooklm/summary.js +30 -0
  147. package/dist/clis/notebooklm/summary.test.d.ts +1 -0
  148. package/dist/clis/notebooklm/summary.test.js +78 -0
  149. package/dist/clis/notebooklm/utils.d.ts +37 -0
  150. package/dist/clis/notebooklm/utils.js +739 -0
  151. package/dist/clis/notebooklm/utils.test.d.ts +1 -0
  152. package/dist/clis/notebooklm/utils.test.js +390 -0
  153. package/dist/clis/ones/common.d.ts +32 -0
  154. package/dist/clis/ones/common.js +144 -0
  155. package/dist/clis/ones/enrich-tasks.d.ts +5 -0
  156. package/dist/clis/ones/enrich-tasks.js +37 -0
  157. package/dist/clis/ones/login.d.ts +1 -0
  158. package/dist/clis/ones/login.js +80 -0
  159. package/dist/clis/ones/logout.d.ts +1 -0
  160. package/dist/clis/ones/logout.js +17 -0
  161. package/dist/clis/ones/me.d.ts +1 -0
  162. package/dist/clis/ones/me.js +30 -0
  163. package/dist/clis/ones/my-tasks.d.ts +1 -0
  164. package/dist/clis/ones/my-tasks.js +120 -0
  165. package/dist/clis/ones/resolve-labels.d.ts +10 -0
  166. package/dist/clis/ones/resolve-labels.js +64 -0
  167. package/dist/clis/ones/task-helpers.d.ts +29 -0
  168. package/dist/clis/ones/task-helpers.js +212 -0
  169. package/dist/clis/ones/task-helpers.test.d.ts +1 -0
  170. package/dist/clis/ones/task-helpers.test.js +12 -0
  171. package/dist/clis/ones/task.d.ts +1 -0
  172. package/dist/clis/ones/task.js +66 -0
  173. package/dist/clis/ones/tasks.d.ts +1 -0
  174. package/dist/clis/ones/tasks.js +79 -0
  175. package/dist/clis/ones/token-info.d.ts +1 -0
  176. package/dist/clis/ones/token-info.js +42 -0
  177. package/dist/clis/ones/worklog.d.ts +11 -0
  178. package/dist/clis/ones/worklog.js +267 -0
  179. package/dist/clis/ones/worklog.test.d.ts +1 -0
  180. package/dist/clis/ones/worklog.test.js +20 -0
  181. package/dist/clis/spotify/spotify.d.ts +1 -0
  182. package/dist/clis/spotify/spotify.js +316 -0
  183. package/dist/clis/spotify/utils.d.ts +21 -0
  184. package/dist/clis/spotify/utils.js +66 -0
  185. package/dist/clis/spotify/utils.test.d.ts +1 -0
  186. package/dist/clis/spotify/utils.test.js +67 -0
  187. package/dist/clis/substack/utils.d.ts +4 -0
  188. package/dist/clis/substack/utils.js +8 -2
  189. package/dist/clis/substack/utils.test.d.ts +1 -0
  190. package/dist/clis/substack/utils.test.js +46 -0
  191. package/dist/clis/tieba/commands.test.d.ts +4 -0
  192. package/dist/clis/tieba/commands.test.js +79 -0
  193. package/dist/clis/tieba/hot.d.ts +1 -0
  194. package/dist/clis/tieba/hot.js +48 -0
  195. package/dist/clis/tieba/posts.d.ts +1 -0
  196. package/dist/clis/tieba/posts.js +85 -0
  197. package/dist/clis/tieba/read.d.ts +1 -0
  198. package/dist/clis/tieba/read.js +140 -0
  199. package/dist/clis/tieba/search.d.ts +1 -0
  200. package/dist/clis/tieba/search.js +108 -0
  201. package/dist/clis/tieba/utils.d.ts +101 -0
  202. package/dist/clis/tieba/utils.js +240 -0
  203. package/dist/clis/tieba/utils.test.d.ts +1 -0
  204. package/dist/clis/tieba/utils.test.js +290 -0
  205. package/dist/clis/v2ex/hot.yaml +4 -1
  206. package/dist/clis/v2ex/latest.yaml +4 -1
  207. package/dist/clis/v2ex/topic.yaml +6 -1
  208. package/dist/clis/weixin/download.d.ts +9 -0
  209. package/dist/clis/weixin/download.js +76 -6
  210. package/dist/clis/weread/book.js +206 -13
  211. package/dist/clis/weread/commands.test.js +331 -0
  212. package/dist/clis/weread/private-api-regression.test.d.ts +1 -0
  213. package/dist/{weread-private-api-regression.test.js → clis/weread/private-api-regression.test.js} +92 -30
  214. package/dist/clis/weread/search-regression.test.d.ts +1 -0
  215. package/dist/clis/weread/search-regression.test.js +407 -0
  216. package/dist/clis/weread/search.js +143 -7
  217. package/dist/clis/weread/shelf.js +13 -95
  218. package/dist/clis/weread/utils.d.ts +56 -0
  219. package/dist/clis/weread/utils.js +234 -7
  220. package/dist/clis/weread/utils.test.js +71 -1
  221. package/dist/clis/xiaohongshu/comments.d.ts +3 -0
  222. package/dist/clis/xiaohongshu/comments.js +76 -17
  223. package/dist/clis/xiaohongshu/comments.test.js +70 -9
  224. package/dist/clis/xiaohongshu/download.d.ts +4 -1
  225. package/dist/clis/xiaohongshu/download.js +83 -22
  226. package/dist/clis/xiaohongshu/download.test.d.ts +1 -0
  227. package/dist/clis/xiaohongshu/download.test.js +75 -0
  228. package/dist/clis/xiaohongshu/note-helpers.d.ts +12 -0
  229. package/dist/clis/xiaohongshu/note-helpers.js +23 -0
  230. package/dist/clis/xiaohongshu/note.d.ts +7 -0
  231. package/dist/clis/xiaohongshu/note.js +76 -0
  232. package/dist/clis/xiaohongshu/note.test.d.ts +1 -0
  233. package/dist/clis/xiaohongshu/note.test.js +136 -0
  234. package/dist/clis/xiaohongshu/publish.d.ts +1 -1
  235. package/dist/clis/xiaohongshu/publish.js +78 -31
  236. package/dist/clis/xiaohongshu/publish.test.js +66 -1
  237. package/dist/clis/xiaohongshu/search.js +9 -0
  238. package/dist/clis/xiaohongshu/search.test.js +10 -4
  239. package/dist/clis/xiaohongshu/user-helpers.d.ts +1 -0
  240. package/dist/clis/xiaohongshu/user-helpers.js +2 -0
  241. package/dist/clis/xiaohongshu/user-helpers.test.js +18 -0
  242. package/dist/clis/xueqiu/comments.d.ts +118 -0
  243. package/dist/clis/xueqiu/comments.js +354 -0
  244. package/dist/clis/xueqiu/comments.test.d.ts +1 -0
  245. package/dist/clis/xueqiu/comments.test.js +696 -0
  246. package/dist/clis/youtube/search.js +57 -17
  247. package/dist/clis/youtube/transcript.js +2 -4
  248. package/dist/clis/youtube/utils.d.ts +9 -0
  249. package/dist/clis/youtube/utils.js +67 -3
  250. package/dist/clis/youtube/utils.test.d.ts +1 -0
  251. package/dist/clis/youtube/utils.test.js +37 -0
  252. package/dist/clis/youtube/video.js +16 -15
  253. package/dist/clis/zhihu/question.js +19 -17
  254. package/dist/clis/zhihu/question.test.d.ts +1 -0
  255. package/dist/clis/zhihu/question.test.js +54 -0
  256. package/dist/clis/zsxq/dynamics.d.ts +1 -0
  257. package/dist/clis/zsxq/dynamics.js +47 -0
  258. package/dist/clis/zsxq/groups.d.ts +1 -0
  259. package/dist/clis/zsxq/groups.js +32 -0
  260. package/dist/clis/zsxq/search.d.ts +1 -0
  261. package/dist/clis/zsxq/search.js +43 -0
  262. package/dist/clis/zsxq/search.test.d.ts +1 -0
  263. package/dist/clis/zsxq/search.test.js +24 -0
  264. package/dist/clis/zsxq/topic.d.ts +1 -0
  265. package/dist/clis/zsxq/topic.js +47 -0
  266. package/dist/clis/zsxq/topic.test.d.ts +1 -0
  267. package/dist/clis/zsxq/topic.test.js +29 -0
  268. package/dist/clis/zsxq/topics.d.ts +1 -0
  269. package/dist/clis/zsxq/topics.js +25 -0
  270. package/dist/clis/zsxq/topics.test.d.ts +1 -0
  271. package/dist/clis/zsxq/topics.test.js +24 -0
  272. package/dist/clis/zsxq/utils.d.ts +97 -0
  273. package/dist/clis/zsxq/utils.js +230 -0
  274. package/dist/commanderAdapter.js +10 -1
  275. package/dist/commanderAdapter.test.js +64 -0
  276. package/dist/commands/daemon.d.ts +9 -0
  277. package/dist/commands/daemon.js +124 -0
  278. package/dist/commands/daemon.test.d.ts +1 -0
  279. package/dist/commands/daemon.test.js +185 -0
  280. package/dist/completion.js +3 -1
  281. package/dist/constants.d.ts +2 -0
  282. package/dist/constants.js +2 -0
  283. package/dist/daemon.d.ts +1 -1
  284. package/dist/daemon.js +25 -14
  285. package/dist/daemon.test.d.ts +1 -0
  286. package/dist/daemon.test.js +65 -0
  287. package/dist/discovery.d.ts +9 -0
  288. package/dist/discovery.js +47 -2
  289. package/dist/electron-apps.d.ts +29 -0
  290. package/dist/electron-apps.js +65 -0
  291. package/dist/electron-apps.test.d.ts +1 -0
  292. package/dist/electron-apps.test.js +43 -0
  293. package/dist/engine.test.js +41 -9
  294. package/dist/execution.js +20 -16
  295. package/dist/external-clis.yaml +17 -0
  296. package/dist/idle-manager.d.ts +19 -0
  297. package/dist/idle-manager.js +54 -0
  298. package/dist/launcher.d.ts +36 -0
  299. package/dist/launcher.js +152 -0
  300. package/dist/launcher.test.d.ts +1 -0
  301. package/dist/launcher.test.js +57 -0
  302. package/dist/main.js +3 -3
  303. package/dist/registry.d.ts +1 -0
  304. package/dist/registry.js +31 -3
  305. package/dist/registry.test.js +13 -0
  306. package/dist/runtime.d.ts +5 -3
  307. package/dist/runtime.js +12 -5
  308. package/dist/serialization.d.ts +1 -0
  309. package/dist/serialization.js +3 -0
  310. package/dist/serialization.test.js +17 -1
  311. package/dist/tui.d.ts +7 -0
  312. package/dist/tui.js +52 -0
  313. package/dist/tui.test.d.ts +1 -0
  314. package/dist/tui.test.js +19 -0
  315. package/dist/types.d.ts +5 -0
  316. package/dist/weixin-download.test.js +14 -0
  317. package/docs/.vitepress/config.mts +4 -0
  318. package/docs/adapters/browser/band.md +63 -0
  319. package/docs/adapters/browser/notebooklm.md +69 -0
  320. package/docs/adapters/browser/ones.md +59 -0
  321. package/docs/adapters/browser/spotify.md +62 -0
  322. package/docs/adapters/browser/tieba.md +45 -0
  323. package/docs/adapters/browser/xiaohongshu.md +19 -10
  324. package/docs/adapters/browser/xueqiu.md +5 -0
  325. package/docs/adapters/browser/zsxq.md +49 -0
  326. package/docs/adapters/index.md +67 -63
  327. package/docs/adapters-doc/ones.md +32 -0
  328. package/docs/guide/browser-bridge.md +12 -0
  329. package/docs/guide/troubleshooting.md +9 -4
  330. package/docs/superpowers/plans/2026-03-31-daemon-lifecycle-redesign.md +857 -0
  331. package/docs/superpowers/specs/2026-03-31-daemon-lifecycle-redesign.md +208 -0
  332. package/docs/zh/guide/browser-bridge.md +12 -0
  333. package/extension/dist/background.js +794 -513
  334. package/extension/src/background.test.ts +202 -2
  335. package/extension/src/background.ts +189 -10
  336. package/extension/src/cdp.ts +54 -0
  337. package/extension/src/protocol.ts +11 -5
  338. package/package.json +1 -1
  339. package/scripts/postinstall.js +16 -0
  340. package/src/browser/cdp.ts +24 -17
  341. package/src/browser/daemon-client.ts +11 -1
  342. package/src/browser/dom-helpers.test.ts +15 -1
  343. package/src/browser/dom-helpers.ts +1 -0
  344. package/src/browser/mcp.ts +18 -13
  345. package/src/browser/page.test.ts +58 -0
  346. package/src/browser/page.ts +34 -2
  347. package/src/browser/stealth.test.ts +153 -0
  348. package/src/browser/stealth.ts +198 -0
  349. package/src/browser.test.ts +1 -1
  350. package/src/build-manifest.test.ts +2 -0
  351. package/src/build-manifest.ts +6 -1
  352. package/src/cli.ts +21 -3
  353. package/src/clis/antigravity/SKILL.md +3 -12
  354. package/src/clis/antigravity/serve.ts +5 -10
  355. package/src/clis/band/bands.ts +76 -0
  356. package/src/clis/band/mentions.ts +134 -0
  357. package/src/clis/band/post.ts +187 -0
  358. package/src/clis/band/posts.ts +106 -0
  359. package/src/clis/bilibili/subtitle.test.ts +60 -0
  360. package/src/clis/bilibili/subtitle.ts +4 -0
  361. package/src/clis/chatwise/ask.ts +0 -2
  362. package/src/clis/chatwise/export.ts +0 -2
  363. package/src/clis/chatwise/history.ts +0 -2
  364. package/src/clis/chatwise/model.ts +0 -2
  365. package/src/clis/chatwise/new.ts +1 -2
  366. package/src/clis/chatwise/read.ts +0 -2
  367. package/src/clis/chatwise/screenshot.ts +1 -2
  368. package/src/clis/chatwise/send.ts +0 -2
  369. package/src/clis/chatwise/status.ts +1 -2
  370. package/src/clis/ctrip/search.test.ts +73 -0
  371. package/src/clis/ctrip/search.ts +97 -47
  372. package/src/clis/doubao/detail.test.ts +53 -0
  373. package/src/clis/doubao/detail.ts +41 -0
  374. package/src/clis/doubao/history.test.ts +45 -0
  375. package/src/clis/doubao/history.ts +32 -0
  376. package/src/clis/doubao/meeting-summary.ts +53 -0
  377. package/src/clis/doubao/meeting-transcript.ts +48 -0
  378. package/src/clis/doubao/utils.test.ts +45 -0
  379. package/src/clis/doubao/utils.ts +371 -0
  380. package/src/clis/douyin/_shared/public-api.ts +84 -0
  381. package/src/clis/douyin/_shared/sts2.test.ts +31 -0
  382. package/src/clis/douyin/_shared/sts2.ts +11 -3
  383. package/src/clis/douyin/activities.test.ts +41 -1
  384. package/src/clis/douyin/activities.ts +12 -3
  385. package/src/clis/douyin/collections.test.ts +35 -2
  386. package/src/clis/douyin/collections.ts +1 -1
  387. package/src/clis/douyin/draft.test.ts +444 -2
  388. package/src/clis/douyin/draft.ts +382 -218
  389. package/src/clis/douyin/hashtag.test.ts +42 -2
  390. package/src/clis/douyin/hashtag.ts +11 -3
  391. package/src/clis/douyin/profile.test.ts +43 -1
  392. package/src/clis/douyin/profile.ts +9 -2
  393. package/src/clis/douyin/user-videos.test.ts +122 -0
  394. package/src/clis/douyin/user-videos.ts +101 -0
  395. package/src/clis/douyin/videos.test.ts +52 -2
  396. package/src/clis/douyin/videos.ts +49 -15
  397. package/src/clis/facebook/search.test.ts +70 -0
  398. package/src/clis/facebook/search.yaml +4 -3
  399. package/src/clis/instagram/download.test.ts +159 -0
  400. package/src/clis/instagram/download.ts +286 -0
  401. package/src/clis/notebooklm/bind-current.test.ts +43 -0
  402. package/src/clis/notebooklm/bind-current.ts +36 -0
  403. package/src/clis/notebooklm/binding.test.ts +53 -0
  404. package/src/clis/notebooklm/compat.test.ts +19 -0
  405. package/src/clis/notebooklm/current.ts +38 -0
  406. package/src/clis/notebooklm/get.ts +53 -0
  407. package/src/clis/notebooklm/history.test.ts +70 -0
  408. package/src/clis/notebooklm/history.ts +36 -0
  409. package/src/clis/notebooklm/list.ts +40 -0
  410. package/src/clis/notebooklm/note-list.test.ts +64 -0
  411. package/src/clis/notebooklm/note-list.ts +42 -0
  412. package/src/clis/notebooklm/notes-get.test.ts +88 -0
  413. package/src/clis/notebooklm/notes-get.ts +67 -0
  414. package/src/clis/notebooklm/rpc.test.ts +126 -0
  415. package/src/clis/notebooklm/rpc.ts +286 -0
  416. package/src/clis/notebooklm/shared.ts +98 -0
  417. package/src/clis/notebooklm/source-fulltext.test.ts +123 -0
  418. package/src/clis/notebooklm/source-fulltext.ts +69 -0
  419. package/src/clis/notebooklm/source-get.test.ts +100 -0
  420. package/src/clis/notebooklm/source-get.ts +60 -0
  421. package/src/clis/notebooklm/source-guide.test.ts +121 -0
  422. package/src/clis/notebooklm/source-guide.ts +69 -0
  423. package/src/clis/notebooklm/source-list.ts +45 -0
  424. package/src/clis/notebooklm/status.ts +34 -0
  425. package/src/clis/notebooklm/summary.test.ts +94 -0
  426. package/src/clis/notebooklm/summary.ts +45 -0
  427. package/src/clis/notebooklm/utils.test.ts +446 -0
  428. package/src/clis/notebooklm/utils.ts +893 -0
  429. package/src/clis/ones/common.ts +187 -0
  430. package/src/clis/ones/enrich-tasks.ts +47 -0
  431. package/src/clis/ones/login.ts +103 -0
  432. package/src/clis/ones/logout.ts +19 -0
  433. package/src/clis/ones/me.ts +34 -0
  434. package/src/clis/ones/my-tasks.ts +148 -0
  435. package/src/clis/ones/resolve-labels.ts +80 -0
  436. package/src/clis/ones/task-helpers.test.ts +14 -0
  437. package/src/clis/ones/task-helpers.ts +214 -0
  438. package/src/clis/ones/task.ts +79 -0
  439. package/src/clis/ones/tasks.ts +92 -0
  440. package/src/clis/ones/token-info.ts +46 -0
  441. package/src/clis/ones/worklog.test.ts +24 -0
  442. package/src/clis/ones/worklog.ts +306 -0
  443. package/src/clis/spotify/spotify.ts +328 -0
  444. package/src/clis/spotify/utils.test.ts +87 -0
  445. package/src/clis/spotify/utils.ts +92 -0
  446. package/src/clis/substack/utils.test.ts +54 -0
  447. package/src/clis/substack/utils.ts +10 -2
  448. package/src/clis/tieba/commands.test.ts +86 -0
  449. package/src/clis/tieba/hot.ts +52 -0
  450. package/src/clis/tieba/posts.ts +108 -0
  451. package/src/clis/tieba/read.ts +158 -0
  452. package/src/clis/tieba/search.ts +119 -0
  453. package/src/clis/tieba/utils.test.ts +322 -0
  454. package/src/clis/tieba/utils.ts +348 -0
  455. package/src/clis/v2ex/hot.yaml +4 -1
  456. package/src/clis/v2ex/latest.yaml +4 -1
  457. package/src/clis/v2ex/topic.yaml +6 -1
  458. package/src/clis/weixin/download.ts +95 -6
  459. package/src/clis/weread/book.ts +256 -13
  460. package/src/clis/weread/commands.test.ts +409 -0
  461. package/src/{weread-private-api-regression.test.ts → clis/weread/private-api-regression.test.ts} +108 -30
  462. package/src/clis/weread/search-regression.test.ts +440 -0
  463. package/src/clis/weread/search.ts +189 -9
  464. package/src/clis/weread/shelf.ts +20 -122
  465. package/src/clis/weread/utils.test.ts +81 -1
  466. package/src/clis/weread/utils.ts +293 -7
  467. package/src/clis/xiaohongshu/comments.test.ts +85 -9
  468. package/src/clis/xiaohongshu/comments.ts +76 -17
  469. package/src/clis/xiaohongshu/download.test.ts +96 -0
  470. package/src/clis/xiaohongshu/download.ts +83 -22
  471. package/src/clis/xiaohongshu/note-helpers.ts +25 -0
  472. package/src/clis/xiaohongshu/note.test.ts +164 -0
  473. package/src/clis/xiaohongshu/note.ts +86 -0
  474. package/src/clis/xiaohongshu/publish.test.ts +79 -1
  475. package/src/clis/xiaohongshu/publish.ts +84 -30
  476. package/src/clis/xiaohongshu/search.test.ts +11 -4
  477. package/src/clis/xiaohongshu/search.ts +13 -0
  478. package/src/clis/xiaohongshu/user-helpers.test.ts +23 -0
  479. package/src/clis/xiaohongshu/user-helpers.ts +4 -0
  480. package/src/clis/xueqiu/comments.test.ts +823 -0
  481. package/src/clis/xueqiu/comments.ts +461 -0
  482. package/src/clis/youtube/search.ts +57 -17
  483. package/src/clis/youtube/transcript.ts +2 -4
  484. package/src/clis/youtube/utils.test.ts +43 -0
  485. package/src/clis/youtube/utils.ts +69 -0
  486. package/src/clis/youtube/video.ts +16 -15
  487. package/src/clis/zhihu/question.test.ts +71 -0
  488. package/src/clis/zhihu/question.ts +27 -15
  489. package/src/clis/zsxq/dynamics.ts +60 -0
  490. package/src/clis/zsxq/groups.ts +41 -0
  491. package/src/clis/zsxq/search.test.ts +29 -0
  492. package/src/clis/zsxq/search.ts +54 -0
  493. package/src/clis/zsxq/topic.test.ts +34 -0
  494. package/src/clis/zsxq/topic.ts +68 -0
  495. package/src/clis/zsxq/topics.test.ts +29 -0
  496. package/src/clis/zsxq/topics.ts +36 -0
  497. package/src/clis/zsxq/utils.ts +351 -0
  498. package/src/commanderAdapter.test.ts +77 -0
  499. package/src/commanderAdapter.ts +8 -1
  500. package/src/commands/daemon.test.ts +238 -0
  501. package/src/commands/daemon.ts +135 -0
  502. package/src/completion.ts +2 -1
  503. package/src/constants.ts +3 -0
  504. package/src/daemon.test.ts +88 -0
  505. package/src/daemon.ts +26 -14
  506. package/src/discovery.ts +52 -2
  507. package/src/electron-apps.test.ts +50 -0
  508. package/src/electron-apps.ts +89 -0
  509. package/src/engine.test.ts +45 -9
  510. package/src/execution.ts +24 -19
  511. package/src/external-clis.yaml +17 -0
  512. package/src/idle-manager.ts +60 -0
  513. package/src/launcher.test.ts +67 -0
  514. package/src/launcher.ts +185 -0
  515. package/src/main.ts +3 -2
  516. package/src/registry.test.ts +15 -0
  517. package/src/registry.ts +32 -3
  518. package/src/runtime.ts +13 -7
  519. package/src/serialization.test.ts +19 -1
  520. package/src/serialization.ts +2 -0
  521. package/src/tui.test.ts +23 -0
  522. package/src/tui.ts +65 -0
  523. package/src/types.ts +5 -0
  524. package/src/weixin-download.test.ts +27 -0
  525. package/tests/e2e/band-auth.test.ts +20 -0
  526. package/tests/e2e/browser-auth-helpers.ts +18 -0
  527. package/tests/e2e/browser-auth.test.ts +35 -47
  528. package/tests/e2e/browser-public-extended.test.ts +6 -2
  529. package/tests/e2e/browser-public.test.ts +288 -0
  530. package/tests/e2e/management.test.ts +1 -1
  531. package/tests/e2e/plugin-management.test.ts +1 -1
  532. package/vitest.config.ts +1 -0
  533. package/chatwise-opencli.ps1 +0 -82
  534. package/dist/clis/chatwise/shared.d.ts +0 -2
  535. package/dist/clis/chatwise/shared.js +0 -6
  536. package/dist/weread-private-api-regression.test.d.ts +0 -1
  537. package/dist/weread-search-regression.test.d.ts +0 -1
  538. package/dist/weread-search-regression.test.js +0 -39
  539. package/src/clis/chatwise/shared.ts +0 -8
  540. package/src/weread-search-regression.test.ts +0 -44
@@ -0,0 +1,739 @@
1
+ import { AuthRequiredError, CliError } from '../../errors.js';
2
+ import { bindCurrentTab } from '../../browser/daemon-client.js';
3
+ import { NOTEBOOKLM_DOMAIN, NOTEBOOKLM_HOME_URL, NOTEBOOKLM_SITE, } from './shared.js';
4
+ import { callNotebooklmRpc, getNotebooklmPageAuth, } from './rpc.js';
5
+ export { buildNotebooklmRpcBody, extractNotebooklmRpcResult, fetchNotebooklmInPage, getNotebooklmPageAuth, parseNotebooklmChunkedResponse, stripNotebooklmAntiXssi, } from './rpc.js';
6
+ const NOTEBOOKLM_LIST_RPC_ID = 'wXbhsf';
7
+ const NOTEBOOKLM_NOTEBOOK_DETAIL_RPC_ID = 'rLM1Ne';
8
+ const NOTEBOOKLM_HISTORY_THREADS_RPC_ID = 'hPTbtc';
9
+ const NOTEBOOKLM_HISTORY_DETAIL_RPC_ID = 'khqZz';
10
+ function unwrapNotebooklmSingletonResult(result) {
11
+ let current = result;
12
+ while (Array.isArray(current) && current.length === 1 && Array.isArray(current[0])) {
13
+ current = current[0];
14
+ }
15
+ return current;
16
+ }
17
+ export function parseNotebooklmIdFromUrl(url) {
18
+ const match = url.match(/\/notebook\/([^/?#]+)/);
19
+ return match?.[1] ?? '';
20
+ }
21
+ export function classifyNotebooklmPage(url) {
22
+ try {
23
+ const parsed = new URL(url);
24
+ if (parsed.hostname !== NOTEBOOKLM_DOMAIN)
25
+ return 'unknown';
26
+ if (/\/notebook\/[^/?#]+/.test(parsed.pathname))
27
+ return 'notebook';
28
+ return 'home';
29
+ }
30
+ catch {
31
+ return 'unknown';
32
+ }
33
+ }
34
+ export function normalizeNotebooklmTitle(value, fallback = '') {
35
+ if (typeof value !== 'string')
36
+ return fallback;
37
+ let normalized = value.replace(/\s+/g, ' ').trim();
38
+ if (/^Untitled\b/i.test(normalized) && /otebook$/i.test(normalized) && normalized !== 'Untitled notebook') {
39
+ normalized = 'Untitled notebook';
40
+ }
41
+ return normalized || fallback;
42
+ }
43
+ function normalizeNotebooklmCreatedAt(value) {
44
+ if (typeof value !== 'string')
45
+ return null;
46
+ const trimmed = value.trim();
47
+ if (!trimmed)
48
+ return null;
49
+ const parsed = Date.parse(trimmed);
50
+ if (Number.isNaN(parsed))
51
+ return trimmed;
52
+ return new Date(parsed).toISOString();
53
+ }
54
+ function toNotebooklmIsoTimestamp(epochSeconds) {
55
+ if (typeof epochSeconds === 'number' && Number.isFinite(epochSeconds)) {
56
+ try {
57
+ return new Date(epochSeconds * 1000).toISOString();
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ if (Array.isArray(epochSeconds) && typeof epochSeconds[0] === 'number' && Number.isFinite(epochSeconds[0])) {
64
+ const seconds = epochSeconds[0];
65
+ const nanos = typeof epochSeconds[1] === 'number' && Number.isFinite(epochSeconds[1]) ? epochSeconds[1] : 0;
66
+ try {
67
+ return new Date(seconds * 1000 + Math.floor(nanos / 1_000_000)).toISOString();
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ }
73
+ return null;
74
+ }
75
+ function parseNotebooklmSourceTypeCode(value) {
76
+ if (typeof value === 'number' && Number.isFinite(value))
77
+ return value;
78
+ if (!Array.isArray(value) || typeof value[1] !== 'number' || !Number.isFinite(value[1]))
79
+ return null;
80
+ return value[1];
81
+ }
82
+ function parseNotebooklmSourceType(value) {
83
+ const code = parseNotebooklmSourceTypeCode(value);
84
+ if (code === 8)
85
+ return 'pasted-text';
86
+ if (code === 9)
87
+ return 'youtube';
88
+ if (code === 2)
89
+ return 'generated-text';
90
+ if (code === 3)
91
+ return 'pdf';
92
+ if (code === 4)
93
+ return 'audio';
94
+ if (code === 5)
95
+ return 'web';
96
+ if (code === 6)
97
+ return 'video';
98
+ return code == null ? null : `type-${code}`;
99
+ }
100
+ function findFirstNotebooklmString(value) {
101
+ if (typeof value === 'string' && value.trim())
102
+ return value.trim();
103
+ if (!Array.isArray(value))
104
+ return null;
105
+ for (const item of value) {
106
+ const found = findFirstNotebooklmString(item);
107
+ if (found)
108
+ return found;
109
+ }
110
+ return null;
111
+ }
112
+ function isNotebooklmUuid(value) {
113
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
114
+ }
115
+ function collectNotebooklmStrings(value, results) {
116
+ if (typeof value === 'string') {
117
+ const normalized = normalizeNotebooklmTitle(value);
118
+ if (!normalized)
119
+ return results;
120
+ if (isNotebooklmUuid(normalized))
121
+ return results;
122
+ if (/^[\d\s]+$/.test(normalized))
123
+ return results;
124
+ if (/^(null|undefined)$/i.test(normalized))
125
+ return results;
126
+ results.push(normalized);
127
+ return results;
128
+ }
129
+ if (!Array.isArray(value))
130
+ return results;
131
+ for (const item of value)
132
+ collectNotebooklmStrings(item, results);
133
+ return results;
134
+ }
135
+ function collectNotebooklmLeafStrings(value, results) {
136
+ if (typeof value === 'string') {
137
+ const normalized = value.trim();
138
+ if (normalized)
139
+ results.push(normalized);
140
+ return results;
141
+ }
142
+ if (!Array.isArray(value))
143
+ return results;
144
+ for (const item of value)
145
+ collectNotebooklmLeafStrings(item, results);
146
+ return results;
147
+ }
148
+ function collectNotebooklmThreadIds(value, results, seen) {
149
+ if (typeof value === 'string') {
150
+ const normalized = value.trim();
151
+ if (isNotebooklmUuid(normalized) && !seen.has(normalized)) {
152
+ seen.add(normalized);
153
+ results.push(normalized);
154
+ }
155
+ return results;
156
+ }
157
+ if (!Array.isArray(value))
158
+ return results;
159
+ for (const item of value)
160
+ collectNotebooklmThreadIds(item, results, seen);
161
+ return results;
162
+ }
163
+ export function parseNotebooklmHistoryThreadIdsResult(result) {
164
+ return collectNotebooklmThreadIds(result, [], new Set());
165
+ }
166
+ export function extractNotebooklmHistoryPreview(result) {
167
+ const strings = collectNotebooklmStrings(result, []);
168
+ return strings.length > 0 ? strings[0] : null;
169
+ }
170
+ export function parseNotebooklmNoteListRawRows(rows, notebookId, url) {
171
+ const parsed = rows.map((row) => {
172
+ const title = normalizeNotebooklmTitle(row.title, '');
173
+ const text = String(row.text ?? '')
174
+ .replace(/\bsticky_note_2\b/g, ' ')
175
+ .replace(/\bmore_vert\b/g, ' ')
176
+ .replace(/\s+/g, ' ')
177
+ .trim();
178
+ if (!title)
179
+ return null;
180
+ const suffix = text.startsWith(title)
181
+ ? text.slice(title.length).trim()
182
+ : text.replace(title, '').trim();
183
+ return {
184
+ notebook_id: notebookId,
185
+ title,
186
+ created_at: suffix || null,
187
+ url,
188
+ source: 'studio-list',
189
+ };
190
+ });
191
+ return parsed.filter((row) => row !== null);
192
+ }
193
+ function parseNotebooklmSummaryRawRow(row, notebookId, url) {
194
+ const title = normalizeNotebooklmTitle(row?.title, 'Untitled Notebook');
195
+ const summary = String(row?.summary ?? '').trim();
196
+ if (!summary)
197
+ return null;
198
+ return {
199
+ notebook_id: notebookId,
200
+ title,
201
+ summary,
202
+ url,
203
+ source: 'summary-dom',
204
+ };
205
+ }
206
+ function parseNotebooklmVisibleNoteRawRow(row, notebookId, url) {
207
+ const title = normalizeNotebooklmTitle(row?.title, '');
208
+ const content = String(row?.content ?? '').replace(/\r\n/g, '\n').trim();
209
+ if (!title)
210
+ return null;
211
+ return {
212
+ notebook_id: notebookId,
213
+ id: null,
214
+ title,
215
+ content,
216
+ url,
217
+ source: 'studio-editor',
218
+ };
219
+ }
220
+ export function parseNotebooklmListResult(result) {
221
+ if (!Array.isArray(result) || result.length === 0)
222
+ return [];
223
+ const rawNotebooks = Array.isArray(result[0]) ? result[0] : result;
224
+ if (!Array.isArray(rawNotebooks))
225
+ return [];
226
+ return rawNotebooks
227
+ .filter((item) => Array.isArray(item))
228
+ .map((item) => {
229
+ const meta = Array.isArray(item[5]) ? item[5] : [];
230
+ const timestamps = Array.isArray(meta[5]) ? meta[5] : [];
231
+ const id = typeof item[2] === 'string' ? item[2] : '';
232
+ const title = typeof item[0] === 'string'
233
+ ? item[0].replace(/^thought\s*\n/, '')
234
+ : '';
235
+ return {
236
+ id,
237
+ title: normalizeNotebooklmTitle(title, 'Untitled Notebook'),
238
+ url: `https://${NOTEBOOKLM_DOMAIN}/notebook/${id}`,
239
+ source: 'rpc',
240
+ is_owner: meta.length > 1 ? meta[1] === false : true,
241
+ created_at: timestamps.length > 0 ? toNotebooklmIsoTimestamp(timestamps[0]) : null,
242
+ };
243
+ })
244
+ .filter((row) => row.id);
245
+ }
246
+ export function parseNotebooklmNotebookDetailResult(result) {
247
+ const detail = unwrapNotebooklmSingletonResult(result);
248
+ if (!Array.isArray(detail) || detail.length < 3)
249
+ return null;
250
+ const id = typeof detail[2] === 'string' ? detail[2] : '';
251
+ if (!id)
252
+ return null;
253
+ const title = normalizeNotebooklmTitle(detail[0], 'Untitled Notebook');
254
+ const emoji = typeof detail[3] === 'string' ? detail[3] : null;
255
+ const meta = Array.isArray(detail[5]) ? detail[5] : [];
256
+ const sources = Array.isArray(detail[1]) ? detail[1] : [];
257
+ return {
258
+ id,
259
+ title,
260
+ url: `https://${NOTEBOOKLM_DOMAIN}/notebook/${id}`,
261
+ source: 'rpc',
262
+ is_owner: meta.length > 1 ? meta[1] === false : true,
263
+ created_at: toNotebooklmIsoTimestamp(meta[8]),
264
+ updated_at: toNotebooklmIsoTimestamp(meta[5]),
265
+ emoji,
266
+ source_count: sources.length,
267
+ };
268
+ }
269
+ export function parseNotebooklmSourceListResult(result) {
270
+ const detail = unwrapNotebooklmSingletonResult(result);
271
+ const notebook = parseNotebooklmNotebookDetailResult(detail);
272
+ if (!notebook || !Array.isArray(detail))
273
+ return [];
274
+ const rawSources = Array.isArray(detail[1]) ? detail[1] : [];
275
+ return rawSources
276
+ .filter((entry) => Array.isArray(entry))
277
+ .map((entry) => {
278
+ const id = findFirstNotebooklmString(entry[0]) ?? '';
279
+ const title = normalizeNotebooklmTitle(entry[1], 'Untitled source');
280
+ const meta = Array.isArray(entry[2]) ? entry[2] : [];
281
+ const typeInfo = typeof meta[4] === 'number' ? meta[4] : entry[3];
282
+ return {
283
+ id,
284
+ notebook_id: notebook.id,
285
+ title,
286
+ url: notebook.url,
287
+ source: 'rpc',
288
+ type: parseNotebooklmSourceType(typeInfo),
289
+ type_code: parseNotebooklmSourceTypeCode(typeInfo),
290
+ size: typeof meta[1] === 'number' && Number.isFinite(meta[1]) ? meta[1] : null,
291
+ created_at: toNotebooklmIsoTimestamp(meta[2]),
292
+ updated_at: toNotebooklmIsoTimestamp(meta[14]),
293
+ };
294
+ })
295
+ .filter((row) => row.id);
296
+ }
297
+ export function parseNotebooklmSourceGuideResult(result, source) {
298
+ if (!Array.isArray(result) || result.length === 0 || !Array.isArray(result[0]))
299
+ return null;
300
+ const outer = result[0];
301
+ const guide = Array.isArray(outer) && outer.length > 0 && Array.isArray(outer[0])
302
+ ? outer[0]
303
+ : outer;
304
+ if (!Array.isArray(guide))
305
+ return null;
306
+ const summary = Array.isArray(guide[1]) && typeof guide[1][0] === 'string'
307
+ ? guide[1][0].trim()
308
+ : '';
309
+ const keywords = Array.isArray(guide[2]) && Array.isArray(guide[2][0])
310
+ ? guide[2][0].filter((item) => typeof item === 'string' && item.trim().length > 0)
311
+ : [];
312
+ if (!summary)
313
+ return null;
314
+ return {
315
+ source_id: source.id,
316
+ notebook_id: source.notebook_id,
317
+ title: source.title,
318
+ type: source.type ?? null,
319
+ summary,
320
+ keywords,
321
+ source: 'rpc',
322
+ };
323
+ }
324
+ export function parseNotebooklmSourceFulltextResult(result, notebookId, fallbackUrl) {
325
+ if (!Array.isArray(result) || result.length === 0 || !Array.isArray(result[0]))
326
+ return null;
327
+ const source = result[0];
328
+ const sourceId = findFirstNotebooklmString(source[0]) ?? '';
329
+ const title = normalizeNotebooklmTitle(source[1], 'Untitled source');
330
+ const meta = Array.isArray(source[2]) ? source[2] : [];
331
+ const url = Array.isArray(meta[7]) && typeof meta[7][0] === 'string' ? meta[7][0] : fallbackUrl;
332
+ const kind = parseNotebooklmSourceType([null, meta[4]]);
333
+ const contentRoot = Array.isArray(result[3]) && result[3].length > 0 ? result[3][0] : [];
334
+ const content = collectNotebooklmLeafStrings(contentRoot, []).join('\n').trim();
335
+ if (!sourceId || !content)
336
+ return null;
337
+ return {
338
+ source_id: sourceId,
339
+ notebook_id: notebookId,
340
+ title,
341
+ kind,
342
+ content,
343
+ char_count: content.length,
344
+ url,
345
+ source: 'rpc',
346
+ };
347
+ }
348
+ export function findNotebooklmSourceRow(rows, query) {
349
+ const needle = query.trim().toLowerCase();
350
+ if (!needle)
351
+ return null;
352
+ const exactId = rows.find((row) => row.id.trim().toLowerCase() === needle);
353
+ if (exactId)
354
+ return exactId;
355
+ const exactTitle = rows.find((row) => row.title.trim().toLowerCase() === needle);
356
+ if (exactTitle)
357
+ return exactTitle;
358
+ const partialMatches = rows.filter((row) => row.title.trim().toLowerCase().includes(needle));
359
+ if (partialMatches.length === 1)
360
+ return partialMatches[0];
361
+ return null;
362
+ }
363
+ export function findNotebooklmNoteRow(rows, query) {
364
+ const needle = query.trim().toLowerCase();
365
+ if (!needle)
366
+ return null;
367
+ const exactTitle = rows.find((row) => row.title.trim().toLowerCase() === needle);
368
+ if (exactTitle)
369
+ return exactTitle;
370
+ const partialMatches = rows.filter((row) => row.title.trim().toLowerCase().includes(needle));
371
+ if (partialMatches.length === 1)
372
+ return partialMatches[0];
373
+ return null;
374
+ }
375
+ export async function listNotebooklmViaRpc(page) {
376
+ const rpc = await callNotebooklmRpc(page, NOTEBOOKLM_LIST_RPC_ID, [null, 1, null, [2]]);
377
+ return parseNotebooklmListResult(rpc.result);
378
+ }
379
+ export async function getNotebooklmDetailViaRpc(page) {
380
+ const state = await getNotebooklmPageState(page);
381
+ if (state.kind !== 'notebook' || !state.notebookId)
382
+ return null;
383
+ const rpc = await callNotebooklmRpc(page, NOTEBOOKLM_NOTEBOOK_DETAIL_RPC_ID, [state.notebookId, null, [2], null, 0]);
384
+ return parseNotebooklmNotebookDetailResult(rpc.result);
385
+ }
386
+ export async function listNotebooklmSourcesViaRpc(page) {
387
+ const state = await getNotebooklmPageState(page);
388
+ if (state.kind !== 'notebook' || !state.notebookId)
389
+ return [];
390
+ const rpc = await callNotebooklmRpc(page, NOTEBOOKLM_NOTEBOOK_DETAIL_RPC_ID, [state.notebookId, null, [2], null, 0]);
391
+ return parseNotebooklmSourceListResult(rpc.result);
392
+ }
393
+ export async function listNotebooklmHistoryViaRpc(page) {
394
+ const state = await getNotebooklmPageState(page);
395
+ if (state.kind !== 'notebook' || !state.notebookId)
396
+ return [];
397
+ const threadsRpc = await callNotebooklmRpc(page, NOTEBOOKLM_HISTORY_THREADS_RPC_ID, [[], null, state.notebookId, 20]);
398
+ const threadIds = parseNotebooklmHistoryThreadIdsResult(threadsRpc.result);
399
+ if (threadIds.length === 0)
400
+ return [];
401
+ const rows = [];
402
+ for (const threadId of threadIds) {
403
+ const detailRpc = await callNotebooklmRpc(page, NOTEBOOKLM_HISTORY_DETAIL_RPC_ID, [[], null, null, threadId, 20]);
404
+ rows.push({
405
+ notebook_id: state.notebookId,
406
+ thread_id: threadId,
407
+ item_count: Array.isArray(detailRpc.result) ? detailRpc.result.length : 0,
408
+ preview: extractNotebooklmHistoryPreview(detailRpc.result),
409
+ url: state.url || `https://${NOTEBOOKLM_DOMAIN}/notebook/${state.notebookId}`,
410
+ source: 'rpc',
411
+ });
412
+ }
413
+ return rows;
414
+ }
415
+ export async function listNotebooklmNotesFromPage(page) {
416
+ const state = await getNotebooklmPageState(page);
417
+ if (state.kind !== 'notebook' || !state.notebookId)
418
+ return [];
419
+ const raw = await page.evaluate(`(() => {
420
+ return Array.from(document.querySelectorAll('artifact-library-note')).map((node) => {
421
+ const titleNode = node.querySelector('.artifact-title');
422
+ return {
423
+ title: (titleNode?.textContent || '').trim(),
424
+ text: (node.innerText || node.textContent || '').replace(/\\s+/g, ' ').trim(),
425
+ };
426
+ });
427
+ })()`);
428
+ if (!Array.isArray(raw) || raw.length === 0)
429
+ return [];
430
+ return parseNotebooklmNoteListRawRows(raw, state.notebookId, state.url || `https://${NOTEBOOKLM_DOMAIN}/notebook/${state.notebookId}`);
431
+ }
432
+ export async function readNotebooklmSummaryFromPage(page) {
433
+ const state = await getNotebooklmPageState(page);
434
+ if (state.kind !== 'notebook' || !state.notebookId)
435
+ return null;
436
+ const raw = await page.evaluate(`(() => {
437
+ const normalize = (value) => (value || '').replace(/\\s+/g, ' ').trim();
438
+ const title = normalize(document.querySelector('.notebook-title, h1, [data-testid="notebook-title"]')?.textContent || document.title || '');
439
+ const summaryNode = document.querySelector('.notebook-summary, .summary-content, [class*="summary"]');
440
+ const summary = normalize(summaryNode?.textContent || '');
441
+ return { title, summary };
442
+ })()`);
443
+ return parseNotebooklmSummaryRawRow(raw, state.notebookId, state.url || `https://${NOTEBOOKLM_DOMAIN}/notebook/${state.notebookId}`);
444
+ }
445
+ export async function getNotebooklmSummaryViaRpc(page) {
446
+ const state = await getNotebooklmPageState(page);
447
+ if (state.kind !== 'notebook' || !state.notebookId)
448
+ return null;
449
+ const rpc = await callNotebooklmRpc(page, NOTEBOOKLM_NOTEBOOK_DETAIL_RPC_ID, [state.notebookId, null, [2], null, 0]);
450
+ const detail = unwrapNotebooklmSingletonResult(rpc.result);
451
+ if (!Array.isArray(detail))
452
+ return null;
453
+ const title = normalizeNotebooklmTitle(detail[0], 'Untitled Notebook');
454
+ const summary = detail
455
+ .filter((value, index) => index !== 0 && index !== 2 && index !== 3)
456
+ .find((value) => typeof value === 'string' && value.trim().length >= 80);
457
+ if (typeof summary !== 'string')
458
+ return null;
459
+ return {
460
+ notebook_id: state.notebookId,
461
+ title,
462
+ summary: summary.trim(),
463
+ url: state.url || `https://${NOTEBOOKLM_DOMAIN}/notebook/${state.notebookId}`,
464
+ source: 'rpc',
465
+ };
466
+ }
467
+ export async function getNotebooklmSourceFulltextViaRpc(page, sourceId) {
468
+ const state = await getNotebooklmPageState(page);
469
+ if (state.kind !== 'notebook' || !state.notebookId || !sourceId)
470
+ return null;
471
+ const rpc = await callNotebooklmRpc(page, 'hizoJc', [[sourceId], [2], [2]]);
472
+ return parseNotebooklmSourceFulltextResult(rpc.result, state.notebookId, state.url || `https://${NOTEBOOKLM_DOMAIN}/notebook/${state.notebookId}`);
473
+ }
474
+ export async function getNotebooklmSourceGuideViaRpc(page, source) {
475
+ if (!source.id)
476
+ return null;
477
+ const rpc = await callNotebooklmRpc(page, 'tr032e', [[[[source.id]]]]);
478
+ return parseNotebooklmSourceGuideResult(rpc.result, source);
479
+ }
480
+ export async function readNotebooklmVisibleNoteFromPage(page) {
481
+ const state = await getNotebooklmPageState(page);
482
+ if (state.kind !== 'notebook' || !state.notebookId)
483
+ return null;
484
+ const raw = await page.evaluate(`(() => {
485
+ const normalizeText = (value) => (value || '').replace(/\\u00a0/g, ' ').replace(/\\r\\n/g, '\\n').trim();
486
+ const titleNode = document.querySelector('.note-header__editable-title');
487
+ const title = titleNode instanceof HTMLInputElement || titleNode instanceof HTMLTextAreaElement
488
+ ? titleNode.value
489
+ : (titleNode?.textContent || '');
490
+ const editor = document.querySelector('.note-editor .ql-editor, .note-editor [contenteditable="true"], .note-editor textarea');
491
+ let content = '';
492
+ if (editor instanceof HTMLTextAreaElement || editor instanceof HTMLInputElement) {
493
+ content = editor.value || '';
494
+ } else if (editor) {
495
+ content = editor.innerText || editor.textContent || '';
496
+ }
497
+ return {
498
+ title: normalizeText(title),
499
+ content: normalizeText(content),
500
+ };
501
+ })()`);
502
+ return parseNotebooklmVisibleNoteRawRow(raw, state.notebookId, state.url || `https://${NOTEBOOKLM_DOMAIN}/notebook/${state.notebookId}`);
503
+ }
504
+ export async function ensureNotebooklmHome(page) {
505
+ const currentUrl = page.getCurrentUrl
506
+ ? await page.getCurrentUrl().catch(() => null)
507
+ : null;
508
+ const currentKind = currentUrl ? classifyNotebooklmPage(currentUrl) : 'unknown';
509
+ if (currentKind === 'home')
510
+ return;
511
+ await page.goto(NOTEBOOKLM_HOME_URL);
512
+ await page.wait(2);
513
+ }
514
+ export async function ensureNotebooklmNotebookBinding(page) {
515
+ if (!page.getCurrentUrl)
516
+ return false;
517
+ if (process.env.OPENCLI_CDP_ENDPOINT)
518
+ return false;
519
+ const currentUrl = await page.getCurrentUrl().catch(() => null);
520
+ if (currentUrl && classifyNotebooklmPage(currentUrl) === 'notebook')
521
+ return false;
522
+ try {
523
+ await bindCurrentTab(`site:${NOTEBOOKLM_SITE}`, {
524
+ matchDomain: NOTEBOOKLM_DOMAIN,
525
+ matchPathPrefix: '/notebook/',
526
+ });
527
+ return true;
528
+ }
529
+ catch {
530
+ return false;
531
+ }
532
+ }
533
+ export async function getNotebooklmPageState(page) {
534
+ const raw = await page.evaluate(`(() => {
535
+ const url = window.location.href;
536
+ const title = document.title || '';
537
+ const hostname = window.location.hostname || '';
538
+ const notebookMatch = url.match(/\\/notebook\\/([^/?#]+)/);
539
+ const notebookId = notebookMatch ? notebookMatch[1] : '';
540
+ const path = window.location.pathname || '/';
541
+ const kind = notebookId
542
+ ? 'notebook'
543
+ : (hostname === 'notebooklm.google.com' ? 'home' : 'unknown');
544
+
545
+ const textNodes = Array.from(document.querySelectorAll('a, button, [role="button"], h1, h2'))
546
+ .map(node => (node.textContent || '').trim().toLowerCase())
547
+ .filter(Boolean);
548
+ const loginRequired = textNodes.some(text =>
549
+ text.includes('sign in') ||
550
+ text.includes('log in') ||
551
+ text.includes('登录') ||
552
+ text.includes('登入')
553
+ );
554
+
555
+ const notebookCount = Array.from(document.querySelectorAll('a[href*="/notebook/"]'))
556
+ .map(node => node instanceof HTMLAnchorElement ? node.href : '')
557
+ .filter(Boolean)
558
+ .reduce((count, href, index, list) => list.indexOf(href) === index ? count + 1 : count, 0);
559
+
560
+ return { url, title, hostname, kind, notebookId, loginRequired, notebookCount, path };
561
+ })()`);
562
+ const state = {
563
+ url: String(raw?.url ?? ''),
564
+ title: normalizeNotebooklmTitle(raw?.title, 'NotebookLM'),
565
+ hostname: String(raw?.hostname ?? ''),
566
+ kind: raw?.kind === 'notebook' || raw?.kind === 'home' ? raw.kind : 'unknown',
567
+ notebookId: String(raw?.notebookId ?? ''),
568
+ loginRequired: Boolean(raw?.loginRequired),
569
+ notebookCount: Number(raw?.notebookCount ?? 0),
570
+ };
571
+ // Notebook pages can still contain "sign in" or login-related text fragments
572
+ // even when the active Google session is valid. Prefer the real page tokens
573
+ // as the stronger auth signal before declaring the session unauthenticated.
574
+ if (state.hostname === NOTEBOOKLM_DOMAIN && state.loginRequired) {
575
+ try {
576
+ await getNotebooklmPageAuth(page);
577
+ state.loginRequired = false;
578
+ }
579
+ catch {
580
+ // Keep the heuristic result when page auth tokens are genuinely unavailable.
581
+ }
582
+ }
583
+ return state;
584
+ }
585
+ export async function readCurrentNotebooklm(page) {
586
+ const raw = await page.evaluate(`(() => {
587
+ const url = window.location.href;
588
+ const match = url.match(/\\/notebook\\/([^/?#]+)/);
589
+ if (!match) return null;
590
+
591
+ const titleNode = document.querySelector('h1, [data-testid="notebook-title"], [role="heading"]');
592
+ const title = (titleNode?.textContent || document.title || '').trim();
593
+ return {
594
+ id: match[1],
595
+ title,
596
+ url,
597
+ source: 'current-page',
598
+ };
599
+ })()`);
600
+ if (!raw)
601
+ return null;
602
+ return {
603
+ id: String(raw.id ?? ''),
604
+ title: normalizeNotebooklmTitle(raw.title, 'Untitled Notebook'),
605
+ url: String(raw.url ?? ''),
606
+ source: 'current-page',
607
+ is_owner: true,
608
+ created_at: null,
609
+ };
610
+ }
611
+ export async function listNotebooklmLinks(page) {
612
+ const raw = await page.evaluate(`(() => {
613
+ const rows = [];
614
+ const seen = new Set();
615
+
616
+ for (const node of Array.from(document.querySelectorAll('a[href*="/notebook/"]'))) {
617
+ if (!(node instanceof HTMLAnchorElement)) continue;
618
+ const href = node.href || '';
619
+ const match = href.match(/\\/notebook\\/([^/?#]+)/);
620
+ if (!match) continue;
621
+ const id = match[1];
622
+ if (seen.has(id)) continue;
623
+ seen.add(id);
624
+
625
+ const parentCard = node.closest('mat-card, [role="listitem"], article, div');
626
+ const titleNode = parentCard?.querySelector('.project-button-title, [id$="-title"]');
627
+ const subtitleTitleNode = parentCard?.querySelector('.project-button-subtitle-part[title]');
628
+ const subtitleTextNode = parentCard?.querySelector('.project-button-subtitle-part, .project-button-subtitle');
629
+ const parentText = (parentCard?.textContent || '').trim();
630
+ const parentLines = parentText
631
+ .split(/\\n+/)
632
+ .map((value) => value.trim())
633
+ .filter(Boolean);
634
+
635
+ const title = (
636
+ titleNode?.textContent ||
637
+ node.getAttribute('aria-label') ||
638
+ node.getAttribute('title') ||
639
+ parentLines.find((line) => !line.includes('个来源') && !line.includes('sources') && !line.includes('more_vert')) ||
640
+ node.textContent ||
641
+ ''
642
+ ).trim();
643
+ const createdAtHint = (
644
+ subtitleTitleNode?.getAttribute?.('title') ||
645
+ subtitleTextNode?.textContent ||
646
+ ''
647
+ ).trim();
648
+
649
+ rows.push({
650
+ id,
651
+ title,
652
+ url: href,
653
+ source: 'home-links',
654
+ is_owner: true,
655
+ created_at: createdAtHint || null,
656
+ });
657
+ }
658
+
659
+ return rows;
660
+ })()`);
661
+ if (!Array.isArray(raw))
662
+ return [];
663
+ return raw
664
+ .map((row) => ({
665
+ id: String(row.id ?? ''),
666
+ title: normalizeNotebooklmTitle(row.title, 'Untitled Notebook'),
667
+ url: String(row.url ?? ''),
668
+ source: 'home-links',
669
+ is_owner: row.is_owner === false ? false : true,
670
+ created_at: normalizeNotebooklmCreatedAt(row.created_at),
671
+ }))
672
+ .filter((row) => row.id && row.url);
673
+ }
674
+ export async function listNotebooklmSourcesFromPage(page) {
675
+ const raw = await page.evaluate(`(() => {
676
+ const notebookMatch = window.location.href.match(/\\/notebook\\/([^/?#]+)/);
677
+ const notebookId = notebookMatch ? notebookMatch[1] : '';
678
+ if (!notebookId) return [];
679
+
680
+ const skip = new Set([
681
+ '选择所有来源',
682
+ '添加来源',
683
+ '收起来源面板',
684
+ '更多',
685
+ 'Web',
686
+ 'Fast Research',
687
+ '提交',
688
+ '创建笔记本',
689
+ '分享笔记本',
690
+ '设置',
691
+ '对话选项',
692
+ '配置笔记本',
693
+ '音频概览',
694
+ '演示文稿',
695
+ '视频概览',
696
+ '思维导图',
697
+ '报告',
698
+ '闪卡',
699
+ '测验',
700
+ '信息图',
701
+ '数据表格',
702
+ '添加笔记',
703
+ '保存到笔记',
704
+ '复制摘要',
705
+ '摘要很棒',
706
+ '摘要欠佳',
707
+ ]);
708
+
709
+ const rows = [];
710
+ const seen = new Set();
711
+ for (const node of Array.from(document.querySelectorAll('button, [role="button"], input[type="checkbox"]'))) {
712
+ const text = (node.getAttribute?.('aria-label') || node.textContent || '').trim();
713
+ if (!text || skip.has(text) || seen.has(text)) continue;
714
+ if (text.includes('个来源') || text.includes('来源') && text.length < 5) continue;
715
+ seen.add(text);
716
+ rows.push({
717
+ id: text,
718
+ notebook_id: notebookId,
719
+ title: text,
720
+ url: window.location.href,
721
+ source: 'current-page',
722
+ });
723
+ }
724
+ return rows;
725
+ })()`);
726
+ if (!Array.isArray(raw))
727
+ return [];
728
+ return raw.filter((row) => row.id && row.title);
729
+ }
730
+ export async function requireNotebooklmSession(page) {
731
+ const state = await getNotebooklmPageState(page);
732
+ if (state.hostname !== NOTEBOOKLM_DOMAIN) {
733
+ throw new CliError('NOTEBOOKLM_UNAVAILABLE', 'NotebookLM page is not available in the current browser session', `Open Chrome and navigate to ${NOTEBOOKLM_HOME_URL}`);
734
+ }
735
+ if (state.loginRequired) {
736
+ throw new AuthRequiredError(NOTEBOOKLM_DOMAIN, 'NotebookLM requires a logged-in Google session');
737
+ }
738
+ return state;
739
+ }