@jackwener/opencli 1.3.3 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (496) hide show
  1. package/.github/pull_request_template.md +3 -1
  2. package/.github/workflows/build-extension.yml +7 -1
  3. package/.github/workflows/ci.yml +29 -3
  4. package/.github/workflows/docs.yml +1 -1
  5. package/.github/workflows/e2e-headed.yml +20 -0
  6. package/.github/workflows/release.yml +1 -1
  7. package/.github/workflows/security.yml +0 -3
  8. package/CHANGELOG.md +55 -0
  9. package/CONTRIBUTING.md +6 -3
  10. package/README.md +30 -3
  11. package/README.zh-CN.md +30 -3
  12. package/SKILL.md +7 -1
  13. package/TESTING.md +1 -0
  14. package/chatwise-opencli.ps1 +82 -0
  15. package/dist/analysis.d.ts +38 -0
  16. package/dist/analysis.js +166 -0
  17. package/dist/browser/cdp.d.ts +0 -4
  18. package/dist/browser/cdp.js +53 -41
  19. package/dist/browser/cdp.test.d.ts +1 -0
  20. package/dist/browser/cdp.test.js +52 -0
  21. package/dist/browser/dom-snapshot.d.ts +2 -2
  22. package/dist/browser/dom-snapshot.js +54 -1
  23. package/dist/browser/dom-snapshot.test.js +36 -0
  24. package/dist/browser/index.d.ts +2 -2
  25. package/dist/browser/index.js +1 -1
  26. package/dist/browser/mcp.d.ts +0 -2
  27. package/dist/browser/mcp.js +2 -3
  28. package/dist/browser/page.d.ts +4 -3
  29. package/dist/browser/page.js +34 -37
  30. package/dist/browser/stealth.d.ts +0 -2
  31. package/dist/browser/stealth.js +24 -9
  32. package/dist/browser.test.js +2 -2
  33. package/dist/build-manifest.js +15 -9
  34. package/dist/build-manifest.test.js +12 -0
  35. package/dist/cascade.js +4 -2
  36. package/dist/cli-manifest.json +639 -258
  37. package/dist/cli.js +57 -29
  38. package/dist/clis/_shared/desktop-commands.d.ts +22 -0
  39. package/dist/clis/_shared/desktop-commands.js +108 -0
  40. package/dist/clis/antigravity/serve.js +5 -2
  41. package/dist/clis/arxiv/search.js +1 -1
  42. package/dist/clis/bilibili/dynamic.test.d.ts +1 -0
  43. package/dist/clis/bilibili/dynamic.test.js +68 -0
  44. package/dist/clis/bilibili/favorite.js +4 -2
  45. package/dist/clis/bilibili/following.js +3 -2
  46. package/dist/clis/bilibili/subtitle.js +8 -7
  47. package/dist/clis/bilibili/utils.js +2 -2
  48. package/dist/clis/boss/batchgreet.js +1 -1
  49. package/dist/clis/boss/chatlist.js +1 -1
  50. package/dist/clis/boss/chatmsg.js +1 -1
  51. package/dist/clis/boss/detail.js +1 -1
  52. package/dist/clis/boss/exchange.js +1 -1
  53. package/dist/clis/boss/greet.js +1 -1
  54. package/dist/clis/boss/invite.js +1 -1
  55. package/dist/clis/boss/joblist.js +1 -1
  56. package/dist/clis/boss/mark.js +4 -3
  57. package/dist/clis/boss/recommend.js +1 -1
  58. package/dist/clis/boss/resume.js +1 -1
  59. package/dist/clis/boss/search.js +1 -1
  60. package/dist/clis/boss/send.js +5 -4
  61. package/dist/clis/boss/stats.js +1 -1
  62. package/dist/clis/chatgpt/ask.js +4 -0
  63. package/dist/clis/chatgpt/new.js +5 -1
  64. package/dist/clis/chatgpt/read.js +5 -1
  65. package/dist/clis/chatgpt/send.js +2 -1
  66. package/dist/clis/chatgpt/status.js +5 -1
  67. package/dist/clis/chatwise/ask.js +8 -2
  68. package/dist/clis/chatwise/export.js +2 -0
  69. package/dist/clis/chatwise/history.js +2 -0
  70. package/dist/clis/chatwise/model.js +8 -3
  71. package/dist/clis/chatwise/new.js +3 -18
  72. package/dist/clis/chatwise/read.js +2 -0
  73. package/dist/clis/chatwise/screenshot.js +3 -27
  74. package/dist/clis/chatwise/send.js +8 -2
  75. package/dist/clis/chatwise/shared.d.ts +2 -0
  76. package/dist/clis/chatwise/shared.js +6 -0
  77. package/dist/clis/chatwise/status.js +3 -22
  78. package/dist/clis/codex/ask.js +6 -2
  79. package/dist/clis/codex/dump.js +2 -25
  80. package/dist/clis/codex/new.js +2 -25
  81. package/dist/clis/codex/screenshot.js +2 -27
  82. package/dist/clis/codex/send.js +6 -4
  83. package/dist/clis/codex/status.js +2 -22
  84. package/dist/clis/cursor/ask.js +2 -1
  85. package/dist/clis/cursor/composer.js +2 -1
  86. package/dist/clis/cursor/dump.js +2 -25
  87. package/dist/clis/cursor/new.js +2 -18
  88. package/dist/clis/cursor/read.js +2 -1
  89. package/dist/clis/cursor/screenshot.js +1 -30
  90. package/dist/clis/cursor/send.js +2 -1
  91. package/dist/clis/cursor/status.js +2 -21
  92. package/dist/clis/dictionary/examples.yaml +25 -0
  93. package/dist/clis/dictionary/search.yaml +27 -0
  94. package/dist/clis/dictionary/synonyms.yaml +25 -0
  95. package/dist/clis/douban/book-hot.js +1 -1
  96. package/dist/clis/douban/movie-hot.js +1 -1
  97. package/dist/clis/douban/search.js +1 -1
  98. package/dist/clis/douban/utils.d.ts +4 -1
  99. package/dist/clis/douban/utils.js +156 -1
  100. package/dist/clis/doubao/ask.js +1 -1
  101. package/dist/clis/doubao/new.js +1 -1
  102. package/dist/clis/doubao/read.js +1 -1
  103. package/dist/clis/doubao/send.js +1 -1
  104. package/dist/clis/doubao/status.js +1 -1
  105. package/dist/clis/doubao-app/ask.js +1 -1
  106. package/dist/clis/doubao-app/new.js +1 -1
  107. package/dist/clis/doubao-app/read.js +1 -1
  108. package/dist/clis/doubao-app/send.js +1 -1
  109. package/dist/clis/grok/ask.d.ts +4 -0
  110. package/dist/clis/grok/ask.js +28 -10
  111. package/dist/clis/grok/ask.test.js +18 -0
  112. package/dist/clis/jd/item.d.ts +1 -0
  113. package/dist/clis/jd/item.js +96 -0
  114. package/dist/clis/jd/item.test.d.ts +1 -0
  115. package/dist/clis/jd/item.test.js +28 -0
  116. package/dist/clis/jike/feed.js +1 -1
  117. package/dist/clis/jike/search.js +1 -1
  118. package/dist/clis/linkedin/search.js +5 -4
  119. package/dist/clis/linkedin/timeline.d.ts +21 -0
  120. package/dist/clis/linkedin/timeline.js +503 -0
  121. package/dist/clis/linkedin/timeline.test.d.ts +1 -0
  122. package/dist/clis/linkedin/timeline.test.js +81 -0
  123. package/dist/clis/medium/feed.js +1 -1
  124. package/dist/clis/medium/search.js +1 -1
  125. package/dist/clis/medium/user.js +1 -1
  126. package/dist/clis/medium/{shared.js → utils.js} +2 -1
  127. package/dist/clis/pixiv/detail.yaml +49 -0
  128. package/dist/clis/pixiv/download.d.ts +7 -0
  129. package/dist/clis/pixiv/download.js +78 -0
  130. package/dist/clis/pixiv/download.test.d.ts +1 -0
  131. package/dist/clis/pixiv/download.test.js +87 -0
  132. package/dist/clis/pixiv/illusts.d.ts +8 -0
  133. package/dist/clis/pixiv/illusts.js +65 -0
  134. package/dist/clis/pixiv/illusts.test.d.ts +1 -0
  135. package/dist/clis/pixiv/illusts.test.js +99 -0
  136. package/dist/clis/pixiv/ranking.yaml +53 -0
  137. package/dist/clis/pixiv/search.d.ts +6 -0
  138. package/dist/clis/pixiv/search.js +43 -0
  139. package/dist/clis/pixiv/search.test.d.ts +1 -0
  140. package/dist/clis/pixiv/search.test.js +83 -0
  141. package/dist/clis/pixiv/test-utils.d.ts +12 -0
  142. package/dist/clis/pixiv/test-utils.js +23 -0
  143. package/dist/clis/pixiv/user.yaml +46 -0
  144. package/dist/clis/pixiv/utils.d.ts +27 -0
  145. package/dist/clis/pixiv/utils.js +49 -0
  146. package/dist/clis/reddit/comment.js +2 -1
  147. package/dist/clis/reddit/read.js +4 -3
  148. package/dist/clis/reddit/read.test.d.ts +1 -0
  149. package/dist/clis/reddit/read.test.js +28 -0
  150. package/dist/clis/reddit/save.js +2 -1
  151. package/dist/clis/reddit/saved.js +7 -3
  152. package/dist/clis/reddit/subscribe.js +2 -1
  153. package/dist/clis/reddit/upvote.js +2 -1
  154. package/dist/clis/reddit/upvoted.js +7 -3
  155. package/dist/clis/sinablog/article.js +1 -1
  156. package/dist/clis/sinablog/hot.js +1 -1
  157. package/dist/clis/sinablog/user.js +1 -1
  158. package/dist/clis/substack/feed.js +1 -1
  159. package/dist/clis/substack/publication.js +1 -1
  160. package/dist/clis/substack/search.js +3 -2
  161. package/dist/clis/substack/{shared.js → utils.js} +3 -2
  162. package/dist/clis/tiktok/search.yaml +2 -1
  163. package/dist/clis/twitter/accept.js +2 -1
  164. package/dist/clis/twitter/article.js +4 -1
  165. package/dist/clis/twitter/block.js +2 -1
  166. package/dist/clis/twitter/bookmark.js +2 -1
  167. package/dist/clis/twitter/bookmarks.js +3 -2
  168. package/dist/clis/twitter/delete.js +2 -1
  169. package/dist/clis/twitter/follow.js +2 -1
  170. package/dist/clis/twitter/followers.js +3 -2
  171. package/dist/clis/twitter/following.js +3 -2
  172. package/dist/clis/twitter/hide-reply.js +2 -1
  173. package/dist/clis/twitter/like.js +2 -1
  174. package/dist/clis/twitter/notifications.js +2 -1
  175. package/dist/clis/twitter/post.js +2 -1
  176. package/dist/clis/twitter/profile.js +5 -2
  177. package/dist/clis/twitter/reply-dm.js +2 -1
  178. package/dist/clis/twitter/reply.js +2 -1
  179. package/dist/clis/twitter/search.js +30 -13
  180. package/dist/clis/twitter/search.test.d.ts +1 -0
  181. package/dist/clis/twitter/search.test.js +104 -0
  182. package/dist/clis/twitter/thread.js +2 -2
  183. package/dist/clis/twitter/timeline.js +3 -2
  184. package/dist/clis/twitter/trending.js +3 -2
  185. package/dist/clis/twitter/unblock.js +2 -1
  186. package/dist/clis/twitter/unbookmark.js +2 -1
  187. package/dist/clis/twitter/unfollow.js +2 -1
  188. package/dist/clis/v2ex/daily.js +3 -2
  189. package/dist/clis/v2ex/me.js +3 -2
  190. package/dist/clis/v2ex/notifications.js +4 -4
  191. package/dist/clis/web/read.d.ts +16 -0
  192. package/dist/clis/web/read.js +202 -0
  193. package/dist/clis/xueqiu/danjuan-utils.d.ts +55 -0
  194. package/dist/clis/xueqiu/danjuan-utils.js +126 -0
  195. package/dist/clis/xueqiu/danjuan-utils.test.d.ts +1 -0
  196. package/dist/clis/xueqiu/danjuan-utils.test.js +41 -0
  197. package/dist/clis/xueqiu/fund-holdings.d.ts +1 -0
  198. package/dist/clis/xueqiu/fund-holdings.js +28 -0
  199. package/dist/clis/xueqiu/fund-snapshot.d.ts +1 -0
  200. package/dist/clis/xueqiu/fund-snapshot.js +25 -0
  201. package/dist/clis/youtube/transcript.js +5 -4
  202. package/dist/clis/youtube/video.js +3 -2
  203. package/dist/daemon.js +7 -3
  204. package/dist/discovery.js +11 -10
  205. package/dist/doctor.js +2 -1
  206. package/dist/download/index.d.ts +4 -12
  207. package/dist/download/index.js +33 -12
  208. package/dist/download/index.test.js +79 -2
  209. package/dist/download/media-download.js +4 -2
  210. package/dist/engine.test.js +76 -4
  211. package/dist/execution.d.ts +1 -9
  212. package/dist/execution.js +56 -46
  213. package/dist/explore.js +12 -111
  214. package/dist/external-clis.yaml +0 -8
  215. package/dist/external.js +7 -5
  216. package/dist/external.test.js +4 -0
  217. package/dist/generate.d.ts +0 -9
  218. package/dist/generate.js +4 -20
  219. package/dist/hooks.d.ts +46 -0
  220. package/dist/hooks.js +56 -0
  221. package/dist/hooks.test.d.ts +4 -0
  222. package/dist/hooks.test.js +92 -0
  223. package/dist/interceptor.js +70 -23
  224. package/dist/main.js +2 -0
  225. package/dist/output.js +12 -6
  226. package/dist/pipeline/executor.js +1 -1
  227. package/dist/pipeline/steps/browser.js +1 -3
  228. package/dist/pipeline/steps/download.js +42 -26
  229. package/dist/pipeline/steps/download.test.d.ts +1 -0
  230. package/dist/pipeline/steps/download.test.js +101 -0
  231. package/dist/pipeline/steps/fetch.js +40 -22
  232. package/dist/pipeline/steps/fetch.test.d.ts +1 -0
  233. package/dist/pipeline/steps/fetch.test.js +123 -0
  234. package/dist/pipeline/steps/transform.js +2 -6
  235. package/dist/pipeline/template.js +66 -52
  236. package/dist/pipeline/template.test.js +28 -0
  237. package/dist/pipeline/transform.test.js +18 -0
  238. package/dist/plugin.d.ts +40 -1
  239. package/dist/plugin.js +214 -17
  240. package/dist/plugin.test.d.ts +1 -1
  241. package/dist/plugin.test.js +219 -3
  242. package/dist/record.js +6 -98
  243. package/dist/registry-api.d.ts +2 -0
  244. package/dist/registry-api.js +1 -0
  245. package/dist/registry.d.ts +5 -2
  246. package/dist/registry.js +1 -2
  247. package/dist/runtime.d.ts +0 -1
  248. package/dist/runtime.js +14 -4
  249. package/dist/snapshotFormatter.d.ts +7 -14
  250. package/dist/snapshotFormatter.js +38 -78
  251. package/dist/utils.d.ts +9 -0
  252. package/dist/utils.js +29 -0
  253. package/dist/validate.js +3 -5
  254. package/dist/yaml-schema.d.ts +26 -0
  255. package/dist/yaml-schema.js +5 -0
  256. package/docs/.vitepress/config.mts +3 -0
  257. package/docs/adapters/browser/dictionary.md +27 -0
  258. package/docs/adapters/browser/jd.md +27 -0
  259. package/docs/adapters/browser/linkedin.md +6 -0
  260. package/docs/adapters/browser/pixiv.md +92 -0
  261. package/docs/adapters/browser/web.md +30 -0
  262. package/docs/adapters/browser/xueqiu.md +27 -9
  263. package/docs/adapters/index.md +3 -1
  264. package/docs/comparison.md +125 -0
  265. package/docs/developer/contributing.md +21 -2
  266. package/docs/developer/testing.md +14 -8
  267. package/docs/developer/ts-adapter.md +18 -0
  268. package/docs/developer/yaml-adapter.md +16 -0
  269. package/docs/guide/plugins.md +10 -0
  270. package/docs/zh/guide/plugins.md +10 -0
  271. package/extension/dist/background.js +519 -444
  272. package/extension/manifest.json +1 -1
  273. package/extension/package.json +1 -1
  274. package/extension/src/background.test.ts +46 -1
  275. package/extension/src/background.ts +108 -33
  276. package/extension/src/cdp.ts +9 -9
  277. package/package.json +3 -2
  278. package/scripts/check-doc-coverage.sh +2 -0
  279. package/src/analysis.ts +170 -0
  280. package/src/browser/cdp.test.ts +66 -0
  281. package/src/browser/cdp.ts +59 -44
  282. package/src/browser/dom-snapshot.test.ts +42 -0
  283. package/src/browser/dom-snapshot.ts +56 -3
  284. package/src/browser/index.ts +2 -2
  285. package/src/browser/mcp.ts +2 -4
  286. package/src/browser/page.ts +34 -37
  287. package/src/browser/stealth.ts +24 -10
  288. package/src/browser.test.ts +2 -2
  289. package/src/build-manifest.test.ts +14 -0
  290. package/src/build-manifest.ts +13 -31
  291. package/src/cascade.ts +5 -3
  292. package/src/cli.ts +66 -34
  293. package/src/clis/_shared/desktop-commands.ts +121 -0
  294. package/src/clis/antigravity/serve.ts +6 -3
  295. package/src/clis/arxiv/search.ts +1 -1
  296. package/src/clis/bilibili/dynamic.test.ts +79 -0
  297. package/src/clis/bilibili/favorite.ts +5 -2
  298. package/src/clis/bilibili/following.ts +3 -2
  299. package/src/clis/bilibili/subtitle.ts +8 -7
  300. package/src/clis/bilibili/utils.ts +2 -2
  301. package/src/clis/boss/batchgreet.ts +1 -1
  302. package/src/clis/boss/chatlist.ts +1 -1
  303. package/src/clis/boss/chatmsg.ts +1 -1
  304. package/src/clis/boss/detail.ts +1 -1
  305. package/src/clis/boss/exchange.ts +1 -1
  306. package/src/clis/boss/greet.ts +1 -1
  307. package/src/clis/boss/invite.ts +1 -1
  308. package/src/clis/boss/joblist.ts +1 -1
  309. package/src/clis/boss/mark.ts +4 -3
  310. package/src/clis/boss/recommend.ts +1 -1
  311. package/src/clis/boss/resume.ts +1 -1
  312. package/src/clis/boss/search.ts +1 -1
  313. package/src/clis/boss/send.ts +5 -4
  314. package/src/clis/boss/stats.ts +1 -1
  315. package/src/clis/chatgpt/ask.ts +5 -0
  316. package/src/clis/chatgpt/new.ts +7 -2
  317. package/src/clis/chatgpt/read.ts +7 -2
  318. package/src/clis/chatgpt/send.ts +3 -2
  319. package/src/clis/chatgpt/status.ts +6 -1
  320. package/src/clis/chatwise/ask.ts +7 -2
  321. package/src/clis/chatwise/export.ts +2 -0
  322. package/src/clis/chatwise/history.ts +2 -0
  323. package/src/clis/chatwise/model.ts +7 -3
  324. package/src/clis/chatwise/new.ts +3 -20
  325. package/src/clis/chatwise/read.ts +2 -0
  326. package/src/clis/chatwise/screenshot.ts +3 -32
  327. package/src/clis/chatwise/send.ts +7 -2
  328. package/src/clis/chatwise/shared.ts +8 -0
  329. package/src/clis/chatwise/status.ts +3 -24
  330. package/src/clis/codex/ask.ts +5 -2
  331. package/src/clis/codex/dump.ts +2 -27
  332. package/src/clis/codex/new.ts +2 -28
  333. package/src/clis/codex/screenshot.ts +2 -32
  334. package/src/clis/codex/send.ts +5 -4
  335. package/src/clis/codex/status.ts +2 -24
  336. package/src/clis/cursor/ask.ts +2 -1
  337. package/src/clis/cursor/composer.ts +2 -1
  338. package/src/clis/cursor/dump.ts +2 -27
  339. package/src/clis/cursor/new.ts +2 -20
  340. package/src/clis/cursor/read.ts +2 -1
  341. package/src/clis/cursor/screenshot.ts +1 -36
  342. package/src/clis/cursor/send.ts +2 -1
  343. package/src/clis/cursor/status.ts +2 -22
  344. package/src/clis/dictionary/examples.yaml +25 -0
  345. package/src/clis/dictionary/search.yaml +27 -0
  346. package/src/clis/dictionary/synonyms.yaml +25 -0
  347. package/src/clis/douban/book-hot.ts +1 -1
  348. package/src/clis/douban/movie-hot.ts +1 -1
  349. package/src/clis/douban/search.ts +1 -1
  350. package/src/clis/douban/utils.ts +165 -1
  351. package/src/clis/doubao/ask.ts +1 -1
  352. package/src/clis/doubao/new.ts +1 -1
  353. package/src/clis/doubao/read.ts +1 -1
  354. package/src/clis/doubao/send.ts +1 -1
  355. package/src/clis/doubao/status.ts +1 -1
  356. package/src/clis/doubao-app/ask.ts +1 -1
  357. package/src/clis/doubao-app/new.ts +1 -1
  358. package/src/clis/doubao-app/read.ts +1 -1
  359. package/src/clis/doubao-app/send.ts +1 -1
  360. package/src/clis/grok/ask.test.ts +25 -0
  361. package/src/clis/grok/ask.ts +25 -12
  362. package/src/clis/jd/item.test.ts +35 -0
  363. package/src/clis/jd/item.ts +101 -0
  364. package/src/clis/jike/feed.ts +1 -1
  365. package/src/clis/jike/search.ts +1 -1
  366. package/src/clis/linkedin/search.ts +5 -4
  367. package/src/clis/linkedin/timeline.test.ts +99 -0
  368. package/src/clis/linkedin/timeline.ts +532 -0
  369. package/src/clis/medium/feed.ts +1 -1
  370. package/src/clis/medium/search.ts +1 -1
  371. package/src/clis/medium/user.ts +1 -1
  372. package/src/clis/medium/{shared.ts → utils.ts} +2 -1
  373. package/src/clis/pixiv/detail.yaml +49 -0
  374. package/src/clis/pixiv/download.test.ts +114 -0
  375. package/src/clis/pixiv/download.ts +91 -0
  376. package/src/clis/pixiv/illusts.test.ts +115 -0
  377. package/src/clis/pixiv/illusts.ts +78 -0
  378. package/src/clis/pixiv/ranking.yaml +53 -0
  379. package/src/clis/pixiv/search.test.ts +97 -0
  380. package/src/clis/pixiv/search.ts +53 -0
  381. package/src/clis/pixiv/test-utils.ts +29 -0
  382. package/src/clis/pixiv/user.yaml +46 -0
  383. package/src/clis/pixiv/utils.ts +62 -0
  384. package/src/clis/reddit/comment.ts +2 -1
  385. package/src/clis/reddit/read.test.ts +34 -0
  386. package/src/clis/reddit/read.ts +4 -3
  387. package/src/clis/reddit/save.ts +2 -1
  388. package/src/clis/reddit/saved.ts +6 -2
  389. package/src/clis/reddit/subscribe.ts +2 -1
  390. package/src/clis/reddit/upvote.ts +2 -1
  391. package/src/clis/reddit/upvoted.ts +6 -2
  392. package/src/clis/sinablog/article.ts +1 -1
  393. package/src/clis/sinablog/hot.ts +1 -1
  394. package/src/clis/sinablog/user.ts +1 -1
  395. package/src/clis/substack/feed.ts +1 -1
  396. package/src/clis/substack/publication.ts +1 -1
  397. package/src/clis/substack/search.ts +3 -2
  398. package/src/clis/substack/{shared.ts → utils.ts} +3 -2
  399. package/src/clis/tiktok/search.yaml +2 -1
  400. package/src/clis/twitter/accept.ts +2 -1
  401. package/src/clis/twitter/article.ts +3 -1
  402. package/src/clis/twitter/block.ts +2 -1
  403. package/src/clis/twitter/bookmark.ts +2 -1
  404. package/src/clis/twitter/bookmarks.ts +3 -2
  405. package/src/clis/twitter/delete.ts +2 -1
  406. package/src/clis/twitter/follow.ts +2 -1
  407. package/src/clis/twitter/followers.ts +3 -2
  408. package/src/clis/twitter/following.ts +3 -2
  409. package/src/clis/twitter/hide-reply.ts +2 -1
  410. package/src/clis/twitter/like.ts +2 -1
  411. package/src/clis/twitter/notifications.ts +2 -1
  412. package/src/clis/twitter/post.ts +2 -1
  413. package/src/clis/twitter/profile.ts +4 -2
  414. package/src/clis/twitter/reply-dm.ts +2 -1
  415. package/src/clis/twitter/reply.ts +2 -1
  416. package/src/clis/twitter/search.test.ts +113 -0
  417. package/src/clis/twitter/search.ts +38 -14
  418. package/src/clis/twitter/thread.ts +2 -2
  419. package/src/clis/twitter/timeline.ts +3 -2
  420. package/src/clis/twitter/trending.ts +3 -2
  421. package/src/clis/twitter/unblock.ts +2 -1
  422. package/src/clis/twitter/unbookmark.ts +2 -1
  423. package/src/clis/twitter/unfollow.ts +2 -1
  424. package/src/clis/v2ex/daily.ts +3 -2
  425. package/src/clis/v2ex/me.ts +3 -2
  426. package/src/clis/v2ex/notifications.ts +3 -4
  427. package/src/clis/web/read.ts +210 -0
  428. package/src/clis/xueqiu/danjuan-utils.test.ts +49 -0
  429. package/src/clis/xueqiu/danjuan-utils.ts +176 -0
  430. package/src/clis/xueqiu/fund-holdings.ts +32 -0
  431. package/src/clis/xueqiu/fund-snapshot.ts +27 -0
  432. package/src/clis/youtube/transcript.ts +5 -4
  433. package/src/clis/youtube/video.ts +3 -2
  434. package/src/daemon.ts +5 -4
  435. package/src/discovery.ts +12 -34
  436. package/src/doctor.ts +3 -2
  437. package/src/download/index.test.ts +93 -2
  438. package/src/download/index.ts +44 -23
  439. package/src/download/media-download.ts +5 -3
  440. package/src/engine.test.ts +84 -3
  441. package/src/execution.ts +62 -46
  442. package/src/explore.ts +21 -90
  443. package/src/external-clis.yaml +0 -8
  444. package/src/external.test.ts +9 -0
  445. package/src/external.ts +12 -10
  446. package/src/generate.ts +4 -41
  447. package/src/hooks.test.ts +126 -0
  448. package/src/hooks.ts +90 -0
  449. package/src/interceptor.ts +73 -23
  450. package/src/main.ts +2 -0
  451. package/src/output.ts +14 -6
  452. package/src/pipeline/executor.ts +1 -1
  453. package/src/pipeline/steps/browser.ts +1 -3
  454. package/src/pipeline/steps/download.test.ts +136 -0
  455. package/src/pipeline/steps/download.ts +47 -34
  456. package/src/pipeline/steps/fetch.test.ts +179 -0
  457. package/src/pipeline/steps/fetch.ts +39 -23
  458. package/src/pipeline/steps/transform.ts +2 -6
  459. package/src/pipeline/template.test.ts +28 -0
  460. package/src/pipeline/template.ts +67 -79
  461. package/src/pipeline/transform.test.ts +20 -0
  462. package/src/plugin.test.ts +251 -3
  463. package/src/plugin.ts +265 -21
  464. package/src/record.ts +12 -84
  465. package/src/registry-api.ts +2 -0
  466. package/src/registry.ts +7 -4
  467. package/src/runtime.ts +14 -4
  468. package/src/snapshotFormatter.ts +43 -121
  469. package/src/utils.ts +39 -0
  470. package/src/validate.ts +3 -5
  471. package/src/yaml-schema.ts +28 -0
  472. package/tests/e2e/browser-auth.test.ts +25 -0
  473. package/tests/e2e/plugin-management.test.ts +137 -0
  474. package/tests/e2e/public-commands.test.ts +34 -1
  475. package/vitest.config.ts +19 -1
  476. package/.github/workflows/pkg-pr-new.yml +0 -30
  477. package/dist/clis/douban/shared.d.ts +0 -4
  478. package/dist/clis/douban/shared.js +0 -155
  479. package/src/clis/douban/shared.ts +0 -165
  480. /package/dist/clis/boss/{common.d.ts → utils.d.ts} +0 -0
  481. /package/dist/clis/boss/{common.js → utils.js} +0 -0
  482. /package/dist/clis/doubao/{common.d.ts → utils.d.ts} +0 -0
  483. /package/dist/clis/doubao/{common.js → utils.js} +0 -0
  484. /package/dist/clis/doubao-app/{common.d.ts → utils.d.ts} +0 -0
  485. /package/dist/clis/doubao-app/{common.js → utils.js} +0 -0
  486. /package/dist/clis/jike/{shared.d.ts → utils.d.ts} +0 -0
  487. /package/dist/clis/jike/{shared.js → utils.js} +0 -0
  488. /package/dist/clis/medium/{shared.d.ts → utils.d.ts} +0 -0
  489. /package/dist/clis/sinablog/{shared.d.ts → utils.d.ts} +0 -0
  490. /package/dist/clis/sinablog/{shared.js → utils.js} +0 -0
  491. /package/dist/clis/substack/{shared.d.ts → utils.d.ts} +0 -0
  492. /package/src/clis/boss/{common.ts → utils.ts} +0 -0
  493. /package/src/clis/doubao/{common.ts → utils.ts} +0 -0
  494. /package/src/clis/doubao-app/{common.ts → utils.ts} +0 -0
  495. /package/src/clis/jike/{shared.ts → utils.ts} +0 -0
  496. /package/src/clis/sinablog/{shared.ts → utils.ts} +0 -0
@@ -1,25 +1,4 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import type { IPage } from '../../types.js';
1
+ import { makeStatusCommand } from '../_shared/desktop-commands.js';
2
+ import { chatwiseRequiredEnv } from './shared.js';
3
3
 
4
- export const statusCommand = cli({
5
- site: 'chatwise',
6
- name: 'status',
7
- description: 'Check active CDP connection to ChatWise Desktop',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- args: [],
12
- columns: ['Status', 'Url', 'Title'],
13
- func: async (page: IPage) => {
14
- const url = await page.evaluate('window.location.href');
15
- const title = await page.evaluate('document.title');
16
-
17
- return [
18
- {
19
- Status: 'Connected',
20
- Url: url,
21
- Title: title,
22
- },
23
- ];
24
- },
25
- });
4
+ export const statusCommand = makeStatusCommand('chatwise', 'ChatWise Desktop', { requiredEnv: chatwiseRequiredEnv });
@@ -1,4 +1,5 @@
1
1
  import { cli, Strategy } from '../../registry.js';
2
+ import { SelectorError } from '../../errors.js';
2
3
  import type { IPage } from '../../types.js';
3
4
 
4
5
  export const askCommand = cli({
@@ -26,15 +27,17 @@ export const askCommand = cli({
26
27
  `);
27
28
 
28
29
  // Inject and send
29
- await page.evaluate(`
30
+ const injected = await page.evaluate(`
30
31
  (function(text) {
31
32
  const editables = Array.from(document.querySelectorAll('[contenteditable="true"]'));
32
33
  const composer = editables.length > 0 ? editables[editables.length - 1] : document.querySelector('textarea');
33
- if (!composer) throw new Error('Could not find Codex input');
34
+ if (!composer) return false;
34
35
  composer.focus();
35
36
  document.execCommand('insertText', false, text);
37
+ return true;
36
38
  })(${JSON.stringify(text)})
37
39
  `);
40
+ if (!injected) throw new SelectorError('Codex input element');
38
41
  await page.wait(0.5);
39
42
  await page.pressKey('Enter');
40
43
 
@@ -1,28 +1,3 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import * as fs from 'fs';
1
+ import { makeDumpCommand } from '../_shared/desktop-commands.js';
3
2
 
4
- export const dumpCommand = cli({
5
- site: 'codex',
6
- name: 'dump',
7
- description: 'Dump the DOM and Accessibility tree of Codex for reverse-engineering',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- columns: ['action', 'files'],
12
- func: async (page) => {
13
- // Extract full HTML
14
- const dom = await page.evaluate('document.body.innerHTML');
15
- fs.writeFileSync('/tmp/codex-dom.html', dom);
16
-
17
- // Get accessibility snapshot
18
- const snap = await page.snapshot({ interactive: false });
19
- fs.writeFileSync('/tmp/codex-snapshot.json', JSON.stringify(snap, null, 2));
20
-
21
- return [
22
- {
23
- action: 'Dom extraction finished',
24
- files: '/tmp/codex-dom.html, /tmp/codex-snapshot.json',
25
- },
26
- ];
27
- },
28
- });
3
+ export const dumpCommand = makeDumpCommand('codex');
@@ -1,29 +1,3 @@
1
- import { cli, Strategy } from '../../registry.js';
1
+ import { makeNewCommand } from '../_shared/desktop-commands.js';
2
2
 
3
- export const newCommand = cli({
4
- site: 'codex',
5
- name: 'new',
6
- description: 'Start a new Codex conversation thread / isolated workspace',
7
- domain: 'localhost',
8
- strategy: Strategy.UI,
9
- browser: true,
10
- columns: ['Status', 'Action'],
11
- func: async (page) => {
12
- // According to research, Cmd+N / Ctrl+N spins up a new thread
13
- const isMac = process.platform === 'darwin';
14
- const newThreadKey = isMac ? 'Meta+N' : 'Control+N';
15
-
16
- // Simulate keyboard shortcut
17
- await page.pressKey(newThreadKey);
18
-
19
- // Wait a brief moment for UI animation
20
- await page.wait(1);
21
-
22
- return [
23
- {
24
- Status: 'Success',
25
- Action: `Pressed ${newThreadKey} to trigger New Thread`,
26
- },
27
- ];
28
- },
29
- });
3
+ export const newCommand = makeNewCommand('codex', 'Codex conversation');
@@ -1,33 +1,3 @@
1
- import * as fs from 'node:fs';
2
- import { cli, Strategy } from '../../registry.js';
3
- import type { IPage } from '../../types.js';
1
+ import { makeScreenshotCommand } from '../_shared/desktop-commands.js';
4
2
 
5
- export const screenshotCommand = cli({
6
- site: 'codex',
7
- name: 'screenshot',
8
- description: 'Capture a snapshot of the current Codex window (DOM + Accessibility tree)',
9
- domain: 'localhost',
10
- strategy: Strategy.UI,
11
- browser: true,
12
- args: [
13
- { name: 'output', required: false, help: 'Output file path (default: /tmp/codex-snapshot.txt)' },
14
- ],
15
- columns: ['Status', 'File'],
16
- func: async (page: IPage, kwargs: any) => {
17
- const outputPath = (kwargs.output as string) || '/tmp/codex-snapshot.txt';
18
-
19
- const snap = await page.snapshot({ compact: true });
20
- const html = await page.evaluate('document.documentElement.outerHTML');
21
-
22
- const htmlPath = outputPath.replace(/\.\w+$/, '') + '-dom.html';
23
- const snapPath = outputPath.replace(/\.\w+$/, '') + '-a11y.txt';
24
-
25
- fs.writeFileSync(htmlPath, html);
26
- fs.writeFileSync(snapPath, typeof snap === 'string' ? snap : JSON.stringify(snap, null, 2));
27
-
28
- return [
29
- { Status: 'Success', File: htmlPath },
30
- { Status: 'Success', File: snapPath },
31
- ];
32
- },
33
- });
3
+ export const screenshotCommand = makeScreenshotCommand('codex', 'Codex');
@@ -1,4 +1,5 @@
1
1
  import { cli, Strategy } from '../../registry.js';
2
+ import { SelectorError } from '../../errors.js';
2
3
  import type { IPage } from '../../types.js';
3
4
 
4
5
  export const sendCommand = cli({
@@ -13,7 +14,7 @@ export const sendCommand = cli({
13
14
  func: async (page: IPage, kwargs: any) => {
14
15
  const textToInsert = kwargs.text as string;
15
16
 
16
- await page.evaluate(`
17
+ const injected = await page.evaluate(`
17
18
  (function(text) {
18
19
  let composer = document.querySelector('textarea, [contenteditable="true"]');
19
20
 
@@ -22,14 +23,14 @@ export const sendCommand = cli({
22
23
  composer = editables[editables.length - 1];
23
24
  }
24
25
 
25
- if (!composer) {
26
- throw new Error('Could not find Composer input element in Codex UI');
27
- }
26
+ if (!composer) return false;
28
27
 
29
28
  composer.focus();
30
29
  document.execCommand('insertText', false, text);
30
+ return true;
31
31
  })(${JSON.stringify(textToInsert)})
32
32
  `);
33
+ if (!injected) throw new SelectorError('Codex Composer input element');
33
34
 
34
35
  // Wait for the UI to register the input
35
36
  await page.wait(0.5);
@@ -1,25 +1,3 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import type { IPage } from '../../types.js';
1
+ import { makeStatusCommand } from '../_shared/desktop-commands.js';
3
2
 
4
- export const statusCommand = cli({
5
- site: 'codex',
6
- name: 'status',
7
- description: 'Check active CDP connection to OpenAI Codex App',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- args: [],
12
- columns: ['Status', 'Url', 'Title'],
13
- func: async (page: IPage) => {
14
- const url = await page.evaluate('window.location.href');
15
- const title = await page.evaluate('document.title');
16
-
17
- return [
18
- {
19
- Status: 'Connected',
20
- Url: url,
21
- Title: title,
22
- },
23
- ];
24
- },
25
- });
3
+ export const statusCommand = makeStatusCommand('codex', 'OpenAI Codex App');
@@ -1,4 +1,5 @@
1
1
  import { cli, Strategy } from '../../registry.js';
2
+ import { SelectorError } from '../../errors.js';
2
3
  import type { IPage } from '../../types.js';
3
4
 
4
5
  export const askCommand = cli({
@@ -33,7 +34,7 @@ export const askCommand = cli({
33
34
  })(${JSON.stringify(text)})`
34
35
  );
35
36
 
36
- if (!injected) throw new Error('Could not find input element.');
37
+ if (!injected) throw new SelectorError('Cursor input element');
37
38
  await page.wait(0.5);
38
39
  await page.pressKey('Enter');
39
40
 
@@ -1,4 +1,5 @@
1
1
  import { cli, Strategy } from '../../registry.js';
2
+ import { SelectorError } from '../../errors.js';
2
3
  import type { IPage } from '../../types.js';
3
4
 
4
5
  export const composerCommand = cli({
@@ -33,7 +34,7 @@ export const composerCommand = cli({
33
34
  );
34
35
 
35
36
  if (!typed) {
36
- throw new Error('Could not find Cursor Composer input element after pressing Cmd+I.');
37
+ throw new SelectorError('Cursor Composer input element', 'Could not find Cursor Composer input element after pressing Cmd+I.');
37
38
  }
38
39
 
39
40
  await page.wait(0.5);
@@ -1,28 +1,3 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import * as fs from 'fs';
1
+ import { makeDumpCommand } from '../_shared/desktop-commands.js';
3
2
 
4
- export const dumpCommand = cli({
5
- site: 'cursor',
6
- name: 'dump',
7
- description: 'Dump the DOM and Accessibility tree of Cursor for reverse-engineering',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- columns: ['action', 'files'],
12
- func: async (page) => {
13
- // Extract full HTML
14
- const dom = await page.evaluate('document.body.innerHTML');
15
- fs.writeFileSync('/tmp/cursor-dom.html', dom);
16
-
17
- // Get accessibility snapshot
18
- const snap = await page.snapshot({ interactive: false });
19
- fs.writeFileSync('/tmp/cursor-snapshot.json', JSON.stringify(snap, null, 2));
20
-
21
- return [
22
- {
23
- action: 'Dom extraction finished',
24
- files: '/tmp/cursor-dom.html, /tmp/cursor-snapshot.json',
25
- },
26
- ];
27
- },
28
- });
3
+ export const dumpCommand = makeDumpCommand('cursor');
@@ -1,21 +1,3 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import type { IPage } from '../../types.js';
1
+ import { makeNewCommand } from '../_shared/desktop-commands.js';
3
2
 
4
- export const newCommand = cli({
5
- site: 'cursor',
6
- name: 'new',
7
- description: 'Start a new Cursor chat or Composer session',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- args: [],
12
- columns: ['Status'],
13
- func: async (page: IPage) => {
14
- // Use keyboard shortcut — most robust approach, avoids brittle DOM selectors
15
- const isMac = process.platform === 'darwin';
16
- await page.pressKey(isMac ? 'Meta+N' : 'Control+N');
17
- await page.wait(1);
18
-
19
- return [{ Status: 'Success' }];
20
- },
21
- });
3
+ export const newCommand = makeNewCommand('cursor', 'Cursor chat or Composer');
@@ -1,4 +1,5 @@
1
1
  import { cli, Strategy } from '../../registry.js';
2
+ import { EmptyResultError } from '../../errors.js';
2
3
  import type { IPage } from '../../types.js';
3
4
 
4
5
  export const readCommand = cli({
@@ -39,7 +40,7 @@ export const readCommand = cli({
39
40
  `);
40
41
 
41
42
  if (!history || history.length === 0) {
42
- throw new Error('No conversation history found in Cursor.');
43
+ throw new EmptyResultError('cursor read', 'No conversation history found in Cursor.');
43
44
  }
44
45
 
45
46
  return history;
@@ -1,38 +1,3 @@
1
- import * as fs from 'node:fs';
2
- import { cli, Strategy } from '../../registry.js';
3
- import type { IPage } from '../../types.js';
4
-
5
- function makeScreenshotCommand(site: string) {
6
- return cli({
7
- site,
8
- name: 'screenshot',
9
- description: `Capture a snapshot of the current ${site} window (DOM + Accessibility tree)`,
10
- domain: 'localhost',
11
- strategy: Strategy.UI,
12
- browser: true,
13
- args: [
14
- { name: 'output', required: false, help: `Output file path (default: /tmp/${site}-snapshot.txt)` },
15
- ],
16
- columns: ['Status', 'File'],
17
- func: async (page: IPage, kwargs: any) => {
18
- const outputPath = (kwargs.output as string) || `/tmp/${site}-snapshot.txt`;
19
-
20
- // Get both the accessibility snapshot and the raw DOM HTML
21
- const snap = await page.snapshot({ compact: true });
22
- const html = await page.evaluate('document.documentElement.outerHTML');
23
-
24
- const htmlPath = outputPath.replace(/\.\w+$/, '') + '-dom.html';
25
- const snapPath = outputPath.replace(/\.\w+$/, '') + '-a11y.txt';
26
-
27
- fs.writeFileSync(htmlPath, html);
28
- fs.writeFileSync(snapPath, typeof snap === 'string' ? snap : JSON.stringify(snap, null, 2));
29
-
30
- return [
31
- { Status: 'Success', File: htmlPath },
32
- { Status: 'Success', File: snapPath },
33
- ];
34
- },
35
- });
36
- }
1
+ import { makeScreenshotCommand } from '../_shared/desktop-commands.js';
37
2
 
38
3
  export const screenshotCursor = makeScreenshotCommand('cursor');
@@ -1,4 +1,5 @@
1
1
  import { cli, Strategy } from '../../registry.js';
2
+ import { SelectorError } from '../../errors.js';
2
3
  import type { IPage } from '../../types.js';
3
4
 
4
5
  export const sendCommand = cli({
@@ -29,7 +30,7 @@ export const sendCommand = cli({
29
30
  );
30
31
 
31
32
  if (!injected) {
32
- throw new Error('Could not find Cursor Composer input element.');
33
+ throw new SelectorError('Cursor Composer input element');
33
34
  }
34
35
 
35
36
  // Submit the command. In Cursor, Enter usually submits the chat.
@@ -1,23 +1,3 @@
1
- import { cli, Strategy } from '../../registry.js';
1
+ import { makeStatusCommand } from '../_shared/desktop-commands.js';
2
2
 
3
- export const statusCommand = cli({
4
- site: 'cursor',
5
- name: 'status',
6
- description: 'Check active CDP connection to Cursor AI Editor',
7
- domain: 'localhost',
8
- strategy: Strategy.UI, // Interactive UI manipulation
9
- browser: true,
10
- columns: ['Status', 'Url', 'Title'],
11
- func: async (page) => {
12
- const url = await page.evaluate('window.location.href');
13
- const title = await page.evaluate('document.title');
14
-
15
- return [
16
- {
17
- Status: 'Connected',
18
- Url: url,
19
- Title: title,
20
- },
21
- ];
22
- },
23
- });
3
+ export const statusCommand = makeStatusCommand('cursor', 'Cursor AI Editor');
@@ -0,0 +1,25 @@
1
+ site: dictionary
2
+ name: examples
3
+ description: Read real-world example sentences utilizing the word
4
+ domain: api.dictionaryapi.dev
5
+ strategy: public
6
+ browser: false
7
+
8
+ args:
9
+ word:
10
+ type: string
11
+ required: true
12
+ positional: true
13
+ description: Word to get example sentences for
14
+
15
+ pipeline:
16
+ - fetch:
17
+ url: "https://api.dictionaryapi.dev/api/v2/entries/en/${{ args.word | urlencode }}"
18
+
19
+ - map:
20
+ word: "${{ item.word }}"
21
+ example: "${{ (() => { if (item.meanings) { for (const m of item.meanings) { if (m.definitions) { for (const d of m.definitions) { if (d.example) return d.example; } } } } return 'No example found in API.'; })() }}"
22
+
23
+ - limit: 1
24
+
25
+ columns: [word, example]
@@ -0,0 +1,27 @@
1
+ site: dictionary
2
+ name: search
3
+ description: Search the Free Dictionary API for definitions, parts of speech, and pronunciations.
4
+ domain: api.dictionaryapi.dev
5
+ strategy: public
6
+ browser: false
7
+
8
+ args:
9
+ word:
10
+ type: string
11
+ required: true
12
+ positional: true
13
+ description: Word to define (e.g., serendipity)
14
+
15
+ pipeline:
16
+ - fetch:
17
+ url: "https://api.dictionaryapi.dev/api/v2/entries/en/${{ args.word | urlencode }}"
18
+
19
+ - map:
20
+ word: "${{ item.word }}"
21
+ phonetic: "${{ (() => { if (item.phonetic) return item.phonetic; if (item.phonetics) { for (const p of item.phonetics) { if (p.text) return p.text; } } return ''; })() }}"
22
+ type: "${{ (() => { if (item.meanings && item.meanings[0] && item.meanings[0].partOfSpeech) return item.meanings[0].partOfSpeech; return 'N/A'; })() }}"
23
+ definition: "${{ (() => { if (item.meanings && item.meanings[0] && item.meanings[0].definitions && item.meanings[0].definitions[0] && item.meanings[0].definitions[0].definition) return item.meanings[0].definitions[0].definition; return 'No definition found in API.'; })() }}"
24
+
25
+ - limit: 1
26
+
27
+ columns: [word, phonetic, type, definition]
@@ -0,0 +1,25 @@
1
+ site: dictionary
2
+ name: synonyms
3
+ description: Find synonyms for a specific word
4
+ domain: api.dictionaryapi.dev
5
+ strategy: public
6
+ browser: false
7
+
8
+ args:
9
+ word:
10
+ type: string
11
+ required: true
12
+ positional: true
13
+ description: Word to find synonyms for (e.g., serendipity)
14
+
15
+ pipeline:
16
+ - fetch:
17
+ url: "https://api.dictionaryapi.dev/api/v2/entries/en/${{ args.word | urlencode }}"
18
+
19
+ - map:
20
+ word: "${{ item.word }}"
21
+ synonyms: "${{ (() => { const s = new Set(); if (item.meanings) { for (const m of item.meanings) { if (m.synonyms) { for (const syn of m.synonyms) s.add(syn); } if (m.definitions) { for (const d of m.definitions) { if (d.synonyms) { for (const syn of d.synonyms) s.add(syn); } } } } } const arr = Array.from(s); return arr.length > 0 ? arr.slice(0, 5).join(', ') : 'No synonyms found in API.'; })() }}"
22
+
23
+ - limit: 1
24
+
25
+ columns: [word, synonyms]
@@ -1,5 +1,5 @@
1
1
  import { cli, Strategy } from '../../registry.js';
2
- import { loadDoubanBookHot } from './shared.js';
2
+ import { loadDoubanBookHot } from './utils.js';
3
3
 
4
4
  cli({
5
5
  site: 'douban',
@@ -1,5 +1,5 @@
1
1
  import { cli, Strategy } from '../../registry.js';
2
- import { loadDoubanMovieHot } from './shared.js';
2
+ import { loadDoubanMovieHot } from './utils.js';
3
3
 
4
4
  cli({
5
5
  site: 'douban',
@@ -1,5 +1,5 @@
1
1
  import { cli, Strategy } from '../../registry.js';
2
- import { searchDouban } from './shared.js';
2
+ import { searchDouban } from './utils.js';
3
3
 
4
4
  cli({
5
5
  site: 'douban',