@jackwener/opencli 1.7.11 → 1.7.12

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 (730) hide show
  1. package/README.zh-CN.md +2 -1
  2. package/cli-manifest.json +1417 -24
  3. package/clis/1688/assets.js +1 -0
  4. package/clis/1688/download.js +1 -0
  5. package/clis/1688/item.js +1 -0
  6. package/clis/1688/search.js +2 -1
  7. package/clis/1688/store.js +1 -0
  8. package/clis/36kr/article.js +1 -0
  9. package/clis/36kr/hot.js +1 -0
  10. package/clis/36kr/news.js +1 -0
  11. package/clis/36kr/search.js +1 -0
  12. package/clis/51job/company.js +1 -0
  13. package/clis/51job/detail.js +1 -0
  14. package/clis/51job/hot.js +1 -0
  15. package/clis/51job/search.js +1 -0
  16. package/clis/amazon/bestsellers.js +1 -0
  17. package/clis/amazon/discussion.js +1 -0
  18. package/clis/amazon/movers-shakers.js +1 -0
  19. package/clis/amazon/new-releases.js +1 -0
  20. package/clis/amazon/offer.js +1 -0
  21. package/clis/amazon/product.js +1 -0
  22. package/clis/amazon/rankings.js +1 -0
  23. package/clis/amazon/search.js +1 -0
  24. package/clis/antigravity/dump.js +1 -0
  25. package/clis/antigravity/extract-code.js +1 -0
  26. package/clis/antigravity/model.js +1 -0
  27. package/clis/antigravity/new.js +1 -0
  28. package/clis/antigravity/read.js +1 -0
  29. package/clis/antigravity/send.js +1 -0
  30. package/clis/antigravity/status.js +1 -0
  31. package/clis/antigravity/watch.js +1 -0
  32. package/clis/apple-podcasts/episodes.js +1 -0
  33. package/clis/apple-podcasts/search.js +1 -0
  34. package/clis/apple-podcasts/top.js +1 -0
  35. package/clis/arxiv/arxiv.test.js +112 -0
  36. package/clis/arxiv/paper.js +4 -3
  37. package/clis/arxiv/recent.js +33 -0
  38. package/clis/arxiv/search.js +19 -7
  39. package/clis/arxiv/utils.js +68 -5
  40. package/clis/baidu-scholar/search.js +1 -0
  41. package/clis/band/bands.js +1 -0
  42. package/clis/band/mentions.js +1 -0
  43. package/clis/band/post.js +1 -0
  44. package/clis/band/posts.js +1 -0
  45. package/clis/barchart/flow.js +1 -0
  46. package/clis/barchart/greeks.js +1 -0
  47. package/clis/barchart/options.js +1 -0
  48. package/clis/barchart/quote.js +1 -0
  49. package/clis/bbc/news.js +1 -0
  50. package/clis/bilibili/comments.js +1 -0
  51. package/clis/bilibili/download.js +1 -0
  52. package/clis/bilibili/dynamic.js +1 -0
  53. package/clis/bilibili/favorite.js +1 -0
  54. package/clis/bilibili/feed.js +2 -0
  55. package/clis/bilibili/following.js +1 -0
  56. package/clis/bilibili/history.js +1 -0
  57. package/clis/bilibili/hot.js +6 -1
  58. package/clis/bilibili/hot.test.js +17 -0
  59. package/clis/bilibili/me.js +1 -1
  60. package/clis/bilibili/ranking.js +1 -0
  61. package/clis/bilibili/search.js +1 -1
  62. package/clis/bilibili/subtitle.js +1 -0
  63. package/clis/bilibili/user-videos.js +1 -0
  64. package/clis/bilibili/video.js +1 -0
  65. package/clis/binance/asks.js +1 -0
  66. package/clis/binance/depth.js +1 -0
  67. package/clis/binance/gainers.js +1 -0
  68. package/clis/binance/klines.js +1 -0
  69. package/clis/binance/losers.js +1 -0
  70. package/clis/binance/pairs.js +1 -0
  71. package/clis/binance/price.js +1 -0
  72. package/clis/binance/prices.js +1 -0
  73. package/clis/binance/ticker.js +1 -0
  74. package/clis/binance/top.js +1 -0
  75. package/clis/binance/trades.js +1 -0
  76. package/clis/bloomberg/businessweek.js +1 -0
  77. package/clis/bloomberg/economics.js +1 -0
  78. package/clis/bloomberg/feeds.js +1 -0
  79. package/clis/bloomberg/industries.js +1 -0
  80. package/clis/bloomberg/main.js +1 -0
  81. package/clis/bloomberg/markets.js +1 -0
  82. package/clis/bloomberg/news.js +1 -0
  83. package/clis/bloomberg/opinions.js +1 -0
  84. package/clis/bloomberg/politics.js +1 -0
  85. package/clis/bloomberg/tech.js +1 -0
  86. package/clis/bluesky/feeds.js +1 -0
  87. package/clis/bluesky/followers.js +1 -0
  88. package/clis/bluesky/following.js +1 -0
  89. package/clis/bluesky/profile.js +1 -0
  90. package/clis/bluesky/search.js +1 -0
  91. package/clis/bluesky/starter-packs.js +1 -0
  92. package/clis/bluesky/thread.js +1 -0
  93. package/clis/bluesky/trending.js +1 -0
  94. package/clis/bluesky/user.js +3 -1
  95. package/clis/boss/batchgreet.js +1 -0
  96. package/clis/boss/chatlist.js +1 -0
  97. package/clis/boss/chatmsg.js +1 -0
  98. package/clis/boss/detail.js +1 -0
  99. package/clis/boss/exchange.js +1 -0
  100. package/clis/boss/greet.js +1 -0
  101. package/clis/boss/invite.js +1 -0
  102. package/clis/boss/joblist.js +1 -0
  103. package/clis/boss/mark.js +1 -0
  104. package/clis/boss/recommend.js +1 -0
  105. package/clis/boss/resume.js +1 -0
  106. package/clis/boss/search.js +1 -0
  107. package/clis/boss/send.js +1 -0
  108. package/clis/boss/stats.js +1 -0
  109. package/clis/chaoxing/assignments.js +1 -0
  110. package/clis/chaoxing/exams.js +1 -0
  111. package/clis/chatgpt/image.js +1 -0
  112. package/clis/chatgpt-app/ask.js +1 -0
  113. package/clis/chatgpt-app/model.js +1 -0
  114. package/clis/chatgpt-app/new.js +1 -0
  115. package/clis/chatgpt-app/read.js +1 -0
  116. package/clis/chatgpt-app/send.js +1 -0
  117. package/clis/chatgpt-app/status.js +1 -0
  118. package/clis/chatwise/ask.js +1 -0
  119. package/clis/chatwise/export.js +1 -0
  120. package/clis/chatwise/history.js +1 -0
  121. package/clis/chatwise/model.js +1 -0
  122. package/clis/chatwise/read.js +1 -0
  123. package/clis/chatwise/send.js +1 -0
  124. package/clis/claude/ask.js +1 -0
  125. package/clis/claude/detail.js +1 -0
  126. package/clis/claude/history.js +1 -0
  127. package/clis/claude/new.js +1 -0
  128. package/clis/claude/read.js +1 -0
  129. package/clis/claude/send.js +1 -0
  130. package/clis/claude/status.js +1 -0
  131. package/clis/cnki/search.js +1 -0
  132. package/clis/codex/ask.js +1 -0
  133. package/clis/codex/export.js +1 -0
  134. package/clis/codex/extract-diff.js +1 -0
  135. package/clis/codex/history.js +1 -0
  136. package/clis/codex/model.js +1 -0
  137. package/clis/codex/read.js +1 -0
  138. package/clis/codex/send.js +1 -0
  139. package/clis/coupang/add-to-cart.js +1 -0
  140. package/clis/coupang/search.js +1 -0
  141. package/clis/ctrip/search.js +1 -0
  142. package/clis/cursor/ask.js +1 -0
  143. package/clis/cursor/composer.js +1 -0
  144. package/clis/cursor/export.js +1 -0
  145. package/clis/cursor/extract-code.js +1 -0
  146. package/clis/cursor/history.js +1 -0
  147. package/clis/cursor/model.js +1 -0
  148. package/clis/cursor/read.js +1 -0
  149. package/clis/cursor/send.js +1 -0
  150. package/clis/dblp/dblp.test.js +397 -0
  151. package/clis/dblp/paper.js +40 -0
  152. package/clis/dblp/search.js +45 -0
  153. package/clis/dblp/utils.js +290 -0
  154. package/clis/deepseek/ask.js +1 -0
  155. package/clis/deepseek/history.js +1 -0
  156. package/clis/deepseek/new.js +1 -0
  157. package/clis/deepseek/read.js +1 -0
  158. package/clis/deepseek/status.js +1 -0
  159. package/clis/devto/devto.test.js +236 -0
  160. package/clis/devto/read.js +103 -0
  161. package/clis/devto/tag.js +5 -1
  162. package/clis/devto/top.js +5 -1
  163. package/clis/devto/user.js +5 -1
  164. package/clis/dianping/__fixtures__/search.html +168 -0
  165. package/clis/dianping/__fixtures__/shop.html +6 -0
  166. package/clis/dianping/dianping.test.js +424 -0
  167. package/clis/dianping/search.js +154 -0
  168. package/clis/dianping/shop.js +173 -0
  169. package/clis/dianping/utils.js +157 -0
  170. package/clis/dictionary/examples.js +1 -0
  171. package/clis/dictionary/search.js +1 -0
  172. package/clis/dictionary/synonyms.js +1 -0
  173. package/clis/discord-app/channels.js +1 -0
  174. package/clis/discord-app/delete.js +1 -0
  175. package/clis/discord-app/members.js +1 -0
  176. package/clis/discord-app/read.js +1 -0
  177. package/clis/discord-app/search.js +1 -0
  178. package/clis/discord-app/send.js +1 -0
  179. package/clis/discord-app/servers.js +1 -0
  180. package/clis/discord-app/status.js +1 -0
  181. package/clis/douban/book-hot.js +1 -0
  182. package/clis/douban/download.js +1 -0
  183. package/clis/douban/marks.js +1 -0
  184. package/clis/douban/movie-hot.js +2 -1
  185. package/clis/douban/movie-hot.test.js +14 -0
  186. package/clis/douban/photos.js +2 -1
  187. package/clis/douban/reviews.js +1 -0
  188. package/clis/douban/search.js +1 -0
  189. package/clis/douban/subject.js +1 -0
  190. package/clis/douban/top250.js +1 -0
  191. package/clis/douban/utils.js +11 -13
  192. package/clis/douban/utils.test.js +79 -0
  193. package/clis/doubao/ask.js +1 -0
  194. package/clis/doubao/detail.js +1 -0
  195. package/clis/doubao/history.js +1 -0
  196. package/clis/doubao/meeting-summary.js +1 -0
  197. package/clis/doubao/meeting-transcript.js +1 -0
  198. package/clis/doubao/new.js +1 -0
  199. package/clis/doubao/read.js +1 -0
  200. package/clis/doubao/send.js +1 -0
  201. package/clis/doubao/status.js +1 -0
  202. package/clis/doubao-app/ask.js +1 -0
  203. package/clis/doubao-app/dump.js +1 -0
  204. package/clis/doubao-app/new.js +1 -0
  205. package/clis/doubao-app/read.js +1 -0
  206. package/clis/doubao-app/screenshot.js +1 -0
  207. package/clis/doubao-app/send.js +1 -0
  208. package/clis/doubao-app/status.js +1 -0
  209. package/clis/douyin/activities.js +1 -0
  210. package/clis/douyin/collections.js +1 -0
  211. package/clis/douyin/delete.js +1 -0
  212. package/clis/douyin/draft.js +1 -0
  213. package/clis/douyin/drafts.js +1 -0
  214. package/clis/douyin/hashtag.js +1 -0
  215. package/clis/douyin/location.js +1 -0
  216. package/clis/douyin/profile.js +1 -0
  217. package/clis/douyin/publish.js +1 -0
  218. package/clis/douyin/stats.js +1 -0
  219. package/clis/douyin/update.js +1 -0
  220. package/clis/douyin/user-videos.js +1 -0
  221. package/clis/douyin/videos.js +1 -0
  222. package/clis/eastmoney/announcement.js +1 -0
  223. package/clis/eastmoney/convertible.js +1 -0
  224. package/clis/eastmoney/etf.js +1 -0
  225. package/clis/eastmoney/holders.js +1 -0
  226. package/clis/eastmoney/hot-rank.js +1 -0
  227. package/clis/eastmoney/index-board.js +1 -0
  228. package/clis/eastmoney/kline.js +1 -0
  229. package/clis/eastmoney/kuaixun.js +1 -0
  230. package/clis/eastmoney/longhu.js +1 -0
  231. package/clis/eastmoney/money-flow.js +1 -0
  232. package/clis/eastmoney/northbound.js +1 -0
  233. package/clis/eastmoney/quote.js +1 -0
  234. package/clis/eastmoney/rank.js +1 -0
  235. package/clis/eastmoney/sectors.js +1 -0
  236. package/clis/facebook/add-friend.js +1 -0
  237. package/clis/facebook/events.js +1 -0
  238. package/clis/facebook/feed.js +1 -0
  239. package/clis/facebook/friends.js +1 -0
  240. package/clis/facebook/groups.js +1 -0
  241. package/clis/facebook/join-group.js +1 -0
  242. package/clis/facebook/marketplace-inbox.js +1 -0
  243. package/clis/facebook/marketplace-listings.js +1 -0
  244. package/clis/facebook/memories.js +1 -0
  245. package/clis/facebook/notifications.js +1 -0
  246. package/clis/facebook/profile.js +1 -0
  247. package/clis/facebook/search.js +1 -0
  248. package/clis/gemini/ask.js +1 -0
  249. package/clis/gemini/deep-research-result.js +1 -0
  250. package/clis/gemini/deep-research.js +1 -0
  251. package/clis/gemini/image.js +1 -0
  252. package/clis/gemini/new.js +1 -0
  253. package/clis/gitee/search.js +1 -0
  254. package/clis/gitee/trending.js +1 -0
  255. package/clis/gitee/user.js +1 -0
  256. package/clis/google/news.js +1 -0
  257. package/clis/google/search.js +1 -0
  258. package/clis/google/suggest.js +1 -0
  259. package/clis/google/trends.js +1 -0
  260. package/clis/google-scholar/cite.js +1 -0
  261. package/clis/google-scholar/profile.js +1 -0
  262. package/clis/google-scholar/search.js +1 -0
  263. package/clis/gov-law/recent.js +1 -0
  264. package/clis/gov-law/search.js +1 -0
  265. package/clis/gov-policy/recent.js +1 -0
  266. package/clis/gov-policy/search.js +1 -0
  267. package/clis/grok/ask.js +1 -0
  268. package/clis/grok/image.ts +1 -0
  269. package/clis/hackernews/ask.js +3 -1
  270. package/clis/hackernews/best.js +3 -1
  271. package/clis/hackernews/hackernews.test.js +132 -0
  272. package/clis/hackernews/jobs.js +3 -1
  273. package/clis/hackernews/new.js +3 -1
  274. package/clis/hackernews/read.js +188 -0
  275. package/clis/hackernews/search.js +3 -1
  276. package/clis/hackernews/show.js +3 -1
  277. package/clis/hackernews/top.js +3 -1
  278. package/clis/hackernews/user.js +1 -0
  279. package/clis/hf/top.js +1 -0
  280. package/clis/hupu/detail.js +1 -0
  281. package/clis/hupu/hot.js +3 -1
  282. package/clis/hupu/like.js +1 -0
  283. package/clis/hupu/mentions.js +2 -1
  284. package/clis/hupu/reply.js +1 -0
  285. package/clis/hupu/search.js +3 -1
  286. package/clis/hupu/unlike.js +1 -0
  287. package/clis/imdb/person.js +1 -0
  288. package/clis/imdb/reviews.js +1 -0
  289. package/clis/imdb/search.js +1 -0
  290. package/clis/imdb/title.js +1 -0
  291. package/clis/imdb/top.js +1 -0
  292. package/clis/imdb/trending.js +1 -0
  293. package/clis/indeed/indeed.test.js +375 -0
  294. package/clis/indeed/job.js +86 -0
  295. package/clis/indeed/search.js +110 -0
  296. package/clis/indeed/utils.js +152 -0
  297. package/clis/instagram/collection-create.js +1 -0
  298. package/clis/instagram/collection-delete.js +1 -0
  299. package/clis/instagram/comment.js +1 -0
  300. package/clis/instagram/download.js +1 -0
  301. package/clis/instagram/explore.js +1 -0
  302. package/clis/instagram/follow.js +1 -0
  303. package/clis/instagram/followers.js +1 -0
  304. package/clis/instagram/following.js +1 -0
  305. package/clis/instagram/like.js +1 -0
  306. package/clis/instagram/note.js +1 -0
  307. package/clis/instagram/post.js +1 -0
  308. package/clis/instagram/profile.js +1 -0
  309. package/clis/instagram/reel.js +1 -0
  310. package/clis/instagram/save.js +1 -0
  311. package/clis/instagram/saved.js +1 -0
  312. package/clis/instagram/search.js +1 -0
  313. package/clis/instagram/story.js +1 -0
  314. package/clis/instagram/unfollow.js +1 -0
  315. package/clis/instagram/unlike.js +1 -0
  316. package/clis/instagram/unsave.js +1 -0
  317. package/clis/instagram/user.js +1 -0
  318. package/clis/jd/add-cart.js +1 -0
  319. package/clis/jd/cart.js +1 -0
  320. package/clis/jd/detail.js +1 -0
  321. package/clis/jd/item.js +1 -0
  322. package/clis/jd/reviews.js +1 -0
  323. package/clis/jd/search.js +1 -0
  324. package/clis/jianyu/detail.js +1 -0
  325. package/clis/jianyu/search.js +1 -0
  326. package/clis/jike/comment.js +1 -0
  327. package/clis/jike/create.js +1 -0
  328. package/clis/jike/feed.js +3 -1
  329. package/clis/jike/like.js +1 -0
  330. package/clis/jike/notifications.js +1 -0
  331. package/clis/jike/post.js +1 -0
  332. package/clis/jike/repost.js +1 -0
  333. package/clis/jike/search.js +3 -1
  334. package/clis/jike/topic.js +1 -0
  335. package/clis/jike/user.js +3 -1
  336. package/clis/jimeng/generate.js +1 -0
  337. package/clis/jimeng/history.js +1 -0
  338. package/clis/jimeng/new.js +1 -0
  339. package/clis/jimeng/workspaces.js +1 -0
  340. package/clis/ke/chengjiao.js +1 -0
  341. package/clis/ke/ershoufang.js +1 -0
  342. package/clis/ke/xiaoqu.js +1 -0
  343. package/clis/ke/zufang.js +1 -0
  344. package/clis/lesswrong/comments.js +1 -0
  345. package/clis/lesswrong/curated.js +1 -0
  346. package/clis/lesswrong/frontpage.js +1 -0
  347. package/clis/lesswrong/new.js +1 -0
  348. package/clis/lesswrong/read.js +1 -0
  349. package/clis/lesswrong/sequences.js +1 -0
  350. package/clis/lesswrong/shortform.js +1 -0
  351. package/clis/lesswrong/tag.js +1 -0
  352. package/clis/lesswrong/tags.js +1 -0
  353. package/clis/lesswrong/top-month.js +1 -0
  354. package/clis/lesswrong/top-week.js +1 -0
  355. package/clis/lesswrong/top-year.js +1 -0
  356. package/clis/lesswrong/top.js +1 -0
  357. package/clis/lesswrong/user-posts.js +1 -0
  358. package/clis/lesswrong/user.js +1 -0
  359. package/clis/linkedin/search.js +1 -0
  360. package/clis/linkedin/timeline.js +1 -0
  361. package/clis/linux-do/categories.js +1 -0
  362. package/clis/linux-do/category.js +1 -0
  363. package/clis/linux-do/feed.js +1 -0
  364. package/clis/linux-do/hot.js +1 -0
  365. package/clis/linux-do/latest.js +1 -0
  366. package/clis/linux-do/search.js +1 -0
  367. package/clis/linux-do/tags.js +2 -1
  368. package/clis/linux-do/topic-content.js +1 -0
  369. package/clis/linux-do/topic.js +1 -0
  370. package/clis/linux-do/user-posts.js +1 -0
  371. package/clis/linux-do/user-topics.js +1 -0
  372. package/clis/lobsters/active.js +4 -1
  373. package/clis/lobsters/hot.js +4 -1
  374. package/clis/lobsters/lobsters.test.js +169 -0
  375. package/clis/lobsters/newest.js +4 -1
  376. package/clis/lobsters/read.js +196 -0
  377. package/clis/lobsters/tag.js +4 -1
  378. package/clis/maimai/search-talents.js +1 -0
  379. package/clis/medium/feed.js +1 -0
  380. package/clis/medium/search.js +1 -0
  381. package/clis/medium/user.js +1 -0
  382. package/clis/mubu/doc.js +1 -0
  383. package/clis/mubu/docs.js +1 -0
  384. package/clis/mubu/notes.js +1 -0
  385. package/clis/mubu/recent.js +1 -0
  386. package/clis/mubu/search.js +1 -0
  387. package/clis/notebooklm/current.js +1 -0
  388. package/clis/notebooklm/get.js +1 -0
  389. package/clis/notebooklm/history.js +1 -0
  390. package/clis/notebooklm/list.js +1 -0
  391. package/clis/notebooklm/note-list.js +1 -0
  392. package/clis/notebooklm/notes-get.js +1 -0
  393. package/clis/notebooklm/open.js +1 -0
  394. package/clis/notebooklm/source-fulltext.js +1 -0
  395. package/clis/notebooklm/source-get.js +1 -0
  396. package/clis/notebooklm/source-guide.js +1 -0
  397. package/clis/notebooklm/source-list.js +1 -0
  398. package/clis/notebooklm/status.js +1 -0
  399. package/clis/notebooklm/summary.js +1 -0
  400. package/clis/notion/export.js +1 -0
  401. package/clis/notion/favorites.js +1 -0
  402. package/clis/notion/new.js +1 -0
  403. package/clis/notion/read.js +1 -0
  404. package/clis/notion/search.js +1 -0
  405. package/clis/notion/sidebar.js +1 -0
  406. package/clis/notion/status.js +1 -0
  407. package/clis/notion/write.js +1 -0
  408. package/clis/nowcoder/companies.js +1 -0
  409. package/clis/nowcoder/creators.js +1 -0
  410. package/clis/nowcoder/detail.js +1 -0
  411. package/clis/nowcoder/experience.js +1 -0
  412. package/clis/nowcoder/hot.js +1 -0
  413. package/clis/nowcoder/jobs.js +1 -0
  414. package/clis/nowcoder/notifications.js +1 -0
  415. package/clis/nowcoder/papers.js +1 -0
  416. package/clis/nowcoder/practice.js +1 -0
  417. package/clis/nowcoder/recommend.js +1 -0
  418. package/clis/nowcoder/referral.js +1 -0
  419. package/clis/nowcoder/salary.js +1 -0
  420. package/clis/nowcoder/search.js +1 -0
  421. package/clis/nowcoder/suggest.js +1 -0
  422. package/clis/nowcoder/topics.js +1 -0
  423. package/clis/nowcoder/trending.js +1 -0
  424. package/clis/ones/login.js +1 -0
  425. package/clis/ones/logout.js +1 -0
  426. package/clis/ones/me.js +1 -0
  427. package/clis/ones/my-tasks.js +1 -0
  428. package/clis/ones/task.js +1 -0
  429. package/clis/ones/tasks.js +1 -0
  430. package/clis/ones/token-info.js +1 -0
  431. package/clis/ones/worklog.js +1 -0
  432. package/clis/openreview/openreview.test.js +345 -0
  433. package/clis/openreview/paper.js +43 -0
  434. package/clis/openreview/reviews.js +131 -0
  435. package/clis/openreview/search.js +46 -0
  436. package/clis/openreview/utils.js +158 -0
  437. package/clis/openreview/venue.js +63 -0
  438. package/clis/paperreview/feedback.js +1 -0
  439. package/clis/paperreview/review.js +1 -0
  440. package/clis/paperreview/submit.js +1 -0
  441. package/clis/pixiv/detail.js +1 -0
  442. package/clis/pixiv/download.js +1 -0
  443. package/clis/pixiv/illusts.js +2 -1
  444. package/clis/pixiv/ranking.js +2 -1
  445. package/clis/pixiv/search.js +2 -1
  446. package/clis/pixiv/user.js +2 -0
  447. package/clis/powerchina/search.js +1 -0
  448. package/clis/producthunt/browse.js +1 -0
  449. package/clis/producthunt/hot.js +1 -0
  450. package/clis/producthunt/posts.js +1 -0
  451. package/clis/producthunt/today.js +1 -0
  452. package/clis/quark/ls.js +1 -0
  453. package/clis/quark/mkdir.js +1 -0
  454. package/clis/quark/mv.js +1 -0
  455. package/clis/quark/rename.js +1 -0
  456. package/clis/quark/rm.js +1 -0
  457. package/clis/quark/save.js +1 -0
  458. package/clis/quark/share-tree.js +1 -0
  459. package/clis/reddit/comment.js +1 -0
  460. package/clis/reddit/frontpage.js +1 -0
  461. package/clis/reddit/hot.js +6 -1
  462. package/clis/reddit/hot.test.js +18 -0
  463. package/clis/reddit/popular.js +1 -0
  464. package/clis/reddit/read.js +1 -0
  465. package/clis/reddit/save.js +1 -0
  466. package/clis/reddit/saved.js +1 -0
  467. package/clis/reddit/search.js +1 -0
  468. package/clis/reddit/subreddit.js +1 -0
  469. package/clis/reddit/subscribe.js +1 -0
  470. package/clis/reddit/upvote.js +1 -0
  471. package/clis/reddit/upvoted.js +1 -0
  472. package/clis/reddit/user-comments.js +1 -0
  473. package/clis/reddit/user-posts.js +1 -0
  474. package/clis/reddit/user.js +1 -0
  475. package/clis/reuters/search.js +1 -0
  476. package/clis/sinablog/article.js +1 -0
  477. package/clis/sinablog/hot.js +1 -0
  478. package/clis/sinablog/search.js +1 -0
  479. package/clis/sinablog/user.js +1 -0
  480. package/clis/sinafinance/news.js +1 -0
  481. package/clis/sinafinance/rolling-news.js +1 -0
  482. package/clis/sinafinance/stock-rank.js +1 -0
  483. package/clis/sinafinance/stock.js +1 -0
  484. package/clis/smzdm/search.js +1 -0
  485. package/clis/spotify/spotify.js +11 -0
  486. package/clis/stackoverflow/bounties.js +11 -3
  487. package/clis/stackoverflow/hot.js +10 -2
  488. package/clis/stackoverflow/read.js +314 -0
  489. package/clis/stackoverflow/search.js +10 -2
  490. package/clis/stackoverflow/stackoverflow.test.js +346 -0
  491. package/clis/stackoverflow/unanswered.js +9 -2
  492. package/clis/steam/top-sellers.js +1 -0
  493. package/clis/substack/feed.js +1 -0
  494. package/clis/substack/publication.js +1 -0
  495. package/clis/substack/search.js +1 -0
  496. package/clis/taobao/add-cart.js +1 -0
  497. package/clis/taobao/cart.js +1 -0
  498. package/clis/taobao/detail.js +1 -0
  499. package/clis/taobao/reviews.js +1 -0
  500. package/clis/taobao/search.js +1 -0
  501. package/clis/tdx/hot-rank.js +1 -0
  502. package/clis/ths/hot-rank.js +1 -0
  503. package/clis/tieba/hot.js +2 -1
  504. package/clis/tieba/posts.js +1 -0
  505. package/clis/tieba/read.js +1 -0
  506. package/clis/tieba/search.js +2 -1
  507. package/clis/tiktok/comment.js +1 -0
  508. package/clis/tiktok/explore.js +1 -0
  509. package/clis/tiktok/follow.js +1 -0
  510. package/clis/tiktok/following.js +1 -0
  511. package/clis/tiktok/friends.js +1 -0
  512. package/clis/tiktok/like.js +1 -0
  513. package/clis/tiktok/live.js +1 -0
  514. package/clis/tiktok/notifications.js +1 -0
  515. package/clis/tiktok/profile.js +1 -0
  516. package/clis/tiktok/save.js +1 -0
  517. package/clis/tiktok/search.js +1 -0
  518. package/clis/tiktok/unfollow.js +1 -0
  519. package/clis/tiktok/unlike.js +1 -0
  520. package/clis/tiktok/unsave.js +1 -0
  521. package/clis/tiktok/user.js +1 -0
  522. package/clis/toutiao/articles.js +1 -0
  523. package/clis/twitter/accept.js +1 -0
  524. package/clis/twitter/article.js +1 -0
  525. package/clis/twitter/block.js +1 -0
  526. package/clis/twitter/bookmark.js +1 -0
  527. package/clis/twitter/bookmarks.js +2 -1
  528. package/clis/twitter/delete.js +1 -0
  529. package/clis/twitter/download.js +1 -0
  530. package/clis/twitter/follow.js +1 -0
  531. package/clis/twitter/followers.js +1 -0
  532. package/clis/twitter/following.js +1 -0
  533. package/clis/twitter/hide-reply.js +1 -0
  534. package/clis/twitter/like.js +1 -0
  535. package/clis/twitter/likes.js +2 -1
  536. package/clis/twitter/list-add.js +1 -0
  537. package/clis/twitter/list-remove.js +1 -0
  538. package/clis/twitter/list-tweets.js +1 -0
  539. package/clis/twitter/lists.js +1 -0
  540. package/clis/twitter/notifications.js +1 -0
  541. package/clis/twitter/post.js +1 -0
  542. package/clis/twitter/profile.js +1 -0
  543. package/clis/twitter/reply-dm.js +1 -0
  544. package/clis/twitter/reply.js +1 -0
  545. package/clis/twitter/search.js +1 -0
  546. package/clis/twitter/thread.js +1 -0
  547. package/clis/twitter/timeline.js +1 -0
  548. package/clis/twitter/trending.js +11 -12
  549. package/clis/twitter/trending.test.js +15 -0
  550. package/clis/twitter/tweets.js +2 -1
  551. package/clis/twitter/tweets.test.js +2 -2
  552. package/clis/twitter/unblock.js +1 -0
  553. package/clis/twitter/unbookmark.js +1 -0
  554. package/clis/twitter/unfollow.js +1 -0
  555. package/clis/uiverse/code.js +1 -0
  556. package/clis/uiverse/preview.js +1 -0
  557. package/clis/v2ex/daily.js +1 -0
  558. package/clis/v2ex/hot.js +1 -0
  559. package/clis/v2ex/latest.js +1 -0
  560. package/clis/v2ex/me.js +1 -0
  561. package/clis/v2ex/member.js +1 -0
  562. package/clis/v2ex/node.js +1 -0
  563. package/clis/v2ex/nodes.js +1 -0
  564. package/clis/v2ex/notifications.js +1 -0
  565. package/clis/v2ex/replies.js +1 -0
  566. package/clis/v2ex/topic.js +1 -0
  567. package/clis/v2ex/user.js +1 -0
  568. package/clis/wanfang/search.js +1 -0
  569. package/clis/web/read.js +1 -0
  570. package/clis/weibo/comments.js +1 -0
  571. package/clis/weibo/favorites.js +1 -0
  572. package/clis/weibo/feed.js +3 -1
  573. package/clis/weibo/hot.js +1 -0
  574. package/clis/weibo/me.js +1 -0
  575. package/clis/weibo/post.js +1 -0
  576. package/clis/weibo/publish.js +1 -0
  577. package/clis/weibo/search.js +8 -2
  578. package/clis/weibo/user.js +1 -0
  579. package/clis/weixin/create-draft.js +1 -0
  580. package/clis/weixin/download.js +1 -0
  581. package/clis/weixin/drafts.js +1 -0
  582. package/clis/weread/ai-outline.js +1 -0
  583. package/clis/weread/book.js +1 -0
  584. package/clis/weread/highlights.js +1 -0
  585. package/clis/weread/notebooks.js +1 -0
  586. package/clis/weread/notes.js +1 -0
  587. package/clis/weread/ranking.js +1 -0
  588. package/clis/weread/search.js +1 -0
  589. package/clis/weread/shelf.js +1 -0
  590. package/clis/wikipedia/random.js +1 -0
  591. package/clis/wikipedia/search.js +1 -0
  592. package/clis/wikipedia/summary.js +1 -0
  593. package/clis/wikipedia/trending.js +1 -0
  594. package/clis/xianyu/chat.js +1 -0
  595. package/clis/xianyu/item.js +1 -0
  596. package/clis/xianyu/search.js +1 -0
  597. package/clis/xiaoe/catalog.js +2 -1
  598. package/clis/xiaoe/content.js +1 -0
  599. package/clis/xiaoe/courses.js +1 -0
  600. package/clis/xiaoe/detail.js +1 -0
  601. package/clis/xiaoe/play-url.js +1 -0
  602. package/clis/xiaohongshu/comments.js +1 -0
  603. package/clis/xiaohongshu/creator-note-detail.js +1 -0
  604. package/clis/xiaohongshu/creator-notes-summary.js +1 -0
  605. package/clis/xiaohongshu/creator-notes.js +1 -0
  606. package/clis/xiaohongshu/creator-profile.js +1 -0
  607. package/clis/xiaohongshu/creator-stats.js +1 -0
  608. package/clis/xiaohongshu/download.js +1 -0
  609. package/clis/xiaohongshu/feed.js +2 -1
  610. package/clis/xiaohongshu/note.js +1 -0
  611. package/clis/xiaohongshu/notifications.js +1 -0
  612. package/clis/xiaohongshu/publish.js +1 -0
  613. package/clis/xiaohongshu/search.js +1 -0
  614. package/clis/xiaohongshu/user.js +1 -0
  615. package/clis/xiaoyuzhou/download.js +1 -0
  616. package/clis/xiaoyuzhou/episode.js +1 -0
  617. package/clis/xiaoyuzhou/podcast-episodes.js +1 -0
  618. package/clis/xiaoyuzhou/podcast.js +1 -0
  619. package/clis/xiaoyuzhou/transcript.js +1 -0
  620. package/clis/xueqiu/comments.js +1 -0
  621. package/clis/xueqiu/earnings-date.js +1 -0
  622. package/clis/xueqiu/feed.js +1 -0
  623. package/clis/xueqiu/fund-holdings.js +1 -0
  624. package/clis/xueqiu/fund-snapshot.js +1 -0
  625. package/clis/xueqiu/groups.js +1 -0
  626. package/clis/xueqiu/hot-stock.js +1 -0
  627. package/clis/xueqiu/hot.js +1 -0
  628. package/clis/xueqiu/kline.js +1 -0
  629. package/clis/xueqiu/search.js +1 -0
  630. package/clis/xueqiu/stock.js +1 -0
  631. package/clis/xueqiu/watchlist.js +1 -0
  632. package/clis/yahoo-finance/quote.js +1 -0
  633. package/clis/yollomi/background.js +1 -0
  634. package/clis/yollomi/edit.js +1 -0
  635. package/clis/yollomi/face-swap.js +1 -0
  636. package/clis/yollomi/generate.js +1 -0
  637. package/clis/yollomi/models.js +1 -0
  638. package/clis/yollomi/object-remover.js +1 -0
  639. package/clis/yollomi/remove-bg.js +1 -0
  640. package/clis/yollomi/restore.js +1 -0
  641. package/clis/yollomi/try-on.js +1 -0
  642. package/clis/yollomi/upload.js +1 -0
  643. package/clis/yollomi/upscale.js +1 -0
  644. package/clis/yollomi/video.js +1 -0
  645. package/clis/youtube/channel.js +1 -0
  646. package/clis/youtube/comments.js +1 -0
  647. package/clis/youtube/feed.js +8 -7
  648. package/clis/youtube/feed.test.js +131 -0
  649. package/clis/youtube/history.js +1 -0
  650. package/clis/youtube/like.js +1 -0
  651. package/clis/youtube/playlist.js +1 -0
  652. package/clis/youtube/search.js +1 -0
  653. package/clis/youtube/subscribe.js +1 -0
  654. package/clis/youtube/subscriptions.js +1 -0
  655. package/clis/youtube/transcript.js +1 -0
  656. package/clis/youtube/unlike.js +1 -0
  657. package/clis/youtube/unsubscribe.js +1 -0
  658. package/clis/youtube/video.js +1 -0
  659. package/clis/youtube/watch-later.js +1 -0
  660. package/clis/yuanbao/ask.js +1 -0
  661. package/clis/yuanbao/new.js +1 -0
  662. package/clis/zhihu/answer.js +1 -0
  663. package/clis/zhihu/collection.js +1 -0
  664. package/clis/zhihu/collections.js +1 -0
  665. package/clis/zhihu/comment.js +1 -0
  666. package/clis/zhihu/download.js +1 -0
  667. package/clis/zhihu/favorite.js +1 -0
  668. package/clis/zhihu/follow.js +1 -0
  669. package/clis/zhihu/hot.js +1 -0
  670. package/clis/zhihu/like.js +1 -0
  671. package/clis/zhihu/question.js +1 -0
  672. package/clis/zhihu/search.js +1 -0
  673. package/clis/zlibrary/info.js +1 -0
  674. package/clis/zlibrary/search.js +1 -0
  675. package/clis/zsxq/dynamics.js +1 -0
  676. package/clis/zsxq/groups.js +1 -0
  677. package/clis/zsxq/search.js +1 -0
  678. package/clis/zsxq/topic.js +1 -0
  679. package/clis/zsxq/topics.js +1 -0
  680. package/dist/src/adapter-source.test.js +1 -1
  681. package/dist/src/browser/analyze.test.js +2 -0
  682. package/dist/src/browser/base-page.d.ts +9 -0
  683. package/dist/src/browser/base-page.js +72 -3
  684. package/dist/src/browser/base-page.test.js +42 -0
  685. package/dist/src/browser/cdp.js +6 -0
  686. package/dist/src/browser/cdp.test.js +3 -0
  687. package/dist/src/browser/page.d.ts +1 -0
  688. package/dist/src/browser/page.js +6 -0
  689. package/dist/src/browser/page.test.js +17 -0
  690. package/dist/src/browser/target-resolver.d.ts +10 -3
  691. package/dist/src/browser/target-resolver.js +16 -10
  692. package/dist/src/browser/verify-fixture.d.ts +6 -1
  693. package/dist/src/browser/verify-fixture.js +87 -0
  694. package/dist/src/browser/verify-fixture.test.js +44 -1
  695. package/dist/src/build-manifest.js +3 -0
  696. package/dist/src/build-manifest.test.js +18 -12
  697. package/dist/src/capabilityRouting.test.js +1 -1
  698. package/dist/src/cli.js +141 -5
  699. package/dist/src/cli.test.js +179 -0
  700. package/dist/src/commanderAdapter.d.ts +1 -1
  701. package/dist/src/commanderAdapter.js +17 -7
  702. package/dist/src/commanderAdapter.test.js +7 -6
  703. package/dist/src/convention-audit.d.ts +50 -0
  704. package/dist/src/convention-audit.js +546 -0
  705. package/dist/src/convention-audit.test.d.ts +1 -0
  706. package/dist/src/convention-audit.test.js +226 -0
  707. package/dist/src/discovery.js +2 -0
  708. package/dist/src/doctor.js +0 -1
  709. package/dist/src/doctor.test.js +1 -1
  710. package/dist/src/engine.test.js +10 -10
  711. package/dist/src/execution.js +1 -1
  712. package/dist/src/execution.test.js +9 -9
  713. package/dist/src/help.d.ts +15 -0
  714. package/dist/src/help.js +149 -0
  715. package/dist/src/main.js +13 -7
  716. package/dist/src/manifest-types.d.ts +2 -0
  717. package/dist/src/plugin.test.js +26 -26
  718. package/dist/src/registry.d.ts +5 -0
  719. package/dist/src/registry.js +8 -0
  720. package/dist/src/registry.test.js +27 -20
  721. package/dist/src/serialization.d.ts +4 -0
  722. package/dist/src/serialization.js +27 -1
  723. package/dist/src/serialization.test.js +24 -2
  724. package/dist/src/types.d.ts +2 -0
  725. package/package.json +4 -1
  726. package/scripts/check-listing-id-pairing.mjs +193 -0
  727. package/scripts/check-silent-column-drop.mjs +105 -0
  728. package/scripts/check-typed-error-lint.mjs +118 -0
  729. package/scripts/silent-column-drop-baseline.json +962 -0
  730. package/scripts/typed-error-lint-baseline.json +1586 -0
@@ -183,6 +183,7 @@ export async function extractAssetsForInput(page, input) {
183
183
  cli({
184
184
  site: '1688',
185
185
  name: 'assets',
186
+ access: 'read',
186
187
  description: '列出 1688 商品页可提取的图片/视频素材',
187
188
  domain: 'www.1688.com',
188
189
  strategy: Strategy.COOKIE,
@@ -42,6 +42,7 @@ function toDownloadItems(offerId, assets) {
42
42
  cli({
43
43
  site: '1688',
44
44
  name: 'download',
45
+ access: 'read',
45
46
  description: '批量下载 1688 商品页可提取的图片和视频素材',
46
47
  domain: 'www.1688.com',
47
48
  strategy: Strategy.COOKIE,
package/clis/1688/item.js CHANGED
@@ -156,6 +156,7 @@ async function readItemPayload(page, itemUrl) {
156
156
  cli({
157
157
  site: '1688',
158
158
  name: 'item',
159
+ access: 'read',
159
160
  description: '1688 商品详情(公开商品字段、价格阶梯、卖家基础信息)',
160
161
  domain: 'www.1688.com',
161
162
  strategy: Strategy.COOKIE,
@@ -275,6 +275,7 @@ async function collectSearchRows(page, query, limit) {
275
275
  cli({
276
276
  site: '1688',
277
277
  name: 'search',
278
+ access: 'read',
278
279
  description: '1688 商品搜索(结果候选、卖家链接、价格/MOQ/销量文本)',
279
280
  domain: 'www.1688.com',
280
281
  strategy: Strategy.COOKIE,
@@ -293,7 +294,7 @@ cli({
293
294
  help: `结果数量上限(默认 ${SEARCH_LIMIT_DEFAULT},最大 ${SEARCH_LIMIT_MAX})`,
294
295
  },
295
296
  ],
296
- columns: ['rank', 'title', 'price_text', 'moq_text', 'seller_name', 'location'],
297
+ columns: ['rank', 'offer_id', 'title', 'item_url', 'price_text', 'moq_text', 'seller_name', 'member_id', 'location'],
297
298
  func: async (page, kwargs) => {
298
299
  const query = String(kwargs.query ?? '');
299
300
  const limit = parseSearchLimit(kwargs.limit);
@@ -167,6 +167,7 @@ function hasAnyEvidence(storePayload, contactPayload, seed) {
167
167
  cli({
168
168
  site: '1688',
169
169
  name: 'store',
170
+ access: 'read',
170
171
  description: '1688 店铺/供应商公开信息(联系方式、主营、入驻年限、公开服务信号)',
171
172
  domain: 'www.1688.com',
172
173
  strategy: Strategy.COOKIE,
@@ -13,6 +13,7 @@ function parseArticleId(input) {
13
13
  cli({
14
14
  site: '36kr',
15
15
  name: 'article',
16
+ access: 'read',
16
17
  description: '获取36氪文章正文内容',
17
18
  domain: 'www.36kr.com',
18
19
  strategy: Strategy.INTERCEPT,
package/clis/36kr/hot.js CHANGED
@@ -26,6 +26,7 @@ function buildHotListUrl(listType, date = new Date()) {
26
26
  cli({
27
27
  site: '36kr',
28
28
  name: 'hot',
29
+ access: 'read',
29
30
  description: '36氪热榜 — trending articles (renqi/zonghe/shoucang/catalog)',
30
31
  domain: 'www.36kr.com',
31
32
  strategy: Strategy.PUBLIC,
package/clis/36kr/news.js CHANGED
@@ -5,6 +5,7 @@ import { cli, Strategy } from '@jackwener/opencli/registry';
5
5
  cli({
6
6
  site: '36kr',
7
7
  name: 'news',
8
+ access: 'read',
8
9
  description: 'Latest tech/startup news from 36kr (36氪)',
9
10
  domain: 'www.36kr.com',
10
11
  strategy: Strategy.PUBLIC,
@@ -8,6 +8,7 @@ import { CliError } from '@jackwener/opencli/errors';
8
8
  cli({
9
9
  site: '36kr',
10
10
  name: 'search',
11
+ access: 'read',
11
12
  description: '搜索36氪文章',
12
13
  domain: 'www.36kr.com',
13
14
  strategy: Strategy.PUBLIC,
@@ -13,6 +13,7 @@ import { JOBS_ORIGIN, requirePage, navigateTo, parseCompanyJobCard } from './uti
13
13
  cli({
14
14
  site: '51job',
15
15
  name: 'company',
16
+ access: 'read',
16
17
  description: '51job 公司简介 + 在招职位(按 encCoId)',
17
18
  domain: 'jobs.51job.com',
18
19
  strategy: Strategy.COOKIE,
@@ -13,6 +13,7 @@ import { JOBS_ORIGIN, requirePage, navigateTo } from './utils.js';
13
13
  cli({
14
14
  site: '51job',
15
15
  name: 'detail',
16
+ access: 'read',
16
17
  description: '51job 职位详情(按 jobId)',
17
18
  domain: 'jobs.51job.com',
18
19
  strategy: Strategy.COOKIE,
package/clis/51job/hot.js CHANGED
@@ -16,6 +16,7 @@ import {
16
16
  cli({
17
17
  site: '51job',
18
18
  name: 'hot',
19
+ access: 'read',
19
20
  description: '51job 推荐职位(按城市/行业/排序浏览)',
20
21
  domain: 'we.51job.com',
21
22
  strategy: Strategy.COOKIE,
@@ -20,6 +20,7 @@ import {
20
20
  cli({
21
21
  site: '51job',
22
22
  name: 'search',
23
+ access: 'read',
23
24
  description: '51job 前程无忧关键词职位搜索',
24
25
  domain: 'we.51job.com',
25
26
  strategy: Strategy.COOKIE,
@@ -2,6 +2,7 @@ import { cli } from '@jackwener/opencli/registry';
2
2
  import { createRankingCliOptions } from './rankings.js';
3
3
  cli(createRankingCliOptions({
4
4
  commandName: 'bestsellers',
5
+ access: 'read',
5
6
  listType: 'bestsellers',
6
7
  description: 'Amazon Best Sellers pages for category candidate discovery',
7
8
  }));
@@ -85,6 +85,7 @@ async function readDiscussionPayload(page, input, limit) {
85
85
  cli({
86
86
  site: 'amazon',
87
87
  name: 'discussion',
88
+ access: 'read',
88
89
  description: 'Amazon review summary and sample customer discussion from product review pages',
89
90
  domain: 'amazon.com',
90
91
  strategy: Strategy.COOKIE,
@@ -2,6 +2,7 @@ import { cli } from '@jackwener/opencli/registry';
2
2
  import { createRankingCliOptions } from './rankings.js';
3
3
  cli(createRankingCliOptions({
4
4
  commandName: 'movers-shakers',
5
+ access: 'read',
5
6
  listType: 'movers_shakers',
6
7
  description: 'Amazon Movers & Shakers pages for short-term growth signals',
7
8
  }));
@@ -2,6 +2,7 @@ import { cli } from '@jackwener/opencli/registry';
2
2
  import { createRankingCliOptions } from './rankings.js';
3
3
  cli(createRankingCliOptions({
4
4
  commandName: 'new-releases',
5
+ access: 'read',
5
6
  listType: 'new_releases',
6
7
  description: 'Amazon New Releases pages for early momentum discovery',
7
8
  }));
@@ -106,6 +106,7 @@ async function readOfferPayload(page, input) {
106
106
  cli({
107
107
  site: 'amazon',
108
108
  name: 'offer',
109
+ access: 'read',
109
110
  description: 'Amazon seller, buy box, and fulfillment facts from the product page',
110
111
  domain: 'amazon.com',
111
112
  strategy: Strategy.COOKIE,
@@ -65,6 +65,7 @@ async function readProductPayload(page, input) {
65
65
  cli({
66
66
  site: 'amazon',
67
67
  name: 'product',
68
+ access: 'read',
68
69
  description: 'Amazon product page facts for candidate validation',
69
70
  domain: 'amazon.com',
70
71
  strategy: Strategy.COOKIE,
@@ -142,6 +142,7 @@ export function createRankingCliOptions(definition) {
142
142
  return {
143
143
  site: 'amazon',
144
144
  name: definition.commandName,
145
+ access: definition.access ?? 'read',
145
146
  description: definition.description,
146
147
  domain: 'amazon.com',
147
148
  strategy: Strategy.COOKIE,
@@ -49,6 +49,7 @@ async function readSearchPayload(page, query) {
49
49
  cli({
50
50
  site: 'amazon',
51
51
  name: 'search',
52
+ access: 'read',
52
53
  description: 'Amazon search results for product discovery and coarse filtering',
53
54
  domain: 'amazon.com',
54
55
  strategy: Strategy.COOKIE,
@@ -3,6 +3,7 @@ import * as fs from 'node:fs';
3
3
  export const dumpCommand = cli({
4
4
  site: 'antigravity',
5
5
  name: 'dump',
6
+ access: 'read',
6
7
  description: 'Dump the DOM to help AI understand the UI',
7
8
  domain: 'localhost',
8
9
  strategy: Strategy.UI,
@@ -2,6 +2,7 @@ import { cli, Strategy } from '@jackwener/opencli/registry';
2
2
  export const extractCodeCommand = cli({
3
3
  site: 'antigravity',
4
4
  name: 'extract-code',
5
+ access: 'read',
5
6
  description: 'Extract multi-line code blocks from the current Antigravity conversation',
6
7
  domain: 'localhost',
7
8
  strategy: Strategy.UI,
@@ -2,6 +2,7 @@ import { cli, Strategy } from '@jackwener/opencli/registry';
2
2
  export const modelCommand = cli({
3
3
  site: 'antigravity',
4
4
  name: 'model',
5
+ access: 'read',
5
6
  description: 'Switch the active LLM model in Antigravity',
6
7
  domain: 'localhost',
7
8
  strategy: Strategy.UI,
@@ -2,6 +2,7 @@ import { cli, Strategy } from '@jackwener/opencli/registry';
2
2
  export const newCommand = cli({
3
3
  site: 'antigravity',
4
4
  name: 'new',
5
+ access: 'read',
5
6
  description: 'Start a new conversation / clear context in Antigravity',
6
7
  domain: 'localhost',
7
8
  strategy: Strategy.UI,
@@ -2,6 +2,7 @@ import { cli, Strategy } from '@jackwener/opencli/registry';
2
2
  export const readCommand = cli({
3
3
  site: 'antigravity',
4
4
  name: 'read',
5
+ access: 'read',
5
6
  description: 'Read the latest chat messages from Antigravity AI',
6
7
  domain: 'localhost',
7
8
  strategy: Strategy.UI,
@@ -2,6 +2,7 @@ import { cli, Strategy } from '@jackwener/opencli/registry';
2
2
  export const sendCommand = cli({
3
3
  site: 'antigravity',
4
4
  name: 'send',
5
+ access: 'write',
5
6
  description: 'Send a message to Antigravity AI via the internal Lexical editor',
6
7
  domain: 'localhost',
7
8
  strategy: Strategy.UI,
@@ -2,6 +2,7 @@ import { cli, Strategy } from '@jackwener/opencli/registry';
2
2
  export const statusCommand = cli({
3
3
  site: 'antigravity',
4
4
  name: 'status',
5
+ access: 'read',
5
6
  description: 'Check Antigravity CDP connection and get current page state',
6
7
  domain: 'localhost',
7
8
  strategy: Strategy.UI,
@@ -2,6 +2,7 @@ import { cli, Strategy } from '@jackwener/opencli/registry';
2
2
  export const watchCommand = cli({
3
3
  site: 'antigravity',
4
4
  name: 'watch',
5
+ access: 'read',
5
6
  description: 'Stream new chat messages from Antigravity in real-time',
6
7
  domain: 'localhost',
7
8
  strategy: Strategy.UI,
@@ -4,6 +4,7 @@ import { itunesFetch, formatDuration, formatDate } from './utils.js';
4
4
  cli({
5
5
  site: 'apple-podcasts',
6
6
  name: 'episodes',
7
+ access: 'read',
7
8
  description: 'List recent episodes of an Apple Podcast (use ID from search)',
8
9
  strategy: Strategy.PUBLIC,
9
10
  browser: false,
@@ -4,6 +4,7 @@ import { itunesFetch } from './utils.js';
4
4
  cli({
5
5
  site: 'apple-podcasts',
6
6
  name: 'search',
7
+ access: 'read',
7
8
  description: 'Search Apple Podcasts',
8
9
  strategy: Strategy.PUBLIC,
9
10
  browser: false,
@@ -6,6 +6,7 @@ const CHARTS_TIMEOUT_MS = 15_000;
6
6
  cli({
7
7
  site: 'apple-podcasts',
8
8
  name: 'top',
9
+ access: 'read',
9
10
  description: 'Top podcasts chart on Apple Podcasts',
10
11
  strategy: Strategy.PUBLIC,
11
12
  browser: false,
@@ -0,0 +1,112 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { getRegistry } from '@jackwener/opencli/registry';
3
+ import { normalizeArxivCategory, normalizeArxivLimit, parseEntries } from './utils.js';
4
+ import './paper.js';
5
+ import './search.js';
6
+ import './recent.js';
7
+
8
+ const SAMPLE_ENTRY_XML = `<?xml version='1.0' encoding='UTF-8'?>
9
+ <feed xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"
10
+ xmlns:arxiv="http://arxiv.org/schemas/atom"
11
+ xmlns="http://www.w3.org/2005/Atom">
12
+ <entry>
13
+ <id>http://arxiv.org/abs/1706.03762v7</id>
14
+ <title>Attention Is All You Need &amp; Friends</title>
15
+ <updated>2023-08-02T00:41:18Z</updated>
16
+ <link href="https://arxiv.org/abs/1706.03762v7" rel="alternate" type="text/html"/>
17
+ <link href="https://arxiv.org/pdf/1706.03762v7" rel="related" type="application/pdf" title="pdf"/>
18
+ <summary>The dominant sequence transduction models are based on complex recurrent or convolutional neural networks. We propose a new simple network architecture, the Transformer, based solely on attention.</summary>
19
+ <category term="cs.CL" scheme="http://arxiv.org/schemas/atom"/>
20
+ <category term="cs.LG" scheme="http://arxiv.org/schemas/atom"/>
21
+ <published>2017-06-12T17:57:34Z</published>
22
+ <arxiv:comment>15 pages, 5 figures</arxiv:comment>
23
+ <arxiv:primary_category term="cs.CL"/>
24
+ <author><name>Ashish Vaswani</name></author>
25
+ <author><name>Noam Shazeer</name></author>
26
+ <author><name>Niki Parmar</name></author>
27
+ <author><name>Jakob Uszkoreit</name></author>
28
+ <author><name>Llion Jones</name></author>
29
+ <author><name>Aidan N. Gomez</name></author>
30
+ <author><name>Lukasz Kaiser</name></author>
31
+ <author><name>Illia Polosukhin</name></author>
32
+ </entry>
33
+ </feed>`;
34
+
35
+ describe('arxiv adapter', () => {
36
+ it('registers paper, search and recent commands with the expected columns', () => {
37
+ const paper = getRegistry().get('arxiv/paper');
38
+ const search = getRegistry().get('arxiv/search');
39
+ const recent = getRegistry().get('arxiv/recent');
40
+
41
+ expect(paper).toBeDefined();
42
+ expect(search).toBeDefined();
43
+ expect(recent).toBeDefined();
44
+
45
+ expect(paper.columns).toEqual([
46
+ 'id', 'title', 'authors', 'published', 'updated',
47
+ 'primary_category', 'categories', 'abstract', 'comment', 'pdf', 'url',
48
+ ]);
49
+ expect(search.columns).toEqual([
50
+ 'id', 'title', 'authors', 'published', 'primary_category', 'url',
51
+ ]);
52
+ expect(recent.columns).toEqual([
53
+ 'id', 'title', 'authors', 'published', 'primary_category', 'url',
54
+ ]);
55
+ });
56
+
57
+ it('parseEntries returns full abstract, all authors, pdf, primary category and comment', () => {
58
+ const [entry] = parseEntries(SAMPLE_ENTRY_XML);
59
+
60
+ expect(entry.id).toBe('1706.03762');
61
+ expect(entry.title).toBe('Attention Is All You Need & Friends');
62
+ // All 8 authors must be present — earlier impl truncated to 3.
63
+ expect(entry.authors.split(', ')).toHaveLength(8);
64
+ expect(entry.authors).toContain('Ashish Vaswani');
65
+ expect(entry.authors).toContain('Illia Polosukhin');
66
+ // Full abstract — earlier impl truncated at 200 chars.
67
+ expect(entry.abstract.length).toBeGreaterThan(140);
68
+ expect(entry.abstract.endsWith('...')).toBe(false);
69
+ expect(entry.abstract).toContain('attention');
70
+ expect(entry.published).toBe('2017-06-12');
71
+ expect(entry.updated).toBe('2023-08-02');
72
+ expect(entry.primary_category).toBe('cs.CL');
73
+ expect(entry.categories).toBe('cs.CL, cs.LG');
74
+ expect(entry.comment).toBe('15 pages, 5 figures');
75
+ expect(entry.pdf).toBe('https://arxiv.org/pdf/1706.03762v7');
76
+ expect(entry.url).toBe('https://arxiv.org/abs/1706.03762');
77
+ });
78
+
79
+ it('parseEntries returns an empty list for feeds with no entries', () => {
80
+ expect(parseEntries('<feed></feed>')).toEqual([]);
81
+ });
82
+
83
+ it('recent rejects malformed category strings', async () => {
84
+ const recent = getRegistry().get('arxiv/recent');
85
+ await expect(recent.func({ category: 'not a category', limit: 5 })).rejects.toMatchObject({
86
+ code: 'ARGUMENT',
87
+ });
88
+ await expect(recent.func({ category: '', limit: 5 })).rejects.toMatchObject({
89
+ code: 'ARGUMENT',
90
+ });
91
+ });
92
+
93
+ it('category validation accepts real arXiv archive and subcategory forms', () => {
94
+ expect(normalizeArxivCategory('cs.CL')).toBe('cs.CL');
95
+ expect(normalizeArxivCategory('math')).toBe('math');
96
+ expect(normalizeArxivCategory('physics.comp-ph')).toBe('physics.comp-ph');
97
+ expect(normalizeArxivCategory('physics.data-an')).toBe('physics.data-an');
98
+ expect(normalizeArxivCategory('cond-mat.soft')).toBe('cond-mat.soft');
99
+ expect(normalizeArxivCategory('q-bio.NC')).toBe('q-bio.NC');
100
+ expect(() => normalizeArxivCategory('not a category')).toThrow('Invalid arXiv category');
101
+ expect(() => normalizeArxivCategory('cs/CL')).toThrow('Invalid arXiv category');
102
+ expect(() => normalizeArxivCategory('')).toThrow('Invalid arXiv category');
103
+ });
104
+
105
+ it('limit validation rejects non-positive, non-integer and over-cap values', () => {
106
+ expect(normalizeArxivLimit(10, 5, 25)).toBe(10);
107
+ expect(normalizeArxivLimit(undefined, 5, 25)).toBe(5);
108
+ expect(() => normalizeArxivLimit(0, 5, 25)).toThrow('positive integer');
109
+ expect(() => normalizeArxivLimit(1.5, 5, 25)).toThrow('positive integer');
110
+ expect(() => normalizeArxivLimit(26, 5, 25)).toThrow('<= 25');
111
+ });
112
+ });
@@ -1,21 +1,22 @@
1
1
  import { cli, Strategy } from '@jackwener/opencli/registry';
2
- import { CliError } from '@jackwener/opencli/errors';
2
+ import { EmptyResultError } from '@jackwener/opencli/errors';
3
3
  import { arxivFetch, parseEntries } from './utils.js';
4
4
  cli({
5
5
  site: 'arxiv',
6
6
  name: 'paper',
7
+ access: 'read',
7
8
  description: 'Get arXiv paper details by ID',
8
9
  strategy: Strategy.PUBLIC,
9
10
  browser: false,
10
11
  args: [
11
12
  { name: 'id', positional: true, required: true, help: 'arXiv paper ID (e.g. 1706.03762)' },
12
13
  ],
13
- columns: ['id', 'title', 'authors', 'published', 'abstract', 'url'],
14
+ columns: ['id', 'title', 'authors', 'published', 'updated', 'primary_category', 'categories', 'abstract', 'comment', 'pdf', 'url'],
14
15
  func: async (args) => {
15
16
  const xml = await arxivFetch(`id_list=${encodeURIComponent(args.id)}`);
16
17
  const entries = parseEntries(xml);
17
18
  if (!entries.length)
18
- throw new CliError('NOT_FOUND', `Paper ${args.id} not found`, 'Check the arXiv ID format, e.g. 1706.03762');
19
+ throw new EmptyResultError('arxiv paper', `Paper ${args.id} was not found. Check the arXiv ID format, e.g. 1706.03762`);
19
20
  return entries;
20
21
  },
21
22
  });
@@ -0,0 +1,33 @@
1
+ import { cli, Strategy } from '@jackwener/opencli/registry';
2
+ import { EmptyResultError } from '@jackwener/opencli/errors';
3
+ import { arxivFetch, normalizeArxivCategory, normalizeArxivLimit, parseEntries } from './utils.js';
4
+ cli({
5
+ site: 'arxiv',
6
+ name: 'recent',
7
+ access: 'read',
8
+ description: 'List recent arXiv submissions in a category',
9
+ strategy: Strategy.PUBLIC,
10
+ browser: false,
11
+ args: [
12
+ { name: 'category', positional: true, required: true, help: 'arXiv category (e.g. cs.CL, cs.LG, math.PR, q-bio.NC)' },
13
+ { name: 'limit', type: 'int', default: 10, help: 'Max results (max 50)' },
14
+ ],
15
+ columns: ['id', 'title', 'authors', 'published', 'primary_category', 'url'],
16
+ func: async (args) => {
17
+ const category = normalizeArxivCategory(args.category);
18
+ const limit = normalizeArxivLimit(args.limit, 10, 50);
19
+ const query = encodeURIComponent(`cat:${category}`);
20
+ const xml = await arxivFetch(`search_query=${query}&max_results=${limit}&sortBy=submittedDate&sortOrder=descending`);
21
+ const entries = parseEntries(xml);
22
+ if (!entries.length)
23
+ throw new EmptyResultError('arxiv', `No recent papers in ${category}. Check the category name.`);
24
+ return entries.map(e => ({
25
+ id: e.id,
26
+ title: e.title,
27
+ authors: e.authors,
28
+ published: e.published,
29
+ primary_category: e.primary_category,
30
+ url: e.url,
31
+ }));
32
+ },
33
+ });
@@ -1,9 +1,10 @@
1
1
  import { cli, Strategy } from '@jackwener/opencli/registry';
2
- import { CliError } from '@jackwener/opencli/errors';
3
- import { arxivFetch, parseEntries } from './utils.js';
2
+ import { ArgumentError, EmptyResultError } from '@jackwener/opencli/errors';
3
+ import { arxivFetch, normalizeArxivLimit, parseEntries } from './utils.js';
4
4
  cli({
5
5
  site: 'arxiv',
6
6
  name: 'search',
7
+ access: 'read',
7
8
  description: 'Search arXiv papers',
8
9
  strategy: Strategy.PUBLIC,
9
10
  browser: false,
@@ -11,14 +12,25 @@ cli({
11
12
  { name: 'query', positional: true, required: true, help: 'Search keyword (e.g. "attention is all you need")' },
12
13
  { name: 'limit', type: 'int', default: 10, help: 'Max results (max 25)' },
13
14
  ],
14
- columns: ['id', 'title', 'authors', 'published', 'url'],
15
+ columns: ['id', 'title', 'authors', 'published', 'primary_category', 'url'],
15
16
  func: async (args) => {
16
- const limit = Math.max(1, Math.min(Number(args.limit), 25));
17
- const query = encodeURIComponent(`all:${args.query}`);
17
+ const queryText = String(args.query || '').trim();
18
+ if (!queryText) {
19
+ throw new ArgumentError('arxiv search query cannot be empty');
20
+ }
21
+ const limit = normalizeArxivLimit(args.limit, 10, 25);
22
+ const query = encodeURIComponent(`all:${queryText}`);
18
23
  const xml = await arxivFetch(`search_query=${query}&max_results=${limit}&sortBy=relevance`);
19
24
  const entries = parseEntries(xml);
20
25
  if (!entries.length)
21
- throw new CliError('NOT_FOUND', 'No papers found', 'Try a different keyword');
22
- return entries.map(e => ({ id: e.id, title: e.title, authors: e.authors, published: e.published, url: e.url }));
26
+ throw new EmptyResultError('arxiv', 'No papers found. Try a different keyword.');
27
+ return entries.map(e => ({
28
+ id: e.id,
29
+ title: e.title,
30
+ authors: e.authors,
31
+ published: e.published,
32
+ primary_category: e.primary_category,
33
+ url: e.url,
34
+ }));
23
35
  },
24
36
  });
@@ -4,15 +4,44 @@
4
4
  * arXiv exposes a public Atom/XML API — no key required.
5
5
  * https://info.arxiv.org/help/api/index.html
6
6
  */
7
- import { CliError } from '@jackwener/opencli/errors';
7
+ import { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';
8
8
  export const ARXIV_BASE = 'https://export.arxiv.org/api/query';
9
+ const ARXIV_CATEGORY_PATTERN = /^[a-z]+(?:-[a-z]+)*(?:\.[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)?$/;
9
10
  export async function arxivFetch(params) {
10
11
  const resp = await fetch(`${ARXIV_BASE}?${params}`);
11
12
  if (!resp.ok) {
12
- throw new CliError('FETCH_ERROR', `arXiv API HTTP ${resp.status}`, 'Check your search term or paper ID');
13
+ throw new CommandExecutionError(`arXiv API HTTP ${resp.status}`, 'Check your search term or paper ID');
13
14
  }
14
15
  return resp.text();
15
16
  }
17
+ export function normalizeArxivLimit(value, defaultValue, maxValue, label = 'limit') {
18
+ const raw = value ?? defaultValue;
19
+ const limit = Number(raw);
20
+ if (!Number.isInteger(limit) || limit <= 0) {
21
+ throw new ArgumentError(`arxiv ${label} must be a positive integer`);
22
+ }
23
+ if (limit > maxValue) {
24
+ throw new ArgumentError(`arxiv ${label} must be <= ${maxValue}`);
25
+ }
26
+ return limit;
27
+ }
28
+ export function normalizeArxivCategory(value) {
29
+ const category = String(value || '').trim();
30
+ if (!ARXIV_CATEGORY_PATTERN.test(category)) {
31
+ throw new ArgumentError(`Invalid arXiv category "${value}". Examples: cs.CL, cs.LG, math.PR, q-bio.NC, physics.comp-ph`);
32
+ }
33
+ return category;
34
+ }
35
+ /** Decode the small set of XML entities arXiv emits in text fields. */
36
+ function decodeEntities(s) {
37
+ return s
38
+ .replace(/&amp;/g, '&')
39
+ .replace(/&lt;/g, '<')
40
+ .replace(/&gt;/g, '>')
41
+ .replace(/&quot;/g, '"')
42
+ .replace(/&apos;/g, "'")
43
+ .replace(/&#39;/g, "'");
44
+ }
16
45
  /** Extract the text content of the first matching XML tag. */
17
46
  function extract(xml, tag) {
18
47
  const m = xml.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)<\\/${tag}>`));
@@ -27,6 +56,34 @@ function extractAll(xml, tag) {
27
56
  results.push(m[1].trim());
28
57
  return results;
29
58
  }
59
+ /** Extract the value of a named attribute from the first matching tag (open or self-closing). */
60
+ function extractAttr(xml, tag, attr) {
61
+ const m = xml.match(new RegExp(`<${tag}\\b[^>]*?\\b${attr}="([^"]*)"`));
62
+ return m ? m[1] : '';
63
+ }
64
+ /** Extract all values of a named attribute across repeated tags. */
65
+ function extractAllAttr(xml, tag, attr) {
66
+ const re = new RegExp(`<${tag}\\b[^>]*?\\b${attr}="([^"]*)"`, 'g');
67
+ const out = [];
68
+ let m;
69
+ while ((m = re.exec(xml)) !== null)
70
+ out.push(m[1]);
71
+ return out;
72
+ }
73
+ /** Find the href of the first <link> tag matching a given rel. */
74
+ function findLinkHref(xml, rel) {
75
+ const re = /<link\b([^>]*)\/?>/g;
76
+ let m;
77
+ while ((m = re.exec(xml)) !== null) {
78
+ const attrs = m[1];
79
+ if (new RegExp(`\\brel="${rel}"`).test(attrs)) {
80
+ const h = attrs.match(/\bhref="([^"]*)"/);
81
+ if (h)
82
+ return h[1];
83
+ }
84
+ }
85
+ return '';
86
+ }
30
87
  /** Parse Atom XML feed into structured entries. */
31
88
  export function parseEntries(xml) {
32
89
  const entryRe = /<entry>([\s\S]*?)<\/entry>/g;
@@ -36,12 +93,18 @@ export function parseEntries(xml) {
36
93
  const e = m[1];
37
94
  const rawId = extract(e, 'id');
38
95
  const arxivId = rawId.replace(/^https?:\/\/arxiv\.org\/abs\//, '').replace(/v\d+$/, '');
96
+ const pdf = findLinkHref(e, 'related') || `https://arxiv.org/pdf/${arxivId}`;
39
97
  entries.push({
40
98
  id: arxivId,
41
- title: extract(e, 'title').replace(/\s+/g, ' '),
42
- authors: extractAll(e, 'name').slice(0, 3).join(', '),
43
- abstract: (() => { const s = extract(e, 'summary').replace(/\s+/g, ' '); return s.length > 200 ? s.slice(0, 200) + '...' : s; })(),
99
+ title: decodeEntities(extract(e, 'title').replace(/\s+/g, ' ')),
100
+ authors: decodeEntities(extractAll(e, 'name').join(', ')),
101
+ abstract: decodeEntities(extract(e, 'summary').replace(/\s+/g, ' ')),
44
102
  published: extract(e, 'published').slice(0, 10),
103
+ updated: extract(e, 'updated').slice(0, 10),
104
+ primary_category: extractAttr(e, 'arxiv:primary_category', 'term'),
105
+ categories: extractAllAttr(e, 'category', 'term').join(', '),
106
+ comment: decodeEntities(extract(e, 'arxiv:comment').replace(/\s+/g, ' ')),
107
+ pdf,
45
108
  url: `https://arxiv.org/abs/${arxivId}`,
46
109
  });
47
110
  }
@@ -4,6 +4,7 @@ import { clampInt, requireNonEmptyQuery } from '../_shared/common.js';
4
4
  cli({
5
5
  site: 'baidu-scholar',
6
6
  name: 'search',
7
+ access: 'read',
7
8
  description: '百度学术搜索',
8
9
  domain: 'xueshu.baidu.com',
9
10
  strategy: Strategy.PUBLIC,
@@ -13,6 +13,7 @@ import { cli, Strategy } from '@jackwener/opencli/registry';
13
13
  cli({
14
14
  site: 'band',
15
15
  name: 'bands',
16
+ access: 'read',
16
17
  description: 'List all Bands you belong to',
17
18
  domain: 'www.band.us',
18
19
  strategy: Strategy.COOKIE,