@jackwener/opencli 1.7.11 → 1.7.13

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 (1004) hide show
  1. package/README.md +8 -7
  2. package/README.zh-CN.md +11 -9
  3. package/cli-manifest.json +12952 -6208
  4. package/clis/1688/assets.js +1 -0
  5. package/clis/1688/download.js +1 -0
  6. package/clis/1688/item.js +1 -0
  7. package/clis/1688/search.js +2 -1
  8. package/clis/1688/store.js +1 -0
  9. package/clis/1point3acres/digest.js +35 -0
  10. package/clis/1point3acres/forum.js +51 -0
  11. package/clis/1point3acres/forums.js +44 -0
  12. package/clis/1point3acres/hot.js +35 -0
  13. package/clis/1point3acres/latest.js +35 -0
  14. package/clis/1point3acres/notifications.js +64 -0
  15. package/clis/1point3acres/search.js +71 -0
  16. package/clis/1point3acres/thread.js +117 -0
  17. package/clis/1point3acres/user.js +77 -0
  18. package/clis/1point3acres/utils.js +247 -0
  19. package/clis/36kr/article.js +1 -0
  20. package/clis/36kr/hot.js +1 -0
  21. package/clis/36kr/news.js +1 -0
  22. package/clis/36kr/search.js +1 -0
  23. package/clis/51job/company.js +1 -0
  24. package/clis/51job/detail.js +1 -0
  25. package/clis/51job/hot.js +1 -0
  26. package/clis/51job/search.js +1 -0
  27. package/clis/_shared/desktop-commands.js +4 -0
  28. package/clis/aibase/news.js +110 -0
  29. package/clis/aibase/news.test.js +59 -0
  30. package/clis/amazon/bestsellers.js +1 -0
  31. package/clis/amazon/discussion.js +1 -0
  32. package/clis/amazon/discussion.test.js +1 -28
  33. package/clis/amazon/movers-shakers.js +1 -0
  34. package/clis/amazon/new-releases.js +1 -0
  35. package/clis/amazon/offer.js +1 -0
  36. package/clis/amazon/product.js +1 -0
  37. package/clis/amazon/rankings.js +1 -0
  38. package/clis/amazon/search.js +1 -0
  39. package/clis/antigravity/dump.js +1 -0
  40. package/clis/antigravity/extract-code.js +1 -0
  41. package/clis/antigravity/model.js +1 -0
  42. package/clis/antigravity/new.js +1 -0
  43. package/clis/antigravity/read.js +1 -0
  44. package/clis/antigravity/send.js +1 -0
  45. package/clis/antigravity/status.js +1 -0
  46. package/clis/antigravity/watch.js +4 -2
  47. package/clis/apple-podcasts/episodes.js +1 -0
  48. package/clis/apple-podcasts/search.js +1 -0
  49. package/clis/apple-podcasts/top.js +1 -0
  50. package/clis/arxiv/arxiv.test.js +112 -0
  51. package/clis/arxiv/author.js +44 -0
  52. package/clis/arxiv/paper.js +4 -3
  53. package/clis/arxiv/recent.js +33 -0
  54. package/clis/arxiv/search.js +19 -7
  55. package/clis/arxiv/utils.js +68 -5
  56. package/clis/baidu-scholar/search.js +1 -1
  57. package/clis/band/bands.js +1 -0
  58. package/clis/band/mentions.js +1 -0
  59. package/clis/band/post.js +1 -0
  60. package/clis/band/posts.js +1 -0
  61. package/clis/barchart/flow.js +1 -0
  62. package/clis/barchart/greeks.js +1 -0
  63. package/clis/barchart/options.js +1 -0
  64. package/clis/barchart/quote.js +1 -0
  65. package/clis/bbc/news.js +1 -0
  66. package/clis/bbc/topic.js +57 -0
  67. package/clis/bbc/utils.js +79 -0
  68. package/clis/bilibili/comments.js +1 -0
  69. package/clis/bilibili/download.js +1 -0
  70. package/clis/bilibili/dynamic.js +1 -0
  71. package/clis/bilibili/favorite.js +1 -0
  72. package/clis/bilibili/feed.js +2 -0
  73. package/clis/bilibili/following.js +1 -0
  74. package/clis/bilibili/history.js +1 -0
  75. package/clis/bilibili/hot.js +6 -1
  76. package/clis/bilibili/hot.test.js +17 -0
  77. package/clis/bilibili/me.js +1 -1
  78. package/clis/bilibili/ranking.js +1 -0
  79. package/clis/bilibili/search.js +1 -1
  80. package/clis/bilibili/subtitle.js +1 -0
  81. package/clis/bilibili/user-videos.js +1 -0
  82. package/clis/bilibili/video.js +1 -0
  83. package/clis/binance/asks.js +1 -0
  84. package/clis/binance/depth.js +1 -0
  85. package/clis/binance/gainers.js +1 -0
  86. package/clis/binance/klines.js +1 -0
  87. package/clis/binance/losers.js +1 -0
  88. package/clis/binance/pairs.js +1 -0
  89. package/clis/binance/price.js +1 -0
  90. package/clis/binance/prices.js +1 -0
  91. package/clis/binance/ticker.js +1 -0
  92. package/clis/binance/top.js +1 -0
  93. package/clis/binance/trades.js +1 -0
  94. package/clis/bloomberg/businessweek.js +1 -0
  95. package/clis/bloomberg/economics.js +1 -0
  96. package/clis/bloomberg/feeds.js +1 -0
  97. package/clis/bloomberg/industries.js +1 -0
  98. package/clis/bloomberg/main.js +1 -0
  99. package/clis/bloomberg/markets.js +1 -0
  100. package/clis/bloomberg/news.js +1 -0
  101. package/clis/bloomberg/opinions.js +1 -0
  102. package/clis/bloomberg/politics.js +1 -0
  103. package/clis/bloomberg/tech.js +1 -0
  104. package/clis/bluesky/feeds.js +1 -0
  105. package/clis/bluesky/followers.js +1 -0
  106. package/clis/bluesky/following.js +1 -0
  107. package/clis/bluesky/profile.js +1 -0
  108. package/clis/bluesky/search.js +1 -0
  109. package/clis/bluesky/starter-packs.js +1 -0
  110. package/clis/bluesky/thread.js +1 -0
  111. package/clis/bluesky/trending.js +1 -0
  112. package/clis/bluesky/user.js +3 -1
  113. package/clis/boss/batchgreet.js +1 -0
  114. package/clis/boss/chatlist.js +1 -0
  115. package/clis/boss/chatmsg.js +1 -0
  116. package/clis/boss/detail.js +1 -0
  117. package/clis/boss/exchange.js +1 -0
  118. package/clis/boss/greet.js +1 -0
  119. package/clis/boss/invite.js +1 -0
  120. package/clis/boss/joblist.js +1 -0
  121. package/clis/boss/mark.js +1 -0
  122. package/clis/boss/recommend.js +1 -0
  123. package/clis/boss/resume.js +1 -0
  124. package/clis/boss/search.js +1 -0
  125. package/clis/boss/send.js +1 -0
  126. package/clis/boss/stats.js +1 -0
  127. package/clis/chaoxing/assignments.js +2 -1
  128. package/clis/chaoxing/exams.js +2 -1
  129. package/clis/chatgpt/ask.js +57 -0
  130. package/clis/chatgpt/commands.test.js +45 -0
  131. package/clis/chatgpt/detail.js +46 -0
  132. package/clis/chatgpt/history.js +39 -0
  133. package/clis/chatgpt/image.js +13 -11
  134. package/clis/chatgpt/image.test.js +23 -0
  135. package/clis/chatgpt/new.js +25 -0
  136. package/clis/chatgpt/read.js +43 -0
  137. package/clis/chatgpt/send.js +46 -0
  138. package/clis/chatgpt/status.js +29 -0
  139. package/clis/chatgpt/utils.js +294 -4
  140. package/clis/chatgpt/utils.test.js +13 -0
  141. package/clis/chatgpt-app/ask.js +7 -3
  142. package/clis/chatgpt-app/model.js +1 -0
  143. package/clis/chatgpt-app/new.js +1 -0
  144. package/clis/chatgpt-app/read.js +1 -0
  145. package/clis/chatgpt-app/send.js +1 -0
  146. package/clis/chatgpt-app/status.js +1 -0
  147. package/clis/chatwise/ask.js +17 -43
  148. package/clis/chatwise/composer.test.js +186 -0
  149. package/clis/chatwise/export.js +1 -0
  150. package/clis/chatwise/history.js +1 -0
  151. package/clis/chatwise/model.js +1 -0
  152. package/clis/chatwise/read.js +1 -0
  153. package/clis/chatwise/send.js +3 -24
  154. package/clis/chatwise/utils.js +143 -0
  155. package/clis/claude/ask.js +2 -1
  156. package/clis/claude/detail.js +2 -0
  157. package/clis/claude/history.js +2 -0
  158. package/clis/claude/new.js +2 -0
  159. package/clis/claude/read.js +2 -0
  160. package/clis/claude/send.js +2 -0
  161. package/clis/claude/status.js +2 -0
  162. package/clis/cnki/search.js +1 -0
  163. package/clis/codex/ask.js +16 -9
  164. package/clis/codex/export.js +1 -0
  165. package/clis/codex/extract-diff.js +1 -0
  166. package/clis/codex/history.js +17 -33
  167. package/clis/codex/model.js +1 -0
  168. package/clis/codex/projects.js +28 -0
  169. package/clis/codex/read.js +11 -4
  170. package/clis/codex/send.js +11 -3
  171. package/clis/codex/sidebar.js +356 -0
  172. package/clis/codex/sidebar.test.js +329 -0
  173. package/clis/coingecko/categories.js +75 -0
  174. package/clis/coingecko/coin.js +107 -0
  175. package/clis/coingecko/coingecko.test.js +109 -0
  176. package/clis/coingecko/derivatives.js +84 -0
  177. package/clis/coingecko/exchanges.js +74 -0
  178. package/clis/coingecko/global.js +71 -0
  179. package/clis/coingecko/top.js +64 -0
  180. package/clis/coingecko/trending.js +55 -0
  181. package/clis/coupang/add-to-cart.js +22 -13
  182. package/clis/coupang/coupang.test.js +159 -0
  183. package/clis/coupang/product.js +257 -0
  184. package/clis/coupang/search.js +39 -16
  185. package/clis/coupang/utils.js +55 -1
  186. package/clis/crates/crate.js +62 -0
  187. package/clis/crates/search.js +44 -0
  188. package/clis/crates/utils.js +72 -0
  189. package/clis/ctrip/ctrip.test.js +234 -0
  190. package/clis/ctrip/hotel-suggest.js +45 -0
  191. package/clis/ctrip/search.js +23 -68
  192. package/clis/ctrip/utils.js +175 -0
  193. package/clis/cursor/ask.js +7 -3
  194. package/clis/cursor/composer.js +1 -0
  195. package/clis/cursor/export.js +1 -0
  196. package/clis/cursor/extract-code.js +1 -0
  197. package/clis/cursor/history.js +1 -0
  198. package/clis/cursor/model.js +1 -0
  199. package/clis/cursor/read.js +1 -0
  200. package/clis/cursor/send.js +1 -0
  201. package/clis/dblp/author.js +133 -0
  202. package/clis/dblp/dblp.test.js +397 -0
  203. package/clis/dblp/paper.js +40 -0
  204. package/clis/dblp/search.js +45 -0
  205. package/clis/dblp/utils.js +290 -0
  206. package/clis/dblp/venue.js +64 -0
  207. package/clis/deepseek/ask.js +13 -7
  208. package/clis/deepseek/ask.test.js +13 -13
  209. package/clis/deepseek/detail.js +38 -0
  210. package/clis/deepseek/detail.test.js +81 -0
  211. package/clis/deepseek/history.js +2 -0
  212. package/clis/deepseek/new.js +2 -0
  213. package/clis/deepseek/read.js +2 -0
  214. package/clis/deepseek/send.js +140 -0
  215. package/clis/deepseek/send.test.js +107 -0
  216. package/clis/deepseek/status.js +2 -0
  217. package/clis/deepseek/utils.js +66 -0
  218. package/clis/deepseek/utils.test.js +107 -1
  219. package/clis/defillama/defillama.test.js +99 -0
  220. package/clis/defillama/protocol.js +84 -0
  221. package/clis/defillama/protocols.js +55 -0
  222. package/clis/defillama/utils.js +99 -0
  223. package/clis/devto/devto.test.js +236 -0
  224. package/clis/devto/latest.js +74 -0
  225. package/clis/devto/read.js +103 -0
  226. package/clis/devto/tag.js +5 -1
  227. package/clis/devto/top.js +5 -1
  228. package/clis/devto/user.js +5 -1
  229. package/clis/dianping/__fixtures__/search.html +168 -0
  230. package/clis/dianping/__fixtures__/shop.html +6 -0
  231. package/clis/dianping/dianping.test.js +424 -0
  232. package/clis/dianping/search.js +154 -0
  233. package/clis/dianping/shop.js +173 -0
  234. package/clis/dianping/utils.js +157 -0
  235. package/clis/dictionary/examples.js +1 -0
  236. package/clis/dictionary/search.js +1 -0
  237. package/clis/dictionary/synonyms.js +1 -0
  238. package/clis/discord-app/channels.js +1 -0
  239. package/clis/discord-app/delete.js +1 -0
  240. package/clis/discord-app/members.js +1 -0
  241. package/clis/discord-app/read.js +1 -0
  242. package/clis/discord-app/search.js +1 -0
  243. package/clis/discord-app/send.js +1 -0
  244. package/clis/discord-app/servers.js +1 -0
  245. package/clis/discord-app/status.js +1 -0
  246. package/clis/dockerhub/image.js +52 -0
  247. package/clis/dockerhub/search.js +47 -0
  248. package/clis/dockerhub/utils.js +100 -0
  249. package/clis/douban/book-hot.js +1 -0
  250. package/clis/douban/download.js +1 -0
  251. package/clis/douban/marks.js +1 -0
  252. package/clis/douban/movie-hot.js +2 -1
  253. package/clis/douban/movie-hot.test.js +14 -0
  254. package/clis/douban/photos.js +2 -1
  255. package/clis/douban/reviews.js +1 -0
  256. package/clis/douban/search.js +1 -0
  257. package/clis/douban/subject.js +1 -0
  258. package/clis/douban/top250.js +1 -0
  259. package/clis/douban/utils.js +11 -13
  260. package/clis/douban/utils.test.js +79 -0
  261. package/clis/doubao/ask.js +8 -3
  262. package/clis/doubao/detail.js +2 -0
  263. package/clis/doubao/history.js +2 -0
  264. package/clis/doubao/meeting-summary.js +2 -0
  265. package/clis/doubao/meeting-transcript.js +2 -0
  266. package/clis/doubao/new.js +2 -0
  267. package/clis/doubao/read.js +2 -0
  268. package/clis/doubao/send.js +2 -0
  269. package/clis/doubao/status.js +2 -0
  270. package/clis/doubao-app/ask.js +1 -0
  271. package/clis/doubao-app/dump.js +1 -0
  272. package/clis/doubao-app/new.js +1 -0
  273. package/clis/doubao-app/read.js +1 -0
  274. package/clis/doubao-app/screenshot.js +1 -0
  275. package/clis/doubao-app/send.js +1 -0
  276. package/clis/doubao-app/status.js +1 -0
  277. package/clis/douyin/activities.js +1 -0
  278. package/clis/douyin/collections.js +1 -0
  279. package/clis/douyin/delete.js +1 -0
  280. package/clis/douyin/draft.js +1 -0
  281. package/clis/douyin/draft.test.js +1 -30
  282. package/clis/douyin/drafts.js +1 -0
  283. package/clis/douyin/hashtag.js +1 -0
  284. package/clis/douyin/location.js +1 -0
  285. package/clis/douyin/profile.js +1 -0
  286. package/clis/douyin/publish.js +1 -0
  287. package/clis/douyin/stats.js +1 -0
  288. package/clis/douyin/update.js +1 -0
  289. package/clis/douyin/user-videos.js +1 -0
  290. package/clis/douyin/videos.js +1 -0
  291. package/clis/eastmoney/announcement.js +1 -0
  292. package/clis/eastmoney/convertible.js +1 -0
  293. package/clis/eastmoney/etf.js +1 -0
  294. package/clis/eastmoney/holders.js +1 -0
  295. package/clis/eastmoney/hot-rank.js +1 -0
  296. package/clis/eastmoney/index-board.js +1 -0
  297. package/clis/eastmoney/kline.js +1 -0
  298. package/clis/eastmoney/kuaixun.js +1 -0
  299. package/clis/eastmoney/longhu.js +1 -0
  300. package/clis/eastmoney/money-flow.js +1 -0
  301. package/clis/eastmoney/northbound.js +1 -0
  302. package/clis/eastmoney/quote.js +1 -0
  303. package/clis/eastmoney/rank.js +1 -0
  304. package/clis/eastmoney/sectors.js +1 -0
  305. package/clis/endoflife/endoflife.test.js +51 -0
  306. package/clis/endoflife/product.js +55 -0
  307. package/clis/endoflife/utils.js +89 -0
  308. package/clis/facebook/__fixtures__/notifications-page.html +13 -0
  309. package/clis/facebook/add-friend.js +1 -0
  310. package/clis/facebook/events.js +1 -0
  311. package/clis/facebook/feed.js +1 -0
  312. package/clis/facebook/friends.js +1 -0
  313. package/clis/facebook/groups.js +1 -0
  314. package/clis/facebook/join-group.js +1 -0
  315. package/clis/facebook/marketplace-inbox.js +1 -0
  316. package/clis/facebook/marketplace-listings.js +1 -0
  317. package/clis/facebook/memories.js +1 -0
  318. package/clis/facebook/notifications.js +327 -30
  319. package/clis/facebook/notifications.test.js +458 -0
  320. package/clis/facebook/profile.js +1 -0
  321. package/clis/facebook/search.js +1 -0
  322. package/clis/flathub/app.js +71 -0
  323. package/clis/flathub/flathub.test.js +90 -0
  324. package/clis/flathub/search.js +80 -0
  325. package/clis/flathub/utils.js +114 -0
  326. package/clis/gemini/ask.js +8 -3
  327. package/clis/gemini/ask.test.js +2 -2
  328. package/clis/gemini/deep-research-result.js +7 -2
  329. package/clis/gemini/deep-research-result.test.js +15 -14
  330. package/clis/gemini/deep-research.js +9 -4
  331. package/clis/gemini/deep-research.test.js +15 -18
  332. package/clis/gemini/image.js +8 -2
  333. package/clis/gemini/new.js +2 -0
  334. package/clis/gemini/utils.js +0 -4
  335. package/clis/gitee/search.js +1 -0
  336. package/clis/gitee/trending.js +1 -0
  337. package/clis/gitee/user.js +1 -0
  338. package/clis/google/news.js +1 -0
  339. package/clis/google/search.js +1 -0
  340. package/clis/google/suggest.js +1 -0
  341. package/clis/google/trends.js +1 -0
  342. package/clis/google-scholar/cite.js +1 -1
  343. package/clis/google-scholar/profile.js +1 -1
  344. package/clis/google-scholar/search.js +1 -1
  345. package/clis/goproxy/goproxy.test.js +103 -0
  346. package/clis/goproxy/module.js +47 -0
  347. package/clis/goproxy/utils.js +165 -0
  348. package/clis/goproxy/versions.js +59 -0
  349. package/clis/gov-law/recent.js +1 -1
  350. package/clis/gov-law/search.js +1 -1
  351. package/clis/gov-policy/__fixtures__/recent.html +16 -0
  352. package/clis/gov-policy/__fixtures__/search.html +41 -0
  353. package/clis/gov-policy/gov-policy.test.js +224 -0
  354. package/clis/gov-policy/recent.js +67 -24
  355. package/clis/gov-policy/search.js +66 -23
  356. package/clis/gov-policy/utils.js +54 -0
  357. package/clis/grok/ask.js +50 -265
  358. package/clis/grok/ask.test.js +21 -46
  359. package/clis/grok/detail.js +60 -0
  360. package/clis/grok/history.js +48 -0
  361. package/clis/grok/{image.ts → image.js} +57 -70
  362. package/clis/grok/image.test.ts +20 -0
  363. package/clis/grok/new.js +20 -0
  364. package/clis/grok/read.js +39 -0
  365. package/clis/grok/send.js +50 -0
  366. package/clis/grok/status.js +41 -0
  367. package/clis/grok/utils.js +326 -0
  368. package/clis/grok/utils.test.js +103 -0
  369. package/clis/hackernews/ask.js +3 -1
  370. package/clis/hackernews/best.js +3 -1
  371. package/clis/hackernews/hackernews.test.js +132 -0
  372. package/clis/hackernews/jobs.js +3 -1
  373. package/clis/hackernews/new.js +3 -1
  374. package/clis/hackernews/read.js +188 -0
  375. package/clis/hackernews/search.js +3 -1
  376. package/clis/hackernews/show.js +3 -1
  377. package/clis/hackernews/top.js +3 -1
  378. package/clis/hackernews/user.js +1 -0
  379. package/clis/hf/datasets.js +88 -0
  380. package/clis/hf/hf.test.js +16 -0
  381. package/clis/hf/models.js +91 -0
  382. package/clis/hf/paper.js +79 -0
  383. package/clis/hf/spaces.js +101 -0
  384. package/clis/hf/top.js +2 -0
  385. package/clis/homebrew/cask.js +39 -0
  386. package/clis/homebrew/formula.js +41 -0
  387. package/clis/homebrew/popular.js +54 -0
  388. package/clis/homebrew/utils.js +100 -0
  389. package/clis/hupu/__fixtures__/hot-home.html +64 -0
  390. package/clis/hupu/detail.js +1 -1
  391. package/clis/hupu/hot.js +157 -34
  392. package/clis/hupu/hot.test.js +224 -0
  393. package/clis/hupu/like.js +1 -0
  394. package/clis/hupu/mentions.js +2 -1
  395. package/clis/hupu/reply.js +1 -0
  396. package/clis/hupu/search.js +3 -2
  397. package/clis/hupu/unlike.js +1 -0
  398. package/clis/imdb/person.js +1 -0
  399. package/clis/imdb/reviews.js +1 -0
  400. package/clis/imdb/search.js +1 -0
  401. package/clis/imdb/title.js +1 -0
  402. package/clis/imdb/top.js +1 -0
  403. package/clis/imdb/trending.js +1 -0
  404. package/clis/indeed/indeed.test.js +375 -0
  405. package/clis/indeed/job.js +86 -0
  406. package/clis/indeed/search.js +110 -0
  407. package/clis/indeed/utils.js +152 -0
  408. package/clis/instagram/collection-create.js +1 -0
  409. package/clis/instagram/collection-delete.js +1 -0
  410. package/clis/instagram/comment.js +1 -0
  411. package/clis/instagram/download.js +1 -0
  412. package/clis/instagram/explore.js +1 -0
  413. package/clis/instagram/follow.js +1 -0
  414. package/clis/instagram/followers.js +1 -0
  415. package/clis/instagram/following.js +1 -0
  416. package/clis/instagram/like.js +1 -0
  417. package/clis/instagram/note.js +2 -1
  418. package/clis/instagram/note.test.js +1 -29
  419. package/clis/instagram/post.js +2 -1
  420. package/clis/instagram/post.test.js +1 -1
  421. package/clis/instagram/profile.js +1 -0
  422. package/clis/instagram/reel.js +2 -1
  423. package/clis/instagram/save.js +1 -0
  424. package/clis/instagram/saved.js +1 -0
  425. package/clis/instagram/search.js +1 -0
  426. package/clis/instagram/story.js +2 -1
  427. package/clis/instagram/story.test.js +1 -34
  428. package/clis/instagram/unfollow.js +1 -0
  429. package/clis/instagram/unlike.js +1 -0
  430. package/clis/instagram/unsave.js +1 -0
  431. package/clis/instagram/user.js +1 -0
  432. package/clis/jd/add-cart.js +1 -0
  433. package/clis/jd/cart.js +1 -0
  434. package/clis/jd/commands.test.js +1 -24
  435. package/clis/jd/detail.js +1 -0
  436. package/clis/jd/item.js +1 -0
  437. package/clis/jd/reviews.js +1 -0
  438. package/clis/jd/search.js +1 -0
  439. package/clis/jianyu/detail.js +1 -0
  440. package/clis/jianyu/search.js +1 -0
  441. package/clis/jike/comment.js +1 -0
  442. package/clis/jike/create.js +1 -0
  443. package/clis/jike/feed.js +3 -1
  444. package/clis/jike/like.js +1 -0
  445. package/clis/jike/notifications.js +1 -0
  446. package/clis/jike/post.js +1 -0
  447. package/clis/jike/repost.js +1 -0
  448. package/clis/jike/search.js +3 -1
  449. package/clis/jike/topic.js +1 -0
  450. package/clis/jike/user.js +3 -1
  451. package/clis/jimeng/generate.js +1 -0
  452. package/clis/jimeng/history.js +1 -0
  453. package/clis/jimeng/new.js +1 -0
  454. package/clis/jimeng/workspaces.js +1 -0
  455. package/clis/ke/chengjiao.js +1 -0
  456. package/clis/ke/ershoufang.js +1 -0
  457. package/clis/ke/xiaoqu.js +1 -0
  458. package/clis/ke/zufang.js +1 -0
  459. package/clis/lesswrong/comments.js +1 -0
  460. package/clis/lesswrong/curated.js +1 -0
  461. package/clis/lesswrong/frontpage.js +1 -0
  462. package/clis/lesswrong/new.js +1 -0
  463. package/clis/lesswrong/read.js +1 -0
  464. package/clis/lesswrong/sequences.js +1 -0
  465. package/clis/lesswrong/shortform.js +1 -0
  466. package/clis/lesswrong/tag.js +1 -0
  467. package/clis/lesswrong/tags.js +1 -0
  468. package/clis/lesswrong/top-month.js +1 -0
  469. package/clis/lesswrong/top-week.js +1 -0
  470. package/clis/lesswrong/top-year.js +1 -0
  471. package/clis/lesswrong/top.js +1 -0
  472. package/clis/lesswrong/user-posts.js +1 -0
  473. package/clis/lesswrong/user.js +1 -0
  474. package/clis/lichess/lichess.test.js +85 -0
  475. package/clis/lichess/top.js +46 -0
  476. package/clis/lichess/user.js +91 -0
  477. package/clis/lichess/utils.js +97 -0
  478. package/clis/linkedin/search.js +108 -10
  479. package/clis/linkedin/search.test.js +222 -0
  480. package/clis/linkedin/timeline.js +1 -0
  481. package/clis/linux-do/categories.js +1 -0
  482. package/clis/linux-do/feed.js +3 -5
  483. package/clis/linux-do/feed.test.js +35 -0
  484. package/clis/linux-do/search.js +1 -0
  485. package/clis/linux-do/tags.js +2 -1
  486. package/clis/linux-do/topic-content.js +1 -0
  487. package/clis/linux-do/topic.js +1 -0
  488. package/clis/linux-do/user-posts.js +1 -0
  489. package/clis/linux-do/user-topics.js +1 -0
  490. package/clis/lobsters/active.js +4 -1
  491. package/clis/lobsters/domain.js +92 -0
  492. package/clis/lobsters/hot.js +4 -1
  493. package/clis/lobsters/lobsters.test.js +169 -0
  494. package/clis/lobsters/newest.js +4 -1
  495. package/clis/lobsters/read.js +196 -0
  496. package/clis/lobsters/tag.js +4 -1
  497. package/clis/maimai/search-talents.js +1 -0
  498. package/clis/maven/artifact.js +49 -0
  499. package/clis/maven/search.js +51 -0
  500. package/clis/maven/utils.js +110 -0
  501. package/clis/mdn/search.js +97 -0
  502. package/clis/medium/feed.js +1 -0
  503. package/clis/medium/search.js +1 -0
  504. package/clis/medium/tag.js +135 -0
  505. package/clis/medium/user.js +1 -0
  506. package/clis/mubu/doc.js +1 -0
  507. package/clis/mubu/docs.js +1 -0
  508. package/clis/mubu/notes.js +1 -0
  509. package/clis/mubu/recent.js +1 -0
  510. package/clis/mubu/search.js +1 -0
  511. package/clis/notebooklm/current.js +1 -0
  512. package/clis/notebooklm/get.js +1 -0
  513. package/clis/notebooklm/history.js +1 -0
  514. package/clis/notebooklm/list.js +1 -0
  515. package/clis/notebooklm/note-list.js +1 -0
  516. package/clis/notebooklm/notes-get.js +1 -0
  517. package/clis/notebooklm/open.js +1 -0
  518. package/clis/notebooklm/source-fulltext.js +1 -0
  519. package/clis/notebooklm/source-get.js +1 -0
  520. package/clis/notebooklm/source-guide.js +1 -0
  521. package/clis/notebooklm/source-list.js +1 -0
  522. package/clis/notebooklm/status.js +1 -0
  523. package/clis/notebooklm/summary.js +1 -0
  524. package/clis/notion/export.js +1 -0
  525. package/clis/notion/favorites.js +1 -0
  526. package/clis/notion/new.js +1 -0
  527. package/clis/notion/read.js +1 -0
  528. package/clis/notion/search.js +1 -0
  529. package/clis/notion/sidebar.js +1 -0
  530. package/clis/notion/status.js +1 -0
  531. package/clis/notion/write.js +1 -0
  532. package/clis/nowcoder/companies.js +1 -0
  533. package/clis/nowcoder/creators.js +1 -0
  534. package/clis/nowcoder/detail.js +1 -0
  535. package/clis/nowcoder/experience.js +1 -0
  536. package/clis/nowcoder/hot.js +1 -0
  537. package/clis/nowcoder/jobs.js +1 -0
  538. package/clis/nowcoder/notifications.js +1 -0
  539. package/clis/nowcoder/papers.js +1 -0
  540. package/clis/nowcoder/practice.js +1 -0
  541. package/clis/nowcoder/recommend.js +1 -0
  542. package/clis/nowcoder/referral.js +1 -0
  543. package/clis/nowcoder/salary.js +1 -0
  544. package/clis/nowcoder/search.js +1 -0
  545. package/clis/nowcoder/suggest.js +1 -0
  546. package/clis/nowcoder/topics.js +1 -0
  547. package/clis/nowcoder/trending.js +1 -0
  548. package/clis/npm/downloads.js +59 -0
  549. package/clis/npm/package.js +70 -0
  550. package/clis/npm/search.js +49 -0
  551. package/clis/npm/utils.js +76 -0
  552. package/clis/nuget/nuget.test.js +111 -0
  553. package/clis/nuget/package.js +101 -0
  554. package/clis/nuget/search.js +69 -0
  555. package/clis/nuget/utils.js +87 -0
  556. package/clis/nvd/cve.js +121 -0
  557. package/clis/oeis/oeis.test.js +88 -0
  558. package/clis/oeis/search.js +63 -0
  559. package/clis/oeis/sequence.js +71 -0
  560. package/clis/oeis/utils.js +88 -0
  561. package/clis/ones/login.js +1 -0
  562. package/clis/ones/logout.js +1 -0
  563. package/clis/ones/me.js +1 -0
  564. package/clis/ones/my-tasks.js +1 -0
  565. package/clis/ones/task.js +1 -0
  566. package/clis/ones/tasks.js +1 -0
  567. package/clis/ones/token-info.js +1 -0
  568. package/clis/ones/worklog.js +1 -0
  569. package/clis/openalex/search.js +69 -0
  570. package/clis/openalex/utils.js +160 -0
  571. package/clis/openalex/work.js +65 -0
  572. package/clis/openfda/drug-label.js +74 -0
  573. package/clis/openfda/food-recall.js +65 -0
  574. package/clis/openfda/openfda.test.js +114 -0
  575. package/clis/openfda/utils.js +67 -0
  576. package/clis/openreview/openreview.test.js +345 -0
  577. package/clis/openreview/paper.js +43 -0
  578. package/clis/openreview/reviews.js +131 -0
  579. package/clis/openreview/search.js +46 -0
  580. package/clis/openreview/utils.js +158 -0
  581. package/clis/openreview/venue.js +63 -0
  582. package/clis/osv/osv.test.js +97 -0
  583. package/clis/osv/query.js +72 -0
  584. package/clis/osv/utils.js +169 -0
  585. package/clis/osv/vulnerability.js +54 -0
  586. package/clis/packagist/package.js +49 -0
  587. package/clis/packagist/search.js +43 -0
  588. package/clis/packagist/utils.js +113 -0
  589. package/clis/paperreview/feedback.js +2 -1
  590. package/clis/paperreview/review.js +2 -1
  591. package/clis/paperreview/submit.js +2 -1
  592. package/clis/pixiv/detail.js +1 -0
  593. package/clis/pixiv/download.js +1 -0
  594. package/clis/pixiv/download.test.js +1 -1
  595. package/clis/pixiv/illusts.js +2 -1
  596. package/clis/pixiv/illusts.test.js +1 -1
  597. package/clis/pixiv/ranking.js +2 -1
  598. package/clis/pixiv/search.js +2 -1
  599. package/clis/pixiv/search.test.js +1 -1
  600. package/clis/pixiv/user.js +2 -0
  601. package/clis/powerchina/search.js +1 -0
  602. package/clis/producthunt/browse.js +1 -0
  603. package/clis/producthunt/hot.js +1 -0
  604. package/clis/producthunt/posts.js +1 -0
  605. package/clis/producthunt/today.js +1 -0
  606. package/clis/pubmed/article.js +50 -0
  607. package/clis/pubmed/author.js +64 -0
  608. package/clis/pubmed/citations.js +36 -0
  609. package/clis/pubmed/pubmed.test.js +276 -0
  610. package/clis/pubmed/related.js +45 -0
  611. package/clis/pubmed/search.js +75 -0
  612. package/clis/pubmed/utils.js +309 -0
  613. package/clis/pypi/downloads.js +66 -0
  614. package/clis/pypi/package.js +79 -0
  615. package/clis/pypi/utils.js +55 -0
  616. package/clis/quark/ls.js +1 -0
  617. package/clis/quark/mkdir.js +1 -0
  618. package/clis/quark/mv.js +2 -1
  619. package/clis/quark/rename.js +1 -0
  620. package/clis/quark/rm.js +1 -0
  621. package/clis/quark/save.js +2 -1
  622. package/clis/quark/share-tree.js +1 -0
  623. package/clis/qwen/ask.js +85 -0
  624. package/clis/qwen/detail.js +62 -0
  625. package/clis/qwen/history.js +61 -0
  626. package/clis/qwen/image.js +179 -0
  627. package/clis/qwen/new.js +23 -0
  628. package/clis/qwen/read.js +41 -0
  629. package/clis/qwen/send.js +55 -0
  630. package/clis/qwen/status.js +37 -0
  631. package/clis/qwen/utils.js +409 -0
  632. package/clis/qwen/utils.test.js +45 -0
  633. package/clis/reddit/comment.js +1 -0
  634. package/clis/reddit/frontpage.js +1 -0
  635. package/clis/reddit/hot.js +6 -1
  636. package/clis/reddit/hot.test.js +18 -0
  637. package/clis/reddit/popular.js +1 -0
  638. package/clis/reddit/read.js +1 -0
  639. package/clis/reddit/save.js +1 -0
  640. package/clis/reddit/saved.js +1 -0
  641. package/clis/reddit/search.js +1 -0
  642. package/clis/reddit/subreddit.js +1 -0
  643. package/clis/reddit/subscribe.js +1 -0
  644. package/clis/reddit/upvote.js +1 -0
  645. package/clis/reddit/upvoted.js +1 -0
  646. package/clis/reddit/user-comments.js +1 -0
  647. package/clis/reddit/user-posts.js +1 -0
  648. package/clis/reddit/user.js +1 -0
  649. package/clis/rest-countries/country.js +65 -0
  650. package/clis/rest-countries/region.js +64 -0
  651. package/clis/rest-countries/rest-countries.test.js +83 -0
  652. package/clis/rest-countries/utils.js +126 -0
  653. package/clis/reuters/article-detail.js +53 -0
  654. package/clis/reuters/reuters.test.js +299 -0
  655. package/clis/reuters/search.js +46 -34
  656. package/clis/reuters/utils.js +159 -0
  657. package/clis/rfc/rfc.js +52 -0
  658. package/clis/rfc/rfc.test.js +74 -0
  659. package/clis/rfc/utils.js +72 -0
  660. package/clis/rubygems/gem.js +42 -0
  661. package/clis/rubygems/search.js +47 -0
  662. package/clis/rubygems/utils.js +86 -0
  663. package/clis/sinablog/article.js +1 -0
  664. package/clis/sinablog/hot.js +1 -0
  665. package/clis/sinablog/search.js +1 -0
  666. package/clis/sinablog/user.js +1 -0
  667. package/clis/sinafinance/news.js +1 -0
  668. package/clis/sinafinance/rolling-news.js +1 -0
  669. package/clis/sinafinance/stock-rank.js +1 -0
  670. package/clis/sinafinance/stock.js +1 -0
  671. package/clis/smzdm/search.js +1 -0
  672. package/clis/spotify/spotify.js +11 -0
  673. package/clis/stackoverflow/bounties.js +11 -3
  674. package/clis/stackoverflow/hot.js +10 -2
  675. package/clis/stackoverflow/read.js +314 -0
  676. package/clis/stackoverflow/related.js +66 -0
  677. package/clis/stackoverflow/search.js +10 -2
  678. package/clis/stackoverflow/stackoverflow.test.js +404 -0
  679. package/clis/stackoverflow/tag.js +60 -0
  680. package/clis/stackoverflow/unanswered.js +9 -2
  681. package/clis/stackoverflow/user.js +50 -0
  682. package/clis/stackoverflow/utils.js +118 -0
  683. package/clis/steam/app.js +67 -0
  684. package/clis/steam/search.js +58 -0
  685. package/clis/steam/steam.test.js +46 -0
  686. package/clis/steam/top-sellers.js +1 -0
  687. package/clis/steam/utils.js +107 -0
  688. package/clis/substack/feed.js +1 -0
  689. package/clis/substack/publication.js +1 -0
  690. package/clis/substack/search.js +1 -0
  691. package/clis/taobao/add-cart.js +1 -0
  692. package/clis/taobao/cart.js +1 -0
  693. package/clis/taobao/commands.test.js +1 -24
  694. package/clis/taobao/detail.js +1 -0
  695. package/clis/taobao/reviews.js +1 -0
  696. package/clis/taobao/search.js +1 -0
  697. package/clis/tdx/hot-rank.js +1 -0
  698. package/clis/test-utils.js +61 -0
  699. package/clis/ths/hot-rank.js +1 -0
  700. package/clis/tieba/hot.js +2 -2
  701. package/clis/tieba/posts.js +1 -0
  702. package/clis/tieba/read.js +1 -0
  703. package/clis/tieba/search.js +2 -1
  704. package/clis/tiktok/comment.js +128 -40
  705. package/clis/tiktok/creator-videos.js +270 -0
  706. package/clis/tiktok/creator-videos.test.js +113 -0
  707. package/clis/tiktok/explore.js +138 -29
  708. package/clis/tiktok/follow.js +116 -33
  709. package/clis/tiktok/following.js +157 -35
  710. package/clis/tiktok/friends.js +140 -37
  711. package/clis/tiktok/like.js +1 -0
  712. package/clis/tiktok/live.js +138 -41
  713. package/clis/tiktok/notifications.js +142 -38
  714. package/clis/tiktok/profile.js +1 -0
  715. package/clis/tiktok/refactor.test.js +389 -0
  716. package/clis/tiktok/save.js +1 -0
  717. package/clis/tiktok/search.js +1 -0
  718. package/clis/tiktok/unfollow.js +125 -38
  719. package/clis/tiktok/unlike.js +1 -0
  720. package/clis/tiktok/unsave.js +1 -0
  721. package/clis/tiktok/user.js +204 -29
  722. package/clis/tiktok/utils.js +505 -0
  723. package/clis/tiktok/write-refactor.test.js +370 -0
  724. package/clis/toutiao/articles.js +37 -62
  725. package/clis/toutiao/hot.js +63 -0
  726. package/clis/toutiao/toutiao.test.js +378 -0
  727. package/clis/toutiao/utils.js +161 -0
  728. package/clis/tvmaze/search.js +61 -0
  729. package/clis/tvmaze/show.js +60 -0
  730. package/clis/tvmaze/tvmaze.test.js +93 -0
  731. package/clis/tvmaze/utils.js +110 -0
  732. package/clis/twitter/accept.js +2 -1
  733. package/clis/twitter/article.js +1 -0
  734. package/clis/twitter/block.js +1 -0
  735. package/clis/twitter/bookmark.js +1 -0
  736. package/clis/twitter/bookmarks.js +2 -1
  737. package/clis/twitter/delete.js +1 -0
  738. package/clis/twitter/download.js +1 -0
  739. package/clis/twitter/follow.js +1 -0
  740. package/clis/twitter/followers.js +135 -69
  741. package/clis/twitter/following.js +1 -0
  742. package/clis/twitter/hide-reply.js +1 -0
  743. package/clis/twitter/like.js +1 -0
  744. package/clis/twitter/likes.js +2 -1
  745. package/clis/twitter/list-add.js +1 -0
  746. package/clis/twitter/list-remove.js +1 -0
  747. package/clis/twitter/list-tweets.js +1 -0
  748. package/clis/twitter/lists.js +1 -0
  749. package/clis/twitter/notifications.js +1 -0
  750. package/clis/twitter/post.js +1 -0
  751. package/clis/twitter/profile.js +1 -0
  752. package/clis/twitter/reply-dm.js +2 -1
  753. package/clis/twitter/reply.js +1 -0
  754. package/clis/twitter/reply.test.js +1 -29
  755. package/clis/twitter/search.js +1 -0
  756. package/clis/twitter/thread.js +1 -0
  757. package/clis/twitter/timeline.js +1 -0
  758. package/clis/twitter/trending.js +11 -12
  759. package/clis/twitter/trending.test.js +15 -0
  760. package/clis/twitter/tweets.js +2 -1
  761. package/clis/twitter/tweets.test.js +2 -2
  762. package/clis/twitter/unblock.js +1 -0
  763. package/clis/twitter/unbookmark.js +1 -0
  764. package/clis/twitter/unfollow.js +1 -0
  765. package/clis/uisdc/news.js +105 -0
  766. package/clis/uisdc/news.test.js +66 -0
  767. package/clis/uiverse/code.js +1 -0
  768. package/clis/uiverse/preview.js +1 -0
  769. package/clis/v2ex/daily.js +1 -0
  770. package/clis/v2ex/hot.js +1 -0
  771. package/clis/v2ex/latest.js +1 -0
  772. package/clis/v2ex/me.js +1 -0
  773. package/clis/v2ex/member.js +1 -0
  774. package/clis/v2ex/node.js +1 -0
  775. package/clis/v2ex/nodes.js +1 -0
  776. package/clis/v2ex/notifications.js +1 -0
  777. package/clis/v2ex/replies.js +1 -0
  778. package/clis/v2ex/topic.js +1 -0
  779. package/clis/v2ex/user.js +1 -0
  780. package/clis/wanfang/search.js +1 -1
  781. package/clis/web/read.js +48 -17
  782. package/clis/web/read.test.js +101 -1
  783. package/clis/weibo/comments.js +1 -0
  784. package/clis/weibo/favorites.js +1 -0
  785. package/clis/weibo/feed.js +3 -1
  786. package/clis/weibo/hot.js +1 -0
  787. package/clis/weibo/me.js +1 -0
  788. package/clis/weibo/post.js +1 -0
  789. package/clis/weibo/publish.js +1 -0
  790. package/clis/weibo/search.js +8 -2
  791. package/clis/weibo/user.js +1 -0
  792. package/clis/weixin/create-draft.js +2 -1
  793. package/clis/weixin/download.js +1 -0
  794. package/clis/weixin/drafts.js +2 -1
  795. package/clis/weixin/drafts.test.js +5 -1
  796. package/clis/weixin/search.js +157 -0
  797. package/clis/weixin/search.test.js +227 -0
  798. package/clis/weread/ai-outline.js +1 -0
  799. package/clis/weread/book.js +1 -0
  800. package/clis/weread/highlights.js +1 -0
  801. package/clis/weread/notebooks.js +1 -0
  802. package/clis/weread/notes.js +1 -0
  803. package/clis/weread/ranking.js +1 -0
  804. package/clis/weread/search.js +1 -0
  805. package/clis/weread/shelf.js +1 -0
  806. package/clis/wikidata/entity.js +60 -0
  807. package/clis/wikidata/search.js +50 -0
  808. package/clis/wikidata/utils.js +117 -0
  809. package/clis/wikidata/wikidata.test.js +83 -0
  810. package/clis/wikipedia/page.js +95 -0
  811. package/clis/wikipedia/random.js +1 -0
  812. package/clis/wikipedia/search.js +1 -0
  813. package/clis/wikipedia/summary.js +1 -0
  814. package/clis/wikipedia/trending.js +1 -0
  815. package/clis/wttr/current.js +63 -0
  816. package/clis/wttr/forecast.js +71 -0
  817. package/clis/wttr/utils.js +50 -0
  818. package/clis/wttr/wttr.test.js +84 -0
  819. package/clis/xianyu/chat.js +17 -4
  820. package/clis/xianyu/chat.test.js +64 -0
  821. package/clis/xianyu/item.js +1 -0
  822. package/clis/xianyu/publish.js +485 -0
  823. package/clis/xianyu/publish.test.js +220 -0
  824. package/clis/xianyu/search.js +1 -0
  825. package/clis/xiaoe/catalog.js +105 -39
  826. package/clis/xiaoe/content.js +165 -29
  827. package/clis/xiaoe/courses.js +86 -28
  828. package/clis/xiaoe/detail.js +1 -0
  829. package/clis/xiaoe/play-url.js +1 -0
  830. package/clis/xiaoe/xiaoe.test.js +486 -0
  831. package/clis/xiaohongshu/comments.js +1 -0
  832. package/clis/xiaohongshu/creator-note-detail.js +1 -0
  833. package/clis/xiaohongshu/creator-notes-summary.js +2 -1
  834. package/clis/xiaohongshu/creator-notes.js +1 -0
  835. package/clis/xiaohongshu/creator-profile.js +1 -0
  836. package/clis/xiaohongshu/creator-stats.js +1 -0
  837. package/clis/xiaohongshu/download.js +1 -0
  838. package/clis/xiaohongshu/feed.js +2 -1
  839. package/clis/xiaohongshu/note.js +1 -0
  840. package/clis/xiaohongshu/notifications.js +1 -0
  841. package/clis/xiaohongshu/publish.js +17 -3
  842. package/clis/xiaohongshu/publish.test.js +46 -1
  843. package/clis/xiaohongshu/search.js +1 -0
  844. package/clis/xiaohongshu/user.js +1 -0
  845. package/clis/xiaoyuzhou/download.js +1 -0
  846. package/clis/xiaoyuzhou/episode.js +1 -0
  847. package/clis/xiaoyuzhou/podcast-episodes.js +1 -0
  848. package/clis/xiaoyuzhou/podcast.js +1 -0
  849. package/clis/xiaoyuzhou/transcript.js +1 -0
  850. package/clis/xueqiu/comments.js +1 -0
  851. package/clis/xueqiu/earnings-date.js +1 -0
  852. package/clis/xueqiu/feed.js +1 -0
  853. package/clis/xueqiu/fund-holdings.js +1 -0
  854. package/clis/xueqiu/fund-snapshot.js +1 -0
  855. package/clis/xueqiu/groups.js +1 -0
  856. package/clis/xueqiu/hot-stock.js +1 -0
  857. package/clis/xueqiu/hot.js +1 -0
  858. package/clis/xueqiu/kline.js +1 -0
  859. package/clis/xueqiu/search.js +1 -0
  860. package/clis/xueqiu/stock.js +1 -0
  861. package/clis/xueqiu/watchlist.js +1 -0
  862. package/clis/yahoo-finance/quote.js +1 -0
  863. package/clis/yollomi/background.js +1 -0
  864. package/clis/yollomi/edit.js +1 -0
  865. package/clis/yollomi/face-swap.js +1 -0
  866. package/clis/yollomi/generate.js +1 -0
  867. package/clis/yollomi/models.js +1 -0
  868. package/clis/yollomi/object-remover.js +1 -0
  869. package/clis/yollomi/remove-bg.js +1 -0
  870. package/clis/yollomi/restore.js +1 -0
  871. package/clis/yollomi/try-on.js +1 -0
  872. package/clis/yollomi/upload.js +1 -0
  873. package/clis/yollomi/upscale.js +1 -0
  874. package/clis/yollomi/video.js +1 -0
  875. package/clis/youtube/channel.js +1 -0
  876. package/clis/youtube/comments.js +1 -0
  877. package/clis/youtube/feed.js +8 -7
  878. package/clis/youtube/feed.test.js +131 -0
  879. package/clis/youtube/history.js +1 -0
  880. package/clis/youtube/like.js +1 -0
  881. package/clis/youtube/playlist.js +1 -0
  882. package/clis/youtube/search.js +1 -0
  883. package/clis/youtube/subscribe.js +1 -0
  884. package/clis/youtube/subscriptions.js +1 -0
  885. package/clis/youtube/transcript.js +14 -19
  886. package/clis/youtube/transcript.test.js +17 -0
  887. package/clis/youtube/unlike.js +1 -0
  888. package/clis/youtube/unsubscribe.js +1 -0
  889. package/clis/youtube/video.js +1 -0
  890. package/clis/youtube/watch-later.js +1 -0
  891. package/clis/yuanbao/ask.js +18 -66
  892. package/clis/yuanbao/ask.test.js +5 -5
  893. package/clis/yuanbao/detail.js +65 -0
  894. package/clis/yuanbao/history.js +51 -0
  895. package/clis/yuanbao/new.js +2 -0
  896. package/clis/yuanbao/read.js +38 -0
  897. package/clis/yuanbao/send.js +57 -0
  898. package/clis/yuanbao/shared.js +297 -5
  899. package/clis/yuanbao/shared.test.js +80 -0
  900. package/clis/yuanbao/status.js +44 -0
  901. package/clis/zhihu/answer.js +1 -0
  902. package/clis/zhihu/collection.js +1 -0
  903. package/clis/zhihu/collections.js +1 -0
  904. package/clis/zhihu/comment.js +1 -0
  905. package/clis/zhihu/download.js +1 -0
  906. package/clis/zhihu/favorite.js +1 -0
  907. package/clis/zhihu/follow.js +1 -0
  908. package/clis/zhihu/hot.js +1 -0
  909. package/clis/zhihu/like.js +1 -0
  910. package/clis/zhihu/question.js +1 -0
  911. package/clis/zhihu/search.js +1 -0
  912. package/clis/zlibrary/commands.test.js +1 -11
  913. package/clis/zlibrary/info.js +1 -0
  914. package/clis/zlibrary/search.js +1 -0
  915. package/clis/zsxq/dynamics.js +1 -0
  916. package/clis/zsxq/groups.js +1 -0
  917. package/clis/zsxq/search.js +1 -0
  918. package/clis/zsxq/topic.js +1 -0
  919. package/clis/zsxq/topics.js +1 -0
  920. package/dist/src/adapter-source.test.js +1 -1
  921. package/dist/src/browser/analyze.test.js +2 -0
  922. package/dist/src/browser/base-page.d.ts +18 -0
  923. package/dist/src/browser/base-page.js +116 -4
  924. package/dist/src/browser/base-page.test.js +108 -0
  925. package/dist/src/browser/cdp.d.ts +1 -0
  926. package/dist/src/browser/cdp.js +57 -9
  927. package/dist/src/browser/cdp.test.js +3 -0
  928. package/dist/src/browser/daemon-client.d.ts +4 -0
  929. package/dist/src/browser/errors.js +1 -1
  930. package/dist/src/browser/page.d.ts +2 -1
  931. package/dist/src/browser/page.js +9 -1
  932. package/dist/src/browser/page.test.js +46 -0
  933. package/dist/src/browser/target-errors.d.ts +2 -1
  934. package/dist/src/browser/target-errors.js +1 -0
  935. package/dist/src/browser/target-resolver.d.ts +35 -3
  936. package/dist/src/browser/target-resolver.js +59 -10
  937. package/dist/src/browser/verify-fixture.d.ts +6 -1
  938. package/dist/src/browser/verify-fixture.js +87 -0
  939. package/dist/src/browser/verify-fixture.test.js +44 -1
  940. package/dist/src/build-manifest.js +12 -4
  941. package/dist/src/build-manifest.test.js +20 -20
  942. package/dist/src/capabilityRouting.d.ts +16 -1
  943. package/dist/src/capabilityRouting.js +24 -1
  944. package/dist/src/capabilityRouting.test.js +20 -2
  945. package/dist/src/cli.js +213 -12
  946. package/dist/src/cli.test.js +329 -0
  947. package/dist/src/commanderAdapter.d.ts +1 -1
  948. package/dist/src/commanderAdapter.js +17 -12
  949. package/dist/src/commanderAdapter.test.js +7 -7
  950. package/dist/src/convention-audit.d.ts +50 -0
  951. package/dist/src/convention-audit.js +546 -0
  952. package/dist/src/convention-audit.test.d.ts +1 -0
  953. package/dist/src/convention-audit.test.js +226 -0
  954. package/dist/src/discovery.js +4 -5
  955. package/dist/src/doctor.js +0 -1
  956. package/dist/src/doctor.test.js +1 -1
  957. package/dist/src/engine.test.js +10 -10
  958. package/dist/src/errors.js +1 -1
  959. package/dist/src/execution.d.ts +1 -1
  960. package/dist/src/execution.js +111 -27
  961. package/dist/src/execution.test.js +334 -25
  962. package/dist/src/help.d.ts +36 -0
  963. package/dist/src/help.js +171 -0
  964. package/dist/src/help.test.d.ts +1 -0
  965. package/dist/src/help.test.js +54 -0
  966. package/dist/src/main.js +27 -8
  967. package/dist/src/manifest-types.d.ts +7 -3
  968. package/dist/src/pipeline/executor.js +1 -1
  969. package/dist/src/pipeline/executor.test.js +8 -0
  970. package/dist/src/pipeline/registry.d.ts +9 -0
  971. package/dist/src/pipeline/registry.js +13 -1
  972. package/dist/src/pipeline/steps/browser.d.ts +1 -0
  973. package/dist/src/pipeline/steps/browser.js +10 -0
  974. package/dist/src/pipeline/steps/download.test.js +1 -0
  975. package/dist/src/plugin.test.js +26 -26
  976. package/dist/src/registry-api.d.ts +1 -1
  977. package/dist/src/registry.d.ts +17 -11
  978. package/dist/src/registry.js +24 -6
  979. package/dist/src/registry.test.js +29 -22
  980. package/dist/src/runtime.d.ts +2 -1
  981. package/dist/src/runtime.js +1 -1
  982. package/dist/src/serialization.d.ts +6 -2
  983. package/dist/src/serialization.js +31 -7
  984. package/dist/src/serialization.test.js +41 -2
  985. package/dist/src/types.d.ts +19 -0
  986. package/dist/src/validate.js +15 -11
  987. package/dist/src/validate.test.d.ts +9 -0
  988. package/dist/src/validate.test.js +90 -0
  989. package/package.json +4 -1
  990. package/scripts/check-listing-id-pairing.mjs +193 -0
  991. package/scripts/check-silent-column-drop.mjs +105 -0
  992. package/scripts/check-typed-error-lint.mjs +118 -0
  993. package/scripts/fetch-adapters.js +1 -1
  994. package/scripts/silent-column-drop-baseline.json +962 -0
  995. package/scripts/typed-error-lint-baseline.json +1514 -0
  996. package/clis/ctrip/search.test.js +0 -64
  997. package/clis/gov-policy/commands.test.js +0 -27
  998. package/clis/linux-do/category.js +0 -36
  999. package/clis/linux-do/hot.js +0 -25
  1000. package/clis/linux-do/latest.js +0 -18
  1001. package/clis/pixiv/test-utils.js +0 -23
  1002. package/clis/toutiao/articles.test.js +0 -30
  1003. package/dist/src/analysis.d.ts +0 -40
  1004. package/dist/src/analysis.js +0 -172
@@ -0,0 +1,290 @@
1
+ /**
2
+ * DBLP adapter utilities.
3
+ *
4
+ * dblp serves a public, unauthenticated API:
5
+ * - Publication search (JSON):
6
+ * `https://dblp.org/search/publ/api?q=<query>&format=json&h=<limit>`
7
+ * - Per-record metadata (XML):
8
+ * `https://dblp.org/rec/<key>.xml`
9
+ *
10
+ * The search response is well-shaped JSON, but the per-record endpoint is
11
+ * XML. We parse it with conservative regexes (same pattern as the arxiv
12
+ * adapter) to avoid pulling in an XML lib for this single endpoint.
13
+ */
14
+ import { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';
15
+
16
+ export const DBLP_ORIGIN = 'https://dblp.org';
17
+
18
+ /**
19
+ * dblp record keys look like `<type>/<venue>/<short>` (e.g.
20
+ * `conf/nips/VaswaniSPUJGKP17`, `journals/corr/abs-2509-05821`,
21
+ * `phd/Smith20`). Allow lowercase letter prefixes plus 1+ slash-segments
22
+ * containing letters / digits / `_` / `.` / `-`.
23
+ */
24
+ const KEY_PATTERN = /^[a-z]+(?:\/[A-Za-z0-9_.-]+)+$/;
25
+
26
+ /**
27
+ * Wraps `fetch` with typed errors. We always set a UA per dblp's
28
+ * polite-fetch guidance (https://dblp.org/faq/How+to+use+the+dblp+search+API.html).
29
+ */
30
+ async function dblpFetch(url, label, accept) {
31
+ let res;
32
+ try {
33
+ res = await fetch(url, {
34
+ headers: {
35
+ accept,
36
+ 'user-agent': 'opencli-dblp/1.0 (+https://github.com/jackwener/opencli)',
37
+ },
38
+ });
39
+ }
40
+ catch (err) {
41
+ throw new CommandExecutionError(`${label} request failed: ${err?.message ?? err}`, 'Check that dblp.org is reachable from this network.');
42
+ }
43
+ if (!res.ok) {
44
+ if (res.status === 429) {
45
+ throw new CommandExecutionError(`${label} returned HTTP 429 (rate limited)`, 'dblp throttles clients that fetch too aggressively. Wait a few seconds and retry, or lower --limit.');
46
+ }
47
+ if (res.status === 404) {
48
+ throw new EmptyResultError(label, 'dblp returned 404 — the requested record may not exist.');
49
+ }
50
+ throw new CommandExecutionError(`${label} returned HTTP ${res.status}`, 'Inspect the response in a browser at the same URL for more context.');
51
+ }
52
+ return res;
53
+ }
54
+
55
+ export async function dblpFetchJson(path, label) {
56
+ const res = await dblpFetch(`${DBLP_ORIGIN}${path}`, label, 'application/json');
57
+ let body;
58
+ try {
59
+ body = await res.json();
60
+ }
61
+ catch (err) {
62
+ throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);
63
+ }
64
+ const statusCode = String(body?.result?.status?.['@code'] ?? '').trim();
65
+ if (!statusCode) {
66
+ throw new CommandExecutionError(
67
+ `${label} returned JSON without result.status.@code`,
68
+ 'dblp changed its JSON envelope or returned a partial error payload; inspect the raw response in a browser.',
69
+ );
70
+ }
71
+ if (statusCode !== '200') {
72
+ const statusText = String(body?.result?.status?.text ?? '').trim();
73
+ throw new CommandExecutionError(
74
+ `${label} returned API status ${statusCode}${statusText ? ` (${statusText})` : ''}`,
75
+ 'dblp accepted the HTTP request but reported an API-level failure. Retry later or inspect the same query in a browser.',
76
+ );
77
+ }
78
+ return body;
79
+ }
80
+
81
+ export async function dblpFetchXml(path, label) {
82
+ const res = await dblpFetch(`${DBLP_ORIGIN}${path}`, label, 'application/xml');
83
+ return res.text();
84
+ }
85
+
86
+ export function coerceInt(value) {
87
+ if (value === undefined || value === null || value === '') return NaN;
88
+ const n = typeof value === 'number' ? value : Number(value);
89
+ return Number.isFinite(n) && Number.isInteger(n) ? n : NaN;
90
+ }
91
+
92
+ export function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {
93
+ const raw = value ?? defaultValue;
94
+ const n = coerceInt(raw);
95
+ if (!Number.isInteger(n) || n <= 0) {
96
+ throw new ArgumentError(`dblp ${label} must be a positive integer`);
97
+ }
98
+ if (n > maxValue) {
99
+ throw new ArgumentError(`dblp ${label} must be <= ${maxValue}`);
100
+ }
101
+ return n;
102
+ }
103
+
104
+ export function requireQuery(value, label = 'query') {
105
+ const q = String(value ?? '').trim();
106
+ if (!q) {
107
+ throw new ArgumentError(`dblp ${label} cannot be empty`);
108
+ }
109
+ return q;
110
+ }
111
+
112
+ export function requireRecordKey(value) {
113
+ const key = String(value ?? '').trim();
114
+ if (!key) {
115
+ throw new ArgumentError('dblp paper key is required');
116
+ }
117
+ if (!KEY_PATTERN.test(key)) {
118
+ throw new ArgumentError(`dblp paper key "${value}" is not a valid record key`, 'Expected something like "conf/nips/VaswaniSPUJGKP17" — copy the `key` column from `dblp search`.');
119
+ }
120
+ return key;
121
+ }
122
+
123
+ /** Decode the small set of XML entities dblp emits in record bodies. */
124
+ export function decodeXmlEntities(text) {
125
+ if (!text) return '';
126
+ return String(text)
127
+ .replace(/&amp;/g, '&')
128
+ .replace(/&lt;/g, '<')
129
+ .replace(/&gt;/g, '>')
130
+ .replace(/&apos;/g, "'")
131
+ .replace(/&quot;/g, '"')
132
+ .replace(/&#x([0-9a-fA-F]+);/g, (_, h) => String.fromCodePoint(parseInt(h, 16)))
133
+ .replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(parseInt(d, 10)));
134
+ }
135
+
136
+ /** Strip dblp's per-author homonym suffixes (`Smith 0001`) → `Smith`. */
137
+ function trimAuthorHomonym(name) {
138
+ return String(name || '').replace(/\s+\d{4,}$/, '').trim();
139
+ }
140
+
141
+ /**
142
+ * Normalize the `info.authors.author` field from a dblp search hit. dblp
143
+ * collapses single authors into one object instead of a 1-element array.
144
+ */
145
+ export function normalizeAuthors(authorsField) {
146
+ if (!authorsField) return [];
147
+ const raw = authorsField?.author;
148
+ if (!raw) return [];
149
+ const list = Array.isArray(raw) ? raw : [raw];
150
+ return list.map((a) => {
151
+ if (a && typeof a === 'object') return trimAuthorHomonym(a.text || a['#text'] || '');
152
+ return trimAuthorHomonym(String(a));
153
+ }).filter(Boolean);
154
+ }
155
+
156
+ /**
157
+ * Project a dblp publication search hit into one row. Drops only the most
158
+ * volatile fields (e.g. abstract, which dblp does not expose) and keeps
159
+ * the canonical key as the round-trip handle.
160
+ */
161
+ export function searchHitToRow(hit, rank) {
162
+ const info = hit?.info ?? {};
163
+ const authors = normalizeAuthors(info.authors);
164
+ const key = String(info.key ?? '').trim();
165
+ return {
166
+ rank,
167
+ key,
168
+ title: stripTrailingDot(decodeXmlEntities(info.title ?? '')).trim(),
169
+ authors: authors.join(', '),
170
+ venue: decodeXmlEntities(info.venue ?? ''),
171
+ year: String(info.year ?? '').trim(),
172
+ type: simplifyHitType(info.type),
173
+ doi: String(info.doi ?? '').trim(),
174
+ url: String(info.ee ?? info.url ?? '').trim(),
175
+ };
176
+ }
177
+
178
+ /** Title strings from dblp end with a period — strip it for cleaner display. */
179
+ function stripTrailingDot(s) {
180
+ return String(s || '').replace(/\.\s*$/, '');
181
+ }
182
+
183
+ /** Compress dblp's verbose `type` strings into single-token tags. */
184
+ function simplifyHitType(type) {
185
+ if (!type) return '';
186
+ const t = String(type);
187
+ if (/Conference and Workshop/i.test(t)) return 'conf';
188
+ if (/Journal Articles/i.test(t)) return 'journal';
189
+ if (/Books and Theses/i.test(t)) return 'book';
190
+ if (/Editorship/i.test(t)) return 'editorship';
191
+ if (/Reference Works/i.test(t)) return 'reference';
192
+ if (/Informal/i.test(t)) return 'preprint';
193
+ return t.toLowerCase().split(/\s+/)[0];
194
+ }
195
+
196
+ /**
197
+ * Extract a single tag from a dblp record XML blob (regex-based, same
198
+ * approach as arxiv/utils.js — keeps the dependency surface flat).
199
+ */
200
+ export function extractFirst(xml, tag) {
201
+ const m = String(xml || '').match(new RegExp(`<${tag}\\b[^>]*>([\\s\\S]*?)<\\/${tag}>`));
202
+ return m ? m[1] : '';
203
+ }
204
+
205
+ export function extractAll(xml, tag) {
206
+ const out = [];
207
+ const re = new RegExp(`<${tag}\\b[^>]*>([\\s\\S]*?)<\\/${tag}>`, 'g');
208
+ let m;
209
+ while ((m = re.exec(String(xml || ''))) !== null) out.push(m[1]);
210
+ return out;
211
+ }
212
+
213
+ /**
214
+ * Pick the first `<ee type="oa">` (open-access link) if present, otherwise
215
+ * fall back to the first `<ee>`.
216
+ */
217
+ export function extractOpenAccessLink(xml) {
218
+ const oa = String(xml || '').match(/<ee\b[^>]*type=["']oa["'][^>]*>([\s\S]*?)<\/ee>/);
219
+ if (oa) return oa[1].trim();
220
+ const any = String(xml || '').match(/<ee\b[^>]*>([\s\S]*?)<\/ee>/);
221
+ return any ? any[1].trim() : '';
222
+ }
223
+
224
+ /** Pull the `key` attribute off the wrapper element regardless of record type. */
225
+ export function extractRecordKey(xml) {
226
+ const m = String(xml || '').match(/<(?:article|inproceedings|incollection|proceedings|book|phdthesis|mastersthesis)\b[^>]*\bkey="([^"]+)"/);
227
+ return m ? m[1] : '';
228
+ }
229
+
230
+ /**
231
+ * Identify the record type from the wrapper element name. Maps to the
232
+ * same simplified tag set the search rows use.
233
+ */
234
+ export function extractRecordType(xml) {
235
+ const m = String(xml || '').match(/<(article|inproceedings|incollection|proceedings|book|phdthesis|mastersthesis)\b/);
236
+ if (!m) return '';
237
+ switch (m[1]) {
238
+ case 'inproceedings': return 'conf';
239
+ case 'article': return 'journal';
240
+ case 'incollection': return 'incollection';
241
+ case 'proceedings': return 'editorship';
242
+ case 'book': return 'book';
243
+ case 'phdthesis': return 'phdthesis';
244
+ case 'mastersthesis': return 'mastersthesis';
245
+ default: return m[1];
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Parse a single dblp record XML into the row shape used by `dblp paper`.
251
+ * Treats every field as optional; throws upstream when the record body
252
+ * is missing entirely (404 already handled at fetch level).
253
+ */
254
+ export function recordXmlToRow(xml) {
255
+ const key = extractRecordKey(xml);
256
+ const type = extractRecordType(xml);
257
+ const title = stripTrailingDot(decodeXmlEntities(extractFirst(xml, 'title')));
258
+ const authors = extractAll(xml, 'author').map((a) => trimAuthorHomonym(decodeXmlEntities(a)));
259
+ const year = decodeXmlEntities(extractFirst(xml, 'year'));
260
+ const pages = decodeXmlEntities(extractFirst(xml, 'pages'));
261
+ const venueRaw = type === 'conf'
262
+ ? decodeXmlEntities(extractFirst(xml, 'booktitle'))
263
+ : decodeXmlEntities(extractFirst(xml, 'journal'));
264
+ const doi = (() => {
265
+ const m = String(xml || '').match(/<ee\b[^>]*>([^<]*?(?:doi\.org\/|10\.[^"<]+))<\/ee>/i);
266
+ if (!m) return '';
267
+ const v = m[1].replace(/^https?:\/\/(?:dx\.)?doi\.org\//i, '');
268
+ return v.startsWith('10.') ? v : '';
269
+ })();
270
+ return {
271
+ key,
272
+ type,
273
+ title,
274
+ authors: authors.join(', '),
275
+ venue: venueRaw,
276
+ year,
277
+ pages,
278
+ doi,
279
+ open_access_url: extractOpenAccessLink(xml),
280
+ dblp_url: key ? `${DBLP_ORIGIN}/rec/${key}.html` : '',
281
+ };
282
+ }
283
+
284
+ export const SEARCH_COLUMNS = [
285
+ 'rank', 'key', 'title', 'authors', 'venue', 'year', 'type', 'doi', 'url',
286
+ ];
287
+
288
+ export const PAPER_COLUMNS = [
289
+ 'key', 'type', 'title', 'authors', 'venue', 'year', 'pages', 'doi', 'open_access_url', 'dblp_url',
290
+ ];
@@ -0,0 +1,64 @@
1
+ // dblp venue — search dblp's venue (conference / journal) registry.
2
+ //
3
+ // Hits `https://dblp.org/search/venue/api?q=…&format=json&h=…`. Returns a
4
+ // row per matched venue. Useful for resolving an acronym (e.g. "ICLR" →
5
+ // dblp's canonical venue page) and for browsing venues that match a topic.
6
+ import { cli, Strategy } from '@jackwener/opencli/registry';
7
+ import { EmptyResultError } from '@jackwener/opencli/errors';
8
+ import {
9
+ DBLP_ORIGIN,
10
+ decodeXmlEntities,
11
+ dblpFetchJson,
12
+ requireBoundedInt,
13
+ requireQuery,
14
+ } from './utils.js';
15
+
16
+ function simplifyVenueType(type) {
17
+ const t = String(type ?? '').trim();
18
+ if (!t) return '';
19
+ if (/Conference or Workshop/i.test(t)) return 'conf';
20
+ if (/Journal/i.test(t)) return 'journal';
21
+ if (/Series/i.test(t)) return 'series';
22
+ if (/Book/i.test(t)) return 'book';
23
+ if (/Reference/i.test(t)) return 'reference';
24
+ return t.toLowerCase().split(/\s+/)[0];
25
+ }
26
+
27
+ function venueHitToRow(hit, rank) {
28
+ const info = hit?.info ?? {};
29
+ const url = String(info.url ?? '').trim();
30
+ return {
31
+ rank,
32
+ acronym: String(info.acronym ?? '').trim(),
33
+ venue: decodeXmlEntities(info.venue ?? ''),
34
+ type: simplifyVenueType(info.type),
35
+ url: url.startsWith('http') ? url : url ? `${DBLP_ORIGIN}${url.startsWith('/') ? '' : '/'}${url}` : '',
36
+ };
37
+ }
38
+
39
+ cli({
40
+ site: 'dblp',
41
+ name: 'venue',
42
+ access: 'read',
43
+ description: 'Search dblp venue registry (conferences / journals) by name or acronym',
44
+ domain: 'dblp.org',
45
+ strategy: Strategy.PUBLIC,
46
+ browser: false,
47
+ args: [
48
+ { name: 'query', positional: true, required: true, help: 'Venue name or acronym (e.g. "ICLR", "neural networks")' },
49
+ { name: 'limit', type: 'int', default: 20, help: 'Max venues (1-100, single dblp page)' },
50
+ ],
51
+ columns: ['rank', 'acronym', 'venue', 'type', 'url'],
52
+ func: async (args) => {
53
+ const query = requireQuery(args.query);
54
+ const limit = requireBoundedInt(args.limit, 20, 100);
55
+ const path = `/search/venue/api?q=${encodeURIComponent(query)}&format=json&h=${limit}`;
56
+ const json = await dblpFetchJson(path, 'dblp venue');
57
+ const hits = json?.result?.hits?.hit;
58
+ const list = Array.isArray(hits) ? hits : [];
59
+ if (list.length === 0) {
60
+ throw new EmptyResultError('dblp venue', `No dblp venues matched "${query}".`);
61
+ }
62
+ return list.slice(0, limit).map((hit, i) => venueHitToRow(hit, i + 1));
63
+ },
64
+ });
@@ -3,17 +3,19 @@ import { CliError, CommandExecutionError, EXIT_CODES } from '@jackwener/opencli/
3
3
  import {
4
4
  DEEPSEEK_DOMAIN, DEEPSEEK_URL, ensureOnDeepSeek, selectModel, setFeature,
5
5
  sendMessage, sendWithFile, getBubbleCount, waitForResponse, parseBoolFlag, withRetry,
6
+ pickResumeUrl,
6
7
  } from './utils.js';
7
8
 
8
9
  export const askCommand = cli({
9
10
  site: 'deepseek',
10
11
  name: 'ask',
12
+ access: 'write',
11
13
  description: 'Send a prompt to DeepSeek and get the response',
12
14
  domain: DEEPSEEK_DOMAIN,
13
15
  strategy: Strategy.COOKIE,
14
16
  browser: true,
17
+ browserSession: { reuse: 'site' },
15
18
  navigateBefore: false,
16
- timeoutSeconds: 180,
17
19
  args: [
18
20
  { name: 'prompt', positional: true, required: true, help: 'Prompt to send' },
19
21
  { name: 'timeout', type: 'int', default: 120, help: 'Max seconds to wait for response' },
@@ -37,12 +39,16 @@ export const askCommand = cli({
37
39
  } else {
38
40
  const navigated = await ensureOnDeepSeek(page);
39
41
  if (navigated) {
40
- // Workspace was recycled; try to resume the most recent
41
- // conversation instead of starting a new one.
42
- await page.evaluate(`(() => {
43
- var link = document.querySelector('a[href*="/a/chat/s/"]');
44
- if (link) link.click();
45
- })()`);
42
+ // Pinned conversations sit in their own DOM section and are
43
+ // skipped so the resume never lands on a topped chat.
44
+ const resumeUrl = await pickResumeUrl(page);
45
+ if (!resumeUrl) {
46
+ throw new CommandExecutionError(
47
+ 'Workspace was recycled but no prior conversation could be loaded',
48
+ 'Pass --new to start a fresh chat, or wait for the sidebar to populate before retrying.',
49
+ );
50
+ }
51
+ await page.goto(resumeUrl);
46
52
  await page.wait(2);
47
53
  }
48
54
  }
@@ -11,6 +11,7 @@ const {
11
11
  mockWaitForResponse,
12
12
  mockParseBoolFlag,
13
13
  mockWithRetry,
14
+ mockPickResumeUrl,
14
15
  } = vi.hoisted(() => ({
15
16
  mockEnsureOnDeepSeek: vi.fn(),
16
17
  mockSelectModel: vi.fn(),
@@ -21,6 +22,7 @@ const {
21
22
  mockWaitForResponse: vi.fn(),
22
23
  mockParseBoolFlag: vi.fn((v) => v === true || v === 'true'),
23
24
  mockWithRetry: vi.fn(async (fn) => fn()),
25
+ mockPickResumeUrl: vi.fn(),
24
26
  }));
25
27
 
26
28
  vi.mock('./utils.js', () => ({
@@ -35,6 +37,7 @@ vi.mock('./utils.js', () => ({
35
37
  waitForResponse: mockWaitForResponse,
36
38
  parseBoolFlag: mockParseBoolFlag,
37
39
  withRetry: mockWithRetry,
40
+ pickResumeUrl: mockPickResumeUrl,
38
41
  }));
39
42
 
40
43
  import { askCommand } from './ask.js';
@@ -185,9 +188,8 @@ describe('deepseek ask conversation resume', () => {
185
188
 
186
189
  it('resumes the most recent conversation and skips model selection', async () => {
187
190
  mockEnsureOnDeepSeek.mockResolvedValue(true);
188
- // first evaluate: sidebar resume click (returns undefined)
189
- page.evaluate.mockResolvedValueOnce(undefined);
190
- // second evaluate: URL check (now inside a conversation)
191
+ mockPickResumeUrl.mockResolvedValue('https://chat.deepseek.com/a/chat/s/abc-123');
192
+ // URL check after resume navigation: now inside a conversation.
191
193
  page.evaluate.mockResolvedValueOnce('https://chat.deepseek.com/a/chat/s/abc-123');
192
194
 
193
195
  const rows = await askCommand.func(page, {
@@ -200,6 +202,7 @@ describe('deepseek ask conversation resume', () => {
200
202
  });
201
203
 
202
204
  expect(rows).toEqual([{ response: 'follow-up reply' }]);
205
+ expect(page.goto).toHaveBeenCalledWith('https://chat.deepseek.com/a/chat/s/abc-123');
203
206
  expect(mockSelectModel).not.toHaveBeenCalled();
204
207
  expect(mockSendMessage).toHaveBeenCalled();
205
208
  });
@@ -243,25 +246,22 @@ describe('deepseek ask conversation resume', () => {
243
246
  expect(mockSelectModel).not.toHaveBeenCalled();
244
247
  });
245
248
 
246
- it('still selects model when no conversation to resume', async () => {
249
+ it('fails fast when the workspace was recycled but no conversation surfaces in time', async () => {
247
250
  mockEnsureOnDeepSeek.mockResolvedValue(true);
248
- mockSelectModel.mockResolvedValue({ ok: true, toggled: false });
249
- // first evaluate: sidebar resume click (no link found)
250
- page.evaluate.mockResolvedValueOnce(undefined);
251
- // second evaluate: URL check (still on root page)
252
- page.evaluate.mockResolvedValueOnce('https://chat.deepseek.com/');
251
+ mockPickResumeUrl.mockResolvedValue(null);
253
252
 
254
- const rows = await askCommand.func(page, {
253
+ await expect(askCommand.func(page, {
255
254
  prompt: 'hello',
256
255
  timeout: 120,
257
256
  new: false,
258
257
  model: 'instant',
259
258
  think: false,
260
259
  search: false,
261
- });
260
+ })).rejects.toBeInstanceOf(CommandExecutionError);
262
261
 
263
- expect(rows).toEqual([{ response: 'follow-up reply' }]);
264
- expect(mockSelectModel).toHaveBeenCalled();
262
+ expect(page.goto).not.toHaveBeenCalled();
263
+ expect(mockSelectModel).not.toHaveBeenCalled();
264
+ expect(mockSendMessage).not.toHaveBeenCalled();
265
265
  });
266
266
 
267
267
  it('skips search toggle in vision mode when search is not requested', async () => {
@@ -0,0 +1,38 @@
1
+ import { cli, Strategy } from '@jackwener/opencli/registry';
2
+ import { EmptyResultError } from '@jackwener/opencli/errors';
3
+ import {
4
+ DEEPSEEK_DOMAIN,
5
+ ensureOnDeepSeek,
6
+ getVisibleMessages,
7
+ parseDeepSeekConversationId,
8
+ } from './utils.js';
9
+
10
+ export const detailCommand = cli({
11
+ site: 'deepseek',
12
+ name: 'detail',
13
+ access: 'read',
14
+ description: 'Read a specific DeepSeek conversation by ID',
15
+ domain: DEEPSEEK_DOMAIN,
16
+ strategy: Strategy.COOKIE,
17
+ browser: true,
18
+ browserSession: { reuse: 'site' },
19
+ navigateBefore: false,
20
+ args: [
21
+ { name: 'id', required: true, positional: true, help: 'Conversation ID (UUID) or full /a/chat/s/<id> URL' },
22
+ ],
23
+ columns: ['Role', 'Text'],
24
+ func: async (page, kwargs) => {
25
+ const id = parseDeepSeekConversationId(kwargs.id);
26
+ await ensureOnDeepSeek(page);
27
+ await page.goto(`https://chat.deepseek.com/a/chat/s/${id}`);
28
+ await page.wait(5);
29
+ const messages = await getVisibleMessages(page);
30
+ if (messages.length === 0) {
31
+ throw new EmptyResultError(
32
+ 'deepseek detail',
33
+ `No visible messages found for conversation ${id}. Verify the ID is correct and that you are logged in.`,
34
+ );
35
+ }
36
+ return messages;
37
+ },
38
+ });
@@ -0,0 +1,81 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { ArgumentError, EmptyResultError } from '@jackwener/opencli/errors';
3
+ import { getRegistry } from '@jackwener/opencli/registry';
4
+
5
+ const {
6
+ mockEnsureOnDeepSeek,
7
+ mockGetVisibleMessages,
8
+ } = vi.hoisted(() => ({
9
+ mockEnsureOnDeepSeek: vi.fn(),
10
+ mockGetVisibleMessages: vi.fn(),
11
+ }));
12
+
13
+ vi.mock('./utils.js', async () => {
14
+ const actual = await vi.importActual('./utils.js');
15
+ return {
16
+ ...actual,
17
+ ensureOnDeepSeek: mockEnsureOnDeepSeek,
18
+ getVisibleMessages: mockGetVisibleMessages,
19
+ };
20
+ });
21
+
22
+ import './detail.js';
23
+
24
+ describe('deepseek detail', () => {
25
+ const command = getRegistry().get('deepseek/detail');
26
+ const id = '749e6bbd-6a45-4440-beaa-ae5238bf06d8';
27
+
28
+ beforeEach(() => {
29
+ vi.clearAllMocks();
30
+ mockEnsureOnDeepSeek.mockResolvedValue(false);
31
+ });
32
+
33
+ it('registers as a cookie-browser read command', () => {
34
+ expect(command).toBeDefined();
35
+ expect(command.browser).toBe(true);
36
+ expect(command.strategy).toBe('cookie');
37
+ expect(command.access).toBe('read');
38
+ expect(command.columns).toEqual(['Role', 'Text']);
39
+ });
40
+
41
+ it('navigates to the conversation URL and returns visible messages', async () => {
42
+ mockGetVisibleMessages.mockResolvedValue([
43
+ { Role: 'user', Text: 'hello' },
44
+ { Role: 'assistant', Text: 'hi' },
45
+ ]);
46
+ const page = { wait: vi.fn().mockResolvedValue(undefined), goto: vi.fn().mockResolvedValue(undefined) };
47
+
48
+ const rows = await command.func(page, { id });
49
+
50
+ expect(rows).toEqual([
51
+ { Role: 'user', Text: 'hello' },
52
+ { Role: 'assistant', Text: 'hi' },
53
+ ]);
54
+ expect(page.goto).toHaveBeenCalledWith(`https://chat.deepseek.com/a/chat/s/${id}`);
55
+ expect(mockGetVisibleMessages).toHaveBeenCalledWith(page);
56
+ });
57
+
58
+ it('accepts a full chat URL and normalises it before navigation', async () => {
59
+ mockGetVisibleMessages.mockResolvedValue([{ Role: 'user', Text: 'hi' }]);
60
+ const page = { wait: vi.fn().mockResolvedValue(undefined), goto: vi.fn().mockResolvedValue(undefined) };
61
+
62
+ await command.func(page, { id: `https://chat.deepseek.com/a/chat/s/${id.toUpperCase()}?ref=foo` });
63
+
64
+ expect(page.goto).toHaveBeenCalledWith(`https://chat.deepseek.com/a/chat/s/${id}`);
65
+ });
66
+
67
+ it('rejects malformed IDs before browser navigation', async () => {
68
+ const page = { wait: vi.fn(), goto: vi.fn() };
69
+
70
+ await expect(command.func(page, { id: 'not-a-uuid' })).rejects.toThrow(ArgumentError);
71
+ expect(page.goto).not.toHaveBeenCalled();
72
+ expect(mockEnsureOnDeepSeek).not.toHaveBeenCalled();
73
+ });
74
+
75
+ it('throws EmptyResultError when the conversation has no visible messages', async () => {
76
+ mockGetVisibleMessages.mockResolvedValue([]);
77
+ const page = { wait: vi.fn().mockResolvedValue(undefined), goto: vi.fn().mockResolvedValue(undefined) };
78
+
79
+ await expect(command.func(page, { id })).rejects.toThrow(EmptyResultError);
80
+ });
81
+ });
@@ -4,10 +4,12 @@ import { DEEPSEEK_DOMAIN, getConversationList } from './utils.js';
4
4
  export const historyCommand = cli({
5
5
  site: 'deepseek',
6
6
  name: 'history',
7
+ access: 'read',
7
8
  description: 'List conversation history from DeepSeek sidebar',
8
9
  domain: DEEPSEEK_DOMAIN,
9
10
  strategy: Strategy.COOKIE,
10
11
  browser: true,
12
+ browserSession: { reuse: 'site' },
11
13
  navigateBefore: false,
12
14
  args: [
13
15
  { name: 'limit', type: 'int', default: 20, help: 'Max conversations to show' },
@@ -4,10 +4,12 @@ import { DEEPSEEK_DOMAIN, DEEPSEEK_URL } from './utils.js';
4
4
  export const newCommand = cli({
5
5
  site: 'deepseek',
6
6
  name: 'new',
7
+ access: 'read',
7
8
  description: 'Start a new conversation in DeepSeek',
8
9
  domain: DEEPSEEK_DOMAIN,
9
10
  strategy: Strategy.COOKIE,
10
11
  browser: true,
12
+ browserSession: { reuse: 'site' },
11
13
  navigateBefore: false,
12
14
  args: [],
13
15
  columns: ['Status'],
@@ -4,10 +4,12 @@ import { DEEPSEEK_DOMAIN, ensureOnDeepSeek, getVisibleMessages } from './utils.j
4
4
  export const readCommand = cli({
5
5
  site: 'deepseek',
6
6
  name: 'read',
7
+ access: 'read',
7
8
  description: 'Read the current DeepSeek conversation',
8
9
  domain: DEEPSEEK_DOMAIN,
9
10
  strategy: Strategy.COOKIE,
10
11
  browser: true,
12
+ browserSession: { reuse: 'site' },
11
13
  navigateBefore: false,
12
14
  args: [],
13
15
  columns: ['Role', 'Text'],