@jackwener/opencli 1.6.9 → 1.7.0

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 (531) hide show
  1. package/README.md +128 -59
  2. package/README.zh-CN.md +134 -78
  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.js +35 -0
  6. package/dist/clis/bluesky/feeds.d.ts +1 -0
  7. package/dist/clis/bluesky/feeds.js +27 -0
  8. package/dist/clis/bluesky/followers.d.ts +1 -0
  9. package/dist/clis/bluesky/followers.js +27 -0
  10. package/dist/clis/bluesky/following.d.ts +1 -0
  11. package/dist/clis/bluesky/following.js +27 -0
  12. package/dist/clis/bluesky/profile.d.ts +1 -0
  13. package/dist/clis/bluesky/profile.js +29 -0
  14. package/dist/clis/bluesky/search.d.ts +1 -0
  15. package/dist/clis/bluesky/search.js +28 -0
  16. package/dist/clis/bluesky/starter-packs.d.ts +1 -0
  17. package/dist/clis/bluesky/starter-packs.js +28 -0
  18. package/dist/clis/bluesky/thread.d.ts +1 -0
  19. package/dist/clis/bluesky/thread.js +30 -0
  20. package/dist/clis/bluesky/trending.d.ts +1 -0
  21. package/dist/clis/bluesky/trending.js +19 -0
  22. package/dist/clis/bluesky/user.d.ts +1 -0
  23. package/dist/clis/bluesky/user.js +33 -0
  24. package/dist/clis/cnki/search.d.ts +1 -0
  25. package/dist/clis/cnki/search.js +60 -0
  26. package/dist/clis/cnki/search.test.d.ts +1 -0
  27. package/dist/clis/cnki/search.test.js +18 -0
  28. package/dist/clis/devto/tag.d.ts +1 -0
  29. package/dist/clis/devto/tag.js +32 -0
  30. package/dist/clis/devto/top.d.ts +1 -0
  31. package/dist/clis/devto/top.js +26 -0
  32. package/dist/clis/devto/user.d.ts +1 -0
  33. package/dist/clis/devto/user.js +31 -0
  34. package/dist/clis/dictionary/examples.d.ts +1 -0
  35. package/dist/clis/dictionary/examples.js +27 -0
  36. package/dist/clis/dictionary/search.d.ts +1 -0
  37. package/dist/clis/dictionary/search.js +29 -0
  38. package/dist/clis/dictionary/synonyms.d.ts +1 -0
  39. package/dist/clis/dictionary/synonyms.js +27 -0
  40. package/dist/clis/douban/subject.d.ts +1 -0
  41. package/dist/clis/douban/subject.js +118 -0
  42. package/dist/clis/douban/top250.d.ts +1 -0
  43. package/dist/clis/douban/top250.js +67 -0
  44. package/dist/clis/facebook/add-friend.d.ts +1 -0
  45. package/dist/clis/facebook/add-friend.js +43 -0
  46. package/dist/clis/facebook/events.d.ts +1 -0
  47. package/dist/clis/facebook/events.js +40 -0
  48. package/dist/clis/facebook/feed.d.ts +1 -0
  49. package/dist/clis/facebook/feed.js +59 -0
  50. package/dist/clis/facebook/friends.d.ts +1 -0
  51. package/dist/clis/facebook/friends.js +38 -0
  52. package/dist/clis/facebook/groups.d.ts +1 -0
  53. package/dist/clis/facebook/groups.js +46 -0
  54. package/dist/clis/facebook/join-group.d.ts +1 -0
  55. package/dist/clis/facebook/join-group.js +44 -0
  56. package/dist/clis/facebook/memories.d.ts +1 -0
  57. package/dist/clis/facebook/memories.js +35 -0
  58. package/dist/clis/facebook/notifications.d.ts +1 -0
  59. package/dist/clis/facebook/notifications.js +36 -0
  60. package/dist/clis/facebook/profile.d.ts +1 -0
  61. package/dist/clis/facebook/profile.js +37 -0
  62. package/dist/clis/facebook/search.d.ts +1 -0
  63. package/dist/clis/facebook/search.js +38 -0
  64. package/dist/clis/facebook/search.test.d.ts +1 -1
  65. package/dist/clis/facebook/search.test.js +6 -9
  66. package/dist/clis/gitee/index.d.ts +3 -0
  67. package/dist/clis/gitee/index.js +3 -0
  68. package/dist/clis/gitee/search.d.ts +1 -0
  69. package/dist/clis/gitee/search.js +136 -0
  70. package/dist/clis/gitee/trending.d.ts +1 -0
  71. package/dist/clis/gitee/trending.js +567 -0
  72. package/dist/clis/gitee/user.d.ts +1 -0
  73. package/dist/clis/gitee/user.js +199 -0
  74. package/dist/clis/gitee/user.test.d.ts +1 -0
  75. package/dist/clis/gitee/user.test.js +63 -0
  76. package/dist/clis/hackernews/ask.d.ts +1 -0
  77. package/dist/clis/hackernews/ask.js +29 -0
  78. package/dist/clis/hackernews/best.d.ts +1 -0
  79. package/dist/clis/hackernews/best.js +29 -0
  80. package/dist/clis/hackernews/jobs.d.ts +1 -0
  81. package/dist/clis/hackernews/jobs.js +27 -0
  82. package/dist/clis/hackernews/new.d.ts +1 -0
  83. package/dist/clis/hackernews/new.js +29 -0
  84. package/dist/clis/hackernews/search.d.ts +1 -0
  85. package/dist/clis/hackernews/search.js +36 -0
  86. package/dist/clis/hackernews/show.d.ts +1 -0
  87. package/dist/clis/hackernews/show.js +29 -0
  88. package/dist/clis/hackernews/top.d.ts +1 -0
  89. package/dist/clis/hackernews/top.js +29 -0
  90. package/dist/clis/hackernews/user.d.ts +1 -0
  91. package/dist/clis/hackernews/user.js +22 -0
  92. package/dist/clis/hupu/hot.d.ts +1 -0
  93. package/dist/clis/hupu/hot.js +40 -0
  94. package/dist/clis/instagram/comment.d.ts +1 -0
  95. package/dist/clis/instagram/comment.js +47 -0
  96. package/dist/clis/instagram/explore.d.ts +1 -0
  97. package/dist/clis/instagram/explore.js +41 -0
  98. package/dist/clis/instagram/follow.d.ts +1 -0
  99. package/dist/clis/instagram/follow.js +43 -0
  100. package/dist/clis/instagram/followers.d.ts +1 -0
  101. package/dist/clis/instagram/followers.js +45 -0
  102. package/dist/clis/instagram/following.d.ts +1 -0
  103. package/dist/clis/instagram/following.js +45 -0
  104. package/dist/clis/instagram/like.d.ts +1 -0
  105. package/dist/clis/instagram/like.js +45 -0
  106. package/dist/clis/instagram/profile.d.ts +1 -0
  107. package/dist/clis/instagram/profile.js +39 -0
  108. package/dist/clis/instagram/save.d.ts +1 -0
  109. package/dist/clis/instagram/save.js +45 -0
  110. package/dist/clis/instagram/saved.d.ts +1 -0
  111. package/dist/clis/instagram/saved.js +38 -0
  112. package/dist/clis/instagram/search.d.ts +1 -0
  113. package/dist/clis/instagram/search.js +38 -0
  114. package/dist/clis/instagram/unfollow.d.ts +1 -0
  115. package/dist/clis/instagram/unfollow.js +40 -0
  116. package/dist/clis/instagram/unlike.d.ts +1 -0
  117. package/dist/clis/instagram/unlike.js +45 -0
  118. package/dist/clis/instagram/unsave.d.ts +1 -0
  119. package/dist/clis/instagram/unsave.js +45 -0
  120. package/dist/clis/instagram/user.d.ts +1 -0
  121. package/dist/clis/instagram/user.js +48 -0
  122. package/dist/clis/jd/add-cart.d.ts +1 -0
  123. package/dist/clis/jd/add-cart.js +71 -0
  124. package/dist/clis/jd/cart.d.ts +1 -0
  125. package/dist/clis/jd/cart.js +79 -0
  126. package/dist/clis/jd/commands.test.d.ts +5 -0
  127. package/dist/clis/jd/commands.test.js +64 -0
  128. package/dist/clis/jd/detail.d.ts +1 -0
  129. package/dist/clis/jd/detail.js +62 -0
  130. package/dist/clis/jd/reviews.d.ts +1 -0
  131. package/dist/clis/jd/reviews.js +54 -0
  132. package/dist/clis/jd/search.d.ts +1 -0
  133. package/dist/clis/jd/search.js +65 -0
  134. package/dist/clis/jianyu/detail.d.ts +1 -0
  135. package/dist/clis/jianyu/detail.js +20 -0
  136. package/dist/clis/jianyu/search.d.ts +41 -4
  137. package/dist/clis/jianyu/search.js +458 -96
  138. package/dist/clis/jianyu/search.test.js +105 -0
  139. package/dist/clis/jianyu/shared/china-bid-search.d.ts +12 -0
  140. package/dist/clis/jianyu/shared/china-bid-search.js +165 -0
  141. package/dist/clis/jianyu/shared/procurement-contract.d.ts +68 -0
  142. package/dist/clis/jianyu/shared/procurement-contract.js +324 -0
  143. package/dist/clis/jianyu/shared/procurement-contract.test.d.ts +1 -0
  144. package/dist/clis/jianyu/shared/procurement-contract.test.js +72 -0
  145. package/dist/clis/jianyu/shared/procurement-detail.d.ts +6 -0
  146. package/dist/clis/jianyu/shared/procurement-detail.js +92 -0
  147. package/dist/clis/jianyu/shared/procurement-detail.test.d.ts +1 -0
  148. package/dist/clis/jianyu/shared/procurement-detail.test.js +72 -0
  149. package/dist/clis/jike/post.d.ts +1 -0
  150. package/dist/clis/jike/post.js +61 -0
  151. package/dist/clis/jike/topic.d.ts +1 -0
  152. package/dist/clis/jike/topic.js +51 -0
  153. package/dist/clis/jike/user.d.ts +1 -0
  154. package/dist/clis/jike/user.js +50 -0
  155. package/dist/clis/jimeng/generate.d.ts +1 -0
  156. package/dist/clis/jimeng/generate.js +83 -0
  157. package/dist/clis/jimeng/history.d.ts +1 -0
  158. package/dist/clis/jimeng/history.js +47 -0
  159. package/dist/clis/jimeng/new.d.ts +1 -0
  160. package/dist/clis/jimeng/new.js +43 -0
  161. package/dist/clis/jimeng/workspaces.d.ts +1 -0
  162. package/dist/clis/jimeng/workspaces.js +41 -0
  163. package/dist/clis/linux-do/categories.d.ts +1 -0
  164. package/dist/clis/linux-do/categories.js +65 -0
  165. package/dist/clis/linux-do/search.d.ts +1 -0
  166. package/dist/clis/linux-do/search.js +41 -0
  167. package/dist/clis/linux-do/tags.d.ts +1 -0
  168. package/dist/clis/linux-do/tags.js +39 -0
  169. package/dist/clis/linux-do/topic-content.test.js +5 -5
  170. package/dist/clis/linux-do/topic.d.ts +1 -0
  171. package/dist/clis/linux-do/topic.js +56 -0
  172. package/dist/clis/linux-do/user-posts.d.ts +1 -0
  173. package/dist/clis/linux-do/user-posts.js +61 -0
  174. package/dist/clis/linux-do/user-topics.d.ts +1 -0
  175. package/dist/clis/linux-do/user-topics.js +48 -0
  176. package/dist/clis/lobsters/active.d.ts +1 -0
  177. package/dist/clis/lobsters/active.js +26 -0
  178. package/dist/clis/lobsters/hot.d.ts +1 -0
  179. package/dist/clis/lobsters/hot.js +26 -0
  180. package/dist/clis/lobsters/newest.d.ts +1 -0
  181. package/dist/clis/lobsters/newest.js +26 -0
  182. package/dist/clis/lobsters/tag.d.ts +1 -0
  183. package/dist/clis/lobsters/tag.js +32 -0
  184. package/dist/clis/pixiv/detail.d.ts +1 -0
  185. package/dist/clis/pixiv/detail.js +58 -0
  186. package/dist/clis/pixiv/ranking.d.ts +1 -0
  187. package/dist/clis/pixiv/ranking.js +59 -0
  188. package/dist/clis/pixiv/user.d.ts +1 -0
  189. package/dist/clis/pixiv/user.js +52 -0
  190. package/dist/clis/reddit/frontpage.d.ts +1 -0
  191. package/dist/clis/reddit/frontpage.js +31 -0
  192. package/dist/clis/reddit/hot.d.ts +1 -0
  193. package/dist/clis/reddit/hot.js +45 -0
  194. package/dist/clis/reddit/popular.d.ts +1 -0
  195. package/dist/clis/reddit/popular.js +41 -0
  196. package/dist/clis/reddit/search.d.ts +1 -0
  197. package/dist/clis/reddit/search.js +65 -0
  198. package/dist/clis/reddit/subreddit.d.ts +1 -0
  199. package/dist/clis/reddit/subreddit.js +52 -0
  200. package/dist/clis/reddit/user-comments.d.ts +1 -0
  201. package/dist/clis/reddit/user-comments.js +44 -0
  202. package/dist/clis/reddit/user-posts.d.ts +1 -0
  203. package/dist/clis/reddit/user-posts.js +42 -0
  204. package/dist/clis/reddit/user.d.ts +1 -0
  205. package/dist/clis/reddit/user.js +37 -0
  206. package/dist/clis/stackoverflow/bounties.d.ts +1 -0
  207. package/dist/clis/stackoverflow/bounties.js +27 -0
  208. package/dist/clis/stackoverflow/hot.d.ts +1 -0
  209. package/dist/clis/stackoverflow/hot.js +24 -0
  210. package/dist/clis/stackoverflow/search.d.ts +1 -0
  211. package/dist/clis/stackoverflow/search.js +27 -0
  212. package/dist/clis/stackoverflow/unanswered.d.ts +1 -0
  213. package/dist/clis/stackoverflow/unanswered.js +26 -0
  214. package/dist/clis/steam/top-sellers.d.ts +1 -0
  215. package/dist/clis/steam/top-sellers.js +25 -0
  216. package/dist/clis/taobao/add-cart.d.ts +1 -0
  217. package/dist/clis/taobao/add-cart.js +149 -0
  218. package/dist/clis/taobao/cart.d.ts +1 -0
  219. package/dist/clis/taobao/cart.js +95 -0
  220. package/dist/clis/taobao/commands.test.d.ts +5 -0
  221. package/dist/clis/taobao/commands.test.js +64 -0
  222. package/dist/clis/taobao/detail.d.ts +1 -0
  223. package/dist/clis/taobao/detail.js +70 -0
  224. package/dist/clis/taobao/reviews.d.ts +1 -0
  225. package/dist/clis/taobao/reviews.js +76 -0
  226. package/dist/clis/taobao/search.d.ts +1 -0
  227. package/dist/clis/taobao/search.js +96 -0
  228. package/dist/clis/tiktok/comment.d.ts +1 -0
  229. package/dist/clis/tiktok/comment.js +57 -0
  230. package/dist/clis/tiktok/explore.d.ts +1 -0
  231. package/dist/clis/tiktok/explore.js +35 -0
  232. package/dist/clis/tiktok/follow.d.ts +1 -0
  233. package/dist/clis/tiktok/follow.js +39 -0
  234. package/dist/clis/tiktok/following.d.ts +1 -0
  235. package/dist/clis/tiktok/following.js +42 -0
  236. package/dist/clis/tiktok/friends.d.ts +1 -0
  237. package/dist/clis/tiktok/friends.js +43 -0
  238. package/dist/clis/tiktok/like.d.ts +1 -0
  239. package/dist/clis/tiktok/like.js +33 -0
  240. package/dist/clis/tiktok/live.d.ts +1 -0
  241. package/dist/clis/tiktok/live.js +47 -0
  242. package/dist/clis/tiktok/notifications.d.ts +1 -0
  243. package/dist/clis/tiktok/notifications.js +49 -0
  244. package/dist/clis/tiktok/profile.d.ts +1 -0
  245. package/dist/clis/tiktok/profile.js +54 -0
  246. package/dist/clis/tiktok/save.d.ts +1 -0
  247. package/dist/clis/tiktok/save.js +29 -0
  248. package/dist/clis/tiktok/search.d.ts +1 -0
  249. package/dist/clis/tiktok/search.js +39 -0
  250. package/dist/clis/tiktok/unfollow.d.ts +1 -0
  251. package/dist/clis/tiktok/unfollow.js +44 -0
  252. package/dist/clis/tiktok/unlike.d.ts +1 -0
  253. package/dist/clis/tiktok/unlike.js +33 -0
  254. package/dist/clis/tiktok/unsave.d.ts +1 -0
  255. package/dist/clis/tiktok/unsave.js +31 -0
  256. package/dist/clis/tiktok/user.d.ts +1 -0
  257. package/dist/clis/tiktok/user.js +41 -0
  258. package/dist/clis/v2ex/hot.d.ts +1 -0
  259. package/dist/clis/v2ex/hot.js +25 -0
  260. package/dist/clis/v2ex/latest.d.ts +1 -0
  261. package/dist/clis/v2ex/latest.js +25 -0
  262. package/dist/clis/v2ex/member.d.ts +1 -0
  263. package/dist/clis/v2ex/member.js +27 -0
  264. package/dist/clis/v2ex/node.d.ts +1 -0
  265. package/dist/clis/v2ex/node.js +38 -0
  266. package/dist/clis/v2ex/nodes.d.ts +1 -0
  267. package/dist/clis/v2ex/nodes.js +25 -0
  268. package/dist/clis/v2ex/replies.d.ts +1 -0
  269. package/dist/clis/v2ex/replies.js +26 -0
  270. package/dist/clis/v2ex/topic.d.ts +1 -0
  271. package/dist/clis/v2ex/topic.js +30 -0
  272. package/dist/clis/v2ex/user.d.ts +1 -0
  273. package/dist/clis/v2ex/user.js +33 -0
  274. package/dist/clis/xiaoe/catalog.d.ts +1 -0
  275. package/dist/clis/xiaoe/catalog.js +161 -0
  276. package/dist/clis/xiaoe/content.d.ts +1 -0
  277. package/dist/clis/xiaoe/content.js +39 -0
  278. package/dist/clis/xiaoe/courses.d.ts +1 -0
  279. package/dist/clis/xiaoe/courses.js +69 -0
  280. package/dist/clis/xiaoe/detail.d.ts +1 -0
  281. package/dist/clis/xiaoe/detail.js +35 -0
  282. package/dist/clis/xiaoe/play-url.d.ts +1 -0
  283. package/dist/clis/xiaoe/play-url.js +120 -0
  284. package/dist/clis/xiaohongshu/feed.d.ts +1 -0
  285. package/dist/clis/xiaohongshu/feed.js +32 -0
  286. package/dist/clis/xiaohongshu/notifications.d.ts +1 -0
  287. package/dist/clis/xiaohongshu/notifications.js +38 -0
  288. package/dist/clis/xueqiu/earnings-date.d.ts +1 -0
  289. package/dist/clis/xueqiu/earnings-date.js +61 -0
  290. package/dist/clis/xueqiu/feed.d.ts +1 -0
  291. package/dist/clis/xueqiu/feed.js +48 -0
  292. package/dist/clis/xueqiu/groups.d.ts +1 -0
  293. package/dist/clis/xueqiu/groups.js +25 -0
  294. package/dist/clis/xueqiu/hot-stock.d.ts +1 -0
  295. package/dist/clis/xueqiu/hot-stock.js +44 -0
  296. package/dist/clis/xueqiu/hot.d.ts +1 -0
  297. package/dist/clis/xueqiu/hot.js +44 -0
  298. package/dist/clis/xueqiu/kline.d.ts +1 -0
  299. package/dist/clis/xueqiu/kline.js +64 -0
  300. package/dist/clis/xueqiu/search.d.ts +1 -0
  301. package/dist/clis/xueqiu/search.js +49 -0
  302. package/dist/clis/xueqiu/stock.d.ts +1 -0
  303. package/dist/clis/xueqiu/stock.js +72 -0
  304. package/dist/clis/xueqiu/watchlist.d.ts +1 -0
  305. package/dist/clis/xueqiu/watchlist.js +45 -0
  306. package/dist/clis/zhihu/hot.d.ts +1 -0
  307. package/dist/clis/zhihu/hot.js +43 -0
  308. package/dist/clis/zhihu/search.d.ts +1 -0
  309. package/dist/clis/zhihu/search.js +52 -0
  310. package/dist/src/browser/bridge.js +1 -1
  311. package/dist/src/browser/daemon-client.d.ts +16 -4
  312. package/dist/src/browser/daemon-client.js +33 -15
  313. package/dist/src/browser/daemon-client.test.js +0 -3
  314. package/dist/src/browser/dom-helpers.test.js +3 -2
  315. package/dist/src/browser/errors.d.ts +26 -1
  316. package/dist/src/browser/errors.js +40 -7
  317. package/dist/src/browser/errors.test.d.ts +1 -0
  318. package/dist/src/browser/errors.test.js +51 -0
  319. package/dist/src/browser/page.d.ts +9 -8
  320. package/dist/src/browser/page.js +33 -31
  321. package/dist/src/browser.test.js +25 -6
  322. package/dist/src/build-manifest.d.ts +5 -11
  323. package/dist/src/build-manifest.js +6 -75
  324. package/dist/src/build-manifest.test.js +1 -39
  325. package/dist/src/cascade.js +3 -2
  326. package/dist/src/cli.d.ts +3 -3
  327. package/dist/src/cli.js +71 -71
  328. package/dist/src/cli.test.js +20 -15
  329. package/dist/src/clis/binance/asks.d.ts +1 -0
  330. package/dist/src/clis/binance/asks.js +20 -0
  331. package/dist/src/clis/binance/commands.test.d.ts +3 -1
  332. package/dist/src/clis/binance/commands.test.js +10 -6
  333. package/dist/src/clis/binance/depth.d.ts +1 -0
  334. package/dist/src/clis/binance/depth.js +20 -0
  335. package/dist/src/clis/binance/gainers.d.ts +1 -0
  336. package/dist/src/clis/binance/gainers.js +21 -0
  337. package/dist/src/clis/binance/klines.d.ts +1 -0
  338. package/dist/src/clis/binance/klines.js +20 -0
  339. package/dist/src/clis/binance/losers.d.ts +1 -0
  340. package/dist/src/clis/binance/losers.js +21 -0
  341. package/dist/src/clis/binance/pairs.d.ts +1 -0
  342. package/dist/src/clis/binance/pairs.js +20 -0
  343. package/dist/src/clis/binance/price.d.ts +1 -0
  344. package/dist/src/clis/binance/price.js +17 -0
  345. package/dist/src/clis/binance/prices.d.ts +1 -0
  346. package/dist/src/clis/binance/prices.js +18 -0
  347. package/dist/src/clis/binance/ticker.d.ts +1 -0
  348. package/dist/src/clis/binance/ticker.js +20 -0
  349. package/dist/src/clis/binance/top.d.ts +1 -0
  350. package/dist/src/clis/binance/top.js +20 -0
  351. package/dist/src/clis/binance/trades.d.ts +1 -0
  352. package/dist/src/clis/binance/trades.js +19 -0
  353. package/dist/src/commands/daemon.d.ts +2 -6
  354. package/dist/src/commands/daemon.js +2 -58
  355. package/dist/src/commands/daemon.test.js +24 -120
  356. package/dist/src/completion-fast.d.ts +25 -0
  357. package/dist/src/completion-fast.js +140 -0
  358. package/dist/src/completion.d.ts +1 -0
  359. package/dist/src/completion.js +1 -0
  360. package/dist/src/constants.d.ts +0 -2
  361. package/dist/src/constants.js +0 -2
  362. package/dist/src/daemon.d.ts +1 -1
  363. package/dist/src/daemon.js +2 -15
  364. package/dist/src/diagnostic.test.js +2 -2
  365. package/dist/src/discovery.d.ts +3 -3
  366. package/dist/src/discovery.js +34 -97
  367. package/dist/src/download/index.d.ts +1 -1
  368. package/dist/src/engine.test.js +4 -19
  369. package/dist/src/execution.js +5 -1
  370. package/dist/src/generate-verified.d.ts +105 -0
  371. package/dist/src/generate-verified.js +696 -0
  372. package/dist/src/generate-verified.test.d.ts +1 -0
  373. package/dist/src/generate-verified.test.js +925 -0
  374. package/dist/src/generate.d.ts +9 -1
  375. package/dist/src/generate.js +2 -2
  376. package/dist/src/main.js +65 -12
  377. package/dist/src/pipeline/steps/download.d.ts +1 -17
  378. package/dist/src/pipeline/steps/download.js +20 -31
  379. package/dist/src/pipeline/steps/intercept.d.ts +1 -1
  380. package/dist/src/pipeline/steps/intercept.js +1 -1
  381. package/dist/src/pipeline/steps/tap.d.ts +1 -1
  382. package/dist/src/pipeline/steps/tap.js +1 -1
  383. package/dist/src/plugin-scaffold.d.ts +2 -2
  384. package/dist/src/plugin-scaffold.js +24 -21
  385. package/dist/src/plugin-scaffold.test.js +1 -1
  386. package/dist/src/plugin.d.ts +1 -1
  387. package/dist/src/plugin.js +4 -6
  388. package/dist/src/plugin.test.js +31 -31
  389. package/dist/src/record.js +26 -25
  390. package/dist/src/runtime-detect.js +3 -7
  391. package/dist/src/scripts/framework.d.ts +3 -0
  392. package/dist/src/scripts/framework.js +8 -4
  393. package/dist/src/scripts/store.d.ts +5 -1
  394. package/dist/src/scripts/store.js +5 -1
  395. package/dist/src/skill-generate.d.ts +30 -0
  396. package/dist/src/skill-generate.js +75 -0
  397. package/dist/src/skill-generate.test.d.ts +1 -0
  398. package/dist/src/skill-generate.test.js +173 -0
  399. package/dist/src/synthesize.d.ts +1 -1
  400. package/dist/src/synthesize.js +7 -8
  401. package/dist/src/types.d.ts +3 -1
  402. package/package.json +4 -3
  403. package/dist/clis/bilibili/hot.yaml +0 -38
  404. package/dist/clis/bluesky/feeds.yaml +0 -29
  405. package/dist/clis/bluesky/followers.yaml +0 -33
  406. package/dist/clis/bluesky/following.yaml +0 -33
  407. package/dist/clis/bluesky/profile.yaml +0 -27
  408. package/dist/clis/bluesky/search.yaml +0 -34
  409. package/dist/clis/bluesky/starter-packs.yaml +0 -34
  410. package/dist/clis/bluesky/thread.yaml +0 -32
  411. package/dist/clis/bluesky/trending.yaml +0 -27
  412. package/dist/clis/bluesky/user.yaml +0 -34
  413. package/dist/clis/devto/tag.yaml +0 -34
  414. package/dist/clis/devto/top.yaml +0 -29
  415. package/dist/clis/devto/user.yaml +0 -33
  416. package/dist/clis/dictionary/examples.yaml +0 -25
  417. package/dist/clis/dictionary/search.yaml +0 -27
  418. package/dist/clis/dictionary/synonyms.yaml +0 -25
  419. package/dist/clis/douban/subject.yaml +0 -107
  420. package/dist/clis/douban/top250.yaml +0 -70
  421. package/dist/clis/facebook/add-friend.yaml +0 -43
  422. package/dist/clis/facebook/events.yaml +0 -44
  423. package/dist/clis/facebook/feed.yaml +0 -63
  424. package/dist/clis/facebook/friends.yaml +0 -42
  425. package/dist/clis/facebook/groups.yaml +0 -50
  426. package/dist/clis/facebook/join-group.yaml +0 -44
  427. package/dist/clis/facebook/memories.yaml +0 -39
  428. package/dist/clis/facebook/notifications.yaml +0 -40
  429. package/dist/clis/facebook/profile.yaml +0 -37
  430. package/dist/clis/facebook/search.yaml +0 -47
  431. package/dist/clis/hackernews/ask.yaml +0 -38
  432. package/dist/clis/hackernews/best.yaml +0 -38
  433. package/dist/clis/hackernews/jobs.yaml +0 -36
  434. package/dist/clis/hackernews/new.yaml +0 -38
  435. package/dist/clis/hackernews/search.yaml +0 -44
  436. package/dist/clis/hackernews/show.yaml +0 -38
  437. package/dist/clis/hackernews/top.yaml +0 -38
  438. package/dist/clis/hackernews/user.yaml +0 -25
  439. package/dist/clis/hupu/hot.yaml +0 -43
  440. package/dist/clis/instagram/comment.yaml +0 -52
  441. package/dist/clis/instagram/explore.yaml +0 -43
  442. package/dist/clis/instagram/follow.yaml +0 -41
  443. package/dist/clis/instagram/followers.yaml +0 -51
  444. package/dist/clis/instagram/following.yaml +0 -51
  445. package/dist/clis/instagram/like.yaml +0 -46
  446. package/dist/clis/instagram/profile.yaml +0 -42
  447. package/dist/clis/instagram/save.yaml +0 -46
  448. package/dist/clis/instagram/saved.yaml +0 -40
  449. package/dist/clis/instagram/search.yaml +0 -44
  450. package/dist/clis/instagram/unfollow.yaml +0 -38
  451. package/dist/clis/instagram/unlike.yaml +0 -46
  452. package/dist/clis/instagram/unsave.yaml +0 -46
  453. package/dist/clis/instagram/user.yaml +0 -54
  454. package/dist/clis/jike/post.yaml +0 -59
  455. package/dist/clis/jike/topic.yaml +0 -53
  456. package/dist/clis/jike/user.yaml +0 -52
  457. package/dist/clis/jimeng/generate.yaml +0 -85
  458. package/dist/clis/jimeng/history.yaml +0 -46
  459. package/dist/clis/linux-do/categories.yaml +0 -70
  460. package/dist/clis/linux-do/search.yaml +0 -48
  461. package/dist/clis/linux-do/tags.yaml +0 -41
  462. package/dist/clis/linux-do/topic.yaml +0 -62
  463. package/dist/clis/linux-do/user-posts.yaml +0 -67
  464. package/dist/clis/linux-do/user-topics.yaml +0 -54
  465. package/dist/clis/lobsters/active.yaml +0 -29
  466. package/dist/clis/lobsters/hot.yaml +0 -29
  467. package/dist/clis/lobsters/newest.yaml +0 -29
  468. package/dist/clis/lobsters/tag.yaml +0 -34
  469. package/dist/clis/pixiv/detail.yaml +0 -49
  470. package/dist/clis/pixiv/ranking.yaml +0 -53
  471. package/dist/clis/pixiv/user.yaml +0 -46
  472. package/dist/clis/reddit/frontpage.yaml +0 -30
  473. package/dist/clis/reddit/hot.yaml +0 -47
  474. package/dist/clis/reddit/popular.yaml +0 -40
  475. package/dist/clis/reddit/search.yaml +0 -61
  476. package/dist/clis/reddit/subreddit.yaml +0 -50
  477. package/dist/clis/reddit/user-comments.yaml +0 -46
  478. package/dist/clis/reddit/user-posts.yaml +0 -44
  479. package/dist/clis/reddit/user.yaml +0 -40
  480. package/dist/clis/stackoverflow/bounties.yaml +0 -29
  481. package/dist/clis/stackoverflow/hot.yaml +0 -28
  482. package/dist/clis/stackoverflow/search.yaml +0 -33
  483. package/dist/clis/stackoverflow/unanswered.yaml +0 -28
  484. package/dist/clis/steam/top-sellers.yaml +0 -29
  485. package/dist/clis/tiktok/comment.yaml +0 -66
  486. package/dist/clis/tiktok/explore.yaml +0 -39
  487. package/dist/clis/tiktok/follow.yaml +0 -39
  488. package/dist/clis/tiktok/following.yaml +0 -46
  489. package/dist/clis/tiktok/friends.yaml +0 -47
  490. package/dist/clis/tiktok/like.yaml +0 -38
  491. package/dist/clis/tiktok/live.yaml +0 -51
  492. package/dist/clis/tiktok/notifications.yaml +0 -52
  493. package/dist/clis/tiktok/profile.yaml +0 -45
  494. package/dist/clis/tiktok/save.yaml +0 -34
  495. package/dist/clis/tiktok/search.yaml +0 -47
  496. package/dist/clis/tiktok/unfollow.yaml +0 -44
  497. package/dist/clis/tiktok/unlike.yaml +0 -38
  498. package/dist/clis/tiktok/unsave.yaml +0 -36
  499. package/dist/clis/tiktok/user.yaml +0 -44
  500. package/dist/clis/v2ex/hot.yaml +0 -28
  501. package/dist/clis/v2ex/latest.yaml +0 -28
  502. package/dist/clis/v2ex/member.yaml +0 -29
  503. package/dist/clis/v2ex/node.yaml +0 -34
  504. package/dist/clis/v2ex/nodes.yaml +0 -31
  505. package/dist/clis/v2ex/replies.yaml +0 -32
  506. package/dist/clis/v2ex/topic.yaml +0 -33
  507. package/dist/clis/v2ex/user.yaml +0 -34
  508. package/dist/clis/xiaoe/catalog.yaml +0 -129
  509. package/dist/clis/xiaoe/content.yaml +0 -43
  510. package/dist/clis/xiaoe/courses.yaml +0 -73
  511. package/dist/clis/xiaoe/detail.yaml +0 -39
  512. package/dist/clis/xiaoe/play-url.yaml +0 -124
  513. package/dist/clis/xiaohongshu/feed.yaml +0 -31
  514. package/dist/clis/xiaohongshu/notifications.yaml +0 -37
  515. package/dist/clis/xueqiu/earnings-date.yaml +0 -69
  516. package/dist/clis/xueqiu/feed.yaml +0 -53
  517. package/dist/clis/xueqiu/groups.yaml +0 -23
  518. package/dist/clis/xueqiu/hot-stock.yaml +0 -49
  519. package/dist/clis/xueqiu/hot.yaml +0 -46
  520. package/dist/clis/xueqiu/kline.yaml +0 -65
  521. package/dist/clis/xueqiu/search.yaml +0 -55
  522. package/dist/clis/xueqiu/stock.yaml +0 -69
  523. package/dist/clis/xueqiu/watchlist.yaml +0 -46
  524. package/dist/clis/zhihu/hot.yaml +0 -46
  525. package/dist/clis/zhihu/search.yaml +0 -59
  526. package/dist/src/daemon.test.js +0 -65
  527. package/dist/src/idle-manager.d.ts +0 -19
  528. package/dist/src/idle-manager.js +0 -54
  529. package/dist/src/yaml-schema.d.ts +0 -29
  530. package/dist/src/yaml-schema.js +0 -22
  531. /package/dist/{src/daemon.test.d.ts → clis/bilibili/hot.d.ts} +0 -0
@@ -146,11 +146,11 @@ describe('validatePluginStructure', () => {
146
146
  expect(res.valid).toBe(false);
147
147
  expect(res.errors[0]).toContain('No command files found');
148
148
  });
149
- it('returns valid for YAML plugin', () => {
149
+ it('returns invalid for YAML-only plugin (YAML no longer supported)', () => {
150
150
  fs.writeFileSync(path.join(testDir, 'cmd.yaml'), 'site: test');
151
151
  const res = _validatePluginStructure(testDir);
152
- expect(res.valid).toBe(true);
153
- expect(res.errors).toHaveLength(0);
152
+ expect(res.valid).toBe(false);
153
+ expect(res.errors[0]).toContain('No command files found');
154
154
  });
155
155
  it('returns valid for JS plugin', () => {
156
156
  fs.writeFileSync(path.join(testDir, 'cmd.js'), 'console.log("hi");');
@@ -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.yaml'), 'site: test\nname: hello\n');
364
+ fs.writeFileSync(path.join(testDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
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.yaml'), 'site: test\nname: hello\n');
372
+ fs.writeFileSync(path.join(testDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
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.yaml'), 'site: test\nname: hello\n');
396
+ fs.writeFileSync(path.join(localTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
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.yaml'), 'site: test');
438
+ fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test" })');
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.yaml'), 'site: test');
444
+ fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test" })');
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.yaml'), 'site: test\nname: hello\n');
467
+ fs.writeFileSync(path.join(localTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
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.yaml'), 'site: test\nname: hello\n');
543
+ fs.writeFileSync(path.join(subDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
544
544
  });
545
545
  afterEach(() => {
546
546
  fs.rmSync(repoDir, { recursive: true, force: true });
@@ -561,9 +561,9 @@ describe('updateAllPlugins', () => {
561
561
  fs.mkdirSync(testDirA, { recursive: true });
562
562
  fs.mkdirSync(testDirB, { recursive: true });
563
563
  fs.mkdirSync(testDirC, { recursive: true });
564
- fs.writeFileSync(path.join(testDirA, 'cmd.yaml'), 'site: a');
565
- fs.writeFileSync(path.join(testDirB, 'cmd.yaml'), 'site: b');
566
- fs.writeFileSync(path.join(testDirC, 'cmd.yaml'), 'site: c');
564
+ fs.writeFileSync(path.join(testDirA, 'cmd.js'), 'cli({ site: "a", name: "cmd" })');
565
+ fs.writeFileSync(path.join(testDirB, 'cmd.js'), 'cli({ site: "b", name: "cmd" })');
566
+ fs.writeFileSync(path.join(testDirC, 'cmd.js'), 'cli({ site: "c", name: "cmd" })');
567
567
  const lock = _readLockFile();
568
568
  lock['plugin-a'] = {
569
569
  source: { kind: 'git', url: 'https://github.com/user/plugin-a.git' },
@@ -608,7 +608,7 @@ describe('updateAllPlugins', () => {
608
608
  const cloneUrl = String(args[3]);
609
609
  const cloneDir = String(args[4]);
610
610
  fs.mkdirSync(cloneDir, { recursive: true });
611
- fs.writeFileSync(path.join(cloneDir, 'cmd.yaml'), 'site: test\nname: hello\n');
611
+ fs.writeFileSync(path.join(cloneDir, 'cmd.js'), 'cli({ site: "test", name: "hello" })');
612
612
  if (cloneUrl.includes('plugin-b')) {
613
613
  fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: 'plugin-b' }));
614
614
  }
@@ -695,7 +695,7 @@ describe('monorepo uninstall with symlink', () => {
695
695
  monoDir = path.join(_getMonoreposDir(), '__test-mono__');
696
696
  const subDir = path.join(monoDir, 'packages', 'sub');
697
697
  fs.mkdirSync(subDir, { recursive: true });
698
- fs.writeFileSync(path.join(subDir, 'cmd.yaml'), 'site: test');
698
+ fs.writeFileSync(path.join(subDir, 'cmd.js'), 'cli({ site: "test", name: "cmd" })');
699
699
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
700
700
  fs.symlinkSync(subDir, pluginDir, 'dir');
701
701
  const lock = _readLockFile();
@@ -762,7 +762,7 @@ describe('listPlugins with monorepo metadata', () => {
762
762
  const testLink = path.join(PLUGINS_DIR, '__test-mono-list__');
763
763
  beforeEach(() => {
764
764
  fs.mkdirSync(testSymlinkTarget, { recursive: true });
765
- fs.writeFileSync(path.join(testSymlinkTarget, 'hello.yaml'), 'site: test\nname: hello\n');
765
+ fs.writeFileSync(path.join(testSymlinkTarget, 'hello.js'), 'cli({ site: "test", name: "hello" })');
766
766
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
767
767
  try {
768
768
  fs.unlinkSync(testLink);
@@ -809,7 +809,7 @@ describe('installLocalPlugin', () => {
809
809
  const pluginName = '__test-local-plugin__';
810
810
  beforeEach(() => {
811
811
  tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-install-'));
812
- fs.writeFileSync(path.join(tmpDir, 'hello.yaml'), 'site: test\nname: hello\n');
812
+ fs.writeFileSync(path.join(tmpDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
813
813
  });
814
814
  afterEach(() => {
815
815
  const linkPath = path.join(PLUGINS_DIR, pluginName);
@@ -1007,7 +1007,7 @@ describe('installPlugin transactional staging', () => {
1007
1007
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
1008
1008
  const cloneDir = String(args[args.length - 1]);
1009
1009
  fs.mkdirSync(cloneDir, { recursive: true });
1010
- fs.writeFileSync(path.join(cloneDir, 'hello.yaml'), 'site: test\nname: hello\n');
1010
+ fs.writeFileSync(path.join(cloneDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1011
1011
  fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: standaloneName }));
1012
1012
  return '';
1013
1013
  }
@@ -1038,7 +1038,7 @@ describe('installPlugin transactional staging', () => {
1038
1038
  alpha: { path: 'packages/alpha' },
1039
1039
  },
1040
1040
  }));
1041
- fs.writeFileSync(path.join(alphaDir, 'hello.yaml'), 'site: test\nname: hello\n');
1041
+ fs.writeFileSync(path.join(alphaDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1042
1042
  return '';
1043
1043
  }
1044
1044
  if (cmd === 'npm' && Array.isArray(args) && args[0] === 'install') {
@@ -1095,7 +1095,7 @@ describe('installPlugin with existing monorepo', () => {
1095
1095
  [pluginName]: { path: `packages/${pluginName}` },
1096
1096
  },
1097
1097
  }));
1098
- fs.writeFileSync(path.join(subDir, 'hello.yaml'), 'site: test\nname: hello\n');
1098
+ fs.writeFileSync(path.join(subDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1099
1099
  mockExecFileSync.mockImplementation((cmd, args) => {
1100
1100
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
1101
1101
  const cloneDir = String(args[4]);
@@ -1154,7 +1154,7 @@ describe('updatePlugin transactional staging', () => {
1154
1154
  });
1155
1155
  it('keeps the existing standalone plugin when staged update preparation fails', () => {
1156
1156
  fs.mkdirSync(standaloneDir, { recursive: true });
1157
- fs.writeFileSync(path.join(standaloneDir, 'old.yaml'), 'site: old\nname: old\n');
1157
+ fs.writeFileSync(path.join(standaloneDir, 'old.js'), 'cli({ site: "old", name: "old" })');
1158
1158
  const lock = _readLockFile();
1159
1159
  lock[standaloneName] = {
1160
1160
  source: {
@@ -1169,7 +1169,7 @@ describe('updatePlugin transactional staging', () => {
1169
1169
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
1170
1170
  const cloneDir = String(args[4]);
1171
1171
  fs.mkdirSync(cloneDir, { recursive: true });
1172
- fs.writeFileSync(path.join(cloneDir, 'hello.yaml'), 'site: test\nname: hello\n');
1172
+ fs.writeFileSync(path.join(cloneDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1173
1173
  fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: standaloneName }));
1174
1174
  return '';
1175
1175
  }
@@ -1183,13 +1183,13 @@ describe('updatePlugin transactional staging', () => {
1183
1183
  });
1184
1184
  expect(() => updatePlugin(standaloneName)).toThrow('npm install failed');
1185
1185
  expect(fs.existsSync(standaloneDir)).toBe(true);
1186
- expect(fs.readFileSync(path.join(standaloneDir, 'old.yaml'), 'utf-8')).toContain('site: old');
1186
+ expect(fs.readFileSync(path.join(standaloneDir, 'old.js'), 'utf-8')).toContain('site: "old"');
1187
1187
  expect(_readLockFile()[standaloneName]?.commitHash).toBe('oldhasholdhasholdhasholdhasholdhasholdh');
1188
1188
  });
1189
1189
  it('keeps the existing monorepo repo and link when staged update preparation fails', () => {
1190
1190
  const subDir = path.join(monorepoRepoDir, 'packages', monorepoPluginName);
1191
1191
  fs.mkdirSync(subDir, { recursive: true });
1192
- fs.writeFileSync(path.join(subDir, 'old.yaml'), 'site: old\nname: old\n');
1192
+ fs.writeFileSync(path.join(subDir, 'old.js'), 'cli({ site: "old", name: "old" })');
1193
1193
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
1194
1194
  fs.symlinkSync(subDir, monorepoLink, 'dir');
1195
1195
  const lock = _readLockFile();
@@ -1218,7 +1218,7 @@ describe('updatePlugin transactional staging', () => {
1218
1218
  [monorepoPluginName]: { path: `packages/${monorepoPluginName}` },
1219
1219
  },
1220
1220
  }));
1221
- fs.writeFileSync(path.join(alphaDir, 'hello.yaml'), 'site: test\nname: hello\n');
1221
+ fs.writeFileSync(path.join(alphaDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1222
1222
  return '';
1223
1223
  }
1224
1224
  if (cmd === 'npm' && Array.isArray(args) && args[0] === 'install') {
@@ -1232,13 +1232,13 @@ describe('updatePlugin transactional staging', () => {
1232
1232
  expect(() => updatePlugin(monorepoPluginName)).toThrow('npm install failed');
1233
1233
  expect(fs.existsSync(monorepoRepoDir)).toBe(true);
1234
1234
  expect(fs.existsSync(monorepoLink)).toBe(true);
1235
- expect(fs.readFileSync(path.join(subDir, 'old.yaml'), 'utf-8')).toContain('site: old');
1235
+ expect(fs.readFileSync(path.join(subDir, 'old.js'), 'utf-8')).toContain('site: "old"');
1236
1236
  expect(_readLockFile()[monorepoPluginName]?.commitHash).toBe('oldmonooldmonooldmonooldmonooldmonoold');
1237
1237
  });
1238
1238
  it('relinks monorepo plugins when the updated manifest moves their subPath', () => {
1239
1239
  const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
1240
1240
  fs.mkdirSync(oldSubDir, { recursive: true });
1241
- fs.writeFileSync(path.join(oldSubDir, 'old.yaml'), 'site: old\nname: old\n');
1241
+ fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old" })');
1242
1242
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
1243
1243
  fs.symlinkSync(oldSubDir, monorepoLink, 'dir');
1244
1244
  const lock = _readLockFile();
@@ -1263,7 +1263,7 @@ describe('updatePlugin transactional staging', () => {
1263
1263
  [monorepoPluginName]: { path: 'packages/moved-alpha' },
1264
1264
  },
1265
1265
  }));
1266
- fs.writeFileSync(path.join(movedDir, 'hello.yaml'), 'site: test\nname: hello\n');
1266
+ fs.writeFileSync(path.join(movedDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1267
1267
  return '';
1268
1268
  }
1269
1269
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'rev-parse' && args[1] === 'HEAD') {
@@ -1282,7 +1282,7 @@ describe('updatePlugin transactional staging', () => {
1282
1282
  it('rolls back the monorepo repo swap when relinking fails', () => {
1283
1283
  const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
1284
1284
  fs.mkdirSync(oldSubDir, { recursive: true });
1285
- fs.writeFileSync(path.join(oldSubDir, 'old.yaml'), 'site: old\nname: old\n');
1285
+ fs.writeFileSync(path.join(oldSubDir, 'old.js'), 'cli({ site: "old", name: "old" })');
1286
1286
  fs.mkdirSync(monorepoLink, { recursive: true });
1287
1287
  fs.writeFileSync(path.join(monorepoLink, 'blocker.txt'), 'not a symlink');
1288
1288
  const lock = _readLockFile();
@@ -1307,7 +1307,7 @@ describe('updatePlugin transactional staging', () => {
1307
1307
  [monorepoPluginName]: { path: 'packages/moved-alpha' },
1308
1308
  },
1309
1309
  }));
1310
- fs.writeFileSync(path.join(movedDir, 'hello.yaml'), 'site: test\nname: hello\n');
1310
+ fs.writeFileSync(path.join(movedDir, 'hello.js'), 'cli({ site: "test", name: "hello" })');
1311
1311
  return '';
1312
1312
  }
1313
1313
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'rev-parse' && args[1] === 'HEAD') {
@@ -1316,7 +1316,7 @@ describe('updatePlugin transactional staging', () => {
1316
1316
  return '';
1317
1317
  });
1318
1318
  expect(() => updatePlugin(monorepoPluginName)).toThrow('to be a symlink');
1319
- expect(fs.existsSync(path.join(monorepoRepoDir, 'packages', 'old-alpha', 'old.yaml'))).toBe(true);
1319
+ expect(fs.existsSync(path.join(monorepoRepoDir, 'packages', 'old-alpha', 'old.js'))).toBe(true);
1320
1320
  expect(fs.existsSync(path.join(monorepoRepoDir, 'packages', 'moved-alpha'))).toBe(false);
1321
1321
  expect(fs.readFileSync(path.join(monorepoLink, 'blocker.txt'), 'utf-8')).toBe('not a symlink');
1322
1322
  expect(_readLockFile()[monorepoPluginName]?.source).toMatchObject({
@@ -15,7 +15,6 @@ import * as fs from 'node:fs';
15
15
  import * as path from 'node:path';
16
16
  import * as readline from 'node:readline';
17
17
  import chalk from 'chalk';
18
- import yaml from 'js-yaml';
19
18
  import { sendCommand } from './browser/daemon-client.js';
20
19
  import { SEARCH_PARAMS, PAGINATION_PARAMS, FIELD_ROLES } from './constants.js';
21
20
  import { urlToPattern, findArrayPath, inferCapabilityName, inferStrategy, detectAuthFromContent, classifyQueryParams, isNoiseUrl, } from './analysis.js';
@@ -454,8 +453,8 @@ export async function recordSession(opts) {
454
453
  const pollMs = opts.pollMs ?? 2000;
455
454
  const timeoutMs = opts.timeoutMs ?? 60_000;
456
455
  const allRequests = [];
457
- // Track which tabIds have already had the interceptor injected
458
- const injectedTabs = new Set();
456
+ // Track which pages (targetIds) have already had the interceptor injected
457
+ const injectedPages = new Set();
459
458
  // Infer site name from URL
460
459
  const site = opts.site ?? (() => {
461
460
  try {
@@ -479,9 +478,10 @@ export async function recordSession(opts) {
479
478
  // Inject into initial tab
480
479
  const initialTabs = await listTabs(workspace);
481
480
  for (const tab of initialTabs) {
482
- await injectIntoTab(workspace, tab.tabId, injectedTabs);
481
+ if (tab.page)
482
+ await injectIntoPage(workspace, tab.page, injectedPages);
483
483
  }
484
- console.log(chalk.bold('\n Recording. Operate the page in the automation window.'));
484
+ console.log(chalk.bold('\n Recording. Use the page in the browser automation window.'));
485
485
  console.log(chalk.dim(` Will auto-stop after ${timeoutMs / 1000}s, or press Enter to stop now.\n`));
486
486
  // Race: Enter key vs timeout
487
487
  let stopped = false;
@@ -500,15 +500,16 @@ export async function recordSession(opts) {
500
500
  // Discover and inject into any new tabs
501
501
  const tabs = await listTabs(workspace);
502
502
  for (const tab of tabs) {
503
- await injectIntoTab(workspace, tab.tabId, injectedTabs);
503
+ if (tab.page)
504
+ await injectIntoPage(workspace, tab.page, injectedPages);
504
505
  }
505
- // Drain captured data from all known tabs
506
- for (const tabId of injectedTabs) {
507
- const batch = await execOnTab(workspace, tabId, generateReadRecordedJs());
506
+ // Drain captured data from all known pages
507
+ for (const page of injectedPages) {
508
+ const batch = await execOnPage(workspace, page, generateReadRecordedJs());
508
509
  if (Array.isArray(batch) && batch.length > 0) {
509
510
  for (const r of batch)
510
511
  allRequests.push(r);
511
- console.log(chalk.dim(` [tab:${tabId}] +${batch.length} captured — total: ${allRequests.length}`));
512
+ console.log(chalk.dim(` [page:${page.slice(0, 8)}] +${batch.length} captured — total: ${allRequests.length}`));
512
513
  }
513
514
  }
514
515
  }
@@ -519,10 +520,10 @@ export async function recordSession(opts) {
519
520
  await Promise.race([enterPromise, timeoutPromise]);
520
521
  cleanupEnter(); // Always clean up readline to prevent process from hanging
521
522
  clearInterval(pollInterval);
522
- // Final drain from all known tabs
523
- for (const tabId of injectedTabs) {
523
+ // Final drain from all known pages
524
+ for (const page of injectedPages) {
524
525
  try {
525
- const last = await execOnTab(workspace, tabId, generateReadRecordedJs());
526
+ const last = await execOnPage(workspace, page, generateReadRecordedJs());
526
527
  if (Array.isArray(last) && last.length > 0) {
527
528
  for (const r of last)
528
529
  allRequests.push(r);
@@ -543,25 +544,25 @@ export async function recordSession(opts) {
543
544
  async function listTabs(workspace) {
544
545
  try {
545
546
  const result = await sendCommand('tabs', { op: 'list', workspace });
546
- return Array.isArray(result) ? result.filter(t => t.tabId != null) : [];
547
+ return Array.isArray(result) ? result.filter(t => t.page != null) : [];
547
548
  }
548
549
  catch {
549
550
  return [];
550
551
  }
551
552
  }
552
- async function execOnTab(workspace, tabId, code) {
553
- return sendCommand('exec', { code, workspace, tabId });
553
+ async function execOnPage(workspace, page, code) {
554
+ return sendCommand('exec', { code, workspace, page });
554
555
  }
555
- async function injectIntoTab(workspace, tabId, injectedTabs) {
556
+ async function injectIntoPage(workspace, page, injectedPages) {
556
557
  try {
557
- await execOnTab(workspace, tabId, generateFullCaptureInterceptorJs());
558
- if (!injectedTabs.has(tabId)) {
559
- injectedTabs.add(tabId);
560
- console.log(chalk.green(` ✓ Interceptor injected into tab:${tabId}`));
558
+ await execOnPage(workspace, page, generateFullCaptureInterceptorJs());
559
+ if (!injectedPages.has(page)) {
560
+ injectedPages.add(page);
561
+ console.log(chalk.green(` ✓ Interceptor injected into page:${page.slice(0, 8)}`));
561
562
  }
562
563
  }
563
564
  catch {
564
- // Tab not debuggable (e.g. chrome:// pages) — skip silently
565
+ // Page not debuggable (e.g. chrome:// pages) — skip silently
565
566
  }
566
567
  }
567
568
  /**
@@ -619,10 +620,10 @@ function analyzeAndWrite(site, pageUrl, requests, outDir) {
619
620
  if (usedNames.has(entry.name))
620
621
  continue;
621
622
  usedNames.add(entry.name);
622
- const filePath = path.join(candidatesDir, `${entry.name}.yaml`);
623
- fs.writeFileSync(filePath, yaml.dump(entry.yaml, { sortKeys: false, lineWidth: 120 }));
623
+ const filePath = path.join(candidatesDir, `${entry.name}.json`);
624
+ fs.writeFileSync(filePath, JSON.stringify(entry.yaml, null, 2));
624
625
  candidates.push({ name: entry.name, path: filePath, strategy: entry.strategy });
625
- console.log(chalk.green(` ✓ Generated: ${chalk.bold(entry.name)}.yaml [${entry.strategy}]`));
626
+ console.log(chalk.green(` ✓ Generated: ${chalk.bold(entry.name)}.json [${entry.strategy}]`));
626
627
  console.log(chalk.dim(` → ${filePath}`));
627
628
  }
628
629
  if (candidates.length === 0) {
@@ -10,19 +10,15 @@
10
10
  */
11
11
  export function detectRuntime() {
12
12
  // Bun always exposes globalThis.Bun (including Bun.version)
13
- if (typeof globalThis.Bun !== 'undefined')
14
- return 'bun';
15
- return 'node';
13
+ return globalThis.Bun !== undefined ? 'bun' : 'node';
16
14
  }
17
15
  /**
18
16
  * Return a human-readable version string for the current runtime.
19
17
  * Examples: "v22.13.0" (Node), "1.1.42" (Bun)
20
18
  */
21
19
  export function getRuntimeVersion() {
22
- if (detectRuntime() === 'bun') {
23
- return globalThis.Bun.version;
24
- }
25
- return process.version; // e.g. "v22.13.0"
20
+ const bun = globalThis.Bun;
21
+ return bun ? bun.version : process.version;
26
22
  }
27
23
  /**
28
24
  * Return a combined label like "node v22.13.0" or "bun 1.1.42".
@@ -1,4 +1,7 @@
1
1
  /**
2
2
  * Injected script for detecting frontend frameworks (Vue, React, Next, Nuxt, etc.)
3
+ *
4
+ * Serialized via `.toString()` and evaluated in the page context. Types here are
5
+ * only for the TS boundary — see scripts/store.ts for the same pattern.
3
6
  */
4
7
  export declare function detectFramework(): Record<string, boolean>;
@@ -1,16 +1,20 @@
1
1
  /**
2
2
  * Injected script for detecting frontend frameworks (Vue, React, Next, Nuxt, etc.)
3
+ *
4
+ * Serialized via `.toString()` and evaluated in the page context. Types here are
5
+ * only for the TS boundary — see scripts/store.ts for the same pattern.
3
6
  */
4
7
  export function detectFramework() {
5
8
  const r = {};
6
9
  try {
7
10
  const app = document.querySelector('#app');
11
+ const w = window;
8
12
  r.vue3 = !!(app && app.__vue_app__);
9
13
  r.vue2 = !!(app && app.__vue__);
10
- r.react = !!window.__REACT_DEVTOOLS_GLOBAL_HOOK__ || !!document.querySelector('[data-reactroot]');
11
- r.nextjs = !!window.__NEXT_DATA__;
12
- r.nuxt = !!window.__NUXT__;
13
- if (r.vue3 && app.__vue_app__) {
14
+ r.react = !!w.__REACT_DEVTOOLS_GLOBAL_HOOK__ || !!document.querySelector('[data-reactroot]');
15
+ r.nextjs = !!w.__NEXT_DATA__;
16
+ r.nuxt = !!w.__NUXT__;
17
+ if (r.vue3 && app?.__vue_app__) {
14
18
  const gp = app.__vue_app__.config?.globalProperties;
15
19
  r.pinia = !!(gp && gp.$pinia);
16
20
  r.vuex = !!(gp && gp.$store);
@@ -1,5 +1,9 @@
1
1
  /**
2
- * Injected script for discovering Pinia or Vuex stores and their actions/state representations
2
+ * Injected script for discovering Pinia or Vuex stores and their actions/state representations.
3
+ *
4
+ * This function is serialized via `.toString()` and evaluated inside the page context,
5
+ * so the types below only exist at the TS boundary — the runtime shapes are whatever
6
+ * Pinia/Vuex put on the Vue app. We use narrow structural types for the fields we touch.
3
7
  */
4
8
  export declare function discoverStores(): {
5
9
  type: string;
@@ -1,5 +1,9 @@
1
1
  /**
2
- * Injected script for discovering Pinia or Vuex stores and their actions/state representations
2
+ * Injected script for discovering Pinia or Vuex stores and their actions/state representations.
3
+ *
4
+ * This function is serialized via `.toString()` and evaluated inside the page context,
5
+ * so the types below only exist at the TS boundary — the runtime shapes are whatever
6
+ * Pinia/Vuex put on the Vue app. We use narrow structural types for the fields we touch.
3
7
  */
4
8
  export function discoverStores() {
5
9
  const stores = [];
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Generate skill: thin wrapper over generateVerifiedFromUrl.
3
+ *
4
+ * Maps GenerateOutcome → SkillOutput.
5
+ * Used by `opencli generate <url>` (automated path in opencli-explorer workflow).
6
+ *
7
+ * Design:
8
+ * - Input: url + goal? (user intent, not execution strategy)
9
+ * - Output: machine-readable decision fields + human-readable message
10
+ * - Single source of truth: P1 GenerateOutcome
11
+ * - No re-orchestration, no auto-escalation to browser
12
+ */
13
+ import { type GenerateOutcome, type StopReason, type EscalationReason, type SuggestedAction, type Reusability } from './generate-verified.js';
14
+ import type { IBrowserFactory } from './runtime.js';
15
+ export interface SkillInput {
16
+ url: string;
17
+ goal?: string;
18
+ }
19
+ export interface SkillOutput {
20
+ conclusion: 'success' | 'blocked' | 'needs-human-check';
21
+ reason?: StopReason | EscalationReason;
22
+ suggested_action?: SuggestedAction;
23
+ reusability?: Reusability;
24
+ command?: string;
25
+ strategy?: string;
26
+ path?: string;
27
+ message: string;
28
+ }
29
+ export declare function mapOutcomeToSkillOutput(outcome: GenerateOutcome): SkillOutput;
30
+ export declare function executeGenerateSkill(input: SkillInput, BrowserFactory: new () => IBrowserFactory): Promise<SkillOutput>;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Generate skill: thin wrapper over generateVerifiedFromUrl.
3
+ *
4
+ * Maps GenerateOutcome → SkillOutput.
5
+ * Used by `opencli generate <url>` (automated path in opencli-explorer workflow).
6
+ *
7
+ * Design:
8
+ * - Input: url + goal? (user intent, not execution strategy)
9
+ * - Output: machine-readable decision fields + human-readable message
10
+ * - Single source of truth: P1 GenerateOutcome
11
+ * - No re-orchestration, no auto-escalation to browser
12
+ */
13
+ import { generateVerifiedFromUrl, } from './generate-verified.js';
14
+ // ── Message Templates ────────────────────────────────────────────────────────
15
+ const BLOCKED_MESSAGES = {
16
+ 'no-viable-api-surface': '该站点没有发现可用的 JSON API 接口,无法自动生成 CLI',
17
+ 'auth-too-complex': '所有接口都需要超出自动化能力的认证方式(如 signature/bearer),无法自动生成',
18
+ 'no-viable-candidate': '发现了 API 接口,但未能合成有效的 CLI 候选',
19
+ 'execution-environment-unavailable': '浏览器未连接,请先运行 opencli doctor 检查环境',
20
+ };
21
+ const ESCALATION_MESSAGES = {
22
+ 'unsupported-required-args': () => '候选需要用户提供必填参数的示例值后重试',
23
+ 'empty-result': () => '候选验证返回空结果,建议用 opencli-browser 检查',
24
+ 'sparse-fields': () => '候选验证结果字段不足,建议人工检查',
25
+ 'non-array-result': () => '返回结果不是数组格式,建议用 opencli-browser 检查接口返回结构',
26
+ 'timeout': () => '验证超时,建议用 opencli-browser 手动检查接口响应',
27
+ 'selector-mismatch': () => '数据路径不匹配,建议用 opencli-browser 检查实际返回结构',
28
+ 'verify-inconclusive': (ctx) => ctx?.path
29
+ ? `验证结果不确定,候选已保存在 ${ctx.path},需要人工审查`
30
+ : '验证结果不确定,需要人工审查',
31
+ };
32
+ // ── Core Mapping ─────────────────────────────────────────────────────────────
33
+ export function mapOutcomeToSkillOutput(outcome) {
34
+ switch (outcome.status) {
35
+ case 'success':
36
+ return {
37
+ conclusion: 'success',
38
+ reusability: outcome.reusability ?? 'verified-artifact',
39
+ command: outcome.adapter?.command,
40
+ strategy: outcome.adapter?.strategy,
41
+ path: outcome.adapter?.path,
42
+ message: `已生成 ${outcome.adapter?.command ?? 'unknown'},可直接使用。策略: ${outcome.adapter?.strategy ?? 'unknown'}`,
43
+ };
44
+ case 'blocked':
45
+ return {
46
+ conclusion: 'blocked',
47
+ reason: outcome.reason,
48
+ message: BLOCKED_MESSAGES[outcome.reason] ?? outcome.message ?? '生成被阻断',
49
+ };
50
+ case 'needs-human-check': {
51
+ const escalation = outcome.escalation;
52
+ const reason = escalation?.reason;
53
+ const candidatePath = escalation?.candidate?.path ?? undefined;
54
+ const messageFn = reason ? ESCALATION_MESSAGES[reason] : undefined;
55
+ return {
56
+ conclusion: 'needs-human-check',
57
+ reason,
58
+ suggested_action: escalation?.suggested_action,
59
+ reusability: outcome.reusability,
60
+ path: candidatePath ?? undefined,
61
+ message: outcome.message ?? messageFn?.({ path: candidatePath ?? undefined }) ?? '需要人工检查',
62
+ };
63
+ }
64
+ }
65
+ }
66
+ // ── Skill Entry Point ────────────────────────────────────────────────────────
67
+ export async function executeGenerateSkill(input, BrowserFactory) {
68
+ const opts = {
69
+ url: input.url,
70
+ BrowserFactory,
71
+ goal: input.goal ?? null,
72
+ };
73
+ const outcome = await generateVerifiedFromUrl(opts);
74
+ return mapOutcomeToSkillOutput(outcome);
75
+ }
@@ -0,0 +1 @@
1
+ export {};