@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
@@ -12,7 +12,7 @@ const { mockExecFileSync, mockExecSync } = vi.hoisted(() => ({
12
12
  mockExecFileSync: vi.fn(),
13
13
  mockExecSync: vi.fn(),
14
14
  }));
15
- const { _getCommitHash, _installDependencies, _postInstallMonorepoLifecycle, _promoteDir, _replaceDir, installPlugin, listPlugins, _readLockFile, _readLockFileWithWriter, _resolveEsbuildBin, uninstallPlugin, updatePlugin, _parseSource, _updateAllPlugins, _validatePluginStructure, _writeLockFile, _writeLockFileWithFs, _isSymlinkSync, _getMonoreposDir, getLockFilePath, _installLocalPlugin, _isLocalPluginSource, _moveDir, _resolvePluginSource, _resolveStoredPluginSource, _toStoredPluginSource, _toLocalPluginSource, } = pluginModule;
15
+ const { _getCommitHash, _installDependencies, _postInstallMonorepoLifecycle, _promoteDir, _replaceDir, installPlugin, listPlugins, _readLockFile, _readLockFileWithWriter, _resolveEsbuildBin, _resolveHostOpencliRoot, uninstallPlugin, updatePlugin, _parseSource, _updateAllPlugins, _validatePluginStructure, _writeLockFile, _writeLockFileWithFs, _isSymlinkSync, _getMonoreposDir, getLockFilePath, _installLocalPlugin, _isLocalPluginSource, _moveDir, _resolvePluginSource, _resolveStoredPluginSource, _toStoredPluginSource, _toLocalPluginSource, } = pluginModule;
16
16
  describe('parseSource', () => {
17
17
  it('parses github:user/repo format', () => {
18
18
  const result = _parseSource('github:ByteYue/opencli-plugin-github-trending');
@@ -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");');
@@ -336,6 +336,21 @@ describe('resolveEsbuildBin', () => {
336
336
  expect(binPath).toMatch(/esbuild(\.cmd)?$/);
337
337
  });
338
338
  });
339
+ describe('resolveHostOpencliRoot', () => {
340
+ let tmpDir;
341
+ beforeEach(() => {
342
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-host-root-test-'));
343
+ });
344
+ afterEach(() => {
345
+ fs.rmSync(tmpDir, { recursive: true, force: true });
346
+ });
347
+ it('walks up from compiled dist/src files to the package root', () => {
348
+ fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify({ name: '@jackwener/opencli' }));
349
+ const distSrcDir = path.join(tmpDir, 'dist', 'src');
350
+ fs.mkdirSync(distSrcDir, { recursive: true });
351
+ expect(_resolveHostOpencliRoot(path.join(distSrcDir, 'plugin.js'))).toBe(tmpDir);
352
+ });
353
+ });
339
354
  describe('listPlugins', () => {
340
355
  const testDir = path.join(PLUGINS_DIR, '__test-list-plugin__');
341
356
  afterEach(() => {
@@ -346,7 +361,7 @@ describe('listPlugins', () => {
346
361
  });
347
362
  it('lists installed plugins', () => {
348
363
  fs.mkdirSync(testDir, { recursive: true });
349
- 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" })');
350
365
  const plugins = listPlugins();
351
366
  const found = plugins.find(p => p.name === '__test-list-plugin__');
352
367
  expect(found).toBeDefined();
@@ -354,7 +369,7 @@ describe('listPlugins', () => {
354
369
  });
355
370
  it('includes version metadata from the lock file', () => {
356
371
  fs.mkdirSync(testDir, { recursive: true });
357
- 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" })');
358
373
  const lock = _readLockFile();
359
374
  lock['__test-list-plugin__'] = {
360
375
  source: { kind: 'git', url: 'https://github.com/user/repo.git' },
@@ -378,7 +393,7 @@ describe('listPlugins', () => {
378
393
  const localTarget = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-list-'));
379
394
  const linkPath = path.join(PLUGINS_DIR, '__test-list-plugin__');
380
395
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
381
- 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" })');
382
397
  try {
383
398
  fs.unlinkSync(linkPath);
384
399
  }
@@ -420,13 +435,13 @@ describe('uninstallPlugin', () => {
420
435
  });
421
436
  it('removes plugin directory', () => {
422
437
  fs.mkdirSync(testDir, { recursive: true });
423
- fs.writeFileSync(path.join(testDir, 'test.yaml'), 'site: test');
438
+ fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test" })');
424
439
  uninstallPlugin('__test-uninstall__');
425
440
  expect(fs.existsSync(testDir)).toBe(false);
426
441
  });
427
442
  it('removes lock entry on uninstall', () => {
428
443
  fs.mkdirSync(testDir, { recursive: true });
429
- fs.writeFileSync(path.join(testDir, 'test.yaml'), 'site: test');
444
+ fs.writeFileSync(path.join(testDir, 'test.js'), 'cli({ site: "test", name: "test" })');
430
445
  const lock = _readLockFile();
431
446
  lock['__test-uninstall__'] = {
432
447
  source: { kind: 'git', url: 'https://github.com/user/repo.git' },
@@ -449,7 +464,7 @@ describe('updatePlugin', () => {
449
464
  const localTarget = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-update-'));
450
465
  const linkPath = path.join(PLUGINS_DIR, '__test-local-update__');
451
466
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
452
- 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" })');
453
468
  fs.symlinkSync(localTarget, linkPath, 'dir');
454
469
  const lock = _readLockFile();
455
470
  lock['__test-local-update__'] = {
@@ -525,7 +540,7 @@ describe('postInstallMonorepoLifecycle', () => {
525
540
  private: true,
526
541
  workspaces: ['packages/*'],
527
542
  }));
528
- 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" })');
529
544
  });
530
545
  afterEach(() => {
531
546
  fs.rmSync(repoDir, { recursive: true, force: true });
@@ -546,9 +561,9 @@ describe('updateAllPlugins', () => {
546
561
  fs.mkdirSync(testDirA, { recursive: true });
547
562
  fs.mkdirSync(testDirB, { recursive: true });
548
563
  fs.mkdirSync(testDirC, { recursive: true });
549
- fs.writeFileSync(path.join(testDirA, 'cmd.yaml'), 'site: a');
550
- fs.writeFileSync(path.join(testDirB, 'cmd.yaml'), 'site: b');
551
- 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" })');
552
567
  const lock = _readLockFile();
553
568
  lock['plugin-a'] = {
554
569
  source: { kind: 'git', url: 'https://github.com/user/plugin-a.git' },
@@ -593,7 +608,7 @@ describe('updateAllPlugins', () => {
593
608
  const cloneUrl = String(args[3]);
594
609
  const cloneDir = String(args[4]);
595
610
  fs.mkdirSync(cloneDir, { recursive: true });
596
- 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" })');
597
612
  if (cloneUrl.includes('plugin-b')) {
598
613
  fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: 'plugin-b' }));
599
614
  }
@@ -680,7 +695,7 @@ describe('monorepo uninstall with symlink', () => {
680
695
  monoDir = path.join(_getMonoreposDir(), '__test-mono__');
681
696
  const subDir = path.join(monoDir, 'packages', 'sub');
682
697
  fs.mkdirSync(subDir, { recursive: true });
683
- fs.writeFileSync(path.join(subDir, 'cmd.yaml'), 'site: test');
698
+ fs.writeFileSync(path.join(subDir, 'cmd.js'), 'cli({ site: "test", name: "cmd" })');
684
699
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
685
700
  fs.symlinkSync(subDir, pluginDir, 'dir');
686
701
  const lock = _readLockFile();
@@ -747,7 +762,7 @@ describe('listPlugins with monorepo metadata', () => {
747
762
  const testLink = path.join(PLUGINS_DIR, '__test-mono-list__');
748
763
  beforeEach(() => {
749
764
  fs.mkdirSync(testSymlinkTarget, { recursive: true });
750
- 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" })');
751
766
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
752
767
  try {
753
768
  fs.unlinkSync(testLink);
@@ -794,7 +809,7 @@ describe('installLocalPlugin', () => {
794
809
  const pluginName = '__test-local-plugin__';
795
810
  beforeEach(() => {
796
811
  tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-local-install-'));
797
- 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" })');
798
813
  });
799
814
  afterEach(() => {
800
815
  const linkPath = path.join(PLUGINS_DIR, pluginName);
@@ -992,7 +1007,7 @@ describe('installPlugin transactional staging', () => {
992
1007
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
993
1008
  const cloneDir = String(args[args.length - 1]);
994
1009
  fs.mkdirSync(cloneDir, { recursive: true });
995
- 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" })');
996
1011
  fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: standaloneName }));
997
1012
  return '';
998
1013
  }
@@ -1023,7 +1038,7 @@ describe('installPlugin transactional staging', () => {
1023
1038
  alpha: { path: 'packages/alpha' },
1024
1039
  },
1025
1040
  }));
1026
- 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" })');
1027
1042
  return '';
1028
1043
  }
1029
1044
  if (cmd === 'npm' && Array.isArray(args) && args[0] === 'install') {
@@ -1080,7 +1095,7 @@ describe('installPlugin with existing monorepo', () => {
1080
1095
  [pluginName]: { path: `packages/${pluginName}` },
1081
1096
  },
1082
1097
  }));
1083
- 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" })');
1084
1099
  mockExecFileSync.mockImplementation((cmd, args) => {
1085
1100
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
1086
1101
  const cloneDir = String(args[4]);
@@ -1139,7 +1154,7 @@ describe('updatePlugin transactional staging', () => {
1139
1154
  });
1140
1155
  it('keeps the existing standalone plugin when staged update preparation fails', () => {
1141
1156
  fs.mkdirSync(standaloneDir, { recursive: true });
1142
- 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" })');
1143
1158
  const lock = _readLockFile();
1144
1159
  lock[standaloneName] = {
1145
1160
  source: {
@@ -1154,7 +1169,7 @@ describe('updatePlugin transactional staging', () => {
1154
1169
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'clone') {
1155
1170
  const cloneDir = String(args[4]);
1156
1171
  fs.mkdirSync(cloneDir, { recursive: true });
1157
- 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" })');
1158
1173
  fs.writeFileSync(path.join(cloneDir, 'package.json'), JSON.stringify({ name: standaloneName }));
1159
1174
  return '';
1160
1175
  }
@@ -1168,13 +1183,13 @@ describe('updatePlugin transactional staging', () => {
1168
1183
  });
1169
1184
  expect(() => updatePlugin(standaloneName)).toThrow('npm install failed');
1170
1185
  expect(fs.existsSync(standaloneDir)).toBe(true);
1171
- 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"');
1172
1187
  expect(_readLockFile()[standaloneName]?.commitHash).toBe('oldhasholdhasholdhasholdhasholdhasholdh');
1173
1188
  });
1174
1189
  it('keeps the existing monorepo repo and link when staged update preparation fails', () => {
1175
1190
  const subDir = path.join(monorepoRepoDir, 'packages', monorepoPluginName);
1176
1191
  fs.mkdirSync(subDir, { recursive: true });
1177
- 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" })');
1178
1193
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
1179
1194
  fs.symlinkSync(subDir, monorepoLink, 'dir');
1180
1195
  const lock = _readLockFile();
@@ -1203,7 +1218,7 @@ describe('updatePlugin transactional staging', () => {
1203
1218
  [monorepoPluginName]: { path: `packages/${monorepoPluginName}` },
1204
1219
  },
1205
1220
  }));
1206
- 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" })');
1207
1222
  return '';
1208
1223
  }
1209
1224
  if (cmd === 'npm' && Array.isArray(args) && args[0] === 'install') {
@@ -1217,13 +1232,13 @@ describe('updatePlugin transactional staging', () => {
1217
1232
  expect(() => updatePlugin(monorepoPluginName)).toThrow('npm install failed');
1218
1233
  expect(fs.existsSync(monorepoRepoDir)).toBe(true);
1219
1234
  expect(fs.existsSync(monorepoLink)).toBe(true);
1220
- 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"');
1221
1236
  expect(_readLockFile()[monorepoPluginName]?.commitHash).toBe('oldmonooldmonooldmonooldmonooldmonoold');
1222
1237
  });
1223
1238
  it('relinks monorepo plugins when the updated manifest moves their subPath', () => {
1224
1239
  const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
1225
1240
  fs.mkdirSync(oldSubDir, { recursive: true });
1226
- 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" })');
1227
1242
  fs.mkdirSync(PLUGINS_DIR, { recursive: true });
1228
1243
  fs.symlinkSync(oldSubDir, monorepoLink, 'dir');
1229
1244
  const lock = _readLockFile();
@@ -1248,7 +1263,7 @@ describe('updatePlugin transactional staging', () => {
1248
1263
  [monorepoPluginName]: { path: 'packages/moved-alpha' },
1249
1264
  },
1250
1265
  }));
1251
- 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" })');
1252
1267
  return '';
1253
1268
  }
1254
1269
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'rev-parse' && args[1] === 'HEAD') {
@@ -1267,7 +1282,7 @@ describe('updatePlugin transactional staging', () => {
1267
1282
  it('rolls back the monorepo repo swap when relinking fails', () => {
1268
1283
  const oldSubDir = path.join(monorepoRepoDir, 'packages', 'old-alpha');
1269
1284
  fs.mkdirSync(oldSubDir, { recursive: true });
1270
- 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" })');
1271
1286
  fs.mkdirSync(monorepoLink, { recursive: true });
1272
1287
  fs.writeFileSync(path.join(monorepoLink, 'blocker.txt'), 'not a symlink');
1273
1288
  const lock = _readLockFile();
@@ -1292,7 +1307,7 @@ describe('updatePlugin transactional staging', () => {
1292
1307
  [monorepoPluginName]: { path: 'packages/moved-alpha' },
1293
1308
  },
1294
1309
  }));
1295
- 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" })');
1296
1311
  return '';
1297
1312
  }
1298
1313
  if (cmd === 'git' && Array.isArray(args) && args[0] === 'rev-parse' && args[1] === 'HEAD') {
@@ -1301,7 +1316,7 @@ describe('updatePlugin transactional staging', () => {
1301
1316
  return '';
1302
1317
  });
1303
1318
  expect(() => updatePlugin(monorepoPluginName)).toThrow('to be a symlink');
1304
- 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);
1305
1320
  expect(fs.existsSync(path.join(monorepoRepoDir, 'packages', 'moved-alpha'))).toBe(false);
1306
1321
  expect(fs.readFileSync(path.join(monorepoLink, 'blocker.txt'), 'utf-8')).toBe('not a symlink');
1307
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 {};