@jackwener/opencli 1.7.11 → 1.7.13

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 (1004) hide show
  1. package/README.md +8 -7
  2. package/README.zh-CN.md +11 -9
  3. package/cli-manifest.json +12952 -6208
  4. package/clis/1688/assets.js +1 -0
  5. package/clis/1688/download.js +1 -0
  6. package/clis/1688/item.js +1 -0
  7. package/clis/1688/search.js +2 -1
  8. package/clis/1688/store.js +1 -0
  9. package/clis/1point3acres/digest.js +35 -0
  10. package/clis/1point3acres/forum.js +51 -0
  11. package/clis/1point3acres/forums.js +44 -0
  12. package/clis/1point3acres/hot.js +35 -0
  13. package/clis/1point3acres/latest.js +35 -0
  14. package/clis/1point3acres/notifications.js +64 -0
  15. package/clis/1point3acres/search.js +71 -0
  16. package/clis/1point3acres/thread.js +117 -0
  17. package/clis/1point3acres/user.js +77 -0
  18. package/clis/1point3acres/utils.js +247 -0
  19. package/clis/36kr/article.js +1 -0
  20. package/clis/36kr/hot.js +1 -0
  21. package/clis/36kr/news.js +1 -0
  22. package/clis/36kr/search.js +1 -0
  23. package/clis/51job/company.js +1 -0
  24. package/clis/51job/detail.js +1 -0
  25. package/clis/51job/hot.js +1 -0
  26. package/clis/51job/search.js +1 -0
  27. package/clis/_shared/desktop-commands.js +4 -0
  28. package/clis/aibase/news.js +110 -0
  29. package/clis/aibase/news.test.js +59 -0
  30. package/clis/amazon/bestsellers.js +1 -0
  31. package/clis/amazon/discussion.js +1 -0
  32. package/clis/amazon/discussion.test.js +1 -28
  33. package/clis/amazon/movers-shakers.js +1 -0
  34. package/clis/amazon/new-releases.js +1 -0
  35. package/clis/amazon/offer.js +1 -0
  36. package/clis/amazon/product.js +1 -0
  37. package/clis/amazon/rankings.js +1 -0
  38. package/clis/amazon/search.js +1 -0
  39. package/clis/antigravity/dump.js +1 -0
  40. package/clis/antigravity/extract-code.js +1 -0
  41. package/clis/antigravity/model.js +1 -0
  42. package/clis/antigravity/new.js +1 -0
  43. package/clis/antigravity/read.js +1 -0
  44. package/clis/antigravity/send.js +1 -0
  45. package/clis/antigravity/status.js +1 -0
  46. package/clis/antigravity/watch.js +4 -2
  47. package/clis/apple-podcasts/episodes.js +1 -0
  48. package/clis/apple-podcasts/search.js +1 -0
  49. package/clis/apple-podcasts/top.js +1 -0
  50. package/clis/arxiv/arxiv.test.js +112 -0
  51. package/clis/arxiv/author.js +44 -0
  52. package/clis/arxiv/paper.js +4 -3
  53. package/clis/arxiv/recent.js +33 -0
  54. package/clis/arxiv/search.js +19 -7
  55. package/clis/arxiv/utils.js +68 -5
  56. package/clis/baidu-scholar/search.js +1 -1
  57. package/clis/band/bands.js +1 -0
  58. package/clis/band/mentions.js +1 -0
  59. package/clis/band/post.js +1 -0
  60. package/clis/band/posts.js +1 -0
  61. package/clis/barchart/flow.js +1 -0
  62. package/clis/barchart/greeks.js +1 -0
  63. package/clis/barchart/options.js +1 -0
  64. package/clis/barchart/quote.js +1 -0
  65. package/clis/bbc/news.js +1 -0
  66. package/clis/bbc/topic.js +57 -0
  67. package/clis/bbc/utils.js +79 -0
  68. package/clis/bilibili/comments.js +1 -0
  69. package/clis/bilibili/download.js +1 -0
  70. package/clis/bilibili/dynamic.js +1 -0
  71. package/clis/bilibili/favorite.js +1 -0
  72. package/clis/bilibili/feed.js +2 -0
  73. package/clis/bilibili/following.js +1 -0
  74. package/clis/bilibili/history.js +1 -0
  75. package/clis/bilibili/hot.js +6 -1
  76. package/clis/bilibili/hot.test.js +17 -0
  77. package/clis/bilibili/me.js +1 -1
  78. package/clis/bilibili/ranking.js +1 -0
  79. package/clis/bilibili/search.js +1 -1
  80. package/clis/bilibili/subtitle.js +1 -0
  81. package/clis/bilibili/user-videos.js +1 -0
  82. package/clis/bilibili/video.js +1 -0
  83. package/clis/binance/asks.js +1 -0
  84. package/clis/binance/depth.js +1 -0
  85. package/clis/binance/gainers.js +1 -0
  86. package/clis/binance/klines.js +1 -0
  87. package/clis/binance/losers.js +1 -0
  88. package/clis/binance/pairs.js +1 -0
  89. package/clis/binance/price.js +1 -0
  90. package/clis/binance/prices.js +1 -0
  91. package/clis/binance/ticker.js +1 -0
  92. package/clis/binance/top.js +1 -0
  93. package/clis/binance/trades.js +1 -0
  94. package/clis/bloomberg/businessweek.js +1 -0
  95. package/clis/bloomberg/economics.js +1 -0
  96. package/clis/bloomberg/feeds.js +1 -0
  97. package/clis/bloomberg/industries.js +1 -0
  98. package/clis/bloomberg/main.js +1 -0
  99. package/clis/bloomberg/markets.js +1 -0
  100. package/clis/bloomberg/news.js +1 -0
  101. package/clis/bloomberg/opinions.js +1 -0
  102. package/clis/bloomberg/politics.js +1 -0
  103. package/clis/bloomberg/tech.js +1 -0
  104. package/clis/bluesky/feeds.js +1 -0
  105. package/clis/bluesky/followers.js +1 -0
  106. package/clis/bluesky/following.js +1 -0
  107. package/clis/bluesky/profile.js +1 -0
  108. package/clis/bluesky/search.js +1 -0
  109. package/clis/bluesky/starter-packs.js +1 -0
  110. package/clis/bluesky/thread.js +1 -0
  111. package/clis/bluesky/trending.js +1 -0
  112. package/clis/bluesky/user.js +3 -1
  113. package/clis/boss/batchgreet.js +1 -0
  114. package/clis/boss/chatlist.js +1 -0
  115. package/clis/boss/chatmsg.js +1 -0
  116. package/clis/boss/detail.js +1 -0
  117. package/clis/boss/exchange.js +1 -0
  118. package/clis/boss/greet.js +1 -0
  119. package/clis/boss/invite.js +1 -0
  120. package/clis/boss/joblist.js +1 -0
  121. package/clis/boss/mark.js +1 -0
  122. package/clis/boss/recommend.js +1 -0
  123. package/clis/boss/resume.js +1 -0
  124. package/clis/boss/search.js +1 -0
  125. package/clis/boss/send.js +1 -0
  126. package/clis/boss/stats.js +1 -0
  127. package/clis/chaoxing/assignments.js +2 -1
  128. package/clis/chaoxing/exams.js +2 -1
  129. package/clis/chatgpt/ask.js +57 -0
  130. package/clis/chatgpt/commands.test.js +45 -0
  131. package/clis/chatgpt/detail.js +46 -0
  132. package/clis/chatgpt/history.js +39 -0
  133. package/clis/chatgpt/image.js +13 -11
  134. package/clis/chatgpt/image.test.js +23 -0
  135. package/clis/chatgpt/new.js +25 -0
  136. package/clis/chatgpt/read.js +43 -0
  137. package/clis/chatgpt/send.js +46 -0
  138. package/clis/chatgpt/status.js +29 -0
  139. package/clis/chatgpt/utils.js +294 -4
  140. package/clis/chatgpt/utils.test.js +13 -0
  141. package/clis/chatgpt-app/ask.js +7 -3
  142. package/clis/chatgpt-app/model.js +1 -0
  143. package/clis/chatgpt-app/new.js +1 -0
  144. package/clis/chatgpt-app/read.js +1 -0
  145. package/clis/chatgpt-app/send.js +1 -0
  146. package/clis/chatgpt-app/status.js +1 -0
  147. package/clis/chatwise/ask.js +17 -43
  148. package/clis/chatwise/composer.test.js +186 -0
  149. package/clis/chatwise/export.js +1 -0
  150. package/clis/chatwise/history.js +1 -0
  151. package/clis/chatwise/model.js +1 -0
  152. package/clis/chatwise/read.js +1 -0
  153. package/clis/chatwise/send.js +3 -24
  154. package/clis/chatwise/utils.js +143 -0
  155. package/clis/claude/ask.js +2 -1
  156. package/clis/claude/detail.js +2 -0
  157. package/clis/claude/history.js +2 -0
  158. package/clis/claude/new.js +2 -0
  159. package/clis/claude/read.js +2 -0
  160. package/clis/claude/send.js +2 -0
  161. package/clis/claude/status.js +2 -0
  162. package/clis/cnki/search.js +1 -0
  163. package/clis/codex/ask.js +16 -9
  164. package/clis/codex/export.js +1 -0
  165. package/clis/codex/extract-diff.js +1 -0
  166. package/clis/codex/history.js +17 -33
  167. package/clis/codex/model.js +1 -0
  168. package/clis/codex/projects.js +28 -0
  169. package/clis/codex/read.js +11 -4
  170. package/clis/codex/send.js +11 -3
  171. package/clis/codex/sidebar.js +356 -0
  172. package/clis/codex/sidebar.test.js +329 -0
  173. package/clis/coingecko/categories.js +75 -0
  174. package/clis/coingecko/coin.js +107 -0
  175. package/clis/coingecko/coingecko.test.js +109 -0
  176. package/clis/coingecko/derivatives.js +84 -0
  177. package/clis/coingecko/exchanges.js +74 -0
  178. package/clis/coingecko/global.js +71 -0
  179. package/clis/coingecko/top.js +64 -0
  180. package/clis/coingecko/trending.js +55 -0
  181. package/clis/coupang/add-to-cart.js +22 -13
  182. package/clis/coupang/coupang.test.js +159 -0
  183. package/clis/coupang/product.js +257 -0
  184. package/clis/coupang/search.js +39 -16
  185. package/clis/coupang/utils.js +55 -1
  186. package/clis/crates/crate.js +62 -0
  187. package/clis/crates/search.js +44 -0
  188. package/clis/crates/utils.js +72 -0
  189. package/clis/ctrip/ctrip.test.js +234 -0
  190. package/clis/ctrip/hotel-suggest.js +45 -0
  191. package/clis/ctrip/search.js +23 -68
  192. package/clis/ctrip/utils.js +175 -0
  193. package/clis/cursor/ask.js +7 -3
  194. package/clis/cursor/composer.js +1 -0
  195. package/clis/cursor/export.js +1 -0
  196. package/clis/cursor/extract-code.js +1 -0
  197. package/clis/cursor/history.js +1 -0
  198. package/clis/cursor/model.js +1 -0
  199. package/clis/cursor/read.js +1 -0
  200. package/clis/cursor/send.js +1 -0
  201. package/clis/dblp/author.js +133 -0
  202. package/clis/dblp/dblp.test.js +397 -0
  203. package/clis/dblp/paper.js +40 -0
  204. package/clis/dblp/search.js +45 -0
  205. package/clis/dblp/utils.js +290 -0
  206. package/clis/dblp/venue.js +64 -0
  207. package/clis/deepseek/ask.js +13 -7
  208. package/clis/deepseek/ask.test.js +13 -13
  209. package/clis/deepseek/detail.js +38 -0
  210. package/clis/deepseek/detail.test.js +81 -0
  211. package/clis/deepseek/history.js +2 -0
  212. package/clis/deepseek/new.js +2 -0
  213. package/clis/deepseek/read.js +2 -0
  214. package/clis/deepseek/send.js +140 -0
  215. package/clis/deepseek/send.test.js +107 -0
  216. package/clis/deepseek/status.js +2 -0
  217. package/clis/deepseek/utils.js +66 -0
  218. package/clis/deepseek/utils.test.js +107 -1
  219. package/clis/defillama/defillama.test.js +99 -0
  220. package/clis/defillama/protocol.js +84 -0
  221. package/clis/defillama/protocols.js +55 -0
  222. package/clis/defillama/utils.js +99 -0
  223. package/clis/devto/devto.test.js +236 -0
  224. package/clis/devto/latest.js +74 -0
  225. package/clis/devto/read.js +103 -0
  226. package/clis/devto/tag.js +5 -1
  227. package/clis/devto/top.js +5 -1
  228. package/clis/devto/user.js +5 -1
  229. package/clis/dianping/__fixtures__/search.html +168 -0
  230. package/clis/dianping/__fixtures__/shop.html +6 -0
  231. package/clis/dianping/dianping.test.js +424 -0
  232. package/clis/dianping/search.js +154 -0
  233. package/clis/dianping/shop.js +173 -0
  234. package/clis/dianping/utils.js +157 -0
  235. package/clis/dictionary/examples.js +1 -0
  236. package/clis/dictionary/search.js +1 -0
  237. package/clis/dictionary/synonyms.js +1 -0
  238. package/clis/discord-app/channels.js +1 -0
  239. package/clis/discord-app/delete.js +1 -0
  240. package/clis/discord-app/members.js +1 -0
  241. package/clis/discord-app/read.js +1 -0
  242. package/clis/discord-app/search.js +1 -0
  243. package/clis/discord-app/send.js +1 -0
  244. package/clis/discord-app/servers.js +1 -0
  245. package/clis/discord-app/status.js +1 -0
  246. package/clis/dockerhub/image.js +52 -0
  247. package/clis/dockerhub/search.js +47 -0
  248. package/clis/dockerhub/utils.js +100 -0
  249. package/clis/douban/book-hot.js +1 -0
  250. package/clis/douban/download.js +1 -0
  251. package/clis/douban/marks.js +1 -0
  252. package/clis/douban/movie-hot.js +2 -1
  253. package/clis/douban/movie-hot.test.js +14 -0
  254. package/clis/douban/photos.js +2 -1
  255. package/clis/douban/reviews.js +1 -0
  256. package/clis/douban/search.js +1 -0
  257. package/clis/douban/subject.js +1 -0
  258. package/clis/douban/top250.js +1 -0
  259. package/clis/douban/utils.js +11 -13
  260. package/clis/douban/utils.test.js +79 -0
  261. package/clis/doubao/ask.js +8 -3
  262. package/clis/doubao/detail.js +2 -0
  263. package/clis/doubao/history.js +2 -0
  264. package/clis/doubao/meeting-summary.js +2 -0
  265. package/clis/doubao/meeting-transcript.js +2 -0
  266. package/clis/doubao/new.js +2 -0
  267. package/clis/doubao/read.js +2 -0
  268. package/clis/doubao/send.js +2 -0
  269. package/clis/doubao/status.js +2 -0
  270. package/clis/doubao-app/ask.js +1 -0
  271. package/clis/doubao-app/dump.js +1 -0
  272. package/clis/doubao-app/new.js +1 -0
  273. package/clis/doubao-app/read.js +1 -0
  274. package/clis/doubao-app/screenshot.js +1 -0
  275. package/clis/doubao-app/send.js +1 -0
  276. package/clis/doubao-app/status.js +1 -0
  277. package/clis/douyin/activities.js +1 -0
  278. package/clis/douyin/collections.js +1 -0
  279. package/clis/douyin/delete.js +1 -0
  280. package/clis/douyin/draft.js +1 -0
  281. package/clis/douyin/draft.test.js +1 -30
  282. package/clis/douyin/drafts.js +1 -0
  283. package/clis/douyin/hashtag.js +1 -0
  284. package/clis/douyin/location.js +1 -0
  285. package/clis/douyin/profile.js +1 -0
  286. package/clis/douyin/publish.js +1 -0
  287. package/clis/douyin/stats.js +1 -0
  288. package/clis/douyin/update.js +1 -0
  289. package/clis/douyin/user-videos.js +1 -0
  290. package/clis/douyin/videos.js +1 -0
  291. package/clis/eastmoney/announcement.js +1 -0
  292. package/clis/eastmoney/convertible.js +1 -0
  293. package/clis/eastmoney/etf.js +1 -0
  294. package/clis/eastmoney/holders.js +1 -0
  295. package/clis/eastmoney/hot-rank.js +1 -0
  296. package/clis/eastmoney/index-board.js +1 -0
  297. package/clis/eastmoney/kline.js +1 -0
  298. package/clis/eastmoney/kuaixun.js +1 -0
  299. package/clis/eastmoney/longhu.js +1 -0
  300. package/clis/eastmoney/money-flow.js +1 -0
  301. package/clis/eastmoney/northbound.js +1 -0
  302. package/clis/eastmoney/quote.js +1 -0
  303. package/clis/eastmoney/rank.js +1 -0
  304. package/clis/eastmoney/sectors.js +1 -0
  305. package/clis/endoflife/endoflife.test.js +51 -0
  306. package/clis/endoflife/product.js +55 -0
  307. package/clis/endoflife/utils.js +89 -0
  308. package/clis/facebook/__fixtures__/notifications-page.html +13 -0
  309. package/clis/facebook/add-friend.js +1 -0
  310. package/clis/facebook/events.js +1 -0
  311. package/clis/facebook/feed.js +1 -0
  312. package/clis/facebook/friends.js +1 -0
  313. package/clis/facebook/groups.js +1 -0
  314. package/clis/facebook/join-group.js +1 -0
  315. package/clis/facebook/marketplace-inbox.js +1 -0
  316. package/clis/facebook/marketplace-listings.js +1 -0
  317. package/clis/facebook/memories.js +1 -0
  318. package/clis/facebook/notifications.js +327 -30
  319. package/clis/facebook/notifications.test.js +458 -0
  320. package/clis/facebook/profile.js +1 -0
  321. package/clis/facebook/search.js +1 -0
  322. package/clis/flathub/app.js +71 -0
  323. package/clis/flathub/flathub.test.js +90 -0
  324. package/clis/flathub/search.js +80 -0
  325. package/clis/flathub/utils.js +114 -0
  326. package/clis/gemini/ask.js +8 -3
  327. package/clis/gemini/ask.test.js +2 -2
  328. package/clis/gemini/deep-research-result.js +7 -2
  329. package/clis/gemini/deep-research-result.test.js +15 -14
  330. package/clis/gemini/deep-research.js +9 -4
  331. package/clis/gemini/deep-research.test.js +15 -18
  332. package/clis/gemini/image.js +8 -2
  333. package/clis/gemini/new.js +2 -0
  334. package/clis/gemini/utils.js +0 -4
  335. package/clis/gitee/search.js +1 -0
  336. package/clis/gitee/trending.js +1 -0
  337. package/clis/gitee/user.js +1 -0
  338. package/clis/google/news.js +1 -0
  339. package/clis/google/search.js +1 -0
  340. package/clis/google/suggest.js +1 -0
  341. package/clis/google/trends.js +1 -0
  342. package/clis/google-scholar/cite.js +1 -1
  343. package/clis/google-scholar/profile.js +1 -1
  344. package/clis/google-scholar/search.js +1 -1
  345. package/clis/goproxy/goproxy.test.js +103 -0
  346. package/clis/goproxy/module.js +47 -0
  347. package/clis/goproxy/utils.js +165 -0
  348. package/clis/goproxy/versions.js +59 -0
  349. package/clis/gov-law/recent.js +1 -1
  350. package/clis/gov-law/search.js +1 -1
  351. package/clis/gov-policy/__fixtures__/recent.html +16 -0
  352. package/clis/gov-policy/__fixtures__/search.html +41 -0
  353. package/clis/gov-policy/gov-policy.test.js +224 -0
  354. package/clis/gov-policy/recent.js +67 -24
  355. package/clis/gov-policy/search.js +66 -23
  356. package/clis/gov-policy/utils.js +54 -0
  357. package/clis/grok/ask.js +50 -265
  358. package/clis/grok/ask.test.js +21 -46
  359. package/clis/grok/detail.js +60 -0
  360. package/clis/grok/history.js +48 -0
  361. package/clis/grok/{image.ts → image.js} +57 -70
  362. package/clis/grok/image.test.ts +20 -0
  363. package/clis/grok/new.js +20 -0
  364. package/clis/grok/read.js +39 -0
  365. package/clis/grok/send.js +50 -0
  366. package/clis/grok/status.js +41 -0
  367. package/clis/grok/utils.js +326 -0
  368. package/clis/grok/utils.test.js +103 -0
  369. package/clis/hackernews/ask.js +3 -1
  370. package/clis/hackernews/best.js +3 -1
  371. package/clis/hackernews/hackernews.test.js +132 -0
  372. package/clis/hackernews/jobs.js +3 -1
  373. package/clis/hackernews/new.js +3 -1
  374. package/clis/hackernews/read.js +188 -0
  375. package/clis/hackernews/search.js +3 -1
  376. package/clis/hackernews/show.js +3 -1
  377. package/clis/hackernews/top.js +3 -1
  378. package/clis/hackernews/user.js +1 -0
  379. package/clis/hf/datasets.js +88 -0
  380. package/clis/hf/hf.test.js +16 -0
  381. package/clis/hf/models.js +91 -0
  382. package/clis/hf/paper.js +79 -0
  383. package/clis/hf/spaces.js +101 -0
  384. package/clis/hf/top.js +2 -0
  385. package/clis/homebrew/cask.js +39 -0
  386. package/clis/homebrew/formula.js +41 -0
  387. package/clis/homebrew/popular.js +54 -0
  388. package/clis/homebrew/utils.js +100 -0
  389. package/clis/hupu/__fixtures__/hot-home.html +64 -0
  390. package/clis/hupu/detail.js +1 -1
  391. package/clis/hupu/hot.js +157 -34
  392. package/clis/hupu/hot.test.js +224 -0
  393. package/clis/hupu/like.js +1 -0
  394. package/clis/hupu/mentions.js +2 -1
  395. package/clis/hupu/reply.js +1 -0
  396. package/clis/hupu/search.js +3 -2
  397. package/clis/hupu/unlike.js +1 -0
  398. package/clis/imdb/person.js +1 -0
  399. package/clis/imdb/reviews.js +1 -0
  400. package/clis/imdb/search.js +1 -0
  401. package/clis/imdb/title.js +1 -0
  402. package/clis/imdb/top.js +1 -0
  403. package/clis/imdb/trending.js +1 -0
  404. package/clis/indeed/indeed.test.js +375 -0
  405. package/clis/indeed/job.js +86 -0
  406. package/clis/indeed/search.js +110 -0
  407. package/clis/indeed/utils.js +152 -0
  408. package/clis/instagram/collection-create.js +1 -0
  409. package/clis/instagram/collection-delete.js +1 -0
  410. package/clis/instagram/comment.js +1 -0
  411. package/clis/instagram/download.js +1 -0
  412. package/clis/instagram/explore.js +1 -0
  413. package/clis/instagram/follow.js +1 -0
  414. package/clis/instagram/followers.js +1 -0
  415. package/clis/instagram/following.js +1 -0
  416. package/clis/instagram/like.js +1 -0
  417. package/clis/instagram/note.js +2 -1
  418. package/clis/instagram/note.test.js +1 -29
  419. package/clis/instagram/post.js +2 -1
  420. package/clis/instagram/post.test.js +1 -1
  421. package/clis/instagram/profile.js +1 -0
  422. package/clis/instagram/reel.js +2 -1
  423. package/clis/instagram/save.js +1 -0
  424. package/clis/instagram/saved.js +1 -0
  425. package/clis/instagram/search.js +1 -0
  426. package/clis/instagram/story.js +2 -1
  427. package/clis/instagram/story.test.js +1 -34
  428. package/clis/instagram/unfollow.js +1 -0
  429. package/clis/instagram/unlike.js +1 -0
  430. package/clis/instagram/unsave.js +1 -0
  431. package/clis/instagram/user.js +1 -0
  432. package/clis/jd/add-cart.js +1 -0
  433. package/clis/jd/cart.js +1 -0
  434. package/clis/jd/commands.test.js +1 -24
  435. package/clis/jd/detail.js +1 -0
  436. package/clis/jd/item.js +1 -0
  437. package/clis/jd/reviews.js +1 -0
  438. package/clis/jd/search.js +1 -0
  439. package/clis/jianyu/detail.js +1 -0
  440. package/clis/jianyu/search.js +1 -0
  441. package/clis/jike/comment.js +1 -0
  442. package/clis/jike/create.js +1 -0
  443. package/clis/jike/feed.js +3 -1
  444. package/clis/jike/like.js +1 -0
  445. package/clis/jike/notifications.js +1 -0
  446. package/clis/jike/post.js +1 -0
  447. package/clis/jike/repost.js +1 -0
  448. package/clis/jike/search.js +3 -1
  449. package/clis/jike/topic.js +1 -0
  450. package/clis/jike/user.js +3 -1
  451. package/clis/jimeng/generate.js +1 -0
  452. package/clis/jimeng/history.js +1 -0
  453. package/clis/jimeng/new.js +1 -0
  454. package/clis/jimeng/workspaces.js +1 -0
  455. package/clis/ke/chengjiao.js +1 -0
  456. package/clis/ke/ershoufang.js +1 -0
  457. package/clis/ke/xiaoqu.js +1 -0
  458. package/clis/ke/zufang.js +1 -0
  459. package/clis/lesswrong/comments.js +1 -0
  460. package/clis/lesswrong/curated.js +1 -0
  461. package/clis/lesswrong/frontpage.js +1 -0
  462. package/clis/lesswrong/new.js +1 -0
  463. package/clis/lesswrong/read.js +1 -0
  464. package/clis/lesswrong/sequences.js +1 -0
  465. package/clis/lesswrong/shortform.js +1 -0
  466. package/clis/lesswrong/tag.js +1 -0
  467. package/clis/lesswrong/tags.js +1 -0
  468. package/clis/lesswrong/top-month.js +1 -0
  469. package/clis/lesswrong/top-week.js +1 -0
  470. package/clis/lesswrong/top-year.js +1 -0
  471. package/clis/lesswrong/top.js +1 -0
  472. package/clis/lesswrong/user-posts.js +1 -0
  473. package/clis/lesswrong/user.js +1 -0
  474. package/clis/lichess/lichess.test.js +85 -0
  475. package/clis/lichess/top.js +46 -0
  476. package/clis/lichess/user.js +91 -0
  477. package/clis/lichess/utils.js +97 -0
  478. package/clis/linkedin/search.js +108 -10
  479. package/clis/linkedin/search.test.js +222 -0
  480. package/clis/linkedin/timeline.js +1 -0
  481. package/clis/linux-do/categories.js +1 -0
  482. package/clis/linux-do/feed.js +3 -5
  483. package/clis/linux-do/feed.test.js +35 -0
  484. package/clis/linux-do/search.js +1 -0
  485. package/clis/linux-do/tags.js +2 -1
  486. package/clis/linux-do/topic-content.js +1 -0
  487. package/clis/linux-do/topic.js +1 -0
  488. package/clis/linux-do/user-posts.js +1 -0
  489. package/clis/linux-do/user-topics.js +1 -0
  490. package/clis/lobsters/active.js +4 -1
  491. package/clis/lobsters/domain.js +92 -0
  492. package/clis/lobsters/hot.js +4 -1
  493. package/clis/lobsters/lobsters.test.js +169 -0
  494. package/clis/lobsters/newest.js +4 -1
  495. package/clis/lobsters/read.js +196 -0
  496. package/clis/lobsters/tag.js +4 -1
  497. package/clis/maimai/search-talents.js +1 -0
  498. package/clis/maven/artifact.js +49 -0
  499. package/clis/maven/search.js +51 -0
  500. package/clis/maven/utils.js +110 -0
  501. package/clis/mdn/search.js +97 -0
  502. package/clis/medium/feed.js +1 -0
  503. package/clis/medium/search.js +1 -0
  504. package/clis/medium/tag.js +135 -0
  505. package/clis/medium/user.js +1 -0
  506. package/clis/mubu/doc.js +1 -0
  507. package/clis/mubu/docs.js +1 -0
  508. package/clis/mubu/notes.js +1 -0
  509. package/clis/mubu/recent.js +1 -0
  510. package/clis/mubu/search.js +1 -0
  511. package/clis/notebooklm/current.js +1 -0
  512. package/clis/notebooklm/get.js +1 -0
  513. package/clis/notebooklm/history.js +1 -0
  514. package/clis/notebooklm/list.js +1 -0
  515. package/clis/notebooklm/note-list.js +1 -0
  516. package/clis/notebooklm/notes-get.js +1 -0
  517. package/clis/notebooklm/open.js +1 -0
  518. package/clis/notebooklm/source-fulltext.js +1 -0
  519. package/clis/notebooklm/source-get.js +1 -0
  520. package/clis/notebooklm/source-guide.js +1 -0
  521. package/clis/notebooklm/source-list.js +1 -0
  522. package/clis/notebooklm/status.js +1 -0
  523. package/clis/notebooklm/summary.js +1 -0
  524. package/clis/notion/export.js +1 -0
  525. package/clis/notion/favorites.js +1 -0
  526. package/clis/notion/new.js +1 -0
  527. package/clis/notion/read.js +1 -0
  528. package/clis/notion/search.js +1 -0
  529. package/clis/notion/sidebar.js +1 -0
  530. package/clis/notion/status.js +1 -0
  531. package/clis/notion/write.js +1 -0
  532. package/clis/nowcoder/companies.js +1 -0
  533. package/clis/nowcoder/creators.js +1 -0
  534. package/clis/nowcoder/detail.js +1 -0
  535. package/clis/nowcoder/experience.js +1 -0
  536. package/clis/nowcoder/hot.js +1 -0
  537. package/clis/nowcoder/jobs.js +1 -0
  538. package/clis/nowcoder/notifications.js +1 -0
  539. package/clis/nowcoder/papers.js +1 -0
  540. package/clis/nowcoder/practice.js +1 -0
  541. package/clis/nowcoder/recommend.js +1 -0
  542. package/clis/nowcoder/referral.js +1 -0
  543. package/clis/nowcoder/salary.js +1 -0
  544. package/clis/nowcoder/search.js +1 -0
  545. package/clis/nowcoder/suggest.js +1 -0
  546. package/clis/nowcoder/topics.js +1 -0
  547. package/clis/nowcoder/trending.js +1 -0
  548. package/clis/npm/downloads.js +59 -0
  549. package/clis/npm/package.js +70 -0
  550. package/clis/npm/search.js +49 -0
  551. package/clis/npm/utils.js +76 -0
  552. package/clis/nuget/nuget.test.js +111 -0
  553. package/clis/nuget/package.js +101 -0
  554. package/clis/nuget/search.js +69 -0
  555. package/clis/nuget/utils.js +87 -0
  556. package/clis/nvd/cve.js +121 -0
  557. package/clis/oeis/oeis.test.js +88 -0
  558. package/clis/oeis/search.js +63 -0
  559. package/clis/oeis/sequence.js +71 -0
  560. package/clis/oeis/utils.js +88 -0
  561. package/clis/ones/login.js +1 -0
  562. package/clis/ones/logout.js +1 -0
  563. package/clis/ones/me.js +1 -0
  564. package/clis/ones/my-tasks.js +1 -0
  565. package/clis/ones/task.js +1 -0
  566. package/clis/ones/tasks.js +1 -0
  567. package/clis/ones/token-info.js +1 -0
  568. package/clis/ones/worklog.js +1 -0
  569. package/clis/openalex/search.js +69 -0
  570. package/clis/openalex/utils.js +160 -0
  571. package/clis/openalex/work.js +65 -0
  572. package/clis/openfda/drug-label.js +74 -0
  573. package/clis/openfda/food-recall.js +65 -0
  574. package/clis/openfda/openfda.test.js +114 -0
  575. package/clis/openfda/utils.js +67 -0
  576. package/clis/openreview/openreview.test.js +345 -0
  577. package/clis/openreview/paper.js +43 -0
  578. package/clis/openreview/reviews.js +131 -0
  579. package/clis/openreview/search.js +46 -0
  580. package/clis/openreview/utils.js +158 -0
  581. package/clis/openreview/venue.js +63 -0
  582. package/clis/osv/osv.test.js +97 -0
  583. package/clis/osv/query.js +72 -0
  584. package/clis/osv/utils.js +169 -0
  585. package/clis/osv/vulnerability.js +54 -0
  586. package/clis/packagist/package.js +49 -0
  587. package/clis/packagist/search.js +43 -0
  588. package/clis/packagist/utils.js +113 -0
  589. package/clis/paperreview/feedback.js +2 -1
  590. package/clis/paperreview/review.js +2 -1
  591. package/clis/paperreview/submit.js +2 -1
  592. package/clis/pixiv/detail.js +1 -0
  593. package/clis/pixiv/download.js +1 -0
  594. package/clis/pixiv/download.test.js +1 -1
  595. package/clis/pixiv/illusts.js +2 -1
  596. package/clis/pixiv/illusts.test.js +1 -1
  597. package/clis/pixiv/ranking.js +2 -1
  598. package/clis/pixiv/search.js +2 -1
  599. package/clis/pixiv/search.test.js +1 -1
  600. package/clis/pixiv/user.js +2 -0
  601. package/clis/powerchina/search.js +1 -0
  602. package/clis/producthunt/browse.js +1 -0
  603. package/clis/producthunt/hot.js +1 -0
  604. package/clis/producthunt/posts.js +1 -0
  605. package/clis/producthunt/today.js +1 -0
  606. package/clis/pubmed/article.js +50 -0
  607. package/clis/pubmed/author.js +64 -0
  608. package/clis/pubmed/citations.js +36 -0
  609. package/clis/pubmed/pubmed.test.js +276 -0
  610. package/clis/pubmed/related.js +45 -0
  611. package/clis/pubmed/search.js +75 -0
  612. package/clis/pubmed/utils.js +309 -0
  613. package/clis/pypi/downloads.js +66 -0
  614. package/clis/pypi/package.js +79 -0
  615. package/clis/pypi/utils.js +55 -0
  616. package/clis/quark/ls.js +1 -0
  617. package/clis/quark/mkdir.js +1 -0
  618. package/clis/quark/mv.js +2 -1
  619. package/clis/quark/rename.js +1 -0
  620. package/clis/quark/rm.js +1 -0
  621. package/clis/quark/save.js +2 -1
  622. package/clis/quark/share-tree.js +1 -0
  623. package/clis/qwen/ask.js +85 -0
  624. package/clis/qwen/detail.js +62 -0
  625. package/clis/qwen/history.js +61 -0
  626. package/clis/qwen/image.js +179 -0
  627. package/clis/qwen/new.js +23 -0
  628. package/clis/qwen/read.js +41 -0
  629. package/clis/qwen/send.js +55 -0
  630. package/clis/qwen/status.js +37 -0
  631. package/clis/qwen/utils.js +409 -0
  632. package/clis/qwen/utils.test.js +45 -0
  633. package/clis/reddit/comment.js +1 -0
  634. package/clis/reddit/frontpage.js +1 -0
  635. package/clis/reddit/hot.js +6 -1
  636. package/clis/reddit/hot.test.js +18 -0
  637. package/clis/reddit/popular.js +1 -0
  638. package/clis/reddit/read.js +1 -0
  639. package/clis/reddit/save.js +1 -0
  640. package/clis/reddit/saved.js +1 -0
  641. package/clis/reddit/search.js +1 -0
  642. package/clis/reddit/subreddit.js +1 -0
  643. package/clis/reddit/subscribe.js +1 -0
  644. package/clis/reddit/upvote.js +1 -0
  645. package/clis/reddit/upvoted.js +1 -0
  646. package/clis/reddit/user-comments.js +1 -0
  647. package/clis/reddit/user-posts.js +1 -0
  648. package/clis/reddit/user.js +1 -0
  649. package/clis/rest-countries/country.js +65 -0
  650. package/clis/rest-countries/region.js +64 -0
  651. package/clis/rest-countries/rest-countries.test.js +83 -0
  652. package/clis/rest-countries/utils.js +126 -0
  653. package/clis/reuters/article-detail.js +53 -0
  654. package/clis/reuters/reuters.test.js +299 -0
  655. package/clis/reuters/search.js +46 -34
  656. package/clis/reuters/utils.js +159 -0
  657. package/clis/rfc/rfc.js +52 -0
  658. package/clis/rfc/rfc.test.js +74 -0
  659. package/clis/rfc/utils.js +72 -0
  660. package/clis/rubygems/gem.js +42 -0
  661. package/clis/rubygems/search.js +47 -0
  662. package/clis/rubygems/utils.js +86 -0
  663. package/clis/sinablog/article.js +1 -0
  664. package/clis/sinablog/hot.js +1 -0
  665. package/clis/sinablog/search.js +1 -0
  666. package/clis/sinablog/user.js +1 -0
  667. package/clis/sinafinance/news.js +1 -0
  668. package/clis/sinafinance/rolling-news.js +1 -0
  669. package/clis/sinafinance/stock-rank.js +1 -0
  670. package/clis/sinafinance/stock.js +1 -0
  671. package/clis/smzdm/search.js +1 -0
  672. package/clis/spotify/spotify.js +11 -0
  673. package/clis/stackoverflow/bounties.js +11 -3
  674. package/clis/stackoverflow/hot.js +10 -2
  675. package/clis/stackoverflow/read.js +314 -0
  676. package/clis/stackoverflow/related.js +66 -0
  677. package/clis/stackoverflow/search.js +10 -2
  678. package/clis/stackoverflow/stackoverflow.test.js +404 -0
  679. package/clis/stackoverflow/tag.js +60 -0
  680. package/clis/stackoverflow/unanswered.js +9 -2
  681. package/clis/stackoverflow/user.js +50 -0
  682. package/clis/stackoverflow/utils.js +118 -0
  683. package/clis/steam/app.js +67 -0
  684. package/clis/steam/search.js +58 -0
  685. package/clis/steam/steam.test.js +46 -0
  686. package/clis/steam/top-sellers.js +1 -0
  687. package/clis/steam/utils.js +107 -0
  688. package/clis/substack/feed.js +1 -0
  689. package/clis/substack/publication.js +1 -0
  690. package/clis/substack/search.js +1 -0
  691. package/clis/taobao/add-cart.js +1 -0
  692. package/clis/taobao/cart.js +1 -0
  693. package/clis/taobao/commands.test.js +1 -24
  694. package/clis/taobao/detail.js +1 -0
  695. package/clis/taobao/reviews.js +1 -0
  696. package/clis/taobao/search.js +1 -0
  697. package/clis/tdx/hot-rank.js +1 -0
  698. package/clis/test-utils.js +61 -0
  699. package/clis/ths/hot-rank.js +1 -0
  700. package/clis/tieba/hot.js +2 -2
  701. package/clis/tieba/posts.js +1 -0
  702. package/clis/tieba/read.js +1 -0
  703. package/clis/tieba/search.js +2 -1
  704. package/clis/tiktok/comment.js +128 -40
  705. package/clis/tiktok/creator-videos.js +270 -0
  706. package/clis/tiktok/creator-videos.test.js +113 -0
  707. package/clis/tiktok/explore.js +138 -29
  708. package/clis/tiktok/follow.js +116 -33
  709. package/clis/tiktok/following.js +157 -35
  710. package/clis/tiktok/friends.js +140 -37
  711. package/clis/tiktok/like.js +1 -0
  712. package/clis/tiktok/live.js +138 -41
  713. package/clis/tiktok/notifications.js +142 -38
  714. package/clis/tiktok/profile.js +1 -0
  715. package/clis/tiktok/refactor.test.js +389 -0
  716. package/clis/tiktok/save.js +1 -0
  717. package/clis/tiktok/search.js +1 -0
  718. package/clis/tiktok/unfollow.js +125 -38
  719. package/clis/tiktok/unlike.js +1 -0
  720. package/clis/tiktok/unsave.js +1 -0
  721. package/clis/tiktok/user.js +204 -29
  722. package/clis/tiktok/utils.js +505 -0
  723. package/clis/tiktok/write-refactor.test.js +370 -0
  724. package/clis/toutiao/articles.js +37 -62
  725. package/clis/toutiao/hot.js +63 -0
  726. package/clis/toutiao/toutiao.test.js +378 -0
  727. package/clis/toutiao/utils.js +161 -0
  728. package/clis/tvmaze/search.js +61 -0
  729. package/clis/tvmaze/show.js +60 -0
  730. package/clis/tvmaze/tvmaze.test.js +93 -0
  731. package/clis/tvmaze/utils.js +110 -0
  732. package/clis/twitter/accept.js +2 -1
  733. package/clis/twitter/article.js +1 -0
  734. package/clis/twitter/block.js +1 -0
  735. package/clis/twitter/bookmark.js +1 -0
  736. package/clis/twitter/bookmarks.js +2 -1
  737. package/clis/twitter/delete.js +1 -0
  738. package/clis/twitter/download.js +1 -0
  739. package/clis/twitter/follow.js +1 -0
  740. package/clis/twitter/followers.js +135 -69
  741. package/clis/twitter/following.js +1 -0
  742. package/clis/twitter/hide-reply.js +1 -0
  743. package/clis/twitter/like.js +1 -0
  744. package/clis/twitter/likes.js +2 -1
  745. package/clis/twitter/list-add.js +1 -0
  746. package/clis/twitter/list-remove.js +1 -0
  747. package/clis/twitter/list-tweets.js +1 -0
  748. package/clis/twitter/lists.js +1 -0
  749. package/clis/twitter/notifications.js +1 -0
  750. package/clis/twitter/post.js +1 -0
  751. package/clis/twitter/profile.js +1 -0
  752. package/clis/twitter/reply-dm.js +2 -1
  753. package/clis/twitter/reply.js +1 -0
  754. package/clis/twitter/reply.test.js +1 -29
  755. package/clis/twitter/search.js +1 -0
  756. package/clis/twitter/thread.js +1 -0
  757. package/clis/twitter/timeline.js +1 -0
  758. package/clis/twitter/trending.js +11 -12
  759. package/clis/twitter/trending.test.js +15 -0
  760. package/clis/twitter/tweets.js +2 -1
  761. package/clis/twitter/tweets.test.js +2 -2
  762. package/clis/twitter/unblock.js +1 -0
  763. package/clis/twitter/unbookmark.js +1 -0
  764. package/clis/twitter/unfollow.js +1 -0
  765. package/clis/uisdc/news.js +105 -0
  766. package/clis/uisdc/news.test.js +66 -0
  767. package/clis/uiverse/code.js +1 -0
  768. package/clis/uiverse/preview.js +1 -0
  769. package/clis/v2ex/daily.js +1 -0
  770. package/clis/v2ex/hot.js +1 -0
  771. package/clis/v2ex/latest.js +1 -0
  772. package/clis/v2ex/me.js +1 -0
  773. package/clis/v2ex/member.js +1 -0
  774. package/clis/v2ex/node.js +1 -0
  775. package/clis/v2ex/nodes.js +1 -0
  776. package/clis/v2ex/notifications.js +1 -0
  777. package/clis/v2ex/replies.js +1 -0
  778. package/clis/v2ex/topic.js +1 -0
  779. package/clis/v2ex/user.js +1 -0
  780. package/clis/wanfang/search.js +1 -1
  781. package/clis/web/read.js +48 -17
  782. package/clis/web/read.test.js +101 -1
  783. package/clis/weibo/comments.js +1 -0
  784. package/clis/weibo/favorites.js +1 -0
  785. package/clis/weibo/feed.js +3 -1
  786. package/clis/weibo/hot.js +1 -0
  787. package/clis/weibo/me.js +1 -0
  788. package/clis/weibo/post.js +1 -0
  789. package/clis/weibo/publish.js +1 -0
  790. package/clis/weibo/search.js +8 -2
  791. package/clis/weibo/user.js +1 -0
  792. package/clis/weixin/create-draft.js +2 -1
  793. package/clis/weixin/download.js +1 -0
  794. package/clis/weixin/drafts.js +2 -1
  795. package/clis/weixin/drafts.test.js +5 -1
  796. package/clis/weixin/search.js +157 -0
  797. package/clis/weixin/search.test.js +227 -0
  798. package/clis/weread/ai-outline.js +1 -0
  799. package/clis/weread/book.js +1 -0
  800. package/clis/weread/highlights.js +1 -0
  801. package/clis/weread/notebooks.js +1 -0
  802. package/clis/weread/notes.js +1 -0
  803. package/clis/weread/ranking.js +1 -0
  804. package/clis/weread/search.js +1 -0
  805. package/clis/weread/shelf.js +1 -0
  806. package/clis/wikidata/entity.js +60 -0
  807. package/clis/wikidata/search.js +50 -0
  808. package/clis/wikidata/utils.js +117 -0
  809. package/clis/wikidata/wikidata.test.js +83 -0
  810. package/clis/wikipedia/page.js +95 -0
  811. package/clis/wikipedia/random.js +1 -0
  812. package/clis/wikipedia/search.js +1 -0
  813. package/clis/wikipedia/summary.js +1 -0
  814. package/clis/wikipedia/trending.js +1 -0
  815. package/clis/wttr/current.js +63 -0
  816. package/clis/wttr/forecast.js +71 -0
  817. package/clis/wttr/utils.js +50 -0
  818. package/clis/wttr/wttr.test.js +84 -0
  819. package/clis/xianyu/chat.js +17 -4
  820. package/clis/xianyu/chat.test.js +64 -0
  821. package/clis/xianyu/item.js +1 -0
  822. package/clis/xianyu/publish.js +485 -0
  823. package/clis/xianyu/publish.test.js +220 -0
  824. package/clis/xianyu/search.js +1 -0
  825. package/clis/xiaoe/catalog.js +105 -39
  826. package/clis/xiaoe/content.js +165 -29
  827. package/clis/xiaoe/courses.js +86 -28
  828. package/clis/xiaoe/detail.js +1 -0
  829. package/clis/xiaoe/play-url.js +1 -0
  830. package/clis/xiaoe/xiaoe.test.js +486 -0
  831. package/clis/xiaohongshu/comments.js +1 -0
  832. package/clis/xiaohongshu/creator-note-detail.js +1 -0
  833. package/clis/xiaohongshu/creator-notes-summary.js +2 -1
  834. package/clis/xiaohongshu/creator-notes.js +1 -0
  835. package/clis/xiaohongshu/creator-profile.js +1 -0
  836. package/clis/xiaohongshu/creator-stats.js +1 -0
  837. package/clis/xiaohongshu/download.js +1 -0
  838. package/clis/xiaohongshu/feed.js +2 -1
  839. package/clis/xiaohongshu/note.js +1 -0
  840. package/clis/xiaohongshu/notifications.js +1 -0
  841. package/clis/xiaohongshu/publish.js +17 -3
  842. package/clis/xiaohongshu/publish.test.js +46 -1
  843. package/clis/xiaohongshu/search.js +1 -0
  844. package/clis/xiaohongshu/user.js +1 -0
  845. package/clis/xiaoyuzhou/download.js +1 -0
  846. package/clis/xiaoyuzhou/episode.js +1 -0
  847. package/clis/xiaoyuzhou/podcast-episodes.js +1 -0
  848. package/clis/xiaoyuzhou/podcast.js +1 -0
  849. package/clis/xiaoyuzhou/transcript.js +1 -0
  850. package/clis/xueqiu/comments.js +1 -0
  851. package/clis/xueqiu/earnings-date.js +1 -0
  852. package/clis/xueqiu/feed.js +1 -0
  853. package/clis/xueqiu/fund-holdings.js +1 -0
  854. package/clis/xueqiu/fund-snapshot.js +1 -0
  855. package/clis/xueqiu/groups.js +1 -0
  856. package/clis/xueqiu/hot-stock.js +1 -0
  857. package/clis/xueqiu/hot.js +1 -0
  858. package/clis/xueqiu/kline.js +1 -0
  859. package/clis/xueqiu/search.js +1 -0
  860. package/clis/xueqiu/stock.js +1 -0
  861. package/clis/xueqiu/watchlist.js +1 -0
  862. package/clis/yahoo-finance/quote.js +1 -0
  863. package/clis/yollomi/background.js +1 -0
  864. package/clis/yollomi/edit.js +1 -0
  865. package/clis/yollomi/face-swap.js +1 -0
  866. package/clis/yollomi/generate.js +1 -0
  867. package/clis/yollomi/models.js +1 -0
  868. package/clis/yollomi/object-remover.js +1 -0
  869. package/clis/yollomi/remove-bg.js +1 -0
  870. package/clis/yollomi/restore.js +1 -0
  871. package/clis/yollomi/try-on.js +1 -0
  872. package/clis/yollomi/upload.js +1 -0
  873. package/clis/yollomi/upscale.js +1 -0
  874. package/clis/yollomi/video.js +1 -0
  875. package/clis/youtube/channel.js +1 -0
  876. package/clis/youtube/comments.js +1 -0
  877. package/clis/youtube/feed.js +8 -7
  878. package/clis/youtube/feed.test.js +131 -0
  879. package/clis/youtube/history.js +1 -0
  880. package/clis/youtube/like.js +1 -0
  881. package/clis/youtube/playlist.js +1 -0
  882. package/clis/youtube/search.js +1 -0
  883. package/clis/youtube/subscribe.js +1 -0
  884. package/clis/youtube/subscriptions.js +1 -0
  885. package/clis/youtube/transcript.js +14 -19
  886. package/clis/youtube/transcript.test.js +17 -0
  887. package/clis/youtube/unlike.js +1 -0
  888. package/clis/youtube/unsubscribe.js +1 -0
  889. package/clis/youtube/video.js +1 -0
  890. package/clis/youtube/watch-later.js +1 -0
  891. package/clis/yuanbao/ask.js +18 -66
  892. package/clis/yuanbao/ask.test.js +5 -5
  893. package/clis/yuanbao/detail.js +65 -0
  894. package/clis/yuanbao/history.js +51 -0
  895. package/clis/yuanbao/new.js +2 -0
  896. package/clis/yuanbao/read.js +38 -0
  897. package/clis/yuanbao/send.js +57 -0
  898. package/clis/yuanbao/shared.js +297 -5
  899. package/clis/yuanbao/shared.test.js +80 -0
  900. package/clis/yuanbao/status.js +44 -0
  901. package/clis/zhihu/answer.js +1 -0
  902. package/clis/zhihu/collection.js +1 -0
  903. package/clis/zhihu/collections.js +1 -0
  904. package/clis/zhihu/comment.js +1 -0
  905. package/clis/zhihu/download.js +1 -0
  906. package/clis/zhihu/favorite.js +1 -0
  907. package/clis/zhihu/follow.js +1 -0
  908. package/clis/zhihu/hot.js +1 -0
  909. package/clis/zhihu/like.js +1 -0
  910. package/clis/zhihu/question.js +1 -0
  911. package/clis/zhihu/search.js +1 -0
  912. package/clis/zlibrary/commands.test.js +1 -11
  913. package/clis/zlibrary/info.js +1 -0
  914. package/clis/zlibrary/search.js +1 -0
  915. package/clis/zsxq/dynamics.js +1 -0
  916. package/clis/zsxq/groups.js +1 -0
  917. package/clis/zsxq/search.js +1 -0
  918. package/clis/zsxq/topic.js +1 -0
  919. package/clis/zsxq/topics.js +1 -0
  920. package/dist/src/adapter-source.test.js +1 -1
  921. package/dist/src/browser/analyze.test.js +2 -0
  922. package/dist/src/browser/base-page.d.ts +18 -0
  923. package/dist/src/browser/base-page.js +116 -4
  924. package/dist/src/browser/base-page.test.js +108 -0
  925. package/dist/src/browser/cdp.d.ts +1 -0
  926. package/dist/src/browser/cdp.js +57 -9
  927. package/dist/src/browser/cdp.test.js +3 -0
  928. package/dist/src/browser/daemon-client.d.ts +4 -0
  929. package/dist/src/browser/errors.js +1 -1
  930. package/dist/src/browser/page.d.ts +2 -1
  931. package/dist/src/browser/page.js +9 -1
  932. package/dist/src/browser/page.test.js +46 -0
  933. package/dist/src/browser/target-errors.d.ts +2 -1
  934. package/dist/src/browser/target-errors.js +1 -0
  935. package/dist/src/browser/target-resolver.d.ts +35 -3
  936. package/dist/src/browser/target-resolver.js +59 -10
  937. package/dist/src/browser/verify-fixture.d.ts +6 -1
  938. package/dist/src/browser/verify-fixture.js +87 -0
  939. package/dist/src/browser/verify-fixture.test.js +44 -1
  940. package/dist/src/build-manifest.js +12 -4
  941. package/dist/src/build-manifest.test.js +20 -20
  942. package/dist/src/capabilityRouting.d.ts +16 -1
  943. package/dist/src/capabilityRouting.js +24 -1
  944. package/dist/src/capabilityRouting.test.js +20 -2
  945. package/dist/src/cli.js +213 -12
  946. package/dist/src/cli.test.js +329 -0
  947. package/dist/src/commanderAdapter.d.ts +1 -1
  948. package/dist/src/commanderAdapter.js +17 -12
  949. package/dist/src/commanderAdapter.test.js +7 -7
  950. package/dist/src/convention-audit.d.ts +50 -0
  951. package/dist/src/convention-audit.js +546 -0
  952. package/dist/src/convention-audit.test.d.ts +1 -0
  953. package/dist/src/convention-audit.test.js +226 -0
  954. package/dist/src/discovery.js +4 -5
  955. package/dist/src/doctor.js +0 -1
  956. package/dist/src/doctor.test.js +1 -1
  957. package/dist/src/engine.test.js +10 -10
  958. package/dist/src/errors.js +1 -1
  959. package/dist/src/execution.d.ts +1 -1
  960. package/dist/src/execution.js +111 -27
  961. package/dist/src/execution.test.js +334 -25
  962. package/dist/src/help.d.ts +36 -0
  963. package/dist/src/help.js +171 -0
  964. package/dist/src/help.test.d.ts +1 -0
  965. package/dist/src/help.test.js +54 -0
  966. package/dist/src/main.js +27 -8
  967. package/dist/src/manifest-types.d.ts +7 -3
  968. package/dist/src/pipeline/executor.js +1 -1
  969. package/dist/src/pipeline/executor.test.js +8 -0
  970. package/dist/src/pipeline/registry.d.ts +9 -0
  971. package/dist/src/pipeline/registry.js +13 -1
  972. package/dist/src/pipeline/steps/browser.d.ts +1 -0
  973. package/dist/src/pipeline/steps/browser.js +10 -0
  974. package/dist/src/pipeline/steps/download.test.js +1 -0
  975. package/dist/src/plugin.test.js +26 -26
  976. package/dist/src/registry-api.d.ts +1 -1
  977. package/dist/src/registry.d.ts +17 -11
  978. package/dist/src/registry.js +24 -6
  979. package/dist/src/registry.test.js +29 -22
  980. package/dist/src/runtime.d.ts +2 -1
  981. package/dist/src/runtime.js +1 -1
  982. package/dist/src/serialization.d.ts +6 -2
  983. package/dist/src/serialization.js +31 -7
  984. package/dist/src/serialization.test.js +41 -2
  985. package/dist/src/types.d.ts +19 -0
  986. package/dist/src/validate.js +15 -11
  987. package/dist/src/validate.test.d.ts +9 -0
  988. package/dist/src/validate.test.js +90 -0
  989. package/package.json +4 -1
  990. package/scripts/check-listing-id-pairing.mjs +193 -0
  991. package/scripts/check-silent-column-drop.mjs +105 -0
  992. package/scripts/check-typed-error-lint.mjs +118 -0
  993. package/scripts/fetch-adapters.js +1 -1
  994. package/scripts/silent-column-drop-baseline.json +962 -0
  995. package/scripts/typed-error-lint-baseline.json +1514 -0
  996. package/clis/ctrip/search.test.js +0 -64
  997. package/clis/gov-policy/commands.test.js +0 -27
  998. package/clis/linux-do/category.js +0 -36
  999. package/clis/linux-do/hot.js +0 -25
  1000. package/clis/linux-do/latest.js +0 -18
  1001. package/clis/pixiv/test-utils.js +0 -23
  1002. package/clis/toutiao/articles.test.js +0 -30
  1003. package/dist/src/analysis.d.ts +0 -40
  1004. package/dist/src/analysis.js +0 -172
@@ -3,6 +3,7 @@ import { ensureZsxqAuth, ensureZsxqPage, fetchFirstJson, getGroupsFromResponse,
3
3
  cli({
4
4
  site: 'zsxq',
5
5
  name: 'groups',
6
+ access: 'read',
6
7
  description: '列出当前账号加入的星球',
7
8
  domain: 'wx.zsxq.com',
8
9
  strategy: Strategy.COOKIE,
@@ -3,6 +3,7 @@ import { getActiveGroupId, ensureZsxqAuth, ensureZsxqPage, fetchFirstJson, getGr
3
3
  cli({
4
4
  site: 'zsxq',
5
5
  name: 'search',
6
+ access: 'read',
6
7
  description: '搜索星球内容',
7
8
  domain: 'wx.zsxq.com',
8
9
  strategy: Strategy.COOKIE,
@@ -4,6 +4,7 @@ import { getActiveGroupId, browserJsonRequest, ensureZsxqAuth, ensureZsxqPage, f
4
4
  cli({
5
5
  site: 'zsxq',
6
6
  name: 'topic',
7
+ access: 'read',
7
8
  description: '获取单个话题详情和评论',
8
9
  domain: 'wx.zsxq.com',
9
10
  strategy: Strategy.COOKIE,
@@ -3,6 +3,7 @@ import { getActiveGroupId, ensureZsxqAuth, ensureZsxqPage, fetchFirstJson, getTo
3
3
  cli({
4
4
  site: 'zsxq',
5
5
  name: 'topics',
6
+ access: 'read',
6
7
  description: '获取当前星球的话题列表',
7
8
  domain: 'wx.zsxq.com',
8
9
  strategy: Strategy.COOKIE,
@@ -3,7 +3,7 @@ import { resolveAdapterSourcePath } from './adapter-source.js';
3
3
  function makeCmd(overrides = {}) {
4
4
  return {
5
5
  site: 'test-site',
6
- name: 'test-cmd',
6
+ name: 'test-cmd', access: 'read',
7
7
  description: 'test',
8
8
  args: [],
9
9
  ...overrides,
@@ -20,8 +20,10 @@ function mkCmd(site, name, domain) {
20
20
  return {
21
21
  site,
22
22
  name,
23
+ access: 'read',
23
24
  description: '',
24
25
  domain,
26
+ browser: false,
25
27
  args: [],
26
28
  };
27
29
  }
@@ -19,10 +19,19 @@ export interface ResolveSuccess {
19
19
  */
20
20
  match_level: TargetMatchLevel;
21
21
  }
22
+ export interface FillTextResult extends ResolveSuccess {
23
+ filled: boolean;
24
+ verified: boolean;
25
+ expected: string;
26
+ actual: string;
27
+ length: number;
28
+ mode?: 'input' | 'textarea' | 'contenteditable';
29
+ }
22
30
  export declare abstract class BasePage implements IPage {
23
31
  protected _lastUrl: string | null;
24
32
  /** Cached previous snapshot hashes for incremental diff marking */
25
33
  private _prevSnapshotHashes;
34
+ private _cdpTargetMarkerSeq;
26
35
  abstract goto(url: string, options?: {
27
36
  waitUntil?: 'load' | 'none';
28
37
  settleMs?: number;
@@ -53,7 +62,16 @@ export declare abstract class BasePage implements IPage {
53
62
  protected tryNativeType(text: string): Promise<boolean>;
54
63
  /** Uses native CDP key events when the concrete page exposes them. */
55
64
  protected tryNativeKeyPress(key: string, modifiers: string[]): Promise<boolean>;
65
+ /**
66
+ * Run a DOM-domain CDP command against `window.__resolved`.
67
+ *
68
+ * CDP DOM.focus / DOM.scrollIntoViewIfNeeded need a nodeId, while our
69
+ * resolver stores the live Element in page JS. Bridge the two worlds with a
70
+ * short-lived marker attribute, then query it through CDP.
71
+ */
72
+ protected tryCdpOnResolvedElement(method: 'DOM.focus' | 'DOM.scrollIntoViewIfNeeded'): Promise<boolean>;
56
73
  typeText(ref: string, text: string, opts?: ResolveOptions): Promise<ResolveSuccess>;
74
+ fillText(ref: string, text: string, opts?: ResolveOptions): Promise<FillTextResult>;
57
75
  pressKey(key: string): Promise<void>;
58
76
  scrollTo(ref: string, opts?: ResolveOptions): Promise<unknown>;
59
77
  getFormState(): Promise<Record<string, unknown>>;
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import { generateSnapshotJs, getFormStateJs } from './dom-snapshot.js';
12
12
  import { pressKeyJs, waitForTextJs, waitForCaptureJs, waitForSelectorJs, scrollJs, autoScrollJs, networkRequestsJs, waitForDomStableJs, } from './dom-helpers.js';
13
- import { resolveTargetJs, clickResolvedJs, typeResolvedJs, prepareNativeTypeResolvedJs, scrollResolvedJs, } from './target-resolver.js';
13
+ import { resolveTargetJs, clickResolvedJs, typeResolvedJs, prepareNativeTypeResolvedJs, verifyFilledResolvedJs, scrollResolvedJs, } from './target-resolver.js';
14
14
  import { TargetError } from './target-errors.js';
15
15
  import { CliError } from '../errors.js';
16
16
  import { formatSnapshot } from '../snapshotFormatter.js';
@@ -61,6 +61,7 @@ export class BasePage {
61
61
  _lastUrl = null;
62
62
  /** Cached previous snapshot hashes for incremental diff marking */
63
63
  _prevSnapshotHashes = null;
64
+ _cdpTargetMarkerSeq = 0;
64
65
  /**
65
66
  * Safely evaluate JS with pre-serialized arguments.
66
67
  * Each key in `args` becomes a `const` declaration with JSON-serialized value,
@@ -154,8 +155,9 @@ export class BasePage {
154
155
  async click(ref, opts = {}) {
155
156
  // Phase 1: Resolve target with fingerprint verification
156
157
  const resolved = await runResolve(this, ref, opts);
158
+ const nativeScrolled = await this.tryCdpOnResolvedElement('DOM.scrollIntoViewIfNeeded');
157
159
  // Phase 2: Execute click on resolved element
158
- const result = await this.evaluate(clickResolvedJs());
160
+ const result = await this.evaluate(clickResolvedJs({ skipScroll: nativeScrolled }));
159
161
  if (typeof result === 'string' || result == null)
160
162
  return resolved;
161
163
  if (result.status === 'clicked')
@@ -217,12 +219,78 @@ export class BasePage {
217
219
  return false;
218
220
  }
219
221
  }
222
+ /**
223
+ * Run a DOM-domain CDP command against `window.__resolved`.
224
+ *
225
+ * CDP DOM.focus / DOM.scrollIntoViewIfNeeded need a nodeId, while our
226
+ * resolver stores the live Element in page JS. Bridge the two worlds with a
227
+ * short-lived marker attribute, then query it through CDP.
228
+ */
229
+ async tryCdpOnResolvedElement(method) {
230
+ const cdp = this.cdp;
231
+ if (typeof cdp !== 'function')
232
+ return false;
233
+ const markerAttr = 'data-opencli-cdp-target';
234
+ const markerValue = `${Date.now().toString(36)}-${++this._cdpTargetMarkerSeq}`;
235
+ const selector = `[${markerAttr}="${markerValue}"]`;
236
+ let marked = false;
237
+ try {
238
+ const marker = await this.evaluateWithArgs(`
239
+ (() => {
240
+ const el = window.__resolved;
241
+ if (!el || el.nodeType !== 1 || typeof el.setAttribute !== 'function') {
242
+ return { ok: false };
243
+ }
244
+ el.setAttribute(markerAttr, markerValue);
245
+ return { ok: true };
246
+ })()
247
+ `, { markerAttr, markerValue });
248
+ marked = marker?.ok === true;
249
+ if (!marked)
250
+ return false;
251
+ await cdp.call(this, 'DOM.enable', {}).catch(() => undefined);
252
+ const doc = await cdp.call(this, 'DOM.getDocument', {});
253
+ const rootNodeId = doc?.root?.nodeId;
254
+ if (typeof rootNodeId !== 'number')
255
+ return false;
256
+ const query = await cdp.call(this, 'DOM.querySelector', {
257
+ nodeId: rootNodeId,
258
+ selector,
259
+ });
260
+ const nodeId = query?.nodeId;
261
+ if (typeof nodeId !== 'number' || nodeId <= 0)
262
+ return false;
263
+ await cdp.call(this, method, { nodeId });
264
+ return true;
265
+ }
266
+ catch {
267
+ return false;
268
+ }
269
+ finally {
270
+ if (marked) {
271
+ await this.evaluateWithArgs(`
272
+ (() => {
273
+ for (const el of document.querySelectorAll(selector)) {
274
+ el.removeAttribute(markerAttr);
275
+ }
276
+ })()
277
+ `, { selector, markerAttr }).catch(() => undefined);
278
+ }
279
+ }
280
+ }
220
281
  async typeText(ref, text, opts = {}) {
221
282
  const resolved = await runResolve(this, ref, opts);
222
283
  let typed = false;
284
+ let nativeScrolled = false;
285
+ let nativeFocused = false;
223
286
  if (typeof this.nativeType === 'function' || typeof this.insertText === 'function') {
224
287
  try {
225
- const preparation = await this.evaluate(prepareNativeTypeResolvedJs());
288
+ nativeScrolled = await this.tryCdpOnResolvedElement('DOM.scrollIntoViewIfNeeded');
289
+ nativeFocused = await this.tryCdpOnResolvedElement('DOM.focus');
290
+ const preparation = await this.evaluate(prepareNativeTypeResolvedJs({
291
+ skipScroll: nativeScrolled,
292
+ skipFocus: nativeFocused,
293
+ }));
226
294
  typed = preparation?.ok === true && await this.tryNativeType(text);
227
295
  }
228
296
  catch {
@@ -235,6 +303,49 @@ export class BasePage {
235
303
  }
236
304
  return resolved;
237
305
  }
306
+ async fillText(ref, text, opts = {}) {
307
+ const resolved = await runResolve(this, ref, opts);
308
+ let nativeScrolled = false;
309
+ let nativeFocused = false;
310
+ try {
311
+ nativeScrolled = await this.tryCdpOnResolvedElement('DOM.scrollIntoViewIfNeeded');
312
+ nativeFocused = await this.tryCdpOnResolvedElement('DOM.focus');
313
+ }
314
+ catch {
315
+ // CDP focus/scroll is best-effort; DOM preparation below remains authoritative.
316
+ }
317
+ const preparation = await this.evaluate(prepareNativeTypeResolvedJs({
318
+ skipScroll: nativeScrolled,
319
+ skipFocus: nativeFocused,
320
+ }));
321
+ if (preparation?.ok !== true) {
322
+ throw new TargetError({
323
+ code: 'not_editable',
324
+ message: `Target "${ref}" is not a fillable input, textarea, or contenteditable element.`,
325
+ hint: 'Use `opencli browser state` to pick an editable target, or use `browser type` for keyboard-like interactions.',
326
+ });
327
+ }
328
+ const usedNativeInput = await this.tryNativeType(text);
329
+ if (!usedNativeInput) {
330
+ await this.evaluate(typeResolvedJs(text));
331
+ }
332
+ let verification = await this.evaluate(verifyFilledResolvedJs(text));
333
+ if (usedNativeInput && verification?.ok !== true) {
334
+ await this.evaluate(typeResolvedJs(text));
335
+ verification = await this.evaluate(verifyFilledResolvedJs(text));
336
+ }
337
+ const actual = verification && 'actual' in verification ? verification.actual : '';
338
+ const mode = verification && 'mode' in verification ? verification.mode : undefined;
339
+ return {
340
+ ...resolved,
341
+ filled: true,
342
+ verified: verification?.ok === true,
343
+ expected: text,
344
+ actual,
345
+ length: actual.length,
346
+ ...(mode ? { mode } : {}),
347
+ };
348
+ }
238
349
  async pressKey(key) {
239
350
  const parsed = parseKeyChord(key);
240
351
  if (!await this.tryNativeKeyPress(parsed.key, parsed.modifiers)) {
@@ -243,7 +354,8 @@ export class BasePage {
243
354
  }
244
355
  async scrollTo(ref, opts = {}) {
245
356
  const resolved = await runResolve(this, ref, opts);
246
- const result = (await this.evaluate(scrollResolvedJs()));
357
+ const nativeScrolled = await this.tryCdpOnResolvedElement('DOM.scrollIntoViewIfNeeded');
358
+ const result = (await this.evaluate(scrollResolvedJs({ skipScroll: nativeScrolled })));
247
359
  // Fold match_level into the scroll payload so the user-facing envelope
248
360
  // carries it the same way click / type do.
249
361
  if (result && typeof result === 'object') {
@@ -1,6 +1,7 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
2
  import { CliError } from '../errors.js';
3
3
  import { BasePage } from './base-page.js';
4
+ import { TargetError } from './target-errors.js';
4
5
  class TestPage extends BasePage {
5
6
  result;
6
7
  args;
@@ -17,15 +18,23 @@ class TestPage extends BasePage {
17
18
  }
18
19
  class ActionPage extends BasePage {
19
20
  results = [];
21
+ withArgsResults = [];
20
22
  scripts = [];
23
+ withArgs = [];
21
24
  nativeType;
22
25
  insertText;
23
26
  nativeKeyPress;
27
+ cdp;
24
28
  async goto() { }
25
29
  async evaluate(js) {
26
30
  this.scripts.push(js);
27
31
  return this.results.shift() ?? null;
28
32
  }
33
+ async evaluateWithArgs(js, args) {
34
+ this.scripts.push(js);
35
+ this.withArgs.push(args);
36
+ return this.withArgsResults.shift() ?? null;
37
+ }
29
38
  async getCookies() { return []; }
30
39
  async screenshot() { return ''; }
31
40
  async tabs() { return []; }
@@ -100,6 +109,27 @@ describe('BasePage native input routing', () => {
100
109
  expect(page.scripts[1]).toContain('nearestContentEditableHost');
101
110
  expect(page.scripts.join('\n')).not.toContain("return 'typed'");
102
111
  });
112
+ it('uses CDP DOM focus and scroll before native text insertion when available', async () => {
113
+ const page = new ActionPage();
114
+ page.nativeType = vi.fn().mockResolvedValue(undefined);
115
+ page.cdp = vi.fn()
116
+ .mockResolvedValueOnce({})
117
+ .mockResolvedValueOnce({ root: { nodeId: 1 } })
118
+ .mockResolvedValueOnce({ nodeId: 7 })
119
+ .mockResolvedValueOnce({})
120
+ .mockResolvedValueOnce({})
121
+ .mockResolvedValueOnce({ root: { nodeId: 1 } })
122
+ .mockResolvedValueOnce({ nodeId: 7 })
123
+ .mockResolvedValueOnce({});
124
+ page.results = [resolveOk, { ok: true, mode: 'input' }];
125
+ page.withArgsResults = [{ ok: true }, undefined, { ok: true }, undefined];
126
+ await page.typeText('#q', 'hello');
127
+ expect(page.cdp).toHaveBeenCalledWith('DOM.scrollIntoViewIfNeeded', { nodeId: 7 });
128
+ expect(page.cdp).toHaveBeenCalledWith('DOM.focus', { nodeId: 7 });
129
+ expect(page.nativeType).toHaveBeenCalledWith('hello');
130
+ expect(page.scripts.at(-1)).toContain('if (false) el.scrollIntoView');
131
+ expect(page.scripts.at(-1)).toContain('if (false) {');
132
+ });
103
133
  it('keeps the DOM setter fallback when native text insertion is unavailable', async () => {
104
134
  const page = new ActionPage();
105
135
  page.results = [resolveOk, 'typed'];
@@ -117,6 +147,84 @@ describe('BasePage native input routing', () => {
117
147
  expect(page.scripts).toHaveLength(3);
118
148
  expect(page.scripts[2]).toContain("return 'typed'");
119
149
  });
150
+ it('fills text through the native input path and verifies the exact value', async () => {
151
+ const page = new ActionPage();
152
+ page.nativeType = vi.fn().mockResolvedValue(undefined);
153
+ page.results = [
154
+ resolveOk,
155
+ { ok: true, mode: 'textarea' },
156
+ { ok: true, actual: 'line1\\n/ / raw', expected: 'line1\\n/ / raw', length: 14, mode: 'textarea' },
157
+ ];
158
+ await expect(page.fillText('#message', 'line1\\n/ / raw')).resolves.toEqual({
159
+ filled: true,
160
+ verified: true,
161
+ expected: 'line1\\n/ / raw',
162
+ actual: 'line1\\n/ / raw',
163
+ length: 14,
164
+ matches_n: 1,
165
+ match_level: 'exact',
166
+ mode: 'textarea',
167
+ });
168
+ expect(page.nativeType).toHaveBeenCalledWith('line1\\n/ / raw');
169
+ expect(page.scripts).toHaveLength(3);
170
+ expect(page.scripts[2]).toContain('actual ===');
171
+ });
172
+ it('falls back to the DOM setter when native fill insertion is unavailable', async () => {
173
+ const page = new ActionPage();
174
+ page.results = [
175
+ resolveOk,
176
+ { ok: true, mode: 'input' },
177
+ 'typed',
178
+ { ok: true, actual: 'hello', expected: 'hello', length: 5, mode: 'input' },
179
+ ];
180
+ await expect(page.fillText('#q', 'hello')).resolves.toEqual(expect.objectContaining({
181
+ filled: true,
182
+ verified: true,
183
+ actual: 'hello',
184
+ mode: 'input',
185
+ }));
186
+ expect(page.scripts).toHaveLength(4);
187
+ expect(page.scripts[2]).toContain("return 'typed'");
188
+ });
189
+ it('falls back to DOM fill if native insertion does not verify', async () => {
190
+ const page = new ActionPage();
191
+ page.nativeType = vi.fn().mockResolvedValue(undefined);
192
+ page.results = [
193
+ resolveOk,
194
+ { ok: true, mode: 'input' },
195
+ { ok: false, actual: '', expected: 'hello', length: 0, mode: 'input' },
196
+ 'typed',
197
+ { ok: true, actual: 'hello', expected: 'hello', length: 5, mode: 'input' },
198
+ ];
199
+ await expect(page.fillText('#q', 'hello')).resolves.toEqual(expect.objectContaining({
200
+ filled: true,
201
+ verified: true,
202
+ actual: 'hello',
203
+ }));
204
+ expect(page.nativeType).toHaveBeenCalledWith('hello');
205
+ expect(page.scripts).toHaveLength(5);
206
+ expect(page.scripts[3]).toContain("return 'typed'");
207
+ });
208
+ it('throws a structured not_editable error for non-fillable targets', async () => {
209
+ const page = new ActionPage();
210
+ page.results = [resolveOk, { ok: false, reason: 'not_editable', tag: 'button' }];
211
+ const err = await page.fillText('button', 'hello').catch((error) => error);
212
+ expect(err).toBeInstanceOf(TargetError);
213
+ expect(err.code).toBe('not_editable');
214
+ });
215
+ it('uses CDP DOM scrollIntoViewIfNeeded before JS click when available', async () => {
216
+ const page = new ActionPage();
217
+ page.cdp = vi.fn()
218
+ .mockResolvedValueOnce({})
219
+ .mockResolvedValueOnce({ root: { nodeId: 1 } })
220
+ .mockResolvedValueOnce({ nodeId: 9 })
221
+ .mockResolvedValueOnce({});
222
+ page.results = [resolveOk, { status: 'clicked', x: 1, y: 2 }];
223
+ page.withArgsResults = [{ ok: true }, undefined];
224
+ await page.click('#save');
225
+ expect(page.cdp).toHaveBeenCalledWith('DOM.scrollIntoViewIfNeeded', { nodeId: 9 });
226
+ expect(page.scripts.at(-1)).toContain('if (false) el.scrollIntoView');
227
+ });
120
228
  it('presses key chords through native CDP key events when available', async () => {
121
229
  const page = new ActionPage();
122
230
  page.nativeKeyPress = vi.fn().mockResolvedValue(undefined);
@@ -26,6 +26,7 @@ export declare class CDPBridge implements IBrowserFactory {
26
26
  workspace?: string;
27
27
  cdpEndpoint?: string;
28
28
  contextId?: string;
29
+ idleTimeout?: number;
29
30
  }): Promise<IPage>;
30
31
  close(): Promise<void>;
31
32
  send(method: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
@@ -202,16 +202,58 @@ class CDPPage extends BasePage {
202
202
  : cookies;
203
203
  }
204
204
  async screenshot(options = {}) {
205
- const result = await this.bridge.send('Page.captureScreenshot', {
206
- format: options.format ?? 'png',
207
- quality: options.format === 'jpeg' ? (options.quality ?? 80) : undefined,
208
- captureBeyondViewport: options.fullPage ?? false,
209
- });
210
- const base64 = isRecord(result) && typeof result.data === 'string' ? result.data : '';
211
- if (options.path) {
212
- await saveBase64ToFile(base64, options.path);
205
+ const fullPage = options.fullPage === true;
206
+ const overrideWidth = options.width && options.width > 0 ? Math.ceil(options.width) : undefined;
207
+ // height is ignored under fullPage so the captureBeyondViewport path stays unchanged for users who pass --height alongside --full-page.
208
+ const overrideHeight = !fullPage && options.height && options.height > 0 ? Math.ceil(options.height) : undefined;
209
+ const needsOverride = overrideWidth !== undefined || overrideHeight !== undefined;
210
+ if (needsOverride) {
211
+ if (overrideWidth !== undefined && fullPage) {
212
+ await this.bridge.send('Emulation.setDeviceMetricsOverride', {
213
+ mobile: false,
214
+ width: overrideWidth,
215
+ height: 0,
216
+ deviceScaleFactor: 1,
217
+ });
218
+ }
219
+ let finalWidth = overrideWidth ?? 0;
220
+ let finalHeight = overrideHeight ?? 0;
221
+ if (fullPage) {
222
+ const metrics = await this.bridge.send('Page.getLayoutMetrics');
223
+ const m = isRecord(metrics) ? metrics : {};
224
+ const css = isRecord(m.cssContentSize) ? m.cssContentSize : undefined;
225
+ const fb = isRecord(m.contentSize) ? m.contentSize : undefined;
226
+ const size = css ?? fb;
227
+ if (size && typeof size.width === 'number' && typeof size.height === 'number') {
228
+ if (finalWidth === 0)
229
+ finalWidth = Math.ceil(size.width);
230
+ finalHeight = Math.ceil(size.height);
231
+ }
232
+ }
233
+ await this.bridge.send('Emulation.setDeviceMetricsOverride', {
234
+ mobile: false,
235
+ width: finalWidth,
236
+ height: finalHeight,
237
+ deviceScaleFactor: 1,
238
+ });
239
+ }
240
+ try {
241
+ const result = await this.bridge.send('Page.captureScreenshot', {
242
+ format: options.format ?? 'png',
243
+ quality: options.format === 'jpeg' ? (options.quality ?? 80) : undefined,
244
+ captureBeyondViewport: !needsOverride && fullPage,
245
+ });
246
+ const base64 = isRecord(result) && typeof result.data === 'string' ? result.data : '';
247
+ if (options.path) {
248
+ await saveBase64ToFile(base64, options.path);
249
+ }
250
+ return base64;
251
+ }
252
+ finally {
253
+ if (needsOverride) {
254
+ await this.bridge.send('Emulation.clearDeviceMetricsOverride').catch(() => { });
255
+ }
213
256
  }
214
- return base64;
215
257
  }
216
258
  async startNetworkCapture(pattern = '') {
217
259
  // Always update the filter pattern
@@ -320,6 +362,12 @@ class CDPPage extends BasePage {
320
362
  async cdp(method, params = {}) {
321
363
  return this.bridge.send(method, params);
322
364
  }
365
+ async handleJavaScriptDialog(accept, promptText) {
366
+ await this.cdp('Page.handleJavaScriptDialog', {
367
+ accept,
368
+ ...(promptText !== undefined && { promptText }),
369
+ });
370
+ }
323
371
  async nativeClick(x, y) {
324
372
  await this.cdp('Input.dispatchMouseEvent', {
325
373
  type: 'mousePressed',
@@ -58,10 +58,12 @@ describe('CDPBridge cookies', () => {
58
58
  expect(page.nativeType).toBeTypeOf('function');
59
59
  expect(page.nativeKeyPress).toBeTypeOf('function');
60
60
  expect(page.nativeClick).toBeTypeOf('function');
61
+ expect(page.handleJavaScriptDialog).toBeTypeOf('function');
61
62
  expect(page.cdp).toBeTypeOf('function');
62
63
  await page.nativeType('hello');
63
64
  await page.nativeKeyPress('a', ['Ctrl']);
64
65
  await page.nativeClick(10, 20);
66
+ await page.handleJavaScriptDialog(true, 'ok');
65
67
  await page.cdp('Page.getLayoutMetrics', {});
66
68
  expect(send.mock.calls).toEqual([
67
69
  ['Input.insertText', { text: 'hello' }],
@@ -69,6 +71,7 @@ describe('CDPBridge cookies', () => {
69
71
  ['Input.dispatchKeyEvent', { type: 'keyUp', key: 'a', modifiers: 2 }],
70
72
  ['Input.dispatchMouseEvent', { type: 'mousePressed', x: 10, y: 20, button: 'left', clickCount: 1 }],
71
73
  ['Input.dispatchMouseEvent', { type: 'mouseReleased', x: 10, y: 20, button: 'left', clickCount: 1 }],
74
+ ['Page.handleJavaScriptDialog', { accept: true, promptText: 'ok' }],
72
75
  ['Page.getLayoutMetrics', {}],
73
76
  ]);
74
77
  });
@@ -20,6 +20,10 @@ export interface DaemonCommand {
20
20
  format?: 'png' | 'jpeg';
21
21
  quality?: number;
22
22
  fullPage?: boolean;
23
+ /** Override viewport width in CSS pixels for screenshot (0 / undefined = use current) */
24
+ width?: number;
25
+ /** Override viewport height in CSS pixels for screenshot (0 / undefined = use current; ignored when fullPage) */
26
+ height?: number;
23
27
  /** Local file paths for set-file-input action */
24
28
  files?: string[];
25
29
  /** CSS selector for file input element (set-file-input action) */
@@ -65,7 +65,7 @@ export function isTransientBrowserError(err) {
65
65
  export function formatBrowserConnectError(kind, detail) {
66
66
  switch (kind) {
67
67
  case 'daemon-not-running':
68
- return new BrowserConnectError('Cannot connect to opencli daemon.' + (detail ? `\n\n${detail}` : ''), `The daemon should auto-start. If it keeps failing, make sure port ${DEFAULT_DAEMON_PORT} is available.`, kind);
68
+ return new BrowserConnectError('Cannot connect to opencli daemon.' + (detail ? `\n\n${detail}` : ''), `Run \`opencli doctor\` to diagnose, or \`opencli daemon restart\` to force a fresh daemon. Default port is ${DEFAULT_DAEMON_PORT}.`, kind);
69
69
  case 'extension-not-connected':
70
70
  return new BrowserConnectError('Browser Bridge extension is not connected.' + (detail ? `\n\n${detail}` : ''), 'Install the extension from GitHub Releases, then reload.', kind);
71
71
  case 'command-failed':
@@ -41,7 +41,7 @@ export declare class Page extends BasePage {
41
41
  domain?: string;
42
42
  url?: string;
43
43
  }): Promise<BrowserCookie[]>;
44
- /** Close the automation window in the extension */
44
+ /** Release the current automation tab lease in the extension */
45
45
  closeWindow(): Promise<void>;
46
46
  tabs(): Promise<unknown[]>;
47
47
  newTab(url?: string): Promise<string | undefined>;
@@ -68,6 +68,7 @@ export declare class Page extends BasePage {
68
68
  }>>;
69
69
  evaluateInFrame(js: string, frameIndex: number): Promise<unknown>;
70
70
  cdp(method: string, params?: Record<string, unknown>): Promise<unknown>;
71
+ handleJavaScriptDialog(accept: boolean, promptText?: string): Promise<void>;
71
72
  /** CDP native click fallback — called when JS el.click() fails */
72
73
  protected tryNativeClick(x: number, y: number): Promise<boolean>;
73
74
  /** Precise click using DOM.getContentQuads/getBoxModel for inline elements */
@@ -143,7 +143,7 @@ export class Page extends BasePage {
143
143
  const result = await sendCommand('cookies', { ...this._wsOpt(), ...opts });
144
144
  return Array.isArray(result) ? result : [];
145
145
  }
146
- /** Close the automation window in the extension */
146
+ /** Release the current automation tab lease in the extension */
147
147
  async closeWindow() {
148
148
  try {
149
149
  await sendCommand('close-window', { ...this._wsOpt() });
@@ -205,6 +205,8 @@ export class Page extends BasePage {
205
205
  format: options.format,
206
206
  quality: options.quality,
207
207
  fullPage: options.fullPage,
208
+ width: options.width,
209
+ height: options.height,
208
210
  });
209
211
  if (options.path) {
210
212
  await saveBase64ToFile(base64, options.path);
@@ -283,6 +285,12 @@ export class Page extends BasePage {
283
285
  ...this._cmdOpts(),
284
286
  });
285
287
  }
288
+ async handleJavaScriptDialog(accept, promptText) {
289
+ await this.cdp('Page.handleJavaScriptDialog', {
290
+ accept,
291
+ ...(promptText !== undefined && { promptText }),
292
+ });
293
+ }
286
294
  /** CDP native click fallback — called when JS el.click() fails */
287
295
  async tryNativeClick(x, y) {
288
296
  try {
@@ -102,6 +102,23 @@ describe('Page network capture compatibility', () => {
102
102
  expect(warnMock).toHaveBeenCalledTimes(1);
103
103
  });
104
104
  });
105
+ describe('Page CDP helpers', () => {
106
+ beforeEach(() => {
107
+ sendCommandMock.mockReset();
108
+ sendCommandFullMock.mockReset();
109
+ warnMock.mockReset();
110
+ });
111
+ it('handles JavaScript dialogs through the CDP passthrough', async () => {
112
+ sendCommandMock.mockResolvedValueOnce({});
113
+ const page = new Page('browser:default');
114
+ await page.handleJavaScriptDialog(true, 'confirm');
115
+ expect(sendCommandMock).toHaveBeenCalledWith('cdp', expect.objectContaining({
116
+ workspace: 'browser:default',
117
+ cdpMethod: 'Page.handleJavaScriptDialog',
118
+ cdpParams: { accept: true, promptText: 'confirm' },
119
+ }));
120
+ });
121
+ });
105
122
  describe('Page active target tracking', () => {
106
123
  beforeEach(() => {
107
124
  sendCommandMock.mockReset();
@@ -199,3 +216,32 @@ describe('Page active target tracking', () => {
199
216
  expect(evalCall?.[1]).not.toHaveProperty('page');
200
217
  });
201
218
  });
219
+ describe('Page.screenshot', () => {
220
+ beforeEach(() => {
221
+ sendCommandMock.mockReset();
222
+ sendCommandFullMock.mockReset();
223
+ warnMock.mockReset();
224
+ });
225
+ it('forwards width / height / fullPage options to the bridge', async () => {
226
+ sendCommandMock.mockResolvedValueOnce('BASE64');
227
+ const page = new Page('browser:default');
228
+ const data = await page.screenshot({ fullPage: true, width: 1080 });
229
+ expect(data).toBe('BASE64');
230
+ expect(sendCommandMock).toHaveBeenCalledWith('screenshot', expect.objectContaining({
231
+ workspace: 'browser:default',
232
+ fullPage: true,
233
+ width: 1080,
234
+ }));
235
+ });
236
+ it('omits viewport overrides when none are set', async () => {
237
+ sendCommandMock.mockResolvedValueOnce('BASE64');
238
+ const page = new Page('browser:default');
239
+ await page.screenshot();
240
+ const call = sendCommandMock.mock.calls.at(-1);
241
+ expect(call?.[0]).toBe('screenshot');
242
+ const args = call?.[1];
243
+ expect(args.width).toBeUndefined();
244
+ expect(args.height).toBeUndefined();
245
+ expect(args.fullPage).toBeUndefined();
246
+ });
247
+ });
@@ -15,8 +15,9 @@
15
15
  * - selector_not_found: 0 matches
16
16
  * - selector_ambiguous: >1 matches for a write op without --nth
17
17
  * - selector_nth_out_of_range: --nth beyond matches_n
18
+ * - not_editable: target exists but cannot accept text input
18
19
  */
19
- export type TargetErrorCode = 'not_found' | 'stale_ref' | 'invalid_selector' | 'selector_not_found' | 'selector_ambiguous' | 'selector_nth_out_of_range';
20
+ export type TargetErrorCode = 'not_found' | 'stale_ref' | 'invalid_selector' | 'selector_not_found' | 'selector_ambiguous' | 'selector_nth_out_of_range' | 'not_editable';
20
21
  export interface TargetErrorInfo {
21
22
  code: TargetErrorCode;
22
23
  message: string;