@jackwener/opencli 1.1.1 → 1.2.1

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 (523) hide show
  1. package/.github/workflows/build-extension.yml +3 -3
  2. package/.github/workflows/ci.yml +6 -6
  3. package/.github/workflows/doc-check.yml +3 -3
  4. package/.github/workflows/e2e-headed.yml +2 -2
  5. package/.github/workflows/pkg-pr-new.yml +2 -2
  6. package/.github/workflows/release.yml +3 -3
  7. package/.github/workflows/security.yml +2 -2
  8. package/CONTRIBUTING.md +39 -1
  9. package/README.md +13 -10
  10. package/README.zh-CN.md +43 -17
  11. package/SKILL.md +10 -5
  12. package/dist/browser/cdp.d.ts +4 -4
  13. package/dist/browser/cdp.js +39 -16
  14. package/dist/browser/daemon-client.d.ts +4 -2
  15. package/dist/browser/daemon-client.js +17 -4
  16. package/dist/browser/dom-helpers.js +38 -7
  17. package/dist/browser/dom-snapshot.d.ts +86 -0
  18. package/dist/browser/dom-snapshot.js +729 -0
  19. package/dist/browser/dom-snapshot.test.d.ts +11 -0
  20. package/dist/browser/dom-snapshot.test.js +212 -0
  21. package/dist/browser/index.d.ts +2 -0
  22. package/dist/browser/index.js +1 -0
  23. package/dist/browser/mcp.js +3 -1
  24. package/dist/browser/page.d.ts +14 -24
  25. package/dist/browser/page.js +46 -6
  26. package/dist/build-manifest.d.ts +11 -4
  27. package/dist/build-manifest.js +59 -21
  28. package/dist/build-manifest.test.js +58 -2
  29. package/dist/cli-manifest.json +3856 -1509
  30. package/dist/cli.js +66 -0
  31. package/dist/clis/barchart/greeks.js +1 -1
  32. package/dist/clis/barchart/options.js +1 -1
  33. package/dist/clis/barchart/quote.js +1 -1
  34. package/dist/clis/bilibili/download.js +1 -1
  35. package/dist/clis/bilibili/following.js +1 -1
  36. package/dist/clis/bilibili/subtitle.js +1 -1
  37. package/dist/clis/bilibili/user-videos.js +1 -1
  38. package/dist/clis/boss/batchgreet.js +10 -97
  39. package/dist/clis/boss/chatlist.js +8 -25
  40. package/dist/clis/boss/chatmsg.js +11 -42
  41. package/dist/clis/boss/common.d.ts +92 -0
  42. package/dist/clis/boss/common.js +223 -0
  43. package/dist/clis/boss/detail.js +7 -49
  44. package/dist/clis/boss/exchange.js +13 -79
  45. package/dist/clis/boss/greet.js +18 -145
  46. package/dist/clis/boss/invite.js +26 -121
  47. package/dist/clis/boss/joblist.js +6 -31
  48. package/dist/clis/boss/mark.js +12 -85
  49. package/dist/clis/boss/recommend.js +10 -49
  50. package/dist/clis/boss/resume.js +18 -118
  51. package/dist/clis/boss/search.js +12 -60
  52. package/dist/clis/boss/send.js +17 -151
  53. package/dist/clis/boss/stats.js +18 -69
  54. package/dist/clis/coupang/add-to-cart.js +1 -1
  55. package/dist/clis/devto/tag.yaml +34 -0
  56. package/dist/clis/devto/top.yaml +29 -0
  57. package/dist/clis/devto/user.yaml +33 -0
  58. package/dist/clis/douban/book-hot.d.ts +1 -0
  59. package/dist/clis/douban/book-hot.js +14 -0
  60. package/dist/clis/douban/marks.d.ts +1 -0
  61. package/dist/clis/douban/marks.js +115 -0
  62. package/dist/clis/douban/movie-hot.d.ts +1 -0
  63. package/dist/clis/douban/movie-hot.js +14 -0
  64. package/dist/clis/douban/reviews.d.ts +1 -0
  65. package/dist/clis/douban/reviews.js +106 -0
  66. package/dist/clis/douban/search.d.ts +1 -0
  67. package/dist/clis/douban/search.js +16 -0
  68. package/dist/clis/douban/shared.d.ts +4 -0
  69. package/dist/clis/douban/shared.js +155 -0
  70. package/dist/clis/douban/subject.yaml +76 -0
  71. package/dist/clis/douban/top250.yaml +70 -0
  72. package/dist/clis/douban/utils.d.ts +35 -0
  73. package/dist/clis/douban/utils.js +48 -0
  74. package/dist/clis/facebook/add-friend.yaml +43 -0
  75. package/dist/clis/facebook/events.yaml +44 -0
  76. package/dist/clis/facebook/feed.yaml +63 -0
  77. package/dist/clis/facebook/friends.yaml +42 -0
  78. package/dist/clis/facebook/groups.yaml +50 -0
  79. package/dist/clis/facebook/join-group.yaml +44 -0
  80. package/dist/clis/facebook/memories.yaml +39 -0
  81. package/dist/clis/facebook/notifications.yaml +40 -0
  82. package/dist/clis/facebook/profile.yaml +37 -0
  83. package/dist/clis/facebook/search.yaml +46 -0
  84. package/dist/clis/google/news.d.ts +5 -0
  85. package/dist/clis/google/news.js +58 -0
  86. package/dist/clis/google/search.d.ts +10 -0
  87. package/dist/clis/google/search.js +127 -0
  88. package/dist/clis/google/suggest.d.ts +5 -0
  89. package/dist/clis/google/suggest.js +34 -0
  90. package/dist/clis/google/trends.d.ts +5 -0
  91. package/dist/clis/google/trends.js +38 -0
  92. package/dist/clis/google/utils.d.ts +9 -0
  93. package/dist/clis/google/utils.js +23 -0
  94. package/dist/clis/google/utils.test.d.ts +1 -0
  95. package/dist/clis/google/utils.test.js +75 -0
  96. package/dist/clis/grok/ask.d.ts +14 -0
  97. package/dist/clis/grok/ask.js +257 -65
  98. package/dist/clis/grok/ask.test.d.ts +1 -0
  99. package/dist/clis/grok/ask.test.js +36 -0
  100. package/dist/clis/instagram/comment.yaml +52 -0
  101. package/dist/clis/instagram/explore.yaml +43 -0
  102. package/dist/clis/instagram/follow.yaml +41 -0
  103. package/dist/clis/instagram/followers.yaml +51 -0
  104. package/dist/clis/instagram/following.yaml +51 -0
  105. package/dist/clis/instagram/like.yaml +46 -0
  106. package/dist/clis/instagram/profile.yaml +42 -0
  107. package/dist/clis/instagram/save.yaml +46 -0
  108. package/dist/clis/instagram/saved.yaml +40 -0
  109. package/dist/clis/instagram/search.yaml +43 -0
  110. package/dist/clis/instagram/unfollow.yaml +38 -0
  111. package/dist/clis/instagram/unlike.yaml +46 -0
  112. package/dist/clis/instagram/unsave.yaml +46 -0
  113. package/dist/clis/instagram/user.yaml +54 -0
  114. package/dist/clis/jike/repost.js +1 -1
  115. package/dist/clis/jimeng/generate.yaml +1 -0
  116. package/dist/clis/linux-do/category.yaml +1 -0
  117. package/dist/clis/lobsters/active.yaml +29 -0
  118. package/dist/clis/lobsters/hot.yaml +29 -0
  119. package/dist/clis/lobsters/newest.yaml +29 -0
  120. package/dist/clis/lobsters/tag.yaml +34 -0
  121. package/dist/clis/medium/feed.d.ts +1 -0
  122. package/dist/clis/medium/feed.js +15 -0
  123. package/dist/clis/medium/search.d.ts +1 -0
  124. package/dist/clis/medium/search.js +15 -0
  125. package/dist/clis/medium/shared.d.ts +5 -0
  126. package/dist/clis/medium/shared.js +78 -0
  127. package/dist/clis/medium/user.d.ts +1 -0
  128. package/dist/clis/medium/user.js +15 -0
  129. package/dist/clis/reddit/comment.js +1 -1
  130. package/dist/clis/reddit/read.js +1 -1
  131. package/dist/clis/reddit/save.js +1 -1
  132. package/dist/clis/reddit/subreddit.yaml +1 -0
  133. package/dist/clis/reddit/subscribe.js +1 -1
  134. package/dist/clis/reddit/upvote.js +1 -1
  135. package/dist/clis/sinablog/article.d.ts +1 -0
  136. package/dist/clis/sinablog/article.js +14 -0
  137. package/dist/clis/sinablog/hot.d.ts +1 -0
  138. package/dist/clis/sinablog/hot.js +14 -0
  139. package/dist/clis/sinablog/search.d.ts +1 -0
  140. package/dist/clis/sinablog/search.js +51 -0
  141. package/dist/clis/sinablog/shared.d.ts +7 -0
  142. package/dist/clis/sinablog/shared.js +187 -0
  143. package/dist/clis/sinablog/user.d.ts +1 -0
  144. package/dist/clis/sinablog/user.js +15 -0
  145. package/dist/clis/substack/feed.d.ts +1 -0
  146. package/dist/clis/substack/feed.js +15 -0
  147. package/dist/clis/substack/publication.d.ts +1 -0
  148. package/dist/clis/substack/publication.js +15 -0
  149. package/dist/clis/substack/search.d.ts +1 -0
  150. package/dist/clis/substack/search.js +77 -0
  151. package/dist/clis/substack/shared.d.ts +4 -0
  152. package/dist/clis/substack/shared.js +129 -0
  153. package/dist/clis/tiktok/comment.yaml +66 -0
  154. package/dist/clis/tiktok/explore.yaml +39 -0
  155. package/dist/clis/tiktok/follow.yaml +39 -0
  156. package/dist/clis/tiktok/following.yaml +46 -0
  157. package/dist/clis/tiktok/friends.yaml +47 -0
  158. package/dist/clis/tiktok/like.yaml +38 -0
  159. package/dist/clis/tiktok/live.yaml +51 -0
  160. package/dist/clis/tiktok/notifications.yaml +52 -0
  161. package/dist/clis/tiktok/profile.yaml +45 -0
  162. package/dist/clis/tiktok/save.yaml +34 -0
  163. package/dist/clis/tiktok/search.yaml +46 -0
  164. package/dist/clis/tiktok/unfollow.yaml +44 -0
  165. package/dist/clis/tiktok/unlike.yaml +38 -0
  166. package/dist/clis/tiktok/unsave.yaml +36 -0
  167. package/dist/clis/tiktok/user.yaml +44 -0
  168. package/dist/clis/twitter/download.d.ts +1 -1
  169. package/dist/clis/twitter/download.js +3 -3
  170. package/dist/clis/twitter/followers.js +1 -1
  171. package/dist/clis/twitter/following.js +1 -1
  172. package/dist/clis/twitter/thread.js +1 -1
  173. package/dist/clis/twitter/timeline.d.ts +23 -0
  174. package/dist/clis/twitter/timeline.js +42 -14
  175. package/dist/clis/twitter/timeline.test.d.ts +1 -0
  176. package/dist/clis/twitter/timeline.test.js +102 -0
  177. package/dist/clis/wikipedia/random.d.ts +1 -0
  178. package/dist/clis/wikipedia/random.js +19 -0
  179. package/dist/clis/wikipedia/search.js +3 -3
  180. package/dist/clis/wikipedia/summary.js +4 -9
  181. package/dist/clis/wikipedia/trending.d.ts +1 -0
  182. package/dist/clis/wikipedia/trending.js +35 -0
  183. package/dist/clis/wikipedia/utils.d.ts +28 -0
  184. package/dist/clis/wikipedia/utils.js +13 -0
  185. package/dist/clis/xiaohongshu/creator-note-detail.js +1 -1
  186. package/dist/clis/xiaohongshu/creator-note-detail.test.js +2 -0
  187. package/dist/clis/xiaohongshu/creator-notes.test.js +2 -0
  188. package/dist/clis/xiaohongshu/download.js +1 -1
  189. package/dist/clis/xueqiu/earnings-date.yaml +69 -0
  190. package/dist/clis/xueqiu/search.yaml +2 -1
  191. package/dist/clis/xueqiu/stock.yaml +2 -0
  192. package/dist/clis/yahoo-finance/quote.js +1 -1
  193. package/dist/commanderAdapter.js +13 -7
  194. package/dist/daemon.js +21 -0
  195. package/dist/discovery.d.ts +8 -0
  196. package/dist/discovery.js +105 -19
  197. package/dist/doctor.js +3 -1
  198. package/dist/doctor.test.js +46 -2
  199. package/dist/engine.test.d.ts +0 -3
  200. package/dist/engine.test.js +74 -6
  201. package/dist/execution.d.ts +4 -2
  202. package/dist/execution.js +31 -7
  203. package/dist/explore.d.ts +76 -3
  204. package/dist/explore.js +11 -4
  205. package/dist/generate.d.ts +41 -2
  206. package/dist/generate.js +5 -4
  207. package/dist/main.js +2 -1
  208. package/dist/pipeline/executor.d.ts +4 -2
  209. package/dist/pipeline/executor.js +54 -15
  210. package/dist/pipeline/executor.test.js +33 -6
  211. package/dist/pipeline/registry.d.ts +1 -1
  212. package/dist/pipeline/steps/browser.d.ts +7 -7
  213. package/dist/pipeline/steps/browser.js +15 -7
  214. package/dist/pipeline/steps/fetch.d.ts +1 -1
  215. package/dist/pipeline/steps/fetch.js +11 -7
  216. package/dist/pipeline/steps/transform.d.ts +6 -5
  217. package/dist/pipeline/steps/transform.js +30 -9
  218. package/dist/pipeline/template.d.ts +6 -6
  219. package/dist/pipeline/template.js +43 -5
  220. package/dist/pipeline/template.test.js +18 -0
  221. package/dist/pipeline/transform.test.js +11 -0
  222. package/dist/plugin.d.ts +31 -0
  223. package/dist/plugin.js +216 -0
  224. package/dist/plugin.test.d.ts +4 -0
  225. package/dist/plugin.test.js +76 -0
  226. package/dist/registry-api.d.ts +11 -0
  227. package/dist/registry-api.js +9 -0
  228. package/dist/registry.d.ts +11 -0
  229. package/dist/registry.js +6 -1
  230. package/dist/synthesize.d.ts +94 -4
  231. package/dist/synthesize.js +5 -4
  232. package/dist/types.d.ts +39 -26
  233. package/dist/validate.js +8 -2
  234. package/docs/.vitepress/config.mts +6 -4
  235. package/docs/adapters/browser/barchart.md +6 -5
  236. package/docs/adapters/browser/bilibili.md +9 -0
  237. package/docs/adapters/browser/devto.md +35 -0
  238. package/docs/adapters/browser/douban.md +38 -0
  239. package/docs/adapters/browser/facebook.md +36 -0
  240. package/docs/adapters/browser/google.md +62 -0
  241. package/docs/adapters/browser/grok.md +26 -8
  242. package/docs/adapters/browser/instagram.md +46 -0
  243. package/docs/adapters/browser/lobsters.md +32 -0
  244. package/docs/adapters/browser/medium.md +32 -0
  245. package/docs/adapters/browser/reddit.md +9 -0
  246. package/docs/adapters/browser/sinablog.md +36 -0
  247. package/docs/adapters/browser/substack.md +38 -0
  248. package/docs/adapters/browser/tiktok.md +68 -0
  249. package/docs/adapters/browser/wikipedia.md +11 -2
  250. package/docs/adapters/browser/xueqiu.md +10 -0
  251. package/docs/adapters/browser/yahoo-finance.md +6 -5
  252. package/docs/adapters/desktop/antigravity.md +6 -0
  253. package/docs/adapters/desktop/chatgpt.md +2 -1
  254. package/docs/adapters/desktop/codex.md +5 -1
  255. package/docs/adapters/desktop/cursor.md +4 -0
  256. package/docs/adapters/desktop/discord.md +7 -7
  257. package/docs/adapters/index.md +1 -4
  258. package/docs/guide/getting-started.md +1 -0
  259. package/docs/guide/plugins.md +153 -0
  260. package/docs/zh/guide/plugins.md +107 -0
  261. package/extension/dist/background.js +91 -23
  262. package/extension/src/background.ts +82 -29
  263. package/extension/src/cdp.ts +42 -1
  264. package/package.json +10 -5
  265. package/scripts/clean-dist.cjs +13 -0
  266. package/src/browser/cdp.ts +71 -31
  267. package/src/browser/daemon-client.ts +21 -5
  268. package/src/browser/dom-helpers.ts +38 -7
  269. package/src/browser/dom-snapshot.test.ts +249 -0
  270. package/src/browser/dom-snapshot.ts +770 -0
  271. package/src/browser/index.ts +2 -0
  272. package/src/browser/mcp.ts +3 -1
  273. package/src/browser/page.ts +57 -21
  274. package/src/build-manifest.test.ts +70 -2
  275. package/src/build-manifest.ts +94 -26
  276. package/src/cli.ts +71 -2
  277. package/src/clis/barchart/greeks.ts +1 -1
  278. package/src/clis/barchart/options.ts +1 -1
  279. package/src/clis/barchart/quote.ts +1 -1
  280. package/src/clis/bilibili/download.ts +1 -1
  281. package/src/clis/bilibili/following.ts +1 -1
  282. package/src/clis/bilibili/subtitle.ts +1 -1
  283. package/src/clis/bilibili/user-videos.ts +1 -1
  284. package/src/clis/boss/batchgreet.ts +14 -106
  285. package/src/clis/boss/chatlist.ts +12 -26
  286. package/src/clis/boss/chatmsg.ts +16 -40
  287. package/src/clis/boss/common.ts +287 -0
  288. package/src/clis/boss/detail.ts +8 -54
  289. package/src/clis/boss/exchange.ts +15 -89
  290. package/src/clis/boss/greet.ts +23 -160
  291. package/src/clis/boss/invite.ts +36 -133
  292. package/src/clis/boss/joblist.ts +7 -36
  293. package/src/clis/boss/mark.ts +13 -94
  294. package/src/clis/boss/recommend.ts +12 -57
  295. package/src/clis/boss/resume.ts +19 -124
  296. package/src/clis/boss/search.ts +13 -66
  297. package/src/clis/boss/send.ts +21 -161
  298. package/src/clis/boss/stats.ts +19 -74
  299. package/src/clis/coupang/add-to-cart.ts +1 -1
  300. package/src/clis/devto/tag.yaml +34 -0
  301. package/src/clis/devto/top.yaml +29 -0
  302. package/src/clis/devto/user.yaml +33 -0
  303. package/src/clis/douban/book-hot.ts +15 -0
  304. package/src/clis/douban/marks.ts +135 -0
  305. package/src/clis/douban/movie-hot.ts +15 -0
  306. package/src/clis/douban/reviews.ts +127 -0
  307. package/src/clis/douban/search.ts +17 -0
  308. package/src/clis/douban/shared.ts +165 -0
  309. package/src/clis/douban/subject.yaml +76 -0
  310. package/src/clis/douban/top250.yaml +70 -0
  311. package/src/clis/douban/utils.ts +81 -0
  312. package/src/clis/facebook/add-friend.yaml +43 -0
  313. package/src/clis/facebook/events.yaml +44 -0
  314. package/src/clis/facebook/feed.yaml +63 -0
  315. package/src/clis/facebook/friends.yaml +42 -0
  316. package/src/clis/facebook/groups.yaml +50 -0
  317. package/src/clis/facebook/join-group.yaml +44 -0
  318. package/src/clis/facebook/memories.yaml +39 -0
  319. package/src/clis/facebook/notifications.yaml +40 -0
  320. package/src/clis/facebook/profile.yaml +37 -0
  321. package/src/clis/facebook/search.yaml +46 -0
  322. package/src/clis/google/news.ts +66 -0
  323. package/src/clis/google/search.ts +133 -0
  324. package/src/clis/google/suggest.ts +40 -0
  325. package/src/clis/google/trends.ts +44 -0
  326. package/src/clis/google/utils.test.ts +82 -0
  327. package/src/clis/google/utils.ts +24 -0
  328. package/src/clis/grok/ask.test.ts +53 -0
  329. package/src/clis/grok/ask.ts +300 -69
  330. package/src/clis/instagram/comment.yaml +52 -0
  331. package/src/clis/instagram/explore.yaml +43 -0
  332. package/src/clis/instagram/follow.yaml +41 -0
  333. package/src/clis/instagram/followers.yaml +51 -0
  334. package/src/clis/instagram/following.yaml +51 -0
  335. package/src/clis/instagram/like.yaml +46 -0
  336. package/src/clis/instagram/profile.yaml +42 -0
  337. package/src/clis/instagram/save.yaml +46 -0
  338. package/src/clis/instagram/saved.yaml +40 -0
  339. package/src/clis/instagram/search.yaml +43 -0
  340. package/src/clis/instagram/unfollow.yaml +38 -0
  341. package/src/clis/instagram/unlike.yaml +46 -0
  342. package/src/clis/instagram/unsave.yaml +46 -0
  343. package/src/clis/instagram/user.yaml +54 -0
  344. package/src/clis/jike/repost.ts +1 -1
  345. package/src/clis/jimeng/generate.yaml +1 -0
  346. package/src/clis/linux-do/category.yaml +1 -0
  347. package/src/clis/lobsters/active.yaml +29 -0
  348. package/src/clis/lobsters/hot.yaml +29 -0
  349. package/src/clis/lobsters/newest.yaml +29 -0
  350. package/src/clis/lobsters/tag.yaml +34 -0
  351. package/src/clis/medium/feed.ts +16 -0
  352. package/src/clis/medium/search.ts +16 -0
  353. package/src/clis/medium/shared.ts +83 -0
  354. package/src/clis/medium/user.ts +16 -0
  355. package/src/clis/reddit/comment.ts +1 -1
  356. package/src/clis/reddit/read.ts +1 -1
  357. package/src/clis/reddit/save.ts +1 -1
  358. package/src/clis/reddit/subreddit.yaml +1 -0
  359. package/src/clis/reddit/subscribe.ts +1 -1
  360. package/src/clis/reddit/upvote.ts +1 -1
  361. package/src/clis/sinablog/article.ts +15 -0
  362. package/src/clis/sinablog/hot.ts +15 -0
  363. package/src/clis/sinablog/search.ts +56 -0
  364. package/src/clis/sinablog/shared.ts +198 -0
  365. package/src/clis/sinablog/user.ts +16 -0
  366. package/src/clis/substack/feed.ts +16 -0
  367. package/src/clis/substack/publication.ts +16 -0
  368. package/src/clis/substack/search.ts +91 -0
  369. package/src/clis/substack/shared.ts +132 -0
  370. package/src/clis/tiktok/comment.yaml +66 -0
  371. package/src/clis/tiktok/explore.yaml +39 -0
  372. package/src/clis/tiktok/follow.yaml +39 -0
  373. package/src/clis/tiktok/following.yaml +46 -0
  374. package/src/clis/tiktok/friends.yaml +47 -0
  375. package/src/clis/tiktok/like.yaml +38 -0
  376. package/src/clis/tiktok/live.yaml +51 -0
  377. package/src/clis/tiktok/notifications.yaml +52 -0
  378. package/src/clis/tiktok/profile.yaml +45 -0
  379. package/src/clis/tiktok/save.yaml +34 -0
  380. package/src/clis/tiktok/search.yaml +46 -0
  381. package/src/clis/tiktok/unfollow.yaml +44 -0
  382. package/src/clis/tiktok/unlike.yaml +38 -0
  383. package/src/clis/tiktok/unsave.yaml +36 -0
  384. package/src/clis/tiktok/user.yaml +44 -0
  385. package/src/clis/twitter/download.ts +3 -3
  386. package/src/clis/twitter/followers.ts +1 -1
  387. package/src/clis/twitter/following.ts +1 -1
  388. package/src/clis/twitter/thread.ts +1 -1
  389. package/src/clis/twitter/timeline.test.ts +109 -0
  390. package/src/clis/twitter/timeline.ts +59 -19
  391. package/src/clis/wikipedia/random.ts +19 -0
  392. package/src/clis/wikipedia/search.ts +10 -4
  393. package/src/clis/wikipedia/summary.ts +4 -9
  394. package/src/clis/wikipedia/trending.ts +41 -0
  395. package/src/clis/wikipedia/utils.ts +31 -0
  396. package/src/clis/xiaohongshu/creator-note-detail.test.ts +2 -0
  397. package/src/clis/xiaohongshu/creator-note-detail.ts +1 -1
  398. package/src/clis/xiaohongshu/creator-notes.test.ts +2 -0
  399. package/src/clis/xiaohongshu/download.ts +1 -1
  400. package/src/clis/xueqiu/earnings-date.yaml +69 -0
  401. package/src/clis/xueqiu/search.yaml +2 -1
  402. package/src/clis/xueqiu/stock.yaml +2 -0
  403. package/src/clis/yahoo-finance/quote.ts +1 -1
  404. package/src/commanderAdapter.ts +17 -10
  405. package/src/daemon.ts +23 -0
  406. package/src/discovery.ts +134 -24
  407. package/src/doctor.test.ts +59 -2
  408. package/src/doctor.ts +4 -2
  409. package/src/engine.test.ts +79 -6
  410. package/src/execution.ts +42 -16
  411. package/src/explore.ts +77 -9
  412. package/src/generate.ts +58 -9
  413. package/src/main.ts +2 -1
  414. package/src/pipeline/executor.test.ts +35 -6
  415. package/src/pipeline/executor.ts +68 -19
  416. package/src/pipeline/registry.ts +3 -3
  417. package/src/pipeline/steps/browser.ts +24 -15
  418. package/src/pipeline/steps/fetch.ts +18 -13
  419. package/src/pipeline/steps/transform.ts +40 -15
  420. package/src/pipeline/template.test.ts +18 -0
  421. package/src/pipeline/template.ts +86 -13
  422. package/src/pipeline/transform.test.ts +15 -2
  423. package/src/plugin.test.ts +86 -0
  424. package/src/plugin.ts +254 -0
  425. package/src/registry-api.ts +12 -0
  426. package/src/registry.ts +19 -1
  427. package/src/synthesize.ts +102 -21
  428. package/src/types.ts +44 -12
  429. package/src/validate.ts +19 -4
  430. package/tests/e2e/browser-public.test.ts +11 -0
  431. package/tests/e2e/public-commands.test.ts +64 -0
  432. package/dist/clis/feishu/new.d.ts +0 -1
  433. package/dist/clis/feishu/new.js +0 -27
  434. package/dist/clis/feishu/read.d.ts +0 -1
  435. package/dist/clis/feishu/read.js +0 -40
  436. package/dist/clis/feishu/search.d.ts +0 -1
  437. package/dist/clis/feishu/search.js +0 -30
  438. package/dist/clis/feishu/send.d.ts +0 -1
  439. package/dist/clis/feishu/send.js +0 -39
  440. package/dist/clis/feishu/status.d.ts +0 -1
  441. package/dist/clis/feishu/status.js +0 -28
  442. package/dist/clis/neteasemusic/like.d.ts +0 -1
  443. package/dist/clis/neteasemusic/like.js +0 -25
  444. package/dist/clis/neteasemusic/lyrics.d.ts +0 -1
  445. package/dist/clis/neteasemusic/lyrics.js +0 -47
  446. package/dist/clis/neteasemusic/next.d.ts +0 -1
  447. package/dist/clis/neteasemusic/next.js +0 -26
  448. package/dist/clis/neteasemusic/play.d.ts +0 -1
  449. package/dist/clis/neteasemusic/play.js +0 -26
  450. package/dist/clis/neteasemusic/playing.d.ts +0 -1
  451. package/dist/clis/neteasemusic/playing.js +0 -59
  452. package/dist/clis/neteasemusic/playlist.d.ts +0 -1
  453. package/dist/clis/neteasemusic/playlist.js +0 -46
  454. package/dist/clis/neteasemusic/prev.d.ts +0 -1
  455. package/dist/clis/neteasemusic/prev.js +0 -25
  456. package/dist/clis/neteasemusic/search.d.ts +0 -1
  457. package/dist/clis/neteasemusic/search.js +0 -52
  458. package/dist/clis/neteasemusic/status.d.ts +0 -1
  459. package/dist/clis/neteasemusic/status.js +0 -16
  460. package/dist/clis/neteasemusic/volume.d.ts +0 -1
  461. package/dist/clis/neteasemusic/volume.js +0 -54
  462. package/dist/clis/wechat/chats.d.ts +0 -1
  463. package/dist/clis/wechat/chats.js +0 -28
  464. package/dist/clis/wechat/contacts.d.ts +0 -1
  465. package/dist/clis/wechat/contacts.js +0 -28
  466. package/dist/clis/wechat/read.d.ts +0 -1
  467. package/dist/clis/wechat/read.js +0 -58
  468. package/dist/clis/wechat/search.d.ts +0 -1
  469. package/dist/clis/wechat/search.js +0 -31
  470. package/dist/clis/wechat/send.d.ts +0 -1
  471. package/dist/clis/wechat/send.js +0 -42
  472. package/dist/clis/wechat/status.d.ts +0 -1
  473. package/dist/clis/wechat/status.js +0 -29
  474. package/dist/pipeline.d.ts +0 -7
  475. package/dist/pipeline.js +0 -7
  476. package/docs/adapters/browser/github.md +0 -26
  477. package/docs/adapters/desktop/feishu.md +0 -20
  478. package/docs/adapters/desktop/neteasemusic.md +0 -31
  479. package/docs/adapters/desktop/wechat.md +0 -28
  480. package/src/clis/antigravity/README.md +0 -5
  481. package/src/clis/antigravity/README.zh-CN.md +0 -51
  482. package/src/clis/chaoxing/README.md +0 -14
  483. package/src/clis/chaoxing/README.zh-CN.md +0 -35
  484. package/src/clis/chatgpt/README.md +0 -5
  485. package/src/clis/chatgpt/README.zh-CN.md +0 -44
  486. package/src/clis/chatwise/README.md +0 -5
  487. package/src/clis/chatwise/README.zh-CN.md +0 -38
  488. package/src/clis/codex/README.md +0 -5
  489. package/src/clis/codex/README.zh-CN.md +0 -33
  490. package/src/clis/cursor/README.md +0 -5
  491. package/src/clis/cursor/README.zh-CN.md +0 -33
  492. package/src/clis/discord-app/README.md +0 -5
  493. package/src/clis/discord-app/README.zh-CN.md +0 -28
  494. package/src/clis/feishu/README.md +0 -5
  495. package/src/clis/feishu/README.zh-CN.md +0 -20
  496. package/src/clis/feishu/new.ts +0 -32
  497. package/src/clis/feishu/read.ts +0 -48
  498. package/src/clis/feishu/search.ts +0 -35
  499. package/src/clis/feishu/send.ts +0 -46
  500. package/src/clis/feishu/status.ts +0 -34
  501. package/src/clis/neteasemusic/README.md +0 -5
  502. package/src/clis/neteasemusic/README.zh-CN.md +0 -31
  503. package/src/clis/neteasemusic/like.ts +0 -28
  504. package/src/clis/neteasemusic/lyrics.ts +0 -53
  505. package/src/clis/neteasemusic/next.ts +0 -30
  506. package/src/clis/neteasemusic/play.ts +0 -30
  507. package/src/clis/neteasemusic/playing.ts +0 -62
  508. package/src/clis/neteasemusic/playlist.ts +0 -51
  509. package/src/clis/neteasemusic/prev.ts +0 -29
  510. package/src/clis/neteasemusic/search.ts +0 -58
  511. package/src/clis/neteasemusic/status.ts +0 -18
  512. package/src/clis/neteasemusic/volume.ts +0 -61
  513. package/src/clis/notion/README.md +0 -5
  514. package/src/clis/notion/README.zh-CN.md +0 -29
  515. package/src/clis/wechat/README.md +0 -5
  516. package/src/clis/wechat/README.zh-CN.md +0 -28
  517. package/src/clis/wechat/chats.ts +0 -33
  518. package/src/clis/wechat/contacts.ts +0 -33
  519. package/src/clis/wechat/read.ts +0 -72
  520. package/src/clis/wechat/search.ts +0 -36
  521. package/src/clis/wechat/send.ts +0 -49
  522. package/src/clis/wechat/status.ts +0 -35
  523. package/src/pipeline.ts +0 -8
@@ -0,0 +1,66 @@
1
+ site: tiktok
2
+ name: comment
3
+ description: Comment on a TikTok video
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ url:
8
+ type: str
9
+ required: true
10
+ positional: true
11
+ description: TikTok video URL
12
+ text:
13
+ positional: true
14
+ type: str
15
+ required: true
16
+ description: Comment text
17
+
18
+ pipeline:
19
+ - navigate:
20
+ url: ${{ args.url }}
21
+ settleMs: 6000
22
+
23
+ - evaluate: |
24
+ (async () => {
25
+ const url = ${{ args.url | json }};
26
+ const commentText = ${{ args.text | json }};
27
+ const wait = (ms) => new Promise(r => setTimeout(r, ms));
28
+
29
+ // Click comment icon to expand comment section
30
+ const commentIcon = document.querySelector('[data-e2e="comment-icon"]');
31
+ if (commentIcon) {
32
+ const cBtn = commentIcon.closest('button') || commentIcon.closest('[role="button"]') || commentIcon;
33
+ cBtn.click();
34
+ await wait(3000);
35
+ }
36
+
37
+ // Count existing comments for verification
38
+ const beforeCount = document.querySelectorAll('[data-e2e="comment-level-1"]').length;
39
+
40
+ // Find comment input
41
+ const input = document.querySelector('[data-e2e="comment-input"] [contenteditable="true"]') ||
42
+ document.querySelector('[contenteditable="true"]');
43
+ if (!input) throw new Error('Comment input not found - make sure you are logged in');
44
+
45
+ input.focus();
46
+ document.execCommand('insertText', false, commentText);
47
+ await wait(1000);
48
+
49
+ // Click post button
50
+ const btns = Array.from(document.querySelectorAll('[data-e2e="comment-post"], button'));
51
+ const postBtn = btns.find(function(b) {
52
+ var t = b.textContent.trim();
53
+ return t === 'Post' || t === '发布' || t === '发送';
54
+ });
55
+ if (!postBtn) throw new Error('Post button not found');
56
+ postBtn.click();
57
+ await wait(3000);
58
+
59
+ // Verify comment was posted by checking if comment count increased
60
+ const afterCount = document.querySelectorAll('[data-e2e="comment-level-1"]').length;
61
+ const posted = afterCount > beforeCount;
62
+
63
+ return [{ status: posted ? 'Commented' : 'Comment may have failed', url: url, text: commentText }];
64
+ })()
65
+
66
+ columns: [status, url, text]
@@ -0,0 +1,39 @@
1
+ site: tiktok
2
+ name: explore
3
+ description: Get trending TikTok videos from explore page
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ limit:
8
+ type: int
9
+ default: 20
10
+ description: Number of videos
11
+
12
+ pipeline:
13
+ - navigate:
14
+ url: https://www.tiktok.com/explore
15
+ settleMs: 5000
16
+
17
+ - evaluate: |
18
+ (() => {
19
+ const limit = ${{ args.limit }};
20
+ const links = Array.from(document.querySelectorAll('a[href*="/video/"]'));
21
+ const seen = new Set();
22
+ const results = [];
23
+ for (const a of links) {
24
+ const href = a.href;
25
+ if (seen.has(href)) continue;
26
+ seen.add(href);
27
+ const match = href.match(/@([^/]+)\/video\/(\d+)/);
28
+ results.push({
29
+ rank: results.length + 1,
30
+ author: match ? match[1] : '',
31
+ views: a.textContent.trim() || '-',
32
+ url: href,
33
+ });
34
+ if (results.length >= limit) break;
35
+ }
36
+ return results;
37
+ })()
38
+
39
+ columns: [rank, author, views, url]
@@ -0,0 +1,39 @@
1
+ site: tiktok
2
+ name: follow
3
+ description: Follow a TikTok user
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ username:
8
+ type: str
9
+ required: true
10
+ positional: true
11
+ description: TikTok username (without @)
12
+
13
+ pipeline:
14
+ - navigate:
15
+ url: https://www.tiktok.com/@${{ args.username }}
16
+ settleMs: 6000
17
+
18
+ - evaluate: |
19
+ (async () => {
20
+ const username = ${{ args.username | json }};
21
+ const buttons = Array.from(document.querySelectorAll('button, [role="button"]'));
22
+ const followBtn = buttons.find(function(b) {
23
+ var text = b.textContent.trim();
24
+ return text === 'Follow' || text === '关注';
25
+ });
26
+ if (!followBtn) {
27
+ var isFollowing = buttons.some(function(b) {
28
+ var t = b.textContent.trim();
29
+ return t === 'Following' || t === '已关注' || t === 'Friends' || t === '互关';
30
+ });
31
+ if (isFollowing) return [{ status: 'Already following', username: username }];
32
+ return [{ status: 'Follow button not found', username: username }];
33
+ }
34
+ followBtn.click();
35
+ await new Promise(r => setTimeout(r, 2000));
36
+ return [{ status: 'Followed', username: username }];
37
+ })()
38
+
39
+ columns: [status, username]
@@ -0,0 +1,46 @@
1
+ site: tiktok
2
+ name: following
3
+ description: List accounts you follow on TikTok
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ limit:
8
+ type: int
9
+ default: 20
10
+ description: Number of accounts
11
+
12
+ pipeline:
13
+ - navigate:
14
+ url: https://www.tiktok.com/following
15
+ settleMs: 5000
16
+
17
+ - evaluate: |
18
+ (() => {
19
+ const limit = ${{ args.limit }};
20
+ const links = Array.from(document.querySelectorAll('a[href*="/@"]'))
21
+ .filter(function(a) {
22
+ const text = a.textContent.trim();
23
+ return text.length > 1 && text.length < 80 &&
24
+ !text.includes('Profile') && !text.includes('More') && !text.includes('Upload');
25
+ });
26
+
27
+ const seen = {};
28
+ const results = [];
29
+ for (const a of links) {
30
+ const match = a.href.match(/@([^/]+)/);
31
+ const username = match ? match[1] : '';
32
+ if (!username || seen[username]) continue;
33
+ seen[username] = true;
34
+ const raw = a.textContent.trim();
35
+ const name = raw.replace(username, '').replace('@', '').trim();
36
+ results.push({
37
+ index: results.length + 1,
38
+ username: username,
39
+ name: name || username,
40
+ });
41
+ if (results.length >= limit) break;
42
+ }
43
+ return results;
44
+ })()
45
+
46
+ columns: [index, username, name]
@@ -0,0 +1,47 @@
1
+ site: tiktok
2
+ name: friends
3
+ description: Get TikTok friend suggestions
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ limit:
8
+ type: int
9
+ default: 20
10
+ description: Number of suggestions
11
+
12
+ pipeline:
13
+ - navigate:
14
+ url: https://www.tiktok.com/friends
15
+ settleMs: 5000
16
+
17
+ - evaluate: |
18
+ (() => {
19
+ const limit = ${{ args.limit }};
20
+ const links = Array.from(document.querySelectorAll('a[href*="/@"]'))
21
+ .filter(function(a) {
22
+ const text = a.textContent.trim();
23
+ return text.length > 1 && text.length < 80 &&
24
+ !text.includes('Profile') && !text.includes('More') && !text.includes('Upload');
25
+ });
26
+
27
+ const seen = {};
28
+ const results = [];
29
+ for (const a of links) {
30
+ const match = a.href.match(/@([^/]+)/);
31
+ const username = match ? match[1] : '';
32
+ if (!username || seen[username]) continue;
33
+ seen[username] = true;
34
+ const raw = a.textContent.trim();
35
+ const hasFollow = raw.includes('Follow');
36
+ const name = raw.replace('Follow', '').replace(username, '').replace('@', '').trim();
37
+ results.push({
38
+ index: results.length + 1,
39
+ username: username,
40
+ name: name || username,
41
+ });
42
+ if (results.length >= limit) break;
43
+ }
44
+ return results;
45
+ })()
46
+
47
+ columns: [index, username, name]
@@ -0,0 +1,38 @@
1
+ site: tiktok
2
+ name: like
3
+ description: Like a TikTok video
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ url:
8
+ type: str
9
+ required: true
10
+ positional: true
11
+ description: TikTok video URL
12
+
13
+ pipeline:
14
+ - navigate:
15
+ url: ${{ args.url }}
16
+ settleMs: 6000
17
+
18
+ - evaluate: |
19
+ (async () => {
20
+ const url = ${{ args.url | json }};
21
+ const btn = document.querySelector('[data-e2e="like-icon"]');
22
+ if (!btn) throw new Error('Like button not found - make sure you are logged in');
23
+ const container = btn.closest('button') || btn.closest('[role="button"]') || btn;
24
+ const aria = (container.getAttribute('aria-label') || '').toLowerCase();
25
+ const color = window.getComputedStyle(btn).color;
26
+ const isLiked = aria.includes('unlike') || aria.includes('取消点赞') ||
27
+ (color && (color.includes('255, 65') || color.includes('fe2c55')));
28
+ if (isLiked) {
29
+ const count = document.querySelector('[data-e2e="like-count"]');
30
+ return [{ status: 'Already liked', likes: count ? count.textContent.trim() : '-', url: url }];
31
+ }
32
+ container.click();
33
+ await new Promise(r => setTimeout(r, 2000));
34
+ const count = document.querySelector('[data-e2e="like-count"]');
35
+ return [{ status: 'Liked', likes: count ? count.textContent.trim() : '-', url: url }];
36
+ })()
37
+
38
+ columns: [status, likes, url]
@@ -0,0 +1,51 @@
1
+ site: tiktok
2
+ name: live
3
+ description: Browse live streams on TikTok
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ limit:
8
+ type: int
9
+ default: 10
10
+ description: Number of streams
11
+
12
+ pipeline:
13
+ - navigate:
14
+ url: https://www.tiktok.com/live
15
+ settleMs: 5000
16
+
17
+ - evaluate: |
18
+ (() => {
19
+ const limit = ${{ args.limit }};
20
+ // Sidebar live list has structured data
21
+ const items = document.querySelectorAll('[data-e2e="live-side-nav-item"]');
22
+ const sidebar = Array.from(items).slice(0, limit).map(function(el, i) {
23
+ const nameEl = el.querySelector('[data-e2e="live-side-nav-name"]');
24
+ const countEl = el.querySelector('[data-e2e="person-count"]');
25
+ const link = el.querySelector('a');
26
+ return {
27
+ index: i + 1,
28
+ streamer: nameEl ? nameEl.textContent.trim() : '',
29
+ viewers: countEl ? countEl.textContent.trim() : '-',
30
+ url: link ? link.href : '',
31
+ };
32
+ });
33
+
34
+ if (sidebar.length > 0) return sidebar;
35
+
36
+ // Fallback: main content cards
37
+ const cards = document.querySelectorAll('[data-e2e="discover-list-live-card"]');
38
+ return Array.from(cards).slice(0, limit).map(function(card, i) {
39
+ const text = card.textContent.trim().replace(/\s+/g, ' ');
40
+ const link = card.querySelector('a[href*="/live"]');
41
+ const viewerMatch = text.match(/(\d[\d,.]*)\s*watching/);
42
+ return {
43
+ index: i + 1,
44
+ streamer: text.replace(/LIVE.*$/, '').trim().substring(0, 40),
45
+ viewers: viewerMatch ? viewerMatch[1] : '-',
46
+ url: link ? link.href : '',
47
+ };
48
+ });
49
+ })()
50
+
51
+ columns: [index, streamer, viewers, url]
@@ -0,0 +1,52 @@
1
+ site: tiktok
2
+ name: notifications
3
+ description: Get TikTok notifications (likes, comments, mentions, followers)
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ limit:
8
+ type: int
9
+ default: 15
10
+ description: Number of notifications
11
+ type:
12
+ type: str
13
+ default: all
14
+ description: Notification type
15
+ choices: [all, likes, comments, mentions, followers]
16
+
17
+ pipeline:
18
+ - navigate:
19
+ url: https://www.tiktok.com/following
20
+ settleMs: 5000
21
+
22
+ - evaluate: |
23
+ (async () => {
24
+ const limit = ${{ args.limit }};
25
+ const type = ${{ args.type | json }};
26
+ const wait = (ms) => new Promise(r => setTimeout(r, ms));
27
+
28
+ // Click inbox icon to open notifications panel
29
+ const inboxIcon = document.querySelector('[data-e2e="inbox-icon"]');
30
+ if (inboxIcon) inboxIcon.click();
31
+ await wait(1500);
32
+
33
+ // Click specific tab if needed
34
+ if (type !== 'all') {
35
+ const tab = document.querySelector('[data-e2e="' + type + '"]');
36
+ if (tab) {
37
+ tab.click();
38
+ await wait(1500);
39
+ }
40
+ }
41
+
42
+ const items = document.querySelectorAll('[data-e2e="inbox-list"] > div, [data-e2e="inbox-list"] [role="button"]');
43
+ return Array.from(items)
44
+ .filter(el => el.textContent.trim().length > 5)
45
+ .slice(0, limit)
46
+ .map((el, i) => ({
47
+ index: i + 1,
48
+ text: el.textContent.trim().replace(/\s+/g, ' ').substring(0, 150),
49
+ }));
50
+ })()
51
+
52
+ columns: [index, text]
@@ -0,0 +1,45 @@
1
+ site: tiktok
2
+ name: profile
3
+ description: Get TikTok user profile info
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ username:
8
+ type: str
9
+ required: true
10
+ positional: true
11
+ description: TikTok username (without @)
12
+
13
+ pipeline:
14
+ - navigate:
15
+ url: https://www.tiktok.com/explore
16
+ settleMs: 5000
17
+
18
+ - evaluate: |
19
+ (async () => {
20
+ const username = ${{ args.username | json }};
21
+ const res = await fetch('https://www.tiktok.com/@' + encodeURIComponent(username), { credentials: 'include' });
22
+ if (!res.ok) throw new Error('User not found: ' + username);
23
+ const html = await res.text();
24
+ const idx = html.indexOf('__UNIVERSAL_DATA_FOR_REHYDRATION__');
25
+ if (idx === -1) throw new Error('Could not parse profile data');
26
+ const start = html.indexOf('>', idx) + 1;
27
+ const end = html.indexOf('</script>', start);
28
+ const data = JSON.parse(html.substring(start, end));
29
+ const ud = data['__DEFAULT_SCOPE__'] && data['__DEFAULT_SCOPE__']['webapp.user-detail'];
30
+ const u = ud && ud.userInfo && ud.userInfo.user;
31
+ const s = ud && ud.userInfo && ud.userInfo.stats;
32
+ if (!u) throw new Error('User not found: ' + username);
33
+ return [{
34
+ username: u.uniqueId || username,
35
+ name: u.nickname || '',
36
+ bio: (u.signature || '').replace(/\n/g, ' ').substring(0, 120),
37
+ followers: s && s.followerCount || 0,
38
+ following: s && s.followingCount || 0,
39
+ likes: s && s.heartCount || 0,
40
+ videos: s && s.videoCount || 0,
41
+ verified: u.verified ? 'Yes' : 'No',
42
+ }];
43
+ })()
44
+
45
+ columns: [username, name, followers, following, likes, videos, verified, bio]
@@ -0,0 +1,34 @@
1
+ site: tiktok
2
+ name: save
3
+ description: Add a TikTok video to Favorites
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ url:
8
+ type: str
9
+ required: true
10
+ positional: true
11
+ description: TikTok video URL
12
+
13
+ pipeline:
14
+ - navigate:
15
+ url: ${{ args.url }}
16
+ settleMs: 6000
17
+
18
+ - evaluate: |
19
+ (async () => {
20
+ const url = ${{ args.url | json }};
21
+ const btn = document.querySelector('[data-e2e="bookmark-icon"]') ||
22
+ document.querySelector('[data-e2e="collect-icon"]');
23
+ if (!btn) throw new Error('Favorites button not found - make sure you are logged in');
24
+ const container = btn.closest('button') || btn.closest('[role="button"]') || btn;
25
+ const aria = (container.getAttribute('aria-label') || '').toLowerCase();
26
+ if (aria.includes('remove from favorites') || aria.includes('取消收藏')) {
27
+ return [{ status: 'Already in Favorites', url: url }];
28
+ }
29
+ container.click();
30
+ await new Promise(r => setTimeout(r, 2000));
31
+ return [{ status: 'Added to Favorites', url: url }];
32
+ })()
33
+
34
+ columns: [status, url]
@@ -0,0 +1,46 @@
1
+ site: tiktok
2
+ name: search
3
+ description: Search TikTok videos
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ query:
8
+ type: str
9
+ required: true
10
+ positional: true
11
+ description: Search query
12
+ limit:
13
+ type: int
14
+ default: 10
15
+ description: Number of results
16
+
17
+ pipeline:
18
+ - navigate:
19
+ url: https://www.tiktok.com/explore
20
+ settleMs: 5000
21
+
22
+ - evaluate: |
23
+ (async () => {
24
+ const query = ${{ args.query | json }};
25
+ const limit = ${{ args.limit }};
26
+ const res = await fetch('/api/search/general/full/?keyword=' + encodeURIComponent(query) + '&offset=0&count=' + limit + '&aid=1988', { credentials: 'include' });
27
+ if (!res.ok) throw new Error('Search failed: HTTP ' + res.status);
28
+ const data = await res.json();
29
+ const items = (data.data || []).filter(function(i) { return i.type === 1 && i.item; });
30
+ return items.slice(0, limit).map(function(i, idx) {
31
+ var v = i.item;
32
+ var a = v.author || {};
33
+ var s = v.stats || {};
34
+ return {
35
+ rank: idx + 1,
36
+ desc: (v.desc || '').replace(/\n/g, ' ').substring(0, 100),
37
+ author: a.uniqueId || '',
38
+ plays: s.playCount || 0,
39
+ likes: s.diggCount || 0,
40
+ comments: s.commentCount || 0,
41
+ shares: s.shareCount || 0,
42
+ };
43
+ });
44
+ })()
45
+
46
+ columns: [rank, desc, author, plays, likes, comments, shares]
@@ -0,0 +1,44 @@
1
+ site: tiktok
2
+ name: unfollow
3
+ description: Unfollow a TikTok user
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ username:
8
+ type: str
9
+ required: true
10
+ positional: true
11
+ description: TikTok username (without @)
12
+
13
+ pipeline:
14
+ - navigate:
15
+ url: https://www.tiktok.com/@${{ args.username }}
16
+ settleMs: 6000
17
+
18
+ - evaluate: |
19
+ (async () => {
20
+ const username = ${{ args.username | json }};
21
+ const buttons = Array.from(document.querySelectorAll('button, [role="button"]'));
22
+ const followingBtn = buttons.find(function(b) {
23
+ var text = b.textContent.trim();
24
+ return text === 'Following' || text === '已关注' || text === 'Friends' || text === '互关';
25
+ });
26
+ if (!followingBtn) {
27
+ return [{ status: 'Not following this user', username: username }];
28
+ }
29
+ followingBtn.click();
30
+ await new Promise(r => setTimeout(r, 2000));
31
+ // Confirm unfollow if dialog appears
32
+ var allBtns = Array.from(document.querySelectorAll('button'));
33
+ var confirm = allBtns.find(function(b) {
34
+ var t = b.textContent.trim();
35
+ return t === 'Unfollow' || t === '取消关注';
36
+ });
37
+ if (confirm) {
38
+ confirm.click();
39
+ await new Promise(r => setTimeout(r, 1500));
40
+ }
41
+ return [{ status: 'Unfollowed', username: username }];
42
+ })()
43
+
44
+ columns: [status, username]
@@ -0,0 +1,38 @@
1
+ site: tiktok
2
+ name: unlike
3
+ description: Unlike a TikTok video
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ url:
8
+ type: str
9
+ required: true
10
+ positional: true
11
+ description: TikTok video URL
12
+
13
+ pipeline:
14
+ - navigate:
15
+ url: ${{ args.url }}
16
+ settleMs: 6000
17
+
18
+ - evaluate: |
19
+ (async () => {
20
+ const url = ${{ args.url | json }};
21
+ const btn = document.querySelector('[data-e2e="like-icon"]');
22
+ if (!btn) throw new Error('Like button not found - make sure you are logged in');
23
+ const container = btn.closest('button') || btn.closest('[role="button"]') || btn;
24
+ const aria = (container.getAttribute('aria-label') || '').toLowerCase();
25
+ const color = window.getComputedStyle(btn).color;
26
+ const isLiked = aria.includes('unlike') || aria.includes('取消点赞') ||
27
+ (color && (color.includes('255, 65') || color.includes('fe2c55')));
28
+ if (!isLiked) {
29
+ const count = document.querySelector('[data-e2e="like-count"]');
30
+ return [{ status: 'Not liked', likes: count ? count.textContent.trim() : '-', url: url }];
31
+ }
32
+ container.click();
33
+ await new Promise(r => setTimeout(r, 2000));
34
+ const count = document.querySelector('[data-e2e="like-count"]');
35
+ return [{ status: 'Unliked', likes: count ? count.textContent.trim() : '-', url: url }];
36
+ })()
37
+
38
+ columns: [status, likes, url]
@@ -0,0 +1,36 @@
1
+ site: tiktok
2
+ name: unsave
3
+ description: Remove a TikTok video from Favorites
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ url:
8
+ type: str
9
+ required: true
10
+ positional: true
11
+ description: TikTok video URL
12
+
13
+ pipeline:
14
+ - navigate:
15
+ url: ${{ args.url }}
16
+ settleMs: 6000
17
+
18
+ - evaluate: |
19
+ (async () => {
20
+ const url = ${{ args.url | json }};
21
+ const btn = document.querySelector('[data-e2e="bookmark-icon"]') ||
22
+ document.querySelector('[data-e2e="collect-icon"]');
23
+ if (!btn) throw new Error('Favorites button not found - make sure you are logged in');
24
+ const container = btn.closest('button') || btn.closest('[role="button"]') || btn;
25
+ const aria = (container.getAttribute('aria-label') || '').toLowerCase();
26
+ if (aria.includes('add to favorites') || aria.includes('收藏')) {
27
+ if (!aria.includes('remove') && !aria.includes('取消')) {
28
+ return [{ status: 'Not in Favorites', url: url }];
29
+ }
30
+ }
31
+ container.click();
32
+ await new Promise(r => setTimeout(r, 2000));
33
+ return [{ status: 'Removed from Favorites', url: url }];
34
+ })()
35
+
36
+ columns: [status, url]
@@ -0,0 +1,44 @@
1
+ site: tiktok
2
+ name: user
3
+ description: Get recent videos from a TikTok user
4
+ domain: www.tiktok.com
5
+
6
+ args:
7
+ username:
8
+ type: str
9
+ required: true
10
+ positional: true
11
+ description: TikTok username (without @)
12
+ limit:
13
+ type: int
14
+ default: 10
15
+ description: Number of videos
16
+
17
+ pipeline:
18
+ - navigate:
19
+ url: https://www.tiktok.com/@${{ args.username }}
20
+ settleMs: 6000
21
+
22
+ - evaluate: |
23
+ (() => {
24
+ const limit = ${{ args.limit }};
25
+ const username = ${{ args.username | json }};
26
+ const links = Array.from(document.querySelectorAll('a[href*="/video/"]'));
27
+ const seen = {};
28
+ const results = [];
29
+ for (const a of links) {
30
+ const href = a.href;
31
+ if (seen[href]) continue;
32
+ seen[href] = true;
33
+ results.push({
34
+ index: results.length + 1,
35
+ views: a.textContent.trim() || '-',
36
+ url: href,
37
+ });
38
+ if (results.length >= limit) break;
39
+ }
40
+ if (results.length === 0) throw new Error('No videos found for @' + username);
41
+ return results;
42
+ })()
43
+
44
+ columns: [index, views, url]