@jackwener/opencli 1.6.8 → 1.6.10

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 (572) hide show
  1. package/README.md +117 -59
  2. package/README.zh-CN.md +123 -79
  3. package/dist/clis/_shared/common.d.ts +3 -0
  4. package/dist/clis/_shared/common.js +22 -0
  5. package/dist/clis/bilibili/hot.d.ts +1 -0
  6. package/dist/clis/bilibili/hot.js +35 -0
  7. package/dist/clis/bluesky/feeds.d.ts +1 -0
  8. package/dist/clis/bluesky/feeds.js +27 -0
  9. package/dist/clis/bluesky/followers.d.ts +1 -0
  10. package/dist/clis/bluesky/followers.js +27 -0
  11. package/dist/clis/bluesky/following.d.ts +1 -0
  12. package/dist/clis/bluesky/following.js +27 -0
  13. package/dist/clis/bluesky/profile.d.ts +1 -0
  14. package/dist/clis/bluesky/profile.js +29 -0
  15. package/dist/clis/bluesky/search.d.ts +1 -0
  16. package/dist/clis/bluesky/search.js +28 -0
  17. package/dist/clis/bluesky/starter-packs.d.ts +1 -0
  18. package/dist/clis/bluesky/starter-packs.js +28 -0
  19. package/dist/clis/bluesky/thread.d.ts +1 -0
  20. package/dist/clis/bluesky/thread.js +30 -0
  21. package/dist/clis/bluesky/trending.d.ts +1 -0
  22. package/dist/clis/bluesky/trending.js +19 -0
  23. package/dist/clis/bluesky/user.d.ts +1 -0
  24. package/dist/clis/bluesky/user.js +33 -0
  25. package/dist/clis/cnki/search.d.ts +1 -0
  26. package/dist/clis/cnki/search.js +60 -0
  27. package/dist/clis/cnki/search.test.d.ts +1 -0
  28. package/dist/clis/cnki/search.test.js +18 -0
  29. package/dist/clis/devto/tag.d.ts +1 -0
  30. package/dist/clis/devto/tag.js +32 -0
  31. package/dist/clis/devto/top.d.ts +1 -0
  32. package/dist/clis/devto/top.js +26 -0
  33. package/dist/clis/devto/user.d.ts +1 -0
  34. package/dist/clis/devto/user.js +31 -0
  35. package/dist/clis/dictionary/examples.d.ts +1 -0
  36. package/dist/clis/dictionary/examples.js +27 -0
  37. package/dist/clis/dictionary/search.d.ts +1 -0
  38. package/dist/clis/dictionary/search.js +29 -0
  39. package/dist/clis/dictionary/synonyms.d.ts +1 -0
  40. package/dist/clis/dictionary/synonyms.js +27 -0
  41. package/dist/clis/douban/subject.d.ts +1 -0
  42. package/dist/clis/douban/subject.js +118 -0
  43. package/dist/clis/douban/top250.d.ts +1 -0
  44. package/dist/clis/douban/top250.js +67 -0
  45. package/dist/clis/facebook/add-friend.d.ts +1 -0
  46. package/dist/clis/facebook/add-friend.js +43 -0
  47. package/dist/clis/facebook/events.d.ts +1 -0
  48. package/dist/clis/facebook/events.js +40 -0
  49. package/dist/clis/facebook/feed.d.ts +1 -0
  50. package/dist/clis/facebook/feed.js +59 -0
  51. package/dist/clis/facebook/friends.d.ts +1 -0
  52. package/dist/clis/facebook/friends.js +38 -0
  53. package/dist/clis/facebook/groups.d.ts +1 -0
  54. package/dist/clis/facebook/groups.js +46 -0
  55. package/dist/clis/facebook/join-group.d.ts +1 -0
  56. package/dist/clis/facebook/join-group.js +44 -0
  57. package/dist/clis/facebook/memories.d.ts +1 -0
  58. package/dist/clis/facebook/memories.js +35 -0
  59. package/dist/clis/facebook/notifications.d.ts +1 -0
  60. package/dist/clis/facebook/notifications.js +36 -0
  61. package/dist/clis/facebook/profile.d.ts +1 -0
  62. package/dist/clis/facebook/profile.js +37 -0
  63. package/dist/clis/facebook/search.d.ts +1 -0
  64. package/dist/clis/facebook/search.js +38 -0
  65. package/dist/clis/facebook/search.test.d.ts +1 -1
  66. package/dist/clis/facebook/search.test.js +6 -9
  67. package/dist/clis/gitee/index.d.ts +3 -0
  68. package/dist/clis/gitee/index.js +3 -0
  69. package/dist/clis/gitee/search.d.ts +1 -0
  70. package/dist/clis/gitee/search.js +136 -0
  71. package/dist/clis/gitee/trending.d.ts +1 -0
  72. package/dist/clis/gitee/trending.js +567 -0
  73. package/dist/clis/gitee/user.d.ts +1 -0
  74. package/dist/clis/gitee/user.js +199 -0
  75. package/dist/clis/gitee/user.test.d.ts +1 -0
  76. package/dist/clis/gitee/user.test.js +63 -0
  77. package/dist/clis/hackernews/ask.d.ts +1 -0
  78. package/dist/clis/hackernews/ask.js +29 -0
  79. package/dist/clis/hackernews/best.d.ts +1 -0
  80. package/dist/clis/hackernews/best.js +29 -0
  81. package/dist/clis/hackernews/jobs.d.ts +1 -0
  82. package/dist/clis/hackernews/jobs.js +27 -0
  83. package/dist/clis/hackernews/new.d.ts +1 -0
  84. package/dist/clis/hackernews/new.js +29 -0
  85. package/dist/clis/hackernews/search.d.ts +1 -0
  86. package/dist/clis/hackernews/search.js +36 -0
  87. package/dist/clis/hackernews/show.d.ts +1 -0
  88. package/dist/clis/hackernews/show.js +29 -0
  89. package/dist/clis/hackernews/top.d.ts +1 -0
  90. package/dist/clis/hackernews/top.js +29 -0
  91. package/dist/clis/hackernews/user.d.ts +1 -0
  92. package/dist/clis/hackernews/user.js +22 -0
  93. package/dist/clis/hupu/hot.d.ts +1 -0
  94. package/dist/clis/hupu/hot.js +40 -0
  95. package/dist/clis/instagram/comment.d.ts +1 -0
  96. package/dist/clis/instagram/comment.js +47 -0
  97. package/dist/clis/instagram/explore.d.ts +1 -0
  98. package/dist/clis/instagram/explore.js +41 -0
  99. package/dist/clis/instagram/follow.d.ts +1 -0
  100. package/dist/clis/instagram/follow.js +43 -0
  101. package/dist/clis/instagram/followers.d.ts +1 -0
  102. package/dist/clis/instagram/followers.js +45 -0
  103. package/dist/clis/instagram/following.d.ts +1 -0
  104. package/dist/clis/instagram/following.js +45 -0
  105. package/dist/clis/instagram/like.d.ts +1 -0
  106. package/dist/clis/instagram/like.js +45 -0
  107. package/dist/clis/instagram/profile.d.ts +1 -0
  108. package/dist/clis/instagram/profile.js +39 -0
  109. package/dist/clis/instagram/save.d.ts +1 -0
  110. package/dist/clis/instagram/save.js +45 -0
  111. package/dist/clis/instagram/saved.d.ts +1 -0
  112. package/dist/clis/instagram/saved.js +38 -0
  113. package/dist/clis/instagram/search.d.ts +1 -0
  114. package/dist/clis/instagram/search.js +38 -0
  115. package/dist/clis/instagram/unfollow.d.ts +1 -0
  116. package/dist/clis/instagram/unfollow.js +40 -0
  117. package/dist/clis/instagram/unlike.d.ts +1 -0
  118. package/dist/clis/instagram/unlike.js +45 -0
  119. package/dist/clis/instagram/unsave.d.ts +1 -0
  120. package/dist/clis/instagram/unsave.js +45 -0
  121. package/dist/clis/instagram/user.d.ts +1 -0
  122. package/dist/clis/instagram/user.js +48 -0
  123. package/dist/clis/jd/add-cart.d.ts +1 -0
  124. package/dist/clis/jd/add-cart.js +71 -0
  125. package/dist/clis/jd/cart.d.ts +1 -0
  126. package/dist/clis/jd/cart.js +79 -0
  127. package/dist/clis/jd/commands.test.d.ts +5 -0
  128. package/dist/clis/jd/commands.test.js +64 -0
  129. package/dist/clis/jd/detail.d.ts +1 -0
  130. package/dist/clis/jd/detail.js +62 -0
  131. package/dist/clis/jd/reviews.d.ts +1 -0
  132. package/dist/clis/jd/reviews.js +54 -0
  133. package/dist/clis/jd/search.d.ts +1 -0
  134. package/dist/clis/jd/search.js +65 -0
  135. package/dist/clis/jianyu/search.d.ts +14 -0
  136. package/dist/clis/jianyu/search.js +135 -0
  137. package/dist/clis/jianyu/search.test.d.ts +1 -0
  138. package/dist/clis/jianyu/search.test.js +23 -0
  139. package/dist/clis/jike/post.d.ts +1 -0
  140. package/dist/clis/jike/post.js +61 -0
  141. package/dist/clis/jike/topic.d.ts +1 -0
  142. package/dist/clis/jike/topic.js +51 -0
  143. package/dist/clis/jike/user.d.ts +1 -0
  144. package/dist/clis/jike/user.js +50 -0
  145. package/dist/clis/jimeng/generate.d.ts +1 -0
  146. package/dist/clis/jimeng/generate.js +83 -0
  147. package/dist/clis/jimeng/history.d.ts +1 -0
  148. package/dist/clis/jimeng/history.js +47 -0
  149. package/dist/clis/jimeng/new.d.ts +1 -0
  150. package/dist/clis/jimeng/new.js +43 -0
  151. package/dist/clis/jimeng/workspaces.d.ts +1 -0
  152. package/dist/clis/jimeng/workspaces.js +41 -0
  153. package/dist/clis/linux-do/categories.d.ts +1 -0
  154. package/dist/clis/linux-do/categories.js +65 -0
  155. package/dist/clis/linux-do/search.d.ts +1 -0
  156. package/dist/clis/linux-do/search.js +41 -0
  157. package/dist/clis/linux-do/tags.d.ts +1 -0
  158. package/dist/clis/linux-do/tags.js +39 -0
  159. package/dist/clis/linux-do/topic-content.test.js +5 -5
  160. package/dist/clis/linux-do/topic.d.ts +1 -0
  161. package/dist/clis/linux-do/topic.js +56 -0
  162. package/dist/clis/linux-do/user-posts.d.ts +1 -0
  163. package/dist/clis/linux-do/user-posts.js +61 -0
  164. package/dist/clis/linux-do/user-topics.d.ts +1 -0
  165. package/dist/clis/linux-do/user-topics.js +48 -0
  166. package/dist/clis/lobsters/active.d.ts +1 -0
  167. package/dist/clis/lobsters/active.js +26 -0
  168. package/dist/clis/lobsters/hot.d.ts +1 -0
  169. package/dist/clis/lobsters/hot.js +26 -0
  170. package/dist/clis/lobsters/newest.d.ts +1 -0
  171. package/dist/clis/lobsters/newest.js +26 -0
  172. package/dist/clis/lobsters/tag.d.ts +1 -0
  173. package/dist/clis/lobsters/tag.js +32 -0
  174. package/dist/clis/pixiv/detail.d.ts +1 -0
  175. package/dist/clis/pixiv/detail.js +58 -0
  176. package/dist/clis/pixiv/ranking.d.ts +1 -0
  177. package/dist/clis/pixiv/ranking.js +59 -0
  178. package/dist/clis/pixiv/user.d.ts +1 -0
  179. package/dist/clis/pixiv/user.js +52 -0
  180. package/dist/clis/quark/ls.d.ts +1 -0
  181. package/dist/clis/quark/ls.js +63 -0
  182. package/dist/clis/quark/mkdir.d.ts +1 -0
  183. package/dist/clis/quark/mkdir.js +36 -0
  184. package/dist/clis/quark/mv.d.ts +1 -0
  185. package/dist/clis/quark/mv.js +53 -0
  186. package/dist/clis/quark/rename.d.ts +1 -0
  187. package/dist/clis/quark/rename.js +26 -0
  188. package/dist/clis/quark/rm.d.ts +1 -0
  189. package/dist/clis/quark/rm.js +24 -0
  190. package/dist/clis/quark/save.d.ts +1 -0
  191. package/dist/clis/quark/save.js +80 -0
  192. package/dist/clis/quark/share-tree.d.ts +1 -0
  193. package/dist/clis/quark/share-tree.js +45 -0
  194. package/dist/clis/quark/utils.d.ts +50 -0
  195. package/dist/clis/quark/utils.js +146 -0
  196. package/dist/clis/quark/utils.test.d.ts +1 -0
  197. package/dist/clis/quark/utils.test.js +58 -0
  198. package/dist/clis/reddit/frontpage.d.ts +1 -0
  199. package/dist/clis/reddit/frontpage.js +31 -0
  200. package/dist/clis/reddit/hot.d.ts +1 -0
  201. package/dist/clis/reddit/hot.js +45 -0
  202. package/dist/clis/reddit/popular.d.ts +1 -0
  203. package/dist/clis/reddit/popular.js +41 -0
  204. package/dist/clis/reddit/search.d.ts +1 -0
  205. package/dist/clis/reddit/search.js +65 -0
  206. package/dist/clis/reddit/subreddit.d.ts +1 -0
  207. package/dist/clis/reddit/subreddit.js +52 -0
  208. package/dist/clis/reddit/user-comments.d.ts +1 -0
  209. package/dist/clis/reddit/user-comments.js +44 -0
  210. package/dist/clis/reddit/user-posts.d.ts +1 -0
  211. package/dist/clis/reddit/user-posts.js +42 -0
  212. package/dist/clis/reddit/user.d.ts +1 -0
  213. package/dist/clis/reddit/user.js +37 -0
  214. package/dist/clis/stackoverflow/bounties.d.ts +1 -0
  215. package/dist/clis/stackoverflow/bounties.js +27 -0
  216. package/dist/clis/stackoverflow/hot.d.ts +1 -0
  217. package/dist/clis/stackoverflow/hot.js +24 -0
  218. package/dist/clis/stackoverflow/search.d.ts +1 -0
  219. package/dist/clis/stackoverflow/search.js +27 -0
  220. package/dist/clis/stackoverflow/unanswered.d.ts +1 -0
  221. package/dist/clis/stackoverflow/unanswered.js +26 -0
  222. package/dist/clis/steam/top-sellers.d.ts +1 -0
  223. package/dist/clis/steam/top-sellers.js +25 -0
  224. package/dist/clis/taobao/add-cart.d.ts +1 -0
  225. package/dist/clis/taobao/add-cart.js +149 -0
  226. package/dist/clis/taobao/cart.d.ts +1 -0
  227. package/dist/clis/taobao/cart.js +95 -0
  228. package/dist/clis/taobao/commands.test.d.ts +5 -0
  229. package/dist/clis/taobao/commands.test.js +64 -0
  230. package/dist/clis/taobao/detail.d.ts +1 -0
  231. package/dist/clis/taobao/detail.js +70 -0
  232. package/dist/clis/taobao/reviews.d.ts +1 -0
  233. package/dist/clis/taobao/reviews.js +76 -0
  234. package/dist/clis/taobao/search.d.ts +1 -0
  235. package/dist/clis/taobao/search.js +96 -0
  236. package/dist/clis/tiktok/comment.d.ts +1 -0
  237. package/dist/clis/tiktok/comment.js +57 -0
  238. package/dist/clis/tiktok/explore.d.ts +1 -0
  239. package/dist/clis/tiktok/explore.js +35 -0
  240. package/dist/clis/tiktok/follow.d.ts +1 -0
  241. package/dist/clis/tiktok/follow.js +39 -0
  242. package/dist/clis/tiktok/following.d.ts +1 -0
  243. package/dist/clis/tiktok/following.js +42 -0
  244. package/dist/clis/tiktok/friends.d.ts +1 -0
  245. package/dist/clis/tiktok/friends.js +43 -0
  246. package/dist/clis/tiktok/like.d.ts +1 -0
  247. package/dist/clis/tiktok/like.js +33 -0
  248. package/dist/clis/tiktok/live.d.ts +1 -0
  249. package/dist/clis/tiktok/live.js +47 -0
  250. package/dist/clis/tiktok/notifications.d.ts +1 -0
  251. package/dist/clis/tiktok/notifications.js +49 -0
  252. package/dist/clis/tiktok/profile.d.ts +1 -0
  253. package/dist/clis/tiktok/profile.js +54 -0
  254. package/dist/clis/tiktok/save.d.ts +1 -0
  255. package/dist/clis/tiktok/save.js +29 -0
  256. package/dist/clis/tiktok/search.d.ts +1 -0
  257. package/dist/clis/tiktok/search.js +39 -0
  258. package/dist/clis/tiktok/unfollow.d.ts +1 -0
  259. package/dist/clis/tiktok/unfollow.js +44 -0
  260. package/dist/clis/tiktok/unlike.d.ts +1 -0
  261. package/dist/clis/tiktok/unlike.js +33 -0
  262. package/dist/clis/tiktok/unsave.d.ts +1 -0
  263. package/dist/clis/tiktok/unsave.js +31 -0
  264. package/dist/clis/tiktok/user.d.ts +1 -0
  265. package/dist/clis/tiktok/user.js +41 -0
  266. package/dist/clis/twitter/reply.js +3 -8
  267. package/dist/clis/twitter/reply.test.js +5 -5
  268. package/dist/clis/v2ex/hot.d.ts +1 -0
  269. package/dist/clis/v2ex/hot.js +25 -0
  270. package/dist/clis/v2ex/latest.d.ts +1 -0
  271. package/dist/clis/v2ex/latest.js +25 -0
  272. package/dist/clis/v2ex/member.d.ts +1 -0
  273. package/dist/clis/v2ex/member.js +27 -0
  274. package/dist/clis/v2ex/node.d.ts +1 -0
  275. package/dist/clis/v2ex/node.js +38 -0
  276. package/dist/clis/v2ex/nodes.d.ts +1 -0
  277. package/dist/clis/v2ex/nodes.js +25 -0
  278. package/dist/clis/v2ex/replies.d.ts +1 -0
  279. package/dist/clis/v2ex/replies.js +26 -0
  280. package/dist/clis/v2ex/topic.d.ts +1 -0
  281. package/dist/clis/v2ex/topic.js +30 -0
  282. package/dist/clis/v2ex/user.d.ts +1 -0
  283. package/dist/clis/v2ex/user.js +33 -0
  284. package/dist/clis/xiaoe/catalog.d.ts +1 -0
  285. package/dist/clis/xiaoe/catalog.js +125 -0
  286. package/dist/clis/xiaoe/content.d.ts +1 -0
  287. package/dist/clis/xiaoe/content.js +39 -0
  288. package/dist/clis/xiaoe/courses.d.ts +1 -0
  289. package/dist/clis/xiaoe/courses.js +69 -0
  290. package/dist/clis/xiaoe/detail.d.ts +1 -0
  291. package/dist/clis/xiaoe/detail.js +35 -0
  292. package/dist/clis/xiaoe/play-url.d.ts +1 -0
  293. package/dist/clis/xiaoe/play-url.js +120 -0
  294. package/dist/clis/xiaohongshu/feed.d.ts +1 -0
  295. package/dist/clis/xiaohongshu/feed.js +32 -0
  296. package/dist/clis/xiaohongshu/note.js +8 -3
  297. package/dist/clis/xiaohongshu/note.test.js +11 -0
  298. package/dist/clis/xiaohongshu/notifications.d.ts +1 -0
  299. package/dist/clis/xiaohongshu/notifications.js +38 -0
  300. package/dist/clis/xueqiu/earnings-date.d.ts +1 -0
  301. package/dist/clis/xueqiu/earnings-date.js +61 -0
  302. package/dist/clis/xueqiu/feed.d.ts +1 -0
  303. package/dist/clis/xueqiu/feed.js +48 -0
  304. package/dist/clis/xueqiu/groups.d.ts +1 -0
  305. package/dist/clis/xueqiu/groups.js +25 -0
  306. package/dist/clis/xueqiu/hot-stock.d.ts +1 -0
  307. package/dist/clis/xueqiu/hot-stock.js +44 -0
  308. package/dist/clis/xueqiu/hot.d.ts +1 -0
  309. package/dist/clis/xueqiu/hot.js +44 -0
  310. package/dist/clis/xueqiu/kline.d.ts +1 -0
  311. package/dist/clis/xueqiu/kline.js +64 -0
  312. package/dist/clis/xueqiu/search.d.ts +1 -0
  313. package/dist/clis/xueqiu/search.js +49 -0
  314. package/dist/clis/xueqiu/stock.d.ts +1 -0
  315. package/dist/clis/xueqiu/stock.js +72 -0
  316. package/dist/clis/xueqiu/watchlist.d.ts +1 -0
  317. package/dist/clis/xueqiu/watchlist.js +45 -0
  318. package/dist/clis/zhihu/answer.d.ts +1 -0
  319. package/dist/clis/zhihu/answer.js +194 -0
  320. package/dist/clis/zhihu/answer.test.d.ts +1 -0
  321. package/dist/clis/zhihu/answer.test.js +81 -0
  322. package/dist/clis/zhihu/comment.d.ts +1 -0
  323. package/dist/clis/zhihu/comment.js +335 -0
  324. package/dist/clis/zhihu/comment.test.d.ts +1 -0
  325. package/dist/clis/zhihu/comment.test.js +54 -0
  326. package/dist/clis/zhihu/favorite.d.ts +1 -0
  327. package/dist/clis/zhihu/favorite.js +224 -0
  328. package/dist/clis/zhihu/favorite.test.d.ts +1 -0
  329. package/dist/clis/zhihu/favorite.test.js +196 -0
  330. package/dist/clis/zhihu/follow.d.ts +1 -0
  331. package/dist/clis/zhihu/follow.js +80 -0
  332. package/dist/clis/zhihu/follow.test.d.ts +1 -0
  333. package/dist/clis/zhihu/follow.test.js +45 -0
  334. package/dist/clis/zhihu/hot.d.ts +1 -0
  335. package/dist/clis/zhihu/hot.js +43 -0
  336. package/dist/clis/zhihu/like.d.ts +1 -0
  337. package/dist/clis/zhihu/like.js +91 -0
  338. package/dist/clis/zhihu/like.test.d.ts +1 -0
  339. package/dist/clis/zhihu/like.test.js +64 -0
  340. package/dist/clis/zhihu/search.d.ts +1 -0
  341. package/dist/clis/zhihu/search.js +52 -0
  342. package/dist/clis/zhihu/target.d.ts +24 -0
  343. package/dist/clis/zhihu/target.js +91 -0
  344. package/dist/clis/zhihu/target.test.d.ts +1 -0
  345. package/dist/clis/zhihu/target.test.js +77 -0
  346. package/dist/clis/zhihu/write-shared.d.ts +32 -0
  347. package/dist/clis/zhihu/write-shared.js +221 -0
  348. package/dist/clis/zhihu/write-shared.test.d.ts +1 -0
  349. package/dist/clis/zhihu/write-shared.test.js +175 -0
  350. package/dist/src/browser/bridge.d.ts +2 -0
  351. package/dist/src/browser/bridge.js +30 -24
  352. package/dist/src/browser/daemon-client.d.ts +30 -10
  353. package/dist/src/browser/daemon-client.js +42 -27
  354. package/dist/src/browser/daemon-client.test.js +32 -25
  355. package/dist/src/browser/dom-helpers.test.js +3 -2
  356. package/dist/src/browser/errors.d.ts +26 -1
  357. package/dist/src/browser/errors.js +40 -7
  358. package/dist/src/browser/errors.test.d.ts +1 -0
  359. package/dist/src/browser/errors.test.js +51 -0
  360. package/dist/src/browser/index.d.ts +2 -1
  361. package/dist/src/browser/index.js +1 -1
  362. package/dist/src/browser/page.d.ts +9 -8
  363. package/dist/src/browser/page.js +33 -31
  364. package/dist/src/browser.test.js +27 -8
  365. package/dist/src/build-manifest.d.ts +5 -11
  366. package/dist/src/build-manifest.js +6 -75
  367. package/dist/src/build-manifest.test.js +1 -39
  368. package/dist/src/cascade.js +3 -2
  369. package/dist/src/cli.d.ts +3 -3
  370. package/dist/src/cli.js +73 -65
  371. package/dist/src/cli.test.js +20 -15
  372. package/dist/src/clis/binance/asks.d.ts +1 -0
  373. package/dist/src/clis/binance/asks.js +20 -0
  374. package/dist/src/clis/binance/commands.test.d.ts +3 -0
  375. package/dist/src/clis/binance/commands.test.js +58 -0
  376. package/dist/src/clis/binance/depth.d.ts +1 -0
  377. package/dist/src/clis/binance/depth.js +20 -0
  378. package/dist/src/clis/binance/gainers.d.ts +1 -0
  379. package/dist/src/clis/binance/gainers.js +21 -0
  380. package/dist/src/clis/binance/klines.d.ts +1 -0
  381. package/dist/src/clis/binance/klines.js +20 -0
  382. package/dist/src/clis/binance/losers.d.ts +1 -0
  383. package/dist/src/clis/binance/losers.js +21 -0
  384. package/dist/src/clis/binance/pairs.d.ts +1 -0
  385. package/dist/src/clis/binance/pairs.js +20 -0
  386. package/dist/src/clis/binance/price.d.ts +1 -0
  387. package/dist/src/clis/binance/price.js +17 -0
  388. package/dist/src/clis/binance/prices.d.ts +1 -0
  389. package/dist/src/clis/binance/prices.js +18 -0
  390. package/dist/src/clis/binance/ticker.d.ts +1 -0
  391. package/dist/src/clis/binance/ticker.js +20 -0
  392. package/dist/src/clis/binance/top.d.ts +1 -0
  393. package/dist/src/clis/binance/top.js +20 -0
  394. package/dist/src/clis/binance/trades.d.ts +1 -0
  395. package/dist/src/clis/binance/trades.js +19 -0
  396. package/dist/src/commanderAdapter.js +19 -6
  397. package/dist/src/completion-fast.d.ts +25 -0
  398. package/dist/src/completion-fast.js +140 -0
  399. package/dist/src/completion.d.ts +1 -0
  400. package/dist/src/completion.js +1 -0
  401. package/dist/src/diagnostic.d.ts +1 -0
  402. package/dist/src/diagnostic.js +64 -2
  403. package/dist/src/diagnostic.test.js +93 -3
  404. package/dist/src/discovery.d.ts +3 -3
  405. package/dist/src/discovery.js +34 -97
  406. package/dist/src/doctor.d.ts +2 -0
  407. package/dist/src/doctor.js +59 -31
  408. package/dist/src/doctor.test.js +89 -16
  409. package/dist/src/download/index.d.ts +1 -1
  410. package/dist/src/engine.test.js +4 -19
  411. package/dist/src/execution.js +1 -13
  412. package/dist/src/explore.js +1 -1
  413. package/dist/src/generate-verified.d.ts +105 -0
  414. package/dist/src/generate-verified.js +696 -0
  415. package/dist/src/generate-verified.test.d.ts +1 -0
  416. package/dist/src/generate-verified.test.js +925 -0
  417. package/dist/src/generate.d.ts +11 -6
  418. package/dist/src/generate.js +4 -7
  419. package/dist/src/main.js +65 -12
  420. package/dist/src/pipeline/steps/download.d.ts +1 -17
  421. package/dist/src/pipeline/steps/download.js +20 -31
  422. package/dist/src/pipeline/steps/intercept.d.ts +1 -1
  423. package/dist/src/pipeline/steps/intercept.js +1 -1
  424. package/dist/src/pipeline/steps/tap.d.ts +1 -1
  425. package/dist/src/pipeline/steps/tap.js +1 -1
  426. package/dist/src/plugin-scaffold.d.ts +2 -2
  427. package/dist/src/plugin-scaffold.js +24 -21
  428. package/dist/src/plugin-scaffold.test.js +1 -1
  429. package/dist/src/plugin.d.ts +3 -2
  430. package/dist/src/plugin.js +29 -14
  431. package/dist/src/plugin.test.js +47 -32
  432. package/dist/src/record.js +26 -25
  433. package/dist/src/runtime-detect.js +3 -7
  434. package/dist/src/scripts/framework.d.ts +3 -0
  435. package/dist/src/scripts/framework.js +8 -4
  436. package/dist/src/scripts/store.d.ts +5 -1
  437. package/dist/src/scripts/store.js +5 -1
  438. package/dist/src/skill-generate.d.ts +30 -0
  439. package/dist/src/skill-generate.js +75 -0
  440. package/dist/src/skill-generate.test.d.ts +1 -0
  441. package/dist/src/skill-generate.test.js +173 -0
  442. package/dist/src/synthesize.d.ts +1 -1
  443. package/dist/src/synthesize.js +7 -8
  444. package/dist/src/types.d.ts +3 -1
  445. package/package.json +5 -5
  446. package/dist/clis/bilibili/hot.yaml +0 -38
  447. package/dist/clis/bluesky/feeds.yaml +0 -29
  448. package/dist/clis/bluesky/followers.yaml +0 -33
  449. package/dist/clis/bluesky/following.yaml +0 -33
  450. package/dist/clis/bluesky/profile.yaml +0 -27
  451. package/dist/clis/bluesky/search.yaml +0 -34
  452. package/dist/clis/bluesky/starter-packs.yaml +0 -34
  453. package/dist/clis/bluesky/thread.yaml +0 -32
  454. package/dist/clis/bluesky/trending.yaml +0 -27
  455. package/dist/clis/bluesky/user.yaml +0 -34
  456. package/dist/clis/devto/tag.yaml +0 -34
  457. package/dist/clis/devto/top.yaml +0 -29
  458. package/dist/clis/devto/user.yaml +0 -33
  459. package/dist/clis/dictionary/examples.yaml +0 -25
  460. package/dist/clis/dictionary/search.yaml +0 -27
  461. package/dist/clis/dictionary/synonyms.yaml +0 -25
  462. package/dist/clis/douban/subject.yaml +0 -107
  463. package/dist/clis/douban/top250.yaml +0 -70
  464. package/dist/clis/facebook/add-friend.yaml +0 -43
  465. package/dist/clis/facebook/events.yaml +0 -44
  466. package/dist/clis/facebook/feed.yaml +0 -63
  467. package/dist/clis/facebook/friends.yaml +0 -42
  468. package/dist/clis/facebook/groups.yaml +0 -50
  469. package/dist/clis/facebook/join-group.yaml +0 -44
  470. package/dist/clis/facebook/memories.yaml +0 -39
  471. package/dist/clis/facebook/notifications.yaml +0 -40
  472. package/dist/clis/facebook/profile.yaml +0 -37
  473. package/dist/clis/facebook/search.yaml +0 -47
  474. package/dist/clis/hackernews/ask.yaml +0 -38
  475. package/dist/clis/hackernews/best.yaml +0 -38
  476. package/dist/clis/hackernews/jobs.yaml +0 -36
  477. package/dist/clis/hackernews/new.yaml +0 -38
  478. package/dist/clis/hackernews/search.yaml +0 -44
  479. package/dist/clis/hackernews/show.yaml +0 -38
  480. package/dist/clis/hackernews/top.yaml +0 -38
  481. package/dist/clis/hackernews/user.yaml +0 -25
  482. package/dist/clis/hupu/hot.yaml +0 -43
  483. package/dist/clis/instagram/comment.yaml +0 -52
  484. package/dist/clis/instagram/explore.yaml +0 -43
  485. package/dist/clis/instagram/follow.yaml +0 -41
  486. package/dist/clis/instagram/followers.yaml +0 -51
  487. package/dist/clis/instagram/following.yaml +0 -51
  488. package/dist/clis/instagram/like.yaml +0 -46
  489. package/dist/clis/instagram/profile.yaml +0 -42
  490. package/dist/clis/instagram/save.yaml +0 -46
  491. package/dist/clis/instagram/saved.yaml +0 -40
  492. package/dist/clis/instagram/search.yaml +0 -44
  493. package/dist/clis/instagram/unfollow.yaml +0 -38
  494. package/dist/clis/instagram/unlike.yaml +0 -46
  495. package/dist/clis/instagram/unsave.yaml +0 -46
  496. package/dist/clis/instagram/user.yaml +0 -54
  497. package/dist/clis/jike/post.yaml +0 -59
  498. package/dist/clis/jike/topic.yaml +0 -53
  499. package/dist/clis/jike/user.yaml +0 -52
  500. package/dist/clis/jimeng/generate.yaml +0 -85
  501. package/dist/clis/jimeng/history.yaml +0 -46
  502. package/dist/clis/linux-do/categories.yaml +0 -70
  503. package/dist/clis/linux-do/search.yaml +0 -48
  504. package/dist/clis/linux-do/tags.yaml +0 -41
  505. package/dist/clis/linux-do/topic.yaml +0 -62
  506. package/dist/clis/linux-do/user-posts.yaml +0 -67
  507. package/dist/clis/linux-do/user-topics.yaml +0 -54
  508. package/dist/clis/lobsters/active.yaml +0 -29
  509. package/dist/clis/lobsters/hot.yaml +0 -29
  510. package/dist/clis/lobsters/newest.yaml +0 -29
  511. package/dist/clis/lobsters/tag.yaml +0 -34
  512. package/dist/clis/pixiv/detail.yaml +0 -49
  513. package/dist/clis/pixiv/ranking.yaml +0 -53
  514. package/dist/clis/pixiv/user.yaml +0 -46
  515. package/dist/clis/reddit/frontpage.yaml +0 -30
  516. package/dist/clis/reddit/hot.yaml +0 -47
  517. package/dist/clis/reddit/popular.yaml +0 -40
  518. package/dist/clis/reddit/search.yaml +0 -61
  519. package/dist/clis/reddit/subreddit.yaml +0 -50
  520. package/dist/clis/reddit/user-comments.yaml +0 -46
  521. package/dist/clis/reddit/user-posts.yaml +0 -44
  522. package/dist/clis/reddit/user.yaml +0 -40
  523. package/dist/clis/stackoverflow/bounties.yaml +0 -29
  524. package/dist/clis/stackoverflow/hot.yaml +0 -28
  525. package/dist/clis/stackoverflow/search.yaml +0 -33
  526. package/dist/clis/stackoverflow/unanswered.yaml +0 -28
  527. package/dist/clis/steam/top-sellers.yaml +0 -29
  528. package/dist/clis/tiktok/comment.yaml +0 -66
  529. package/dist/clis/tiktok/explore.yaml +0 -39
  530. package/dist/clis/tiktok/follow.yaml +0 -39
  531. package/dist/clis/tiktok/following.yaml +0 -46
  532. package/dist/clis/tiktok/friends.yaml +0 -47
  533. package/dist/clis/tiktok/like.yaml +0 -38
  534. package/dist/clis/tiktok/live.yaml +0 -51
  535. package/dist/clis/tiktok/notifications.yaml +0 -52
  536. package/dist/clis/tiktok/profile.yaml +0 -45
  537. package/dist/clis/tiktok/save.yaml +0 -34
  538. package/dist/clis/tiktok/search.yaml +0 -47
  539. package/dist/clis/tiktok/unfollow.yaml +0 -44
  540. package/dist/clis/tiktok/unlike.yaml +0 -38
  541. package/dist/clis/tiktok/unsave.yaml +0 -36
  542. package/dist/clis/tiktok/user.yaml +0 -44
  543. package/dist/clis/v2ex/hot.yaml +0 -28
  544. package/dist/clis/v2ex/latest.yaml +0 -28
  545. package/dist/clis/v2ex/member.yaml +0 -29
  546. package/dist/clis/v2ex/node.yaml +0 -34
  547. package/dist/clis/v2ex/nodes.yaml +0 -31
  548. package/dist/clis/v2ex/replies.yaml +0 -32
  549. package/dist/clis/v2ex/topic.yaml +0 -33
  550. package/dist/clis/v2ex/user.yaml +0 -34
  551. package/dist/clis/xiaoe/catalog.yaml +0 -129
  552. package/dist/clis/xiaoe/content.yaml +0 -43
  553. package/dist/clis/xiaoe/courses.yaml +0 -73
  554. package/dist/clis/xiaoe/detail.yaml +0 -39
  555. package/dist/clis/xiaoe/play-url.yaml +0 -124
  556. package/dist/clis/xiaohongshu/feed.yaml +0 -31
  557. package/dist/clis/xiaohongshu/notifications.yaml +0 -37
  558. package/dist/clis/xueqiu/earnings-date.yaml +0 -69
  559. package/dist/clis/xueqiu/feed.yaml +0 -53
  560. package/dist/clis/xueqiu/groups.yaml +0 -23
  561. package/dist/clis/xueqiu/hot-stock.yaml +0 -49
  562. package/dist/clis/xueqiu/hot.yaml +0 -46
  563. package/dist/clis/xueqiu/kline.yaml +0 -65
  564. package/dist/clis/xueqiu/search.yaml +0 -55
  565. package/dist/clis/xueqiu/stock.yaml +0 -69
  566. package/dist/clis/xueqiu/watchlist.yaml +0 -46
  567. package/dist/clis/zhihu/hot.yaml +0 -46
  568. package/dist/clis/zhihu/search.yaml +0 -59
  569. package/dist/src/browser/discover.d.ts +0 -15
  570. package/dist/src/browser/discover.js +0 -19
  571. package/dist/src/yaml-schema.d.ts +0 -29
  572. package/dist/src/yaml-schema.js +0 -22
@@ -0,0 +1,21 @@
1
+ import { cli, Strategy } from '@jackwener/opencli/registry';
2
+ cli({
3
+ site: 'binance',
4
+ name: 'losers',
5
+ description: 'Top losing trading pairs by 24h price change',
6
+ domain: 'data-api.binance.vision',
7
+ strategy: Strategy.PUBLIC,
8
+ browser: false,
9
+ args: [
10
+ { name: 'limit', type: 'int', default: 10, help: 'Number of trading pairs' },
11
+ ],
12
+ columns: ['rank', 'symbol', 'price', 'change_24h', 'volume'],
13
+ pipeline: [
14
+ { fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/24hr' } },
15
+ { filter: 'item.priceChangePercent' },
16
+ { map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_24h: '${{ item.priceChangePercent }}', volume: '${{ item.quoteVolume }}', sort_change: '${{ Number(item.priceChangePercent) }}' } },
17
+ { sort: { by: 'sort_change' } },
18
+ { map: { rank: '${{ index + 1 }}', symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_24h: '${{ item.priceChangePercent }}', volume: '${{ item.quoteVolume }}' } },
19
+ { limit: '${{ args.limit }}' },
20
+ ],
21
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { cli, Strategy } from '@jackwener/opencli/registry';
2
+ cli({
3
+ site: 'binance',
4
+ name: 'pairs',
5
+ description: 'List active trading pairs on Binance',
6
+ domain: 'data-api.binance.vision',
7
+ strategy: Strategy.PUBLIC,
8
+ browser: false,
9
+ args: [
10
+ { name: 'limit', type: 'int', default: 20, help: 'Number of trading pairs' },
11
+ ],
12
+ columns: ['symbol', 'base', 'quote', 'status'],
13
+ pipeline: [
14
+ { fetch: { url: 'https://data-api.binance.vision/api/v3/exchangeInfo' } },
15
+ { select: 'symbols' },
16
+ { filter: 'item.status === \'TRADING\'' },
17
+ { map: { symbol: '${{ item.symbol }}', base: '${{ item.baseAsset }}', quote: '${{ item.quoteAsset }}', status: '${{ item.status }}' } },
18
+ { limit: '${{ args.limit }}' },
19
+ ],
20
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ import { cli, Strategy } from '@jackwener/opencli/registry';
2
+ cli({
3
+ site: 'binance',
4
+ name: 'price',
5
+ description: 'Quick price check for a trading pair',
6
+ domain: 'data-api.binance.vision',
7
+ strategy: Strategy.PUBLIC,
8
+ browser: false,
9
+ args: [
10
+ { name: 'symbol', type: 'str', required: true, positional: true, help: 'Trading pair symbol (e.g. BTCUSDT, ETHUSDT)' },
11
+ ],
12
+ columns: ['symbol', 'price', 'change', 'change_pct', 'high', 'low', 'volume', 'quote_volume', 'trades'],
13
+ pipeline: [
14
+ { fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/24hr?symbol=${{ args.symbol }}' } },
15
+ { map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change: '${{ item.priceChange }}', change_pct: '${{ item.priceChangePercent }}', high: '${{ item.highPrice }}', low: '${{ item.lowPrice }}', volume: '${{ item.volume }}', quote_volume: '${{ item.quoteVolume }}', trades: '${{ item.count }}' } },
16
+ ],
17
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ import { cli, Strategy } from '@jackwener/opencli/registry';
2
+ cli({
3
+ site: 'binance',
4
+ name: 'prices',
5
+ description: 'Latest prices for all trading pairs',
6
+ domain: 'data-api.binance.vision',
7
+ strategy: Strategy.PUBLIC,
8
+ browser: false,
9
+ args: [
10
+ { name: 'limit', type: 'int', default: 20, help: 'Number of prices' },
11
+ ],
12
+ columns: ['rank', 'symbol', 'price'],
13
+ pipeline: [
14
+ { fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/price' } },
15
+ { map: { rank: '${{ index + 1 }}', symbol: '${{ item.symbol }}', price: '${{ item.price }}' } },
16
+ { limit: '${{ args.limit }}' },
17
+ ],
18
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { cli, Strategy } from '@jackwener/opencli/registry';
2
+ cli({
3
+ site: 'binance',
4
+ name: 'ticker',
5
+ description: '24h ticker statistics for top trading pairs by volume',
6
+ domain: 'data-api.binance.vision',
7
+ strategy: Strategy.PUBLIC,
8
+ browser: false,
9
+ args: [
10
+ { name: 'limit', type: 'int', default: 20, help: 'Number of tickers' },
11
+ ],
12
+ columns: ['symbol', 'price', 'change_pct', 'high', 'low', 'volume', 'quote_vol', 'trades'],
13
+ pipeline: [
14
+ { fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/24hr' } },
15
+ { map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_pct: '${{ item.priceChangePercent }}', high: '${{ item.highPrice }}', low: '${{ item.lowPrice }}', volume: '${{ item.volume }}', quote_vol: '${{ item.quoteVolume }}', trades: '${{ item.count }}', sort_volume: '${{ Number(item.quoteVolume) }}' } },
16
+ { sort: { by: 'sort_volume', order: 'desc' } },
17
+ { map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_pct: '${{ item.priceChangePercent }}', high: '${{ item.highPrice }}', low: '${{ item.lowPrice }}', volume: '${{ item.volume }}', quote_vol: '${{ item.quoteVolume }}', trades: '${{ item.count }}' } },
18
+ { limit: '${{ args.limit }}' },
19
+ ],
20
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { cli, Strategy } from '@jackwener/opencli/registry';
2
+ cli({
3
+ site: 'binance',
4
+ name: 'top',
5
+ description: 'Top trading pairs by 24h volume on Binance',
6
+ domain: 'data-api.binance.vision',
7
+ strategy: Strategy.PUBLIC,
8
+ browser: false,
9
+ args: [
10
+ { name: 'limit', type: 'int', default: 20, help: 'Number of trading pairs' },
11
+ ],
12
+ columns: ['rank', 'symbol', 'price', 'change_24h', 'high', 'low', 'volume'],
13
+ pipeline: [
14
+ { fetch: { url: 'https://data-api.binance.vision/api/v3/ticker/24hr' } },
15
+ { map: { symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_24h: '${{ item.priceChangePercent }}', high: '${{ item.highPrice }}', low: '${{ item.lowPrice }}', volume: '${{ item.quoteVolume }}', sort_volume: '${{ Number(item.quoteVolume) }}' } },
16
+ { sort: { by: 'sort_volume', order: 'desc' } },
17
+ { map: { rank: '${{ index + 1 }}', symbol: '${{ item.symbol }}', price: '${{ item.lastPrice }}', change_24h: '${{ item.priceChangePercent }}', high: '${{ item.highPrice }}', low: '${{ item.lowPrice }}', volume: '${{ item.quoteVolume }}' } },
18
+ { limit: '${{ args.limit }}' },
19
+ ],
20
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ import { cli, Strategy } from '@jackwener/opencli/registry';
2
+ cli({
3
+ site: 'binance',
4
+ name: 'trades',
5
+ description: 'Recent trades for a trading pair',
6
+ domain: 'data-api.binance.vision',
7
+ strategy: Strategy.PUBLIC,
8
+ browser: false,
9
+ args: [
10
+ { name: 'symbol', type: 'str', required: true, positional: true, help: 'Trading pair symbol (e.g. BTCUSDT, ETHUSDT)' },
11
+ { name: 'limit', type: 'int', default: 20, help: 'Number of trades (max 1000)' },
12
+ ],
13
+ columns: ['id', 'price', 'qty', 'quote_qty', 'buyer_maker'],
14
+ pipeline: [
15
+ { fetch: { url: 'https://data-api.binance.vision/api/v3/trades?symbol=${{ args.symbol }}&limit=${{ args.limit }}' } },
16
+ { map: { id: '${{ item.id }}', price: '${{ item.price }}', qty: '${{ item.qty }}', quote_qty: '${{ item.quoteQty }}', buyer_maker: '${{ item.isBuyerMaker }}' } },
17
+ { limit: '${{ args.limit }}' },
18
+ ],
19
+ });
@@ -15,7 +15,8 @@ import { formatRegistryHelpText } from './serialization.js';
15
15
  import { render as renderOutput } from './output.js';
16
16
  import { executeCommand } from './execution.js';
17
17
  import { CliError, EXIT_CODES, ERROR_ICONS, getErrorMessage, BrowserConnectError, AuthRequiredError, TimeoutError, SelectorError, EmptyResultError, ArgumentError, AdapterLoadError, CommandExecutionError, } from './errors.js';
18
- import { checkDaemonStatus } from './browser/discover.js';
18
+ import { getDaemonHealth } from './browser/daemon-client.js';
19
+ import { isDiagnosticEnabled } from './diagnostic.js';
19
20
  export function normalizeArgValue(argType, value, name) {
20
21
  if (argType !== 'bool' && argType !== 'boolean')
21
22
  return value;
@@ -169,18 +170,27 @@ function renderBridgeStatus(running, extensionConnected) {
169
170
  console.error(chalk.dim(' Try reloading the extension, or run: opencli doctor'));
170
171
  }
171
172
  }
173
+ /** Emit AutoFix hint for repairable adapter errors (skipped if already in diagnostic mode). */
174
+ function emitAutoFixHint(cmdName) {
175
+ if (isDiagnosticEnabled())
176
+ return; // Already collecting diagnostics, don't repeat
177
+ console.error();
178
+ console.error(chalk.cyan('💡 AutoFix: re-run with OPENCLI_DIAGNOSTIC=1 for repair context.'));
179
+ console.error(chalk.dim(` OPENCLI_DIAGNOSTIC=1 ${cmdName}`));
180
+ }
172
181
  async function renderError(err, cmdName, verbose) {
173
182
  // ── BrowserConnectError: real-time diagnosis, kind as fallback ────────
174
183
  if (err instanceof BrowserConnectError) {
175
- console.error(chalk.red('🔌 Browser Bridge not connected'));
184
+ console.error(chalk.red(`🔌 ${err.message}`));
185
+ if (err.hint)
186
+ console.error(chalk.yellow(`→ ${err.hint}`));
176
187
  console.error();
177
188
  try {
178
- // 300ms matches execution.ts localhost responds in <50ms when running.
179
- const status = await checkDaemonStatus({ timeout: 300 });
180
- renderBridgeStatus(status.running, status.extensionConnected);
189
+ const health = await getDaemonHealth({ timeout: 300 });
190
+ renderBridgeStatus(health.state !== 'stopped', health.state === 'ready');
181
191
  }
182
192
  catch (_statusErr) {
183
- // checkDaemonStatus itself failed — derive best-guess state from kind.
193
+ // getDaemonHealth itself failed — derive best-guess state from kind.
184
194
  const running = err.kind !== 'daemon-not-running';
185
195
  const extensionConnected = err.kind === 'command-failed';
186
196
  renderBridgeStatus(running, extensionConnected);
@@ -208,6 +218,7 @@ async function renderError(err, cmdName, verbose) {
208
218
  console.error(chalk.yellow(`→ ${err.hint ?? 'The page structure may have changed — this adapter may be outdated.'}`));
209
219
  console.error(chalk.dim(` Debug: ${cmdName} --verbose`));
210
220
  console.error(chalk.dim(` Report: ${ISSUES_URL}`));
221
+ emitAutoFixHint(cmdName);
211
222
  return;
212
223
  }
213
224
  // ── ArgumentError ─────────────────────────────────────────────────────
@@ -251,6 +262,8 @@ async function renderError(err, cmdName, verbose) {
251
262
  console.error(chalk.yellow(`→ ${classified.hint}`));
252
263
  if (classified.kind === 'not-found')
253
264
  console.error(chalk.dim(` Report: ${ISSUES_URL}`));
265
+ if (classified.kind === 'not-found')
266
+ emitAutoFixHint(cmdName);
254
267
  return;
255
268
  }
256
269
  // ── Unknown error: show stack in verbose mode ─────────────────────────
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Lightweight manifest-based completion for the fast path.
3
+ *
4
+ * This module MUST NOT import registry, discovery, or any heavy module.
5
+ * It only reads pre-compiled cli-manifest.json files synchronously.
6
+ */
7
+ /**
8
+ * Returns true only if ALL manifest files exist and are readable.
9
+ * If any source lacks a manifest (e.g. user adapters without a compiled manifest),
10
+ * the fast path must not be used — otherwise those adapters would silently
11
+ * disappear from completion results.
12
+ */
13
+ export declare function hasAllManifests(manifestPaths: string[]): boolean;
14
+ /**
15
+ * Lightweight completion that reads directly from manifest JSON files,
16
+ * bypassing full CLI discovery and adapter loading.
17
+ */
18
+ export declare function getCompletionsFromManifest(words: string[], cursor: number, manifestPaths: string[]): string[];
19
+ export declare function bashCompletionScript(): string;
20
+ export declare function zshCompletionScript(): string;
21
+ export declare function fishCompletionScript(): string;
22
+ /**
23
+ * Print completion script for the given shell. Returns true if handled, false if unknown shell.
24
+ */
25
+ export declare function printCompletionScriptFast(shell: string): boolean;
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Lightweight manifest-based completion for the fast path.
3
+ *
4
+ * This module MUST NOT import registry, discovery, or any heavy module.
5
+ * It only reads pre-compiled cli-manifest.json files synchronously.
6
+ */
7
+ import * as fs from 'node:fs';
8
+ const BUILTIN_COMMANDS = [
9
+ 'list',
10
+ 'validate',
11
+ 'verify',
12
+ 'explore',
13
+ 'probe',
14
+ 'synthesize',
15
+ 'generate',
16
+ 'cascade',
17
+ 'doctor',
18
+ 'plugin',
19
+ 'install',
20
+ 'register',
21
+ 'completion',
22
+ ];
23
+ /**
24
+ * Returns true only if ALL manifest files exist and are readable.
25
+ * If any source lacks a manifest (e.g. user adapters without a compiled manifest),
26
+ * the fast path must not be used — otherwise those adapters would silently
27
+ * disappear from completion results.
28
+ */
29
+ export function hasAllManifests(manifestPaths) {
30
+ for (const p of manifestPaths) {
31
+ try {
32
+ fs.accessSync(p);
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ return manifestPaths.length > 0;
39
+ }
40
+ /**
41
+ * Lightweight completion that reads directly from manifest JSON files,
42
+ * bypassing full CLI discovery and adapter loading.
43
+ */
44
+ export function getCompletionsFromManifest(words, cursor, manifestPaths) {
45
+ const entries = loadManifestEntries(manifestPaths);
46
+ if (entries === null) {
47
+ return [];
48
+ }
49
+ if (cursor <= 1) {
50
+ const sites = new Set();
51
+ for (const entry of entries) {
52
+ sites.add(entry.site);
53
+ }
54
+ return [...BUILTIN_COMMANDS, ...sites].sort();
55
+ }
56
+ const site = words[0];
57
+ if (BUILTIN_COMMANDS.includes(site)) {
58
+ return [];
59
+ }
60
+ if (cursor === 2) {
61
+ const subcommands = [];
62
+ for (const entry of entries) {
63
+ if (entry.site === site) {
64
+ subcommands.push(entry.name);
65
+ if (entry.aliases?.length)
66
+ subcommands.push(...entry.aliases);
67
+ }
68
+ }
69
+ return [...new Set(subcommands)].sort();
70
+ }
71
+ return [];
72
+ }
73
+ // ── Shell script generators (pure strings, no registry dependency) ───────
74
+ export function bashCompletionScript() {
75
+ return `# Bash completion for opencli
76
+ # Add to ~/.bashrc: eval "$(opencli completion bash)"
77
+ _opencli_completions() {
78
+ local cur words cword
79
+ _get_comp_words_by_ref -n : cur words cword
80
+
81
+ local completions
82
+ completions=$(opencli --get-completions --cursor "$cword" "\${words[@]:1}" 2>/dev/null)
83
+
84
+ COMPREPLY=( $(compgen -W "$completions" -- "$cur") )
85
+ __ltrim_colon_completions "$cur"
86
+ }
87
+ complete -F _opencli_completions opencli
88
+ `;
89
+ }
90
+ export function zshCompletionScript() {
91
+ return `# Zsh completion for opencli
92
+ # Add to ~/.zshrc: eval "$(opencli completion zsh)"
93
+ _opencli() {
94
+ local -a completions
95
+ local cword=$((CURRENT - 1))
96
+ completions=(\${(f)"$(opencli --get-completions --cursor "$cword" "\${words[@]:1}" 2>/dev/null)"})
97
+ compadd -a completions
98
+ }
99
+ compdef _opencli opencli
100
+ `;
101
+ }
102
+ export function fishCompletionScript() {
103
+ return `# Fish completion for opencli
104
+ # Add to ~/.config/fish/config.fish: opencli completion fish | source
105
+ complete -c opencli -f -a '(
106
+ set -l tokens (commandline -cop)
107
+ set -l cursor (count (commandline -cop))
108
+ opencli --get-completions --cursor $cursor $tokens[2..] 2>/dev/null
109
+ )'
110
+ `;
111
+ }
112
+ const SHELL_SCRIPTS = {
113
+ bash: bashCompletionScript,
114
+ zsh: zshCompletionScript,
115
+ fish: fishCompletionScript,
116
+ };
117
+ /**
118
+ * Print completion script for the given shell. Returns true if handled, false if unknown shell.
119
+ */
120
+ export function printCompletionScriptFast(shell) {
121
+ const gen = SHELL_SCRIPTS[shell];
122
+ if (!gen)
123
+ return false;
124
+ process.stdout.write(gen());
125
+ return true;
126
+ }
127
+ function loadManifestEntries(manifestPaths) {
128
+ const entries = [];
129
+ let found = false;
130
+ for (const manifestPath of manifestPaths) {
131
+ try {
132
+ const raw = fs.readFileSync(manifestPath, 'utf-8');
133
+ const manifest = JSON.parse(raw);
134
+ entries.push(...manifest);
135
+ found = true;
136
+ }
137
+ catch { /* skip missing/unreadable */ }
138
+ }
139
+ return found ? entries : null;
140
+ }
@@ -7,6 +7,7 @@
7
7
  */
8
8
  /**
9
9
  * Return completion candidates given the current command-line words and cursor index.
10
+ * Requires full CLI discovery to have been run (uses getRegistry()).
10
11
  *
11
12
  * @param words - The argv after 'opencli' (words[0] is the first arg, e.g. site name)
12
13
  * @param cursor - 1-based position of the word being completed (1 = first arg)
@@ -28,6 +28,7 @@ const BUILTIN_COMMANDS = [
28
28
  ];
29
29
  /**
30
30
  * Return completion candidates given the current command-line words and cursor index.
31
+ * Requires full CLI discovery to have been run (uses getRegistry()).
31
32
  *
32
33
  * @param words - The argv after 'opencli' (words[0] is the first arg, e.g. site name)
33
34
  * @param cursor - 1-based position of the word being completed (1 = first arg)
@@ -32,6 +32,7 @@ export interface RepairContext {
32
32
  url: string;
33
33
  snapshot: string;
34
34
  networkRequests: unknown[];
35
+ capturedPayloads?: unknown[];
35
36
  consoleErrors: unknown[];
36
37
  };
37
38
  timestamp: string;
@@ -24,10 +24,16 @@ const MAX_SNAPSHOT_CHARS = 100_000;
24
24
  const MAX_SOURCE_CHARS = 50_000;
25
25
  /** Maximum number of network requests to include. */
26
26
  const MAX_NETWORK_REQUESTS = 50;
27
+ /** Maximum number of captured interceptor payloads to include. */
28
+ const MAX_CAPTURED_PAYLOADS = 20;
27
29
  /** Maximum characters for a single network request body. */
28
30
  const MAX_REQUEST_BODY_CHARS = 4_000;
29
31
  /** Maximum characters for error stack trace. */
30
32
  const MAX_STACK_CHARS = 5_000;
33
+ /** Maximum nesting depth for arbitrary captured payloads. */
34
+ const MAX_CAPTURED_DEPTH = 4;
35
+ /** Maximum object keys or array items to keep per nesting level. */
36
+ const MAX_CAPTURED_CHILDREN = 20;
31
37
  // ── Sensitive data patterns ──────────────────────────────────────────────────
32
38
  const SENSITIVE_HEADERS = new Set([
33
39
  'authorization',
@@ -82,6 +88,39 @@ function redactHeaders(headers) {
82
88
  }
83
89
  return result;
84
90
  }
91
+ /** Recursively sanitize arbitrary captured response content for diagnostic output. */
92
+ function sanitizeCapturedValue(value, depth = 0) {
93
+ if (typeof value === 'string') {
94
+ return redactText(truncate(value, MAX_REQUEST_BODY_CHARS));
95
+ }
96
+ if (value === null || typeof value === 'number' || typeof value === 'boolean') {
97
+ return value;
98
+ }
99
+ if (depth >= MAX_CAPTURED_DEPTH) {
100
+ return '[truncated: max depth reached]';
101
+ }
102
+ if (Array.isArray(value)) {
103
+ const items = value
104
+ .slice(0, MAX_CAPTURED_CHILDREN)
105
+ .map(item => sanitizeCapturedValue(item, depth + 1));
106
+ if (value.length > MAX_CAPTURED_CHILDREN) {
107
+ items.push(`[truncated, ${value.length - MAX_CAPTURED_CHILDREN} items omitted]`);
108
+ }
109
+ return items;
110
+ }
111
+ if (!value || typeof value !== 'object') {
112
+ return value;
113
+ }
114
+ const entries = Object.entries(value);
115
+ const result = {};
116
+ for (const [key, child] of entries.slice(0, MAX_CAPTURED_CHILDREN)) {
117
+ result[key] = sanitizeCapturedValue(child, depth + 1);
118
+ }
119
+ if (entries.length > MAX_CAPTURED_CHILDREN) {
120
+ result.__truncated__ = `[${entries.length - MAX_CAPTURED_CHILDREN} fields omitted]`;
121
+ }
122
+ return result;
123
+ }
85
124
  /** Redact sensitive data from a single network request entry. */
86
125
  function redactNetworkRequest(req) {
87
126
  if (!req || typeof req !== 'object')
@@ -106,6 +145,12 @@ function redactNetworkRequest(req) {
106
145
  if (typeof redacted.body === 'string') {
107
146
  redacted.body = truncate(redacted.body, MAX_REQUEST_BODY_CHARS);
108
147
  }
148
+ if ('responseBody' in redacted) {
149
+ redacted.responseBody = sanitizeCapturedValue(redacted.responseBody);
150
+ }
151
+ if ('responsePreview' in redacted) {
152
+ redacted.responsePreview = sanitizeCapturedValue(redacted.responsePreview);
153
+ }
109
154
  return redacted;
110
155
  }
111
156
  // ── Timeout helper ───────────────────────────────────────────────────────────
@@ -163,23 +208,32 @@ function mapDistToSource(filePath) {
163
208
  export function isDiagnosticEnabled() {
164
209
  return process.env.OPENCLI_DIAGNOSTIC === '1';
165
210
  }
211
+ function normalizeInterceptedRequests(interceptedRequests) {
212
+ return interceptedRequests.slice(0, MAX_CAPTURED_PAYLOADS).map(responseBody => ({
213
+ source: 'interceptor',
214
+ responseBody: sanitizeCapturedValue(responseBody),
215
+ }));
216
+ }
166
217
  /** Safely collect page diagnostic state with redaction, size caps, and timeout. */
167
218
  async function collectPageState(page) {
168
219
  const collect = async () => {
169
220
  try {
170
- const [url, snapshot, networkRequests, consoleErrors] = await Promise.all([
221
+ const [url, snapshot, networkRequests, interceptedRequests, consoleErrors] = await Promise.all([
171
222
  page.getCurrentUrl?.().catch(() => null) ?? Promise.resolve(null),
172
223
  page.snapshot().catch(() => '(snapshot unavailable)'),
173
224
  page.networkRequests().catch(() => []),
225
+ page.getInterceptedRequests().catch(() => []),
174
226
  page.consoleMessages('error').catch(() => []),
175
227
  ]);
176
228
  const rawUrl = url ?? 'unknown';
229
+ const capturedResponses = normalizeInterceptedRequests(interceptedRequests);
177
230
  return {
178
231
  url: redactUrl(rawUrl),
179
232
  snapshot: redactText(truncate(snapshot, MAX_SNAPSHOT_CHARS)),
180
233
  networkRequests: networkRequests
181
234
  .slice(0, MAX_NETWORK_REQUESTS)
182
235
  .map(redactNetworkRequest),
236
+ capturedPayloads: capturedResponses,
183
237
  consoleErrors: consoleErrors
184
238
  .slice(0, 50)
185
239
  .map(e => typeof e === 'string' ? redactText(e) : e),
@@ -235,7 +289,15 @@ export function emitDiagnostic(ctx) {
235
289
  let json = JSON.stringify(ctx);
236
290
  // Enforce total output budget — drop page state (largest section) first if over budget
237
291
  if (json.length > MAX_DIAGNOSTIC_BYTES && ctx.page) {
238
- const trimmed = { ...ctx, page: { ...ctx.page, snapshot: '[omitted: over size budget]', networkRequests: [] } };
292
+ const trimmed = {
293
+ ...ctx,
294
+ page: {
295
+ ...ctx.page,
296
+ snapshot: '[omitted: over size budget]',
297
+ networkRequests: [],
298
+ capturedPayloads: [],
299
+ },
300
+ };
239
301
  json = JSON.stringify(trimmed);
240
302
  }
241
303
  // If still over budget, drop page entirely
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, vi, afterEach } from 'vitest';
2
- import { buildRepairContext, isDiagnosticEnabled, emitDiagnostic, truncate, redactUrl, redactText, resolveAdapterSourcePath, MAX_DIAGNOSTIC_BYTES, } from './diagnostic.js';
2
+ import { buildRepairContext, collectDiagnostic, isDiagnosticEnabled, emitDiagnostic, truncate, redactUrl, redactText, resolveAdapterSourcePath, MAX_DIAGNOSTIC_BYTES, } from './diagnostic.js';
3
3
  import { SelectorError, CommandExecutionError } from './errors.js';
4
4
  function makeCmd(overrides = {}) {
5
5
  return {
@@ -83,8 +83,8 @@ describe('redactText', () => {
83
83
  });
84
84
  describe('resolveAdapterSourcePath', () => {
85
85
  it('returns source when it is a real file path (not manifest:)', () => {
86
- const cmd = makeCmd({ source: '/home/user/.opencli/clis/arxiv/search.yaml' });
87
- expect(resolveAdapterSourcePath(cmd)).toBe('/home/user/.opencli/clis/arxiv/search.yaml');
86
+ const cmd = makeCmd({ source: '/home/user/.opencli/clis/arxiv/search.ts' });
87
+ expect(resolveAdapterSourcePath(cmd)).toBe('/home/user/.opencli/clis/arxiv/search.ts');
88
88
  });
89
89
  it('skips manifest: pseudo-paths and falls back to _modulePath', () => {
90
90
  const cmd = makeCmd({ source: 'manifest:arxiv/search', _modulePath: '/pkg/dist/clis/arxiv/search.js' });
@@ -211,3 +211,93 @@ describe('emitDiagnostic', () => {
211
211
  expect(redactUrl('https://api.com/data?token=secret123')).toContain('[REDACTED]');
212
212
  });
213
213
  });
214
+ function makePage(overrides = {}) {
215
+ return {
216
+ goto: vi.fn(),
217
+ evaluate: vi.fn(),
218
+ getCookies: vi.fn(),
219
+ snapshot: vi.fn().mockResolvedValue('<div>...</div>'),
220
+ click: vi.fn(),
221
+ typeText: vi.fn(),
222
+ pressKey: vi.fn(),
223
+ scrollTo: vi.fn(),
224
+ getFormState: vi.fn(),
225
+ wait: vi.fn(),
226
+ tabs: vi.fn(),
227
+ selectTab: vi.fn(),
228
+ networkRequests: vi.fn().mockResolvedValue([]),
229
+ consoleMessages: vi.fn().mockResolvedValue([]),
230
+ scroll: vi.fn(),
231
+ autoScroll: vi.fn(),
232
+ installInterceptor: vi.fn(),
233
+ getInterceptedRequests: vi.fn().mockResolvedValue([]),
234
+ waitForCapture: vi.fn(),
235
+ screenshot: vi.fn(),
236
+ getCurrentUrl: vi.fn().mockResolvedValue('https://example.com/page'),
237
+ ...overrides,
238
+ };
239
+ }
240
+ describe('collectDiagnostic', () => {
241
+ it('keeps intercepted payloads in a dedicated capturedPayloads field', async () => {
242
+ const page = makePage({
243
+ networkRequests: vi.fn().mockResolvedValue([{ url: '/api/data', status: 200 }]),
244
+ getInterceptedRequests: vi.fn().mockResolvedValue([{ items: [{ id: 1 }] }]),
245
+ });
246
+ const ctx = await collectDiagnostic(new Error('boom'), makeCmd(), page);
247
+ expect(ctx.page?.networkRequests).toEqual([
248
+ { url: '/api/data', status: 200 },
249
+ ]);
250
+ expect(ctx.page?.capturedPayloads).toEqual([
251
+ { source: 'interceptor', responseBody: { items: [{ id: 1 }] } },
252
+ ]);
253
+ });
254
+ it('preserves the previous network request output when interception is empty', async () => {
255
+ const page = makePage({
256
+ networkRequests: vi.fn().mockResolvedValue([{ url: '/api/data', status: 200 }]),
257
+ getInterceptedRequests: vi.fn().mockResolvedValue([]),
258
+ });
259
+ const ctx = await collectDiagnostic(new Error('boom'), makeCmd(), page);
260
+ expect(ctx.page?.networkRequests).toEqual([{ url: '/api/data', status: 200 }]);
261
+ expect(ctx.page?.capturedPayloads).toEqual([]);
262
+ });
263
+ it('swallows intercepted request failures and still returns page state', async () => {
264
+ const page = makePage({
265
+ networkRequests: vi.fn().mockResolvedValue([{ url: '/api/data', status: 200 }]),
266
+ getInterceptedRequests: vi.fn().mockRejectedValue(new Error('interceptor unavailable')),
267
+ });
268
+ const ctx = await collectDiagnostic(new Error('boom'), makeCmd(), page);
269
+ expect(ctx.page).toEqual({
270
+ url: 'https://example.com/page',
271
+ snapshot: '<div>...</div>',
272
+ networkRequests: [{ url: '/api/data', status: 200 }],
273
+ capturedPayloads: [],
274
+ consoleErrors: [],
275
+ });
276
+ });
277
+ it('redacts and truncates intercepted payloads recursively', async () => {
278
+ const page = makePage({
279
+ getInterceptedRequests: vi.fn().mockResolvedValue([{
280
+ token: 'token=abc123def456ghi789',
281
+ nested: {
282
+ cookie: 'cookie: session=super-secret-cookie-value',
283
+ body: 'x'.repeat(5000),
284
+ },
285
+ }]),
286
+ });
287
+ const ctx = await collectDiagnostic(new Error('boom'), makeCmd(), page);
288
+ const payload = ctx.page?.capturedPayloads?.[0];
289
+ const body = payload.responseBody.nested.body;
290
+ expect(payload).toEqual({
291
+ source: 'interceptor',
292
+ responseBody: {
293
+ token: 'token=[REDACTED]',
294
+ nested: {
295
+ cookie: 'cookie: [REDACTED]',
296
+ body,
297
+ },
298
+ },
299
+ });
300
+ expect(body).toContain('[truncated,');
301
+ expect(body.length).toBeLessThan(5000);
302
+ });
303
+ });