@jackwener/opencli 1.7.10 → 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 (740) hide show
  1. package/README.md +3 -3
  2. package/README.zh-CN.md +5 -4
  3. package/cli-manifest.json +1443 -24
  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/36kr/article.js +1 -0
  10. package/clis/36kr/hot.js +1 -0
  11. package/clis/36kr/news.js +1 -0
  12. package/clis/36kr/search.js +1 -0
  13. package/clis/51job/company.js +1 -0
  14. package/clis/51job/detail.js +1 -0
  15. package/clis/51job/hot.js +1 -0
  16. package/clis/51job/search.js +1 -0
  17. package/clis/amazon/bestsellers.js +1 -0
  18. package/clis/amazon/discussion.js +1 -0
  19. package/clis/amazon/movers-shakers.js +1 -0
  20. package/clis/amazon/new-releases.js +1 -0
  21. package/clis/amazon/offer.js +1 -0
  22. package/clis/amazon/product.js +1 -0
  23. package/clis/amazon/rankings.js +1 -0
  24. package/clis/amazon/search.js +1 -0
  25. package/clis/antigravity/dump.js +1 -0
  26. package/clis/antigravity/extract-code.js +1 -0
  27. package/clis/antigravity/model.js +1 -0
  28. package/clis/antigravity/new.js +1 -0
  29. package/clis/antigravity/read.js +1 -0
  30. package/clis/antigravity/send.js +1 -0
  31. package/clis/antigravity/status.js +1 -0
  32. package/clis/antigravity/watch.js +1 -0
  33. package/clis/apple-podcasts/episodes.js +1 -0
  34. package/clis/apple-podcasts/search.js +1 -0
  35. package/clis/apple-podcasts/top.js +1 -0
  36. package/clis/arxiv/arxiv.test.js +112 -0
  37. package/clis/arxiv/paper.js +4 -3
  38. package/clis/arxiv/recent.js +33 -0
  39. package/clis/arxiv/search.js +19 -7
  40. package/clis/arxiv/utils.js +68 -5
  41. package/clis/baidu-scholar/search.js +1 -0
  42. package/clis/band/bands.js +1 -0
  43. package/clis/band/mentions.js +1 -0
  44. package/clis/band/post.js +1 -0
  45. package/clis/band/posts.js +1 -0
  46. package/clis/barchart/flow.js +1 -0
  47. package/clis/barchart/greeks.js +1 -0
  48. package/clis/barchart/options.js +1 -0
  49. package/clis/barchart/quote.js +1 -0
  50. package/clis/bbc/news.js +1 -0
  51. package/clis/bilibili/comments.js +1 -0
  52. package/clis/bilibili/download.js +1 -0
  53. package/clis/bilibili/dynamic.js +1 -0
  54. package/clis/bilibili/favorite.js +1 -0
  55. package/clis/bilibili/feed.js +2 -0
  56. package/clis/bilibili/following.js +1 -0
  57. package/clis/bilibili/history.js +1 -0
  58. package/clis/bilibili/hot.js +6 -1
  59. package/clis/bilibili/hot.test.js +17 -0
  60. package/clis/bilibili/me.js +1 -1
  61. package/clis/bilibili/ranking.js +1 -0
  62. package/clis/bilibili/search.js +1 -1
  63. package/clis/bilibili/subtitle.js +1 -0
  64. package/clis/bilibili/user-videos.js +1 -0
  65. package/clis/bilibili/video.js +1 -0
  66. package/clis/binance/asks.js +1 -0
  67. package/clis/binance/depth.js +1 -0
  68. package/clis/binance/gainers.js +1 -0
  69. package/clis/binance/klines.js +1 -0
  70. package/clis/binance/losers.js +1 -0
  71. package/clis/binance/pairs.js +1 -0
  72. package/clis/binance/price.js +1 -0
  73. package/clis/binance/prices.js +1 -0
  74. package/clis/binance/ticker.js +1 -0
  75. package/clis/binance/top.js +1 -0
  76. package/clis/binance/trades.js +1 -0
  77. package/clis/bloomberg/businessweek.js +1 -0
  78. package/clis/bloomberg/economics.js +1 -0
  79. package/clis/bloomberg/feeds.js +1 -0
  80. package/clis/bloomberg/industries.js +1 -0
  81. package/clis/bloomberg/main.js +1 -0
  82. package/clis/bloomberg/markets.js +1 -0
  83. package/clis/bloomberg/news.js +1 -0
  84. package/clis/bloomberg/opinions.js +1 -0
  85. package/clis/bloomberg/politics.js +1 -0
  86. package/clis/bloomberg/tech.js +1 -0
  87. package/clis/bluesky/feeds.js +1 -0
  88. package/clis/bluesky/followers.js +1 -0
  89. package/clis/bluesky/following.js +1 -0
  90. package/clis/bluesky/profile.js +1 -0
  91. package/clis/bluesky/search.js +1 -0
  92. package/clis/bluesky/starter-packs.js +1 -0
  93. package/clis/bluesky/thread.js +1 -0
  94. package/clis/bluesky/trending.js +1 -0
  95. package/clis/bluesky/user.js +3 -1
  96. package/clis/boss/batchgreet.js +1 -0
  97. package/clis/boss/chatlist.js +1 -0
  98. package/clis/boss/chatmsg.js +1 -0
  99. package/clis/boss/detail.js +1 -0
  100. package/clis/boss/exchange.js +1 -0
  101. package/clis/boss/greet.js +1 -0
  102. package/clis/boss/invite.js +1 -0
  103. package/clis/boss/joblist.js +1 -0
  104. package/clis/boss/mark.js +1 -0
  105. package/clis/boss/recommend.js +1 -0
  106. package/clis/boss/resume.js +1 -0
  107. package/clis/boss/search.js +1 -0
  108. package/clis/boss/send.js +1 -0
  109. package/clis/boss/stats.js +1 -0
  110. package/clis/chaoxing/assignments.js +1 -0
  111. package/clis/chaoxing/exams.js +1 -0
  112. package/clis/chatgpt/image.js +1 -0
  113. package/clis/chatgpt-app/ask.js +1 -0
  114. package/clis/chatgpt-app/model.js +1 -0
  115. package/clis/chatgpt-app/new.js +1 -0
  116. package/clis/chatgpt-app/read.js +1 -0
  117. package/clis/chatgpt-app/send.js +1 -0
  118. package/clis/chatgpt-app/status.js +1 -0
  119. package/clis/chatwise/ask.js +1 -0
  120. package/clis/chatwise/export.js +1 -0
  121. package/clis/chatwise/history.js +1 -0
  122. package/clis/chatwise/model.js +1 -0
  123. package/clis/chatwise/read.js +1 -0
  124. package/clis/chatwise/send.js +1 -0
  125. package/clis/claude/ask.js +1 -0
  126. package/clis/claude/detail.js +1 -0
  127. package/clis/claude/history.js +1 -0
  128. package/clis/claude/new.js +1 -0
  129. package/clis/claude/read.js +1 -0
  130. package/clis/claude/send.js +1 -0
  131. package/clis/claude/status.js +1 -0
  132. package/clis/cnki/search.js +1 -0
  133. package/clis/codex/ask.js +1 -0
  134. package/clis/codex/export.js +1 -0
  135. package/clis/codex/extract-diff.js +1 -0
  136. package/clis/codex/history.js +1 -0
  137. package/clis/codex/model.js +1 -0
  138. package/clis/codex/read.js +1 -0
  139. package/clis/codex/send.js +1 -0
  140. package/clis/coupang/add-to-cart.js +1 -0
  141. package/clis/coupang/search.js +1 -0
  142. package/clis/ctrip/search.js +1 -0
  143. package/clis/cursor/ask.js +1 -0
  144. package/clis/cursor/composer.js +1 -0
  145. package/clis/cursor/export.js +1 -0
  146. package/clis/cursor/extract-code.js +1 -0
  147. package/clis/cursor/history.js +1 -0
  148. package/clis/cursor/model.js +1 -0
  149. package/clis/cursor/read.js +1 -0
  150. package/clis/cursor/send.js +1 -0
  151. package/clis/dblp/dblp.test.js +397 -0
  152. package/clis/dblp/paper.js +40 -0
  153. package/clis/dblp/search.js +45 -0
  154. package/clis/dblp/utils.js +290 -0
  155. package/clis/deepseek/ask.js +1 -0
  156. package/clis/deepseek/history.js +1 -0
  157. package/clis/deepseek/new.js +1 -0
  158. package/clis/deepseek/read.js +1 -0
  159. package/clis/deepseek/status.js +1 -0
  160. package/clis/devto/devto.test.js +236 -0
  161. package/clis/devto/read.js +103 -0
  162. package/clis/devto/tag.js +5 -1
  163. package/clis/devto/top.js +5 -1
  164. package/clis/devto/user.js +5 -1
  165. package/clis/dianping/__fixtures__/search.html +168 -0
  166. package/clis/dianping/__fixtures__/shop.html +6 -0
  167. package/clis/dianping/dianping.test.js +424 -0
  168. package/clis/dianping/search.js +154 -0
  169. package/clis/dianping/shop.js +173 -0
  170. package/clis/dianping/utils.js +157 -0
  171. package/clis/dictionary/examples.js +1 -0
  172. package/clis/dictionary/search.js +1 -0
  173. package/clis/dictionary/synonyms.js +1 -0
  174. package/clis/discord-app/channels.js +1 -0
  175. package/clis/discord-app/delete.js +1 -0
  176. package/clis/discord-app/members.js +1 -0
  177. package/clis/discord-app/read.js +1 -0
  178. package/clis/discord-app/search.js +1 -0
  179. package/clis/discord-app/send.js +1 -0
  180. package/clis/discord-app/servers.js +1 -0
  181. package/clis/discord-app/status.js +1 -0
  182. package/clis/douban/book-hot.js +1 -0
  183. package/clis/douban/download.js +1 -0
  184. package/clis/douban/marks.js +1 -0
  185. package/clis/douban/movie-hot.js +2 -1
  186. package/clis/douban/movie-hot.test.js +14 -0
  187. package/clis/douban/photos.js +2 -1
  188. package/clis/douban/reviews.js +1 -0
  189. package/clis/douban/search.js +1 -0
  190. package/clis/douban/subject.js +1 -0
  191. package/clis/douban/top250.js +1 -0
  192. package/clis/douban/utils.js +11 -13
  193. package/clis/douban/utils.test.js +79 -0
  194. package/clis/doubao/ask.js +1 -0
  195. package/clis/doubao/detail.js +1 -0
  196. package/clis/doubao/history.js +1 -0
  197. package/clis/doubao/meeting-summary.js +1 -0
  198. package/clis/doubao/meeting-transcript.js +1 -0
  199. package/clis/doubao/new.js +1 -0
  200. package/clis/doubao/read.js +1 -0
  201. package/clis/doubao/send.js +1 -0
  202. package/clis/doubao/status.js +1 -0
  203. package/clis/doubao-app/ask.js +1 -0
  204. package/clis/doubao-app/dump.js +1 -0
  205. package/clis/doubao-app/new.js +1 -0
  206. package/clis/doubao-app/read.js +1 -0
  207. package/clis/doubao-app/screenshot.js +1 -0
  208. package/clis/doubao-app/send.js +1 -0
  209. package/clis/doubao-app/status.js +1 -0
  210. package/clis/douyin/activities.js +1 -0
  211. package/clis/douyin/collections.js +1 -0
  212. package/clis/douyin/delete.js +1 -0
  213. package/clis/douyin/draft.js +1 -0
  214. package/clis/douyin/drafts.js +1 -0
  215. package/clis/douyin/hashtag.js +1 -0
  216. package/clis/douyin/location.js +1 -0
  217. package/clis/douyin/profile.js +1 -0
  218. package/clis/douyin/publish.js +1 -0
  219. package/clis/douyin/stats.js +1 -0
  220. package/clis/douyin/update.js +1 -0
  221. package/clis/douyin/user-videos.js +1 -0
  222. package/clis/douyin/videos.js +1 -0
  223. package/clis/eastmoney/announcement.js +1 -0
  224. package/clis/eastmoney/convertible.js +1 -0
  225. package/clis/eastmoney/etf.js +1 -0
  226. package/clis/eastmoney/holders.js +1 -0
  227. package/clis/eastmoney/hot-rank.js +1 -0
  228. package/clis/eastmoney/index-board.js +1 -0
  229. package/clis/eastmoney/kline.js +1 -0
  230. package/clis/eastmoney/kuaixun.js +1 -0
  231. package/clis/eastmoney/longhu.js +1 -0
  232. package/clis/eastmoney/money-flow.js +1 -0
  233. package/clis/eastmoney/northbound.js +1 -0
  234. package/clis/eastmoney/quote.js +1 -0
  235. package/clis/eastmoney/rank.js +1 -0
  236. package/clis/eastmoney/sectors.js +1 -0
  237. package/clis/facebook/add-friend.js +1 -0
  238. package/clis/facebook/events.js +1 -0
  239. package/clis/facebook/feed.js +1 -0
  240. package/clis/facebook/friends.js +1 -0
  241. package/clis/facebook/groups.js +1 -0
  242. package/clis/facebook/join-group.js +1 -0
  243. package/clis/facebook/marketplace-inbox.js +1 -0
  244. package/clis/facebook/marketplace-listings.js +1 -0
  245. package/clis/facebook/memories.js +1 -0
  246. package/clis/facebook/notifications.js +1 -0
  247. package/clis/facebook/profile.js +1 -0
  248. package/clis/facebook/search.js +1 -0
  249. package/clis/gemini/ask.js +1 -0
  250. package/clis/gemini/deep-research-result.js +1 -0
  251. package/clis/gemini/deep-research.js +1 -0
  252. package/clis/gemini/image.js +1 -0
  253. package/clis/gemini/new.js +1 -0
  254. package/clis/gitee/search.js +1 -0
  255. package/clis/gitee/trending.js +1 -0
  256. package/clis/gitee/user.js +1 -0
  257. package/clis/google/news.js +1 -0
  258. package/clis/google/search.js +1 -0
  259. package/clis/google/suggest.js +1 -0
  260. package/clis/google/trends.js +1 -0
  261. package/clis/google-scholar/cite.js +1 -0
  262. package/clis/google-scholar/profile.js +1 -0
  263. package/clis/google-scholar/search.js +1 -0
  264. package/clis/gov-law/recent.js +1 -0
  265. package/clis/gov-law/search.js +1 -0
  266. package/clis/gov-policy/recent.js +1 -0
  267. package/clis/gov-policy/search.js +1 -0
  268. package/clis/grok/ask.js +1 -0
  269. package/clis/grok/image.ts +1 -0
  270. package/clis/hackernews/ask.js +3 -1
  271. package/clis/hackernews/best.js +3 -1
  272. package/clis/hackernews/hackernews.test.js +132 -0
  273. package/clis/hackernews/jobs.js +3 -1
  274. package/clis/hackernews/new.js +3 -1
  275. package/clis/hackernews/read.js +188 -0
  276. package/clis/hackernews/search.js +3 -1
  277. package/clis/hackernews/show.js +3 -1
  278. package/clis/hackernews/top.js +3 -1
  279. package/clis/hackernews/user.js +1 -0
  280. package/clis/hf/top.js +1 -0
  281. package/clis/hupu/detail.js +1 -0
  282. package/clis/hupu/hot.js +3 -1
  283. package/clis/hupu/like.js +1 -0
  284. package/clis/hupu/mentions.js +2 -1
  285. package/clis/hupu/reply.js +1 -0
  286. package/clis/hupu/search.js +3 -1
  287. package/clis/hupu/unlike.js +1 -0
  288. package/clis/imdb/person.js +1 -0
  289. package/clis/imdb/reviews.js +1 -0
  290. package/clis/imdb/search.js +1 -0
  291. package/clis/imdb/title.js +1 -0
  292. package/clis/imdb/top.js +1 -0
  293. package/clis/imdb/trending.js +1 -0
  294. package/clis/indeed/indeed.test.js +375 -0
  295. package/clis/indeed/job.js +86 -0
  296. package/clis/indeed/search.js +110 -0
  297. package/clis/indeed/utils.js +152 -0
  298. package/clis/instagram/collection-create.js +1 -0
  299. package/clis/instagram/collection-delete.js +92 -0
  300. package/clis/instagram/comment.js +1 -0
  301. package/clis/instagram/download.js +1 -0
  302. package/clis/instagram/explore.js +1 -0
  303. package/clis/instagram/follow.js +1 -0
  304. package/clis/instagram/followers.js +1 -0
  305. package/clis/instagram/following.js +1 -0
  306. package/clis/instagram/like.js +1 -0
  307. package/clis/instagram/note.js +1 -0
  308. package/clis/instagram/post.js +1 -0
  309. package/clis/instagram/profile.js +1 -0
  310. package/clis/instagram/reel.js +1 -0
  311. package/clis/instagram/save.js +1 -0
  312. package/clis/instagram/saved.js +1 -0
  313. package/clis/instagram/search.js +1 -0
  314. package/clis/instagram/story.js +1 -0
  315. package/clis/instagram/unfollow.js +1 -0
  316. package/clis/instagram/unlike.js +1 -0
  317. package/clis/instagram/unsave.js +1 -0
  318. package/clis/instagram/user.js +1 -0
  319. package/clis/jd/add-cart.js +1 -0
  320. package/clis/jd/cart.js +1 -0
  321. package/clis/jd/detail.js +1 -0
  322. package/clis/jd/item.js +1 -0
  323. package/clis/jd/reviews.js +1 -0
  324. package/clis/jd/search.js +1 -0
  325. package/clis/jianyu/detail.js +1 -0
  326. package/clis/jianyu/search.js +1 -0
  327. package/clis/jike/comment.js +1 -0
  328. package/clis/jike/create.js +1 -0
  329. package/clis/jike/feed.js +3 -1
  330. package/clis/jike/like.js +1 -0
  331. package/clis/jike/notifications.js +1 -0
  332. package/clis/jike/post.js +1 -0
  333. package/clis/jike/repost.js +1 -0
  334. package/clis/jike/search.js +3 -1
  335. package/clis/jike/topic.js +1 -0
  336. package/clis/jike/user.js +3 -1
  337. package/clis/jimeng/generate.js +1 -0
  338. package/clis/jimeng/history.js +1 -0
  339. package/clis/jimeng/new.js +1 -0
  340. package/clis/jimeng/workspaces.js +1 -0
  341. package/clis/ke/chengjiao.js +1 -0
  342. package/clis/ke/ershoufang.js +1 -0
  343. package/clis/ke/xiaoqu.js +1 -0
  344. package/clis/ke/zufang.js +1 -0
  345. package/clis/lesswrong/comments.js +1 -0
  346. package/clis/lesswrong/curated.js +1 -0
  347. package/clis/lesswrong/frontpage.js +1 -0
  348. package/clis/lesswrong/new.js +1 -0
  349. package/clis/lesswrong/read.js +1 -0
  350. package/clis/lesswrong/sequences.js +1 -0
  351. package/clis/lesswrong/shortform.js +1 -0
  352. package/clis/lesswrong/tag.js +1 -0
  353. package/clis/lesswrong/tags.js +1 -0
  354. package/clis/lesswrong/top-month.js +1 -0
  355. package/clis/lesswrong/top-week.js +1 -0
  356. package/clis/lesswrong/top-year.js +1 -0
  357. package/clis/lesswrong/top.js +1 -0
  358. package/clis/lesswrong/user-posts.js +1 -0
  359. package/clis/lesswrong/user.js +1 -0
  360. package/clis/linkedin/search.js +1 -0
  361. package/clis/linkedin/timeline.js +1 -0
  362. package/clis/linux-do/categories.js +1 -0
  363. package/clis/linux-do/category.js +1 -0
  364. package/clis/linux-do/feed.js +1 -0
  365. package/clis/linux-do/hot.js +1 -0
  366. package/clis/linux-do/latest.js +1 -0
  367. package/clis/linux-do/search.js +1 -0
  368. package/clis/linux-do/tags.js +2 -1
  369. package/clis/linux-do/topic-content.js +1 -0
  370. package/clis/linux-do/topic.js +1 -0
  371. package/clis/linux-do/user-posts.js +1 -0
  372. package/clis/linux-do/user-topics.js +1 -0
  373. package/clis/lobsters/active.js +4 -1
  374. package/clis/lobsters/hot.js +4 -1
  375. package/clis/lobsters/lobsters.test.js +169 -0
  376. package/clis/lobsters/newest.js +4 -1
  377. package/clis/lobsters/read.js +196 -0
  378. package/clis/lobsters/tag.js +4 -1
  379. package/clis/maimai/search-talents.js +1 -0
  380. package/clis/medium/feed.js +1 -0
  381. package/clis/medium/search.js +1 -0
  382. package/clis/medium/user.js +1 -0
  383. package/clis/mubu/doc.js +1 -0
  384. package/clis/mubu/docs.js +1 -0
  385. package/clis/mubu/notes.js +1 -0
  386. package/clis/mubu/recent.js +1 -0
  387. package/clis/mubu/search.js +1 -0
  388. package/clis/notebooklm/current.js +1 -0
  389. package/clis/notebooklm/get.js +1 -0
  390. package/clis/notebooklm/history.js +1 -0
  391. package/clis/notebooklm/list.js +1 -0
  392. package/clis/notebooklm/note-list.js +1 -0
  393. package/clis/notebooklm/notes-get.js +1 -0
  394. package/clis/notebooklm/open.js +1 -0
  395. package/clis/notebooklm/source-fulltext.js +1 -0
  396. package/clis/notebooklm/source-get.js +1 -0
  397. package/clis/notebooklm/source-guide.js +1 -0
  398. package/clis/notebooklm/source-list.js +1 -0
  399. package/clis/notebooklm/status.js +1 -0
  400. package/clis/notebooklm/summary.js +1 -0
  401. package/clis/notion/export.js +1 -0
  402. package/clis/notion/favorites.js +1 -0
  403. package/clis/notion/new.js +1 -0
  404. package/clis/notion/read.js +1 -0
  405. package/clis/notion/search.js +1 -0
  406. package/clis/notion/sidebar.js +1 -0
  407. package/clis/notion/status.js +1 -0
  408. package/clis/notion/write.js +1 -0
  409. package/clis/nowcoder/companies.js +1 -0
  410. package/clis/nowcoder/creators.js +1 -0
  411. package/clis/nowcoder/detail.js +1 -0
  412. package/clis/nowcoder/experience.js +1 -0
  413. package/clis/nowcoder/hot.js +1 -0
  414. package/clis/nowcoder/jobs.js +1 -0
  415. package/clis/nowcoder/notifications.js +1 -0
  416. package/clis/nowcoder/papers.js +1 -0
  417. package/clis/nowcoder/practice.js +1 -0
  418. package/clis/nowcoder/recommend.js +1 -0
  419. package/clis/nowcoder/referral.js +1 -0
  420. package/clis/nowcoder/salary.js +1 -0
  421. package/clis/nowcoder/search.js +1 -0
  422. package/clis/nowcoder/suggest.js +1 -0
  423. package/clis/nowcoder/topics.js +1 -0
  424. package/clis/nowcoder/trending.js +1 -0
  425. package/clis/ones/login.js +1 -0
  426. package/clis/ones/logout.js +1 -0
  427. package/clis/ones/me.js +1 -0
  428. package/clis/ones/my-tasks.js +1 -0
  429. package/clis/ones/task.js +1 -0
  430. package/clis/ones/tasks.js +1 -0
  431. package/clis/ones/token-info.js +1 -0
  432. package/clis/ones/worklog.js +1 -0
  433. package/clis/openreview/openreview.test.js +345 -0
  434. package/clis/openreview/paper.js +43 -0
  435. package/clis/openreview/reviews.js +131 -0
  436. package/clis/openreview/search.js +46 -0
  437. package/clis/openreview/utils.js +158 -0
  438. package/clis/openreview/venue.js +63 -0
  439. package/clis/paperreview/feedback.js +1 -0
  440. package/clis/paperreview/review.js +1 -0
  441. package/clis/paperreview/submit.js +1 -0
  442. package/clis/pixiv/detail.js +1 -0
  443. package/clis/pixiv/download.js +1 -0
  444. package/clis/pixiv/illusts.js +2 -1
  445. package/clis/pixiv/ranking.js +2 -1
  446. package/clis/pixiv/search.js +2 -1
  447. package/clis/pixiv/user.js +2 -0
  448. package/clis/powerchina/search.js +1 -0
  449. package/clis/producthunt/browse.js +1 -0
  450. package/clis/producthunt/hot.js +1 -0
  451. package/clis/producthunt/posts.js +1 -0
  452. package/clis/producthunt/today.js +1 -0
  453. package/clis/quark/ls.js +1 -0
  454. package/clis/quark/mkdir.js +1 -0
  455. package/clis/quark/mv.js +1 -0
  456. package/clis/quark/rename.js +1 -0
  457. package/clis/quark/rm.js +1 -0
  458. package/clis/quark/save.js +1 -0
  459. package/clis/quark/share-tree.js +1 -0
  460. package/clis/reddit/comment.js +1 -0
  461. package/clis/reddit/frontpage.js +1 -0
  462. package/clis/reddit/hot.js +6 -1
  463. package/clis/reddit/hot.test.js +18 -0
  464. package/clis/reddit/popular.js +1 -0
  465. package/clis/reddit/read.js +1 -0
  466. package/clis/reddit/save.js +1 -0
  467. package/clis/reddit/saved.js +1 -0
  468. package/clis/reddit/search.js +1 -0
  469. package/clis/reddit/subreddit.js +1 -0
  470. package/clis/reddit/subscribe.js +1 -0
  471. package/clis/reddit/upvote.js +1 -0
  472. package/clis/reddit/upvoted.js +1 -0
  473. package/clis/reddit/user-comments.js +1 -0
  474. package/clis/reddit/user-posts.js +1 -0
  475. package/clis/reddit/user.js +1 -0
  476. package/clis/reuters/search.js +1 -0
  477. package/clis/sinablog/article.js +1 -0
  478. package/clis/sinablog/hot.js +1 -0
  479. package/clis/sinablog/search.js +1 -0
  480. package/clis/sinablog/user.js +1 -0
  481. package/clis/sinafinance/news.js +1 -0
  482. package/clis/sinafinance/rolling-news.js +1 -0
  483. package/clis/sinafinance/stock-rank.js +1 -0
  484. package/clis/sinafinance/stock.js +1 -0
  485. package/clis/smzdm/search.js +1 -0
  486. package/clis/spotify/spotify.js +11 -0
  487. package/clis/stackoverflow/bounties.js +11 -3
  488. package/clis/stackoverflow/hot.js +10 -2
  489. package/clis/stackoverflow/read.js +314 -0
  490. package/clis/stackoverflow/search.js +10 -2
  491. package/clis/stackoverflow/stackoverflow.test.js +346 -0
  492. package/clis/stackoverflow/unanswered.js +9 -2
  493. package/clis/steam/top-sellers.js +1 -0
  494. package/clis/substack/feed.js +1 -0
  495. package/clis/substack/publication.js +1 -0
  496. package/clis/substack/search.js +1 -0
  497. package/clis/taobao/add-cart.js +1 -0
  498. package/clis/taobao/cart.js +1 -0
  499. package/clis/taobao/detail.js +1 -0
  500. package/clis/taobao/reviews.js +1 -0
  501. package/clis/taobao/search.js +1 -0
  502. package/clis/tdx/hot-rank.js +1 -0
  503. package/clis/ths/hot-rank.js +1 -0
  504. package/clis/tieba/hot.js +2 -1
  505. package/clis/tieba/posts.js +1 -0
  506. package/clis/tieba/read.js +1 -0
  507. package/clis/tieba/search.js +2 -1
  508. package/clis/tiktok/comment.js +1 -0
  509. package/clis/tiktok/explore.js +1 -0
  510. package/clis/tiktok/follow.js +1 -0
  511. package/clis/tiktok/following.js +1 -0
  512. package/clis/tiktok/friends.js +1 -0
  513. package/clis/tiktok/like.js +1 -0
  514. package/clis/tiktok/live.js +1 -0
  515. package/clis/tiktok/notifications.js +1 -0
  516. package/clis/tiktok/profile.js +1 -0
  517. package/clis/tiktok/save.js +1 -0
  518. package/clis/tiktok/search.js +1 -0
  519. package/clis/tiktok/unfollow.js +1 -0
  520. package/clis/tiktok/unlike.js +1 -0
  521. package/clis/tiktok/unsave.js +1 -0
  522. package/clis/tiktok/user.js +1 -0
  523. package/clis/toutiao/articles.js +1 -0
  524. package/clis/twitter/accept.js +1 -0
  525. package/clis/twitter/article.js +1 -0
  526. package/clis/twitter/block.js +1 -0
  527. package/clis/twitter/bookmark.js +1 -0
  528. package/clis/twitter/bookmarks.js +2 -1
  529. package/clis/twitter/delete.js +1 -0
  530. package/clis/twitter/download.js +1 -0
  531. package/clis/twitter/follow.js +1 -0
  532. package/clis/twitter/followers.js +1 -0
  533. package/clis/twitter/following.js +1 -0
  534. package/clis/twitter/hide-reply.js +1 -0
  535. package/clis/twitter/like.js +1 -0
  536. package/clis/twitter/likes.js +2 -1
  537. package/clis/twitter/list-add.js +1 -0
  538. package/clis/twitter/list-remove.js +1 -0
  539. package/clis/twitter/list-tweets.js +1 -0
  540. package/clis/twitter/lists.js +1 -0
  541. package/clis/twitter/notifications.js +1 -0
  542. package/clis/twitter/post.js +1 -0
  543. package/clis/twitter/profile.js +1 -0
  544. package/clis/twitter/reply-dm.js +1 -0
  545. package/clis/twitter/reply.js +1 -0
  546. package/clis/twitter/search.js +1 -0
  547. package/clis/twitter/thread.js +1 -0
  548. package/clis/twitter/timeline.js +1 -0
  549. package/clis/twitter/trending.js +11 -12
  550. package/clis/twitter/trending.test.js +15 -0
  551. package/clis/twitter/tweets.js +2 -1
  552. package/clis/twitter/tweets.test.js +2 -2
  553. package/clis/twitter/unblock.js +1 -0
  554. package/clis/twitter/unbookmark.js +1 -0
  555. package/clis/twitter/unfollow.js +1 -0
  556. package/clis/uiverse/code.js +1 -0
  557. package/clis/uiverse/preview.js +1 -0
  558. package/clis/v2ex/daily.js +1 -0
  559. package/clis/v2ex/hot.js +1 -0
  560. package/clis/v2ex/latest.js +1 -0
  561. package/clis/v2ex/me.js +1 -0
  562. package/clis/v2ex/member.js +1 -0
  563. package/clis/v2ex/node.js +1 -0
  564. package/clis/v2ex/nodes.js +1 -0
  565. package/clis/v2ex/notifications.js +1 -0
  566. package/clis/v2ex/replies.js +1 -0
  567. package/clis/v2ex/topic.js +1 -0
  568. package/clis/v2ex/user.js +1 -0
  569. package/clis/wanfang/search.js +1 -0
  570. package/clis/web/read.js +1 -0
  571. package/clis/weibo/comments.js +1 -0
  572. package/clis/weibo/favorites.js +1 -0
  573. package/clis/weibo/feed.js +3 -1
  574. package/clis/weibo/hot.js +1 -0
  575. package/clis/weibo/me.js +1 -0
  576. package/clis/weibo/post.js +1 -0
  577. package/clis/weibo/publish.js +1 -0
  578. package/clis/weibo/search.js +8 -2
  579. package/clis/weibo/user.js +1 -0
  580. package/clis/weixin/create-draft.js +1 -0
  581. package/clis/weixin/download.js +1 -0
  582. package/clis/weixin/drafts.js +1 -0
  583. package/clis/weread/ai-outline.js +1 -0
  584. package/clis/weread/book.js +1 -0
  585. package/clis/weread/highlights.js +1 -0
  586. package/clis/weread/notebooks.js +1 -0
  587. package/clis/weread/notes.js +1 -0
  588. package/clis/weread/ranking.js +1 -0
  589. package/clis/weread/search.js +1 -0
  590. package/clis/weread/shelf.js +1 -0
  591. package/clis/wikipedia/random.js +1 -0
  592. package/clis/wikipedia/search.js +1 -0
  593. package/clis/wikipedia/summary.js +1 -0
  594. package/clis/wikipedia/trending.js +1 -0
  595. package/clis/xianyu/chat.js +1 -0
  596. package/clis/xianyu/item.js +1 -0
  597. package/clis/xianyu/search.js +1 -0
  598. package/clis/xiaoe/catalog.js +2 -1
  599. package/clis/xiaoe/content.js +1 -0
  600. package/clis/xiaoe/courses.js +1 -0
  601. package/clis/xiaoe/detail.js +1 -0
  602. package/clis/xiaoe/play-url.js +1 -0
  603. package/clis/xiaohongshu/comments.js +1 -0
  604. package/clis/xiaohongshu/creator-note-detail.js +1 -0
  605. package/clis/xiaohongshu/creator-notes-summary.js +1 -0
  606. package/clis/xiaohongshu/creator-notes.js +1 -0
  607. package/clis/xiaohongshu/creator-profile.js +1 -0
  608. package/clis/xiaohongshu/creator-stats.js +1 -0
  609. package/clis/xiaohongshu/download.js +1 -0
  610. package/clis/xiaohongshu/feed.js +2 -1
  611. package/clis/xiaohongshu/note.js +1 -0
  612. package/clis/xiaohongshu/notifications.js +1 -0
  613. package/clis/xiaohongshu/publish.js +1 -0
  614. package/clis/xiaohongshu/search.js +1 -0
  615. package/clis/xiaohongshu/user.js +1 -0
  616. package/clis/xiaoyuzhou/download.js +1 -0
  617. package/clis/xiaoyuzhou/episode.js +1 -0
  618. package/clis/xiaoyuzhou/podcast-episodes.js +1 -0
  619. package/clis/xiaoyuzhou/podcast.js +1 -0
  620. package/clis/xiaoyuzhou/transcript.js +1 -0
  621. package/clis/xueqiu/comments.js +1 -0
  622. package/clis/xueqiu/earnings-date.js +1 -0
  623. package/clis/xueqiu/feed.js +1 -0
  624. package/clis/xueqiu/fund-holdings.js +1 -0
  625. package/clis/xueqiu/fund-snapshot.js +1 -0
  626. package/clis/xueqiu/groups.js +1 -0
  627. package/clis/xueqiu/hot-stock.js +1 -0
  628. package/clis/xueqiu/hot.js +1 -0
  629. package/clis/xueqiu/kline.js +1 -0
  630. package/clis/xueqiu/search.js +1 -0
  631. package/clis/xueqiu/stock.js +1 -0
  632. package/clis/xueqiu/watchlist.js +1 -0
  633. package/clis/yahoo-finance/quote.js +1 -0
  634. package/clis/yollomi/background.js +1 -0
  635. package/clis/yollomi/edit.js +1 -0
  636. package/clis/yollomi/face-swap.js +1 -0
  637. package/clis/yollomi/generate.js +1 -0
  638. package/clis/yollomi/models.js +1 -0
  639. package/clis/yollomi/object-remover.js +1 -0
  640. package/clis/yollomi/remove-bg.js +1 -0
  641. package/clis/yollomi/restore.js +1 -0
  642. package/clis/yollomi/try-on.js +1 -0
  643. package/clis/yollomi/upload.js +1 -0
  644. package/clis/yollomi/upscale.js +1 -0
  645. package/clis/yollomi/video.js +1 -0
  646. package/clis/youtube/channel.js +1 -0
  647. package/clis/youtube/comments.js +1 -0
  648. package/clis/youtube/feed.js +8 -7
  649. package/clis/youtube/feed.test.js +131 -0
  650. package/clis/youtube/history.js +1 -0
  651. package/clis/youtube/like.js +1 -0
  652. package/clis/youtube/playlist.js +1 -0
  653. package/clis/youtube/search.js +1 -0
  654. package/clis/youtube/subscribe.js +1 -0
  655. package/clis/youtube/subscriptions.js +1 -0
  656. package/clis/youtube/transcript.js +1 -0
  657. package/clis/youtube/unlike.js +1 -0
  658. package/clis/youtube/unsubscribe.js +1 -0
  659. package/clis/youtube/video.js +1 -0
  660. package/clis/youtube/watch-later.js +1 -0
  661. package/clis/yuanbao/ask.js +1 -0
  662. package/clis/yuanbao/new.js +1 -0
  663. package/clis/zhihu/answer.js +1 -0
  664. package/clis/zhihu/collection.js +1 -0
  665. package/clis/zhihu/collections.js +1 -0
  666. package/clis/zhihu/comment.js +1 -0
  667. package/clis/zhihu/download.js +1 -0
  668. package/clis/zhihu/favorite.js +1 -0
  669. package/clis/zhihu/follow.js +1 -0
  670. package/clis/zhihu/hot.js +1 -0
  671. package/clis/zhihu/like.js +1 -0
  672. package/clis/zhihu/question.js +1 -0
  673. package/clis/zhihu/search.js +1 -0
  674. package/clis/zlibrary/info.js +1 -0
  675. package/clis/zlibrary/search.js +1 -0
  676. package/clis/zsxq/dynamics.js +1 -0
  677. package/clis/zsxq/groups.js +1 -0
  678. package/clis/zsxq/search.js +1 -0
  679. package/clis/zsxq/topic.js +1 -0
  680. package/clis/zsxq/topics.js +1 -0
  681. package/dist/src/adapter-shadow.d.ts +11 -0
  682. package/dist/src/adapter-shadow.js +72 -0
  683. package/dist/src/adapter-shadow.test.d.ts +1 -0
  684. package/dist/src/adapter-shadow.test.js +49 -0
  685. package/dist/src/adapter-source.test.js +1 -1
  686. package/dist/src/browser/analyze.test.js +2 -0
  687. package/dist/src/browser/base-page.d.ts +15 -2
  688. package/dist/src/browser/base-page.js +159 -8
  689. package/dist/src/browser/base-page.test.js +103 -1
  690. package/dist/src/browser/cdp.js +54 -0
  691. package/dist/src/browser/cdp.test.js +26 -0
  692. package/dist/src/browser/dom-helpers.d.ts +1 -1
  693. package/dist/src/browser/dom-helpers.js +15 -3
  694. package/dist/src/browser/page.d.ts +1 -0
  695. package/dist/src/browser/page.js +7 -1
  696. package/dist/src/browser/page.test.js +17 -0
  697. package/dist/src/browser/target-resolver.d.ts +17 -2
  698. package/dist/src/browser/target-resolver.js +85 -4
  699. package/dist/src/browser/verify-fixture.d.ts +7 -1
  700. package/dist/src/browser/verify-fixture.js +105 -0
  701. package/dist/src/browser/verify-fixture.test.js +59 -1
  702. package/dist/src/build-manifest.d.ts +68 -33
  703. package/dist/src/build-manifest.js +178 -29
  704. package/dist/src/build-manifest.test.js +85 -5
  705. package/dist/src/capabilityRouting.test.js +1 -1
  706. package/dist/src/cli.js +150 -11
  707. package/dist/src/cli.test.js +237 -0
  708. package/dist/src/commanderAdapter.d.ts +1 -1
  709. package/dist/src/commanderAdapter.js +17 -7
  710. package/dist/src/commanderAdapter.test.js +7 -6
  711. package/dist/src/convention-audit.d.ts +50 -0
  712. package/dist/src/convention-audit.js +546 -0
  713. package/dist/src/convention-audit.test.d.ts +1 -0
  714. package/dist/src/convention-audit.test.js +226 -0
  715. package/dist/src/discovery.js +2 -0
  716. package/dist/src/doctor.d.ts +2 -0
  717. package/dist/src/doctor.js +6 -0
  718. package/dist/src/doctor.test.js +36 -1
  719. package/dist/src/engine.test.js +10 -10
  720. package/dist/src/execution.js +1 -1
  721. package/dist/src/execution.test.js +9 -9
  722. package/dist/src/help.d.ts +15 -0
  723. package/dist/src/help.js +149 -0
  724. package/dist/src/main.js +13 -7
  725. package/dist/src/manifest-types.d.ts +41 -0
  726. package/dist/src/manifest-types.js +9 -0
  727. package/dist/src/plugin.test.js +26 -26
  728. package/dist/src/registry.d.ts +5 -0
  729. package/dist/src/registry.js +8 -0
  730. package/dist/src/registry.test.js +27 -20
  731. package/dist/src/serialization.d.ts +4 -0
  732. package/dist/src/serialization.js +27 -1
  733. package/dist/src/serialization.test.js +24 -2
  734. package/dist/src/types.d.ts +2 -0
  735. package/package.json +5 -2
  736. package/scripts/check-listing-id-pairing.mjs +193 -0
  737. package/scripts/check-silent-column-drop.mjs +105 -0
  738. package/scripts/check-typed-error-lint.mjs +118 -0
  739. package/scripts/silent-column-drop-baseline.json +962 -0
  740. package/scripts/typed-error-lint-baseline.json +1586 -0
@@ -0,0 +1,149 @@
1
+ import yaml from 'js-yaml';
2
+ import { fullName } from './registry.js';
3
+ import { formatCommandExample } from './serialization.js';
4
+ function normalizeStructuredHelpFormat(value) {
5
+ const normalized = value?.toLowerCase();
6
+ if (normalized === 'yaml' || normalized === 'yml')
7
+ return 'yaml';
8
+ if (normalized === 'json')
9
+ return 'json';
10
+ return undefined;
11
+ }
12
+ export function getRequestedHelpFormat(argv = process.argv) {
13
+ for (let i = 0; i < argv.length; i++) {
14
+ const token = argv[i];
15
+ if (token === '-f' || token === '--format') {
16
+ return normalizeStructuredHelpFormat(argv[i + 1]);
17
+ }
18
+ if (token.startsWith('--format=')) {
19
+ return normalizeStructuredHelpFormat(token.slice('--format='.length));
20
+ }
21
+ if (token.startsWith('-f') && token.length > 2) {
22
+ return normalizeStructuredHelpFormat(token.slice(2));
23
+ }
24
+ }
25
+ return undefined;
26
+ }
27
+ export function renderStructuredHelp(data, format) {
28
+ if (format === 'json')
29
+ return `${JSON.stringify(data, null, 2)}\n`;
30
+ return yaml.dump(data, { sortKeys: false, lineWidth: 120, noRefs: true });
31
+ }
32
+ export function wrapCommaList(items, opts = {}) {
33
+ const width = Math.max(opts.width ?? process.stdout.columns ?? 100, 40);
34
+ const indent = opts.indent ?? ' ';
35
+ const sorted = [...items].sort((a, b) => a.localeCompare(b));
36
+ const lines = [];
37
+ let line = indent;
38
+ sorted.forEach((item, index) => {
39
+ const token = `${item}${index < sorted.length - 1 ? ',' : ''}`;
40
+ const prefix = line === indent ? '' : ' ';
41
+ if (line.length + prefix.length + token.length > width && line.trim()) {
42
+ lines.push(line);
43
+ line = `${indent}${token}`;
44
+ }
45
+ else {
46
+ line += `${prefix}${token}`;
47
+ }
48
+ });
49
+ if (line.trim())
50
+ lines.push(line);
51
+ return lines.join('\n');
52
+ }
53
+ export function formatRootAdapterHelpText(siteNames) {
54
+ if (siteNames.length === 0)
55
+ return '';
56
+ return [
57
+ '',
58
+ `Site adapters (${siteNames.length}):`,
59
+ wrapCommaList(siteNames),
60
+ '',
61
+ "Run 'opencli list' for full command details, or 'opencli <site> --help' to inspect one site.",
62
+ "Agent tip: use 'opencli <site> --help -f yaml' for structured commands, args, access, and examples.",
63
+ '',
64
+ ].join('\n');
65
+ }
66
+ function compactArg(arg) {
67
+ return {
68
+ name: arg.name,
69
+ ...(arg.type && arg.type !== 'string' ? { type: arg.type } : {}),
70
+ ...(arg.positional ? { positional: true } : {}),
71
+ ...(arg.required ? { required: true } : {}),
72
+ ...(arg.valueRequired ? { valueRequired: true } : {}),
73
+ ...(arg.default !== undefined ? { default: arg.default } : {}),
74
+ ...(arg.choices?.length ? { choices: arg.choices } : {}),
75
+ ...(arg.help ? { help: arg.help } : {}),
76
+ };
77
+ }
78
+ function compactCommand(cmd, opts = {}) {
79
+ return {
80
+ name: cmd.name,
81
+ command: `opencli ${cmd.site} ${cmd.name}`,
82
+ access: cmd.access,
83
+ description: cmd.description,
84
+ ...(cmd.aliases?.length ? { aliases: cmd.aliases } : {}),
85
+ args: cmd.args.map(compactArg),
86
+ example: formatCommandExample(cmd),
87
+ ...(opts.includeColumns && cmd.columns?.length ? { columns: cmd.columns } : {}),
88
+ ...(cmd.deprecated ? { deprecated: cmd.deprecated } : {}),
89
+ ...(cmd.replacedBy ? { replacedBy: cmd.replacedBy } : {}),
90
+ };
91
+ }
92
+ export function rootHelpData(program, siteNames) {
93
+ const siteSet = new Set(siteNames);
94
+ const commands = program.commands
95
+ .filter(command => !siteSet.has(command.name()))
96
+ .map(command => ({
97
+ name: command.name(),
98
+ description: command.description(),
99
+ }));
100
+ return {
101
+ name: program.name(),
102
+ description: program.description(),
103
+ commands,
104
+ site_adapters: {
105
+ count: siteNames.length,
106
+ sites: [...siteNames].sort((a, b) => a.localeCompare(b)),
107
+ },
108
+ next: [
109
+ 'opencli <site> --help -f yaml',
110
+ 'opencli list -f yaml',
111
+ 'opencli <site> <command> -f yaml',
112
+ ],
113
+ };
114
+ }
115
+ export function siteHelpData(site, commands) {
116
+ const unique = [...new Map(commands.map(cmd => [fullName(cmd), cmd])).values()]
117
+ .sort((a, b) => a.name.localeCompare(b.name));
118
+ return {
119
+ site,
120
+ command_count: unique.length,
121
+ commands: unique.map(cmd => compactCommand(cmd)),
122
+ next: [
123
+ `opencli ${site} <command> --help -f yaml`,
124
+ `opencli ${site} <command> -f yaml`,
125
+ ],
126
+ };
127
+ }
128
+ export function commandHelpData(cmd) {
129
+ return {
130
+ site: cmd.site,
131
+ ...compactCommand(cmd, { includeColumns: true }),
132
+ output_formats: ['table', 'plain', 'yaml', 'json', 'md', 'csv'],
133
+ };
134
+ }
135
+ export function installStructuredHelp(command, data, textSuffix) {
136
+ const original = command.helpInformation.bind(command);
137
+ command.helpInformation = ((contextOptions) => {
138
+ const format = getRequestedHelpFormat();
139
+ if (format)
140
+ return renderStructuredHelp(data(), format);
141
+ const suffix = typeof textSuffix === 'function' ? textSuffix() : textSuffix ?? '';
142
+ return original(contextOptions) + suffix;
143
+ });
144
+ }
145
+ export function formatSiteCommandDescription(cmd) {
146
+ const access = cmd.access === 'write' ? '[write]' : '[read]';
147
+ const deprecatedSuffix = cmd.deprecated ? ' [deprecated]' : '';
148
+ return `${access} ${cmd.description}${deprecatedSuffix}`;
149
+ }
package/dist/src/main.js CHANGED
@@ -118,13 +118,19 @@ installNodeNetwork();
118
118
  // user-CLI discovery MUST run after built-in discovery to preserve the
119
119
  // intended override order (user adapters override built-in ones).
120
120
  // - discoverPlugins runs last: plugins may override both built-in and user CLIs.
121
- const [, ,] = await Promise.all([
122
- ensureUserCliCompatShims(),
123
- ensureUserAdapters(),
124
- discoverClis(BUILTIN_CLIS),
125
- ]);
126
- await discoverClis(USER_CLIS);
127
- await discoverPlugins();
121
+ const skipUserDiscovery = argv[0] === 'convention-audit';
122
+ if (skipUserDiscovery) {
123
+ await discoverClis(BUILTIN_CLIS);
124
+ }
125
+ else {
126
+ const [, ,] = await Promise.all([
127
+ ensureUserCliCompatShims(),
128
+ ensureUserAdapters(),
129
+ discoverClis(BUILTIN_CLIS),
130
+ ]);
131
+ await discoverClis(USER_CLIS);
132
+ await discoverPlugins();
133
+ }
128
134
  // Register exit hook: notice appears after command output (same as npm/gh/yarn)
129
135
  registerUpdateNoticeOnExit();
130
136
  // Kick off background fetch for next run (non-blocking)
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Shared manifest types — kept in their own module so both runtime code
3
+ * (discovery.ts) and the build-time compiler (build-manifest.ts) can
4
+ * import them without pulling each other in. This is what lets us
5
+ * exclude `src/build-manifest.ts` from `tsc`'s emit set: the only thing
6
+ * runtime code needs from build-manifest is the `ManifestEntry` type,
7
+ * and that lives here.
8
+ */
9
+ export interface ManifestEntry {
10
+ site: string;
11
+ name: string;
12
+ aliases?: string[];
13
+ description: string;
14
+ access: 'read' | 'write';
15
+ example?: string;
16
+ domain?: string;
17
+ strategy: string;
18
+ browser: boolean;
19
+ args: Array<{
20
+ name: string;
21
+ type?: string;
22
+ default?: unknown;
23
+ required?: boolean;
24
+ valueRequired?: boolean;
25
+ positional?: boolean;
26
+ help?: string;
27
+ choices?: string[];
28
+ }>;
29
+ columns?: string[];
30
+ pipeline?: Record<string, unknown>[];
31
+ timeout?: number;
32
+ deprecated?: boolean | string;
33
+ replacedBy?: string;
34
+ type: 'js';
35
+ /** Relative path from clis/ dir, e.g. 'bilibili/search.js' */
36
+ modulePath?: string;
37
+ /** Relative path to the source file from clis/ dir (e.g. 'site/cmd.js') */
38
+ sourceFile?: string;
39
+ /** Pre-navigation control — see CliCommand.navigateBefore */
40
+ navigateBefore?: boolean | string;
41
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Shared manifest types — kept in their own module so both runtime code
3
+ * (discovery.ts) and the build-time compiler (build-manifest.ts) can
4
+ * import them without pulling each other in. This is what lets us
5
+ * exclude `src/build-manifest.ts` from `tsc`'s emit set: the only thing
6
+ * runtime code needs from build-manifest is the `ManifestEntry` type,
7
+ * and that lives here.
8
+ */
9
+ export {};
@@ -361,7 +361,7 @@ describe('listPlugins', () => {
361
361
  });
362
362
  it('lists installed plugins', () => {
363
363
  fs.mkdirSync(testDir, { recursive: true });
364
- fs.writeFileSync(path.join(testDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
364
+ fs.writeFileSync(path.join(testDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
365
365
  const plugins = listPlugins();
366
366
  const found = plugins.find(p => p.name === '__test-list-plugin__');
367
367
  expect(found).toBeDefined();
@@ -369,7 +369,7 @@ describe('listPlugins', () => {
369
369
  });
370
370
  it('includes version metadata from the lock file', () => {
371
371
  fs.mkdirSync(testDir, { recursive: true });
372
- fs.writeFileSync(path.join(testDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
372
+ fs.writeFileSync(path.join(testDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
373
373
  const lock = _readLockFile();
374
374
  lock['__test-list-plugin__'] = {
375
375
  source: { kind: 'git', url: 'https://github.com/user/repo.git' },
@@ -393,7 +393,7 @@ describe('listPlugins', () => {
393
393
  const localTarget = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-list-'));
394
394
  const linkPath = path.join(PLUGINS_DIR, '__test-list-plugin__');
395
395
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
396
- fs.writeFileSync(path.join(localTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
396
+ fs.writeFileSync(path.join(localTarget, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
397
397
  try {
398
398
  fs.unlinkSync(linkPath);
399
399
  }
@@ -435,13 +435,13 @@ describe('uninstallPlugin', () => {
435
435
  });
436
436
  it('removes plugin directory', () => {
437
437
  fs.mkdirSync(testDir, { recursive: true });
438
- fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test" })');
438
+ fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test", access: "read" })');
439
439
  uninstallPlugin('__test-uninstall__');
440
440
  expect(fs.existsSync(testDir)).toBe(false);
441
441
  });
442
442
  it('removes lock entry on uninstall', () => {
443
443
  fs.mkdirSync(testDir, { recursive: true });
444
- fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test" })');
444
+ fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test", access: "read" })');
445
445
  const lock = _readLockFile();
446
446
  lock['__test-uninstall__'] = {
447
447
  source: { kind: 'git', url: 'https://github.com/user/repo.git' },
@@ -464,7 +464,7 @@ describe('updatePlugin', () => {
464
464
  const localTarget = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-update-'));
465
465
  const linkPath = path.join(PLUGINS_DIR, '__test-local-update__');
466
466
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
467
- fs.writeFileSync(path.join(localTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
467
+ fs.writeFileSync(path.join(localTarget, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
468
468
  fs.symlinkSync(localTarget, linkPath, 'dir');
469
469
  const lock = _readLockFile();
470
470
  lock['__test-local-update__'] = {
@@ -540,7 +540,7 @@ describe('postInstallMonorepoLifecycle', () => {
540
540
  private: true,
541
541
  workspaces: ['packages/*'],
542
542
  }));
543
- fs.writeFileSync(path.join(subDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
543
+ fs.writeFileSync(path.join(subDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
544
544
  });
545
545
  afterEach(() => {
546
546
  fs.rmSync(repoDir, { recursive: true, force: true });
@@ -575,9 +575,9 @@ describe('updateAllPlugins', () => {
575
575
  fs.mkdirSync(testDirA, { recursive: true });
576
576
  fs.mkdirSync(testDirB, { recursive: true });
577
577
  fs.mkdirSync(testDirC, { recursive: true });
578
- fs.writeFileSync(path.join(testDirA, 'cmd.js'), 'cli({ site: "a", name: "cmd" })');
579
- fs.writeFileSync(path.join(testDirB, 'cmd.js'), 'cli({ site: "b", name: "cmd" })');
580
- fs.writeFileSync(path.join(testDirC, 'cmd.js'), 'cli({ site: "c", name: "cmd" })');
578
+ fs.writeFileSync(path.join(testDirA, 'cmd.js'), 'cli({ site: "a", name: "cmd", access: "read" })');
579
+ fs.writeFileSync(path.join(testDirB, 'cmd.js'), 'cli({ site: "b", name: "cmd", access: "read" })');
580
+ fs.writeFileSync(path.join(testDirC, 'cmd.js'), 'cli({ site: "c", name: "cmd", access: "read" })');
581
581
  const lock = _readLockFile();
582
582
  lock['plugin-a'] = {
583
583
  source: { kind: 'git', url: 'https://github.com/user/plugin-a.git' },
@@ -622,7 +622,7 @@ describe('updateAllPlugins', () => {
622
622
  const cloneUrl = String(args[3]);
623
623
  const cloneDir = String(args[4]);
624
624
  fs.mkdirSync(cloneDir, { recursive: true });
625
- fs.writeFileSync(path.join(cloneDir, 'cmd.js'), 'cli({ site: "test", name: "hello" })');
625
+ fs.writeFileSync(path.join(cloneDir, 'cmd.js'), 'cli({ site: "test", name: "hello", access: "read" })');
626
626
  if (cloneUrl.includes('plugin-b')) {
627
627
  fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: 'plugin-b' }));
628
628
  }
@@ -709,7 +709,7 @@ describe('monorepo uninstall with symlink', () => {
709
709
  monoDir = path.join(_getMonoreposDir(), '__test-mono__');
710
710
  const subDir = path.join(monoDir, 'packages', 'sub');
711
711
  fs.mkdirSync(subDir, { recursive: true });
712
- fs.writeFileSync(path.join(subDir, 'cmd.js'), 'cli({ site: "test", name: "cmd" })');
712
+ fs.writeFileSync(path.join(subDir, 'cmd.js'), 'cli({ site: "test", name: "cmd", access: "read" })');
713
713
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
714
714
  fs.symlinkSync(subDir, pluginDir, 'dir');
715
715
  const lock = _readLockFile();
@@ -776,7 +776,7 @@ describe('listPlugins with monorepo metadata', () => {
776
776
  const testLink = path.join(PLUGINS_DIR, '__test-mono-list__');
777
777
  beforeEach(() => {
778
778
  fs.mkdirSync(testSymlinkTarget, { recursive: true });
779
- fs.writeFileSync(path.join(testSymlinkTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
779
+ fs.writeFileSync(path.join(testSymlinkTarget, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
780
780
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
781
781
  try {
782
782
  fs.unlinkSync(testLink);
@@ -823,7 +823,7 @@ describe('installLocalPlugin', () => {
823
823
  const pluginName = '__test-local-plugin__';
824
824
  beforeEach(() => {
825
825
  tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-install-'));
826
- fs.writeFileSync(path.join(tmpDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
826
+ fs.writeFileSync(path.join(tmpDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
827
827
  });
828
828
  afterEach(() => {
829
829
  const linkPath = path.join(PLUGINS_DIR, pluginName);
@@ -963,7 +963,7 @@ describe('installPlugin transactional staging', () => {
963
963
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
964
964
  const cloneDir = String(args[args.length - 1]);
965
965
  fs.mkdirSync(cloneDir, { recursive: true });
966
- fs.writeFileSync(path.join(cloneDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
966
+ fs.writeFileSync(path.join(cloneDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
967
967
  fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: standaloneName }));
968
968
  return '';
969
969
  }
@@ -994,7 +994,7 @@ describe('installPlugin transactional staging', () => {
994
994
  alpha: { path: 'packages/alpha' },
995
995
  },
996
996
  }));
997
- fs.writeFileSync(path.join(alphaDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
997
+ fs.writeFileSync(path.join(alphaDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
998
998
  return '';
999
999
  }
1000
1000
  if (cmd === 'npm' && Array.isArray(args) && args[0] === 'install') {
@@ -1051,7 +1051,7 @@ describe('installPlugin with existing monorepo', () => {
1051
1051
  [pluginName]: { path: `packages/${pluginName}` },
1052
1052
  },
1053
1053
  }));
1054
- fs.writeFileSync(path.join(subDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1054
+ fs.writeFileSync(path.join(subDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
1055
1055
  mockExecFileSync.mockImplementation((cmd, args) => {
1056
1056
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
1057
1057
  const cloneDir = String(args[4]);
@@ -1110,7 +1110,7 @@ describe('updatePlugin transactional staging', () => {
1110
1110
  });
1111
1111
  it('keeps the existing standalone plugin when staged update preparation fails', () => {
1112
1112
  fs.mkdirSync(standaloneDir, { recursive: true });
1113
- fs.writeFileSync(path.join(standaloneDir, 'old.js'), 'cli({ site: "old", name: "old" })');
1113
+ fs.writeFileSync(path.join(standaloneDir, 'old.js'), 'cli({ site: "old", name: "old", access: "read" })');
1114
1114
  const lock = _readLockFile();
1115
1115
  lock[standaloneName] = {
1116
1116
  source: {
@@ -1125,7 +1125,7 @@ describe('updatePlugin transactional staging', () => {
1125
1125
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
1126
1126
  const cloneDir = String(args[4]);
1127
1127
  fs.mkdirSync(cloneDir, { recursive: true });
1128
- fs.writeFileSync(path.join(cloneDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1128
+ fs.writeFileSync(path.join(cloneDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
1129
1129
  fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: standaloneName }));
1130
1130
  return '';
1131
1131
  }
@@ -1145,7 +1145,7 @@ describe('updatePlugin transactional staging', () => {
1145
1145
  it('keeps the existing monorepo repo and link when staged update preparation fails', () => {
1146
1146
  const subDir = path.join(monorepoRepoDir, 'packages', monorepoPluginName);
1147
1147
  fs.mkdirSync(subDir, { recursive: true });
1148
- fs.writeFileSync(path.join(subDir, 'old.js'), 'cli({ site: "old", name: "old" })');
1148
+ fs.writeFileSync(path.join(subDir, 'old.js'), 'cli({ site: "old", name: "old", access: "read" })');
1149
1149
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
1150
1150
  fs.symlinkSync(subDir, monorepoLink, 'dir');
1151
1151
  const lock = _readLockFile();
@@ -1174,7 +1174,7 @@ describe('updatePlugin transactional staging', () => {
1174
1174
  [monorepoPluginName]: { path: `packages/${monorepoPluginName}` },
1175
1175
  },
1176
1176
  }));
1177
- fs.writeFileSync(path.join(alphaDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1177
+ fs.writeFileSync(path.join(alphaDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
1178
1178
  return '';
1179
1179
  }
1180
1180
  if (cmd === 'npm' && Array.isArray(args) && args[0] === 'install') {
@@ -1194,7 +1194,7 @@ describe('updatePlugin transactional staging', () => {
1194
1194
  it('relinks monorepo plugins when the updated manifest moves their subPath', () => {
1195
1195
  const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
1196
1196
  fs.mkdirSync(oldSubDir, { recursive: true });
1197
- fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old" })');
1197
+ fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old", access: "read" })');
1198
1198
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
1199
1199
  fs.symlinkSync(oldSubDir, monorepoLink, 'dir');
1200
1200
  const lock = _readLockFile();
@@ -1219,7 +1219,7 @@ describe('updatePlugin transactional staging', () => {
1219
1219
  [monorepoPluginName]: { path: 'packages/moved-alpha' },
1220
1220
  },
1221
1221
  }));
1222
- fs.writeFileSync(path.join(movedDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1222
+ fs.writeFileSync(path.join(movedDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
1223
1223
  return '';
1224
1224
  }
1225
1225
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'rev-parse' && args[1] === 'HEAD') {
@@ -1238,7 +1238,7 @@ describe('updatePlugin transactional staging', () => {
1238
1238
  it('rejects monorepo updates whose manifest path escapes the repo root', () => {
1239
1239
  const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
1240
1240
  fs.mkdirSync(oldSubDir, { recursive: true });
1241
- fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old" })');
1241
+ fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old", access: "read" })');
1242
1242
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
1243
1243
  fs.symlinkSync(oldSubDir, monorepoLink, 'dir');
1244
1244
  const lock = _readLockFile();
@@ -1279,7 +1279,7 @@ describe('updatePlugin transactional staging', () => {
1279
1279
  it('rolls back the monorepo repo swap when relinking fails', () => {
1280
1280
  const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
1281
1281
  fs.mkdirSync(oldSubDir, { recursive: true });
1282
- fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old" })');
1282
+ fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old", access: "read" })');
1283
1283
  fs.mkdirSync(monorepoLink, { recursive: true });
1284
1284
  fs.writeFileSync(path.join(monorepoLink, 'blocker.txt'), 'not a symlink');
1285
1285
  const lock = _readLockFile();
@@ -1304,7 +1304,7 @@ describe('updatePlugin transactional staging', () => {
1304
1304
  [monorepoPluginName]: { path: 'packages/moved-alpha' },
1305
1305
  },
1306
1306
  }));
1307
- fs.writeFileSync(path.join(movedDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1307
+ fs.writeFileSync(path.join(movedDir, 'hello.js'), 'cli({ site: "test", name: "hello", access: "read" })');
1308
1308
  return '';
1309
1309
  }
1310
1310
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'rev-parse' && args[1] === 'HEAD') {
@@ -27,11 +27,15 @@ export interface RequiredEnv {
27
27
  export type CommandArgs = Record<string, any>;
28
28
  export type BrowserCommandFunc = (page: IPage, kwargs: CommandArgs, debug?: boolean) => Promise<unknown>;
29
29
  export type NonBrowserCommandFunc = (kwargs: CommandArgs, debug?: boolean) => Promise<unknown>;
30
+ export type CommandAccess = 'read' | 'write';
30
31
  interface BaseCliCommand {
31
32
  site: string;
32
33
  name: string;
33
34
  aliases?: string[];
34
35
  description: string;
36
+ access: CommandAccess;
37
+ /** Canonical invocation shown in agent-facing help. Generated when omitted. */
38
+ example?: string;
35
39
  domain?: string;
36
40
  strategy?: Strategy;
37
41
  args: Arg[];
@@ -89,6 +93,7 @@ export type InternalCliCommand = CliCommand & {
89
93
  type RequiredCliOptions = {
90
94
  site: string;
91
95
  name: string;
96
+ access: CommandAccess;
92
97
  description?: string;
93
98
  args?: Arg[];
94
99
  };
@@ -17,6 +17,7 @@ export function cli(opts) {
17
17
  name: opts.name,
18
18
  aliases: opts.aliases,
19
19
  description: opts.description ?? '',
20
+ access: opts.access,
20
21
  domain: opts.domain,
21
22
  strategy: opts.strategy,
22
23
  browser: opts.browser,
@@ -58,6 +59,7 @@ export function strategyLabel(cmd) {
58
59
  * 2. Derived from strategy + domain (the defaults below)
59
60
  */
60
61
  function normalizeCommand(cmd) {
62
+ assertCommandAccess(cmd);
61
63
  const strategy = cmd.strategy ?? (cmd.browser === false ? Strategy.PUBLIC : Strategy.COOKIE);
62
64
  const browser = cmd.browser ?? (strategy !== Strategy.PUBLIC && strategy !== Strategy.LOCAL);
63
65
  let navigateBefore = cmd.navigateBefore;
@@ -76,6 +78,12 @@ function normalizeCommand(cmd) {
76
78
  ? { ...cmd, strategy, browser: true, navigateBefore }
77
79
  : { ...cmd, strategy, browser: false, navigateBefore };
78
80
  }
81
+ function assertCommandAccess(cmd) {
82
+ if (cmd.access === 'read' || cmd.access === 'write')
83
+ return;
84
+ const key = `${cmd.site}/${cmd.name}`;
85
+ throw new Error(`Command ${key} must declare access: 'read' | 'write'`);
86
+ }
79
87
  export function registerCommand(cmd) {
80
88
  const normalized = normalizeCommand(cmd);
81
89
  const canonicalKey = fullName(normalized);