@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
package/CONTRIBUTING.md CHANGED
@@ -40,6 +40,11 @@ strategy: public # public | cookie | header
40
40
  browser: false # true if browser session is needed
41
41
 
42
42
  args:
43
+ query:
44
+ positional: true
45
+ type: str
46
+ required: true
47
+ description: Search keyword
43
48
  limit:
44
49
  type: int
45
50
  default: 20
@@ -76,7 +81,7 @@ cli({
76
81
  domain: 'www.mysite.com',
77
82
  strategy: Strategy.COOKIE,
78
83
  args: [
79
- { name: 'query', required: true, help: 'Search query' },
84
+ { name: 'query', positional: true, required: true, help: 'Search query' },
80
85
  { name: 'limit', type: 'int', default: 10, help: 'Max results' },
81
86
  ],
82
87
  columns: ['title', 'url', 'date'],
@@ -118,6 +123,39 @@ opencli <site> <command> --limit 3 -f json
118
123
  opencli <site> <command> -v
119
124
  ```
120
125
 
126
+ ## Arg Design Convention
127
+
128
+ Use **positional** for the primary, required argument of a command (the "what" — query, symbol, id, url, username). Use **named options** (`--flag`) for secondary/optional configuration (limit, format, sort, page, filters, language, date).
129
+
130
+ **Rule of thumb**: Think about how the user will type the command. `opencli xueqiu stock SH600519` is more natural than `opencli xueqiu stock --symbol SH600519`.
131
+
132
+ | Arg type | Positional? | Examples |
133
+ |----------|-------------|----------|
134
+ | Main target (query, symbol, id, url, username) | ✅ `positional: true` | `search '茅台'`, `stock SH600519`, `download BV1xxx` |
135
+ | Configuration (limit, format, sort, page, type, filters) | ❌ Named `--flag` | `--limit 10`, `--format json`, `--sort hot`, `--location seattle` |
136
+
137
+ Do **not** convert an argument to positional just because it appears first in the file. If the argument is optional, acts like a filter, or selects a mode/configuration, it should usually stay a named option.
138
+
139
+ YAML example:
140
+ ```yaml
141
+ args:
142
+ query:
143
+ positional: true # ← primary arg, user types it directly
144
+ type: str
145
+ required: true
146
+ limit:
147
+ type: int # ← config arg, user types --limit 10
148
+ default: 20
149
+ ```
150
+
151
+ TS example:
152
+ ```typescript
153
+ args: [
154
+ { name: 'query', positional: true, required: true, help: 'Search query' },
155
+ { name: 'limit', type: 'int', default: 10, help: 'Max results' },
156
+ ]
157
+ ```
158
+
121
159
  ## Testing
122
160
 
123
161
  See [TESTING.md](./TESTING.md) for the full guide and exact test locations.
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  [![Node.js Version](https://img.shields.io/node/v/@jackwener/opencli?style=flat-square)](https://nodejs.org)
10
10
  [![License](https://img.shields.io/npm/l/@jackwener/opencli?style=flat-square)](./LICENSE)
11
11
 
12
- A CLI tool that turns **any website** or **Electron app** into a command-line interface — Bilibili, Zhihu, 小红书, Twitter/X, Reddit, YouTube, Antigravity, and [many more](#built-in-commands) — powered by browser session reuse and AI-native discovery.
12
+ A CLI tool that turns **any website**, **Electron app**, or **local CLI tool** into a command-line interface — Bilibili, Zhihu, 小红书, Twitter/X, Reddit, YouTube, Antigravity, `gh`, `docker`, and [many more](#built-in-commands) — powered by browser session reuse and AI-native discovery.
13
13
 
14
14
  **Built for AI Agents**: Simply configure an instruction in your global `AGENT.md` or `.cursorrules` guiding the AI to execute `opencli list` via Bash to discover available tools. Register your favorite local CLIs (`opencli register mycli`), and the AI will automatically learn how to invoke all your tools perfectly!
15
15
 
@@ -25,6 +25,7 @@ Turn ANY Electron application into a CLI tool! Recombine, script, and extend app
25
25
  - [Quick Start](#quick-start)
26
26
  - [Built-in Commands](#built-in-commands)
27
27
  - [Desktop App Adapters](#desktop-app-adapters)
28
+ - [External CLI Hub](#external-cli-hub)
28
29
  - [Download Support](#download-support)
29
30
  - [Output Formats](#output-formats)
30
31
  - [For AI Agents (Developer Guide)](#for-ai-agents-developer-guide)
@@ -127,8 +128,8 @@ Run `opencli list` for the live registry.
127
128
  | **notion** | `status` `search` `read` `new` `write` `sidebar` `favorites` `export` | Desktop |
128
129
  | **discord-app** | `status` `send` `read` `channels` `servers` `search` `members` | Desktop |
129
130
  | **v2ex** | `hot` `latest` `topic` `daily` `me` `notifications` | Public / Browser |
130
- | **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` | Browser |
131
- | **antigravity** | `status` `send` `read` `new` `dump` `extract-code` `model` `watch` | Desktop |
131
+ | **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` `earnings-date` | Browser |
132
+ | **antigravity** | `status` `send` `read` `new` `dump` `extract-code` `model` `watch` `serve` | Desktop |
132
133
  | **chatgpt** | `status` `new` `send` `read` `ask` | Desktop |
133
134
  | **xiaohongshu** | `search` `notifications` `feed` `user` `download` `creator-notes` `creator-note-detail` `creator-notes-summary` `creator-profile` `creator-stats` | Browser |
134
135
  | **apple-podcasts** | `search` `episodes` `top` | Public |
@@ -140,7 +141,7 @@ Run `opencli list` for the live registry.
140
141
  | **bbc** | `news` | Public |
141
142
  | **bloomberg** | `main` `markets` `economics` `industries` `tech` `politics` `businessweek` `opinions` `feeds` `news` | Public / Browser |
142
143
  | **ctrip** | `search` | Browser |
143
- | **github** | `search` | Public |
144
+ | **devto** | `top` `tag` `user` | Public |
144
145
  | **arxiv** | `search` `paper` | Public |
145
146
  | **wikipedia** | `search` `summary` | Public |
146
147
  | **hackernews** | `top` | Public |
@@ -160,6 +161,7 @@ Run `opencli list` for the live registry.
160
161
  | **stackoverflow** | `hot` `search` `bounties` `unanswered` | Public |
161
162
  | **steam** | `top-sellers` | Public |
162
163
  | **weread** | `shelf` `search` `book` `highlights` `notes` `notebooks` `ranking` | Browser |
164
+ | **douban** | `search` `top250` `subject` `marks` `reviews` | Browser |
163
165
 
164
166
  > **Bloomberg note**: The RSS-backed Bloomberg listing commands (`main`, section feeds, `feeds`) work without a browser. `bloomberg news` is for standard Bloomberg story/article pages that your current Chrome session can already access. Audio and some other non-standard pages may fail, and OpenCLI does not bypass Bloomberg paywall or entitlement checks.
165
167
 
@@ -198,9 +200,6 @@ Each desktop adapter has its own detailed documentation with commands reference,
198
200
  | **ChatWise** | Multi-LLM client (GPT-4, Claude, Gemini) | [Doc](./docs/adapters/desktop/chatwise.md) |
199
201
  | **Notion** | Search, read, write Notion pages | [Doc](./docs/adapters/desktop/notion.md) |
200
202
  | **Discord** | Discord Desktop — messages, channels, servers | [Doc](./docs/adapters/desktop/discord.md) |
201
- | **Feishu** | 飞书/Lark Desktop via AppleScript | [Doc](./docs/adapters/desktop/feishu.md) |
202
- | **WeChat** | 微信 Desktop via AppleScript + Accessibility | [Doc](./docs/adapters/desktop/wechat.md) |
203
- | **NeteaseMusic** | 网易云音乐 Desktop via CEF/CDP | [Doc](./docs/adapters/desktop/neteasemusic.md) |
204
203
 
205
204
  ## Download Support
206
205
 
@@ -230,11 +229,11 @@ brew install yt-dlp
230
229
 
231
230
  ```bash
232
231
  # Download images/videos from Xiaohongshu note
233
- opencli xiaohongshu download --note-id abc123 --output ./xhs
232
+ opencli xiaohongshu download abc123 --output ./xhs
234
233
 
235
234
  # Download Bilibili video (requires yt-dlp)
236
- opencli bilibili download --bvid BV1xxx --output ./bilibili
237
- opencli bilibili download --bvid BV1xxx --quality 1080p # Specify quality
235
+ opencli bilibili download BV1xxx --output ./bilibili
236
+ opencli bilibili download BV1xxx --quality 1080p # Specify quality
238
237
 
239
238
  # Download Twitter media from user
240
239
  opencli twitter download elonmusk --limit 20 --output ./twitter
package/README.zh-CN.md CHANGED
@@ -9,7 +9,7 @@
9
9
  [![Node.js Version](https://img.shields.io/node/v/@jackwener/opencli?style=flat-square)](https://nodejs.org)
10
10
  [![License](https://img.shields.io/npm/l/@jackwener/opencli?style=flat-square)](./LICENSE)
11
11
 
12
- OpenCLI 将任何网站或 Electron 应用(如 Antigravity)变成命令行工具 — B站、知乎、小红书、Twitter/X、Reddit、YouTube 等[多种站点与应用](#内置命令) — 复用浏览器登录态,AI 驱动探索。
12
+ OpenCLI 将任何网站、本地 CLI 或 Electron 应用(如 Antigravity)变成命令行工具 — B站、知乎、小红书、Twitter/X、Reddit、YouTube,以及 `gh`、`docker` 等[多种站点与工具](#内置命令) — 复用浏览器登录态,AI 驱动探索。
13
13
 
14
14
  **专为 AI Agent 打造**:只需在全局 `.cursorrules` 或 `AGENT.md` 中配置简单指令,引导 AI 通过 Bash 执行 `opencli list` 来检索可用的 CLI 工具及其用法。随后,将你常用的 CLI 列表整合注册进去(`opencli register mycli`),AI 便能瞬间学会自动调用相应的本地工具!
15
15
 
@@ -27,6 +27,7 @@ CLI all electron!现在支持把所有 electron 应用 CLI 化,从而组合
27
27
  - [快速开始](#快速开始)
28
28
  - [内置命令](#内置命令)
29
29
  - [桌面应用适配器](#桌面应用适配器)
30
+ - [外部 CLI 枢纽](#外部-cli-枢纽)
30
31
  - [下载支持](#下载支持)
31
32
  - [输出格式](#输出格式)
32
33
  - [致 AI Agent(开发者指南)](#致-ai-agent开发者指南)
@@ -42,6 +43,7 @@ CLI all electron!现在支持把所有 electron 应用 CLI 化,从而组合
42
43
  - **CLI All Electron** — 支持把所有 electron 应用(如 Antigravity Ultra)CLI 化,让 AI 控制自己!
43
44
  - **多站点覆盖** — 覆盖 B站、知乎、小红书、Twitter、Reddit,以及多种桌面应用
44
45
  - **零风控** — 复用 Chrome 登录态,无需存储任何凭证
46
+ - **外部 CLI 枢纽** — 统一发现、自动安装、透传执行 `gh`、`docker`、`kubectl` 等本地 CLI
45
47
  - **自修复配置** — `opencli setup` 检查 Browser Bridge 连通性;`opencli doctor` 诊断 daemon、扩展和浏览器连接状态
46
48
  - **AI 原生** — `explore` 自动发现 API,`synthesize` 生成适配器,`cascade` 探测认证策略
47
49
  - **动态加载引擎** — 声明式的 `.yaml` 或者底层定制的 `.ts` 适配器,放入 `clis/` 文件夹即可自动注册生效
@@ -127,8 +129,8 @@ npm install -g @jackwener/opencli@latest
127
129
  | **notion** | `status` `search` `read` `new` `write` `sidebar` `favorites` `export` | 桌面端 |
128
130
  | **discord-app** | `status` `send` `read` `channels` `servers` `search` `members` | 桌面端 |
129
131
  | **v2ex** | `hot` `latest` `topic` `daily` `me` `notifications` | 公开 / 浏览器 |
130
- | **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` | 浏览器 |
131
- | **antigravity** | `status` `send` `read` `new` `dump` `extract-code` `model` `watch` | 桌面端 |
132
+ | **xueqiu** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` `earnings-date` | 浏览器 |
133
+ | **antigravity** | `status` `send` `read` `new` `dump` `extract-code` `model` `watch` `serve` | 桌面端 |
132
134
  | **chatgpt** | `status` `new` `send` `read` `ask` | 桌面端 |
133
135
  | **xiaohongshu** | `search` `notifications` `feed` `user` `download` `creator-notes` `creator-note-detail` `creator-notes-summary` `creator-profile` `creator-stats` | 浏览器 |
134
136
  | **apple-podcasts** | `search` `episodes` `top` | 公开 |
@@ -140,7 +142,7 @@ npm install -g @jackwener/opencli@latest
140
142
  | **bbc** | `news` | 公共 API |
141
143
  | **bloomberg** | `main` `markets` `economics` `industries` `tech` `politics` `businessweek` `opinions` `feeds` `news` | 公共 API / 浏览器 |
142
144
  | **ctrip** | `search` | 浏览器 |
143
- | **github** | `search` | 公共 API |
145
+ | **devto** | `top` `tag` `user` | 公开 |
144
146
  | **arxiv** | `search` `paper` | 公开 |
145
147
  | **wikipedia** | `search` `summary` | 公开 |
146
148
  | **hackernews** | `top` | 公共 API |
@@ -160,25 +162,45 @@ npm install -g @jackwener/opencli@latest
160
162
  | **stackoverflow** | `hot` `search` `bounties` `unanswered` | 公开 |
161
163
  | **steam** | `top-sellers` | 公开 |
162
164
  | **weread** | `shelf` `search` `book` `highlights` `notes` `notebooks` `ranking` | 浏览器 |
165
+ | **douban** | `search` `top250` `subject` `marks` `reviews` | 浏览器 |
163
166
 
164
167
  > **Bloomberg 说明**:Bloomberg 的 RSS 列表命令(`main`、各栏目 feed、`feeds`)无需浏览器即可使用。`bloomberg news` 适用于当前 Chrome 会话本身就能访问的标准 Bloomberg 文章页。音频页和部分非标准页面可能失败,OpenCLI 也不会绕过 Bloomberg 的付费墙、登录或权限校验。
165
168
 
169
+ ### 外部 CLI 枢纽
170
+
171
+ OpenCLI 也可以作为你现有命令行工具的统一入口,负责发现、自动安装和纯透传执行。
172
+
173
+ | 外部 CLI | 描述 | 示例 |
174
+ |----------|------|------|
175
+ | **gh** | GitHub CLI | `opencli gh pr list --limit 5` |
176
+ | **obsidian** | Obsidian 仓库管理 | `opencli obsidian search query="AI"` |
177
+ | **docker** | Docker 命令行工具 | `opencli docker ps` |
178
+ | **kubectl** | Kubernetes CLI | `opencli kubectl get pods` |
179
+ | **readwise** | Readwise / Reader CLI | `opencli readwise login` |
180
+
181
+ **零配置透传**:OpenCLI 会把你的输入原样转发给底层二进制,保留原生 stdout / stderr 行为。
182
+
183
+ **自动安装**:如果你运行 `opencli gh ...` 时系统中还没有 `gh`,OpenCLI 会优先尝试通过系统包管理器安装,然后自动重试命令。
184
+
185
+ **注册自定义本地 CLI**:
186
+
187
+ ```bash
188
+ opencli register mycli
189
+ ```
190
+
166
191
  ### 桌面应用适配器
167
192
 
168
193
  每个桌面适配器都有自己详细的文档说明,包括命令参考、启动配置与使用示例:
169
194
 
170
195
  | 应用 | 描述 | 文档 |
171
196
  |-----|-------------|-----|
172
- | **Cursor** | 控制 Cursor IDE — Composer、对话、代码提取等 | [README](./src/clis/cursor/README.md) |
173
- | **Codex** | 在后台(无头)驱动 OpenAI Codex CLI Agent | [README](./src/clis/codex/README.md) |
174
- | **Antigravity** | 在终端直接控制 Antigravity Ultra | [README](./src/clis/antigravity/README.md) |
175
- | **ChatGPT** | 自动化操作 ChatGPT macOS 桌面客户端 | [README](./src/clis/chatgpt/README.md) |
176
- | **ChatWise** | 多 LLM 客户端(GPT-4、Claude、Gemini) | [README](./src/clis/chatwise/README.md) |
177
- | **Notion** | 搜索、读取、写入 Notion 页面 | [README](./src/clis/notion/README.md) |
178
- | **Discord** | Discord 桌面版 — 消息、频道、服务器 | [README](./src/clis/discord-app/README.md) |
179
- | **Feishu** | 飞书/Lark 桌面版 (AppleScript 驱动) | [README](./src/clis/feishu/README.md) |
180
- | **WeChat** | 微信 Mac 桌面端 (AppleScript + 无障碍接口) | [README](./src/clis/wechat/README.md) |
181
- | **NeteaseMusic** | 网易云音乐 (CEF/CDP 驱动) | [README](./src/clis/neteasemusic/README.md) |
197
+ | **Cursor** | 控制 Cursor IDE — Composer、对话、代码提取等 | [Doc](./docs/adapters/desktop/cursor.md) |
198
+ | **Codex** | 在后台(无头)驱动 OpenAI Codex CLI Agent | [Doc](./docs/adapters/desktop/codex.md) |
199
+ | **Antigravity** | 在终端直接控制 Antigravity Ultra | [Doc](./docs/adapters/desktop/antigravity.md) |
200
+ | **ChatGPT** | 自动化操作 ChatGPT macOS 桌面客户端 | [Doc](./docs/adapters/desktop/chatgpt.md) |
201
+ | **ChatWise** | 多 LLM 客户端(GPT-4、Claude、Gemini) | [Doc](./docs/adapters/desktop/chatwise.md) |
202
+ | **Notion** | 搜索、读取、写入 Notion 页面 | [Doc](./docs/adapters/desktop/notion.md) |
203
+ | **Discord** | Discord 桌面版 — 消息、频道、服务器 | [Doc](./docs/adapters/desktop/discord.md) |
182
204
 
183
205
  ## 下载支持
184
206
 
@@ -208,11 +230,11 @@ brew install yt-dlp
208
230
 
209
231
  ```bash
210
232
  # 下载小红书笔记中的图片/视频
211
- opencli xiaohongshu download --note-id abc123 --output ./xhs
233
+ opencli xiaohongshu download abc123 --output ./xhs
212
234
 
213
235
  # 下载B站视频(需要 yt-dlp)
214
- opencli bilibili download --bvid BV1xxx --output ./bilibili
215
- opencli bilibili download --bvid BV1xxx --quality 1080p # 指定画质
236
+ opencli bilibili download BV1xxx --output ./bilibili
237
+ opencli bilibili download BV1xxx --quality 1080p # 指定画质
216
238
 
217
239
  # 下载 Twitter 用户的媒体
218
240
  opencli twitter download elonmusk --limit 20 --output ./twitter
package/SKILL.md CHANGED
@@ -39,7 +39,7 @@ Browser commands require:
39
39
 
40
40
  > **Note**: You must be logged into the target website in Chrome before running commands. Tabs opened during command execution are auto-closed afterwards.
41
41
 
42
- Public API commands (`hackernews`, `github search`, `v2ex`) need no browser.
42
+ Public API commands (`hackernews`, `v2ex`) need no browser.
43
43
 
44
44
  ## Commands Reference
45
45
 
@@ -83,8 +83,10 @@ opencli xueqiu feed # 我的关注 timeline
83
83
  opencli xueqiu hot --limit 10 # 雪球热榜
84
84
  opencli xueqiu search "特斯拉" # 搜索 (query positional)
85
85
 
86
- # GitHub (public)
87
- opencli github search "cli" # 搜索仓库 (query positional)
86
+ # GitHub (via gh External CLI)
87
+ opencli gh repo list # 列出仓库 (passthrough to gh)
88
+ opencli gh pr list --limit 5 # PR 列表
89
+ opencli gh issue list # Issue 列表
88
90
 
89
91
  # Twitter/X (browser)
90
92
  opencli twitter trending --limit 10 # 热门话题
@@ -176,9 +178,11 @@ opencli antigravity status # 检查 CDP 连接
176
178
  opencli antigravity send "hello" # 发送文本到当前 agent 聊天框
177
179
  opencli antigravity read # 读取整个聊天记录面板
178
180
  opencli antigravity new # 清空聊天、开启新对话
181
+ opencli antigravity dump # 导出 DOM 和快照调试信息
179
182
  opencli antigravity extract-code # 自动抽取 AI 回复中的代码块
180
183
  opencli antigravity model claude # 切换底层模型
181
184
  opencli antigravity watch # 流式监听增量消息
185
+ opencli antigravity serve --port 8082 # 启动 Anthropic 兼容代理
182
186
 
183
187
  # Barchart (browser)
184
188
  opencli barchart quote --symbol AAPL # 股票行情
@@ -218,8 +222,9 @@ opencli weread ranking --limit 10 # 排行榜
218
222
  opencli jimeng generate --prompt "描述" # AI 生图
219
223
  opencli jimeng history --limit 10 # 生成历史
220
224
 
221
- # Grok (Desktop)
222
- opencli grok ask "问题" # 提问 Grok (text positional)
225
+ # Grok (default + explicit web)
226
+ opencli grok ask --prompt "问题" # 提问 Grok(兼容默认路径)
227
+ opencli grok ask --prompt "问题" --web # 显式 grok.com consumer web UI 路径
223
228
 
224
229
  # HuggingFace (public)
225
230
  opencli hf top --limit 10 # 热门模型
@@ -25,13 +25,13 @@ export declare class CDPBridge {
25
25
  }): Promise<IPage>;
26
26
  close(): Promise<void>;
27
27
  /** Send a CDP command with timeout guard (P0 fix #4) */
28
- send(method: string, params?: any, timeoutMs?: number): Promise<any>;
28
+ send(method: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
29
29
  /** Listen for a CDP event */
30
- on(event: string, handler: (params: any) => void): void;
30
+ on(event: string, handler: (params: unknown) => void): void;
31
31
  /** Remove a CDP event listener */
32
- off(event: string, handler: (params: any) => void): void;
32
+ off(event: string, handler: (params: unknown) => void): void;
33
33
  /** Wait for a CDP event to fire (one-shot) */
34
- waitForEvent(event: string, timeoutMs?: number): Promise<any>;
34
+ waitForEvent(event: string, timeoutMs?: number): Promise<unknown>;
35
35
  }
36
36
  declare function selectCDPTarget(targets: CDPTarget[]): CDPTarget | undefined;
37
37
  declare function scoreCDPTarget(target: CDPTarget, preferredPattern?: RegExp): number;
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { WebSocket } from 'ws';
11
11
  import { wrapForEval } from './utils.js';
12
+ import { generateSnapshotJs, scrollToRefJs, getFormStateJs } from './dom-snapshot.js';
12
13
  import { clickJs, typeTextJs, pressKeyJs, waitForTextJs, scrollJs, autoScrollJs, networkRequestsJs, } from './dom-helpers.js';
13
14
  const CDP_SEND_TIMEOUT = 30_000; // 30s per command
14
15
  export class CDPBridge {
@@ -35,7 +36,8 @@ export class CDPBridge {
35
36
  }
36
37
  return new Promise((resolve, reject) => {
37
38
  const ws = new WebSocket(wsUrl);
38
- const timeout = setTimeout(() => reject(new Error('CDP connect timeout')), opts?.timeout ?? 10000);
39
+ const timeoutMs = (opts?.timeout ?? 10) * 1000; // opts.timeout is in seconds
40
+ const timeout = setTimeout(() => reject(new Error('CDP connect timeout')), timeoutMs);
39
41
  ws.on('open', () => {
40
42
  clearTimeout(timeout);
41
43
  this._ws = ws;
@@ -163,14 +165,22 @@ class CDPPage {
163
165
  }
164
166
  async getCookies(opts = {}) {
165
167
  const result = await this.bridge.send('Network.getCookies', opts.url ? { urls: [opts.url] } : {});
166
- const cookies = Array.isArray(result?.cookies) ? result.cookies : [];
167
- return opts.domain
168
- ? cookies.filter((cookie) => typeof cookie.domain === 'string' && cookie.domain.includes(opts.domain))
168
+ const cookies = isRecord(result) && Array.isArray(result.cookies) ? result.cookies : [];
169
+ const domain = opts.domain;
170
+ return domain
171
+ ? cookies.filter((cookie) => isCookie(cookie) && cookie.domain.includes(domain))
169
172
  : cookies;
170
173
  }
171
- async snapshot(_opts) {
172
- // CDP doesn't have a built-in accessibility tree equivalent without additional setup
173
- return '(snapshot not available in CDP mode)';
174
+ async snapshot(opts = {}) {
175
+ const snapshotJs = generateSnapshotJs({
176
+ viewportExpand: opts.viewportExpand ?? 800,
177
+ maxDepth: Math.max(1, Math.min(Number(opts.maxDepth) || 50, 200)),
178
+ interactiveOnly: opts.interactive ?? false,
179
+ maxTextLength: opts.maxTextLength ?? 120,
180
+ includeScrollInfo: true,
181
+ bboxDedup: true,
182
+ });
183
+ return this.evaluate(snapshotJs);
174
184
  }
175
185
  // ── Shared DOM operations (P1 fix #5 — using dom-helpers.ts) ──
176
186
  async click(ref) {
@@ -182,13 +192,20 @@ class CDPPage {
182
192
  async pressKey(key) {
183
193
  await this.evaluate(pressKeyJs(key));
184
194
  }
195
+ async scrollTo(ref) {
196
+ return this.evaluate(scrollToRefJs(ref));
197
+ }
198
+ async getFormState() {
199
+ return (await this.evaluate(getFormStateJs()));
200
+ }
185
201
  async wait(options) {
186
202
  if (typeof options === 'number') {
187
203
  await new Promise(resolve => setTimeout(resolve, options * 1000));
188
204
  return;
189
205
  }
190
- if (options.time) {
191
- await new Promise(resolve => setTimeout(resolve, options.time * 1000));
206
+ if (typeof options.time === 'number') {
207
+ const waitTime = options.time;
208
+ await new Promise(resolve => setTimeout(resolve, waitTime * 1000));
192
209
  return;
193
210
  }
194
211
  if (options.text) {
@@ -211,7 +228,7 @@ class CDPPage {
211
228
  quality: options.format === 'jpeg' ? (options.quality ?? 80) : undefined,
212
229
  captureBeyondViewport: options.fullPage ?? false,
213
230
  });
214
- const base64 = result.data;
231
+ const base64 = isRecord(result) && typeof result.data === 'string' ? result.data : '';
215
232
  if (options.path) {
216
233
  const fs = await import('node:fs');
217
234
  const path = await import('node:path');
@@ -222,7 +239,8 @@ class CDPPage {
222
239
  return base64;
223
240
  }
224
241
  async networkRequests(includeStatic = false) {
225
- return this.evaluate(networkRequestsJs(includeStatic));
242
+ const result = await this.evaluate(networkRequestsJs(includeStatic));
243
+ return Array.isArray(result) ? result : [];
226
244
  }
227
245
  async tabs() {
228
246
  return [];
@@ -249,9 +267,18 @@ class CDPPage {
249
267
  async getInterceptedRequests() {
250
268
  const { generateReadInterceptedJs } = await import('../interceptor.js');
251
269
  const result = await this.evaluate(generateReadInterceptedJs('__opencli_xhr'));
252
- return result || [];
270
+ return Array.isArray(result) ? result : [];
253
271
  }
254
272
  }
273
+ function isRecord(value) {
274
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
275
+ }
276
+ function isCookie(value) {
277
+ return isRecord(value)
278
+ && typeof value.name === 'string'
279
+ && typeof value.value === 'string'
280
+ && typeof value.domain === 'string';
281
+ }
255
282
  // ── CDP target selection (unchanged) ──
256
283
  function selectCDPTarget(targets) {
257
284
  const preferredPattern = compilePreferredPattern(process.env.OPENCLI_CDP_TARGET);
@@ -311,8 +338,6 @@ function scoreCDPTarget(target, preferredPattern) {
311
338
  score += 120;
312
339
  if (title.includes('discord'))
313
340
  score += 120;
314
- if (title.includes('netease'))
315
- score += 120;
316
341
  if (url.includes('antigravity'))
317
342
  score += 100;
318
343
  if (url.includes('codex'))
@@ -325,8 +350,6 @@ function scoreCDPTarget(target, preferredPattern) {
325
350
  score += 100;
326
351
  if (url.includes('discord'))
327
352
  score += 100;
328
- if (url.includes('netease'))
329
- score += 100;
330
353
  return score;
331
354
  }
332
355
  function compilePreferredPattern(raw) {
@@ -36,4 +36,5 @@ export declare function isExtensionConnected(): Promise<boolean>;
36
36
  * Retries up to 3 times with 500ms delay for transient failures.
37
37
  */
38
38
  export declare function sendCommand(action: DaemonCommand['action'], params?: Omit<DaemonCommand, 'id' | 'action'>): Promise<unknown>;
39
- export declare function listSessions(): Promise<any[]>;
39
+ export declare function listSessions(): Promise<BrowserSessionInfo[]>;
40
+ import type { BrowserSessionInfo } from '../types.js';
@@ -10,8 +10,21 @@ export function clickJs(ref) {
10
10
  return `
11
11
  (() => {
12
12
  const ref = ${safeRef};
13
- const el = document.querySelector('[data-ref="' + ref + '"]')
14
- || document.querySelectorAll('a, button, input, [role="button"], [tabindex]')[parseInt(ref, 10) || 0];
13
+ // 1. data-opencli-ref (set by snapshot engine)
14
+ let el = document.querySelector('[data-opencli-ref="' + ref + '"]');
15
+ // 2. data-ref (legacy)
16
+ if (!el) el = document.querySelector('[data-ref="' + ref + '"]');
17
+ // 3. CSS selector
18
+ if (!el && ref.match(/^[a-zA-Z#.\\[]/)) {
19
+ try { el = document.querySelector(ref); } catch {}
20
+ }
21
+ // 4. Numeric index into interactive elements
22
+ if (!el) {
23
+ const idx = parseInt(ref, 10);
24
+ if (!isNaN(idx)) {
25
+ el = document.querySelectorAll('a, button, input, select, textarea, [role="button"], [tabindex]:not([tabindex="-1"])')[idx];
26
+ }
27
+ }
15
28
  if (!el) throw new Error('Element not found: ' + ref);
16
29
  el.scrollIntoView({ behavior: 'instant', block: 'center' });
17
30
  el.click();
@@ -26,13 +39,31 @@ export function typeTextJs(ref, text) {
26
39
  return `
27
40
  (() => {
28
41
  const ref = ${safeRef};
29
- const el = document.querySelector('[data-ref="' + ref + '"]')
30
- || document.querySelectorAll('input, textarea, [contenteditable]')[parseInt(ref, 10) || 0];
42
+ // 1. data-opencli-ref (set by snapshot engine)
43
+ let el = document.querySelector('[data-opencli-ref="' + ref + '"]');
44
+ // 2. data-ref (legacy)
45
+ if (!el) el = document.querySelector('[data-ref="' + ref + '"]');
46
+ // 3. CSS selector
47
+ if (!el && ref.match(/^[a-zA-Z#.\\[]/)) {
48
+ try { el = document.querySelector(ref); } catch {}
49
+ }
50
+ // 4. Numeric index into typeable elements
51
+ if (!el) {
52
+ const idx = parseInt(ref, 10);
53
+ if (!isNaN(idx)) {
54
+ el = document.querySelectorAll('input, textarea, [contenteditable="true"]')[idx];
55
+ }
56
+ }
31
57
  if (!el) throw new Error('Element not found: ' + ref);
32
58
  el.focus();
33
- el.value = ${safeText};
34
- el.dispatchEvent(new Event('input', { bubbles: true }));
35
- el.dispatchEvent(new Event('change', { bubbles: true }));
59
+ if (el.isContentEditable) {
60
+ el.textContent = ${safeText};
61
+ el.dispatchEvent(new Event('input', { bubbles: true }));
62
+ } else {
63
+ el.value = ${safeText};
64
+ el.dispatchEvent(new Event('input', { bubbles: true }));
65
+ el.dispatchEvent(new Event('change', { bubbles: true }));
66
+ }
36
67
  return 'typed';
37
68
  })()
38
69
  `;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * DOM Snapshot Engine — Advanced DOM pruning for LLM consumption.
3
+ *
4
+ * Inspired by browser-use's multi-layer pruning pipeline, adapted for opencli's
5
+ * Chrome Extension + CDP architecture. Runs entirely in-page via Runtime.evaluate.
6
+ *
7
+ * Pipeline:
8
+ * 1. Walk DOM tree, collect visibility + layout + interactivity signals
9
+ * 2. Prune invisible, zero-area, non-content elements
10
+ * 3. SVG & decoration collapse
11
+ * 4. Shadow DOM traversal
12
+ * 5. Same-origin iframe content extraction
13
+ * 6. Bounding-box parent-child dedup (link/button wrapping children)
14
+ * 7. Paint-order occlusion detection (overlay/modal coverage)
15
+ * 8. Attribute whitelist filtering
16
+ * 9. Table-aware serialization (markdown tables)
17
+ * 10. Token-efficient serialization with interactive indices
18
+ * 11. data-ref annotation for click/type targeting
19
+ * 12. Hidden interactive element hints (scroll-to-reveal)
20
+ * 13. Incremental diff (mark new elements with *)
21
+ *
22
+ * Additional tools:
23
+ * - scrollToRefJs(ref) — scroll to a data-opencli-ref element
24
+ * - getFormStateJs() — extract all form fields as structured JSON
25
+ */
26
+ export interface SnapshotOptions {
27
+ /** Extra pixels beyond viewport to include (default 800) */
28
+ viewportExpand?: number;
29
+ /** Maximum DOM depth to traverse (default 50) */
30
+ maxDepth?: number;
31
+ /** Only emit interactive elements and their landmark ancestors */
32
+ interactiveOnly?: boolean;
33
+ /** Maximum text content length per node (default 120) */
34
+ maxTextLength?: number;
35
+ /** Include scroll position info on scrollable containers (default true) */
36
+ includeScrollInfo?: boolean;
37
+ /** Enable bounding-box parent-child dedup (default true) */
38
+ bboxDedup?: boolean;
39
+ /** Traverse Shadow DOM roots (default true) */
40
+ includeShadowDom?: boolean;
41
+ /** Extract same-origin iframe content (default true) */
42
+ includeIframes?: boolean;
43
+ /** Maximum number of iframes to process (default 5) */
44
+ maxIframes?: number;
45
+ /** Enable paint-order occlusion detection (default true) */
46
+ paintOrderCheck?: boolean;
47
+ /** Annotate interactive elements with data-opencli-ref (default true) */
48
+ annotateRefs?: boolean;
49
+ /** Report hidden interactive elements outside viewport (default true) */
50
+ reportHidden?: boolean;
51
+ /** Filter ad/noise elements (default true) */
52
+ filterAds?: boolean;
53
+ /** Serialize tables as markdown (default true) */
54
+ markdownTables?: boolean;
55
+ /** Previous snapshot hash set (JSON array of hashes) for diff marking (default null) */
56
+ previousHashes?: string | null;
57
+ }
58
+ /**
59
+ * Generate JS to scroll to an element identified by data-opencli-ref.
60
+ * Completes the snapshot→action loop: snapshot identifies `[3]<button>`,
61
+ * caller can then `scrollToRef('3')` to bring it into view.
62
+ */
63
+ export declare function scrollToRefJs(ref: string): string;
64
+ /**
65
+ * Generate JS to extract all form field values from the page.
66
+ * Returns structured JSON: { forms: [{ id, action, fields: [{ tag, type, name, value, ... }] }] }
67
+ */
68
+ export declare function getFormStateJs(): string;
69
+ /**
70
+ * Generate JavaScript code that, when evaluated in a page context via CDP
71
+ * Runtime.evaluate, returns a pruned DOM snapshot string optimised for LLMs.
72
+ *
73
+ * The snapshot output format:
74
+ * [42]<button type=submit>Search</button>
75
+ * |scroll|<div> (0.5↑ 3.2↓)
76
+ * *[58]<a href=/r/1>Result 1</a>
77
+ * [59]<a href=/r/2>Result 2</a>
78
+ *
79
+ * - `[id]` — interactive element with backend index for targeting
80
+ * - `*` prefix — newly appeared element (incremental diff)
81
+ * - `|scroll|` — scrollable container with page counts
82
+ * - `|shadow|` — Shadow DOM boundary
83
+ * - `|iframe|` — iframe content
84
+ * - `|table|` — markdown table rendering
85
+ */
86
+ export declare function generateSnapshotJs(opts?: SnapshotOptions): string;