@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
@@ -2,8 +2,8 @@
2
2
  /**
3
3
  * Build-time CLI manifest compiler.
4
4
  *
5
- * Scans all YAML/TS CLI definitions and pre-compiles them into a single
6
- * manifest.json for instant cold-start registration (no runtime YAML parsing).
5
+ * Scans all TS CLI definitions and pre-compiles them into a single
6
+ * manifest.json for instant cold-start registration.
7
7
  *
8
8
  * Usage: npx tsx src/build-manifest.ts
9
9
  * Output: cli-manifest.json at the package root
@@ -11,14 +11,12 @@
11
11
  import * as fs from 'node:fs';
12
12
  import * as path from 'node:path';
13
13
  import { fileURLToPath, pathToFileURL } from 'node:url';
14
- import yaml from 'js-yaml';
15
14
  import { getErrorMessage } from './errors.js';
16
15
  import { fullName, getRegistry } from './registry.js';
17
16
  import { findPackageRoot, getCliManifestPath } from './package-paths.js';
18
17
  const PACKAGE_ROOT = findPackageRoot(fileURLToPath(import.meta.url));
19
18
  const CLIS_DIR = path.join(PACKAGE_ROOT, 'clis');
20
19
  const OUTPUT = getCliManifestPath(CLIS_DIR);
21
- import { parseYamlArgs } from './yaml-schema.js';
22
20
  import { isRecord } from './utils.js';
23
21
  const CLI_MODULE_PATTERN = /\bcli\s*\(/;
24
22
  function toManifestArgs(args) {
@@ -64,43 +62,6 @@ function toManifestEntry(cmd, modulePath, sourceFile) {
64
62
  navigateBefore: cmd.navigateBefore,
65
63
  };
66
64
  }
67
- function scanYaml(filePath, site) {
68
- try {
69
- const raw = fs.readFileSync(filePath, 'utf-8');
70
- const def = yaml.load(raw);
71
- if (!isRecord(def))
72
- return null;
73
- const cliDef = def;
74
- const strategyStr = cliDef.strategy ?? (cliDef.browser === false ? 'public' : 'cookie');
75
- const strategy = strategyStr.toUpperCase();
76
- const browser = cliDef.browser ?? (strategy !== 'PUBLIC');
77
- const args = parseYamlArgs(cliDef.args);
78
- return {
79
- site: cliDef.site ?? site,
80
- name: cliDef.name ?? path.basename(filePath, path.extname(filePath)),
81
- description: cliDef.description ?? '',
82
- domain: cliDef.domain,
83
- strategy: strategy.toLowerCase(),
84
- browser,
85
- aliases: isRecord(cliDef) && Array.isArray(cliDef.aliases)
86
- ? cliDef.aliases.filter((value) => typeof value === 'string')
87
- : undefined,
88
- args,
89
- columns: cliDef.columns,
90
- pipeline: cliDef.pipeline,
91
- timeout: cliDef.timeout,
92
- deprecated: cliDef.deprecated,
93
- replacedBy: cliDef.replacedBy,
94
- type: 'yaml',
95
- sourceFile: path.relative(CLIS_DIR, filePath),
96
- navigateBefore: cliDef.navigateBefore,
97
- };
98
- }
99
- catch (err) {
100
- process.stderr.write(`Warning: failed to parse ${filePath}: ${getErrorMessage(err)}\n`);
101
- return null;
102
- }
103
- }
104
65
  export async function loadTsManifestEntries(filePath, site, importer = moduleHref => import(moduleHref)) {
105
66
  try {
106
67
  const src = fs.readFileSync(filePath, 'utf-8');
@@ -141,15 +102,6 @@ export async function loadTsManifestEntries(filePath, site, importer = moduleHre
141
102
  return [];
142
103
  }
143
104
  }
144
- /**
145
- * When both YAML and TS adapters exist for the same site/name,
146
- * prefer the TS version (it self-registers and typically has richer logic).
147
- */
148
- export function shouldReplaceManifestEntry(current, next) {
149
- if (current.type === next.type)
150
- return false;
151
- return current.type === 'yaml' && next.type === 'ts';
152
- }
153
105
  export async function buildManifest() {
154
106
  const manifest = new Map();
155
107
  if (fs.existsSync(CLIS_DIR)) {
@@ -158,32 +110,13 @@ export async function buildManifest() {
158
110
  if (!fs.statSync(siteDir).isDirectory())
159
111
  continue;
160
112
  for (const file of fs.readdirSync(siteDir)) {
161
- const filePath = path.join(siteDir, file);
162
- if (file.endsWith('.yaml') || file.endsWith('.yml')) {
163
- const entry = scanYaml(filePath, site);
164
- if (entry) {
165
- const key = `${entry.site}/${entry.name}`;
166
- const existing = manifest.get(key);
167
- if (!existing || shouldReplaceManifestEntry(existing, entry)) {
168
- if (existing && existing.type !== entry.type) {
169
- process.stderr.write(`⚠️ Duplicate adapter ${key}: ${existing.type} superseded by ${entry.type}\n`);
170
- }
171
- manifest.set(key, entry);
172
- }
173
- }
174
- }
175
- else if ((file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.endsWith('.test.ts') && file !== 'index.ts') ||
113
+ if ((file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.endsWith('.test.ts') && file !== 'index.ts') ||
176
114
  (file.endsWith('.js') && !file.endsWith('.d.js') && !file.endsWith('.test.js') && file !== 'index.js')) {
115
+ const filePath = path.join(siteDir, file);
177
116
  const entries = await loadTsManifestEntries(filePath, site);
178
117
  for (const entry of entries) {
179
118
  const key = `${entry.site}/${entry.name}`;
180
- const existing = manifest.get(key);
181
- if (!existing || shouldReplaceManifestEntry(existing, entry)) {
182
- if (existing && existing.type !== entry.type) {
183
- process.stderr.write(`⚠️ Duplicate adapter ${key}: ${existing.type} superseded by ${entry.type}\n`);
184
- }
185
- manifest.set(key, entry);
186
- }
119
+ manifest.set(key, entry);
187
120
  }
188
121
  }
189
122
  }
@@ -195,9 +128,7 @@ async function main() {
195
128
  const manifest = await buildManifest();
196
129
  fs.mkdirSync(path.dirname(OUTPUT), { recursive: true });
197
130
  fs.writeFileSync(OUTPUT, JSON.stringify(manifest, null, 2));
198
- const yamlCount = manifest.filter(e => e.type === 'yaml').length;
199
- const tsCount = manifest.filter(e => e.type === 'ts').length;
200
- console.log(`✅ Manifest compiled: ${manifest.length} entries (${yamlCount} YAML, ${tsCount} TS) → ${OUTPUT}`);
131
+ console.log(`✅ Manifest compiled: ${manifest.length} entries ${OUTPUT}`);
201
132
  // Restore executable permissions on bin entries.
202
133
  // tsc does not preserve the +x bit, so after a clean rebuild the CLI
203
134
  // entry-point loses its executable permission, causing "Permission denied".
@@ -3,7 +3,7 @@ import * as fs from 'node:fs';
3
3
  import * as os from 'node:os';
4
4
  import * as path from 'node:path';
5
5
  import { cli, getRegistry, Strategy } from './registry.js';
6
- import { loadTsManifestEntries, shouldReplaceManifestEntry } from './build-manifest.js';
6
+ import { loadTsManifestEntries } from './build-manifest.js';
7
7
  describe('manifest helper rules', () => {
8
8
  const tempDirs = [];
9
9
  afterEach(() => {
@@ -11,44 +11,6 @@ describe('manifest helper rules', () => {
11
11
  fs.rmSync(dir, { recursive: true, force: true });
12
12
  }
13
13
  });
14
- it('prefers TS adapters over duplicate YAML adapters', () => {
15
- expect(shouldReplaceManifestEntry({
16
- site: 'demo',
17
- name: 'search',
18
- description: 'yaml',
19
- strategy: 'public',
20
- browser: false,
21
- args: [],
22
- type: 'yaml',
23
- }, {
24
- site: 'demo',
25
- name: 'search',
26
- description: 'ts',
27
- strategy: 'public',
28
- browser: false,
29
- args: [],
30
- type: 'ts',
31
- modulePath: 'demo/search.js',
32
- })).toBe(true);
33
- expect(shouldReplaceManifestEntry({
34
- site: 'demo',
35
- name: 'search',
36
- description: 'ts',
37
- strategy: 'public',
38
- browser: false,
39
- args: [],
40
- type: 'ts',
41
- modulePath: 'demo/search.js',
42
- }, {
43
- site: 'demo',
44
- name: 'search',
45
- description: 'yaml',
46
- strategy: 'public',
47
- browser: false,
48
- args: [],
49
- type: 'yaml',
50
- })).toBe(false);
51
- });
52
14
  it('skips TS files that do not register a cli', () => {
53
15
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-manifest-'));
54
16
  tempDirs.push(dir);
@@ -72,13 +72,14 @@ export async function probeEndpoint(page, url, strategy, _opts = {}) {
72
72
  try {
73
73
  const opts = PROBE_OPTIONS[strategy];
74
74
  if (opts) {
75
- const resp = await page.evaluate(buildFetchProbeJs(url, opts));
75
+ const resp = (await page.evaluate(buildFetchProbeJs(url, opts)));
76
76
  result.statusCode = resp?.status;
77
- result.success = resp?.ok && resp?.hasData;
77
+ result.success = !!(resp?.ok && resp?.hasData);
78
78
  result.hasData = resp?.hasData;
79
79
  result.responsePreview = resp?.preview;
80
80
  }
81
81
  else {
82
+ // INTERCEPT / UI require site-specific implementation.
82
83
  result.error = `Strategy ${strategy} requires site-specific implementation`;
83
84
  }
84
85
  }
package/dist/src/cli.d.ts CHANGED
@@ -8,16 +8,16 @@ import { Command } from 'commander';
8
8
  import { findPackageRoot } from './package-paths.js';
9
9
  export declare function createProgram(BUILTIN_CLIS: string, USER_CLIS: string): Command;
10
10
  export declare function runCli(BUILTIN_CLIS: string, USER_CLIS: string): void;
11
- export interface OperateVerifyInvocation {
11
+ export interface BrowserVerifyInvocation {
12
12
  binary: string;
13
13
  args: string[];
14
14
  cwd: string;
15
15
  shell?: boolean;
16
16
  }
17
17
  export { findPackageRoot };
18
- export declare function resolveOperateVerifyInvocation(opts?: {
18
+ export declare function resolveBrowserVerifyInvocation(opts?: {
19
19
  projectRoot?: string;
20
20
  platform?: NodeJS.Platform;
21
21
  fileExists?: (path: string) => boolean;
22
22
  readFile?: (path: string) => string;
23
- }): OperateVerifyInvocation;
23
+ }): BrowserVerifyInvocation;
package/dist/src/cli.js CHANGED
@@ -19,13 +19,13 @@ import { printCompletionScript } from './completion.js';
19
19
  import { loadExternalClis, executeExternalCli, installExternalCli, registerExternalCli, isBinaryInstalled } from './external.js';
20
20
  import { registerAllCommands } from './commanderAdapter.js';
21
21
  import { EXIT_CODES, getErrorMessage } from './errors.js';
22
- import { daemonStatus, daemonStop, daemonRestart } from './commands/daemon.js';
22
+ import { daemonStop } from './commands/daemon.js';
23
23
  const CLI_FILE = fileURLToPath(import.meta.url);
24
- /** Create a browser page for operate commands. Uses 'operate' workspace for session persistence. */
25
- async function getOperatePage() {
24
+ /** Create a browser page for browser commands. Uses a dedicated browser workspace for session persistence. */
25
+ async function getBrowserPage() {
26
26
  const { BrowserBridge } = await import('./browser/index.js');
27
27
  const bridge = new BrowserBridge();
28
- return bridge.connect({ timeout: 30, workspace: 'operate:default' });
28
+ return bridge.connect({ timeout: 30, workspace: 'browser:default' });
29
29
  }
30
30
  function applyVerbose(opts) {
31
31
  if (opts.verbose)
@@ -171,24 +171,30 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
171
171
  });
172
172
  program
173
173
  .command('generate')
174
- .description('One-shot: explore → synthesize → register')
174
+ .description('One-shot: explore → synthesize → verify → register')
175
175
  .argument('<url>')
176
176
  .option('--goal <text>')
177
177
  .option('--site <name>')
178
+ .option('--format <fmt>', 'Output format: table, json', 'table')
179
+ .option('--no-register', 'Verify the generated adapter without registering it')
178
180
  .option('-v, --verbose', 'Debug output')
179
181
  .action(async (url, opts) => {
180
182
  applyVerbose(opts);
181
- const { generateCliFromUrl, renderGenerateSummary } = await import('./generate.js');
183
+ const { generateVerifiedFromUrl, renderGenerateVerifiedSummary } = await import('./generate-verified.js');
182
184
  const workspace = `generate:${inferHost(url, opts.site)}`;
183
- const r = await generateCliFromUrl({
185
+ const r = await generateVerifiedFromUrl({
184
186
  url,
185
187
  BrowserFactory: getBrowserFactory(),
186
188
  goal: opts.goal,
187
189
  site: opts.site,
188
190
  workspace,
191
+ noRegister: opts.register === false,
189
192
  });
190
- console.log(renderGenerateSummary(r));
191
- process.exitCode = r.ok ? EXIT_CODES.SUCCESS : EXIT_CODES.GENERIC_ERROR;
193
+ if (opts.format === 'json')
194
+ console.log(JSON.stringify(r, null, 2));
195
+ else
196
+ console.log(renderGenerateVerifiedSummary(r));
197
+ process.exitCode = r.status === 'success' ? EXIT_CODES.SUCCESS : EXIT_CODES.GENERIC_ERROR;
192
198
  });
193
199
  // ── Built-in: record ─────────────────────────────────────────────────────
194
200
  program
@@ -235,22 +241,22 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
235
241
  }, { workspace });
236
242
  console.log(renderCascadeResult(result));
237
243
  });
238
- // ── Built-in: operate (browser control for Claude Code skill) ───────────────
244
+ // ── Built-in: browser (browser control for Claude Code skill) ───────────────
239
245
  //
240
246
  // Make websites accessible for AI agents.
241
- // All commands wrapped in operateAction() for consistent error handling.
242
- const operate = program
243
- .command('operate')
247
+ // All commands wrapped in browserAction() for consistent error handling.
248
+ const browser = program
249
+ .command('browser')
244
250
  .description('Browser control — navigate, click, type, extract, wait (no LLM needed)');
245
- /** Wrap operate actions with error handling and optional --json output */
246
- function operateAction(fn) {
251
+ /** Wrap browser actions with error handling and optional --json output */
252
+ function browserAction(fn) {
247
253
  return async (...args) => {
248
254
  try {
249
- const page = await getOperatePage();
255
+ const page = await getBrowserPage();
250
256
  await fn(page, ...args);
251
257
  }
252
258
  catch (err) {
253
- const msg = err instanceof Error ? err.message : String(err);
259
+ const msg = getErrorMessage(err);
254
260
  if (msg.includes('Extension not connected') || msg.includes('Daemon')) {
255
261
  console.error(`Browser not connected. Run 'opencli doctor' to diagnose.`);
256
262
  }
@@ -267,8 +273,8 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
267
273
  // ── Navigation ──
268
274
  /** Network interceptor JS — injected on every open/navigate to capture fetch/XHR */
269
275
  const NETWORK_INTERCEPTOR_JS = `(function(){if(window.__opencli_net)return;window.__opencli_net=[];var M=200,B=50000,F=window.fetch;window.fetch=async function(){var r=await F.apply(this,arguments);try{var ct=r.headers.get('content-type')||'';if(ct.includes('json')||ct.includes('text')){var c=r.clone(),t=await c.text();if(window.__opencli_net.length<M){var b=null;if(t.length<=B)try{b=JSON.parse(t)}catch(e){b=t}window.__opencli_net.push({url:r.url||(arguments[0]&&arguments[0].url)||String(arguments[0]),method:(arguments[1]&&arguments[1].method)||'GET',status:r.status,size:t.length,ct:ct,body:b})}}}catch(e){}return r};var X=XMLHttpRequest.prototype,O=X.open,S=X.send;X.open=function(m,u){this._om=m;this._ou=u;return O.apply(this,arguments)};X.send=function(){var x=this;x.addEventListener('load',function(){try{var ct=x.getResponseHeader('content-type')||'';if((ct.includes('json')||ct.includes('text'))&&window.__opencli_net.length<M){var t=x.responseText,b=null;if(t&&t.length<=B)try{b=JSON.parse(t)}catch(e){b=t}window.__opencli_net.push({url:x._ou,method:x._om||'GET',status:x.status,size:t?t.length:0,ct:ct,body:b})}}catch(e){}});return S.apply(this,arguments)}})()`;
270
- operate.command('open').argument('<url>').description('Open URL in automation window')
271
- .action(operateAction(async (page, url) => {
276
+ browser.command('open').argument('<url>').description('Open URL in automation window')
277
+ .action(browserAction(async (page, url) => {
272
278
  // Start session-level capture before navigation (catches initial requests)
273
279
  const hasSessionCapture = await page.startNetworkCapture?.().then(() => true).catch(() => false);
274
280
  await page.goto(url);
@@ -282,15 +288,15 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
282
288
  }
283
289
  console.log(`Navigated to: ${await page.getCurrentUrl?.() ?? url}`);
284
290
  }));
285
- operate.command('back').description('Go back in browser history')
286
- .action(operateAction(async (page) => {
291
+ browser.command('back').description('Go back in browser history')
292
+ .action(browserAction(async (page) => {
287
293
  await page.evaluate('history.back()');
288
294
  await page.wait(2);
289
295
  console.log('Navigated back');
290
296
  }));
291
- operate.command('scroll').argument('<direction>', 'up or down').option('--amount <pixels>', 'Pixels to scroll', '500')
297
+ browser.command('scroll').argument('<direction>', 'up or down').option('--amount <pixels>', 'Pixels to scroll', '500')
292
298
  .description('Scroll page')
293
- .action(operateAction(async (page, direction, opts) => {
299
+ .action(browserAction(async (page, direction, opts) => {
294
300
  if (direction !== 'up' && direction !== 'down') {
295
301
  console.error(`Invalid direction "${direction}". Use "up" or "down".`);
296
302
  process.exitCode = EXIT_CODES.USAGE_ERROR;
@@ -300,16 +306,16 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
300
306
  console.log(`Scrolled ${direction}`);
301
307
  }));
302
308
  // ── Inspect ──
303
- operate.command('state').description('Page state: URL, title, interactive elements with [N] indices')
304
- .action(operateAction(async (page) => {
309
+ browser.command('state').description('Page state: URL, title, interactive elements with [N] indices')
310
+ .action(browserAction(async (page) => {
305
311
  const snapshot = await page.snapshot({ viewportExpand: 2000 });
306
312
  const url = await page.getCurrentUrl?.() ?? '';
307
313
  console.log(`URL: ${url}\n`);
308
314
  console.log(typeof snapshot === 'string' ? snapshot : JSON.stringify(snapshot, null, 2));
309
315
  }));
310
- operate.command('screenshot').argument('[path]', 'Save to file (base64 if omitted)')
316
+ browser.command('screenshot').argument('[path]', 'Save to file (base64 if omitted)')
311
317
  .description('Take screenshot')
312
- .action(operateAction(async (page, path) => {
318
+ .action(browserAction(async (page, path) => {
313
319
  if (path) {
314
320
  await page.screenshot({ path });
315
321
  console.log(`Screenshot saved to: ${path}`);
@@ -319,45 +325,45 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
319
325
  }
320
326
  }));
321
327
  // ── Get commands (structured data extraction) ──
322
- const get = operate.command('get').description('Get page properties');
328
+ const get = browser.command('get').description('Get page properties');
323
329
  get.command('title').description('Page title')
324
- .action(operateAction(async (page) => {
330
+ .action(browserAction(async (page) => {
325
331
  console.log(await page.evaluate('document.title'));
326
332
  }));
327
333
  get.command('url').description('Current page URL')
328
- .action(operateAction(async (page) => {
334
+ .action(browserAction(async (page) => {
329
335
  console.log(await page.getCurrentUrl?.() ?? await page.evaluate('location.href'));
330
336
  }));
331
337
  get.command('text').argument('<index>', 'Element index').description('Element text content')
332
- .action(operateAction(async (page, index) => {
338
+ .action(browserAction(async (page, index) => {
333
339
  const text = await page.evaluate(`document.querySelector('[data-opencli-ref="${index}"]')?.textContent?.trim()`);
334
340
  console.log(text ?? '(empty)');
335
341
  }));
336
342
  get.command('value').argument('<index>', 'Element index').description('Input/textarea value')
337
- .action(operateAction(async (page, index) => {
343
+ .action(browserAction(async (page, index) => {
338
344
  const val = await page.evaluate(`document.querySelector('[data-opencli-ref="${index}"]')?.value`);
339
345
  console.log(val ?? '(empty)');
340
346
  }));
341
347
  get.command('html').option('--selector <css>', 'CSS selector scope').description('Page HTML (or scoped)')
342
- .action(operateAction(async (page, opts) => {
348
+ .action(browserAction(async (page, opts) => {
343
349
  const sel = opts.selector ? JSON.stringify(opts.selector) : 'null';
344
350
  const html = await page.evaluate(`(${sel} ? document.querySelector(${sel})?.outerHTML : document.documentElement.outerHTML)?.slice(0, 50000)`);
345
351
  console.log(html ?? '(empty)');
346
352
  }));
347
353
  get.command('attributes').argument('<index>', 'Element index').description('Element attributes')
348
- .action(operateAction(async (page, index) => {
354
+ .action(browserAction(async (page, index) => {
349
355
  const attrs = await page.evaluate(`JSON.stringify(Object.fromEntries([...document.querySelector('[data-opencli-ref="${index}"]')?.attributes].map(a=>[a.name,a.value])))`);
350
356
  console.log(attrs ?? '{}');
351
357
  }));
352
358
  // ── Interact ──
353
- operate.command('click').argument('<index>', 'Element index from state').description('Click element by index')
354
- .action(operateAction(async (page, index) => {
359
+ browser.command('click').argument('<index>', 'Element index from state').description('Click element by index')
360
+ .action(browserAction(async (page, index) => {
355
361
  await page.click(index);
356
362
  console.log(`Clicked element [${index}]`);
357
363
  }));
358
- operate.command('type').argument('<index>', 'Element index').argument('<text>', 'Text to type')
364
+ browser.command('type').argument('<index>', 'Element index').argument('<text>', 'Text to type')
359
365
  .description('Click element, then type text')
360
- .action(operateAction(async (page, index, text) => {
366
+ .action(browserAction(async (page, index, text) => {
361
367
  await page.click(index);
362
368
  await page.wait(0.3);
363
369
  await page.typeText(index, text);
@@ -380,9 +386,9 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
380
386
  console.log(`Typed "${text}" into element [${index}]`);
381
387
  }
382
388
  }));
383
- operate.command('select').argument('<index>', 'Element index of <select>').argument('<option>', 'Option text')
389
+ browser.command('select').argument('<index>', 'Element index of <select>').argument('<option>', 'Option text')
384
390
  .description('Select dropdown option')
385
- .action(operateAction(async (page, index, option) => {
391
+ .action(browserAction(async (page, index, option) => {
386
392
  const result = await page.evaluate(`
387
393
  (function() {
388
394
  var sel = document.querySelector('[data-opencli-ref="${index}"]');
@@ -404,19 +410,19 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
404
410
  console.log(`Selected "${result?.selected}" in element [${index}]`);
405
411
  }
406
412
  }));
407
- operate.command('keys').argument('<key>', 'Key to press (Enter, Escape, Tab, Control+a)')
413
+ browser.command('keys').argument('<key>', 'Key to press (Enter, Escape, Tab, Control+a)')
408
414
  .description('Press keyboard key')
409
- .action(operateAction(async (page, key) => {
415
+ .action(browserAction(async (page, key) => {
410
416
  await page.pressKey(key);
411
417
  console.log(`Pressed: ${key}`);
412
418
  }));
413
419
  // ── Wait commands ──
414
- operate.command('wait')
420
+ browser.command('wait')
415
421
  .argument('<type>', 'selector, text, or time')
416
422
  .argument('[value]', 'CSS selector, text string, or seconds')
417
423
  .option('--timeout <ms>', 'Timeout in milliseconds', '10000')
418
424
  .description('Wait for selector, text, or time (e.g. wait selector ".loaded", wait text "Success", wait time 3)')
419
- .action(operateAction(async (page, type, value, opts) => {
425
+ .action(browserAction(async (page, type, value, opts) => {
420
426
  const timeout = parseInt(opts.timeout, 10);
421
427
  if (type === 'time') {
422
428
  const seconds = parseFloat(value ?? '2');
@@ -447,8 +453,8 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
447
453
  }
448
454
  }));
449
455
  // ── Extract ──
450
- operate.command('eval').argument('<js>', 'JavaScript code').description('Execute JS in page context, return result')
451
- .action(operateAction(async (page, js) => {
456
+ browser.command('eval').argument('<js>', 'JavaScript code').description('Execute JS in page context, return result')
457
+ .action(browserAction(async (page, js) => {
452
458
  const result = await page.evaluate(js);
453
459
  if (typeof result === 'string')
454
460
  console.log(result);
@@ -456,11 +462,11 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
456
462
  console.log(JSON.stringify(result, null, 2));
457
463
  }));
458
464
  // ── Network (API discovery) ──
459
- operate.command('network')
465
+ browser.command('network')
460
466
  .option('--detail <index>', 'Show full response body of request at index')
461
467
  .option('--all', 'Show all requests including static resources')
462
468
  .description('Show captured network requests (auto-captured since last open)')
463
- .action(operateAction(async (page, opts) => {
469
+ .action(browserAction(async (page, opts) => {
464
470
  let items = [];
465
471
  if (page.readNetworkCapture) {
466
472
  const raw = await page.readNetworkCapture();
@@ -498,7 +504,7 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
498
504
  items = JSON.parse(requests);
499
505
  }
500
506
  catch {
501
- console.log('No network data captured. Run "operate open <url>" first.');
507
+ console.log('No network data captured. Run "browser open <url>" first.');
502
508
  return;
503
509
  }
504
510
  }
@@ -537,7 +543,7 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
537
543
  }
538
544
  }));
539
545
  // ── Init (adapter scaffolding) ──
540
- operate.command('init')
546
+ browser.command('init')
541
547
  .argument('<name>', 'Adapter name in site/command format (e.g. hn/top)')
542
548
  .description('Generate adapter scaffold in ~/.opencli/clis/')
543
549
  .action(async (name) => {
@@ -563,10 +569,10 @@ export function createProgram(BUILTIN_CLIS, USER_CLIS) {
563
569
  console.log(`Adapter already exists: ${filePath}`);
564
570
  return;
565
571
  }
566
- // Try to detect domain from last operate session
572
+ // Try to detect domain from the last browser session
567
573
  let domain = site;
568
574
  try {
569
- const page = await getOperatePage();
575
+ const page = await getBrowserPage();
570
576
  const url = await page.getCurrentUrl?.();
571
577
  if (url) {
572
578
  try {
@@ -600,7 +606,7 @@ cli({
600
606
  fs.mkdirSync(dir, { recursive: true });
601
607
  fs.writeFileSync(filePath, template, 'utf-8');
602
608
  console.log(`Created: ${filePath}`);
603
- console.log(`Edit the file to implement your adapter, then run: opencli operate verify ${name}`);
609
+ console.log(`Edit the file to implement your adapter, then run: opencli browser verify ${name}`);
604
610
  }
605
611
  catch (err) {
606
612
  console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
@@ -608,7 +614,7 @@ cli({
608
614
  }
609
615
  });
610
616
  // ── Verify (test adapter) ──
611
- operate.command('verify')
617
+ browser.command('verify')
612
618
  .argument('<name>', 'Adapter name in site/command format (e.g. hn/top)')
613
619
  .description('Execute an adapter and show results')
614
620
  .action(async (name) => {
@@ -630,7 +636,7 @@ cli({
630
636
  const filePath = path.join(os.homedir(), '.opencli', 'clis', site, `${command}.ts`);
631
637
  if (!fs.existsSync(filePath)) {
632
638
  console.error(`Adapter not found: ${filePath}`);
633
- console.error(`Run "opencli operate init ${name}" to create it.`);
639
+ console.error(`Run "opencli browser init ${name}" to create it.`);
634
640
  process.exitCode = EXIT_CODES.GENERIC_ERROR;
635
641
  return;
636
642
  }
@@ -641,7 +647,7 @@ cli({
641
647
  const hasLimitArg = /['"]limit['"]/.test(adapterSrc);
642
648
  const limitFlag = hasLimitArg ? ' --limit 3' : '';
643
649
  const limitArgs = hasLimitArg ? ['--limit', '3'] : [];
644
- const invocation = resolveOperateVerifyInvocation();
650
+ const invocation = resolveBrowserVerifyInvocation();
645
651
  try {
646
652
  const output = execFileSync(invocation.binary, [...invocation.args, site, command, ...limitArgs], {
647
653
  cwd: invocation.cwd,
@@ -657,10 +663,12 @@ cli({
657
663
  }
658
664
  catch (err) {
659
665
  console.log(` Executing: opencli ${site} ${command}${limitFlag}\n`);
660
- if (err.stdout)
661
- console.log(err.stdout);
662
- if (err.stderr)
663
- console.error(err.stderr.slice(0, 500));
666
+ // execFileSync attaches captured stdout/stderr on its thrown Error.
667
+ const execErr = err;
668
+ if (execErr.stdout)
669
+ console.log(String(execErr.stdout));
670
+ if (execErr.stderr)
671
+ console.error(String(execErr.stderr).slice(0, 500));
664
672
  console.log(`\n ✗ Adapter failed. Fix the code and try again.`);
665
673
  process.exitCode = EXIT_CODES.GENERIC_ERROR;
666
674
  }
@@ -671,8 +679,8 @@ cli({
671
679
  }
672
680
  });
673
681
  // ── Session ──
674
- operate.command('close').description('Close the automation window')
675
- .action(operateAction(async (page) => {
682
+ browser.command('close').description('Close the automation window')
683
+ .action(browserAction(async (page) => {
676
684
  await page.closeWindow?.();
677
685
  console.log('Automation window closed');
678
686
  }));
@@ -884,18 +892,10 @@ cli({
884
892
  });
885
893
  // ── Built-in: daemon ──────────────────────────────────────────────────────
886
894
  const daemonCmd = program.command('daemon').description('Manage the opencli daemon');
887
- daemonCmd
888
- .command('status')
889
- .description('Show daemon status')
890
- .action(async () => { await daemonStatus(); });
891
895
  daemonCmd
892
896
  .command('stop')
893
897
  .description('Stop the daemon')
894
898
  .action(async () => { await daemonStop(); });
895
- daemonCmd
896
- .command('restart')
897
- .description('Restart the daemon')
898
- .action(async () => { await daemonRestart(); });
899
899
  // ── External CLIs ─────────────────────────────────────────────────────────
900
900
  const externalClis = loadExternalClis();
901
901
  program
@@ -978,7 +978,7 @@ export function runCli(BUILTIN_CLIS, USER_CLIS) {
978
978
  createProgram(BUILTIN_CLIS, USER_CLIS).parse();
979
979
  }
980
980
  export { findPackageRoot };
981
- export function resolveOperateVerifyInvocation(opts = {}) {
981
+ export function resolveBrowserVerifyInvocation(opts = {}) {
982
982
  const platform = opts.platform ?? process.platform;
983
983
  const fileExists = opts.fileExists ?? fs.existsSync;
984
984
  const readFile = opts.readFile ?? ((filePath) => fs.readFileSync(filePath, 'utf-8'));