@jackwener/opencli 1.1.1 → 1.2.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 (509) hide show
  1. package/CONTRIBUTING.md +39 -1
  2. package/README.md +9 -10
  3. package/README.zh-CN.md +39 -17
  4. package/SKILL.md +10 -5
  5. package/dist/browser/cdp.d.ts +4 -4
  6. package/dist/browser/cdp.js +39 -16
  7. package/dist/browser/daemon-client.d.ts +2 -1
  8. package/dist/browser/dom-helpers.js +38 -7
  9. package/dist/browser/dom-snapshot.d.ts +86 -0
  10. package/dist/browser/dom-snapshot.js +729 -0
  11. package/dist/browser/dom-snapshot.test.d.ts +11 -0
  12. package/dist/browser/dom-snapshot.test.js +212 -0
  13. package/dist/browser/index.d.ts +2 -0
  14. package/dist/browser/index.js +1 -0
  15. package/dist/browser/page.d.ts +14 -24
  16. package/dist/browser/page.js +37 -4
  17. package/dist/build-manifest.d.ts +11 -4
  18. package/dist/build-manifest.js +59 -21
  19. package/dist/build-manifest.test.js +58 -2
  20. package/dist/cli-manifest.json +3856 -1509
  21. package/dist/cli.js +66 -0
  22. package/dist/clis/barchart/greeks.js +1 -1
  23. package/dist/clis/barchart/options.js +1 -1
  24. package/dist/clis/barchart/quote.js +1 -1
  25. package/dist/clis/bilibili/download.js +1 -1
  26. package/dist/clis/bilibili/following.js +1 -1
  27. package/dist/clis/bilibili/subtitle.js +1 -1
  28. package/dist/clis/bilibili/user-videos.js +1 -1
  29. package/dist/clis/boss/batchgreet.js +10 -97
  30. package/dist/clis/boss/chatlist.js +8 -25
  31. package/dist/clis/boss/chatmsg.js +11 -42
  32. package/dist/clis/boss/common.d.ts +92 -0
  33. package/dist/clis/boss/common.js +223 -0
  34. package/dist/clis/boss/detail.js +7 -49
  35. package/dist/clis/boss/exchange.js +13 -79
  36. package/dist/clis/boss/greet.js +18 -145
  37. package/dist/clis/boss/invite.js +26 -121
  38. package/dist/clis/boss/joblist.js +6 -31
  39. package/dist/clis/boss/mark.js +12 -85
  40. package/dist/clis/boss/recommend.js +10 -49
  41. package/dist/clis/boss/resume.js +18 -118
  42. package/dist/clis/boss/search.js +12 -60
  43. package/dist/clis/boss/send.js +17 -151
  44. package/dist/clis/boss/stats.js +18 -69
  45. package/dist/clis/coupang/add-to-cart.js +1 -1
  46. package/dist/clis/devto/tag.yaml +34 -0
  47. package/dist/clis/devto/top.yaml +29 -0
  48. package/dist/clis/devto/user.yaml +33 -0
  49. package/dist/clis/douban/book-hot.d.ts +1 -0
  50. package/dist/clis/douban/book-hot.js +14 -0
  51. package/dist/clis/douban/marks.d.ts +1 -0
  52. package/dist/clis/douban/marks.js +115 -0
  53. package/dist/clis/douban/movie-hot.d.ts +1 -0
  54. package/dist/clis/douban/movie-hot.js +14 -0
  55. package/dist/clis/douban/reviews.d.ts +1 -0
  56. package/dist/clis/douban/reviews.js +106 -0
  57. package/dist/clis/douban/search.d.ts +1 -0
  58. package/dist/clis/douban/search.js +16 -0
  59. package/dist/clis/douban/shared.d.ts +4 -0
  60. package/dist/clis/douban/shared.js +155 -0
  61. package/dist/clis/douban/subject.yaml +76 -0
  62. package/dist/clis/douban/top250.yaml +70 -0
  63. package/dist/clis/douban/utils.d.ts +35 -0
  64. package/dist/clis/douban/utils.js +48 -0
  65. package/dist/clis/facebook/add-friend.yaml +43 -0
  66. package/dist/clis/facebook/events.yaml +44 -0
  67. package/dist/clis/facebook/feed.yaml +63 -0
  68. package/dist/clis/facebook/friends.yaml +42 -0
  69. package/dist/clis/facebook/groups.yaml +50 -0
  70. package/dist/clis/facebook/join-group.yaml +44 -0
  71. package/dist/clis/facebook/memories.yaml +39 -0
  72. package/dist/clis/facebook/notifications.yaml +40 -0
  73. package/dist/clis/facebook/profile.yaml +37 -0
  74. package/dist/clis/facebook/search.yaml +46 -0
  75. package/dist/clis/google/news.d.ts +5 -0
  76. package/dist/clis/google/news.js +58 -0
  77. package/dist/clis/google/search.d.ts +10 -0
  78. package/dist/clis/google/search.js +127 -0
  79. package/dist/clis/google/suggest.d.ts +5 -0
  80. package/dist/clis/google/suggest.js +34 -0
  81. package/dist/clis/google/trends.d.ts +5 -0
  82. package/dist/clis/google/trends.js +38 -0
  83. package/dist/clis/google/utils.d.ts +9 -0
  84. package/dist/clis/google/utils.js +23 -0
  85. package/dist/clis/google/utils.test.d.ts +1 -0
  86. package/dist/clis/google/utils.test.js +75 -0
  87. package/dist/clis/grok/ask.d.ts +14 -0
  88. package/dist/clis/grok/ask.js +257 -65
  89. package/dist/clis/grok/ask.test.d.ts +1 -0
  90. package/dist/clis/grok/ask.test.js +36 -0
  91. package/dist/clis/instagram/comment.yaml +52 -0
  92. package/dist/clis/instagram/explore.yaml +43 -0
  93. package/dist/clis/instagram/follow.yaml +41 -0
  94. package/dist/clis/instagram/followers.yaml +51 -0
  95. package/dist/clis/instagram/following.yaml +51 -0
  96. package/dist/clis/instagram/like.yaml +46 -0
  97. package/dist/clis/instagram/profile.yaml +42 -0
  98. package/dist/clis/instagram/save.yaml +46 -0
  99. package/dist/clis/instagram/saved.yaml +40 -0
  100. package/dist/clis/instagram/search.yaml +43 -0
  101. package/dist/clis/instagram/unfollow.yaml +38 -0
  102. package/dist/clis/instagram/unlike.yaml +46 -0
  103. package/dist/clis/instagram/unsave.yaml +46 -0
  104. package/dist/clis/instagram/user.yaml +54 -0
  105. package/dist/clis/jike/repost.js +1 -1
  106. package/dist/clis/jimeng/generate.yaml +1 -0
  107. package/dist/clis/linux-do/category.yaml +1 -0
  108. package/dist/clis/lobsters/active.yaml +29 -0
  109. package/dist/clis/lobsters/hot.yaml +29 -0
  110. package/dist/clis/lobsters/newest.yaml +29 -0
  111. package/dist/clis/lobsters/tag.yaml +34 -0
  112. package/dist/clis/medium/feed.d.ts +1 -0
  113. package/dist/clis/medium/feed.js +15 -0
  114. package/dist/clis/medium/search.d.ts +1 -0
  115. package/dist/clis/medium/search.js +15 -0
  116. package/dist/clis/medium/shared.d.ts +5 -0
  117. package/dist/clis/medium/shared.js +78 -0
  118. package/dist/clis/medium/user.d.ts +1 -0
  119. package/dist/clis/medium/user.js +15 -0
  120. package/dist/clis/reddit/comment.js +1 -1
  121. package/dist/clis/reddit/read.js +1 -1
  122. package/dist/clis/reddit/save.js +1 -1
  123. package/dist/clis/reddit/subreddit.yaml +1 -0
  124. package/dist/clis/reddit/subscribe.js +1 -1
  125. package/dist/clis/reddit/upvote.js +1 -1
  126. package/dist/clis/sinablog/article.d.ts +1 -0
  127. package/dist/clis/sinablog/article.js +14 -0
  128. package/dist/clis/sinablog/hot.d.ts +1 -0
  129. package/dist/clis/sinablog/hot.js +14 -0
  130. package/dist/clis/sinablog/search.d.ts +1 -0
  131. package/dist/clis/sinablog/search.js +51 -0
  132. package/dist/clis/sinablog/shared.d.ts +7 -0
  133. package/dist/clis/sinablog/shared.js +187 -0
  134. package/dist/clis/sinablog/user.d.ts +1 -0
  135. package/dist/clis/sinablog/user.js +15 -0
  136. package/dist/clis/substack/feed.d.ts +1 -0
  137. package/dist/clis/substack/feed.js +15 -0
  138. package/dist/clis/substack/publication.d.ts +1 -0
  139. package/dist/clis/substack/publication.js +15 -0
  140. package/dist/clis/substack/search.d.ts +1 -0
  141. package/dist/clis/substack/search.js +77 -0
  142. package/dist/clis/substack/shared.d.ts +4 -0
  143. package/dist/clis/substack/shared.js +129 -0
  144. package/dist/clis/tiktok/comment.yaml +66 -0
  145. package/dist/clis/tiktok/explore.yaml +39 -0
  146. package/dist/clis/tiktok/follow.yaml +39 -0
  147. package/dist/clis/tiktok/following.yaml +46 -0
  148. package/dist/clis/tiktok/friends.yaml +47 -0
  149. package/dist/clis/tiktok/like.yaml +38 -0
  150. package/dist/clis/tiktok/live.yaml +51 -0
  151. package/dist/clis/tiktok/notifications.yaml +52 -0
  152. package/dist/clis/tiktok/profile.yaml +45 -0
  153. package/dist/clis/tiktok/save.yaml +34 -0
  154. package/dist/clis/tiktok/search.yaml +46 -0
  155. package/dist/clis/tiktok/unfollow.yaml +44 -0
  156. package/dist/clis/tiktok/unlike.yaml +38 -0
  157. package/dist/clis/tiktok/unsave.yaml +36 -0
  158. package/dist/clis/tiktok/user.yaml +44 -0
  159. package/dist/clis/twitter/download.d.ts +1 -1
  160. package/dist/clis/twitter/download.js +3 -3
  161. package/dist/clis/twitter/followers.js +1 -1
  162. package/dist/clis/twitter/following.js +1 -1
  163. package/dist/clis/twitter/thread.js +1 -1
  164. package/dist/clis/twitter/timeline.d.ts +23 -0
  165. package/dist/clis/twitter/timeline.js +42 -14
  166. package/dist/clis/twitter/timeline.test.d.ts +1 -0
  167. package/dist/clis/twitter/timeline.test.js +102 -0
  168. package/dist/clis/wikipedia/random.d.ts +1 -0
  169. package/dist/clis/wikipedia/random.js +19 -0
  170. package/dist/clis/wikipedia/search.js +3 -3
  171. package/dist/clis/wikipedia/summary.js +4 -9
  172. package/dist/clis/wikipedia/trending.d.ts +1 -0
  173. package/dist/clis/wikipedia/trending.js +35 -0
  174. package/dist/clis/wikipedia/utils.d.ts +28 -0
  175. package/dist/clis/wikipedia/utils.js +13 -0
  176. package/dist/clis/xiaohongshu/creator-note-detail.js +1 -1
  177. package/dist/clis/xiaohongshu/creator-note-detail.test.js +2 -0
  178. package/dist/clis/xiaohongshu/creator-notes.test.js +2 -0
  179. package/dist/clis/xiaohongshu/download.js +1 -1
  180. package/dist/clis/xueqiu/earnings-date.yaml +69 -0
  181. package/dist/clis/xueqiu/search.yaml +2 -1
  182. package/dist/clis/xueqiu/stock.yaml +2 -0
  183. package/dist/clis/yahoo-finance/quote.js +1 -1
  184. package/dist/commanderAdapter.js +13 -7
  185. package/dist/discovery.d.ts +8 -0
  186. package/dist/discovery.js +105 -19
  187. package/dist/doctor.js +3 -1
  188. package/dist/doctor.test.js +46 -2
  189. package/dist/engine.test.d.ts +0 -3
  190. package/dist/engine.test.js +74 -6
  191. package/dist/execution.d.ts +4 -2
  192. package/dist/execution.js +31 -7
  193. package/dist/explore.d.ts +76 -3
  194. package/dist/explore.js +11 -4
  195. package/dist/generate.d.ts +41 -2
  196. package/dist/generate.js +5 -4
  197. package/dist/main.js +2 -1
  198. package/dist/pipeline/executor.d.ts +2 -2
  199. package/dist/pipeline/executor.js +2 -2
  200. package/dist/pipeline/executor.test.js +33 -6
  201. package/dist/pipeline/registry.d.ts +1 -1
  202. package/dist/pipeline/steps/browser.d.ts +7 -7
  203. package/dist/pipeline/steps/browser.js +15 -7
  204. package/dist/pipeline/steps/fetch.d.ts +1 -1
  205. package/dist/pipeline/steps/fetch.js +11 -7
  206. package/dist/pipeline/steps/transform.d.ts +6 -5
  207. package/dist/pipeline/steps/transform.js +30 -9
  208. package/dist/pipeline/template.d.ts +6 -6
  209. package/dist/pipeline/template.js +43 -5
  210. package/dist/pipeline/template.test.js +18 -0
  211. package/dist/pipeline/transform.test.js +11 -0
  212. package/dist/plugin.d.ts +31 -0
  213. package/dist/plugin.js +216 -0
  214. package/dist/plugin.test.d.ts +4 -0
  215. package/dist/plugin.test.js +76 -0
  216. package/dist/registry-api.d.ts +11 -0
  217. package/dist/registry-api.js +9 -0
  218. package/dist/registry.d.ts +11 -0
  219. package/dist/registry.js +6 -1
  220. package/dist/synthesize.d.ts +94 -4
  221. package/dist/synthesize.js +5 -4
  222. package/dist/types.d.ts +39 -26
  223. package/dist/validate.js +8 -2
  224. package/docs/.vitepress/config.mts +6 -4
  225. package/docs/adapters/browser/barchart.md +6 -5
  226. package/docs/adapters/browser/bilibili.md +9 -0
  227. package/docs/adapters/browser/devto.md +35 -0
  228. package/docs/adapters/browser/douban.md +38 -0
  229. package/docs/adapters/browser/facebook.md +36 -0
  230. package/docs/adapters/browser/google.md +62 -0
  231. package/docs/adapters/browser/grok.md +26 -8
  232. package/docs/adapters/browser/instagram.md +46 -0
  233. package/docs/adapters/browser/lobsters.md +32 -0
  234. package/docs/adapters/browser/medium.md +32 -0
  235. package/docs/adapters/browser/reddit.md +9 -0
  236. package/docs/adapters/browser/sinablog.md +36 -0
  237. package/docs/adapters/browser/substack.md +38 -0
  238. package/docs/adapters/browser/tiktok.md +68 -0
  239. package/docs/adapters/browser/wikipedia.md +11 -2
  240. package/docs/adapters/browser/xueqiu.md +10 -0
  241. package/docs/adapters/browser/yahoo-finance.md +6 -5
  242. package/docs/adapters/desktop/antigravity.md +6 -0
  243. package/docs/adapters/desktop/chatgpt.md +2 -1
  244. package/docs/adapters/desktop/codex.md +5 -1
  245. package/docs/adapters/desktop/cursor.md +4 -0
  246. package/docs/adapters/desktop/discord.md +7 -7
  247. package/docs/adapters/index.md +1 -4
  248. package/docs/guide/getting-started.md +1 -0
  249. package/docs/guide/plugins.md +153 -0
  250. package/docs/zh/guide/plugins.md +107 -0
  251. package/extension/src/background.ts +18 -11
  252. package/package.json +10 -5
  253. package/scripts/clean-dist.cjs +13 -0
  254. package/src/browser/cdp.ts +71 -31
  255. package/src/browser/daemon-client.ts +2 -1
  256. package/src/browser/dom-helpers.ts +38 -7
  257. package/src/browser/dom-snapshot.test.ts +249 -0
  258. package/src/browser/dom-snapshot.ts +770 -0
  259. package/src/browser/index.ts +2 -0
  260. package/src/browser/page.ts +50 -19
  261. package/src/build-manifest.test.ts +70 -2
  262. package/src/build-manifest.ts +94 -26
  263. package/src/cli.ts +71 -2
  264. package/src/clis/barchart/greeks.ts +1 -1
  265. package/src/clis/barchart/options.ts +1 -1
  266. package/src/clis/barchart/quote.ts +1 -1
  267. package/src/clis/bilibili/download.ts +1 -1
  268. package/src/clis/bilibili/following.ts +1 -1
  269. package/src/clis/bilibili/subtitle.ts +1 -1
  270. package/src/clis/bilibili/user-videos.ts +1 -1
  271. package/src/clis/boss/batchgreet.ts +14 -106
  272. package/src/clis/boss/chatlist.ts +12 -26
  273. package/src/clis/boss/chatmsg.ts +16 -40
  274. package/src/clis/boss/common.ts +287 -0
  275. package/src/clis/boss/detail.ts +8 -54
  276. package/src/clis/boss/exchange.ts +15 -89
  277. package/src/clis/boss/greet.ts +23 -160
  278. package/src/clis/boss/invite.ts +36 -133
  279. package/src/clis/boss/joblist.ts +7 -36
  280. package/src/clis/boss/mark.ts +13 -94
  281. package/src/clis/boss/recommend.ts +12 -57
  282. package/src/clis/boss/resume.ts +19 -124
  283. package/src/clis/boss/search.ts +13 -66
  284. package/src/clis/boss/send.ts +21 -161
  285. package/src/clis/boss/stats.ts +19 -74
  286. package/src/clis/coupang/add-to-cart.ts +1 -1
  287. package/src/clis/devto/tag.yaml +34 -0
  288. package/src/clis/devto/top.yaml +29 -0
  289. package/src/clis/devto/user.yaml +33 -0
  290. package/src/clis/douban/book-hot.ts +15 -0
  291. package/src/clis/douban/marks.ts +135 -0
  292. package/src/clis/douban/movie-hot.ts +15 -0
  293. package/src/clis/douban/reviews.ts +127 -0
  294. package/src/clis/douban/search.ts +17 -0
  295. package/src/clis/douban/shared.ts +165 -0
  296. package/src/clis/douban/subject.yaml +76 -0
  297. package/src/clis/douban/top250.yaml +70 -0
  298. package/src/clis/douban/utils.ts +81 -0
  299. package/src/clis/facebook/add-friend.yaml +43 -0
  300. package/src/clis/facebook/events.yaml +44 -0
  301. package/src/clis/facebook/feed.yaml +63 -0
  302. package/src/clis/facebook/friends.yaml +42 -0
  303. package/src/clis/facebook/groups.yaml +50 -0
  304. package/src/clis/facebook/join-group.yaml +44 -0
  305. package/src/clis/facebook/memories.yaml +39 -0
  306. package/src/clis/facebook/notifications.yaml +40 -0
  307. package/src/clis/facebook/profile.yaml +37 -0
  308. package/src/clis/facebook/search.yaml +46 -0
  309. package/src/clis/google/news.ts +66 -0
  310. package/src/clis/google/search.ts +133 -0
  311. package/src/clis/google/suggest.ts +40 -0
  312. package/src/clis/google/trends.ts +44 -0
  313. package/src/clis/google/utils.test.ts +82 -0
  314. package/src/clis/google/utils.ts +24 -0
  315. package/src/clis/grok/ask.test.ts +53 -0
  316. package/src/clis/grok/ask.ts +300 -69
  317. package/src/clis/instagram/comment.yaml +52 -0
  318. package/src/clis/instagram/explore.yaml +43 -0
  319. package/src/clis/instagram/follow.yaml +41 -0
  320. package/src/clis/instagram/followers.yaml +51 -0
  321. package/src/clis/instagram/following.yaml +51 -0
  322. package/src/clis/instagram/like.yaml +46 -0
  323. package/src/clis/instagram/profile.yaml +42 -0
  324. package/src/clis/instagram/save.yaml +46 -0
  325. package/src/clis/instagram/saved.yaml +40 -0
  326. package/src/clis/instagram/search.yaml +43 -0
  327. package/src/clis/instagram/unfollow.yaml +38 -0
  328. package/src/clis/instagram/unlike.yaml +46 -0
  329. package/src/clis/instagram/unsave.yaml +46 -0
  330. package/src/clis/instagram/user.yaml +54 -0
  331. package/src/clis/jike/repost.ts +1 -1
  332. package/src/clis/jimeng/generate.yaml +1 -0
  333. package/src/clis/linux-do/category.yaml +1 -0
  334. package/src/clis/lobsters/active.yaml +29 -0
  335. package/src/clis/lobsters/hot.yaml +29 -0
  336. package/src/clis/lobsters/newest.yaml +29 -0
  337. package/src/clis/lobsters/tag.yaml +34 -0
  338. package/src/clis/medium/feed.ts +16 -0
  339. package/src/clis/medium/search.ts +16 -0
  340. package/src/clis/medium/shared.ts +83 -0
  341. package/src/clis/medium/user.ts +16 -0
  342. package/src/clis/reddit/comment.ts +1 -1
  343. package/src/clis/reddit/read.ts +1 -1
  344. package/src/clis/reddit/save.ts +1 -1
  345. package/src/clis/reddit/subreddit.yaml +1 -0
  346. package/src/clis/reddit/subscribe.ts +1 -1
  347. package/src/clis/reddit/upvote.ts +1 -1
  348. package/src/clis/sinablog/article.ts +15 -0
  349. package/src/clis/sinablog/hot.ts +15 -0
  350. package/src/clis/sinablog/search.ts +56 -0
  351. package/src/clis/sinablog/shared.ts +198 -0
  352. package/src/clis/sinablog/user.ts +16 -0
  353. package/src/clis/substack/feed.ts +16 -0
  354. package/src/clis/substack/publication.ts +16 -0
  355. package/src/clis/substack/search.ts +91 -0
  356. package/src/clis/substack/shared.ts +132 -0
  357. package/src/clis/tiktok/comment.yaml +66 -0
  358. package/src/clis/tiktok/explore.yaml +39 -0
  359. package/src/clis/tiktok/follow.yaml +39 -0
  360. package/src/clis/tiktok/following.yaml +46 -0
  361. package/src/clis/tiktok/friends.yaml +47 -0
  362. package/src/clis/tiktok/like.yaml +38 -0
  363. package/src/clis/tiktok/live.yaml +51 -0
  364. package/src/clis/tiktok/notifications.yaml +52 -0
  365. package/src/clis/tiktok/profile.yaml +45 -0
  366. package/src/clis/tiktok/save.yaml +34 -0
  367. package/src/clis/tiktok/search.yaml +46 -0
  368. package/src/clis/tiktok/unfollow.yaml +44 -0
  369. package/src/clis/tiktok/unlike.yaml +38 -0
  370. package/src/clis/tiktok/unsave.yaml +36 -0
  371. package/src/clis/tiktok/user.yaml +44 -0
  372. package/src/clis/twitter/download.ts +3 -3
  373. package/src/clis/twitter/followers.ts +1 -1
  374. package/src/clis/twitter/following.ts +1 -1
  375. package/src/clis/twitter/thread.ts +1 -1
  376. package/src/clis/twitter/timeline.test.ts +109 -0
  377. package/src/clis/twitter/timeline.ts +59 -19
  378. package/src/clis/wikipedia/random.ts +19 -0
  379. package/src/clis/wikipedia/search.ts +10 -4
  380. package/src/clis/wikipedia/summary.ts +4 -9
  381. package/src/clis/wikipedia/trending.ts +41 -0
  382. package/src/clis/wikipedia/utils.ts +31 -0
  383. package/src/clis/xiaohongshu/creator-note-detail.test.ts +2 -0
  384. package/src/clis/xiaohongshu/creator-note-detail.ts +1 -1
  385. package/src/clis/xiaohongshu/creator-notes.test.ts +2 -0
  386. package/src/clis/xiaohongshu/download.ts +1 -1
  387. package/src/clis/xueqiu/earnings-date.yaml +69 -0
  388. package/src/clis/xueqiu/search.yaml +2 -1
  389. package/src/clis/xueqiu/stock.yaml +2 -0
  390. package/src/clis/yahoo-finance/quote.ts +1 -1
  391. package/src/commanderAdapter.ts +17 -10
  392. package/src/discovery.ts +134 -24
  393. package/src/doctor.test.ts +59 -2
  394. package/src/doctor.ts +4 -2
  395. package/src/engine.test.ts +79 -6
  396. package/src/execution.ts +42 -16
  397. package/src/explore.ts +77 -9
  398. package/src/generate.ts +58 -9
  399. package/src/main.ts +2 -1
  400. package/src/pipeline/executor.test.ts +35 -6
  401. package/src/pipeline/executor.ts +11 -7
  402. package/src/pipeline/registry.ts +3 -3
  403. package/src/pipeline/steps/browser.ts +24 -15
  404. package/src/pipeline/steps/fetch.ts +18 -13
  405. package/src/pipeline/steps/transform.ts +40 -15
  406. package/src/pipeline/template.test.ts +18 -0
  407. package/src/pipeline/template.ts +86 -13
  408. package/src/pipeline/transform.test.ts +15 -2
  409. package/src/plugin.test.ts +86 -0
  410. package/src/plugin.ts +254 -0
  411. package/src/registry-api.ts +12 -0
  412. package/src/registry.ts +19 -1
  413. package/src/synthesize.ts +102 -21
  414. package/src/types.ts +44 -12
  415. package/src/validate.ts +19 -4
  416. package/tests/e2e/browser-public.test.ts +11 -0
  417. package/tests/e2e/public-commands.test.ts +64 -0
  418. package/dist/clis/feishu/new.d.ts +0 -1
  419. package/dist/clis/feishu/new.js +0 -27
  420. package/dist/clis/feishu/read.d.ts +0 -1
  421. package/dist/clis/feishu/read.js +0 -40
  422. package/dist/clis/feishu/search.d.ts +0 -1
  423. package/dist/clis/feishu/search.js +0 -30
  424. package/dist/clis/feishu/send.d.ts +0 -1
  425. package/dist/clis/feishu/send.js +0 -39
  426. package/dist/clis/feishu/status.d.ts +0 -1
  427. package/dist/clis/feishu/status.js +0 -28
  428. package/dist/clis/neteasemusic/like.d.ts +0 -1
  429. package/dist/clis/neteasemusic/like.js +0 -25
  430. package/dist/clis/neteasemusic/lyrics.d.ts +0 -1
  431. package/dist/clis/neteasemusic/lyrics.js +0 -47
  432. package/dist/clis/neteasemusic/next.d.ts +0 -1
  433. package/dist/clis/neteasemusic/next.js +0 -26
  434. package/dist/clis/neteasemusic/play.d.ts +0 -1
  435. package/dist/clis/neteasemusic/play.js +0 -26
  436. package/dist/clis/neteasemusic/playing.d.ts +0 -1
  437. package/dist/clis/neteasemusic/playing.js +0 -59
  438. package/dist/clis/neteasemusic/playlist.d.ts +0 -1
  439. package/dist/clis/neteasemusic/playlist.js +0 -46
  440. package/dist/clis/neteasemusic/prev.d.ts +0 -1
  441. package/dist/clis/neteasemusic/prev.js +0 -25
  442. package/dist/clis/neteasemusic/search.d.ts +0 -1
  443. package/dist/clis/neteasemusic/search.js +0 -52
  444. package/dist/clis/neteasemusic/status.d.ts +0 -1
  445. package/dist/clis/neteasemusic/status.js +0 -16
  446. package/dist/clis/neteasemusic/volume.d.ts +0 -1
  447. package/dist/clis/neteasemusic/volume.js +0 -54
  448. package/dist/clis/wechat/chats.d.ts +0 -1
  449. package/dist/clis/wechat/chats.js +0 -28
  450. package/dist/clis/wechat/contacts.d.ts +0 -1
  451. package/dist/clis/wechat/contacts.js +0 -28
  452. package/dist/clis/wechat/read.d.ts +0 -1
  453. package/dist/clis/wechat/read.js +0 -58
  454. package/dist/clis/wechat/search.d.ts +0 -1
  455. package/dist/clis/wechat/search.js +0 -31
  456. package/dist/clis/wechat/send.d.ts +0 -1
  457. package/dist/clis/wechat/send.js +0 -42
  458. package/dist/clis/wechat/status.d.ts +0 -1
  459. package/dist/clis/wechat/status.js +0 -29
  460. package/dist/pipeline.d.ts +0 -7
  461. package/dist/pipeline.js +0 -7
  462. package/docs/adapters/browser/github.md +0 -26
  463. package/docs/adapters/desktop/feishu.md +0 -20
  464. package/docs/adapters/desktop/neteasemusic.md +0 -31
  465. package/docs/adapters/desktop/wechat.md +0 -28
  466. package/src/clis/antigravity/README.md +0 -5
  467. package/src/clis/antigravity/README.zh-CN.md +0 -51
  468. package/src/clis/chaoxing/README.md +0 -14
  469. package/src/clis/chaoxing/README.zh-CN.md +0 -35
  470. package/src/clis/chatgpt/README.md +0 -5
  471. package/src/clis/chatgpt/README.zh-CN.md +0 -44
  472. package/src/clis/chatwise/README.md +0 -5
  473. package/src/clis/chatwise/README.zh-CN.md +0 -38
  474. package/src/clis/codex/README.md +0 -5
  475. package/src/clis/codex/README.zh-CN.md +0 -33
  476. package/src/clis/cursor/README.md +0 -5
  477. package/src/clis/cursor/README.zh-CN.md +0 -33
  478. package/src/clis/discord-app/README.md +0 -5
  479. package/src/clis/discord-app/README.zh-CN.md +0 -28
  480. package/src/clis/feishu/README.md +0 -5
  481. package/src/clis/feishu/README.zh-CN.md +0 -20
  482. package/src/clis/feishu/new.ts +0 -32
  483. package/src/clis/feishu/read.ts +0 -48
  484. package/src/clis/feishu/search.ts +0 -35
  485. package/src/clis/feishu/send.ts +0 -46
  486. package/src/clis/feishu/status.ts +0 -34
  487. package/src/clis/neteasemusic/README.md +0 -5
  488. package/src/clis/neteasemusic/README.zh-CN.md +0 -31
  489. package/src/clis/neteasemusic/like.ts +0 -28
  490. package/src/clis/neteasemusic/lyrics.ts +0 -53
  491. package/src/clis/neteasemusic/next.ts +0 -30
  492. package/src/clis/neteasemusic/play.ts +0 -30
  493. package/src/clis/neteasemusic/playing.ts +0 -62
  494. package/src/clis/neteasemusic/playlist.ts +0 -51
  495. package/src/clis/neteasemusic/prev.ts +0 -29
  496. package/src/clis/neteasemusic/search.ts +0 -58
  497. package/src/clis/neteasemusic/status.ts +0 -18
  498. package/src/clis/neteasemusic/volume.ts +0 -61
  499. package/src/clis/notion/README.md +0 -5
  500. package/src/clis/notion/README.zh-CN.md +0 -29
  501. package/src/clis/wechat/README.md +0 -5
  502. package/src/clis/wechat/README.zh-CN.md +0 -28
  503. package/src/clis/wechat/chats.ts +0 -33
  504. package/src/clis/wechat/contacts.ts +0 -33
  505. package/src/clis/wechat/read.ts +0 -72
  506. package/src/clis/wechat/search.ts +0 -36
  507. package/src/clis/wechat/send.ts +0 -49
  508. package/src/clis/wechat/status.ts +0 -35
  509. package/src/pipeline.ts +0 -8
@@ -1,33 +0,0 @@
1
- # OpenAI Codex 桌面端适配器 (OpenCLI)
2
-
3
- 利用 CDP 协议,直接从命令行/外部脚本接管和操控 **OpenAI Codex 官方桌面版**。
4
- 因为官方 Codex 是基于 Electron 构建的“多 Agent 协作中心”,通过本适配器,你可以让 AI 自动控制另一个 AI 完成工作,甚至自动截取代码审查的 Diff!
5
-
6
- ## 前置环境准备
7
-
8
- 1. 你必须下载并安装了官方原版的 OpenAI Codex 客户端。
9
- 2. 必须通过命令行挂载 CDP 调试端口启动它:
10
- ```bash
11
- # macOS 启动示例
12
- /Applications/Codex.app/Contents/MacOS/Codex --remote-debugging-port=9222
13
- ```
14
-
15
- ## 配置指南
16
-
17
- 在你要运行命令的终端里导出环境变量:
18
- ```bash
19
- export OPENCLI_CODEX_CDP_ENDPOINT="http://127.0.0.1:9222"
20
- ```
21
-
22
- ## 核心指令
23
-
24
- ### 探查与调试
25
- - `opencli codex status`: 检查是否成功连上内部 Chromium,获取上下文 Title。
26
- - `opencli codex dump`: 强制剥离整个 App 的内部 DOM 树和无障碍视图并保存到 `/tmp`,是编写复杂自动化 RPA 脚本的终极利刃。
27
-
28
- ### 自动化执行
29
- - `opencli codex new`: 模拟按下 `Cmd+N`。建立一个彻底干净、隔离了 Git Worktree 的全线并行 Thread。
30
- - `opencli codex send "要发送的话"`: 强行跨越 Shadow Root 找到对应的富文本编辑器并注入提词。
31
- - *高阶技巧*: 你可以直接发送内置宏!例如 `opencli codex send "/review"` 就能触发本工作流的代码审查,或者 `opencli codex send "$imagegen"` 触发技能。
32
- - `opencli codex read`: 完整抓取并提取整个当前 Thread 里的思考过程和对话日志。
33
- - `opencli codex extract-diff`: 专门用于拦截并提取由 AI 建议的 `+` / `-` 代码 Patch 修改块,直接输出结构化数据!
@@ -1,5 +0,0 @@
1
- # Cursor Adapter
2
-
3
- Control the **Cursor IDE** from the terminal via Chrome DevTools Protocol (CDP).
4
-
5
- 📖 **Full documentation**: [docs/adapters/desktop/cursor](../../../docs/adapters/desktop/cursor.md)
@@ -1,33 +0,0 @@
1
- # Cursor 适配器
2
-
3
- 通过 Chrome DevTools Protocol (CDP) 在终端中控制 **Cursor IDE**。由于 Cursor 基于 Electron(VS Code 分支),OpenCLI 可以驱动其内部 UI,自动化 Composer 交互,操控聊天会话。
4
-
5
- ## 前置条件
6
-
7
- 1. 安装 [Cursor](https://cursor.sh/)。
8
- 2. 通过远程调试端口启动:
9
- ```bash
10
- /Applications/Cursor.app/Contents/MacOS/Cursor --remote-debugging-port=9226
11
- ```
12
-
13
- ## 配置
14
-
15
- ```bash
16
- export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9226"
17
- ```
18
-
19
- ## 命令
20
-
21
- ### 诊断
22
- - `opencli cursor status`:检查 CDP 连接状态。
23
- - `opencli cursor dump`:导出完整 DOM 和 Accessibility 快照到 `/tmp/cursor-dom.html` 和 `/tmp/cursor-snapshot.json`。
24
-
25
- ### 对话操作
26
- - `opencli cursor new`:按 `Cmd+N` 创建新文件/标签。
27
- - `opencli cursor send "消息"`:将文本注入活跃的 Composer/Chat 输入框并提交。
28
- - `opencli cursor read`:提取当前聊天面板的完整对话历史。
29
-
30
- ### AI 功能
31
- - `opencli cursor composer "提示词"`:打开 Composer 面板(`Cmd+I`)并发送提示词进行内联 AI 编辑。
32
- - `opencli cursor model`:获取当前活跃的 AI 模型(如 `claude-4.5-sonnet`)。
33
- - `opencli cursor extract-code`:从当前对话中提取所有代码块。
@@ -1,5 +0,0 @@
1
- # Discord Adapter
2
-
3
- Control the **Discord Desktop App** from the terminal via Chrome DevTools Protocol (CDP).
4
-
5
- 📖 **Full documentation**: [docs/adapters/desktop/discord](../../../docs/adapters/desktop/discord.md)
@@ -1,28 +0,0 @@
1
- # Discord 桌面端适配器
2
-
3
- 通过 Chrome DevTools Protocol (CDP) 在终端中控制 **Discord 桌面应用**。
4
-
5
- ## 前置条件
6
-
7
- 通过远程调试端口启动:
8
- ```bash
9
- /Applications/Discord.app/Contents/MacOS/Discord --remote-debugging-port=9232
10
- ```
11
-
12
- ## 配置
13
-
14
- ```bash
15
- export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9232"
16
- ```
17
-
18
- ## 命令
19
-
20
- | 命令 | 说明 |
21
- |------|------|
22
- | `discord status` | 检查 CDP 连接 |
23
- | `discord send "消息"` | 在当前频道发送消息 |
24
- | `discord read` | 读取最近消息 |
25
- | `discord channels` | 列出当前服务器的频道 |
26
- | `discord servers` | 列出已加入的服务器 |
27
- | `discord search "关键词"` | 搜索消息(Cmd+F) |
28
- | `discord members` | 列出在线成员 |
@@ -1,5 +0,0 @@
1
- # Feishu (飞书/Lark) Adapter
2
-
3
- Control **Feishu/Lark Desktop** from the terminal via AppleScript.
4
-
5
- 📖 **Full documentation**: [docs/adapters/desktop/feishu](../../../docs/adapters/desktop/feishu.md)
@@ -1,20 +0,0 @@
1
- # 飞书 (Lark) 桌面端适配器
2
-
3
- 通过 AppleScript 在终端中控制**飞书桌面端**。
4
-
5
- > **注意:** 飞书使用自研 `Lark Framework`(基于 Chromium 但非 Electron),不支持 CDP。
6
-
7
- ## 前置条件
8
-
9
- 1. 飞书必须正在运行且已登录
10
- 2. Terminal 需要辅助功能权限
11
-
12
- ## 命令
13
-
14
- | 命令 | 说明 |
15
- |------|------|
16
- | `feishu status` | 检查飞书是否在运行 |
17
- | `feishu send "消息"` | 发送消息(粘贴 + 回车) |
18
- | `feishu read` | 读取当前聊天(Cmd+A → Cmd+C) |
19
- | `feishu search "关键词"` | 全局搜索(Cmd+K) |
20
- | `feishu new` | 新建消息/文档(Cmd+N) |
@@ -1,32 +0,0 @@
1
- import { execSync } from 'node:child_process';
2
- import { cli, Strategy } from '../../registry.js';
3
- import type { IPage } from '../../types.js';
4
-
5
- export const newCommand = cli({
6
- site: 'feishu',
7
- name: 'new',
8
- description: 'Create a new message or document in Feishu',
9
- domain: 'localhost',
10
- strategy: Strategy.PUBLIC,
11
- browser: false,
12
- args: [],
13
- columns: ['Status'],
14
- func: async (page: IPage | null) => {
15
- try {
16
- execSync("osascript -e 'tell application \"Lark\" to activate'");
17
- execSync("osascript -e 'delay 0.3'");
18
-
19
- // Cmd+N for new conversation/document
20
- execSync(
21
- "osascript " +
22
- "-e 'tell application \"System Events\"' " +
23
- "-e 'keystroke \"n\" using command down' " +
24
- "-e 'end tell'"
25
- );
26
-
27
- return [{ Status: 'New item dialog opened (Cmd+N)' }];
28
- } catch (err: any) {
29
- return [{ Status: 'Error: ' + err.message }];
30
- }
31
- },
32
- });
@@ -1,48 +0,0 @@
1
- import { execSync, spawnSync } from 'node:child_process';
2
- import { cli, Strategy } from '../../registry.js';
3
- import type { IPage } from '../../types.js';
4
-
5
- export const readCommand = cli({
6
- site: 'feishu',
7
- name: 'read',
8
- description: 'Read the current chat content by selecting all and copying',
9
- domain: 'localhost',
10
- strategy: Strategy.PUBLIC,
11
- browser: false,
12
- args: [],
13
- columns: ['Content'],
14
- func: async (page: IPage | null) => {
15
- try {
16
- let clipBackup = '';
17
- try {
18
- clipBackup = execSync('pbpaste', { encoding: 'utf-8' });
19
- } catch { /* empty */ }
20
-
21
- execSync("osascript -e 'tell application \"Lark\" to activate'");
22
- execSync("osascript -e 'delay 0.3'");
23
-
24
- execSync(
25
- "osascript " +
26
- "-e 'tell application \"System Events\"' " +
27
- "-e 'keystroke \"a\" using command down' " +
28
- "-e 'delay 0.2' " +
29
- "-e 'keystroke \"c\" using command down' " +
30
- "-e 'delay 0.2' " +
31
- "-e 'end tell'"
32
- );
33
-
34
- const content = execSync('pbpaste', { encoding: 'utf-8' }).trim();
35
-
36
- if (clipBackup) {
37
- spawnSync('pbcopy', { input: clipBackup });
38
- }
39
-
40
- // Deselect
41
- execSync("osascript -e 'tell application \"System Events\" to key code 53'");
42
-
43
- return [{ Content: content || '(no content captured)' }];
44
- } catch (err: any) {
45
- return [{ Content: 'Error: ' + err.message }];
46
- }
47
- },
48
- });
@@ -1,35 +0,0 @@
1
- import { execSync } from 'node:child_process';
2
- import { cli, Strategy } from '../../registry.js';
3
- import type { IPage } from '../../types.js';
4
-
5
- export const searchCommand = cli({
6
- site: 'feishu',
7
- name: 'search',
8
- description: 'Open Feishu global search and type a query (Cmd+K)',
9
- domain: 'localhost',
10
- strategy: Strategy.PUBLIC,
11
- browser: false,
12
- args: [{ name: 'query', required: true, positional: true, help: 'Search query' }],
13
- columns: ['Status'],
14
- func: async (page: IPage | null, kwargs: any) => {
15
- const query = kwargs.query as string;
16
- try {
17
- execSync("osascript -e 'tell application \"Lark\" to activate'");
18
- execSync("osascript -e 'delay 0.3'");
19
-
20
- // Feishu uses Cmd+K for global search (similar to Slack/Notion)
21
- execSync(
22
- "osascript " +
23
- "-e 'tell application \"System Events\"' " +
24
- "-e 'keystroke \"k\" using command down' " +
25
- "-e 'delay 0.5' " +
26
- `-e 'keystroke ${JSON.stringify(query)}' ` +
27
- "-e 'end tell'"
28
- );
29
-
30
- return [{ Status: `Searching for: ${query}` }];
31
- } catch (err: any) {
32
- return [{ Status: 'Error: ' + err.message }];
33
- }
34
- },
35
- });
@@ -1,46 +0,0 @@
1
- import { execSync, spawnSync } from 'node:child_process';
2
- import { cli, Strategy } from '../../registry.js';
3
- import type { IPage } from '../../types.js';
4
-
5
- export const sendCommand = cli({
6
- site: 'feishu',
7
- name: 'send',
8
- description: 'Send a message in the active Feishu (Lark) conversation',
9
- domain: 'localhost',
10
- strategy: Strategy.PUBLIC,
11
- browser: false,
12
- args: [{ name: 'text', required: true, positional: true, help: 'Message to send' }],
13
- columns: ['Status'],
14
- func: async (page: IPage | null, kwargs: any) => {
15
- const text = kwargs.text as string;
16
- try {
17
- // Backup clipboard
18
- let clipBackup = '';
19
- try {
20
- clipBackup = execSync('pbpaste', { encoding: 'utf-8' });
21
- } catch { /* empty */ }
22
-
23
- spawnSync('pbcopy', { input: text });
24
-
25
- execSync("osascript -e 'tell application \"Lark\" to activate'");
26
- execSync("osascript -e 'delay 0.5'");
27
-
28
- execSync(
29
- "osascript " +
30
- "-e 'tell application \"System Events\"' " +
31
- "-e 'keystroke \"v\" using command down' " +
32
- "-e 'delay 0.2' " +
33
- "-e 'keystroke return' " +
34
- "-e 'end tell'"
35
- );
36
-
37
- if (clipBackup) {
38
- spawnSync('pbcopy', { input: clipBackup });
39
- }
40
-
41
- return [{ Status: 'Success' }];
42
- } catch (err: any) {
43
- return [{ Status: 'Error: ' + err.message }];
44
- }
45
- },
46
- });
@@ -1,34 +0,0 @@
1
- import { execSync } from 'node:child_process';
2
- import { cli, Strategy } from '../../registry.js';
3
- import type { IPage } from '../../types.js';
4
-
5
- export const statusCommand = cli({
6
- site: 'feishu',
7
- name: 'status',
8
- description: 'Check if Feishu (Lark) Desktop is running on macOS',
9
- domain: 'localhost',
10
- strategy: Strategy.PUBLIC,
11
- browser: false,
12
- args: [],
13
- columns: ['Status', 'Detail'],
14
- func: async (page: IPage | null) => {
15
- try {
16
- const running = execSync("osascript -e 'application \"Lark\" is running'", { encoding: 'utf-8' }).trim();
17
- if (running !== 'true') {
18
- return [{ Status: 'Stopped', Detail: 'Feishu/Lark is not running' }];
19
- }
20
-
21
- const windowCount = execSync(
22
- "osascript -e 'tell application \"System Events\" to count windows of application process \"Lark\"'",
23
- { encoding: 'utf-8' }
24
- ).trim();
25
-
26
- return [{
27
- Status: 'Running',
28
- Detail: `${windowCount} window(s) open`,
29
- }];
30
- } catch (err: any) {
31
- return [{ Status: 'Error', Detail: err.message }];
32
- }
33
- },
34
- });
@@ -1,5 +0,0 @@
1
- # NeteaseMusic (网易云音乐) Adapter
2
-
3
- Control **NeteaseMusic** from the terminal via Chrome DevTools Protocol (CDP/CEF).
4
-
5
- 📖 **Full documentation**: [docs/adapters/desktop/neteasemusic](../../../docs/adapters/desktop/neteasemusic.md)
@@ -1,31 +0,0 @@
1
- # 网易云音乐桌面端适配器
2
-
3
- 通过 Chrome DevTools Protocol (CDP) 在终端中控制 **网易云音乐**。该应用基于 Chromium Embedded Framework (CEF)。
4
-
5
- ## 前置条件
6
-
7
- 通过远程调试端口启动:
8
- ```bash
9
- /Applications/NeteaseMusic.app/Contents/MacOS/NeteaseMusic --remote-debugging-port=9234
10
- ```
11
-
12
- ## 配置
13
-
14
- ```bash
15
- export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9234"
16
- ```
17
-
18
- ## 命令
19
-
20
- | 命令 | 说明 |
21
- |------|------|
22
- | `neteasemusic status` | 检查 CDP 连接 |
23
- | `neteasemusic playing` | 当前播放歌曲信息 |
24
- | `neteasemusic play` | 播放 / 暂停切换 |
25
- | `neteasemusic next` | 下一首 |
26
- | `neteasemusic prev` | 上一首 |
27
- | `neteasemusic search "关键词"` | 搜索歌曲 |
28
- | `neteasemusic playlist` | 显示当前播放列表 |
29
- | `neteasemusic like` | 喜欢 / 取消喜欢 |
30
- | `neteasemusic lyrics` | 获取当前歌词 |
31
- | `neteasemusic volume [0-100]` | 获取或设置音量 |
@@ -1,28 +0,0 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import type { IPage } from '../../types.js';
3
-
4
- export const likeCommand = cli({
5
- site: 'neteasemusic',
6
- name: 'like',
7
- description: 'Like/unlike the currently playing song',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- args: [],
12
- columns: ['Status'],
13
- func: async (page: IPage) => {
14
- const result = await page.evaluate(`
15
- (function() {
16
- // The like/heart button in the player bar
17
- const btn = document.querySelector('.m-playbar .icn-love, .m-playbar [class*="like"], .m-player [class*="love"], [data-action="like"]');
18
- if (!btn) return 'Like button not found';
19
-
20
- const wasLiked = btn.classList.contains('loved') || btn.classList.contains('active') || btn.getAttribute('data-liked') === 'true';
21
- btn.click();
22
- return wasLiked ? 'Unliked' : 'Liked';
23
- })()
24
- `);
25
-
26
- return [{ Status: result }];
27
- },
28
- });
@@ -1,53 +0,0 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import type { IPage } from '../../types.js';
3
-
4
- export const lyricsCommand = cli({
5
- site: 'neteasemusic',
6
- name: 'lyrics',
7
- description: 'Get the lyrics of the currently playing song',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- args: [],
12
- columns: ['Line'],
13
- func: async (page: IPage) => {
14
- // Try to open lyrics panel if not visible
15
- await page.evaluate(`
16
- (function() {
17
- const btn = document.querySelector('.m-playbar .icn-lyric, [class*="lyric-btn"], [data-action="lyric"]');
18
- if (btn) btn.click();
19
- })()
20
- `);
21
-
22
- await page.wait(1);
23
-
24
- const lyrics = await page.evaluate(`
25
- (function() {
26
- // Look for lyrics container
27
- const selectors = [
28
- '.m-lyric p, .m-lyric [class*="line"]',
29
- '[class*="lyric-content"] p',
30
- '.listlyric li',
31
- '[class*="lyric"] [class*="line"]',
32
- '.j-lyric p',
33
- ];
34
-
35
- for (const sel of selectors) {
36
- const nodes = document.querySelectorAll(sel);
37
- if (nodes.length > 0) {
38
- return Array.from(nodes).map(n => (n.textContent || '').trim()).filter(l => l.length > 0);
39
- }
40
- }
41
-
42
- // Fallback: try the body text for any lyrics-like content
43
- return [];
44
- })()
45
- `);
46
-
47
- if (lyrics.length === 0) {
48
- return [{ Line: 'No lyrics found. Try opening the lyrics panel first.' }];
49
- }
50
-
51
- return lyrics.map((line: string) => ({ Line: line }));
52
- },
53
- });
@@ -1,30 +0,0 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import type { IPage } from '../../types.js';
3
-
4
- export const nextCommand = cli({
5
- site: 'neteasemusic',
6
- name: 'next',
7
- description: 'Skip to the next song',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- args: [],
12
- columns: ['Status'],
13
- func: async (page: IPage) => {
14
- const clicked = await page.evaluate(`
15
- (function() {
16
- const btn = document.querySelector('.m-playbar .btnfwd, .m-playbar [class*="next"], .m-player .btn-next, [data-action="next"]');
17
- if (btn) { btn.click(); return true; }
18
- return false;
19
- })()
20
- `);
21
-
22
- if (!clicked) {
23
- // Fallback: Ctrl+Right is common next-track shortcut
24
- await page.pressKey('Control+ArrowRight');
25
- }
26
-
27
- await page.wait(1);
28
- return [{ Status: 'Skipped to next song' }];
29
- },
30
- });
@@ -1,30 +0,0 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import type { IPage } from '../../types.js';
3
-
4
- export const playCommand = cli({
5
- site: 'neteasemusic',
6
- name: 'play',
7
- description: 'Toggle play/pause for the current song',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- args: [],
12
- columns: ['Status'],
13
- func: async (page: IPage) => {
14
- // Click the play/pause button or use Space key
15
- const clicked = await page.evaluate(`
16
- (function() {
17
- const btn = document.querySelector('.m-playbar .btnp, .m-playbar [class*="play"], .m-player .btn-play, [data-action="play"]');
18
- if (btn) { btn.click(); return true; }
19
- return false;
20
- })()
21
- `);
22
-
23
- if (!clicked) {
24
- // Fallback: use Space key which is the universal play/pause shortcut
25
- await page.pressKey('Space');
26
- }
27
-
28
- return [{ Status: 'Play/Pause toggled' }];
29
- },
30
- });
@@ -1,62 +0,0 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import type { IPage } from '../../types.js';
3
-
4
- export const playingCommand = cli({
5
- site: 'neteasemusic',
6
- name: 'playing',
7
- description: 'Get the currently playing song info',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- args: [],
12
- columns: ['Title', 'Artist', 'Album', 'Duration', 'Progress'],
13
- func: async (page: IPage) => {
14
- const info = await page.evaluate(`
15
- (function() {
16
- // NeteaseMusic player bar is at the bottom
17
- const selectors = {
18
- title: '.m-playbar .j-song .name, .m-playbar .song .name, [class*="playing"] .name, .m-player .name',
19
- artist: '.m-playbar .j-song .by, .m-playbar .song .by, [class*="playing"] .artist, .m-player .by',
20
- album: '.m-playbar .j-song .album, [class*="playing"] .album',
21
- time: '.m-playbar .j-dur, .m-playbar .time, .m-player .time',
22
- progress: '.m-playbar .barbg .rng, .m-playbar [role="progressbar"], .m-player [class*="progress"]',
23
- };
24
-
25
- function getText(sel) {
26
- for (const s of sel.split(',')) {
27
- const el = document.querySelector(s.trim());
28
- if (el) return (el.textContent || el.innerText || '').trim();
29
- }
30
- return '';
31
- }
32
-
33
- const title = getText(selectors.title);
34
- const artist = getText(selectors.artist);
35
- const album = getText(selectors.album);
36
- const time = getText(selectors.time);
37
-
38
- // Try to get playback progress from the progress bar width
39
- let progress = '';
40
- const bar = document.querySelector('.m-playbar .barbg .rng, [class*="progress"] [class*="played"]');
41
- if (bar) {
42
- const style = bar.getAttribute('style') || '';
43
- const match = style.match(/width:\\s*(\\d+\\.?\\d*)%/);
44
- if (match) progress = match[1] + '%';
45
- }
46
-
47
- if (!title) {
48
- // Fallback: try document title which often contains "songName - NeteaseMusic"
49
- const docTitle = document.title;
50
- if (docTitle && !docTitle.includes('NeteaseMusic')) {
51
- return { Title: docTitle, Artist: '', Album: '', Duration: '', Progress: '' };
52
- }
53
- return { Title: 'No song playing', Artist: '—', Album: '—', Duration: '—', Progress: '—' };
54
- }
55
-
56
- return { Title: title, Artist: artist, Album: album, Duration: time, Progress: progress };
57
- })()
58
- `);
59
-
60
- return [info];
61
- },
62
- });
@@ -1,51 +0,0 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import type { IPage } from '../../types.js';
3
-
4
- export const playlistCommand = cli({
5
- site: 'neteasemusic',
6
- name: 'playlist',
7
- description: 'Show the current playback queue / playlist',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- args: [],
12
- columns: ['Index', 'Title', 'Artist'],
13
- func: async (page: IPage) => {
14
- // Open the playlist panel (usually a button at the bottom bar)
15
- await page.evaluate(`
16
- (function() {
17
- const btn = document.querySelector('.m-playbar .icn-list, .m-playbar [class*="playlist"], [data-action="playlist"], .m-playbar .btnlist');
18
- if (btn) btn.click();
19
- })()
20
- `);
21
-
22
- await page.wait(1);
23
-
24
- const items = await page.evaluate(`
25
- (function() {
26
- const results = [];
27
- // Playlist panel items
28
- const rows = document.querySelectorAll('.m-playlist li, [class*="playlist-panel"] li, .listlyric li, .j-playlist li');
29
-
30
- rows.forEach((row, i) => {
31
- const nameEl = row.querySelector('.name, [class*="name"], a, span:first-child');
32
- const artistEl = row.querySelector('.by, [class*="artist"], .ar');
33
-
34
- const title = nameEl ? (nameEl.getAttribute('title') || nameEl.textContent || '').trim() : (row.textContent || '').trim();
35
- const artist = artistEl ? (artistEl.textContent || '').trim() : '';
36
-
37
- if (title && title.length > 0) {
38
- results.push({ Index: i + 1, Title: title.substring(0, 80), Artist: artist });
39
- }
40
- });
41
-
42
- return results;
43
- })()
44
- `);
45
-
46
- if (items.length === 0) {
47
- return [{ Index: 0, Title: 'Playlist is empty or panel not open', Artist: '—' }];
48
- }
49
- return items;
50
- },
51
- });
@@ -1,29 +0,0 @@
1
- import { cli, Strategy } from '../../registry.js';
2
- import type { IPage } from '../../types.js';
3
-
4
- export const prevCommand = cli({
5
- site: 'neteasemusic',
6
- name: 'prev',
7
- description: 'Go back to the previous song',
8
- domain: 'localhost',
9
- strategy: Strategy.UI,
10
- browser: true,
11
- args: [],
12
- columns: ['Status'],
13
- func: async (page: IPage) => {
14
- const clicked = await page.evaluate(`
15
- (function() {
16
- const btn = document.querySelector('.m-playbar .btnbak, .m-playbar [class*="prev"], .m-player .btn-prev, [data-action="prev"]');
17
- if (btn) { btn.click(); return true; }
18
- return false;
19
- })()
20
- `);
21
-
22
- if (!clicked) {
23
- await page.pressKey('Control+ArrowLeft');
24
- }
25
-
26
- await page.wait(1);
27
- return [{ Status: 'Went to previous song' }];
28
- },
29
- });