publishport-opencli 1.0.20 → 1.0.21

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 (1041) hide show
  1. package/clis/12306/me.js +2 -2
  2. package/clis/12306/orders.js +3 -3
  3. package/clis/12306/passengers.js +3 -3
  4. package/clis/12306/price.js +1 -1
  5. package/clis/12306/stations.js +1 -1
  6. package/clis/12306/train.js +1 -1
  7. package/clis/12306/trains.js +1 -1
  8. package/clis/12306/utils.js +1 -1
  9. package/clis/1688/download.js +1 -1
  10. package/clis/1688/item.js +4 -4
  11. package/clis/1688/search.js +4 -4
  12. package/clis/1688/store.js +4 -4
  13. package/clis/1point3acres/forum.js +1 -1
  14. package/clis/1point3acres/forums.js +1 -1
  15. package/clis/1point3acres/notifications.js +1 -1
  16. package/clis/1point3acres/search.js +1 -1
  17. package/clis/1point3acres/thread.js +2 -2
  18. package/clis/1point3acres/user.js +1 -1
  19. package/clis/1point3acres/utils.js +2 -2
  20. package/clis/36kr/article.js +2 -2
  21. package/clis/36kr/hot.js +2 -2
  22. package/clis/36kr/news.js +1 -1
  23. package/clis/36kr/search.js +2 -2
  24. package/clis/51job/company.js +2 -2
  25. package/clis/51job/detail.js +2 -2
  26. package/clis/51job/hot.js +1 -1
  27. package/clis/51job/search.js +1 -1
  28. package/clis/51job/utils.js +7 -7
  29. package/clis/_atlassian/shared.js +9 -9
  30. package/clis/_shared/article/auth.js +4 -4
  31. package/clis/_shared/article/douban-md2draft.js +4 -4
  32. package/clis/_shared/article/format.js +1 -1
  33. package/clis/_shared/article/images.js +7 -7
  34. package/clis/_shared/article/login.js +1 -1
  35. package/clis/_shared/article/publish.js +11 -11
  36. package/clis/_shared/common.js +1 -1
  37. package/clis/_shared/content-guard.js +1 -1
  38. package/clis/_shared/desktop-commands.js +1 -1
  39. package/clis/_shared/file-inject.js +12 -12
  40. package/clis/_shared/self-hosted-sites.js +2 -2
  41. package/clis/_shared/site-auth.js +1 -1
  42. package/clis/_shared/token-auth.js +2 -2
  43. package/clis/_shared/video-publish.js +9 -9
  44. package/clis/amazon/offer.js +3 -3
  45. package/clis/amazon/product.js +5 -5
  46. package/clis/amazon/shared.js +6 -6
  47. package/clis/antigravity/_actions.js +13 -13
  48. package/clis/antigravity/audit-extras.js +10 -10
  49. package/clis/antigravity/delete.js +1 -1
  50. package/clis/antigravity/model.js +6 -6
  51. package/clis/antigravity/new.js +2 -2
  52. package/clis/antigravity/read.js +2 -2
  53. package/clis/antigravity/rename.js +1 -1
  54. package/clis/antigravity/send.js +3 -3
  55. package/clis/antigravity/serve.js +17 -17
  56. package/clis/antigravity/storage.js +6 -6
  57. package/clis/antigravity/watch.js +2 -2
  58. package/clis/apple-podcasts/episodes.js +1 -1
  59. package/clis/apple-podcasts/top.js +1 -1
  60. package/clis/apple-podcasts/utils.js +1 -1
  61. package/clis/archive/item.js +1 -1
  62. package/clis/archive/search.js +1 -1
  63. package/clis/archive/snapshots.js +1 -1
  64. package/clis/archive/wayback.js +1 -1
  65. package/clis/arxiv/author.js +1 -1
  66. package/clis/arxiv/utils.js +1 -1
  67. package/clis/autohome/brand.js +1 -1
  68. package/clis/autohome/score.js +1 -1
  69. package/clis/autohome/utils.js +1 -1
  70. package/clis/baijiahao/article.js +1 -1
  71. package/clis/baijiahao/lists.js +1 -1
  72. package/clis/baijiahao/login.js +1 -1
  73. package/clis/baijiahao/publish.js +9 -9
  74. package/clis/baijiahao/stats.js +1 -1
  75. package/clis/baijiahao/whoami.js +1 -1
  76. package/clis/band/bands.js +2 -2
  77. package/clis/band/mentions.js +2 -2
  78. package/clis/band/post.js +4 -4
  79. package/clis/band/posts.js +3 -3
  80. package/clis/barchart/flow.js +3 -3
  81. package/clis/barchart/greeks.js +2 -2
  82. package/clis/barchart/quote.js +3 -3
  83. package/clis/bbc/news.js +1 -1
  84. package/clis/bbc/topic.js +1 -1
  85. package/clis/bbc/utils.js +1 -1
  86. package/clis/bilibili/article.js +1 -1
  87. package/clis/bilibili/categories.js +1 -1
  88. package/clis/bilibili/coin.js +1 -1
  89. package/clis/bilibili/comment-del.js +1 -1
  90. package/clis/bilibili/comment-like.js +1 -1
  91. package/clis/bilibili/comment.js +1 -1
  92. package/clis/bilibili/comments.js +1 -1
  93. package/clis/bilibili/dm-list.js +1 -1
  94. package/clis/bilibili/dm-read.js +1 -1
  95. package/clis/bilibili/dm-send.js +1 -1
  96. package/clis/bilibili/download.js +2 -2
  97. package/clis/bilibili/drafts.js +1 -1
  98. package/clis/bilibili/dynamic-post.js +3 -3
  99. package/clis/bilibili/favorite-add.js +1 -1
  100. package/clis/bilibili/favorite.js +1 -1
  101. package/clis/bilibili/feed.js +2 -2
  102. package/clis/bilibili/follow.js +1 -1
  103. package/clis/bilibili/following.js +1 -1
  104. package/clis/bilibili/like.js +1 -1
  105. package/clis/bilibili/partitions.js +1 -1
  106. package/clis/bilibili/stats.js +1 -1
  107. package/clis/bilibili/subtitle.js +3 -3
  108. package/clis/bilibili/summary.js +1 -1
  109. package/clis/bilibili/topics.js +1 -1
  110. package/clis/bilibili/unfollow.js +1 -1
  111. package/clis/bilibili/upload.js +1 -1
  112. package/clis/bilibili/utils.js +10 -10
  113. package/clis/bilibili/video-drafts.js +1 -1
  114. package/clis/bilibili/video.js +1 -1
  115. package/clis/bloomberg/businessweek.js +4 -4
  116. package/clis/bloomberg/news.js +2 -2
  117. package/clis/bloomberg/utils.js +13 -13
  118. package/clis/bluesky/post.js +1 -1
  119. package/clis/bluesky/shared.js +11 -11
  120. package/clis/bluesky/whoami.js +1 -1
  121. package/clis/booking/search.js +2 -2
  122. package/clis/boss/accept.js +1 -1
  123. package/clis/boss/applied.js +1 -1
  124. package/clis/boss/auth.js +1 -1
  125. package/clis/boss/batchgreet.js +1 -1
  126. package/clis/boss/bossinfo.js +1 -1
  127. package/clis/boss/chatlist.js +1 -1
  128. package/clis/boss/chatmsg.js +1 -1
  129. package/clis/boss/cities.js +1 -1
  130. package/clis/boss/detail.js +1 -1
  131. package/clis/boss/exchange.js +1 -1
  132. package/clis/boss/greet.js +1 -1
  133. package/clis/boss/interviews.js +1 -1
  134. package/clis/boss/invite.js +1 -1
  135. package/clis/boss/joblist.js +1 -1
  136. package/clis/boss/mark.js +1 -1
  137. package/clis/boss/me.js +2 -2
  138. package/clis/boss/recommend.js +1 -1
  139. package/clis/boss/resumedelete.js +1 -1
  140. package/clis/boss/resumelist.js +1 -1
  141. package/clis/boss/resumeupload.js +11 -11
  142. package/clis/boss/search.js +1 -1
  143. package/clis/boss/send.js +1 -1
  144. package/clis/boss/sendresume.js +1 -1
  145. package/clis/boss/stats.js +1 -1
  146. package/clis/boss/unread.js +1 -1
  147. package/clis/boss/utils.js +13 -13
  148. package/clis/chaoxing/assignments.js +1 -1
  149. package/clis/chaoxing/exams.js +1 -1
  150. package/clis/chaoxing/utils.js +9 -9
  151. package/clis/chatgpt/ask.js +1 -1
  152. package/clis/chatgpt/auth.js +2 -2
  153. package/clis/chatgpt/detail.js +1 -1
  154. package/clis/chatgpt/image.js +1 -1
  155. package/clis/chatgpt/read.js +1 -1
  156. package/clis/chatgpt/send.js +1 -1
  157. package/clis/chatgpt/utils.js +59 -59
  158. package/clis/chatgpt-app/ask.js +1 -1
  159. package/clis/chatgpt-app/send.js +1 -1
  160. package/clis/chatwise/model.js +6 -6
  161. package/clis/chess/analyze.js +1 -1
  162. package/clis/chess/game.js +1 -1
  163. package/clis/chess/games.js +1 -1
  164. package/clis/chess/stats.js +1 -1
  165. package/clis/chess/utils.js +1 -1
  166. package/clis/claude/ask.js +2 -2
  167. package/clis/claude/detail.js +1 -1
  168. package/clis/claude/new.js +1 -1
  169. package/clis/claude/read.js +1 -1
  170. package/clis/claude/send.js +1 -1
  171. package/clis/claude/utils.js +23 -23
  172. package/clis/cnblogs/article.js +1 -1
  173. package/clis/cnblogs/login.js +1 -1
  174. package/clis/cnblogs/stats.js +7 -7
  175. package/clis/cnblogs/whoami.js +1 -1
  176. package/clis/codex/_actions.js +3 -3
  177. package/clis/codex/archive.js +1 -1
  178. package/clis/codex/ask.js +6 -6
  179. package/clis/codex/model.js +8 -8
  180. package/clis/codex/pin.js +1 -1
  181. package/clis/codex/rename.js +4 -4
  182. package/clis/codex/send.js +3 -3
  183. package/clis/codex/sidebar.js +1 -1
  184. package/clis/coingecko/categories.js +1 -1
  185. package/clis/coingecko/coin.js +1 -1
  186. package/clis/coingecko/derivatives.js +1 -1
  187. package/clis/coingecko/exchanges.js +1 -1
  188. package/clis/coingecko/global.js +1 -1
  189. package/clis/coingecko/trending.js +1 -1
  190. package/clis/confluence/search.js +1 -1
  191. package/clis/coupang/product.js +3 -3
  192. package/clis/coupang/utils.js +1 -1
  193. package/clis/crates/crate.js +1 -1
  194. package/clis/crates/search.js +1 -1
  195. package/clis/crates/utils.js +1 -1
  196. package/clis/csdn/article.js +13 -13
  197. package/clis/csdn/columns.js +1 -1
  198. package/clis/csdn/login.js +1 -1
  199. package/clis/csdn/stats.js +4 -4
  200. package/clis/csdn/whoami.js +1 -1
  201. package/clis/cto51/article.js +1 -1
  202. package/clis/cto51/whoami.js +1 -1
  203. package/clis/ctrip/flight.js +2 -2
  204. package/clis/ctrip/hotel-search.js +3 -3
  205. package/clis/ctrip/hotel-suggest.js +1 -1
  206. package/clis/ctrip/search.js +1 -1
  207. package/clis/ctrip/utils.js +6 -6
  208. package/clis/cursor/ask.js +5 -5
  209. package/clis/cursor/composer.js +2 -2
  210. package/clis/cursor/model.js +4 -4
  211. package/clis/cursor/send.js +2 -2
  212. package/clis/dblp/author.js +1 -1
  213. package/clis/dblp/paper.js +1 -1
  214. package/clis/dblp/search.js +1 -1
  215. package/clis/dblp/utils.js +1 -1
  216. package/clis/dblp/venue.js +1 -1
  217. package/clis/deepseek/ask.js +1 -1
  218. package/clis/deepseek/auth.js +2 -2
  219. package/clis/deepseek/detail.js +1 -1
  220. package/clis/deepseek/new.js +1 -1
  221. package/clis/deepseek/read.js +1 -1
  222. package/clis/deepseek/send.js +7 -7
  223. package/clis/deepseek/utils.js +25 -25
  224. package/clis/defillama/protocol.js +1 -1
  225. package/clis/defillama/protocols.js +1 -1
  226. package/clis/defillama/utils.js +1 -1
  227. package/clis/devto/auth.js +2 -2
  228. package/clis/devto/latest.js +1 -1
  229. package/clis/devto/publish.js +5 -5
  230. package/clis/devto/read.js +2 -2
  231. package/clis/devto/stats.js +3 -3
  232. package/clis/dianping/auth.js +2 -2
  233. package/clis/dianping/cityResolver.js +2 -2
  234. package/clis/dianping/search.js +1 -1
  235. package/clis/dianping/shop.js +1 -1
  236. package/clis/dianping/utils.js +1 -1
  237. package/clis/discord-app/delete.js +3 -3
  238. package/clis/discord-app/read.js +1 -1
  239. package/clis/discord-app/thread-read.js +1 -1
  240. package/clis/discord-web/auth.js +2 -2
  241. package/clis/discord-web/send.js +5 -5
  242. package/clis/dockerhub/image.js +1 -1
  243. package/clis/dockerhub/search.js +1 -1
  244. package/clis/dockerhub/utils.js +1 -1
  245. package/clis/dongchedi/koubei.js +1 -1
  246. package/clis/dongchedi/models.js +1 -1
  247. package/clis/dongchedi/score.js +1 -1
  248. package/clis/dongchedi/search.js +1 -1
  249. package/clis/dongchedi/series.js +1 -1
  250. package/clis/dongchedi/specs.js +1 -1
  251. package/clis/dongchedi/utils.js +1 -1
  252. package/clis/douban/article.js +3 -3
  253. package/clis/douban/auth.js +2 -2
  254. package/clis/douban/download.js +1 -1
  255. package/clis/douban/utils.js +23 -23
  256. package/clis/doubao/auth.js +3 -3
  257. package/clis/doubao/utils.js +39 -39
  258. package/clis/doubao-app/ask.js +1 -1
  259. package/clis/doubao-app/utils.js +4 -4
  260. package/clis/douyin/_shared/browser-fetch.js +7 -7
  261. package/clis/douyin/_shared/draft-cache.js +1 -1
  262. package/clis/douyin/_shared/imagex-upload.js +1 -1
  263. package/clis/douyin/_shared/sts2.js +1 -1
  264. package/clis/douyin/_shared/text-extra.js +1 -1
  265. package/clis/douyin/_shared/tos-upload.js +4 -4
  266. package/clis/douyin/_shared/transcode.js +1 -1
  267. package/clis/douyin/_shared/vod-upload.js +4 -4
  268. package/clis/douyin/draft.js +18 -18
  269. package/clis/douyin/drafts.js +1 -1
  270. package/clis/douyin/publish-image.js +12 -12
  271. package/clis/douyin/publish.js +9 -9
  272. package/clis/douyin/search.js +3 -3
  273. package/clis/douyin/videos.js +1 -1
  274. package/clis/eastmoney/_secid.js +1 -1
  275. package/clis/eastmoney/announcement.js +1 -1
  276. package/clis/eastmoney/article.js +1 -1
  277. package/clis/eastmoney/convertible.js +1 -1
  278. package/clis/eastmoney/etf.js +1 -1
  279. package/clis/eastmoney/holders.js +1 -1
  280. package/clis/eastmoney/index-board.js +1 -1
  281. package/clis/eastmoney/kline.js +1 -1
  282. package/clis/eastmoney/kuaixun.js +1 -1
  283. package/clis/eastmoney/longhu.js +1 -1
  284. package/clis/eastmoney/money-flow.js +1 -1
  285. package/clis/eastmoney/northbound.js +1 -1
  286. package/clis/eastmoney/quote.js +1 -1
  287. package/clis/eastmoney/rank.js +1 -1
  288. package/clis/eastmoney/sectors.js +1 -1
  289. package/clis/endoflife/product.js +1 -1
  290. package/clis/endoflife/utils.js +1 -1
  291. package/clis/facebook/comment.js +8 -8
  292. package/clis/facebook/feed.js +4 -4
  293. package/clis/facebook/like.js +5 -5
  294. package/clis/facebook/notifications.js +3 -3
  295. package/clis/facebook/post.js +11 -11
  296. package/clis/facebook/search.js +3 -3
  297. package/clis/flathub/app.js +1 -1
  298. package/clis/flathub/search.js +1 -1
  299. package/clis/flathub/utils.js +1 -1
  300. package/clis/flomo/memos.js +1 -1
  301. package/clis/gemini/deep-research-result.js +4 -4
  302. package/clis/gemini/deep-research.js +1 -1
  303. package/clis/gemini/detail.js +1 -1
  304. package/clis/gemini/history.js +1 -1
  305. package/clis/gemini/image.js +2 -2
  306. package/clis/gemini/status.js +1 -1
  307. package/clis/gemini/utils.js +43 -43
  308. package/clis/geogebra/hexagon.js +1 -1
  309. package/clis/geogebra/info.js +3 -3
  310. package/clis/geogebra/triangle.js +1 -1
  311. package/clis/geogebra/utils.js +11 -11
  312. package/clis/ghost/login.js +1 -1
  313. package/clis/ghost/shared.js +2 -2
  314. package/clis/gitee/auth.js +2 -2
  315. package/clis/github-trending/repos.js +1 -1
  316. package/clis/google/news.js +1 -1
  317. package/clis/google/search.js +2 -2
  318. package/clis/google/suggest.js +1 -1
  319. package/clis/google/trends.js +1 -1
  320. package/clis/google/utils.js +1 -1
  321. package/clis/goproxy/module.js +1 -1
  322. package/clis/goproxy/utils.js +1 -1
  323. package/clis/goproxy/versions.js +1 -1
  324. package/clis/gov-policy/recent.js +2 -2
  325. package/clis/gov-policy/search.js +2 -2
  326. package/clis/grok/ask.js +1 -1
  327. package/clis/grok/detail.js +1 -1
  328. package/clis/grok/image.js +8 -8
  329. package/clis/grok/pin.js +1 -1
  330. package/clis/grok/send.js +1 -1
  331. package/clis/grok/status.js +1 -1
  332. package/clis/grok/utils.js +21 -21
  333. package/clis/guazi/browse.js +1 -1
  334. package/clis/guazi/car.js +1 -1
  335. package/clis/guazi/utils.js +1 -1
  336. package/clis/hackernews/auth.js +2 -2
  337. package/clis/hackernews/comment.js +8 -8
  338. package/clis/hackernews/read.js +7 -7
  339. package/clis/hackernews/submit.js +7 -7
  340. package/clis/hashnode/auth.js +3 -3
  341. package/clis/hashnode/publish.js +14 -14
  342. package/clis/hf/auth.js +2 -2
  343. package/clis/hf/models.js +1 -1
  344. package/clis/hf/paper.js +1 -1
  345. package/clis/hf/spaces.js +1 -1
  346. package/clis/hf/top.js +1 -1
  347. package/clis/homebrew/cask.js +1 -1
  348. package/clis/homebrew/formula.js +1 -1
  349. package/clis/homebrew/popular.js +1 -1
  350. package/clis/homebrew/utils.js +1 -1
  351. package/clis/huodongxing/events.js +1 -1
  352. package/clis/hupu/detail.js +4 -4
  353. package/clis/hupu/hot.js +3 -3
  354. package/clis/hupu/reply.js +1 -1
  355. package/clis/hupu/search.js +1 -1
  356. package/clis/hupu/unlike.js +1 -1
  357. package/clis/hupu/utils.js +10 -10
  358. package/clis/imdb/person.js +2 -2
  359. package/clis/imdb/reviews.js +3 -3
  360. package/clis/imdb/search.js +2 -2
  361. package/clis/imdb/title.js +1 -1
  362. package/clis/imdb/top.js +1 -1
  363. package/clis/imdb/trending.js +1 -1
  364. package/clis/imdb/utils.js +13 -13
  365. package/clis/imooc/article.js +6 -6
  366. package/clis/imooc/login.js +1 -1
  367. package/clis/imooc/whoami.js +1 -1
  368. package/clis/indeed/job.js +2 -2
  369. package/clis/indeed/search.js +2 -2
  370. package/clis/indeed/utils.js +1 -1
  371. package/clis/infoq/article.js +2 -2
  372. package/clis/infoq/login.js +1 -1
  373. package/clis/infoq/whoami.js +1 -1
  374. package/clis/instagram/_shared/private-publish.js +4 -4
  375. package/clis/instagram/_shared/protocol-capture.js +9 -9
  376. package/clis/instagram/detail.js +3 -3
  377. package/clis/instagram/post.js +25 -25
  378. package/clis/instagram/reel.js +18 -18
  379. package/clis/instagram/story.js +4 -4
  380. package/clis/instagram/user.js +2 -2
  381. package/clis/jd/item.js +65 -65
  382. package/clis/jianshu/article.js +1 -1
  383. package/clis/jianshu/login.js +1 -1
  384. package/clis/jianshu/notebooks.js +1 -1
  385. package/clis/jianshu/whoami.js +1 -1
  386. package/clis/jianyu/search.js +6 -6
  387. package/clis/jianyu/shared/procurement-contract.js +1 -1
  388. package/clis/jike/api.js +6 -6
  389. package/clis/jike/auth.js +3 -3
  390. package/clis/jike/comment.js +1 -1
  391. package/clis/jike/create.js +6 -6
  392. package/clis/jike/feed.js +3 -3
  393. package/clis/jike/like.js +1 -1
  394. package/clis/jike/notifications.js +3 -3
  395. package/clis/jike/repost.js +13 -13
  396. package/clis/jike/search.js +3 -3
  397. package/clis/jimeng/auth.js +2 -2
  398. package/clis/jimeng/generate.js +10 -10
  399. package/clis/jira/shared.js +1 -1
  400. package/clis/juejin/article.js +4 -4
  401. package/clis/juejin/categories.js +1 -1
  402. package/clis/juejin/hot.js +1 -1
  403. package/clis/juejin/login.js +1 -1
  404. package/clis/juejin/recommend.js +1 -1
  405. package/clis/juejin/stats.js +3 -3
  406. package/clis/juejin/tags.js +1 -1
  407. package/clis/juejin/utils.js +1 -1
  408. package/clis/juejin/whoami.js +1 -1
  409. package/clis/ke/utils.js +4 -4
  410. package/clis/kimi/_utils.js +7 -7
  411. package/clis/kimi/audit-extras.js +14 -14
  412. package/clis/kimi/auth.js +3 -3
  413. package/clis/kimi/chat.js +15 -15
  414. package/clis/kimi/storage.js +5 -5
  415. package/clis/kimi/ui.js +13 -13
  416. package/clis/kimi/usage.js +3 -3
  417. package/clis/kuaishou/auth.js +1 -1
  418. package/clis/kuaishou/publish.js +6 -6
  419. package/clis/lesswrong/_helpers.js +5 -5
  420. package/clis/lesswrong/comments.js +5 -5
  421. package/clis/lichess/top.js +1 -1
  422. package/clis/lichess/user.js +1 -1
  423. package/clis/lichess/utils.js +1 -1
  424. package/clis/linkedin/comment.js +1 -1
  425. package/clis/linkedin/connect.js +11 -11
  426. package/clis/linkedin/create.js +5 -5
  427. package/clis/linkedin/follow.js +1 -1
  428. package/clis/linkedin/inbox.js +1 -1
  429. package/clis/linkedin/job-detail.js +3 -3
  430. package/clis/linkedin/like.js +1 -1
  431. package/clis/linkedin/notifications.js +1 -1
  432. package/clis/linkedin/people-search.js +1 -1
  433. package/clis/linkedin/post-comments.js +1 -1
  434. package/clis/linkedin/post-detail.js +1 -1
  435. package/clis/linkedin/profile-analytics.js +1 -1
  436. package/clis/linkedin/profile-api.js +13 -13
  437. package/clis/linkedin/profile-experience.js +1 -1
  438. package/clis/linkedin/profile-projects.js +1 -1
  439. package/clis/linkedin/profile-read.js +3 -3
  440. package/clis/linkedin/reply.js +1 -1
  441. package/clis/linkedin/repost.js +1 -1
  442. package/clis/linkedin/safe-send.js +8 -8
  443. package/clis/linkedin/salesnav-inbox.js +5 -5
  444. package/clis/linkedin/salesnav-message.js +3 -3
  445. package/clis/linkedin/salesnav-search.js +4 -4
  446. package/clis/linkedin/salesnav-thread.js +1 -1
  447. package/clis/linkedin/search-api.js +3 -3
  448. package/clis/linkedin/search.js +8 -8
  449. package/clis/linkedin/social-api.js +31 -31
  450. package/clis/linkedin/timeline.js +3 -3
  451. package/clis/linkedin-learning/search.js +2 -2
  452. package/clis/linkedin-learning/trending.js +2 -2
  453. package/clis/linux-do/feed.js +4 -4
  454. package/clis/linux-do/topic-content.js +8 -8
  455. package/clis/lobsters/domain.js +1 -1
  456. package/clis/lobsters/read.js +7 -7
  457. package/clis/maimai/auth.js +2 -2
  458. package/clis/maimai/search-talents.js +4 -4
  459. package/clis/manus/_utils.js +1 -1
  460. package/clis/mastodon/login.js +1 -1
  461. package/clis/mastodon/post.js +1 -1
  462. package/clis/mastodon/shared.js +12 -12
  463. package/clis/mastodon/whoami.js +1 -1
  464. package/clis/maven/artifact.js +1 -1
  465. package/clis/maven/search.js +1 -1
  466. package/clis/maven/utils.js +1 -1
  467. package/clis/mdn/search.js +1 -1
  468. package/clis/medium/article.js +5 -5
  469. package/clis/medium/login.js +1 -1
  470. package/clis/medium/stats.js +3 -3
  471. package/clis/medium/tag.js +1 -1
  472. package/clis/medium/whoami.js +1 -1
  473. package/clis/mubu/notes.js +1 -1
  474. package/clis/mubu/utils.js +15 -15
  475. package/clis/note/auth.js +2 -2
  476. package/clis/note/note-utils.js +2 -2
  477. package/clis/note/publish.js +8 -8
  478. package/clis/notebooklm/add-source.js +8 -8
  479. package/clis/notebooklm/create.js +1 -1
  480. package/clis/notebooklm/generate-slides.js +1 -1
  481. package/clis/notebooklm/notes-get.js +1 -1
  482. package/clis/notebooklm/rpc.js +8 -8
  483. package/clis/notebooklm/source-fulltext.js +1 -1
  484. package/clis/notebooklm/utils.js +10 -10
  485. package/clis/nowcoder/auth.js +2 -2
  486. package/clis/nowcoder/comment.js +1 -1
  487. package/clis/nowcoder/comments.js +1 -1
  488. package/clis/nowcoder/dm-list.js +1 -1
  489. package/clis/nowcoder/dm-read.js +1 -1
  490. package/clis/nowcoder/dm-send.js +1 -1
  491. package/clis/nowcoder/drafts.js +1 -1
  492. package/clis/nowcoder/inbox.js +1 -1
  493. package/clis/nowcoder/like.js +1 -1
  494. package/clis/nowcoder/my.js +1 -1
  495. package/clis/nowcoder/post.js +1 -1
  496. package/clis/nowcoder/utils.js +13 -13
  497. package/clis/npm/downloads.js +1 -1
  498. package/clis/npm/package.js +1 -1
  499. package/clis/npm/search.js +1 -1
  500. package/clis/npm/utils.js +1 -1
  501. package/clis/nuget/package.js +1 -1
  502. package/clis/nuget/search.js +1 -1
  503. package/clis/nuget/utils.js +1 -1
  504. package/clis/nvd/cve.js +1 -1
  505. package/clis/oeis/search.js +1 -1
  506. package/clis/oeis/sequence.js +1 -1
  507. package/clis/oeis/utils.js +1 -1
  508. package/clis/ones/common.js +6 -6
  509. package/clis/ones/enrich-tasks.js +1 -1
  510. package/clis/ones/my-tasks.js +1 -1
  511. package/clis/ones/resolve-labels.js +1 -1
  512. package/clis/ones/task-helpers.js +1 -1
  513. package/clis/ones/task.js +1 -1
  514. package/clis/ones/worklog.js +7 -7
  515. package/clis/openalex/search.js +1 -1
  516. package/clis/openalex/utils.js +1 -1
  517. package/clis/openalex/work.js +1 -1
  518. package/clis/openfda/drug-label.js +1 -1
  519. package/clis/openfda/food-recall.js +1 -1
  520. package/clis/openfda/utils.js +1 -1
  521. package/clis/openreview/author.js +1 -1
  522. package/clis/openreview/paper.js +1 -1
  523. package/clis/openreview/reviews.js +3 -3
  524. package/clis/openreview/search.js +1 -1
  525. package/clis/openreview/utils.js +1 -1
  526. package/clis/openreview/venue.js +1 -1
  527. package/clis/oschina/article.js +1 -1
  528. package/clis/oschina/catalogs.js +1 -1
  529. package/clis/oschina/login.js +1 -1
  530. package/clis/oschina/stats.js +6 -6
  531. package/clis/oschina/whoami.js +1 -1
  532. package/clis/osv/query.js +1 -1
  533. package/clis/osv/utils.js +1 -1
  534. package/clis/osv/vulnerability.js +1 -1
  535. package/clis/packagist/package.js +1 -1
  536. package/clis/packagist/search.js +1 -1
  537. package/clis/packagist/utils.js +1 -1
  538. package/clis/pinterest/api.js +1 -1
  539. package/clis/pinterest/auth.js +1 -1
  540. package/clis/pinterest/boards.js +1 -1
  541. package/clis/pinterest/client.js +6 -6
  542. package/clis/pinterest/publish.js +5 -5
  543. package/clis/pixiv/auth.js +2 -2
  544. package/clis/pixiv/download.js +1 -1
  545. package/clis/pixiv/illusts.js +1 -1
  546. package/clis/pixiv/search.js +1 -1
  547. package/clis/pixiv/utils.js +3 -3
  548. package/clis/powerchina/auth.js +2 -2
  549. package/clis/powerchina/search.js +1 -1
  550. package/clis/producthunt/browse.js +2 -2
  551. package/clis/producthunt/hot.js +2 -2
  552. package/clis/producthunt/posts.js +1 -1
  553. package/clis/producthunt/today.js +1 -1
  554. package/clis/producthunt/utils.js +1 -1
  555. package/clis/pypi/downloads.js +1 -1
  556. package/clis/pypi/package.js +1 -1
  557. package/clis/pypi/utils.js +1 -1
  558. package/clis/qiita/auth.js +1 -1
  559. package/clis/qiita/gql.js +6 -6
  560. package/clis/qiita/publish.js +4 -4
  561. package/clis/qiita/stats.js +4 -4
  562. package/clis/qoder/_utils.js +16 -16
  563. package/clis/qoder/composer.js +1 -1
  564. package/clis/qoder/quest.js +1 -1
  565. package/clis/qoder/ui.js +14 -14
  566. package/clis/quark/auth.js +2 -2
  567. package/clis/quark/utils.js +2 -2
  568. package/clis/quora/answer-comments.js +3 -3
  569. package/clis/quora/create-answer.js +4 -4
  570. package/clis/quora/create-question.js +3 -3
  571. package/clis/quora/shared.js +17 -17
  572. package/clis/quora/whoami.js +1 -1
  573. package/clis/qwen/ask.js +1 -1
  574. package/clis/qwen/auth.js +3 -3
  575. package/clis/qwen/detail.js +1 -1
  576. package/clis/qwen/image.js +5 -5
  577. package/clis/qwen/status.js +1 -1
  578. package/clis/qwen/utils.js +16 -16
  579. package/clis/reddit/home.js +3 -3
  580. package/clis/reddit/read.js +10 -10
  581. package/clis/reddit/reply.js +4 -4
  582. package/clis/reddit/submit.js +11 -11
  583. package/clis/reddit/subreddit-info.js +3 -3
  584. package/clis/reddit/subscribed.js +4 -4
  585. package/clis/reddit/whoami.js +2 -2
  586. package/clis/rednote/comments.js +1 -1
  587. package/clis/rednote/download.js +1 -1
  588. package/clis/rednote/feed.js +1 -1
  589. package/clis/rednote/note.js +1 -1
  590. package/clis/rednote/notifications.js +2 -2
  591. package/clis/rednote/search.js +2 -2
  592. package/clis/rest-countries/country.js +1 -1
  593. package/clis/rest-countries/region.js +1 -1
  594. package/clis/rest-countries/utils.js +1 -1
  595. package/clis/reuters/article-detail.js +1 -1
  596. package/clis/reuters/auth.js +3 -3
  597. package/clis/reuters/search.js +1 -1
  598. package/clis/reuters/utils.js +4 -4
  599. package/clis/rfc/rfc.js +1 -1
  600. package/clis/rfc/utils.js +1 -1
  601. package/clis/rubygems/gem.js +1 -1
  602. package/clis/rubygems/search.js +1 -1
  603. package/clis/rubygems/utils.js +1 -1
  604. package/clis/segmentfault/article.js +3 -3
  605. package/clis/segmentfault/channels.js +1 -1
  606. package/clis/segmentfault/login.js +1 -1
  607. package/clis/segmentfault/stats.js +4 -4
  608. package/clis/segmentfault/tags.js +1 -1
  609. package/clis/segmentfault/whoami.js +1 -1
  610. package/clis/semanticscholar/citations.js +1 -1
  611. package/clis/semanticscholar/paper.js +1 -1
  612. package/clis/semanticscholar/recommendations.js +1 -1
  613. package/clis/semanticscholar/search.js +1 -1
  614. package/clis/semanticscholar/utils.js +1 -1
  615. package/clis/sinafinance/news.js +1 -1
  616. package/clis/sinafinance/stock-rank.js +1 -1
  617. package/clis/sinafinance/stock.js +1 -1
  618. package/clis/slock/attachment-download.js +1 -1
  619. package/clis/slock/attachment-upload.js +7 -7
  620. package/clis/slock/attachment-url.js +1 -1
  621. package/clis/slock/auth-verify.js +1 -1
  622. package/clis/slock/bookmark-add.js +1 -1
  623. package/clis/slock/bookmark-remove.js +1 -1
  624. package/clis/slock/channel-action.js +1 -1
  625. package/clis/slock/channel-create.js +1 -1
  626. package/clis/slock/channel-files.js +1 -1
  627. package/clis/slock/channel-list.js +1 -1
  628. package/clis/slock/channel-mark.js +1 -1
  629. package/clis/slock/channel-members.js +1 -1
  630. package/clis/slock/channel-unarchive.js +1 -1
  631. package/clis/slock/dm-list.js +1 -1
  632. package/clis/slock/errors.js +1 -1
  633. package/clis/slock/in-page.js +28 -28
  634. package/clis/slock/inbox-done.js +5 -5
  635. package/clis/slock/inbox.js +1 -1
  636. package/clis/slock/message-read.js +22 -22
  637. package/clis/slock/message-search.js +10 -10
  638. package/clis/slock/message-send.js +25 -25
  639. package/clis/slock/reaction-add.js +1 -1
  640. package/clis/slock/reaction-remove.js +1 -1
  641. package/clis/slock/resolve.js +1 -1
  642. package/clis/slock/server-list.js +2 -2
  643. package/clis/slock/task-claim.js +4 -4
  644. package/clis/slock/task-convert.js +13 -13
  645. package/clis/slock/task-create.js +1 -1
  646. package/clis/slock/task-delete.js +5 -5
  647. package/clis/slock/task-get.js +5 -5
  648. package/clis/slock/task-list-server.js +4 -4
  649. package/clis/slock/task-list.js +5 -5
  650. package/clis/slock/task-status.js +3 -3
  651. package/clis/slock/task-unclaim.js +3 -3
  652. package/clis/slock/thread-follow.js +1 -1
  653. package/clis/slock/thread-state.js +1 -1
  654. package/clis/slock/unread-summary.js +5 -5
  655. package/clis/slock/whoami.js +1 -1
  656. package/clis/smzdm/search.js +3 -3
  657. package/clis/sohu/article.js +1 -1
  658. package/clis/sohu/attributes.js +1 -1
  659. package/clis/sohu/categories.js +1 -1
  660. package/clis/sohu/channels.js +1 -1
  661. package/clis/sohu/columns.js +1 -1
  662. package/clis/sohu/login.js +1 -1
  663. package/clis/sohu/stats.js +3 -3
  664. package/clis/sohu/topics.js +1 -1
  665. package/clis/sohu/whoami.js +1 -1
  666. package/clis/spotify/spotify.js +1 -1
  667. package/clis/stackoverflow/read.js +6 -6
  668. package/clis/stackoverflow/related.js +1 -1
  669. package/clis/stackoverflow/tag.js +1 -1
  670. package/clis/stackoverflow/user.js +1 -1
  671. package/clis/stackoverflow/utils.js +1 -1
  672. package/clis/steam/app.js +1 -1
  673. package/clis/steam/search.js +1 -1
  674. package/clis/steam/utils.js +1 -1
  675. package/clis/substack/auth.js +2 -2
  676. package/clis/substack/post-utils.js +2 -2
  677. package/clis/substack/publish.js +5 -5
  678. package/clis/suno/auth.js +2 -2
  679. package/clis/suno/download.js +5 -5
  680. package/clis/suno/generate.js +3 -3
  681. package/clis/suno/list.js +1 -1
  682. package/clis/suno/status.js +1 -1
  683. package/clis/suno/utils.js +29 -29
  684. package/clis/telegram/send.js +7 -7
  685. package/clis/telegram/shared.js +2 -2
  686. package/clis/telegram/whoami.js +1 -1
  687. package/clis/test-utils.js +1 -1
  688. package/clis/threads/post.js +23 -23
  689. package/clis/threads/shared.js +3 -3
  690. package/clis/threads/whoami.js +1 -1
  691. package/clis/tieba/hot.js +3 -3
  692. package/clis/tieba/posts.js +1 -1
  693. package/clis/tieba/read.js +2 -2
  694. package/clis/tieba/search.js +3 -3
  695. package/clis/tieba/utils.js +1 -1
  696. package/clis/tiktok/comment.js +2 -2
  697. package/clis/tiktok/creator-videos.js +3 -3
  698. package/clis/tiktok/explore.js +3 -3
  699. package/clis/tiktok/follow.js +8 -8
  700. package/clis/tiktok/following.js +4 -4
  701. package/clis/tiktok/friends.js +7 -7
  702. package/clis/tiktok/live.js +3 -3
  703. package/clis/tiktok/notifications.js +6 -6
  704. package/clis/tiktok/publish.js +17 -17
  705. package/clis/tiktok/unfollow.js +4 -4
  706. package/clis/tiktok/user.js +2 -2
  707. package/clis/tiktok/utils.js +1 -1
  708. package/clis/toutiao/article.js +1 -1
  709. package/clis/toutiao/articles.js +2 -2
  710. package/clis/toutiao/auth.js +2 -2
  711. package/clis/toutiao/hot.js +1 -1
  712. package/clis/toutiao/recommend.js +1 -1
  713. package/clis/toutiao/utils.js +2 -2
  714. package/clis/trae-solo/_actions.js +4 -4
  715. package/clis/trae-solo/_fs.js +5 -5
  716. package/clis/trae-solo/_state.js +2 -2
  717. package/clis/trae-solo/automation.js +4 -4
  718. package/clis/trae-solo/mode.js +4 -4
  719. package/clis/trae-solo/model.js +4 -4
  720. package/clis/trae-solo/renderer-storage.js +4 -4
  721. package/clis/trae-solo/settings.js +1 -1
  722. package/clis/trae-solo/skill-fs.js +1 -1
  723. package/clis/trae-solo/skill.js +12 -12
  724. package/clis/trae-solo/state-fs.js +2 -2
  725. package/clis/trae-solo/task-fs.js +5 -5
  726. package/clis/trae-solo/workspaces-fs.js +1 -1
  727. package/clis/tumblr/auth.js +2 -2
  728. package/clis/tumblr/publish.js +3 -3
  729. package/clis/tvmaze/search.js +1 -1
  730. package/clis/tvmaze/show.js +1 -1
  731. package/clis/tvmaze/utils.js +1 -1
  732. package/clis/twitter/accept.js +7 -7
  733. package/clis/twitter/article.js +7 -7
  734. package/clis/twitter/bookmark-folder.js +3 -3
  735. package/clis/twitter/bookmark-folders.js +3 -3
  736. package/clis/twitter/bookmarks.js +4 -4
  737. package/clis/twitter/delete.js +5 -5
  738. package/clis/twitter/device-follow.js +3 -3
  739. package/clis/twitter/dm-list.js +1 -1
  740. package/clis/twitter/dm-read.js +1 -1
  741. package/clis/twitter/dm-send.js +5 -5
  742. package/clis/twitter/dm-shared.js +3 -3
  743. package/clis/twitter/download.js +6 -6
  744. package/clis/twitter/followers.js +5 -5
  745. package/clis/twitter/following.js +2 -2
  746. package/clis/twitter/like.js +3 -3
  747. package/clis/twitter/likes.js +8 -8
  748. package/clis/twitter/list-add-core.js +9 -9
  749. package/clis/twitter/list-create.js +5 -5
  750. package/clis/twitter/list-remove-core.js +9 -9
  751. package/clis/twitter/list-tweets.js +7 -7
  752. package/clis/twitter/lists.js +6 -6
  753. package/clis/twitter/notifications.js +2 -2
  754. package/clis/twitter/post.js +24 -24
  755. package/clis/twitter/profile.js +7 -7
  756. package/clis/twitter/quote.js +7 -7
  757. package/clis/twitter/reply-dm.js +7 -7
  758. package/clis/twitter/reply.js +12 -12
  759. package/clis/twitter/retweet.js +3 -3
  760. package/clis/twitter/scheduled-delete.js +3 -3
  761. package/clis/twitter/scheduled-list.js +2 -2
  762. package/clis/twitter/scheduled-utils.js +3 -3
  763. package/clis/twitter/search.js +5 -5
  764. package/clis/twitter/shared.js +6 -6
  765. package/clis/twitter/thread.js +4 -4
  766. package/clis/twitter/timeline.js +3 -3
  767. package/clis/twitter/trending.js +2 -2
  768. package/clis/twitter/tweets.js +11 -11
  769. package/clis/twitter/unlike.js +3 -3
  770. package/clis/twitter/unretweet.js +3 -3
  771. package/clis/twitter/utils.js +6 -6
  772. package/clis/upwork/detail.js +2 -2
  773. package/clis/upwork/feed.js +2 -2
  774. package/clis/upwork/search.js +2 -2
  775. package/clis/upwork/utils.js +1 -1
  776. package/clis/v2ex/auth.js +2 -2
  777. package/clis/v2ex/daily.js +3 -3
  778. package/clis/v2ex/me.js +2 -2
  779. package/clis/v2ex/notifications.js +2 -2
  780. package/clis/vk/post.js +1 -1
  781. package/clis/vk/shared.js +2 -2
  782. package/clis/vk/whoami.js +1 -1
  783. package/clis/web/read.js +8 -8
  784. package/clis/wechat-channels/auth.js +2 -2
  785. package/clis/wechat-channels/publish.js +30 -30
  786. package/clis/weibo/article.js +1 -1
  787. package/clis/weibo/auth.js +3 -3
  788. package/clis/weibo/comments.js +1 -1
  789. package/clis/weibo/delete.js +2 -2
  790. package/clis/weibo/feed.js +3 -3
  791. package/clis/weibo/hot.js +1 -1
  792. package/clis/weibo/publish.js +10 -10
  793. package/clis/weibo/search.js +2 -2
  794. package/clis/weibo/user-posts.js +3 -3
  795. package/clis/weibo/user.js +2 -2
  796. package/clis/weibo/utils.js +3 -3
  797. package/clis/weixin/article.js +1 -1
  798. package/clis/weixin/create-draft.js +26 -26
  799. package/clis/weixin/download.js +2 -2
  800. package/clis/weixin/login.js +1 -1
  801. package/clis/weixin/search.js +2 -2
  802. package/clis/weixin/stats.js +3 -3
  803. package/clis/weixin/whoami.js +1 -1
  804. package/clis/weread/ai-outline.js +2 -2
  805. package/clis/weread/book-search.js +2 -2
  806. package/clis/weread/book.js +2 -2
  807. package/clis/weread/notebooks.js +1 -1
  808. package/clis/weread/search.js +1 -1
  809. package/clis/weread/shelf.js +1 -1
  810. package/clis/weread/utils.js +6 -6
  811. package/clis/weread-official/book.js +1 -1
  812. package/clis/weread-official/discover.js +1 -1
  813. package/clis/weread-official/list-apis.js +1 -1
  814. package/clis/weread-official/notes.js +1 -1
  815. package/clis/weread-official/readdata.js +1 -1
  816. package/clis/weread-official/review.js +1 -1
  817. package/clis/weread-official/search.js +1 -1
  818. package/clis/weread-official/shelf.js +1 -1
  819. package/clis/weread-official/utils.js +1 -1
  820. package/clis/wikidata/entity.js +1 -1
  821. package/clis/wikidata/search.js +1 -1
  822. package/clis/wikidata/utils.js +1 -1
  823. package/clis/wikipedia/page.js +1 -1
  824. package/clis/wikipedia/trending.js +1 -1
  825. package/clis/wikipedia/utils.js +1 -1
  826. package/clis/wordpress/login.js +1 -1
  827. package/clis/wordpress/publish.js +1 -1
  828. package/clis/wordpress/shared.js +3 -3
  829. package/clis/wordpress/whoami.js +1 -1
  830. package/clis/woshipm/article.js +1 -1
  831. package/clis/woshipm/login.js +1 -1
  832. package/clis/woshipm/stats.js +4 -4
  833. package/clis/woshipm/whoami.js +1 -1
  834. package/clis/wttr/current.js +1 -1
  835. package/clis/wttr/forecast.js +1 -1
  836. package/clis/wttr/utils.js +1 -1
  837. package/clis/xianyu/collect.js +1 -1
  838. package/clis/xianyu/inbox.js +1 -1
  839. package/clis/xianyu/item-stats.js +2 -2
  840. package/clis/xianyu/location.js +1 -1
  841. package/clis/xianyu/manage.js +1 -1
  842. package/clis/xianyu/messages.js +1 -1
  843. package/clis/xianyu/mtop.js +5 -5
  844. package/clis/xianyu/order.js +1 -1
  845. package/clis/xianyu/promote-stats.js +2 -2
  846. package/clis/xianyu/publish.js +17 -17
  847. package/clis/xianyu/rate.js +1 -1
  848. package/clis/xianyu/reply.js +1 -1
  849. package/clis/xianyu/search.js +8 -8
  850. package/clis/xianyu/seller-data.js +1 -1
  851. package/clis/xianyu/seller-list.js +1 -1
  852. package/clis/xianyu/user.js +1 -1
  853. package/clis/xiaoe/catalog.js +2 -2
  854. package/clis/xiaoe/content.js +2 -2
  855. package/clis/xiaoe/courses.js +2 -2
  856. package/clis/xiaohongshu/ask.js +6 -6
  857. package/clis/xiaohongshu/comments.js +6 -6
  858. package/clis/xiaohongshu/creator-note-detail.js +7 -7
  859. package/clis/xiaohongshu/creator-notes-summary.js +1 -1
  860. package/clis/xiaohongshu/creator-notes.js +13 -13
  861. package/clis/xiaohongshu/creator-profile.js +2 -2
  862. package/clis/xiaohongshu/creator-stats.js +2 -2
  863. package/clis/xiaohongshu/delete-note.js +7 -7
  864. package/clis/xiaohongshu/download.js +4 -4
  865. package/clis/xiaohongshu/feed.js +2 -2
  866. package/clis/xiaohongshu/follow.js +3 -3
  867. package/clis/xiaohongshu/human.js +3 -3
  868. package/clis/xiaohongshu/note-helpers.js +1 -1
  869. package/clis/xiaohongshu/note.js +2 -2
  870. package/clis/xiaohongshu/notifications.js +1 -1
  871. package/clis/xiaohongshu/publish-video.js +8 -8
  872. package/clis/xiaohongshu/publish.js +59 -59
  873. package/clis/xiaohongshu/search.js +8 -8
  874. package/clis/xiaohongshu/unfollow.js +4 -4
  875. package/clis/xiaohongshu/user-helpers.js +1 -1
  876. package/clis/xiaohongshu/user.js +2 -2
  877. package/clis/xiaoyuzhou/auth.js +3 -3
  878. package/clis/xiaoyuzhou/download.js +1 -1
  879. package/clis/xiaoyuzhou/utils.js +1 -1
  880. package/clis/xueqiu/article.js +4 -4
  881. package/clis/xueqiu/comments.js +4 -4
  882. package/clis/xueqiu/danjuan-utils.js +4 -4
  883. package/clis/xueqiu/earnings-date.js +1 -1
  884. package/clis/xueqiu/events.js +3 -3
  885. package/clis/xueqiu/hashtags.js +3 -3
  886. package/clis/xueqiu/stocks.js +3 -3
  887. package/clis/xueqiu/users.js +3 -3
  888. package/clis/xueqiu/utils.js +3 -3
  889. package/clis/yahoo-finance/quote.js +1 -1
  890. package/clis/yollomi/background.js +1 -1
  891. package/clis/yollomi/edit.js +1 -1
  892. package/clis/yollomi/face-swap.js +1 -1
  893. package/clis/yollomi/generate.js +1 -1
  894. package/clis/yollomi/object-remover.js +1 -1
  895. package/clis/yollomi/remove-bg.js +1 -1
  896. package/clis/yollomi/restore.js +1 -1
  897. package/clis/yollomi/try-on.js +1 -1
  898. package/clis/yollomi/upload.js +4 -4
  899. package/clis/yollomi/upscale.js +1 -1
  900. package/clis/yollomi/utils.js +4 -4
  901. package/clis/yollomi/video.js +1 -1
  902. package/clis/youtube/channel.js +4 -4
  903. package/clis/youtube/feed.js +2 -2
  904. package/clis/youtube/like.js +5 -5
  905. package/clis/youtube/playlist.js +7 -7
  906. package/clis/youtube/publish.js +11 -11
  907. package/clis/youtube/search.js +3 -3
  908. package/clis/youtube/subscribe.js +7 -7
  909. package/clis/youtube/subscriptions.js +1 -1
  910. package/clis/youtube/transcript-group.js +2 -2
  911. package/clis/youtube/transcript.js +13 -13
  912. package/clis/youtube/unlike.js +5 -5
  913. package/clis/youtube/unsubscribe.js +7 -7
  914. package/clis/youtube/utils.js +3 -3
  915. package/clis/youtube/video.js +4 -4
  916. package/clis/youtube/watch-later.js +2 -2
  917. package/clis/yuanbao/ask.js +18 -18
  918. package/clis/yuanbao/detail.js +1 -1
  919. package/clis/yuanbao/read.js +1 -1
  920. package/clis/yuanbao/shared.js +9 -9
  921. package/clis/yuanbao/status.js +1 -1
  922. package/clis/yuque/article.js +1 -1
  923. package/clis/yuque/whoami.js +1 -1
  924. package/clis/zhihu/answer-comments.js +2 -2
  925. package/clis/zhihu/answer-detail.js +3 -3
  926. package/clis/zhihu/answer.js +1 -1
  927. package/clis/zhihu/article-transform.js +1 -1
  928. package/clis/zhihu/article.js +1 -1
  929. package/clis/zhihu/auth.js +2 -2
  930. package/clis/zhihu/collection.js +3 -3
  931. package/clis/zhihu/collections.js +3 -3
  932. package/clis/zhihu/download.js +2 -2
  933. package/clis/zhihu/image-profile.js +6 -6
  934. package/clis/zhihu/paginate.js +3 -3
  935. package/clis/zhihu/pin.js +4 -4
  936. package/clis/zhihu/question.js +3 -3
  937. package/clis/zhihu/recommend.js +3 -3
  938. package/clis/zhihu/search.js +3 -3
  939. package/clis/zhihu/stats.js +3 -3
  940. package/clis/zhihu/user-arg.js +1 -1
  941. package/clis/zhihu/write-shared.js +7 -7
  942. package/clis/zlibrary/utils.js +6 -6
  943. package/clis/zsxq/auth.js +3 -3
  944. package/clis/zsxq/search.js +1 -1
  945. package/clis/zsxq/topic.js +1 -1
  946. package/clis/zsxq/utils.js +5 -5
  947. package/dist/src/adapter-source.js +1 -1
  948. package/dist/src/browser/analyze.js +1 -1
  949. package/dist/src/browser/article-extract.js +2 -2
  950. package/dist/src/browser/ax-snapshot.js +2 -2
  951. package/dist/src/browser/base-page.js +25 -25
  952. package/dist/src/browser/bridge.js +1 -1
  953. package/dist/src/browser/cdp.js +1 -1
  954. package/dist/src/browser/daemon-client.js +1 -1
  955. package/dist/src/browser/daemon-lifecycle.js +7 -7
  956. package/dist/src/browser/dom-helpers.js +35 -35
  957. package/dist/src/browser/dom-snapshot.js +19 -19
  958. package/dist/src/browser/errors.js +3 -3
  959. package/dist/src/browser/extract.js +5 -5
  960. package/dist/src/browser/find.js +13 -13
  961. package/dist/src/browser/fingerprint.js +2 -2
  962. package/dist/src/browser/html-tree.js +6 -6
  963. package/dist/src/browser/managed-chrome.js +1 -1
  964. package/dist/src/browser/network-cache.js +1 -1
  965. package/dist/src/browser/network-key.js +1 -1
  966. package/dist/src/browser/page.js +7 -7
  967. package/dist/src/browser/profile.js +2 -2
  968. package/dist/src/browser/proxy-test.js +8 -8
  969. package/dist/src/browser/shape-filter.js +1 -1
  970. package/dist/src/browser/shape.js +1 -1
  971. package/dist/src/browser/stealth.js +3 -3
  972. package/dist/src/browser/tabs.js +2 -2
  973. package/dist/src/browser/target-errors.js +1 -1
  974. package/dist/src/browser/target-resolver.js +23 -23
  975. package/dist/src/browser/trace.js +2 -2
  976. package/dist/src/browser/utils.js +1 -1
  977. package/dist/src/browser/verify-fixture.js +2 -2
  978. package/dist/src/browser-session-lock.js +1 -1
  979. package/dist/src/build-manifest.js +11 -11
  980. package/dist/src/capabilityRouting.js +1 -1
  981. package/dist/src/cli-argv-preprocess.js +1 -1
  982. package/dist/src/cli.js +32 -32
  983. package/dist/src/commanderAdapter.js +3 -3
  984. package/dist/src/commands/auth.js +3 -3
  985. package/dist/src/commands/daemon.js +1 -1
  986. package/dist/src/completion-fast.js +1 -1
  987. package/dist/src/completion.js +1 -1
  988. package/dist/src/constants.js +1 -1
  989. package/dist/src/convention-audit.js +2 -2
  990. package/dist/src/daemon-utils.js +1 -1
  991. package/dist/src/daemon.js +1 -1
  992. package/dist/src/discovery.js +2 -2
  993. package/dist/src/doctor.js +9 -9
  994. package/dist/src/download/article-download.js +15 -15
  995. package/dist/src/download/index.js +4 -4
  996. package/dist/src/download/media-download.js +1 -1
  997. package/dist/src/download/progress.js +3 -3
  998. package/dist/src/electron-apps.js +1 -1
  999. package/dist/src/errors.js +2 -2
  1000. package/dist/src/execution.js +2 -2
  1001. package/dist/src/external.js +1 -1
  1002. package/dist/src/help.js +8 -8
  1003. package/dist/src/hooks.js +1 -1
  1004. package/dist/src/interceptor.js +21 -21
  1005. package/dist/src/launcher.js +7 -7
  1006. package/dist/src/logger.js +8 -8
  1007. package/dist/src/main.js +7 -7
  1008. package/dist/src/observation/artifact.js +5 -5
  1009. package/dist/src/observation/retention.js +1 -1
  1010. package/dist/src/output.js +2 -2
  1011. package/dist/src/package-paths.js +1 -1
  1012. package/dist/src/pipeline/executor.js +1 -1
  1013. package/dist/src/pipeline/registry.js +1 -1
  1014. package/dist/src/pipeline/steps/browser.js +1 -1
  1015. package/dist/src/pipeline/steps/download.js +1 -1
  1016. package/dist/src/pipeline/steps/fetch.js +6 -6
  1017. package/dist/src/pipeline/steps/intercept.js +1 -1
  1018. package/dist/src/pipeline/steps/tap.js +17 -17
  1019. package/dist/src/pipeline/steps/transform.js +1 -1
  1020. package/dist/src/pipeline/template.js +1 -1
  1021. package/dist/src/plugin-manifest.js +1 -1
  1022. package/dist/src/plugin-scaffold.js +19 -19
  1023. package/dist/src/plugin.js +12 -12
  1024. package/dist/src/rate-limit.js +1 -1
  1025. package/dist/src/registry.js +1 -1
  1026. package/dist/src/runtime-detect.js +1 -1
  1027. package/dist/src/runtime.js +1 -1
  1028. package/dist/src/scripts/framework.js +1 -1
  1029. package/dist/src/scripts/interact.js +1 -1
  1030. package/dist/src/scripts/store.js +1 -1
  1031. package/dist/src/serialization.js +2 -2
  1032. package/dist/src/session-lease.js +1 -1
  1033. package/dist/src/snapshotFormatter.js +2 -2
  1034. package/dist/src/tui.js +12 -12
  1035. package/dist/src/user-runtime.js +1 -1
  1036. package/dist/src/utils.d.ts +12 -0
  1037. package/dist/src/utils.js +4 -4
  1038. package/dist/src/validate.js +2 -2
  1039. package/dist/src/verify.js +2 -2
  1040. package/dist/src/version.js +1 -1
  1041. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import{cli as $,Strategy as K}from"@jackwener/opencli/registry";import{EmptyResultError as O}from"@jackwener/opencli/errors";const P="https://mp.csdn.net/mp_blog/manage/article",U=20,b=`
1
+ import{cli as b,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as f}from"@jackwener/opencli/errors";const h="https://mp.csdn.net/mp_blog/manage/article",y=20,w=`
2
2
  () => {
3
3
  const dateRe = /^\\d{4}-\\d{2}-\\d{2}(\\s|$)/;
4
4
  return Array.from(document.querySelectorAll('.article-list-item-mp')).map((row) => {
@@ -38,7 +38,7 @@ import{cli as $,Strategy as K}from"@jackwener/opencli/registry";import{EmptyResu
38
38
  };
39
39
  }).filter((r) => r.title);
40
40
  }
41
- `,h=`
41
+ `,S=`
42
42
  async () => {
43
43
  for (let i = 0; i < 40; i++) {
44
44
  if (document.querySelector('.article-list-item-mp')) break;
@@ -53,7 +53,7 @@ import{cli as $,Strategy as K}from"@jackwener/opencli/registry";import{EmptyResu
53
53
  bodyHint: (document.body?.innerText || '').slice(0, 200),
54
54
  };
55
55
  }
56
- `,j=`
56
+ `,x=`
57
57
  () => {
58
58
  const next = document.querySelector('[class*=pagination] .btn-next, [class*=pagination] button.next, .el_mcm-pagination .btn-next');
59
59
  if (next && !next.disabled && !next.classList.contains('is-disabled')) {
@@ -68,4 +68,4 @@ import{cli as $,Strategy as K}from"@jackwener/opencli/registry";import{EmptyResu
68
68
  }
69
69
  return false;
70
70
  }
71
- `;function D(q){if(q&&typeof q==="object"&&!Array.isArray(q)&&"session"in q&&"data"in q)return q.data;return q}$({site:"csdn",name:"stats",access:"read",description:"CSDN 文章数据(每篇阅读/点赞/评论/收藏等全量运营指标)",domain:"mp.csdn.net",strategy:K.COOKIE,browser:!0,args:[{name:"limit",type:"number",default:20,help:"返回条数"}],columns:["id","type","title","url","published_at","views","likes","comments","collects","shares","status","badges","edit_url"],func:async(q,Z)=>{const B=Number(Z.limit)||20;await q.goto(P);const x=D(await q.evaluate(h));if(x&&/passport\.csdn\.net/.test(String(x.href||"")))throw Error("未登录 CSDN:页面被重定向到登录页。请先在 Chrome 中登录 mp.csdn.net(可用 ppcli csdn login)。");const F=new Set,v=[];for(let f=1;f<=U&&v.length<B;f++){const H=D(await q.evaluate(b));let Q=0;for(const z of Array.isArray(H)?H:[]){const Y=z.id||`${z.title}@@${z.published_at}`;if(F.has(Y))continue;F.add(Y);v.push(z);Q++}if(v.length>=B)break;const V=D(await q.evaluate(j));if(!V)break;await q.wait(2);if(Q===0&&!V)break}if(v.length===0){if(String(x?.bodyHint||"").includes("登录")||!x?.hasRows)throw Error("未能读取 CSDN 文章列表:可能未登录或页面未加载出内容。请确认已在 Chrome 中登录 mp.csdn.net 后重试。");throw new O("csdn stats","内容管理页没有任何文章。")}return v.slice(0,B).map((f)=>({id:f.id,type:"文章",title:f.title,url:f.url,published_at:f.published_at,views:f.views,likes:f.likes,comments:f.comments,collects:f.collects,shares:"",status:f.status,badges:f.badges,edit_url:f.edit_url}))}});
71
+ `;function l(e){if(e&&typeof e==="object"&&!Array.isArray(e)&&"session"in e&&"data"in e)return e.data;return e}b({site:"csdn",name:"stats",access:"read",description:"CSDN 文章数据(每篇阅读/点赞/评论/收藏等全量运营指标)",domain:"mp.csdn.net",strategy:p.COOKIE,browser:!0,args:[{name:"limit",type:"number",default:20,help:"返回条数"}],columns:["id","type","title","url","published_at","views","likes","comments","collects","shares","status","badges","edit_url"],func:async(e,d)=>{const r=Number(d.limit)||20;await e.goto(h);const s=l(await e.evaluate(S));if(s&&/passport\.csdn\.net/.test(String(s.href||"")))throw Error("未登录 CSDN:页面被重定向到登录页。请先在 Chrome 中登录 mp.csdn.net(可用 ppcli csdn login)。");const o=new Set,i=[];for(let t=1;t<=y&&i.length<r;t++){const a=l(await e.evaluate(w));let c=0;for(const n of Array.isArray(a)?a:[]){const u=n.id||`${n.title}@@${n.published_at}`;if(o.has(u))continue;o.add(u);i.push(n);c++}if(i.length>=r)break;const m=l(await e.evaluate(x));if(!m)break;await e.wait(2);if(c===0&&!m)break}if(i.length===0){if(String(s?.bodyHint||"").includes("登录")||!s?.hasRows)throw Error("未能读取 CSDN 文章列表:可能未登录或页面未加载出内容。请确认已在 Chrome 中登录 mp.csdn.net 后重试。");throw new f("csdn stats","内容管理页没有任何文章。")}return i.slice(0,r).map((t)=>({id:t.id,type:"文章",title:t.title,url:t.url,published_at:t.published_at,views:t.views,likes:t.likes,comments:t.comments,collects:t.collects,shares:"",status:t.status,badges:t.badges,edit_url:t.edit_url}))}});
@@ -1 +1 @@
1
- import{cli as v,Strategy as x}from"@jackwener/opencli/registry";import{checkLogin as z,cookieQuickCheck as A}from"../_shared/article/auth.js";import{csdnProfile as m}from"./article.js";const B={home:m.home,originRe:m.originRe,checkAuth:m.checkAuth};v({site:"csdn",name:"whoami",access:"read",description:"查看当前登录的 CSDN 账号信息",domain:"editor.csdn.net",strategy:x.COOKIE,browser:!0,args:[],columns:["logged_in","user_id","username"],authStatus:{quickCheck:A("https://www.csdn.net",["UserToken"])},func:async(q)=>{const b=await z(q,B);return[{logged_in:b.isAuthenticated,user_id:b.userId||"",username:b.username||""}]}});
1
+ import{cli as i,Strategy as o}from"@jackwener/opencli/registry";import{checkLogin as c,cookieQuickCheck as n}from"../_shared/article/auth.js";import{csdnProfile as r}from"./article.js";const s={home:r.home,originRe:r.originRe,checkAuth:r.checkAuth};i({site:"csdn",name:"whoami",access:"read",description:"查看当前登录的 CSDN 账号信息",domain:"editor.csdn.net",strategy:o.COOKIE,browser:!0,args:[],columns:["logged_in","user_id","username"],authStatus:{quickCheck:n("https://www.csdn.net",["UserToken"])},func:async(t)=>{const e=await c(t,s);return[{logged_in:e.isAuthenticated,user_id:e.userId||"",username:e.username||""}]}});
@@ -1 +1 @@
1
- import{CliError as Y,CommandExecutionError as L}from"@jackwener/opencli/errors";import{cli as P,Strategy as S}from"@jackwener/opencli/registry";import{publishArticle as _}from"../_shared/article/publish.js";export const cto51Profile={home:"https://blog.51cto.com/blogger/publish",outputFormat:"markdown",checkAuth:async(X)=>{try{const G=await(await fetch("https://blog.51cto.com/blogger/publish",{credentials:"include"})).text(),K=G.match(/<li class="more user">\s*<a[^>]*href="([^"]+)"[^>]*>\s*<img[^>]*src="([^"]+)"/);if(!K)return{isAuthenticated:!1,error:"未登录或解析页面失败"};const q=K[1],V=K[2],z=q.split("/").filter(Boolean).pop()||"",Q=G.match(/<meta\s+name="csrf-token"\s+content="([^"]+)"/),U=Q?Q[1]:"";return{isAuthenticated:!0,userId:z,username:z,avatar:V,_csrf:U}}catch(B){return{isAuthenticated:!1,error:String(B&&B.message||B)}}},image:{uploadFn:async(X,B)=>{const G=await fetch(X,{credentials:"omit"});if(!G.ok)throw Error("下载图片失败: "+G.status);const K=await G.blob(),q=K.type||"image/jpeg",V=q.split("/")[1]||"jpeg",z=String(Date.now())+"."+V,U=await(await fetch("https://blog.51cto.com/getUploadSign",{method:"POST",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8","X-Requested-With":"XMLHttpRequest"},body:"upload_type=image"})).json();if(U.code!==0)throw Error(U.msg||"获取上传签名失败");const Z=U.data,v=await(await fetch("https://blog.51cto.com/getUploadConfig",{method:"POST",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8","X-Requested-With":"XMLHttpRequest"},body:new URLSearchParams({upload_type:"image",upload_sign:Z.sign,ext:q,name:z}).toString()})).json();if(v.code!==0)throw Error(v.msg||"获取上传配置失败");const A=v.data,W=A.fields,H=new FormData;H.append("key",W.key);H.append("policy",W.policy);H.append("x-amz-algorithm",W["x-amz-algorithm"]);H.append("x-amz-signature",W["x-amz-signature"]);H.append("x-amz-credential",W["x-amz-credential"]);H.append("X-Amz-Date",W["X-Amz-Date"]);H.append("Content-Type",q);H.append("file",K,z);const F=await fetch(A.url,{method:"POST",body:H});if(!F.ok)throw Error("上传到 COS 失败: "+F.status);return{url:"https://s2.51cto.com/"+W.key}},skip:["s2.51cto.com","51cto.com"]},publish:async(X,B)=>{let G="";try{const $=(await(await fetch("https://blog.51cto.com/blogger/publish",{credentials:"include"})).text()).match(/<meta\s+name="csrf-token"\s+content="([^"]+)"/);if($)G=$[1]}catch(U){}const K=new URLSearchParams({title:X.title,content:X.content,pid:"",cate_id:"",custom_id:"0",tag:"",abstract:"",banner_type:"0",blog_type:"1",copy_code:"1",is_hide:"0",top_time:"0",is_comment:"0",is_old:"0",blog_id:"",did:"",work_id:"",class_id:"",subjectId:"",import_type:"-1",invite_code:"",raffle:"",orig:"",_csrf:G}),q=await fetch("https://blog.51cto.com/blogger/draft",{method:"POST",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8","X-Requested-With":"XMLHttpRequest",Accept:"application/json, text/javascript, */*; q=0.01"},body:K.toString()}),V=await q.text();let z=null;try{z=JSON.parse(V)}catch(U){}if(!q.ok||!z||z.status!==1||!z.data)return{ok:!1,stage:"publish",status:q.status,message:z&&z.msg||V.slice(0,300)};const Q=String(z.data.did);return{ok:!0,id:Q,url:"https://blog.51cto.com/blogger/draft/"+Q,draft:!0}}};P({site:"cto51",name:"article",access:"write",description:"发布 51CTO 博客文章(草稿)。正文默认为 Markdown;图片自动转存到 51CTO 图床(腾讯云 COS)。",domain:"blog.51cto.com",strategy:S.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题"},{name:"text",positional:!0,help:"文章正文(默认 Markdown;传 --html 则视为 HTML)"},{name:"file",help:"正文文件路径(UTF-8,默认 Markdown)"},{name:"html",type:"boolean",help:"将正文视为 HTML 而非 Markdown"},{name:"draft",type:"boolean",help:"(保留参数,51CTO 只支持保存草稿)"},{name:"execute",type:"boolean",help:"真正执行创建/发布。没有此参数时命令拒绝写操作。"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(X,B)=>{if(!X)throw new L("51CTO 文章发布需要浏览器会话");if(!B.execute)throw new Y("INVALID_INPUT","该 51CTO 写操作需要 --execute 参数确认");const G=String(B.title??"").trim();if(!G)throw new Y("INVALID_INPUT","文章标题不能为空");const K=typeof B.text==="string"?B.text:void 0,q=typeof B.file==="string"?B.file:void 0;if(K&&q)throw new Y("INVALID_INPUT","正文与 --file 不能同时使用");let V=K??"";if(q){const{readFile:v,stat:A}=await import("node:fs/promises");let W;try{W=await A(q)}catch{throw new Y("INVALID_INPUT","文件不存在: "+q)}if(!W.isFile())throw new Y("INVALID_INPUT","必须是可读文本文件: "+q);let H;try{H=await v(q)}catch{throw new Y("INVALID_INPUT","无法读取文件: "+q)}try{V=new TextDecoder("utf-8",{fatal:!0}).decode(H)}catch{throw new Y("INVALID_INPUT","文件不是有效 UTF-8 编码: "+q)}}if(!V.trim())throw new Y("INVALID_INPUT","正文内容不能为空");const z=!0,Q=await _(X,{title:G,body:V,format:B.html?"html":"markdown",draftOnly:z,profile:cto51Profile}),U=Q.images.uploaded.length|0,Z=Q.images.failed.length|0;let $="已保存 51CTO 草稿";if(U||Z)$+=`(图片:${U} 张已转存${Z?`,${Z} 张失败`:""})`;return[{status:"success",outcome:"draft",message:$,target_type:"article",target:"",created_target:"article:"+Q.id,created_url:Q.url}]}});
1
+ import{CliError as d,CommandExecutionError as w}from"@jackwener/opencli/errors";import{cli as y,Strategy as b}from"@jackwener/opencli/registry";import{publishArticle as _}from"../_shared/article/publish.js";export const cto51Profile={home:"https://blog.51cto.com/blogger/publish",outputFormat:"markdown",checkAuth:async(p)=>{try{const a=await(await fetch("https://blog.51cto.com/blogger/publish",{credentials:"include"})).text(),s=a.match(/<li class="more user">\s*<a[^>]*href="([^"]+)"[^>]*>\s*<img[^>]*src="([^"]+)"/);if(!s)return{isAuthenticated:!1,error:"未登录或解析页面失败"};const t=s[1],c=s[2],e=t.split("/").filter(Boolean).pop()||"",n=a.match(/<meta\s+name="csrf-token"\s+content="([^"]+)"/),i=n?n[1]:"";return{isAuthenticated:!0,userId:e,username:e,avatar:c,_csrf:i}}catch(o){return{isAuthenticated:!1,error:String(o&&o.message||o)}}},image:{uploadFn:async(p,o)=>{const a=await fetch(p,{credentials:"omit"});if(!a.ok)throw Error("下载图片失败: "+a.status);const s=await a.blob(),t=s.type||"image/jpeg",c=t.split("/")[1]||"jpeg",e=String(Date.now())+"."+c,i=await(await fetch("https://blog.51cto.com/getUploadSign",{method:"POST",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8","X-Requested-With":"XMLHttpRequest"},body:"upload_type=image"})).json();if(i.code!==0)throw Error(i.msg||"获取上传签名失败");const m=i.data,u=await(await fetch("https://blog.51cto.com/getUploadConfig",{method:"POST",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8","X-Requested-With":"XMLHttpRequest"},body:new URLSearchParams({upload_type:"image",upload_sign:m.sign,ext:t,name:e}).toString()})).json();if(u.code!==0)throw Error(u.msg||"获取上传配置失败");const f=u.data,l=f.fields,r=new FormData;r.append("key",l.key);r.append("policy",l.policy);r.append("x-amz-algorithm",l["x-amz-algorithm"]);r.append("x-amz-signature",l["x-amz-signature"]);r.append("x-amz-credential",l["x-amz-credential"]);r.append("X-Amz-Date",l["X-Amz-Date"]);r.append("Content-Type",t);r.append("file",s,e);const g=await fetch(f.url,{method:"POST",body:r});if(!g.ok)throw Error("上传到 COS 失败: "+g.status);return{url:"https://s2.51cto.com/"+l.key}},skip:["s2.51cto.com","51cto.com"]},publish:async(p,o)=>{let a="";try{const h=(await(await fetch("https://blog.51cto.com/blogger/publish",{credentials:"include"})).text()).match(/<meta\s+name="csrf-token"\s+content="([^"]+)"/);if(h)a=h[1]}catch(i){}const s=new URLSearchParams({title:p.title,content:p.content,pid:"",cate_id:"",custom_id:"0",tag:"",abstract:"",banner_type:"0",blog_type:"1",copy_code:"1",is_hide:"0",top_time:"0",is_comment:"0",is_old:"0",blog_id:"",did:"",work_id:"",class_id:"",subjectId:"",import_type:"-1",invite_code:"",raffle:"",orig:"",_csrf:a}),t=await fetch("https://blog.51cto.com/blogger/draft",{method:"POST",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8","X-Requested-With":"XMLHttpRequest",Accept:"application/json, text/javascript, */*; q=0.01"},body:s.toString()}),c=await t.text();let e=null;try{e=JSON.parse(c)}catch(i){}if(!t.ok||!e||e.status!==1||!e.data)return{ok:!1,stage:"publish",status:t.status,message:e&&e.msg||c.slice(0,300)};const n=String(e.data.did);return{ok:!0,id:n,url:"https://blog.51cto.com/blogger/draft/"+n,draft:!0}}};y({site:"cto51",name:"article",access:"write",description:"发布 51CTO 博客文章(草稿)。正文默认为 Markdown;图片自动转存到 51CTO 图床(腾讯云 COS)。",domain:"blog.51cto.com",strategy:b.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题"},{name:"text",positional:!0,help:"文章正文(默认 Markdown;传 --html 则视为 HTML)"},{name:"file",help:"正文文件路径(UTF-8,默认 Markdown)"},{name:"html",type:"boolean",help:"将正文视为 HTML 而非 Markdown"},{name:"draft",type:"boolean",help:"(保留参数,51CTO 只支持保存草稿)"},{name:"execute",type:"boolean",help:"真正执行创建/发布。没有此参数时命令拒绝写操作。"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(p,o)=>{if(!p)throw new w("51CTO 文章发布需要浏览器会话");if(!o.execute)throw new d("INVALID_INPUT","该 51CTO 写操作需要 --execute 参数确认");const a=String(o.title??"").trim();if(!a)throw new d("INVALID_INPUT","文章标题不能为空");const s=typeof o.text==="string"?o.text:void 0,t=typeof o.file==="string"?o.file:void 0;if(s&&t)throw new d("INVALID_INPUT","正文与 --file 不能同时使用");let c=s??"";if(t){const{readFile:u,stat:f}=await import("node:fs/promises");let l;try{l=await f(t)}catch{throw new d("INVALID_INPUT","文件不存在: "+t)}if(!l.isFile())throw new d("INVALID_INPUT","必须是可读文本文件: "+t);let r;try{r=await u(t)}catch{throw new d("INVALID_INPUT","无法读取文件: "+t)}try{c=new TextDecoder("utf-8",{fatal:!0}).decode(r)}catch{throw new d("INVALID_INPUT","文件不是有效 UTF-8 编码: "+t)}}if(!c.trim())throw new d("INVALID_INPUT","正文内容不能为空");const e=!0,n=await _(p,{title:a,body:c,format:o.html?"html":"markdown",draftOnly:e,profile:cto51Profile}),i=n.images.uploaded.length|0,m=n.images.failed.length|0;let h="已保存 51CTO 草稿";if(i||m)h+=`(图片:${i} 张已转存${m?`,${m} 张失败`:""})`;return[{status:"success",outcome:"draft",message:h,target_type:"article",target:"",created_target:"article:"+n.id,created_url:n.url}]}});
@@ -1 +1 @@
1
- import{cli as x,Strategy as z}from"@jackwener/opencli/registry";import{checkLogin as B}from"../_shared/article/auth.js";import{cto51Profile as q}from"./article.js";const C={home:q.home,checkAuth:q.checkAuth};x({site:"cto51",name:"whoami",access:"read",description:"查看当前 51CTO 登录账号信息。",domain:"blog.51cto.com",strategy:z.COOKIE,browser:!0,columns:["logged_in","user_id","username"],func:async(v)=>{const b=await B(v,C);return[{logged_in:b.isAuthenticated,user_id:b.userId||"",username:b.username||""}]}});
1
+ import{cli as t,Strategy as c}from"@jackwener/opencli/registry";import{checkLogin as i}from"../_shared/article/auth.js";import{cto51Profile as o}from"./article.js";const s={home:o.home,checkAuth:o.checkAuth};t({site:"cto51",name:"whoami",access:"read",description:"查看当前 51CTO 登录账号信息。",domain:"blog.51cto.com",strategy:c.COOKIE,browser:!0,columns:["logged_in","user_id","username"],func:async(r)=>{const e=await i(r,s);return[{logged_in:e.isAuthenticated,user_id:e.userId||"",username:e.username||""}]}});
@@ -1,4 +1,4 @@
1
- import{ArgumentError as q,AuthRequiredError as x,CommandExecutionError as Q,EmptyResultError as y}from"@jackwener/opencli/errors";import{cli as U,Strategy as S}from"@jackwener/opencli/registry";import{buildFlightExtractJs as h,buildScrollUntilJs as F,parseIataCode as j,parseIsoDate as R}from"./utils.js";const V=1,Y=50,D=20;function J(K){if(K===void 0||K===null||K==="")return D;const B=Number(K);if(!Number.isFinite(B)||!Number.isInteger(B))throw new q(`--limit must be an integer between ${V} and ${Y}, got ${JSON.stringify(K)}`);if(B<V||B>Y)throw new q(`--limit must be between ${V} and ${Y}, got ${B}`);return B}const N=`
1
+ import{ArgumentError as c,AuthRequiredError as y,CommandExecutionError as o,EmptyResultError as I}from"@jackwener/opencli/errors";import{cli as C,Strategy as _}from"@jackwener/opencli/registry";import{buildFlightExtractJs as N,buildScrollUntilJs as E,parseIataCode as g,parseIsoDate as S}from"./utils.js";const n=1,a=50,w=20;function b(r){if(r===void 0||r===null||r==="")return w;const t=Number(r);if(!Number.isFinite(t)||!Number.isInteger(t))throw new c(`--limit must be an integer between ${n} and ${a}, got ${JSON.stringify(r)}`);if(t<n||t>a)throw new c(`--limit must be between ${n} and ${a}, got ${t}`);return t}const v=`
2
2
  new Promise((resolve) => {
3
3
  const detect = () => {
4
4
  if (location.pathname.includes('captcha') || /验证码|verify the human/i.test(document.body?.innerText || '')) return 'captcha';
@@ -14,4 +14,4 @@ import{ArgumentError as q,AuthRequiredError as x,CommandExecutionError as Q,Empt
14
14
  observer.observe(document.documentElement, { childList: true, subtree: true });
15
15
  setTimeout(() => { observer.disconnect(); resolve('timeout'); }, 8000);
16
16
  })
17
- `;U({site:"ctrip",name:"flight",access:"read",description:"搜索携程一程机票(按出发/到达 IATA 三字码 + 日期)",domain:"flights.ctrip.com",strategy:S.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"from",required:!0,positional:!0,help:"Departure IATA code (e.g. BJS / PEK)"},{name:"to",required:!0,positional:!0,help:"Arrival IATA code (e.g. SHA / PVG)"},{name:"date",required:!0,help:"Departure date (YYYY-MM-DD)"},{name:"limit",type:"int",default:D,help:`Number of flights (${V}-${Y})`}],columns:["rank","airline","flightNo","aircraft","departureTime","departureAirport","arrivalTime","arrivalAirport","terminal","price","currency","cabin","url"],func:async(K,B)=>{const P=j("from",B.from),Z=j("to",B.to);if(P===Z)throw new q(`--from and --to must differ (got ${P})`);const z=R("date",B.date),G=J(B.limit),H=`https://flights.ctrip.com/online/list/oneway-${P.toLowerCase()}-${Z.toLowerCase()}?depdate=${z}&cabin=Y_S_C_F&adult=1&child=0&infant=0`;await K.goto(H);const $=await K.evaluate(N);if($==="captcha")throw new x("flights.ctrip.com","Ctrip is asking for a captcha; complete it in your browser session and retry");if($!=="content")throw new Q(`Ctrip flight page did not render flight cards (state=${String($)})`);const X=await K.evaluate(F(".flight-list > span > div",G)),O=await K.evaluate(h());if(!Array.isArray(O))throw new Q("Ctrip flight DOM extraction returned malformed rows");const W=O;if(W.length===0){if(Number(X)>0)throw new Q("Ctrip flight cards rendered but parser did not find required flight anchors");throw new y("ctrip flight",`No flights for ${P}→${Z} on ${z}`)}const b=W.filter((v)=>v.departureTime&&v.departureAirport&&v.arrivalTime&&v.arrivalAirport&&v.airline&&v.flightNo).slice(0,G).map((v,f)=>({rank:f+1,airline:v.airline,flightNo:v.flightNo,aircraft:v.aircraft,departureTime:v.departureTime,departureAirport:v.departureAirport,arrivalTime:v.arrivalTime,arrivalAirport:v.arrivalAirport,terminal:v.terminal,price:v.price,currency:v.currency,cabin:v.cabin,url:H}));if(b.length===0)throw new Q("Ctrip flight rows were missing required airline/flight/time/airport anchors");return b}});export const __test__={parseFlightLimit:J,WAIT_FOR_FLIGHTS_JS:N};
17
+ `;C({site:"ctrip",name:"flight",access:"read",description:"搜索携程一程机票(按出发/到达 IATA 三字码 + 日期)",domain:"flights.ctrip.com",strategy:_.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"from",required:!0,positional:!0,help:"Departure IATA code (e.g. BJS / PEK)"},{name:"to",required:!0,positional:!0,help:"Arrival IATA code (e.g. SHA / PVG)"},{name:"date",required:!0,help:"Departure date (YYYY-MM-DD)"},{name:"limit",type:"int",default:w,help:`Number of flights (${n}-${a})`}],columns:["rank","airline","flightNo","aircraft","departureTime","departureAirport","arrivalTime","arrivalAirport","terminal","price","currency","cabin","url"],func:async(r,t)=>{const i=g("from",t.from),s=g("to",t.to);if(i===s)throw new c(`--from and --to must differ (got ${i})`);const u=S("date",t.date),d=b(t.limit),m=`https://flights.ctrip.com/online/list/oneway-${i.toLowerCase()}-${s.toLowerCase()}?depdate=${u}&cabin=Y_S_C_F&adult=1&child=0&infant=0`;await r.goto(m);const l=await r.evaluate(v);if(l==="captcha")throw new y("flights.ctrip.com","Ctrip is asking for a captcha; complete it in your browser session and retry");if(l!=="content")throw new o(`Ctrip flight page did not render flight cards (state=${String(l)})`);const A=await r.evaluate(E(".flight-list > span > div",d)),f=await r.evaluate(N());if(!Array.isArray(f))throw new o("Ctrip flight DOM extraction returned malformed rows");const p=f;if(p.length===0){if(Number(A)>0)throw new o("Ctrip flight cards rendered but parser did not find required flight anchors");throw new I("ctrip flight",`No flights for ${i}→${s} on ${u}`)}const h=p.filter((e)=>e.departureTime&&e.departureAirport&&e.arrivalTime&&e.arrivalAirport&&e.airline&&e.flightNo).slice(0,d).map((e,T)=>({rank:T+1,airline:e.airline,flightNo:e.flightNo,aircraft:e.aircraft,departureTime:e.departureTime,departureAirport:e.departureAirport,arrivalTime:e.arrivalTime,arrivalAirport:e.arrivalAirport,terminal:e.terminal,price:e.price,currency:e.currency,cabin:e.cabin,url:m}));if(h.length===0)throw new o("Ctrip flight rows were missing required airline/flight/time/airport anchors");return h}});export const __test__={parseFlightLimit:b,WAIT_FOR_FLIGHTS_JS:v};
@@ -1,4 +1,4 @@
1
- import{ArgumentError as v,AuthRequiredError as H,CommandExecutionError as b,EmptyResultError as f}from"@jackwener/opencli/errors";import{cli as X,Strategy as y}from"@jackwener/opencli/registry";import{mapHotelRow as C,parseCityId as S,parseIsoDate as U}from"./utils.js";const P=1,Q=30,j=10;function W(G){if(G===void 0||G===null||G==="")return j;const z=Number(G);if(!Number.isFinite(z)||!Number.isInteger(z))throw new v(`--limit must be an integer between ${P} and ${Q}, got ${JSON.stringify(G)}`);if(z<P||z>Q)throw new v(`--limit must be between ${P} and ${Q}, got ${z}`);return z}const x=`
1
+ import{ArgumentError as l,AuthRequiredError as v,CommandExecutionError as u,EmptyResultError as A}from"@jackwener/opencli/errors";import{cli as S,Strategy as T}from"@jackwener/opencli/registry";import{mapHotelRow as C,parseCityId as k,parseIsoDate as p}from"./utils.js";const o=1,i=30,d=10;function f(t){if(t===void 0||t===null||t==="")return d;const e=Number(t);if(!Number.isFinite(e)||!Number.isInteger(e))throw new l(`--limit must be an integer between ${o} and ${i}, got ${JSON.stringify(t)}`);if(e<o||e>i)throw new l(`--limit must be between ${o} and ${i}, got ${e}`);return e}const w=`
2
2
  new Promise((resolve) => {
3
3
  const detect = () => {
4
4
  if (location.pathname.includes('captcha') || /验证码|verify the human/i.test(document.body?.innerText || '')) return 'captcha';
@@ -15,10 +15,10 @@ import{ArgumentError as v,AuthRequiredError as H,CommandExecutionError as b,Empt
15
15
  observer.observe(document.documentElement, { childList: true, subtree: true });
16
16
  setTimeout(() => { observer.disconnect(); resolve('timeout'); }, 5000);
17
17
  })
18
- `,D=`
18
+ `,y=`
19
19
  (() => {
20
20
  const list = window.__NEXT_DATA__?.props?.pageProps?.initListData?.hotelList;
21
21
  if (!Array.isArray(list)) return null;
22
22
  return list;
23
23
  })()
24
- `;function F(G,z){if(Date.parse(G+"T00:00:00Z")>=Date.parse(z+"T00:00:00Z"))throw new v(`--checkin must be earlier than --checkout (got ${G} >= ${z})`)}X({site:"ctrip",name:"hotel-search",access:"read",description:"搜索携程酒店列表(按城市 + 入住/离店日期)",domain:"hotels.ctrip.com",strategy:y.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"city",required:!0,positional:!0,help:"Numeric Ctrip city ID (use `ctrip search` or `ctrip hotel-suggest` to discover)"},{name:"checkin",required:!0,help:"Check-in date (YYYY-MM-DD)"},{name:"checkout",required:!0,help:"Check-out date (YYYY-MM-DD)"},{name:"limit",type:"int",default:j,help:`Number of hotels (${P}-${Q}); SSR first page returns ~13 entries`}],columns:["rank","hotelId","name","enName","star","score","scoreLabel","reviewCount","cityName","district","address","lat","lon","price","currency","url"],func:async(G,z)=>{const q=S(z.city),V=U("checkin",z.checkin),Y=U("checkout",z.checkout);F(V,Y);const J=W(z.limit),N=`https://hotels.ctrip.com/hotels/list?city=${q}&checkin=${V}&checkout=${Y}`;await G.goto(N);const Z=await G.evaluate(x);if(Z==="captcha")throw new H("hotels.ctrip.com","Ctrip is asking for a captcha; complete it in your browser session and retry");if(Z!=="content")throw new b(`Ctrip hotel-search page did not expose SSR hotel list (state=${String(Z)})`);const $=await G.evaluate(D);if(!Array.isArray($))throw new b("Ctrip hotel-search returned malformed SSR hotel list");if($.length===0)throw new f("ctrip hotel-search",`No hotels for city=${q} on ${V} → ${Y}`);const B=$.map((K,O)=>C(K,O)).filter((K)=>K.hotelId&&K.name).slice(0,J);if(B.length===0)throw new b("Ctrip hotel-search SSR rows were missing required hotelId/name anchors");return B}});export const __test__={parseHotelLimit:W,assertCheckinBeforeCheckout:F,WAIT_FOR_SSR_JS:x,EXTRACT_HOTELS_JS:D};
24
+ `;function _(t,e){if(Date.parse(t+"T00:00:00Z")>=Date.parse(e+"T00:00:00Z"))throw new l(`--checkin must be earlier than --checkout (got ${t} >= ${e})`)}S({site:"ctrip",name:"hotel-search",access:"read",description:"搜索携程酒店列表(按城市 + 入住/离店日期)",domain:"hotels.ctrip.com",strategy:T.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"city",required:!0,positional:!0,help:"Numeric Ctrip city ID (use `ctrip search` or `ctrip hotel-suggest` to discover)"},{name:"checkin",required:!0,help:"Check-in date (YYYY-MM-DD)"},{name:"checkout",required:!0,help:"Check-out date (YYYY-MM-DD)"},{name:"limit",type:"int",default:d,help:`Number of hotels (${o}-${i}); SSR first page returns ~13 entries`}],columns:["rank","hotelId","name","enName","star","score","scoreLabel","reviewCount","cityName","district","address","lat","lon","price","currency","url"],func:async(t,e)=>{const h=k(e.city),n=p("checkin",e.checkin),s=p("checkout",e.checkout);_(n,s);const b=f(e.limit),g=`https://hotels.ctrip.com/hotels/list?city=${h}&checkin=${n}&checkout=${s}`;await t.goto(g);const c=await t.evaluate(w);if(c==="captcha")throw new v("hotels.ctrip.com","Ctrip is asking for a captcha; complete it in your browser session and retry");if(c!=="content")throw new u(`Ctrip hotel-search page did not expose SSR hotel list (state=${String(c)})`);const a=await t.evaluate(y);if(!Array.isArray(a))throw new u("Ctrip hotel-search returned malformed SSR hotel list");if(a.length===0)throw new A("ctrip hotel-search",`No hotels for city=${h} on ${n} → ${s}`);const m=a.map((r,I)=>C(r,I)).filter((r)=>r.hotelId&&r.name).slice(0,b);if(m.length===0)throw new u("Ctrip hotel-search SSR rows were missing required hotelId/name anchors");return m}});export const __test__={parseHotelLimit:f,assertCheckinBeforeCheckout:_,WAIT_FOR_SSR_JS:w,EXTRACT_HOTELS_JS:y};
@@ -1 +1 @@
1
- import{ArgumentError as o,EmptyResultError as a}from"@jackwener/opencli/errors";import{cli as n,Strategy as c}from"@jackwener/opencli/registry";import{fetchSuggest as l,mapSuggestRow as u,parseLimit as m}from"./utils.js";n({site:"ctrip",name:"hotel-suggest",access:"read",description:"搜索携程酒店上下文联想:城市、商圈、单酒店匹配",strategy:c.PUBLIC,browser:!1,args:[{name:"query",required:!0,positional:!0,help:"Search keyword (city, business area, or hotel name)"},{name:"limit",type:"int",default:15,help:"Number of results (1-50)"}],columns:["rank","id","type","displayType","name","eName","cityId","cityName","provinceName","countryName","lat","lon","score","url"],func:async(t)=>{const r=String(t.query||"").trim();if(!r)throw new o("Search keyword cannot be empty");const i=m(t.limit),s=(await l(r,"H")).filter((e)=>!!e&&typeof e==="object").slice(0,i).map(u).filter((e)=>e.name);if(!s.length)throw new a("ctrip hotel-suggest",'Try a city, business area, or hotel keyword such as "陆家嘴" or "汉庭酒店"');return s}});
1
+ import{ArgumentError as i,EmptyResultError as s}from"@jackwener/opencli/errors";import{cli as n,Strategy as c}from"@jackwener/opencli/registry";import{fetchSuggest as m,mapSuggestRow as l,parseLimit as u}from"./utils.js";n({site:"ctrip",name:"hotel-suggest",access:"read",description:"搜索携程酒店上下文联想:城市、商圈、单酒店匹配",strategy:c.PUBLIC,browser:!1,args:[{name:"query",required:!0,positional:!0,help:"Search keyword (city, business area, or hotel name)"},{name:"limit",type:"int",default:15,help:"Number of results (1-50)"}],columns:["rank","id","type","displayType","name","eName","cityId","cityName","provinceName","countryName","lat","lon","score","url"],func:async(r)=>{const t=String(r.query||"").trim();if(!t)throw new i("Search keyword cannot be empty");const a=u(r.limit),o=(await m(t,"H")).filter((e)=>!!e&&typeof e==="object").slice(0,a).map(l).filter((e)=>e.name);if(!o.length)throw new s("ctrip hotel-suggest",'Try a city, business area, or hotel keyword such as "陆家嘴" or "汉庭酒店"');return o}});
@@ -1 +1 @@
1
- import{ArgumentError as o,EmptyResultError as s}from"@jackwener/opencli/errors";import{cli as n,Strategy as c}from"@jackwener/opencli/registry";import{fetchSuggest as m,mapSuggestRow as l,parseLimit as p}from"./utils.js";n({site:"ctrip",name:"search",access:"read",description:"搜索携程目的地、景区、火车站和地标联想结果",strategy:c.PUBLIC,browser:!1,args:[{name:"query",required:!0,positional:!0,help:"Search keyword (city, scenic spot, landmark)"},{name:"limit",type:"int",default:15,help:"Number of results (1-50)"}],columns:["rank","id","type","displayType","name","eName","cityId","cityName","provinceName","countryName","lat","lon","score","url"],func:async(r)=>{const t=String(r.query||"").trim();if(!t)throw new o("Search keyword cannot be empty");const a=p(r.limit),i=(await m(t,"D")).filter((e)=>!!e&&typeof e==="object").slice(0,a).map(l).filter((e)=>e.name);if(!i.length)throw new s("ctrip search",'Try a destination, scenic spot, or landmark keyword such as "苏州" or "故宫"');return i}});
1
+ import{ArgumentError as o,EmptyResultError as n}from"@jackwener/opencli/errors";import{cli as s,Strategy as c}from"@jackwener/opencli/registry";import{fetchSuggest as m,mapSuggestRow as l,parseLimit as p}from"./utils.js";s({site:"ctrip",name:"search",access:"read",description:"搜索携程目的地、景区、火车站和地标联想结果",strategy:c.PUBLIC,browser:!1,args:[{name:"query",required:!0,positional:!0,help:"Search keyword (city, scenic spot, landmark)"},{name:"limit",type:"int",default:15,help:"Number of results (1-50)"}],columns:["rank","id","type","displayType","name","eName","cityId","cityName","provinceName","countryName","lat","lon","score","url"],func:async(r)=>{const t=String(r.query||"").trim();if(!t)throw new o("Search keyword cannot be empty");const i=p(r.limit),a=(await m(t,"D")).filter((e)=>!!e&&typeof e==="object").slice(0,i).map(l).filter((e)=>e.name);if(!a.length)throw new n("ctrip search",'Try a destination, scenic spot, or landmark keyword such as "苏州" or "故宫"');return a}});
@@ -1,4 +1,4 @@
1
- import{ArgumentError as Y,CliError as J}from"@jackwener/opencli/errors";const X="https://m.ctrip.com/restapi/soa2/21881/json/gaHotelSearchEngine",Z=1,j=50;export function parseLimit(z,K=15){if(z===void 0||z===null||z==="")return K;const G=Number(z);if(!Number.isFinite(G)||!Number.isInteger(G))throw new Y(`--limit must be an integer between ${Z} and ${j}, got ${JSON.stringify(z)}`);if(G<Z||G>j)throw new Y(`--limit must be between ${Z} and ${j}, got ${G}`);return G}export async function fetchSuggest(z,K){let G;try{G=await fetch(X,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({keyword:z,searchType:K,platform:"online",pageID:"102001",head:{Locale:"zh-CN",LocaleController:"zh_cn",Currency:"CNY",PageId:"102001",clientID:"opencli-ctrip",group:"ctrip",Frontend:{sessionID:1,pvid:1},HotelExtension:{group:"CTRIP",WebpSupport:!1}}})})}catch(V){throw new J("FETCH_ERROR",`ctrip suggest fetch failed: ${V instanceof Error?V.message:String(V)}`,"Check your network connection and retry")}if(!G.ok)throw new J("FETCH_ERROR",`ctrip suggest failed with status ${G.status}`,"Retry the command or verify ctrip.com is reachable");let Q;try{Q=await G.json()}catch(V){throw new J("COMMAND_EXEC",`ctrip suggest returned invalid JSON: ${V instanceof Error?V.message:String(V)}`,"Ctrip may have changed the endpoint response format; retry later")}if(Q&&Q.Result===!1){const V=Q.ErrorCode??"unknown";throw new J("COMMAND_EXEC",`ctrip suggest API returned Result=false (ErrorCode=${V})`,"Verify keyword and retry; this typically means upstream rejected the query envelope")}return Array.isArray(Q?.Response?.searchResults)?Q.Response.searchResults:[]}export function pickCoords(z){const K=[[z.gdLat,z.gdLon],[z.gLat,z.gLon],[z.lat,z.lon]];for(const[G,Q]of K)if(Number.isFinite(G)&&Number.isFinite(Q)&&(G!==0||Q!==0))return{lat:G,lon:Q};return{lat:null,lon:null}}export function buildUrl(z){const K=z?.id?String(z.id):"",G=z?.cityId??"",Q=z?.cityName?String(z.cityName):"";switch(z?.type){case"City":return G?`https://you.ctrip.com/place/${encodeURIComponent(Q)}${G}.html`:null;case"Markland":return K&&G?`https://you.ctrip.com/sight/${encodeURIComponent(Q)}${G}/${K}.html`:null;case"Hotel":return K?`https://hotels.ctrip.com/hotels/detail/?hotelid=${K}`:null;case"BusinessArea":case"Zone":return G&&K?`https://hotels.ctrip.com/hotels/list?city=${G}&zone=${K}`:null;case"RailwayStation":return K?`https://trains.ctrip.com/trainstation/${K}.html`:null;default:return null}}function x(z){return Number.isFinite(z)&&z!==0?z:null}function L(...z){for(const K of z){const G=Number(K);if(Number.isFinite(G)&&G!==0)return G}return null}export function mapSuggestRow(z,K){const{lat:G,lon:Q}=pickCoords(z);return{rank:K+1,id:z?.id?String(z.id):null,type:z?.type?String(z.type):null,displayType:z?.displayType?String(z.displayType).trim():null,name:String(z?.displayName||z?.word||z?.cityName||"").replace(/\s+/g," ").trim()||null,eName:z?.eName?String(z.eName).trim():null,cityId:Number.isFinite(z?.cityId)&&z.cityId!==0?z.cityId:null,cityName:z?.cityName?String(z.cityName).trim():null,provinceName:z?.provinceName?String(z.provinceName).trim():null,countryName:z?.countryName?String(z.countryName).trim():null,lat:G,lon:Q,score:L(z?.commentScore,z?.cStar),url:buildUrl(z)}}const _=/^(\d{4})-(\d{2})-(\d{2})$/;export function parseIsoDate(z,K){if(K===void 0||K===null||K==="")throw new Y(`--${z} is required (YYYY-MM-DD)`);const G=String(K).trim(),Q=_.exec(G);if(!Q)throw new Y(`--${z} must be YYYY-MM-DD, got ${JSON.stringify(K)}`);const V=Number(Q[1]),W=Number(Q[2]),B=Number(Q[3]);if(W<1||W>12||B<1||B>31)throw new Y(`--${z} has invalid month/day: ${G}`);const $=new Date(Date.UTC(V,W-1,B));if($.getUTCFullYear()!==V||$.getUTCMonth()!==W-1||$.getUTCDate()!==B)throw new Y(`--${z} is not a real calendar date: ${G}`);return G}export function parseIataCode(z,K){if(K===void 0||K===null||K==="")throw new Y(`--${z} is required (3-letter IATA code, e.g. PEK, SHA)`);const G=String(K).trim().toUpperCase();if(!/^[A-Z]{3}$/.test(G))throw new Y(`--${z} must be a 3-letter IATA code, got ${JSON.stringify(K)}`);return G}export function parseCityId(z){if(z===void 0||z===null||z==="")throw new Y("--city is required (numeric city ID from `ctrip search` or `ctrip hotel-suggest`)");const K=Number(z);if(!Number.isFinite(K)||!Number.isInteger(K)||K<=0)throw new Y(`--city must be a positive integer city ID, got ${JSON.stringify(z)}`);return K}export function pickHotelMapCoords(z){if(!Array.isArray(z)||z.length===0)return{lat:null,lon:null};const K=(Q)=>{const V=Number(Q?.coordinateType);if(V===1)return 0;if(V===2)return 1;if(V===3)return 2;return 3},G=[...z].sort((Q,V)=>K(Q)-K(V));for(const Q of G){const V=Number(Q?.latitude),W=Number(Q?.longitude);if(Number.isFinite(V)&&Number.isFinite(W)&&(V!==0||W!==0))return{lat:V,lon:W}}return{lat:null,lon:null}}export function mapHotelRow(z,K){const G=z?.hotelInfo??{},Q=Array.isArray(z?.roomInfo)?z.roomInfo:[],V=G.summary??{},W=G.nameInfo??{},B=G.hotelStar??{},$=G.commentInfo??{},F=G.positionInfo??{},H=(Q[0]??{}).priceInfo??{},q=V.hotelId?String(V.hotelId):null,{lat:D,lon:O}=pickHotelMapCoords(F.mapCoordinate);let P=null;if($.commenterNumber){const R=String($.commenterNumber).replace(/[^\d]/g,"");if(R)P=Number(R)}const U=$.commentScore?Number($.commentScore):null,b=Number.isFinite(B.star)&&B.star>0?B.star:null,k=Number.isFinite(H.price)&&H.price>0?H.price:null;return{rank:K+1,hotelId:q,name:W.name?String(W.name).trim():null,enName:W.enName?String(W.enName).trim():null,star:b,score:Number.isFinite(U)&&U>0?U:null,scoreLabel:$.commentDescription?String($.commentDescription).trim():null,reviewCount:P,cityName:F.cityName?String(F.cityName).trim():null,district:F.positionDesc?String(F.positionDesc).trim():null,address:F.address?String(F.address).trim():null,lat:D,lon:O,price:k,currency:H.currency?String(H.currency).trim():null,url:q?`https://hotels.ctrip.com/hotels/detail/?hotelid=${q}`:null}}export function buildFlightExtractJs(){return`
1
+ import{ArgumentError as s,CliError as d}from"@jackwener/opencli/errors";const N="https://m.ctrip.com/restapi/soa2/21881/json/gaHotelSearchEngine",m=1,p=50;export function parseLimit(e,n=15){if(e===void 0||e===null||e==="")return n;const t=Number(e);if(!Number.isFinite(t)||!Number.isInteger(t))throw new s(`--limit must be an integer between ${m} and ${p}, got ${JSON.stringify(e)}`);if(t<m||t>p)throw new s(`--limit must be between ${m} and ${p}, got ${t}`);return t}export async function fetchSuggest(e,n){let t;try{t=await fetch(N,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({keyword:e,searchType:n,platform:"online",pageID:"102001",head:{Locale:"zh-CN",LocaleController:"zh_cn",Currency:"CNY",PageId:"102001",clientID:"opencli-ctrip",group:"ctrip",Frontend:{sessionID:1,pvid:1},HotelExtension:{group:"CTRIP",WebpSupport:!1}}})})}catch(i){throw new d("FETCH_ERROR",`ctrip suggest fetch failed: ${i instanceof Error?i.message:String(i)}`,"Check your network connection and retry")}if(!t.ok)throw new d("FETCH_ERROR",`ctrip suggest failed with status ${t.status}`,"Retry the command or verify ctrip.com is reachable");let r;try{r=await t.json()}catch(i){throw new d("COMMAND_EXEC",`ctrip suggest returned invalid JSON: ${i instanceof Error?i.message:String(i)}`,"Ctrip may have changed the endpoint response format; retry later")}if(r&&r.Result===!1){const i=r.ErrorCode??"unknown";throw new d("COMMAND_EXEC",`ctrip suggest API returned Result=false (ErrorCode=${i})`,"Verify keyword and retry; this typically means upstream rejected the query envelope")}return Array.isArray(r?.Response?.searchResults)?r.Response.searchResults:[]}export function pickCoords(e){const n=[[e.gdLat,e.gdLon],[e.gLat,e.gLon],[e.lat,e.lon]];for(const[t,r]of n)if(Number.isFinite(t)&&Number.isFinite(r)&&(t!==0||r!==0))return{lat:t,lon:r};return{lat:null,lon:null}}export function buildUrl(e){const n=e?.id?String(e.id):"",t=e?.cityId??"",r=e?.cityName?String(e.cityName):"";switch(e?.type){case"City":return t?`https://you.ctrip.com/place/${encodeURIComponent(r)}${t}.html`:null;case"Markland":return n&&t?`https://you.ctrip.com/sight/${encodeURIComponent(r)}${t}/${n}.html`:null;case"Hotel":return n?`https://hotels.ctrip.com/hotels/detail/?hotelid=${n}`:null;case"BusinessArea":case"Zone":return t&&n?`https://hotels.ctrip.com/hotels/list?city=${t}&zone=${n}`:null;case"RailwayStation":return n?`https://trains.ctrip.com/trainstation/${n}.html`:null;default:return null}}function x(e){return Number.isFinite(e)&&e!==0?e:null}function k(...e){for(const n of e){const t=Number(n);if(Number.isFinite(t)&&t!==0)return t}return null}export function mapSuggestRow(e,n){const{lat:t,lon:r}=pickCoords(e);return{rank:n+1,id:e?.id?String(e.id):null,type:e?.type?String(e.type):null,displayType:e?.displayType?String(e.displayType).trim():null,name:String(e?.displayName||e?.word||e?.cityName||"").replace(/\s+/g," ").trim()||null,eName:e?.eName?String(e.eName).trim():null,cityId:Number.isFinite(e?.cityId)&&e.cityId!==0?e.cityId:null,cityName:e?.cityName?String(e.cityName).trim():null,provinceName:e?.provinceName?String(e.provinceName).trim():null,countryName:e?.countryName?String(e.countryName).trim():null,lat:t,lon:r,score:k(e?.commentScore,e?.cStar),url:buildUrl(e)}}const S=/^(\d{4})-(\d{2})-(\d{2})$/;export function parseIsoDate(e,n){if(n===void 0||n===null||n==="")throw new s(`--${e} is required (YYYY-MM-DD)`);const t=String(n).trim(),r=S.exec(t);if(!r)throw new s(`--${e} must be YYYY-MM-DD, got ${JSON.stringify(n)}`);const i=Number(r[1]),o=Number(r[2]),l=Number(r[3]);if(o<1||o>12||l<1||l>31)throw new s(`--${e} has invalid month/day: ${t}`);const c=new Date(Date.UTC(i,o-1,l));if(c.getUTCFullYear()!==i||c.getUTCMonth()!==o-1||c.getUTCDate()!==l)throw new s(`--${e} is not a real calendar date: ${t}`);return t}export function parseIataCode(e,n){if(n===void 0||n===null||n==="")throw new s(`--${e} is required (3-letter IATA code, e.g. PEK, SHA)`);const t=String(n).trim().toUpperCase();if(!/^[A-Z]{3}$/.test(t))throw new s(`--${e} must be a 3-letter IATA code, got ${JSON.stringify(n)}`);return t}export function parseCityId(e){if(e===void 0||e===null||e==="")throw new s("--city is required (numeric city ID from `ctrip search` or `ctrip hotel-suggest`)");const n=Number(e);if(!Number.isFinite(n)||!Number.isInteger(n)||n<=0)throw new s(`--city must be a positive integer city ID, got ${JSON.stringify(e)}`);return n}export function pickHotelMapCoords(e){if(!Array.isArray(e)||e.length===0)return{lat:null,lon:null};const n=(r)=>{const i=Number(r?.coordinateType);if(i===1)return 0;if(i===2)return 1;if(i===3)return 2;return 3},t=[...e].sort((r,i)=>n(r)-n(i));for(const r of t){const i=Number(r?.latitude),o=Number(r?.longitude);if(Number.isFinite(i)&&Number.isFinite(o)&&(i!==0||o!==0))return{lat:i,lon:o}}return{lat:null,lon:null}}export function mapHotelRow(e,n){const t=e?.hotelInfo??{},r=Array.isArray(e?.roomInfo)?e.roomInfo:[],i=t.summary??{},o=t.nameInfo??{},l=t.hotelStar??{},c=t.commentInfo??{},u=t.positionInfo??{},a=(r[0]??{}).priceInfo??{},f=i.hotelId?String(i.hotelId):null,{lat:b,lon:I}=pickHotelMapCoords(u.mapCoordinate);let g=null;if(c.commenterNumber){const y=String(c.commenterNumber).replace(/[^\d]/g,"");if(y)g=Number(y)}const h=c.commentScore?Number(c.commentScore):null,T=Number.isFinite(l.star)&&l.star>0?l.star:null,w=Number.isFinite(a.price)&&a.price>0?a.price:null;return{rank:n+1,hotelId:f,name:o.name?String(o.name).trim():null,enName:o.enName?String(o.enName).trim():null,star:T,score:Number.isFinite(h)&&h>0?h:null,scoreLabel:c.commentDescription?String(c.commentDescription).trim():null,reviewCount:g,cityName:u.cityName?String(u.cityName).trim():null,district:u.positionDesc?String(u.positionDesc).trim():null,address:u.address?String(u.address).trim():null,lat:b,lon:I,price:w,currency:a.currency?String(a.currency).trim():null,url:f?`https://hotels.ctrip.com/hotels/detail/?hotelid=${f}`:null}}export function buildFlightExtractJs(){return`
2
2
  (() => {
3
3
  const cleanText = (value) => (value || '').replace(/\\s+/g, ' ').trim();
4
4
  const isTime = (s) => /^([01]?\\d|2[0-3]):[0-5]\\d$/.test(s);
@@ -77,9 +77,9 @@ import{ArgumentError as Y,CliError as J}from"@jackwener/opencli/errors";const X=
77
77
  });
78
78
  return rows;
79
79
  })()
80
- `}export function buildScrollUntilJs(z,K,G=8){if(!Number.isInteger(K)||K<1||K>100)throw new Y(`targetCount must be an integer between 1 and 100, got ${JSON.stringify(K)}`);if(!Number.isInteger(G)||G<1||G>30)throw new Y(`maxScrolls must be an integer between 1 and 30, got ${JSON.stringify(G)}`);return`
80
+ `}export function buildScrollUntilJs(e,n,t=8){if(!Number.isInteger(n)||n<1||n>100)throw new s(`targetCount must be an integer between 1 and 100, got ${JSON.stringify(n)}`);if(!Number.isInteger(t)||t<1||t>30)throw new s(`maxScrolls must be an integer between 1 and 30, got ${JSON.stringify(t)}`);return`
81
81
  (async () => {
82
- const sel = ${JSON.stringify(z)};
82
+ const sel = ${JSON.stringify(e)};
83
83
  const isVisible = (el) => {
84
84
  const style = window.getComputedStyle(el);
85
85
  if (style.display === 'none' || style.visibility === 'hidden' || Number(style.opacity) === 0) return false;
@@ -89,8 +89,8 @@ import{ArgumentError as Y,CliError as J}from"@jackwener/opencli/errors";const X=
89
89
  const countItems = () => Array.from(document.querySelectorAll(sel)).filter(isVisible).length;
90
90
  let lastCount = countItems();
91
91
  let plateauRounds = 0;
92
- for (let i = 0; i < ${G}; i++) {
93
- if (countItems() >= ${K}) break;
92
+ for (let i = 0; i < ${t}; i++) {
93
+ if (countItems() >= ${n}) break;
94
94
  const lastHeight = document.body.scrollHeight;
95
95
  window.scrollTo(0, lastHeight);
96
96
  await new Promise((resolve) => {
@@ -116,4 +116,4 @@ import{ArgumentError as Y,CliError as J}from"@jackwener/opencli/errors";const X=
116
116
  }
117
117
  return countItems();
118
118
  })()
119
- `}export const __test__={ENDPOINT:X,MIN_LIMIT:Z,MAX_LIMIT:j};
119
+ `}export const __test__={ENDPOINT:N,MIN_LIMIT:m,MAX_LIMIT:p};
@@ -1,12 +1,12 @@
1
- import{cli as L,Strategy as M}from"@jackwener/opencli/registry";import{ArgumentError as N,selectorError as O}from"@jackwener/opencli/errors";export const askCommand=L({site:"cursor",name:"ask",access:"write",description:"Send a prompt and wait for the AI response (send + wait + read)",domain:"localhost",strategy:M.UI,browser:!0,args:[{name:"text",fromFile:!0,required:!0,positional:!0,help:"Prompt to send"},{name:"timeout",type:"int",required:!1,help:"Max seconds to wait for response (default: 30)",default:30}],columns:["Role","Text"],func:async(h,D)=>{const{text:z,timeout:q}=D;if(!Number.isInteger(q)||q<1)throw new N("--timeout must be a positive integer (seconds)");const J=await h.evaluate(`
1
+ import{cli as c,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as d,selectorError as f}from"@jackwener/opencli/errors";export const askCommand=c({site:"cursor",name:"ask",access:"write",description:"Send a prompt and wait for the AI response (send + wait + read)",domain:"localhost",strategy:m.UI,browser:!0,args:[{name:"text",fromFile:!0,required:!0,positional:!0,help:"Prompt to send"},{name:"timeout",type:"int",required:!1,help:"Max seconds to wait for response (default: 30)",default:30}],columns:["Role","Text"],func:async(e,s)=>{const{text:r,timeout:t}=s;if(!Number.isInteger(t)||t<1)throw new d("--timeout must be a positive integer (seconds)");const l=await e.evaluate(`
2
2
  document.querySelectorAll('[data-message-role]').length
3
- `);if(!await h.evaluate(`(function(text) {
3
+ `);if(!await e.evaluate(`(function(text) {
4
4
  let editor = document.querySelector('.aislash-editor-input, [data-lexical-editor="true"], [contenteditable="true"]');
5
5
  if (!editor) return false;
6
6
  editor.focus();
7
7
  document.execCommand('insertText', false, text);
8
8
  return true;
9
- })(${JSON.stringify(z)})`))throw O("Cursor input element");await h.wait(0.5);await h.pressKey("Enter");const F=2,K=Math.ceil(q/F);let B="";for(let G=0;G<K;G++){await h.wait(F);const H=await h.evaluate(`
9
+ })(${JSON.stringify(r)})`))throw f("Cursor input element");await e.wait(0.5);await e.pressKey("Enter");const n=2,u=Math.ceil(t/n);let o="";for(let a=0;a<u;a++){await e.wait(n);const i=await e.evaluate(`
10
10
  (function(prevCount) {
11
11
  const msgs = document.querySelectorAll('[data-message-role]');
12
12
  if (msgs.length <= prevCount) return null;
@@ -18,5 +18,5 @@ import{cli as L,Strategy as M}from"@jackwener/opencli/registry";import{ArgumentE
18
18
  const root = lastMsg.querySelector('.markdown-root');
19
19
  const text = root ? root.innerText : lastMsg.innerText;
20
20
  return text ? text.trim() : null;
21
- })(${J})
22
- `);if(H){B=H;break}}if(!B)return[{Role:"User",Text:z},{Role:"System",Text:`No response received within ${q}s. The AI may still be generating.`}];return[{Role:"User",Text:z},{Role:"Assistant",Text:B}]}});
21
+ })(${l})
22
+ `);if(i){o=i;break}}if(!o)return[{Role:"User",Text:r},{Role:"System",Text:`No response received within ${t}s. The AI may still be generating.`}];return[{Role:"User",Text:r},{Role:"Assistant",Text:o}]}});
@@ -1,4 +1,4 @@
1
- import{cli as A,Strategy as B}from"@jackwener/opencli/registry";import{selectorError as D}from"@jackwener/opencli/errors";export const composerCommand=A({site:"cursor",name:"composer",access:"write",description:"Send a prompt directly into Cursor Composer (Cmd+I shortcut)",domain:"localhost",strategy:B.UI,browser:!0,args:[{name:"text",fromFile:!0,required:!0,positional:!0,help:"Text to send into Composer"}],columns:["Status","InjectedText"],func:async(b,z)=>{const q=z.text;await b.pressKey("Meta+I");await b.wait(1);if(!await b.evaluate(`(function(text) {
1
+ import{cli as r,Strategy as s}from"@jackwener/opencli/registry";import{selectorError as i}from"@jackwener/opencli/errors";export const composerCommand=r({site:"cursor",name:"composer",access:"write",description:"Send a prompt directly into Cursor Composer (Cmd+I shortcut)",domain:"localhost",strategy:s.UI,browser:!0,args:[{name:"text",fromFile:!0,required:!0,positional:!0,help:"Text to send into Composer"}],columns:["Status","InjectedText"],func:async(t,o)=>{const e=o.text;await t.pressKey("Meta+I");await t.wait(1);if(!await t.evaluate(`(function(text) {
2
2
  let composer = document.activeElement;
3
3
  if (!composer || !composer.isContentEditable) {
4
4
  composer = document.querySelector('.composer-bar [data-lexical-editor="true"], [id*="composer"] [contenteditable="true"], .aislash-editor-input');
@@ -9,4 +9,4 @@ import{cli as A,Strategy as B}from"@jackwener/opencli/registry";import{selectorE
9
9
  composer.focus();
10
10
  document.execCommand('insertText', false, text);
11
11
  return true;
12
- })(${JSON.stringify(q)})`))throw D("Cursor Composer input element","Could not find Cursor Composer input element after pressing Cmd+I.");await b.wait(0.5);await b.pressKey("Enter");await b.wait(1);return[{Status:"Success",InjectedText:q}]}});
12
+ })(${JSON.stringify(e)})`))throw i("Cursor Composer input element","Could not find Cursor Composer input element after pressing Cmd+I.");await t.wait(0.5);await t.pressKey("Enter");await t.wait(1);return[{Status:"Success",InjectedText:e}]}});
@@ -1,9 +1,9 @@
1
- import{cli as v,Strategy as x}from"@jackwener/opencli/registry";export const modelCommand=v({site:"cursor",name:"model",access:"read",description:"Get or switch the currently active AI model in Cursor",domain:"localhost",strategy:x.UI,browser:!0,args:[{name:"model-name",required:!1,positional:!0,help:"The ID of the model to switch to (e.g. claude-3.5-sonnet)"}],columns:["Status","Model"],func:async(f,q)=>{const b=q["model-name"];if(!b)return[{Status:"Active",Model:await f.evaluate(`
1
+ import{cli as r,Strategy as s}from"@jackwener/opencli/registry";export const modelCommand=r({site:"cursor",name:"model",access:"read",description:"Get or switch the currently active AI model in Cursor",domain:"localhost",strategy:s.UI,browser:!0,args:[{name:"model-name",required:!1,positional:!0,help:"The ID of the model to switch to (e.g. claude-3.5-sonnet)"}],columns:["Status","Model"],func:async(o,t)=>{const e=t["model-name"];if(!e)return[{Status:"Active",Model:await o.evaluate(`
2
2
  (function() {
3
3
  const m = document.querySelector('.composer-unified-dropdown-model span, [class*="unifiedmodeldropdown"] span');
4
4
  return m ? m.textContent.trim() : 'Unknown or Not Found';
5
5
  })()
6
- `)}];else return[{Status:await f.evaluate(`
6
+ `)}];else return[{Status:await o.evaluate(`
7
7
  (function(targetModel) {
8
8
  const dropdown = document.querySelector('.composer-unified-dropdown-model, [class*="unifiedmodeldropdown"]');
9
9
  if (!dropdown) return 'Dropdown not found';
@@ -14,5 +14,5 @@ import{cli as v,Strategy as x}from"@jackwener/opencli/registry";export const mod
14
14
  // a simple scriptable approach is just to click it, and hope we can select it via UI.
15
15
  // In many React apps, clicking it opens a menu, and clicking the item works.
16
16
  return 'Dropdown opened. Automated switching is not fully generic. Please implement precise list navigation depending on DOM.';
17
- })(${JSON.stringify(b)})
18
- `),Model:b}]}});
17
+ })(${JSON.stringify(e)})
18
+ `),Model:e}]}});
@@ -1,4 +1,4 @@
1
- import{cli as z,Strategy as A}from"@jackwener/opencli/registry";import{selectorError as B}from"@jackwener/opencli/errors";export const sendCommand=z({site:"cursor",name:"send",access:"write",description:"Send a prompt directly into Cursor Composer/Chat",domain:"localhost",strategy:A.UI,browser:!0,args:[{name:"text",fromFile:!0,required:!0,positional:!0,help:"Text to send into Cursor"}],columns:["Status","InjectedText"],func:async(f,v)=>{const q=v.text;if(!await f.evaluate(`(function(text) {
1
+ import{cli as o,Strategy as s}from"@jackwener/opencli/registry";import{selectorError as n}from"@jackwener/opencli/errors";export const sendCommand=o({site:"cursor",name:"send",access:"write",description:"Send a prompt directly into Cursor Composer/Chat",domain:"localhost",strategy:s.UI,browser:!0,args:[{name:"text",fromFile:!0,required:!0,positional:!0,help:"Text to send into Cursor"}],columns:["Status","InjectedText"],func:async(t,r)=>{const e=r.text;if(!await t.evaluate(`(function(text) {
2
2
  // Find the Lexical editor input for Composer or Chat
3
3
  let composer = document.querySelector('.aislash-editor-input, [data-lexical-editor="true"], [contenteditable="true"]');
4
4
 
@@ -9,4 +9,4 @@ import{cli as z,Strategy as A}from"@jackwener/opencli/registry";import{selectorE
9
9
  composer.focus();
10
10
  document.execCommand('insertText', false, text);
11
11
  return true;
12
- })(${JSON.stringify(q)})`))throw B("Cursor Composer input element");await f.wait(0.5);await f.pressKey("Enter");await f.wait(1);return[{Status:"Success",InjectedText:q}]}});
12
+ })(${JSON.stringify(e)})`))throw n("Cursor Composer input element");await t.wait(0.5);await t.pressKey("Enter");await t.wait(1);return[{Status:"Success",InjectedText:e}]}});
@@ -1 +1 @@
1
- import{cli as C,Strategy as D}from"@jackwener/opencli/registry";import{ArgumentError as H,CommandExecutionError as J,EmptyResultError as f}from"@jackwener/opencli/errors";import{DBLP_ORIGIN as x,decodeXmlEntities as K,dblpFetchJson as Q,dblpFetchXml as _,extractRecordKey as b,recordXmlToRow as q,requireBoundedInt as I,requireQuery as S}from"./utils.js";const j=/^[0-9a-z]+(?:\/[0-9a-z-]+)+$/i;function F(G){const M=String(G?.info?.url??"").trim().match(/\/pid\/([^/]+(?:\/[^/]+)+)$/);return M?M[1]:""}function P(G){return G[0]}function k(G){const V=[],M=/<r>\s*([\s\S]*?)\s*<\/r>/g;let L;while((L=M.exec(String(G||"")))!==null){const O=L[1];if(/^<crossref/.test(O))continue;V.push(O)}return V}C({site:"dblp",name:"author",access:"read",description:"List dblp publications by a given author (newest first; resolves to top PID match)",domain:"dblp.org",strategy:D.PUBLIC,browser:!1,args:[{name:"author",positional:!0,required:!1,help:'Author name (e.g. "Yoshua Bengio"). Optional when --pid is given.'},{name:"pid",help:'Canonical dblp PID (e.g. "56/953"). Bypasses author search.'},{name:"limit",type:"int",default:20,help:"Max publications (1-200)"}],columns:["rank","key","title","authors","venue","year","type","doi","pid","url"],func:async(G)=>{const V=I(G.limit,20,200),M=G.pid!=null?String(G.pid).trim():"";let L="",O="";if(M){if(!j.test(M))throw new H(`dblp pid "${M}" is not a valid PID`,'Expected something like "56/953" — visit the author page on dblp.org to find it.');L=M}else{const U=S(G.author,"author"),z=(await Q(`/search/author/api?q=${encodeURIComponent(U)}&format=json&h=20`,"dblp author search"))?.result?.hits?.hit,Z=Array.isArray(z)?z:z?[z]:[];if(!Z.length)throw new f("dblp author",`No dblp author matched "${U}". Try a different spelling, or pass --pid to bypass author search.`);const $=P(Z);L=F($);if(!L)throw new J(`dblp author search for "${U}" returned a hit without a PID URL`,"dblp may have changed its author-search response shape; retry or pass --pid manually.");O=K(String($?.info?.author??"")).trim()}const B=await _(`/pid/${L}.xml`,`dblp pid ${L}`),W=k(B);if(!W.length)throw new f("dblp author",`dblp PID ${L}${O?` (${O})`:""} has no publications.`);return W.slice(0,V).map((U,Y)=>{const z=q(`<root>${U}</root>`);return{rank:Y+1,key:z.key||b(U),title:z.title,authors:z.authors,venue:z.venue,year:z.year,type:z.type,doi:z.doi,pid:L,url:z.open_access_url||z.dblp_url}})}});
1
+ import{cli as d,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as f,CommandExecutionError as y,EmptyResultError as c}from"@jackwener/opencli/errors";import{DBLP_ORIGIN as T,decodeXmlEntities as b,dblpFetchJson as g,dblpFetchXml as w,extractRecordKey as I,recordXmlToRow as v,requireBoundedInt as P,requireQuery as x}from"./utils.js";const A=/^[0-9a-z]+(?:\/[0-9a-z-]+)+$/i;function E(e){const o=String(e?.info?.url??"").trim().match(/\/pid\/([^/]+(?:\/[^/]+)+)$/);return o?o[1]:""}function R(e){return e[0]}function k(e){const a=[],o=/<r>\s*([\s\S]*?)\s*<\/r>/g;let r;while((r=o.exec(String(e||"")))!==null){const i=r[1];if(/^<crossref/.test(i))continue;a.push(i)}return a}d({site:"dblp",name:"author",access:"read",description:"List dblp publications by a given author (newest first; resolves to top PID match)",domain:"dblp.org",strategy:m.PUBLIC,browser:!1,args:[{name:"author",positional:!0,required:!1,help:'Author name (e.g. "Yoshua Bengio"). Optional when --pid is given.'},{name:"pid",help:'Canonical dblp PID (e.g. "56/953"). Bypasses author search.'},{name:"limit",type:"int",default:20,help:"Max publications (1-200)"}],columns:["rank","key","title","authors","venue","year","type","doi","pid","url"],func:async(e)=>{const a=P(e.limit,20,200),o=e.pid!=null?String(e.pid).trim():"";let r="",i="";if(o){if(!A.test(o))throw new f(`dblp pid "${o}" is not a valid PID`,'Expected something like "56/953" — visit the author page on dblp.org to find it.');r=o}else{const n=x(e.author,"author"),t=(await g(`/search/author/api?q=${encodeURIComponent(n)}&format=json&h=20`,"dblp author search"))?.result?.hits?.hit,p=Array.isArray(t)?t:t?[t]:[];if(!p.length)throw new c("dblp author",`No dblp author matched "${n}". Try a different spelling, or pass --pid to bypass author search.`);const u=R(p);r=E(u);if(!r)throw new y(`dblp author search for "${n}" returned a hit without a PID URL`,"dblp may have changed its author-search response shape; retry or pass --pid manually.");i=b(String(u?.info?.author??"")).trim()}const h=await w(`/pid/${r}.xml`,`dblp pid ${r}`),s=k(h);if(!s.length)throw new c("dblp author",`dblp PID ${r}${i?` (${i})`:""} has no publications.`);return s.slice(0,a).map((n,l)=>{const t=v(`<root>${n}</root>`);return{rank:l+1,key:t.key||I(n),title:t.title,authors:t.authors,venue:t.venue,year:t.year,type:t.type,doi:t.doi,pid:r,url:t.open_access_url||t.dblp_url}})}});
@@ -1 +1 @@
1
- import{cli as t,Strategy as s}from"@jackwener/opencli/registry";import{EmptyResultError as l}from"@jackwener/opencli/errors";import{PAPER_COLUMNS as p,dblpFetchXml as c,recordXmlToRow as d,requireRecordKey as i}from"./utils.js";t({site:"dblp",name:"paper",aliases:["detail","view"],access:"read",description:"Fetch a dblp record by canonical key (e.g. conf/nips/VaswaniSPUJGKP17)",domain:"dblp.org",strategy:s.PUBLIC,browser:!1,args:[{name:"key",positional:!0,required:!0,help:"dblp record key (round-tripped from the `key` column of `dblp search`)"}],columns:p,func:async(a)=>{const r=i(a.key),o=await c(`/rec/${encodeURI(r)}.xml`,"dblp paper"),e=d(o);if(!e.key&&!e.title)throw new l("dblp paper",`dblp returned an empty record for key "${r}".`);return[e]}});
1
+ import{cli as a,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as c}from"@jackwener/opencli/errors";import{PAPER_COLUMNS as l,dblpFetchXml as d,recordXmlToRow as n,requireRecordKey as i}from"./utils.js";a({site:"dblp",name:"paper",aliases:["detail","view"],access:"read",description:"Fetch a dblp record by canonical key (e.g. conf/nips/VaswaniSPUJGKP17)",domain:"dblp.org",strategy:p.PUBLIC,browser:!1,args:[{name:"key",positional:!0,required:!0,help:"dblp record key (round-tripped from the `key` column of `dblp search`)"}],columns:l,func:async(o)=>{const r=i(o.key),t=await d(`/rec/${encodeURI(r)}.xml`,"dblp paper"),e=n(t);if(!e.key&&!e.title)throw new c("dblp paper",`dblp returned an empty record for key "${r}".`);return[e]}});
@@ -1 +1 @@
1
- import{cli as l,Strategy as c}from"@jackwener/opencli/registry";import{EmptyResultError as p}from"@jackwener/opencli/errors";import{SEARCH_COLUMNS as h,dblpFetchJson as u,requireBoundedInt as d,requireQuery as m,searchHitToRow as b}from"./utils.js";l({site:"dblp",name:"search",access:"read",description:"Search dblp computer-science bibliography by free-text query",domain:"dblp.org",strategy:c.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (title / author / venue, e.g. "attention is all you need")'},{name:"limit",type:"int",default:20,help:"Max results (1-100, single dblp page)"}],columns:h,func:async(e)=>{const t=m(e.query),r=d(e.limit,20,100),o=`/search/publ/api?q=${encodeURIComponent(t)}&format=json&h=${r}`,a=(await u(o,"dblp search"))?.result?.hits?.hit,s=Array.isArray(a)?a:[];if(s.length===0)throw new p("dblp search",`No publications matched "${t}".`);return s.slice(0,r).map((i,n)=>b(i,n+1))}});
1
+ import{cli as l,Strategy as c}from"@jackwener/opencli/registry";import{EmptyResultError as p}from"@jackwener/opencli/errors";import{SEARCH_COLUMNS as u,dblpFetchJson as h,requireBoundedInt as m,requireQuery as d,searchHitToRow as y}from"./utils.js";l({site:"dblp",name:"search",access:"read",description:"Search dblp computer-science bibliography by free-text query",domain:"dblp.org",strategy:c.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (title / author / venue, e.g. "attention is all you need")'},{name:"limit",type:"int",default:20,help:"Max results (1-100, single dblp page)"}],columns:u,func:async(e)=>{const t=d(e.query),r=m(e.limit,20,100),s=`/search/publ/api?q=${encodeURIComponent(t)}&format=json&h=${r}`,o=(await h(s,"dblp search"))?.result?.hits?.hit,i=Array.isArray(o)?o:[];if(i.length===0)throw new p("dblp search",`No publications matched "${t}".`);return i.slice(0,r).map((a,n)=>y(a,n+1))}});
@@ -1 +1 @@
1
- import{ArgumentError as j,CommandExecutionError as $,EmptyResultError as N}from"@jackwener/opencli/errors";export const DBLP_ORIGIN="https://dblp.org";const O=/^[a-z]+(?:\/[A-Za-z0-9_.-]+)+$/;async function q(Q,J,S){let U;try{U=await fetch(Q,{headers:{accept:S,"user-agent":"opencli-dblp/1.0 (+https://github.com/jackwener/OpenCLI)"}})}catch(W){throw new $(`${J} request failed: ${W?.message??W}`,"Check that dblp.org is reachable from this network.")}if(!U.ok){if(U.status===429)throw new $(`${J} returned HTTP 429 (rate limited)`,"dblp throttles clients that fetch too aggressively. Wait a few seconds and retry, or lower --limit.");if(U.status===404)throw new N(J,"dblp returned 404 — the requested record may not exist.");throw new $(`${J} returned HTTP ${U.status}`,"Inspect the response in a browser at the same URL for more context.")}return U}export async function dblpFetchJson(Q,J){const S=await q(`${DBLP_ORIGIN}${Q}`,J,"application/json");let U;try{U=await S.json()}catch(Z){throw new $(`${J} returned malformed JSON: ${Z?.message??Z}`)}const W=String(U?.result?.status?.["@code"]??"").trim();if(!W)throw new $(`${J} returned JSON without result.status.@code`,"dblp changed its JSON envelope or returned a partial error payload; inspect the raw response in a browser.");if(W!=="200"){const Z=String(U?.result?.status?.text??"").trim();throw new $(`${J} returned API status ${W}${Z?` (${Z})`:""}`,"dblp accepted the HTTP request but reported an API-level failure. Retry later or inspect the same query in a browser.")}return U}export async function dblpFetchXml(Q,J){return(await q(`${DBLP_ORIGIN}${Q}`,J,"application/xml")).text()}export function coerceInt(Q){if(Q===void 0||Q===null||Q==="")return NaN;const J=typeof Q==="number"?Q:Number(Q);return Number.isFinite(J)&&Number.isInteger(J)?J:NaN}export function requireBoundedInt(Q,J,S,U="limit"){const Z=coerceInt(Q??J);if(!Number.isInteger(Z)||Z<=0)throw new j(`dblp ${U} must be a positive integer`);if(Z>S)throw new j(`dblp ${U} must be <= ${S}`);return Z}export function requireQuery(Q,J="query"){const S=String(Q??"").trim();if(!S)throw new j(`dblp ${J} cannot be empty`);return S}export function requireRecordKey(Q){const J=String(Q??"").trim();if(!J)throw new j("dblp paper key is required");if(!O.test(J))throw new j(`dblp paper key "${Q}" is not a valid record key`,'Expected something like "conf/nips/VaswaniSPUJGKP17" — copy the `key` column from `dblp search`.');return J}export function decodeXmlEntities(Q){if(!Q)return"";return String(Q).replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&apos;/g,"'").replace(/&quot;/g,'"').replace(/&#x([0-9a-fA-F]+);/g,(J,S)=>String.fromCodePoint(parseInt(S,16))).replace(/&#(\d+);/g,(J,S)=>String.fromCodePoint(parseInt(S,10)))}function M(Q){return String(Q||"").replace(/\s+\d{4,}$/,"").trim()}export function normalizeAuthors(Q){if(!Q)return[];const J=Q?.author;if(!J)return[];return(Array.isArray(J)?J:[J]).map((U)=>{if(U&&typeof U==="object")return M(U.text||U["#text"]||"");return M(String(U))}).filter(Boolean)}export function searchHitToRow(Q,J){const S=Q?.info??{},U=normalizeAuthors(S.authors),W=String(S.key??"").trim();return{rank:J,key:W,title:K(decodeXmlEntities(S.title??"")).trim(),authors:U.join(", "),venue:decodeXmlEntities(S.venue??""),year:String(S.year??"").trim(),type:_(S.type),doi:String(S.doi??"").trim(),url:String(S.ee??S.url??"").trim()}}function K(Q){return String(Q||"").replace(/\.\s*$/,"")}function _(Q){if(!Q)return"";const J=String(Q);if(/Conference and Workshop/i.test(J))return"conf";if(/Journal Articles/i.test(J))return"journal";if(/Books and Theses/i.test(J))return"book";if(/Editorship/i.test(J))return"editorship";if(/Reference Works/i.test(J))return"reference";if(/Informal/i.test(J))return"preprint";return J.toLowerCase().split(/\s+/)[0]}export function extractFirst(Q,J){const S=String(Q||"").match(new RegExp(`<${J}\\b[^>]*>([\\s\\S]*?)<\\/${J}>`));return S?S[1]:""}export function extractAll(Q,J){const S=[],U=new RegExp(`<${J}\\b[^>]*>([\\s\\S]*?)<\\/${J}>`,"g");let W;while((W=U.exec(String(Q||"")))!==null)S.push(W[1]);return S}export function extractOpenAccessLink(Q){const J=String(Q||"").match(/<ee\b[^>]*type=["']oa["'][^>]*>([\s\S]*?)<\/ee>/);if(J)return J[1].trim();const S=String(Q||"").match(/<ee\b[^>]*>([\s\S]*?)<\/ee>/);return S?S[1].trim():""}export function extractRecordKey(Q){const J=String(Q||"").match(/<(?:article|inproceedings|incollection|proceedings|book|phdthesis|mastersthesis)\b[^>]*\bkey="([^"]+)"/);return J?J[1]:""}export function extractRecordType(Q){const J=String(Q||"").match(/<(article|inproceedings|incollection|proceedings|book|phdthesis|mastersthesis)\b/);if(!J)return"";switch(J[1]){case"inproceedings":return"conf";case"article":return"journal";case"incollection":return"incollection";case"proceedings":return"editorship";case"book":return"book";case"phdthesis":return"phdthesis";case"mastersthesis":return"mastersthesis";default:return J[1]}}export function recordXmlToRow(Q){const J=extractRecordKey(Q),S=extractRecordType(Q),U=K(decodeXmlEntities(extractFirst(Q,"title"))),W=extractAll(Q,"author").map((z)=>M(decodeXmlEntities(z))),Z=decodeXmlEntities(extractFirst(Q,"year")),B=decodeXmlEntities(extractFirst(Q,"pages")),G=S==="conf"?decodeXmlEntities(extractFirst(Q,"booktitle")):decodeXmlEntities(extractFirst(Q,"journal")),H=(()=>{const z=String(Q||"").match(/<ee\b[^>]*>([^<]*?(?:doi\.org\/|10\.[^"<]+))<\/ee>/i);if(!z)return"";const Y=z[1].replace(/^https?:\/\/(?:dx\.)?doi\.org\//i,"");return Y.startsWith("10.")?Y:""})();return{key:J,type:S,title:U,authors:W.join(", "),venue:G,year:Z,pages:B,doi:H,open_access_url:extractOpenAccessLink(Q),dblp_url:J?`${DBLP_ORIGIN}/rec/${J}.html`:""}}export const SEARCH_COLUMNS=["rank","key","title","authors","venue","year","type","doi","url"],PAPER_COLUMNS=["key","type","title","authors","venue","year","pages","doi","open_access_url","dblp_url"];
1
+ import{ArgumentError as c,CommandExecutionError as s,EmptyResultError as g}from"@jackwener/opencli/errors";export const DBLP_ORIGIN="https://dblp.org";const y=/^[a-z]+(?:\/[A-Za-z0-9_.-]+)+$/;async function d(e,t,r){let n;try{n=await fetch(e,{headers:{accept:r,"user-agent":"opencli-dblp/1.0 (+https://github.com/jackwener/OpenCLI)"}})}catch(o){throw new s(`${t} request failed: ${o?.message??o}`,"Check that dblp.org is reachable from this network.")}if(!n.ok){if(n.status===429)throw new s(`${t} returned HTTP 429 (rate limited)`,"dblp throttles clients that fetch too aggressively. Wait a few seconds and retry, or lower --limit.");if(n.status===404)throw new g(t,"dblp returned 404 — the requested record may not exist.");throw new s(`${t} returned HTTP ${n.status}`,"Inspect the response in a browser at the same URL for more context.")}return n}export async function dblpFetchJson(e,t){const r=await d(`${DBLP_ORIGIN}${e}`,t,"application/json");let n;try{n=await r.json()}catch(i){throw new s(`${t} returned malformed JSON: ${i?.message??i}`)}const o=String(n?.result?.status?.["@code"]??"").trim();if(!o)throw new s(`${t} returned JSON without result.status.@code`,"dblp changed its JSON envelope or returned a partial error payload; inspect the raw response in a browser.");if(o!=="200"){const i=String(n?.result?.status?.text??"").trim();throw new s(`${t} returned API status ${o}${i?` (${i})`:""}`,"dblp accepted the HTTP request but reported an API-level failure. Retry later or inspect the same query in a browser.")}return n}export async function dblpFetchXml(e,t){return(await d(`${DBLP_ORIGIN}${e}`,t,"application/xml")).text()}export function coerceInt(e){if(e===void 0||e===null||e==="")return NaN;const t=typeof e==="number"?e:Number(e);return Number.isFinite(t)&&Number.isInteger(t)?t:NaN}export function requireBoundedInt(e,t,r,n="limit"){const i=coerceInt(e??t);if(!Number.isInteger(i)||i<=0)throw new c(`dblp ${n} must be a positive integer`);if(i>r)throw new c(`dblp ${n} must be <= ${r}`);return i}export function requireQuery(e,t="query"){const r=String(e??"").trim();if(!r)throw new c(`dblp ${t} cannot be empty`);return r}export function requireRecordKey(e){const t=String(e??"").trim();if(!t)throw new c("dblp paper key is required");if(!y.test(t))throw new c(`dblp paper key "${e}" is not a valid record key`,'Expected something like "conf/nips/VaswaniSPUJGKP17" — copy the `key` column from `dblp search`.');return t}export function decodeXmlEntities(e){if(!e)return"";return String(e).replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&apos;/g,"'").replace(/&quot;/g,'"').replace(/&#x([0-9a-fA-F]+);/g,(t,r)=>String.fromCodePoint(parseInt(r,16))).replace(/&#(\d+);/g,(t,r)=>String.fromCodePoint(parseInt(r,10)))}function u(e){return String(e||"").replace(/\s+\d{4,}$/,"").trim()}export function normalizeAuthors(e){if(!e)return[];const t=e?.author;if(!t)return[];return(Array.isArray(t)?t:[t]).map((n)=>{if(n&&typeof n==="object")return u(n.text||n["#text"]||"");return u(String(n))}).filter(Boolean)}export function searchHitToRow(e,t){const r=e?.info??{},n=normalizeAuthors(r.authors),o=String(r.key??"").trim();return{rank:t,key:o,title:h(decodeXmlEntities(r.title??"")).trim(),authors:n.join(", "),venue:decodeXmlEntities(r.venue??""),year:String(r.year??"").trim(),type:w(r.type),doi:String(r.doi??"").trim(),url:String(r.ee??r.url??"").trim()}}function h(e){return String(e||"").replace(/\.\s*$/,"")}function w(e){if(!e)return"";const t=String(e);if(/Conference and Workshop/i.test(t))return"conf";if(/Journal Articles/i.test(t))return"journal";if(/Books and Theses/i.test(t))return"book";if(/Editorship/i.test(t))return"editorship";if(/Reference Works/i.test(t))return"reference";if(/Informal/i.test(t))return"preprint";return t.toLowerCase().split(/\s+/)[0]}export function extractFirst(e,t){const r=String(e||"").match(new RegExp(`<${t}\\b[^>]*>([\\s\\S]*?)<\\/${t}>`));return r?r[1]:""}export function extractAll(e,t){const r=[],n=new RegExp(`<${t}\\b[^>]*>([\\s\\S]*?)<\\/${t}>`,"g");let o;while((o=n.exec(String(e||"")))!==null)r.push(o[1]);return r}export function extractOpenAccessLink(e){const t=String(e||"").match(/<ee\b[^>]*type=["']oa["'][^>]*>([\s\S]*?)<\/ee>/);if(t)return t[1].trim();const r=String(e||"").match(/<ee\b[^>]*>([\s\S]*?)<\/ee>/);return r?r[1].trim():""}export function extractRecordKey(e){const t=String(e||"").match(/<(?:article|inproceedings|incollection|proceedings|book|phdthesis|mastersthesis)\b[^>]*\bkey="([^"]+)"/);return t?t[1]:""}export function extractRecordType(e){const t=String(e||"").match(/<(article|inproceedings|incollection|proceedings|book|phdthesis|mastersthesis)\b/);if(!t)return"";switch(t[1]){case"inproceedings":return"conf";case"article":return"journal";case"incollection":return"incollection";case"proceedings":return"editorship";case"book":return"book";case"phdthesis":return"phdthesis";case"mastersthesis":return"mastersthesis";default:return t[1]}}export function recordXmlToRow(e){const t=extractRecordKey(e),r=extractRecordType(e),n=h(decodeXmlEntities(extractFirst(e,"title"))),o=extractAll(e,"author").map((a)=>u(decodeXmlEntities(a))),i=decodeXmlEntities(extractFirst(e,"year")),l=decodeXmlEntities(extractFirst(e,"pages")),f=r==="conf"?decodeXmlEntities(extractFirst(e,"booktitle")):decodeXmlEntities(extractFirst(e,"journal")),m=(()=>{const a=String(e||"").match(/<ee\b[^>]*>([^<]*?(?:doi\.org\/|10\.[^"<]+))<\/ee>/i);if(!a)return"";const p=a[1].replace(/^https?:\/\/(?:dx\.)?doi\.org\//i,"");return p.startsWith("10.")?p:""})();return{key:t,type:r,title:n,authors:o.join(", "),venue:f,year:i,pages:l,doi:m,open_access_url:extractOpenAccessLink(e),dblp_url:t?`${DBLP_ORIGIN}/rec/${t}.html`:""}}export const SEARCH_COLUMNS=["rank","key","title","authors","venue","year","type","doi","url"],PAPER_COLUMNS=["key","type","title","authors","venue","year","pages","doi","open_access_url","dblp_url"];
@@ -1 +1 @@
1
- import{cli as u,Strategy as c}from"@jackwener/opencli/registry";import{EmptyResultError as l}from"@jackwener/opencli/errors";import{DBLP_ORIGIN as p,decodeXmlEntities as m,dblpFetchJson as f,requireBoundedInt as d,requireQuery as y}from"./utils.js";function h(t){const e=String(t??"").trim();if(!e)return"";if(/Conference or Workshop/i.test(e))return"conf";if(/Journal/i.test(e))return"journal";if(/Series/i.test(e))return"series";if(/Book/i.test(e))return"book";if(/Reference/i.test(e))return"reference";return e.toLowerCase().split(/\s+/)[0]}function v(t,e){const r=t?.info??{},n=String(r.url??"").trim();return{rank:e,acronym:String(r.acronym??"").trim(),venue:m(r.venue??""),type:h(r.type),url:n.startsWith("http")?n:n?`${p}${n.startsWith("/")?"":"/"}${n}`:""}}u({site:"dblp",name:"venue",access:"read",description:"Search dblp venue registry (conferences / journals) by name or acronym",domain:"dblp.org",strategy:c.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Venue name or acronym (e.g. "ICLR", "neural networks")'},{name:"limit",type:"int",default:20,help:"Max venues (1-100, single dblp page)"}],columns:["rank","acronym","venue","type","url"],func:async(t)=>{const e=y(t.query),r=d(t.limit,20,100),n=`/search/venue/api?q=${encodeURIComponent(e)}&format=json&h=${r}`,o=(await f(n,"dblp venue"))?.result?.hits?.hit,i=Array.isArray(o)?o:[];if(i.length===0)throw new l("dblp venue",`No dblp venues matched "${e}".`);return i.slice(0,r).map((s,a)=>v(s,a+1))}});
1
+ import{cli as a,Strategy as c}from"@jackwener/opencli/registry";import{EmptyResultError as l}from"@jackwener/opencli/errors";import{DBLP_ORIGIN as m,decodeXmlEntities as p,dblpFetchJson as f,requireBoundedInt as y,requireQuery as d}from"./utils.js";function h(n){const e=String(n??"").trim();if(!e)return"";if(/Conference or Workshop/i.test(e))return"conf";if(/Journal/i.test(e))return"journal";if(/Series/i.test(e))return"series";if(/Book/i.test(e))return"book";if(/Reference/i.test(e))return"reference";return e.toLowerCase().split(/\s+/)[0]}function b(n,e){const r=n?.info??{},t=String(r.url??"").trim();return{rank:e,acronym:String(r.acronym??"").trim(),venue:p(r.venue??""),type:h(r.type),url:t.startsWith("http")?t:t?`${m}${t.startsWith("/")?"":"/"}${t}`:""}}a({site:"dblp",name:"venue",access:"read",description:"Search dblp venue registry (conferences / journals) by name or acronym",domain:"dblp.org",strategy:c.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Venue name or acronym (e.g. "ICLR", "neural networks")'},{name:"limit",type:"int",default:20,help:"Max venues (1-100, single dblp page)"}],columns:["rank","acronym","venue","type","url"],func:async(n)=>{const e=d(n.query),r=y(n.limit,20,100),t=`/search/venue/api?q=${encodeURIComponent(e)}&format=json&h=${r}`,o=(await f(t,"dblp venue"))?.result?.hits?.hit,i=Array.isArray(o)?o:[];if(i.length===0)throw new l("dblp venue",`No dblp venues matched "${e}".`);return i.slice(0,r).map((s,u)=>b(s,u+1))}});
@@ -1 +1 @@
1
- import{cli as _,Strategy as x}from"@jackwener/opencli/registry";import{CliError as L,CommandExecutionError as V,EXIT_CODES as U,TimeoutError as X}from"@jackwener/opencli/errors";import{DEEPSEEK_DOMAIN as y,DEEPSEEK_URL as F,ensureOnDeepSeek as S,selectModel as M,setFeature as f,sendMessage as C,sendWithFile as T,getBubbleCount as A,waitForResponse as B,parseBoolFlag as v,withRetry as Y,pickResumeUrl as c,TEXTAREA_SELECTOR as b}from"./utils.js";export const askCommand=_({site:"deepseek",name:"ask",access:"write",description:"Send a prompt to DeepSeek and get the response",domain:y,strategy:x.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"prompt",fromFile:"prompt-file",positional:!0,required:!0,help:"Prompt to send"},{name:"timeout",type:"int",default:120,help:"Max seconds to wait for response"},{name:"new",type:"boolean",default:!1,help:"Start a new chat before sending"},{name:"model",default:"instant",choices:["instant","expert","vision"],help:"Model to use: instant, expert, or vision"},{name:"think",type:"boolean",default:!1,help:"Enable DeepThink mode"},{name:"search",type:"boolean",default:!1,help:"Enable web search"},{name:"file",help:"Attach a file (PDF, image, text) with the prompt"}],func:async(q,z)=>{const $=z.prompt,K=(z.timeout||120)*1000,Q=v(z.think),N=v(z.search),G=z.model||"instant";if((G==="vision"||G==="expert")&&N)throw new L("ARGUMENT",`DeepSeek ${G} mode does not support --search.`,"Run without --search, or use --model instant for web search.",U.USAGE_ERROR);if(v(z.new)){await q.goto(F);try{await q.wait({selector:b,timeout:8})}catch{}}else if(await S(q)){const H=await c(q);if(!H)throw new V("Workspace was recycled but no prior conversation could be loaded","Pass --new to start a fresh chat, or wait for the sidebar to populate before retrying.");await q.goto(H);try{await q.wait({selector:b,timeout:5})}catch{}}const P=(await q.evaluate("window.location.href")||"").includes("/a/chat/s/"),D=z.__opencliOptionSources?.model==="cli";if(P&&D)throw new L("ARGUMENT",`Cannot switch to ${G} model inside an existing conversation.`,"Re-run with --new to start a fresh chat before selecting a model.",U.USAGE_ERROR);if(!P){if(!(await Y(()=>M(q,G)))?.ok)throw new V(`Could not switch to ${G} model`)}if(!(await Y(()=>f(q,"DeepThink",Q)))?.ok&&Q)throw new V("Could not enable DeepThink");let j;if(G!=="vision"&&G!=="expert"){j=await Y(()=>f(q,"Search",N));if(!j?.ok&&N)throw new V("Could not enable Search")}if(z.file){const W=await Y(()=>A(q));try{const J=await T(q,z.file,$);if(J&&!J.ok)throw new V(J.reason||"Failed to attach file")}catch(J){if(!String(J?.message||J).includes("Promise was collected"))throw J}const H=await B(q,W,$,K,Q);if(!H)throw new X("deepseek ask",z.timeout,"No DeepSeek reply observed before timeout. Retry with --timeout increased.");if(Q&&typeof H==="object"&&H.response!==void 0)return[H];return[{response:H}]}const O=await Y(()=>A(q)),I=await Y(()=>C(q,$));if(!I?.ok)throw new V(I?.reason||"Failed to send message");const Z=await B(q,O,$,K,Q);if(!Z)throw new X("deepseek ask",z.timeout,"No DeepSeek reply observed before timeout. Retry with --timeout increased.");if(Q&&typeof Z==="object"&&Z.response!==void 0)return[Z];return[{response:Z}]}});
1
+ import{cli as T,Strategy as x}from"@jackwener/opencli/registry";import{CliError as E,CommandExecutionError as r,EXIT_CODES as b,TimeoutError as R}from"@jackwener/opencli/errors";import{DEEPSEEK_DOMAIN as M,DEEPSEEK_URL as O,ensureOnDeepSeek as U,selectModel as A,setFeature as S,sendMessage as F,sendWithFile as _,getBubbleCount as y,waitForResponse as k,parseBoolFlag as h,withRetry as a,pickResumeUrl as P,TEXTAREA_SELECTOR as v}from"./utils.js";export const askCommand=T({site:"deepseek",name:"ask",access:"write",description:"Send a prompt to DeepSeek and get the response",domain:M,strategy:x.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"prompt",fromFile:"prompt-file",positional:!0,required:!0,help:"Prompt to send"},{name:"timeout",type:"int",default:120,help:"Max seconds to wait for response"},{name:"new",type:"boolean",default:!1,help:"Start a new chat before sending"},{name:"model",default:"instant",choices:["instant","expert","vision"],help:"Model to use: instant, expert, or vision"},{name:"think",type:"boolean",default:!1,help:"Enable DeepThink mode"},{name:"search",type:"boolean",default:!1,help:"Enable web search"},{name:"file",help:"Attach a file (PDF, image, text) with the prompt"}],func:async(e,t)=>{const c=t.prompt,m=(t.timeout||120)*1000,s=h(t.think),d=h(t.search),o=t.model||"instant";if((o==="vision"||o==="expert")&&d)throw new E("ARGUMENT",`DeepSeek ${o} mode does not support --search.`,"Run without --search, or use --model instant for web search.",b.USAGE_ERROR);if(h(t.new)){await e.goto(O);try{await e.wait({selector:v,timeout:8})}catch{}}else if(await U(e)){const n=await P(e);if(!n)throw new r("Workspace was recycled but no prior conversation could be loaded","Pass --new to start a fresh chat, or wait for the sidebar to populate before retrying.");await e.goto(n);try{await e.wait({selector:v,timeout:5})}catch{}}const w=(await e.evaluate("window.location.href")||"").includes("/a/chat/s/"),D=t.__opencliOptionSources?.model==="cli";if(w&&D)throw new E("ARGUMENT",`Cannot switch to ${o} model inside an existing conversation.`,"Re-run with --new to start a fresh chat before selecting a model.",b.USAGE_ERROR);if(!w){if(!(await a(()=>A(e,o)))?.ok)throw new r(`Could not switch to ${o} model`)}if(!(await a(()=>S(e,"DeepThink",s)))?.ok&&s)throw new r("Could not enable DeepThink");let f;if(o!=="vision"&&o!=="expert"){f=await a(()=>S(e,"Search",d));if(!f?.ok&&d)throw new r("Could not enable Search")}if(t.file){const u=await a(()=>y(e));try{const i=await _(e,t.file,c);if(i&&!i.ok)throw new r(i.reason||"Failed to attach file")}catch(i){if(!String(i?.message||i).includes("Promise was collected"))throw i}const n=await k(e,u,c,m,s);if(!n)throw new R("deepseek ask",t.timeout,"No DeepSeek reply observed before timeout. Retry with --timeout increased.");if(s&&typeof n==="object"&&n.response!==void 0)return[n];return[{response:n}]}const C=await a(()=>y(e)),p=await a(()=>F(e,c));if(!p?.ok)throw new r(p?.reason||"Failed to send message");const l=await k(e,C,c,m,s);if(!l)throw new R("deepseek ask",t.timeout,"No DeepSeek reply observed before timeout. Retry with --timeout increased.");if(s&&typeof l==="object"&&l.response!==void 0)return[l];return[{response:l}]}});
@@ -1,4 +1,4 @@
1
- import{AuthRequiredError as J,CommandExecutionError as G}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as L}from"../_shared/site-auth.js";const K=`(async () => {
1
+ import{AuthRequiredError as n,CommandExecutionError as r}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as i}from"../_shared/site-auth.js";const a=`(async () => {
2
2
  try {
3
3
  let token = '';
4
4
  const raw = localStorage.getItem('userToken');
@@ -19,4 +19,4 @@ import{AuthRequiredError as J,CommandExecutionError as G}from"@jackwener/opencli
19
19
  } catch (e) {
20
20
  return { kind: 'exception', detail: String(e && e.message || e) };
21
21
  }
22
- })()`;async function N(F){await F.goto("https://chat.deepseek.com/");await F.wait(2);const z=await F.evaluate(K);if(z?.kind==="auth")throw new J("chat.deepseek.com",z.detail);if(z?.kind==="http")throw new G(`HTTP ${z.httpStatus} from DeepSeek users/current`);if(z?.kind==="render-error")throw new G(z.detail);if(z?.kind==="exception")throw new G(`DeepSeek whoami failed: ${z.detail}`);if(!z?.ok)throw new G(`Unexpected DeepSeek probe: ${JSON.stringify(z)}`);return{user_id:z.user_id,name:z.name}}L({site:"deepseek",domain:"chat.deepseek.com",loginUrl:"https://chat.deepseek.com/sign_in",columns:["user_id","name"],verify:N,poll:async(F)=>{const z=await F.evaluate(K);if(!z?.ok)throw new J("chat.deepseek.com","Waiting for DeepSeek login");return{user_id:z.user_id,name:z.name}}});
22
+ })()`;async function o(t){await t.goto("https://chat.deepseek.com/");await t.wait(2);const e=await t.evaluate(a);if(e?.kind==="auth")throw new n("chat.deepseek.com",e.detail);if(e?.kind==="http")throw new r(`HTTP ${e.httpStatus} from DeepSeek users/current`);if(e?.kind==="render-error")throw new r(e.detail);if(e?.kind==="exception")throw new r(`DeepSeek whoami failed: ${e.detail}`);if(!e?.ok)throw new r(`Unexpected DeepSeek probe: ${JSON.stringify(e)}`);return{user_id:e.user_id,name:e.name}}i({site:"deepseek",domain:"chat.deepseek.com",loginUrl:"https://chat.deepseek.com/sign_in",columns:["user_id","name"],verify:o,poll:async(t)=>{const e=await t.evaluate(a);if(!e?.ok)throw new n("chat.deepseek.com","Waiting for DeepSeek login");return{user_id:e.user_id,name:e.name}}});
@@ -1 +1 @@
1
- import{cli as B,Strategy as F}from"@jackwener/opencli/registry";import{EmptyResultError as H}from"@jackwener/opencli/errors";import{DEEPSEEK_DOMAIN as J,MESSAGE_SELECTOR as Q,ensureOnDeepSeek as U,getVisibleMessages as W,parseDeepSeekConversationId as X}from"./utils.js";export const detailCommand=B({site:"deepseek",name:"detail",access:"read",description:"Read a specific DeepSeek conversation by ID",domain:J,strategy:F.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"id",required:!0,positional:!0,help:"Conversation ID (UUID) or full /a/chat/s/<id> URL"}],columns:["Role","Text"],func:async(f,z)=>{const q=X(z.id);await U(f);await f.goto(`https://chat.deepseek.com/a/chat/s/${q}`);try{await f.wait({selector:Q,timeout:10})}catch{}const x=await W(f);if(x.length===0)throw new H("deepseek detail",`No visible messages found for conversation ${q}. Verify the ID is correct and that you are logged in.`);return x}});
1
+ import{cli as i,Strategy as o}from"@jackwener/opencli/registry";import{EmptyResultError as r}from"@jackwener/opencli/errors";import{DEEPSEEK_DOMAIN as n,MESSAGE_SELECTOR as c,ensureOnDeepSeek as d,getVisibleMessages as l,parseDeepSeekConversationId as m}from"./utils.js";export const detailCommand=i({site:"deepseek",name:"detail",access:"read",description:"Read a specific DeepSeek conversation by ID",domain:n,strategy:o.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"id",required:!0,positional:!0,help:"Conversation ID (UUID) or full /a/chat/s/<id> URL"}],columns:["Role","Text"],func:async(e,a)=>{const t=m(a.id);await d(e);await e.goto(`https://chat.deepseek.com/a/chat/s/${t}`);try{await e.wait({selector:c,timeout:10})}catch{}const s=await l(e);if(s.length===0)throw new r("deepseek detail",`No visible messages found for conversation ${t}. Verify the ID is correct and that you are logged in.`);return s}});
@@ -1 +1 @@
1
- import{cli as f,Strategy as q}from"@jackwener/opencli/registry";import{CommandExecutionError as v}from"@jackwener/opencli/errors";import{DEEPSEEK_DOMAIN as z,DEEPSEEK_URL as B,TEXTAREA_SELECTOR as F}from"./utils.js";export const newCommand=f({site:"deepseek",name:"new",access:"read",description:"Start a new conversation in DeepSeek",domain:z,strategy:q.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:["Status"],func:async(b)=>{await b.goto(B);try{await b.wait({selector:F,timeout:8})}catch{throw new v("DeepSeek composer did not mount within 8 s","Verify you are logged into chat.deepseek.com.")}return[{Status:"New chat started"}]}});
1
+ import{cli as t,Strategy as o}from"@jackwener/opencli/registry";import{CommandExecutionError as r}from"@jackwener/opencli/errors";import{DEEPSEEK_DOMAIN as a,DEEPSEEK_URL as n,TEXTAREA_SELECTOR as s}from"./utils.js";export const newCommand=t({site:"deepseek",name:"new",access:"read",description:"Start a new conversation in DeepSeek",domain:a,strategy:o.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:["Status"],func:async(e)=>{await e.goto(n);try{await e.wait({selector:s,timeout:8})}catch{throw new r("DeepSeek composer did not mount within 8 s","Verify you are logged into chat.deepseek.com.")}return[{Status:"New chat started"}]}});
@@ -1 +1 @@
1
- import{cli as v,Strategy as x}from"@jackwener/opencli/registry";import{DEEPSEEK_DOMAIN as z,ensureOnDeepSeek as B,getVisibleMessages as C}from"./utils.js";export const readCommand=v({site:"deepseek",name:"read",access:"read",description:"Read the current DeepSeek conversation",domain:z,strategy:x.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:["Role","Text"],func:async(h)=>{await B(h);const q=await C(h);if(q.length>0)return q;return[{Role:"system",Text:"No visible messages found."}]}});
1
+ import{cli as t,Strategy as r}from"@jackwener/opencli/registry";import{DEEPSEEK_DOMAIN as a,ensureOnDeepSeek as n,getVisibleMessages as o}from"./utils.js";export const readCommand=t({site:"deepseek",name:"read",access:"read",description:"Read the current DeepSeek conversation",domain:a,strategy:r.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:["Role","Text"],func:async(e)=>{await n(e);const s=await o(e);if(s.length>0)return s;return[{Role:"system",Text:"No visible messages found."}]}});
@@ -1,12 +1,12 @@
1
- import{cli as Z,Strategy as $}from"@jackwener/opencli/registry";import{CommandExecutionError as H}from"@jackwener/opencli/errors";import{DEEPSEEK_DOMAIN as h,MESSAGE_SELECTOR as F,TEXTAREA_SELECTOR as V,parseDeepSeekConversationId as G}from"./utils.js";export const sendCommand=Z({site:"deepseek",name:"send",access:"write",description:"Send a prompt to a specific DeepSeek conversation by ID, without waiting for a response",domain:h,strategy:$.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"id",required:!0,positional:!0,help:"Conversation ID (UUID) or full /a/chat/s/<id> URL"},{name:"prompt",fromFile:!0,required:!0,positional:!0,help:"Prompt to send"},{name:"timeout",type:"int",required:!1,default:60,help:"Max seconds for the overall command (default: 60)"}],columns:["Status","InjectedText"],func:async(q,z)=>{const B=G(z.id),Q=z.prompt;await q.goto(`https://chat.deepseek.com/a/chat/s/${B}`);await J(q);if(!await q.evaluate(`(() => {
2
- const box = document.querySelector('${V}');
1
+ import{cli as l,Strategy as d}from"@jackwener/opencli/registry";import{CommandExecutionError as o}from"@jackwener/opencli/errors";import{DEEPSEEK_DOMAIN as c,MESSAGE_SELECTOR as p,TEXTAREA_SELECTOR as s,parseDeepSeekConversationId as m}from"./utils.js";export const sendCommand=l({site:"deepseek",name:"send",access:"write",description:"Send a prompt to a specific DeepSeek conversation by ID, without waiting for a response",domain:c,strategy:d.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"id",required:!0,positional:!0,help:"Conversation ID (UUID) or full /a/chat/s/<id> URL"},{name:"prompt",fromFile:!0,required:!0,positional:!0,help:"Prompt to send"},{name:"timeout",type:"int",required:!1,default:60,help:"Max seconds for the overall command (default: 60)"}],columns:["Status","InjectedText"],func:async(e,t)=>{const n=m(t.id),r=t.prompt;await e.goto(`https://chat.deepseek.com/a/chat/s/${n}`);await f(e);if(!await e.evaluate(`(() => {
2
+ const box = document.querySelector('${s}');
3
3
  if (!box) return false;
4
4
  box.focus();
5
5
  return document.activeElement === box;
6
- })()`))throw new H("Could not focus DeepSeek textarea before native input");if(typeof q.nativeType!=="function")throw new H("Native CDP input is not available on this page object","deepseek send relies on Input.insertText; ensure the daemon and extension are up to date.");await q.nativeType(Q);await q.wait(0.6);const Y=JSON.stringify(Q),W=await q.evaluate(`(async () => {
7
- const TEXTAREA = '${V}';
8
- const MESSAGE = '${F}';
9
- const expected = ${Y};
6
+ })()`))throw new o("Could not focus DeepSeek textarea before native input");if(typeof e.nativeType!=="function")throw new o("Native CDP input is not available on this page object","deepseek send relies on Input.insertText; ensure the daemon and extension are up to date.");await e.nativeType(r);await e.wait(0.6);const u=JSON.stringify(r),i=await e.evaluate(`(async () => {
7
+ const TEXTAREA = '${s}';
8
+ const MESSAGE = '${p}';
9
+ const expected = ${u};
10
10
  const isUser = (m) => m.className.split(/\\s+/).length > 2;
11
11
  const box = document.querySelector(TEXTAREA);
12
12
  if (!box) return { ok: false, reason: 'textarea not found' };
@@ -47,4 +47,4 @@ import{cli as Z,Strategy as $}from"@jackwener/opencli/registry";import{CommandEx
47
47
  }
48
48
  }
49
49
  return { ok: true };
50
- })()`).catch((U)=>{if(String(U?.message||U).includes("Promise was collected"))return{ok:!0};throw U});if(!W?.ok)throw new H(W?.reason||"Failed to send message");return[{Status:"Success",InjectedText:Q}]}});async function J(q){const z=`(() => !!document.querySelector('${V}'))()`;for(let B=0;B<10;B++){if(await q.evaluate(z))return;await q.wait(1)}throw new H("DeepSeek textarea did not mount within 10s; the conversation page may not have loaded")}
50
+ })()`).catch((a)=>{if(String(a?.message||a).includes("Promise was collected"))return{ok:!0};throw a});if(!i?.ok)throw new o(i?.reason||"Failed to send message");return[{Status:"Success",InjectedText:r}]}});async function f(e){const t=`(() => !!document.querySelector('${s}'))()`;for(let n=0;n<10;n++){if(await e.evaluate(t))return;await e.wait(1)}throw new o("DeepSeek textarea did not mount within 10s; the conversation page may not have loaded")}