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,5 +1,5 @@
1
- import{cli as Q,Strategy as V}from"@jackwener/opencli/registry";import{ArgumentError as j,CommandExecutionError as G,EmptyResultError as Z}from"@jackwener/opencli/errors";import{KIMI_DOMAIN as W,ensureOnKimi as X}from"./_utils.js";const Y=["Field","Value","Index","Key","Bytes","Name","Preview","Database","Version"];function D(z){const h=String(z?.storage||"local").trim().toLowerCase();if(h!=="local"&&h!=="session")throw new j("storage",'must be "local" or "session"');return h==="session"?"sessionStorage":"localStorage"}Q({site:"kimi",name:"storage-keys",access:"read",description:"List localStorage / sessionStorage keys on kimi.com (with byte sizes).",domain:W,strategy:V.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"storage",required:!1,default:"local",help:'"local" or "session"'},{name:"filter",required:!1,help:"Case-insensitive substring filter over keys"},{name:"limit",type:"int",required:!1,default:100}],columns:Y,func:async(z,h)=>{await X(z);const B=D(h),q=await z.evaluate(`(() => {
2
- const s = ${B};
1
+ import{cli as c,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as k,CommandExecutionError as b,EmptyResultError as f}from"@jackwener/opencli/errors";import{KIMI_DOMAIN as u,ensureOnKimi as d}from"./_utils.js";const y=["Field","Value","Index","Key","Bytes","Name","Preview","Database","Version"];function p(i){const e=String(i?.storage||"local").trim().toLowerCase();if(e!=="local"&&e!=="session")throw new k("storage",'must be "local" or "session"');return e==="session"?"sessionStorage":"localStorage"}c({site:"kimi",name:"storage-keys",access:"read",description:"List localStorage / sessionStorage keys on kimi.com (with byte sizes).",domain:u,strategy:m.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"storage",required:!1,default:"local",help:'"local" or "session"'},{name:"filter",required:!1,help:"Case-insensitive substring filter over keys"},{name:"limit",type:"int",required:!1,default:100}],columns:y,func:async(i,e)=>{await d(i);const a=p(e),t=await i.evaluate(`(() => {
2
+ const s = ${a};
3
3
  const out = [];
4
4
  for (let i = 0; i < s.length; i++) {
5
5
  const k = s.key(i);
@@ -7,8 +7,8 @@ import{cli as Q,Strategy as V}from"@jackwener/opencli/registry";import{ArgumentE
7
7
  out.push({ k, bytes: v.length });
8
8
  }
9
9
  return out;
10
- })()`),v=h?.filter?String(h.filter).toLowerCase():null,P=v?q.filter((F)=>F.k.toLowerCase().includes(v)):q;if(!P.length)throw new Z("kimi storage-keys",v?`No keys match "${v}".`:`${B} is empty.`);P.sort((F,H)=>F.k.localeCompare(H.k));const J=Number.isInteger(h?.limit)&&h.limit>0?h.limit:100;return P.slice(0,J).map((F,H)=>({Index:H+1,Key:F.k,Bytes:F.bytes}))}});Q({site:"kimi",name:"storage-get",access:"read",description:"Read a single localStorage / sessionStorage value on kimi.com. Auto-decodes JSON.",domain:W,strategy:V.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"key",positional:!0,required:!0,help:"Storage key"},{name:"storage",required:!1,default:"local"},{name:"max-bytes",type:"int",required:!1,default:4000}],columns:Y,func:async(z,h)=>{const B=String(h?.key||"").trim();if(!B)throw new j("key","is required");await X(z);const q=D(h),v=await z.evaluate(`${q}.getItem(${JSON.stringify(B)})`);if(v===null||v===void 0)throw new G(`Key not found in ${q}: ${B}`,"");const P=Number.isInteger(h["max-bytes"])&&h["max-bytes"]>0?h["max-bytes"]:4000;let J=v,F="string";try{J=JSON.parse(v);F=Array.isArray(J)?"array":typeof J}catch{}const H=F==="string"?J:JSON.stringify(J,null,2),$=H.length>P;return[{Field:"Key",Value:B},{Field:"Store",Value:q},{Field:"Type",Value:F},{Field:"Size",Value:`${H.length} chars${$?" (truncated)":""}`},{Field:"Value",Value:$?H.slice(0,P)+`
11
- ...(truncated)`:H}]}});Q({site:"kimi",name:"cookies",access:"read",description:"List kimi.com cookies visible to JavaScript (httpOnly cookies are deliberately not shown).",domain:W,strategy:V.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:Y,func:async(z)=>{await X(z);const h=await z.evaluate("document.cookie");if(!h)throw new Z("kimi cookies","document.cookie is empty (likely all cookies are httpOnly).");return h.split("; ").map((q)=>{const v=q.indexOf("=");if(v<0)return{name:q,value:""};return{name:q.slice(0,v),value:q.slice(v+1)}}).map((q,v)=>({Index:v+1,Name:q.name,Bytes:q.value.length,Preview:q.value.slice(0,40)+(q.value.length>40?"…":"")}))}});Q({site:"kimi",name:"idb-list",access:"read",description:"List IndexedDB databases on kimi.com.",domain:W,strategy:V.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:Y,func:async(z)=>{await X(z);const h=await z.evaluate(`(async () => {
10
+ })()`),s=e?.filter?String(e.filter).toLowerCase():null,l=s?t.filter((n)=>n.k.toLowerCase().includes(s)):t;if(!l.length)throw new f("kimi storage-keys",s?`No keys match "${s}".`:`${a} is empty.`);l.sort((n,r)=>n.k.localeCompare(r.k));const o=Number.isInteger(e?.limit)&&e.limit>0?e.limit:100;return l.slice(0,o).map((n,r)=>({Index:r+1,Key:n.k,Bytes:n.bytes}))}});c({site:"kimi",name:"storage-get",access:"read",description:"Read a single localStorage / sessionStorage value on kimi.com. Auto-decodes JSON.",domain:u,strategy:m.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"key",positional:!0,required:!0,help:"Storage key"},{name:"storage",required:!1,default:"local"},{name:"max-bytes",type:"int",required:!1,default:4000}],columns:y,func:async(i,e)=>{const a=String(e?.key||"").trim();if(!a)throw new k("key","is required");await d(i);const t=p(e),s=await i.evaluate(`${t}.getItem(${JSON.stringify(a)})`);if(s===null||s===void 0)throw new b(`Key not found in ${t}: ${a}`,"");const l=Number.isInteger(e["max-bytes"])&&e["max-bytes"]>0?e["max-bytes"]:4000;let o=s,n="string";try{o=JSON.parse(s);n=Array.isArray(o)?"array":typeof o}catch{}const r=n==="string"?o:JSON.stringify(o,null,2),g=r.length>l;return[{Field:"Key",Value:a},{Field:"Store",Value:t},{Field:"Type",Value:n},{Field:"Size",Value:`${r.length} chars${g?" (truncated)":""}`},{Field:"Value",Value:g?r.slice(0,l)+`
11
+ ...(truncated)`:r}]}});c({site:"kimi",name:"cookies",access:"read",description:"List kimi.com cookies visible to JavaScript (httpOnly cookies are deliberately not shown).",domain:u,strategy:m.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:y,func:async(i)=>{await d(i);const e=await i.evaluate("document.cookie");if(!e)throw new f("kimi cookies","document.cookie is empty (likely all cookies are httpOnly).");return e.split("; ").map((t)=>{const s=t.indexOf("=");if(s<0)return{name:t,value:""};return{name:t.slice(0,s),value:t.slice(s+1)}}).map((t,s)=>({Index:s+1,Name:t.name,Bytes:t.value.length,Preview:t.value.slice(0,40)+(t.value.length>40?"…":"")}))}});c({site:"kimi",name:"idb-list",access:"read",description:"List IndexedDB databases on kimi.com.",domain:u,strategy:m.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:y,func:async(i)=>{await d(i);const e=await i.evaluate(`(async () => {
12
12
  if (!indexedDB.databases) return [];
13
13
  return await indexedDB.databases();
14
- })()`);if(!Array.isArray(h)||!h.length)throw new Z("kimi idb-list","No IndexedDB databases.");return h.map((B,q)=>({Index:q+1,Database:B.name||"(unnamed)",Version:String(B.version||"")}))}});
14
+ })()`);if(!Array.isArray(e)||!e.length)throw new f("kimi idb-list","No IndexedDB databases.");return e.map((a,t)=>({Index:t+1,Database:a.name||"(unnamed)",Version:String(a.version||"")}))}});
package/clis/kimi/ui.js CHANGED
@@ -1,5 +1,5 @@
1
- import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{ArgumentError as B,CommandExecutionError as z,EmptyResultError as D}from"@jackwener/opencli/errors";import{KIMI_DOMAIN as Z,KIMI_URL as h,IS_VISIBLE_JS as $,ensureOnKimi as v,clickBySvgNameScript as N,navByHrefScript as x}from"./_utils.js";const b=["Mode","Status","Url","Field","Value","Index","Model","Active"],R={ppt:"/slides",docs:"/docs","deep-research":"/deep-research",websites:"/websites",sheets:"/sheets","agent-swarm":"/agent-swarm",code:"/code"};X({site:"kimi",name:"mode",access:"write",description:"Switch to a Kimi work mode: ppt | docs | deep-research | websites | sheets | agent-swarm | code. With no argument, lists modes.",domain:Z,strategy:Y.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"name",positional:!0,required:!1,help:"Mode name (omit to list all)"}],columns:b,func:async(q,F)=>{const P=String(F?.name||"").trim().toLowerCase();if(!P)return Object.entries(R).map(([T,H])=>({Mode:T,Status:"available",Url:h+H.slice(1)}));const G=R[P];if(!G)throw new B("name",`unknown mode "${P}". Known: ${Object.keys(R).join(", ")}`);await v(q);await q.goto(`${h}${G.slice(1)}`);await q.wait(1);const W=await q.evaluate("window.location.href");return[{Mode:P,Status:"navigated",Url:String(W||"")}]}});X({site:"kimi",name:"sidebar-toggle",access:"write",description:"Click the LeftBar svg to toggle the Kimi sidebar.",domain:Z,strategy:Y.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:b,func:async(q)=>{await v(q);const F=await q.evaluate(N("LeftBar",{last:!1}));if(!F?.ok)throw new z(F?.reason||"LeftBar svg not visible","");return[{Status:"toggled"}]}});X({site:"kimi",name:"view-all-history",access:"write",description:"Navigate to /chat/history (full conversation list page).",domain:Z,strategy:Y.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:b,func:async(q)=>{await q.goto(`${h}chat/history`);await q.wait(1);const F=await q.evaluate("window.location.href");return[{Status:"navigated",Url:String(F||"")}]}});X({site:"kimi",name:"settings",access:"write",description:"Open the Kimi settings page (/settings).",domain:Z,strategy:Y.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:b,func:async(q)=>{await q.goto(`${h}settings`);await q.wait(1);const F=await q.evaluate("window.location.href");return[{Status:"navigated",Url:String(F||"")}]}});X({site:"kimi",name:"account",access:"read",description:'Read account info from the Kimi sidebar (display name + plan label, e.g. "Allegretto").',domain:Z,strategy:Y.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:b,func:async(q)=>{await v(q);const F=await q.evaluate(`(() => {
2
- ${$}
1
+ import{cli as l,Strategy as c}from"@jackwener/opencli/registry";import{ArgumentError as y,CommandExecutionError as f,EmptyResultError as k}from"@jackwener/opencli/errors";import{KIMI_DOMAIN as d,KIMI_URL as v,IS_VISIBLE_JS as m,ensureOnKimi as g,clickBySvgNameScript as x,navByHrefScript as C}from"./_utils.js";const u=["Mode","Status","Url","Field","Value","Index","Model","Active"],S={ppt:"/slides",docs:"/docs","deep-research":"/deep-research",websites:"/websites",sheets:"/sheets","agent-swarm":"/agent-swarm",code:"/code"};l({site:"kimi",name:"mode",access:"write",description:"Switch to a Kimi work mode: ppt | docs | deep-research | websites | sheets | agent-swarm | code. With no argument, lists modes.",domain:d,strategy:c.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"name",positional:!0,required:!1,help:"Mode name (omit to list all)"}],columns:u,func:async(e,t)=>{const n=String(t?.name||"").trim().toLowerCase();if(!n)return Object.entries(S).map(([s,r])=>({Mode:s,Status:"available",Url:v+r.slice(1)}));const i=S[n];if(!i)throw new y("name",`unknown mode "${n}". Known: ${Object.keys(S).join(", ")}`);await g(e);await e.goto(`${v}${i.slice(1)}`);await e.wait(1);const a=await e.evaluate("window.location.href");return[{Mode:n,Status:"navigated",Url:String(a||"")}]}});l({site:"kimi",name:"sidebar-toggle",access:"write",description:"Click the LeftBar svg to toggle the Kimi sidebar.",domain:d,strategy:c.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:u,func:async(e)=>{await g(e);const t=await e.evaluate(x("LeftBar",{last:!1}));if(!t?.ok)throw new f(t?.reason||"LeftBar svg not visible","");return[{Status:"toggled"}]}});l({site:"kimi",name:"view-all-history",access:"write",description:"Navigate to /chat/history (full conversation list page).",domain:d,strategy:c.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:u,func:async(e)=>{await e.goto(`${v}chat/history`);await e.wait(1);const t=await e.evaluate("window.location.href");return[{Status:"navigated",Url:String(t||"")}]}});l({site:"kimi",name:"settings",access:"write",description:"Open the Kimi settings page (/settings).",domain:d,strategy:c.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:u,func:async(e)=>{await e.goto(`${v}settings`);await e.wait(1);const t=await e.evaluate("window.location.href");return[{Status:"navigated",Url:String(t||"")}]}});l({site:"kimi",name:"account",access:"read",description:'Read account info from the Kimi sidebar (display name + plan label, e.g. "Allegretto").',domain:d,strategy:c.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[],columns:u,func:async(e)=>{await g(e);const t=await e.evaluate(`(() => {
2
+ ${m}
3
3
  const avatar = document.querySelector('img[src*="avatar.moonshot.cn"]');
4
4
  if (!avatar) return null;
5
5
  // The display name + plan are siblings in a parent container.
@@ -14,8 +14,8 @@ import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{ArgumentE
14
14
  avatarAlt: avatar.alt || '',
15
15
  labels: uniq.slice(0, 10),
16
16
  };
17
- })()`);if(!F)throw new z("No avatar found — not logged in?","");const P=[{Field:"AvatarAlt",Value:F.avatarAlt||"(none)"},{Field:"AvatarUrl",Value:F.avatarUrl}];F.labels.forEach((G,W)=>P.push({Field:`Label[${W+1}]`,Value:G}));return P}});X({site:"kimi",name:"model",access:"write",description:'Read the current Kimi model (e.g. "K2.6 思考") or switch by clicking the model dropdown. With no argument, returns current; with --list, opens dropdown + lists; with --set <name>, switches.',domain:Z,strategy:Y.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"list",type:"boolean",default:!1,help:"Open model dropdown + list options"},{name:"set",required:!1,help:"Substring (case-insensitive) of model to switch to"}],columns:b,func:async(q,F)=>{await v(q);const P=F?.list===!0||F?.list==="true",G=String(F?.set||"").trim(),W=await q.evaluate(`(() => {
18
- ${$}
17
+ })()`);if(!t)throw new f("No avatar found — not logged in?","");const n=[{Field:"AvatarAlt",Value:t.avatarAlt||"(none)"},{Field:"AvatarUrl",Value:t.avatarUrl}];t.labels.forEach((i,a)=>n.push({Field:`Label[${a+1}]`,Value:i}));return n}});l({site:"kimi",name:"model",access:"write",description:'Read the current Kimi model (e.g. "K2.6 思考") or switch by clicking the model dropdown. With no argument, returns current; with --list, opens dropdown + lists; with --set <name>, switches.',domain:d,strategy:c.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!1,args:[{name:"list",type:"boolean",default:!1,help:"Open model dropdown + list options"},{name:"set",required:!1,help:"Substring (case-insensitive) of model to switch to"}],columns:u,func:async(e,t)=>{await g(e);const n=t?.list===!0||t?.list==="true",i=String(t?.set||"").trim(),a=await e.evaluate(`(() => {
18
+ ${m}
19
19
  // The model button is a div containing a Down_b svg + a span with model name.
20
20
  const svgs = Array.from(document.querySelectorAll('svg[name="Down_b"]')).filter(isVisible);
21
21
  for (const svg of svgs) {
@@ -30,8 +30,8 @@ import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{ArgumentE
30
30
  }
31
31
  }
32
32
  return '';
33
- })()`);if(!P&&!G)return[{Index:1,Model:W||"(unknown)",Active:"yes"}];await q.evaluate(`(() => {
34
- ${$}
33
+ })()`);if(!n&&!i)return[{Index:1,Model:a||"(unknown)",Active:"yes"}];await e.evaluate(`(() => {
34
+ ${m}
35
35
  const svgs = Array.from(document.querySelectorAll('svg[name="Down_b"]')).filter(isVisible);
36
36
  // The model trigger is usually the one with a sibling span starting with "K"
37
37
  for (const svg of svgs) {
@@ -46,8 +46,8 @@ import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{ArgumentE
46
46
  p = p.parentElement;
47
47
  }
48
48
  }
49
- })()`);await q.wait(0.5);const T=await q.evaluate(`(() => {
50
- ${$}
49
+ })()`);await e.wait(0.5);const s=await e.evaluate(`(() => {
50
+ ${m}
51
51
  // Dropdown items appear in a floating popover.
52
52
  const popovers = Array.from(document.querySelectorAll('[class*="popover"i], [class*="dropdown"i], [role="menu"], [role="listbox"]')).filter(isVisible)
53
53
  .filter((el) => { const r = el.getBoundingClientRect(); return r.width < 600 && r.height < 600; });
@@ -59,8 +59,8 @@ import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{ArgumentE
59
59
  .filter((t) => t && t.length < 80 && (/K\\d|Kimi|Pro\\b|Auto|思考/.test(t)))
60
60
  .filter((t, i, arr) => arr.indexOf(t) === i)
61
61
  .slice(0, 20);
62
- })()`);if(G){const H=(Q)=>String(Q||"").toLowerCase().replace(/[^a-z0-9.\u4e00-\u9fa5]+/g,""),f=H(G),j=T.findIndex((Q)=>H(Q)===f),J=j>=0?[]:T.map((Q,C)=>({model:Q,index:C})).filter((Q)=>H(Q.model).includes(f));if(j<0&&J.length>1){try{await q.evaluate("document.body.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));")}catch{}throw new B("set",`Model "${G}" is ambiguous: ${J.map((Q)=>Q.model).join(", ")}`)}const A=j>=0?j:J[0]?.index??-1;if(A<0){try{await q.evaluate("document.body.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));")}catch{}throw new B("set",`No model matched "${G}". Available: ${T.join(", ")}`)}const V=await q.evaluate(`(() => {
63
- ${$}
62
+ })()`);if(i){const r=(o)=>String(o||"").toLowerCase().replace(/[^a-z0-9.\u4e00-\u9fa5]+/g,""),p=r(i),w=s.findIndex((o)=>r(o)===p),h=w>=0?[]:s.map((o,E)=>({model:o,index:E})).filter((o)=>r(o.model).includes(p));if(w<0&&h.length>1){try{await e.evaluate("document.body.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));")}catch{}throw new y("set",`Model "${i}" is ambiguous: ${h.map((o)=>o.model).join(", ")}`)}const A=w>=0?w:h[0]?.index??-1;if(A<0){try{await e.evaluate("document.body.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));")}catch{}throw new y("set",`No model matched "${i}". Available: ${s.join(", ")}`)}const b=await e.evaluate(`(() => {
63
+ ${m}
64
64
  const popovers = Array.from(document.querySelectorAll('[class*="popover"i], [class*="dropdown"i], [role="menu"], [role="listbox"]')).filter(isVisible);
65
65
  const pop = popovers[popovers.length - 1];
66
66
  if (!pop) return { ok: false };
@@ -71,8 +71,8 @@ import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{ArgumentE
71
71
  if (!target) return { ok: false };
72
72
  target.click();
73
73
  return { ok: true, clicked: (target.innerText || '').trim() };
74
- })()`);if(!V?.ok)throw new z("Failed to click model option","");await q.wait(0.5);const y=await q.evaluate(`(() => {
75
- ${$}
74
+ })()`);if(!b?.ok)throw new f("Failed to click model option","");await e.wait(0.5);const K=await e.evaluate(`(() => {
75
+ ${m}
76
76
  const svgs = Array.from(document.querySelectorAll('svg[name="Down_b"]')).filter(isVisible);
77
77
  for (const svg of svgs) {
78
78
  let p = svg.parentElement;
@@ -86,4 +86,4 @@ import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{ArgumentE
86
86
  }
87
87
  }
88
88
  return '';
89
- })()`);if(H(y)!==H(V.clicked))throw new z(`Kimi model switch did not verify the requested model: requested "${G}", current "${y||"not visible"}"`,"Open the Kimi model menu and verify the requested model is selectable, then retry.");return[{Index:1,Model:V.clicked,Active:"switched"}]}try{await q.evaluate("document.body.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));")}catch{}if(!T.length)throw new D("kimi model","Model dropdown opened but no options detected.");return T.map((H,f)=>({Index:f+1,Model:H,Active:H===W?"yes":""}))}});
89
+ })()`);if(r(K)!==r(b.clicked))throw new f(`Kimi model switch did not verify the requested model: requested "${i}", current "${K||"not visible"}"`,"Open the Kimi model menu and verify the requested model is selectable, then retry.");return[{Index:1,Model:b.clicked,Active:"switched"}]}try{await e.evaluate("document.body.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));")}catch{}if(!s.length)throw new k("kimi model","Model dropdown opened but no options detected.");return s.map((r,p)=>({Index:p+1,Model:r,Active:r===a?"yes":""}))}});
@@ -1,4 +1,4 @@
1
- import{cli as u,Strategy as f}from"@jackwener/opencli/registry";import{CommandExecutionError as n}from"@jackwener/opencli/errors";const y="kimi.com",g="https://www.kimi.com/",h=`${g}code/console`,p=`
1
+ import{cli as u,Strategy as f}from"@jackwener/opencli/registry";import{CommandExecutionError as s}from"@jackwener/opencli/errors";const y="kimi.com",g="https://www.kimi.com/",h=`${g}code/console`,p=`
2
2
  const isVisible = (el) => {
3
3
  if (!el) return false;
4
4
  const r = el.getBoundingClientRect();
@@ -7,7 +7,7 @@ import{cli as u,Strategy as f}from"@jackwener/opencli/registry";import{CommandEx
7
7
  if (cs.visibility === 'hidden' || cs.display === 'none' || cs.opacity === '0') return false;
8
8
  return true;
9
9
  };
10
- `,w=["本周用量","频限明细","我的权益","模型权限"];function b(t){const e=String(t||"").match(/(\d+(?:\.\d+)?)\s*%/);return e?Number(e[1]):null}function a(t,e){const r=t[e];if(!Array.isArray(r)||r.length===0)throw new n(`kimi usage returned malformed payload: missing "${e}" card`);const o=r.map((s)=>String(s||"").trim()).filter(Boolean);if(o.length===0)throw new n(`kimi usage returned malformed payload: missing "${e}" card`);return o}function d(t,e){const r=b(t[0]);if(!Number.isFinite(r))throw new n(`kimi usage returned malformed payload: "${e}" card is missing a percentage`);return r}u({site:"kimi",name:"usage",access:"read",description:"Read Kimi Code console usage cards: weekly quota, rate limit, membership, and model permission.",domain:y,strategy:f.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!0,args:[],columns:["weeklyUsagePct","weeklyResetIn","rateLimitPct","rateLimitResetIn","membershipName","membershipTier","modelPermission","modelCost"],func:async(t)=>{await t.goto(h);await t.wait(3);const e=await t.evaluate(`(() => {
10
+ `,w=["本周用量","频限明细","我的权益","模型权限"];function b(t){const e=String(t||"").match(/(\d+(?:\.\d+)?)\s*%/);return e?Number(e[1]):null}function c(t,e){const r=t[e];if(!Array.isArray(r)||r.length===0)throw new s(`kimi usage returned malformed payload: missing "${e}" card`);const n=r.map((o)=>String(o||"").trim()).filter(Boolean);if(n.length===0)throw new s(`kimi usage returned malformed payload: missing "${e}" card`);return n}function l(t,e){const r=b(t[0]);if(!Number.isFinite(r))throw new s(`kimi usage returned malformed payload: "${e}" card is missing a percentage`);return r}u({site:"kimi",name:"usage",access:"read",description:"Read Kimi Code console usage cards: weekly quota, rate limit, membership, and model permission.",domain:y,strategy:f.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!0,args:[],columns:["weeklyUsagePct","weeklyResetIn","rateLimitPct","rateLimitResetIn","membershipName","membershipTier","modelPermission","modelCost"],func:async(t)=>{await t.goto(h);await t.wait(3);const e=await t.evaluate(`(() => {
11
11
  ${p}
12
12
 
13
13
  const getDirectText = (el) => {
@@ -48,4 +48,4 @@ import{cli as u,Strategy as f}from"@jackwener/opencli/registry";import{CommandEx
48
48
  }
49
49
  }
50
50
  return cards;
51
- })()`);if(!e||typeof e!=="object"||Array.isArray(e))throw new n("kimi usage returned malformed payload: usage cards must be an object");if(Object.keys(e).length===0)throw new n("kimi usage returned malformed payload: no usage cards found on the console page");const r=a(e,"本周用量"),o=a(e,"频限明细"),s=a(e,"我的权益"),c=a(e,"模型权限"),l=d(r,"本周用量"),m=d(o,"频限明细");return[{weeklyUsagePct:l,weeklyResetIn:r.find((i)=>/重置/.test(i))||null,rateLimitPct:m,rateLimitResetIn:o.find((i)=>/重置/.test(i))||null,membershipName:s[0]||null,membershipTier:s.find((i)=>i!==s[0])||null,modelPermission:c[0]||null,modelCost:c.find((i)=>i!==c[0])||null}]}});
51
+ })()`);if(!e||typeof e!=="object"||Array.isArray(e))throw new s("kimi usage returned malformed payload: usage cards must be an object");if(Object.keys(e).length===0)throw new s("kimi usage returned malformed payload: no usage cards found on the console page");const r=c(e,"本周用量"),n=c(e,"频限明细"),o=c(e,"我的权益"),a=c(e,"模型权限"),d=l(r,"本周用量"),m=l(n,"频限明细");return[{weeklyUsagePct:d,weeklyResetIn:r.find((i)=>/重置/.test(i))||null,rateLimitPct:m,rateLimitResetIn:n.find((i)=>/重置/.test(i))||null,membershipName:o[0]||null,membershipTier:o.find((i)=>i!==o[0])||null,modelPermission:a[0]||null,modelCost:a.find((i)=>i!==a[0])||null}]}});
@@ -1 +1 @@
1
- import{AuthRequiredError as F}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as J}from"../_shared/site-auth.js";import{currentUrl as M}from"../_shared/video-publish.js";const N="https://cp.kuaishou.com/article/publish/video";async function G(x){return(await x.getCookies({url:"https://cp.kuaishou.com"})).some((B)=>B.value&&(/_st$/.test(B.name)||B.name==="userId"||B.name==="kuaishou.web.cp.api_st"))}async function H(x){await x.goto(N);let z="";for(let B=0;B<30;B++){z=await M(x);if(z&&/cp\.kuaishou\.com\/article/.test(z))return{logged_in:!0};if(z&&(/passport\.kuaishou\.com/.test(z)||/\/account\/login/.test(z)))throw new F("cp.kuaishou.com","快手创作者平台需要登录");await x.wait({time:0.5})}throw new F("cp.kuaishou.com",`快手登录态校验未 settle(当前: ${z||"unknown"})`)}J({site:"kuaishou",domain:"cp.kuaishou.com",loginUrl:"https://passport.kuaishou.com/pc/account/login/?sid=kuaishou.web.cp.api&callback=https%3A%2F%2Fcp.kuaishou.com%2Frest%2Finfra%2Fsts%3FfollowUrl%3Dhttps%253A%252F%252Fcp.kuaishou.com%252Farticle%252Fpublish%252Fvideo%26setRootDomain%3Dtrue",columns:["logged_in"],quickCheck:G,verify:H,poll:async(x)=>{if(!await G(x))throw new F("cp.kuaishou.com","等待快手登录 cookie");return H(x)}});
1
+ import{AuthRequiredError as s}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as a}from"../_shared/site-auth.js";import{currentUrl as c}from"../_shared/video-publish.js";const r="https://cp.kuaishou.com/article/publish/video";async function u(o){return(await o.getCookies({url:"https://cp.kuaishou.com"})).some((i)=>i.value&&(/_st$/.test(i.name)||i.name==="userId"||i.name==="kuaishou.web.cp.api_st"))}async function e(o){await o.goto(r);let t="";for(let i=0;i<30;i++){t=await c(o);if(t&&/cp\.kuaishou\.com\/article/.test(t))return{logged_in:!0};if(t&&(/passport\.kuaishou\.com/.test(t)||/\/account\/login/.test(t)))throw new s("cp.kuaishou.com","快手创作者平台需要登录");await o.wait({time:0.5})}throw new s("cp.kuaishou.com",`快手登录态校验未 settle(当前: ${t||"unknown"})`)}a({site:"kuaishou",domain:"cp.kuaishou.com",loginUrl:"https://passport.kuaishou.com/pc/account/login/?sid=kuaishou.web.cp.api&callback=https%3A%2F%2Fcp.kuaishou.com%2Frest%2Finfra%2Fsts%3FfollowUrl%3Dhttps%253A%252F%252Fcp.kuaishou.com%252Farticle%252Fpublish%252Fvideo%26setRootDomain%3Dtrue",columns:["logged_in"],quickCheck:u,verify:e,poll:async(o)=>{if(!await u(o))throw new s("cp.kuaishou.com","等待快手登录 cookie");return e(o)}});
@@ -1,4 +1,4 @@
1
- import{cli as V,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentError as O,CommandExecutionError as H}from"@jackwener/opencli/errors";import{resolveVideoFile as _,resolveImageFile as U,setVideoInput as Z,unwrap as W,currentUrl as B,parseScheduleDate as C,clickByText as M,countByText as f,existsByText as I,waitForUrlIncludes as j,waitForSelector as N,videoTimeoutArg as D}from"../_shared/video-publish.js";const S="https://cp.kuaishou.com/article/publish/video",b="button[class^='_upload-btn']",A=["input[class^='upload-btn-input']","div.progress-div [class^='upload-btn-input']","button[class^='_upload-btn'] input[type='file']","input[type='file']"];async function y(q,z){if(!Boolean(W(await q.evaluate(`
1
+ import{cli as S,Strategy as x}from"@jackwener/opencli/registry";import{ArgumentError as E,CommandExecutionError as a}from"@jackwener/opencli/errors";import{resolveVideoFile as D,resolveImageFile as k,setVideoInput as w,unwrap as s,currentUrl as T,parseScheduleDate as _,clickByText as r,countByText as m,existsByText as B,waitForUrlIncludes as f,waitForSelector as b,videoTimeoutArg as O}from"../_shared/video-publish.js";const q="https://cp.kuaishou.com/article/publish/video",I="button[class^='_upload-btn']",p=["input[class^='upload-btn-input']","div.progress-div [class^='upload-btn-input']","button[class^='_upload-btn'] input[type='file']","input[type='file']"];async function C(t,e){if(!Boolean(s(await t.evaluate(`
2
2
  (() => {
3
3
  const norm = (v) => (v || '').replace(/\\s+/g, ' ').trim();
4
4
  let label = null;
@@ -17,7 +17,7 @@ import{cli as V,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentE
17
17
  editable.focus();
18
18
  return true;
19
19
  })()
20
- `))))throw new H("找不到快手「描述」输入框");try{await q.pressKey("Backspace")}catch{}try{await q.pressKey("Control+a")}catch{}try{await q.pressKey("Delete")}catch{}await q.insertText(z);await q.pressKey("Enter")}async function P(q,z){const G=(X)=>String(X).padStart(2,"0"),J=`${z.getFullYear()}-${G(z.getMonth()+1)}-${G(z.getDate())} ${G(z.getHours())}:${G(z.getMinutes())}:${G(z.getSeconds())}`;await M(q,"定时发布",{timeoutMs:5000});await q.wait({time:2});await q.click('input[placeholder="选择日期时间"]');await q.wait({time:1});if(!Boolean(W(await q.evaluate(`
20
+ `))))throw new a("找不到快手「描述」输入框");try{await t.pressKey("Backspace")}catch{}try{await t.pressKey("Control+a")}catch{}try{await t.pressKey("Delete")}catch{}await t.insertText(e);await t.pressKey("Enter")}async function U(t,e){const i=(c)=>String(c).padStart(2,"0"),n=`${e.getFullYear()}-${i(e.getMonth()+1)}-${i(e.getDate())} ${i(e.getHours())}:${i(e.getMinutes())}:${i(e.getSeconds())}`;await r(t,"定时发布",{timeoutMs:5000});await t.wait({time:2});await t.click('input[placeholder="选择日期时间"]');await t.wait({time:1});if(!Boolean(s(await t.evaluate(`
21
21
  ((newValue) => {
22
22
  const input = document.querySelector('input[placeholder="选择日期时间"]');
23
23
  if (!input) return false;
@@ -26,8 +26,8 @@ import{cli as V,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentE
26
26
  input.dispatchEvent(new Event('input', { bubbles: true }));
27
27
  input.dispatchEvent(new Event('change', { bubbles: true }));
28
28
  return true;
29
- })(${JSON.stringify(J)})
30
- `))))throw new H("找不到快手定时发布时间选择器输入框");await q.wait({time:1});await q.pressKey("Enter");await q.wait({time:2})}async function T(q,z){if(!z)return;if(!Boolean(W(await q.evaluate(`
29
+ })(${JSON.stringify(n)})
30
+ `))))throw new a("找不到快手定时发布时间选择器输入框");await t.wait({time:1});await t.pressKey("Enter");await t.wait({time:2})}async function V(t,e){if(!e)return;if(!Boolean(s(await t.evaluate(`
31
31
  (() => {
32
32
  const norm = (v) => (v || '').replace(/\\s+/g, ' ').trim();
33
33
  let label = null;
@@ -42,7 +42,7 @@ import{cli as V,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentE
42
42
  first.click();
43
43
  return true;
44
44
  })()
45
- `))))throw new H("找不到快手「封面设置」入口");if(!await N(q,'div[role="document"].ant-modal',30000))throw new H("封面设置弹窗未出现");await M(q,"上传封面",{exact:!0,timeoutMs:1e4});await q.wait({time:0.5});await Z(q,['div[role="document"].ant-modal input[type="file"]','input[type="file"]'],[z]);await q.wait({time:1});await M(q,"确认",{exact:!0,timeoutMs:1e4});const J=Date.now()+30000;while(Date.now()<J){if(!Boolean(W(await q.evaluate(`(() => { const m = document.querySelector('div[role="document"].ant-modal'); return !!(m && m.getBoundingClientRect().width > 0); })()`))))break;await q.wait({time:0.5})}}V({site:"kuaishou",name:"publish",access:"write",description:"发布视频到快手(一条命令完成上传+填写+发布;可选封面/定时/话题)",domain:"cp.kuaishou.com",strategy:v.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"video",required:!0,positional:!0,help:"视频文件路径"},{name:"title",required:!0,help:"作品标题(无 --desc 时作为描述)"},{name:"desc",fromFile:!0,default:"",help:"视频描述(默认用标题)"},{name:"tags",default:"",help:"话题标签,逗号分隔,最多取前 3 个(不含 #)"},{name:"cover",default:"",help:"封面图片路径(可选)"},{name:"schedule",default:"",help:"定时发布时间(ISO8601 或 Unix 秒;不填即立即发布)"},D()],columns:["status","title","url"],func:async(q,z)=>{const G=String(z.title??"").trim();if(!G)throw new O("快手视频上传时,title 是必须的");const J=_(z.video),Q=z.cover?U(z.cover):"",X=String(z.desc||"").trim()||G,R=z.tags?String(z.tags).split(",").map((K)=>K.trim()).filter(Boolean):[],Y=C(z.schedule);await q.goto(S);if(!await j(q,"article/publish/video",30000))throw new H("未能进入快手上传页(登录态可能失效,请先 ppcli kuaishou login)");if(!await N(q,b,15000))throw new H("快手上传按钮未出现");await Z(q,A,[J]);await q.wait({time:2});if(await I(q,"我知道了",{exact:!0}))await M(q,"我知道了",{exact:!0});await q.evaluate(`
45
+ `))))throw new a("找不到快手「封面设置」入口");if(!await b(t,'div[role="document"].ant-modal',30000))throw new a("封面设置弹窗未出现");await r(t,"上传封面",{exact:!0,timeoutMs:1e4});await t.wait({time:0.5});await w(t,['div[role="document"].ant-modal input[type="file"]','input[type="file"]'],[e]);await t.wait({time:1});await r(t,"确认",{exact:!0,timeoutMs:1e4});const n=Date.now()+30000;while(Date.now()<n){if(!Boolean(s(await t.evaluate(`(() => { const m = document.querySelector('div[role="document"].ant-modal'); return !!(m && m.getBoundingClientRect().width > 0); })()`))))break;await t.wait({time:0.5})}}S({site:"kuaishou",name:"publish",access:"write",description:"发布视频到快手(一条命令完成上传+填写+发布;可选封面/定时/话题)",domain:"cp.kuaishou.com",strategy:x.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"video",required:!0,positional:!0,help:"视频文件路径"},{name:"title",required:!0,help:"作品标题(无 --desc 时作为描述)"},{name:"desc",fromFile:!0,default:"",help:"视频描述(默认用标题)"},{name:"tags",default:"",help:"话题标签,逗号分隔,最多取前 3 个(不含 #)"},{name:"cover",default:"",help:"封面图片路径(可选)"},{name:"schedule",default:"",help:"定时发布时间(ISO8601 或 Unix 秒;不填即立即发布)"},O()],columns:["status","title","url"],func:async(t,e)=>{const i=String(e.title??"").trim();if(!i)throw new E("快手视频上传时,title 是必须的");const n=D(e.video),o=e.cover?k(e.cover):"",c=String(e.desc||"").trim()||i,h=e.tags?String(e.tags).split(",").map((l)=>l.trim()).filter(Boolean):[],u=_(e.schedule);await t.goto(q);if(!await f(t,"article/publish/video",30000))throw new a("未能进入快手上传页(登录态可能失效,请先 ppcli kuaishou login)");if(!await b(t,I,15000))throw new a("快手上传按钮未出现");await w(t,p,[n]);await t.wait({time:2});if(await B(t,"我知道了",{exact:!0}))await r(t,"我知道了",{exact:!0});await t.evaluate(`
46
46
  (() => {
47
47
  const tip = document.querySelector('div[id^="react-joyride-step"] div[role="alertdialog"]');
48
48
  if (!tip) return false;
@@ -50,4 +50,4 @@ import{cli as V,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentE
50
50
  if (skip) { skip.click(); return true; }
51
51
  return false;
52
52
  })()
53
- `);await y(q,X);for(const K of R.slice(0,3)){await q.insertText(`#${K} `);await q.wait({time:2})}const F=60;for(let K=0;K<F;K++){if(await f(q,"上传中")===0)break;if(await f(q,"上传失败")>0)await Z(q,A,[J]);await q.wait({time:2})}if(Q)await T(q,Q);if(Y)await P(q,Y);const L=Date.now()+60000;let $=!1;while(Date.now()<L){await M(q,"发布",{exact:!0});await q.wait({time:1});await M(q,"确认发布");if(await j(q,"article/manage",5000)){$=!0;break}await q.wait({time:1})}if(!$)throw new H("快手发布未确认成功(未跳转到作品管理页),请检查页面状态");return[{status:Y?"✅ 定时发布已提交":"✅ 发布成功",title:G,url:await B(q)}]}});
53
+ `);await C(t,c);for(const l of h.slice(0,3)){await t.insertText(`#${l} `);await t.wait({time:2})}const v=60;for(let l=0;l<v;l++){if(await m(t,"上传中")===0)break;if(await m(t,"上传失败")>0)await w(t,p,[n]);await t.wait({time:2})}if(o)await V(t,o);if(u)await U(t,u);const y=Date.now()+60000;let d=!1;while(Date.now()<y){await r(t,"发布",{exact:!0});await t.wait({time:1});await r(t,"确认发布");if(await f(t,"article/manage",5000)){d=!0;break}await t.wait({time:1})}if(!d)throw new a("快手发布未确认成功(未跳转到作品管理页),请检查页面状态");return[{status:u?"✅ 定时发布已提交":"✅ 发布成功",title:i,url:await T(t)}]}});
@@ -1,9 +1,9 @@
1
- import{CommandExecutionError as K,EmptyResultError as S}from"@jackwener/opencli/errors";export const SITE="lesswrong",DOMAIN="www.lesswrong.com";const T=`https://${DOMAIN}/graphql`;export async function gqlRequest(f){const z=await fetch(T,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({query:f}),signal:AbortSignal.timeout(15000)});if(!z.ok)throw new K(`LessWrong API returned HTTP ${z.status}`);const B=await z.json();if(B.errors?.length)throw new K(B.errors[0]?.message??"Unknown GraphQL error");return B.data}export function gqlEscape(f){return f.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}export function stripHtml(f){if(!f)return"";return f.replace(/<script[^>]*>.*?<\/script>/gis," ").replace(/<style[^>]*>.*?<\/style>/gis," ").replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim()}export function daysAgo(f){const z=new Date;z.setDate(z.getDate()-f);return z.toISOString()}export async function resolveTagId(f){const B=`query TagBySlug {
2
- tags(input: {terms: {view: "tagBySlug", slug: "${gqlEscape(f.toLowerCase().trim().replace(/\s+/g,"-"))}"}}) {
1
+ import{CommandExecutionError as o,EmptyResultError as a}from"@jackwener/opencli/errors";export const SITE="lesswrong",DOMAIN="www.lesswrong.com";const i=`https://${DOMAIN}/graphql`;export async function gqlRequest(e){const t=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({query:e}),signal:AbortSignal.timeout(15000)});if(!t.ok)throw new o(`LessWrong API returned HTTP ${t.status}`);const r=await t.json();if(r.errors?.length)throw new o(r.errors[0]?.message??"Unknown GraphQL error");return r.data}export function gqlEscape(e){return e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}export function stripHtml(e){if(!e)return"";return e.replace(/<script[^>]*>.*?<\/script>/gis," ").replace(/<style[^>]*>.*?<\/style>/gis," ").replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim()}export function daysAgo(e){const t=new Date;t.setDate(t.getDate()-e);return t.toISOString()}export async function resolveTagId(e){const r=`query TagBySlug {
2
+ tags(input: {terms: {view: "tagBySlug", slug: "${gqlEscape(e.toLowerCase().trim().replace(/\s+/g,"-"))}"}}) {
3
3
  results { _id name slug }
4
4
  }
5
- }`,F=(await gqlRequest(B))?.tags?.results?.[0];if(!F?._id||!F?.name)return null;return{_id:F._id,name:F.name}}export function resolveUserId(f){const B=`query UserProfile {
6
- user(input: {selector: {slug: "${gqlEscape(f.toLowerCase())}"}}) {
5
+ }`,s=(await gqlRequest(r))?.tags?.results?.[0];if(!s?._id||!s?.name)return null;return{_id:s._id,name:s.name}}export function resolveUserId(e){const r=`query UserProfile {
6
+ user(input: {selector: {slug: "${gqlEscape(e.toLowerCase())}"}}) {
7
7
  result { _id displayName slug }
8
8
  }
9
- }`;return gqlRequest(B).then((J)=>{const F=J?.user?.result;if(!F?._id)throw new S(`lesswrong user ${f}`,'Check the username — LessWrong slugs are lowercase (e.g. "zvi", "eliezer-yudkowsky")');return{_id:F._id,displayName:F.displayName??""}})}export function parsePostId(f){const z=f.trim(),B=z.match(/posts\/([a-zA-Z0-9]+)/);return B?B[1]:z}
9
+ }`;return gqlRequest(r).then((n)=>{const s=n?.user?.result;if(!s?._id)throw new a(`lesswrong user ${e}`,'Check the username — LessWrong slugs are lowercase (e.g. "zvi", "eliezer-yudkowsky")');return{_id:s._id,displayName:s.displayName??""}})}export function parsePostId(e){const t=e.trim(),r=t.match(/posts\/([a-zA-Z0-9]+)/);return r?r[1]:t}
@@ -1,9 +1,9 @@
1
- import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{EmptyResultError as Z}from"@jackwener/opencli/errors";import{DOMAIN as K,SITE as $,gqlEscape as x,gqlRequest as L,parsePostId as H,stripHtml as P}from"./_helpers.js";X({site:$,name:"comments",access:"read",description:"Top comments on a post",domain:K,strategy:Y.PUBLIC,browser:!1,args:[{name:"url-or-id",type:"string",required:!0,positional:!0,help:"Post URL or LessWrong post ID"},{name:"limit",type:"int",default:5,help:"Number of comments"}],columns:["rank","score","author","text"],func:async(G)=>{const v=x(H(String(G["url-or-id"]))),Q=Number(G.limit??5),[U,V]=await Promise.all([L(`query PostTitle {
2
- post(input: {selector: {documentId: "${v}"}}) {
1
+ import{cli as h,Strategy as g}from"@jackwener/opencli/registry";import{EmptyResultError as y}from"@jackwener/opencli/errors";import{DOMAIN as l,SITE as f,gqlEscape as I,gqlRequest as a,parsePostId as w,stripHtml as q}from"./_helpers.js";h({site:f,name:"comments",access:"read",description:"Top comments on a post",domain:l,strategy:g.PUBLIC,browser:!1,args:[{name:"url-or-id",type:"string",required:!0,positional:!0,help:"Post URL or LessWrong post ID"},{name:"limit",type:"int",default:5,help:"Number of comments"}],columns:["rank","score","author","text"],func:async(n)=>{const e=I(w(String(n["url-or-id"]))),c=Number(n.limit??5),[p,u]=await Promise.all([a(`query PostTitle {
2
+ post(input: {selector: {documentId: "${e}"}}) {
3
3
  result { _id title slug }
4
4
  }
5
- }`),L(`query Comments {
6
- comments(input: {terms: {view: "postCommentsTop", postId: "${v}", limit: ${Q}}}) {
5
+ }`),a(`query Comments {
6
+ comments(input: {terms: {view: "postCommentsTop", postId: "${e}", limit: ${c}}}) {
7
7
  results { _id user { displayName } baseScore htmlBody postedAt }
8
8
  }
9
- }`)]),b=U?.post?.result;if(!b?._id)throw new Z("lesswrong comments",`Post "${v}" not found`);const J=V?.comments?.results??[],z=[];z.push({rank:"",score:"",author:"",text:`Comments on: ${b.title??"Untitled"} (https://${K}/posts/${b._id}/${b.slug})`});for(let f=0;f<J.length;f++){const B=J[f],W=B.user,C=P(B.htmlBody??"");z.push({rank:f+1,score:B.baseScore??0,author:W?.displayName??"",text:C.length>500?`${C.slice(0,500)}...`:C})}return z}});
9
+ }`)]),t=p?.post?.result;if(!t?._id)throw new y("lesswrong comments",`Post "${e}" not found`);const i=u?.comments?.results??[],o=[];o.push({rank:"",score:"",author:"",text:`Comments on: ${t.title??"Untitled"} (https://${l}/posts/${t._id}/${t.slug})`});for(let s=0;s<i.length;s++){const r=i[s],d=r.user,m=q(r.htmlBody??"");o.push({rank:s+1,score:r.baseScore??0,author:d?.displayName??"",text:m.length>500?`${m.slice(0,500)}...`:m})}return o}});
@@ -1 +1 @@
1
- import{cli as f,Strategy as u}from"@jackwener/opencli/registry";import{EmptyResultError as d}from"@jackwener/opencli/errors";import{LICHESS_BASE as p,lichessFetch as m,requireBoundedInt as y,requirePerf as g}from"./utils.js";f({site:"lichess",name:"top",access:"read",description:"Top-N Lichess leaderboard for a perf type (bullet/blitz/rapid/classical/...)",domain:"lichess.org",strategy:u.PUBLIC,browser:!1,args:[{name:"perf",positional:!0,required:!0,help:"Perf type (bullet, blitz, rapid, classical, ultraBullet, chess960, ...)"},{name:"limit",type:"int",default:10,help:"Top-N rows (1-200)"}],columns:["rank","username","id","title","rating","progress","patron","url"],func:async(o)=>{const r=g(o.perf),i=y(o.limit,10,200),a=`${p}/api/player/top/${i}/${encodeURIComponent(r)}`,n=await m(a,"lichess top"),l=Array.isArray(n?.users)?n.users:[];if(!l.length)throw new d("lichess top",`Lichess returned no leaderboard rows for perf "${r}".`);return l.slice(0,i).map((e,c)=>{const s=typeof e?.username==="string"?e.username:"",t=e?.perfs&&typeof e.perfs==="object"?e.perfs[r]??{}:{};return{rank:c+1,username:s,id:typeof e?.id==="string"?e.id:null,title:typeof e?.title==="string"?e.title:null,rating:typeof t.rating==="number"?t.rating:null,progress:typeof t.progress==="number"?t.progress:null,patron:e?.patron===!0,url:s?`${p}/@/${encodeURIComponent(s)}/perf/${encodeURIComponent(r)}`:""}})}});
1
+ import{cli as f,Strategy as m}from"@jackwener/opencli/registry";import{EmptyResultError as u}from"@jackwener/opencli/errors";import{LICHESS_BASE as p,lichessFetch as d,requireBoundedInt as y,requirePerf as g}from"./utils.js";f({site:"lichess",name:"top",access:"read",description:"Top-N Lichess leaderboard for a perf type (bullet/blitz/rapid/classical/...)",domain:"lichess.org",strategy:m.PUBLIC,browser:!1,args:[{name:"perf",positional:!0,required:!0,help:"Perf type (bullet, blitz, rapid, classical, ultraBullet, chess960, ...)"},{name:"limit",type:"int",default:10,help:"Top-N rows (1-200)"}],columns:["rank","username","id","title","rating","progress","patron","url"],func:async(o)=>{const r=g(o.perf),n=y(o.limit,10,200),a=`${p}/api/player/top/${n}/${encodeURIComponent(r)}`,i=await d(a,"lichess top"),l=Array.isArray(i?.users)?i.users:[];if(!l.length)throw new u("lichess top",`Lichess returned no leaderboard rows for perf "${r}".`);return l.slice(0,n).map((e,c)=>{const s=typeof e?.username==="string"?e.username:"",t=e?.perfs&&typeof e.perfs==="object"?e.perfs[r]??{}:{};return{rank:c+1,username:s,id:typeof e?.id==="string"?e.id:null,title:typeof e?.title==="string"?e.title:null,rating:typeof t.rating==="number"?t.rating:null,progress:typeof t.progress==="number"?t.progress:null,patron:e?.patron===!0,url:s?`${p}/@/${encodeURIComponent(s)}/perf/${encodeURIComponent(r)}`:""}})}});
@@ -1 +1 @@
1
- import{cli as A,Strategy as B}from"@jackwener/opencli/registry";import{EmptyResultError as Z}from"@jackwener/opencli/errors";import{LICHESS_BASE as $,formatTimestamp as q,lichessFetch as C,requireUsername as H}from"./utils.js";A({site:"lichess",name:"user",access:"read",description:"Fetch a Lichess player profile by username (rating, perfs, counts)",domain:"lichess.org",strategy:B.PUBLIC,browser:!1,args:[{name:"username",positional:!0,required:!0,help:"Lichess username (case-insensitive)"}],columns:["username","id","title","patron","online","tosViolation","createdAt","seenAt","gamesAll","gamesWin","gamesLoss","gamesDraw","topPerfName","topPerfRating","topPerfGames","fideRating","country","bio","url"],func:async(x)=>{const O=H(x.username),F=`${$}/api/user/${encodeURIComponent(O)}`,D=await C(F,"lichess user");if(!D||typeof D!=="object")throw new Z("lichess user",`Lichess user "${O}" returned empty payload.`);if(D.disabled===!0)throw new Z("lichess user",`Lichess user "${O}" is closed/disabled.`);const U=D.perfs&&typeof D.perfs==="object"?D.perfs:{},z=Object.entries(U).filter(([V,K])=>K&&typeof K==="object"&&!["puzzle","storm","racer","streak"].includes(V));let W=null,X=null,Q=null;for(const[V,K]of z){const Y=typeof K.games==="number"?K.games:0;if(Q==null||Y>Q){W=V;Q=Y;X=typeof K.rating==="number"?K.rating:null}}const J=D.count&&typeof D.count==="object"?D.count:{},M=D.profile&&typeof D.profile==="object"?D.profile:{};return[{username:typeof D.username==="string"?D.username:O,id:typeof D.id==="string"?D.id:null,title:typeof D.title==="string"?D.title:null,patron:D.patron===!0,online:D.online===!0,tosViolation:D.tosViolation===!0,createdAt:q(D.createdAt),seenAt:q(D.seenAt),gamesAll:typeof J.all==="number"?J.all:null,gamesWin:typeof J.win==="number"?J.win:null,gamesLoss:typeof J.loss==="number"?J.loss:null,gamesDraw:typeof J.draw==="number"?J.draw:null,topPerfName:W,topPerfRating:X,topPerfGames:Q,fideRating:typeof M.fideRating==="number"?M.fideRating:null,country:typeof M.country==="string"?M.country:null,bio:typeof M.bio==="string"?M.bio.trim():null,url:`${$}/@/${encodeURIComponent(typeof D.username==="string"?D.username:O)}`}]}});
1
+ import{cli as b,Strategy as h}from"@jackwener/opencli/registry";import{EmptyResultError as m}from"@jackwener/opencli/errors";import{LICHESS_BASE as p,formatTimestamp as c,lichessFetch as w,requireUsername as A}from"./utils.js";b({site:"lichess",name:"user",access:"read",description:"Fetch a Lichess player profile by username (rating, perfs, counts)",domain:"lichess.org",strategy:h.PUBLIC,browser:!1,args:[{name:"username",positional:!0,required:!0,help:"Lichess username (case-insensitive)"}],columns:["username","id","title","patron","online","tosViolation","createdAt","seenAt","gamesAll","gamesWin","gamesLoss","gamesDraw","topPerfName","topPerfRating","topPerfGames","fideRating","country","bio","url"],func:async(f)=>{const n=A(f.username),y=`${p}/api/user/${encodeURIComponent(n)}`,e=await w(y,"lichess user");if(!e||typeof e!=="object")throw new m("lichess user",`Lichess user "${n}" returned empty payload.`);if(e.disabled===!0)throw new m("lichess user",`Lichess user "${n}" is closed/disabled.`);const g=e.perfs&&typeof e.perfs==="object"?e.perfs:{},d=Object.entries(g).filter(([i,s])=>s&&typeof s==="object"&&!["puzzle","storm","racer","streak"].includes(i));let l=null,a=null,o=null;for(const[i,s]of d){const u=typeof s.games==="number"?s.games:0;if(o==null||u>o){l=i;o=u;a=typeof s.rating==="number"?s.rating:null}}const t=e.count&&typeof e.count==="object"?e.count:{},r=e.profile&&typeof e.profile==="object"?e.profile:{};return[{username:typeof e.username==="string"?e.username:n,id:typeof e.id==="string"?e.id:null,title:typeof e.title==="string"?e.title:null,patron:e.patron===!0,online:e.online===!0,tosViolation:e.tosViolation===!0,createdAt:c(e.createdAt),seenAt:c(e.seenAt),gamesAll:typeof t.all==="number"?t.all:null,gamesWin:typeof t.win==="number"?t.win:null,gamesLoss:typeof t.loss==="number"?t.loss:null,gamesDraw:typeof t.draw==="number"?t.draw:null,topPerfName:l,topPerfRating:a,topPerfGames:o,fideRating:typeof r.fideRating==="number"?r.fideRating:null,country:typeof r.country==="string"?r.country:null,bio:typeof r.bio==="string"?r.bio.trim():null,url:`${p}/@/${encodeURIComponent(typeof e.username==="string"?e.username:n)}`}]}});
@@ -1 +1 @@
1
- import{ArgumentError as J,CommandExecutionError as W,EmptyResultError as X}from"@jackwener/opencli/errors";export const LICHESS_BASE="https://lichess.org";const Z="opencli-lichess-adapter/1.0 (+https://github.com/jackwener/OpenCLI; mailto:ppcli@example.com)",$=/^[A-Za-z0-9_-]{2,30}$/;export const LICHESS_PERFS=new Set(["ultraBullet","bullet","blitz","rapid","classical","chess960","crazyhouse","antichess","atomic","horde","kingOfTheHill","racingKings","threeCheck"]);export function requireUsername(z){const q=String(z??"").trim();if(!q)throw new J("lichess username is required");if(!$.test(q))throw new J(`lichess username "${z}" is not a valid handle`,"Allowed: letters, digits, underscore, dash; length 2-30.");return q}export function requirePerf(z){const q=String(z??"").trim();if(!q)throw new J('lichess perf is required (e.g. "blitz", "bullet", "rapid")');if(!LICHESS_PERFS.has(q))throw new J(`lichess perf "${z}" is not recognised`,`Allowed values: ${[...LICHESS_PERFS].join(", ")}.`);return q}export function requireBoundedInt(z,q,B,K="limit"){const G=z??q,Q=typeof G==="number"?G:Number(G);if(!Number.isInteger(Q)||Q<=0)throw new J(`lichess ${K} must be a positive integer`);if(Q>B)throw new J(`lichess ${K} must be <= ${B}`);return Q}export async function lichessFetch(z,q){let B;try{B=await fetch(z,{headers:{"user-agent":Z,accept:"application/json"}})}catch(G){throw new W(`${q} request failed: ${G?.message??G}`,"Check that lichess.org is reachable from this network.")}if(B.status===404)throw new X(q,`Lichess returned 404 for ${z}.`);if(B.status===429)throw new W(`${q} returned HTTP 429 (rate limited)`,"Lichess throttles anonymous traffic at ~60 req/min; back off and retry.");if(!B.ok)throw new W(`${q} returned HTTP ${B.status}`);let K;try{K=await B.json()}catch(G){throw new W(`${q} returned malformed JSON: ${G?.message??G}`)}return K}export function formatTimestamp(z){if(typeof z!=="number"||!Number.isFinite(z)||z<=0)return null;const q=new Date(z);if(Number.isNaN(q.getTime()))return null;return q.toISOString()}
1
+ import{ArgumentError as n,CommandExecutionError as c,EmptyResultError as a}from"@jackwener/opencli/errors";export const LICHESS_BASE="https://lichess.org";const h="opencli-lichess-adapter/1.0 (+https://github.com/jackwener/OpenCLI; mailto:ppcli@example.com)",u=/^[A-Za-z0-9_-]{2,30}$/;export const LICHESS_PERFS=new Set(["ultraBullet","bullet","blitz","rapid","classical","chess960","crazyhouse","antichess","atomic","horde","kingOfTheHill","racingKings","threeCheck"]);export function requireUsername(t){const e=String(t??"").trim();if(!e)throw new n("lichess username is required");if(!u.test(e))throw new n(`lichess username "${t}" is not a valid handle`,"Allowed: letters, digits, underscore, dash; length 2-30.");return e}export function requirePerf(t){const e=String(t??"").trim();if(!e)throw new n('lichess perf is required (e.g. "blitz", "bullet", "rapid")');if(!LICHESS_PERFS.has(e))throw new n(`lichess perf "${t}" is not recognised`,`Allowed values: ${[...LICHESS_PERFS].join(", ")}.`);return e}export function requireBoundedInt(t,e,r,s="limit"){const i=t??e,o=typeof i==="number"?i:Number(i);if(!Number.isInteger(o)||o<=0)throw new n(`lichess ${s} must be a positive integer`);if(o>r)throw new n(`lichess ${s} must be <= ${r}`);return o}export async function lichessFetch(t,e){let r;try{r=await fetch(t,{headers:{"user-agent":h,accept:"application/json"}})}catch(i){throw new c(`${e} request failed: ${i?.message??i}`,"Check that lichess.org is reachable from this network.")}if(r.status===404)throw new a(e,`Lichess returned 404 for ${t}.`);if(r.status===429)throw new c(`${e} returned HTTP 429 (rate limited)`,"Lichess throttles anonymous traffic at ~60 req/min; back off and retry.");if(!r.ok)throw new c(`${e} returned HTTP ${r.status}`);let s;try{s=await r.json()}catch(i){throw new c(`${e} returned malformed JSON: ${i?.message??i}`)}return s}export function formatTimestamp(t){if(typeof t!=="number"||!Number.isFinite(t)||t<=0)return null;const e=new Date(t);if(Number.isNaN(e.getTime()))return null;return e.toISOString()}
@@ -1 +1 @@
1
- import{cli as Z,Strategy as $}from"@jackwener/opencli/registry";import{ArgumentError as Q,AuthRequiredError as b,CommandExecutionError as V}from"@jackwener/opencli/errors";import{assertLinkedInAuthenticated as q,LINKEDIN_DOMAIN as W,unwrapEvaluateResult as v}from"./shared.js";import{buildCommentScript as z,NORM_COMMENT_DECORATION as K,normalizeThreadUrn as k}from"./social-api.js";const P=1250;Z({site:"linkedin",name:"comment",access:"write",description:"Post a top-level comment on a LinkedIn post via the Voyager API. Dry-run by default; pass --send true to actually publish. Takes a post URL or activity/ugcPost urn.",domain:W,strategy:$.COOKIE,browser:!0,args:[{name:"post",type:"string",required:!0,positional:!0,help:"Post to comment on: a LinkedIn post URL (…/feed/update/… or …/posts/…) or a raw urn:li:activity:… / urn:li:ugcPost:… urn."},{name:"text",fromFile:!0,type:"string",required:!0,help:`Comment body (max ${P} chars).`},{name:"send",type:"bool",required:!1,default:!1,help:"Actually post the comment. Default false = dry-run (validates the session only; nothing is posted)."}],columns:["status","post_urn","comment_urn","text_chars"],func:async(F,G)=>{if(!F)throw new V("Browser session required for linkedin comment");const J=k(G?.post),B=String(G?.text??"").replace(/ /g," ").trim();if(!B)throw new Q("--text is required");if(B.length>P)throw new Q(`--text must be ${P} characters or fewer (got ${B.length})`);const Y=G?.send===!0||G?.send==="true";await F.goto(`https://www.linkedin.com/feed/update/${J}/`);await F.wait(2);if(!Y){await q(F,"LinkedIn comment");return[{status:"dry_run",post_urn:J,comment_urn:"(not posted — pass --send true to publish)",text_chars:B.length}]}const f=v(await F.evaluate(z({threadUrn:J,text:B,decorationId:K})));if(!f?.ok){if(f?.stage==="auth"||f?.httpStatus===401||f?.httpStatus===403)throw new b(W,`LinkedIn comment requires an active signed-in LinkedIn browser session (${f?.error||"auth"}).`);throw new V(`LinkedIn comment failed: stage=${f?.stage||"unknown"} http=${f?.httpStatus||"?"} ${f?.error||""}`.trim())}return[{status:"commented",post_urn:J,comment_urn:f.commentUrn||"",text_chars:B.length}]}});
1
+ import{cli as d,Strategy as c}from"@jackwener/opencli/registry";import{ArgumentError as i,AuthRequiredError as l,CommandExecutionError as a}from"@jackwener/opencli/errors";import{assertLinkedInAuthenticated as p,LINKEDIN_DOMAIN as u,unwrapEvaluateResult as h}from"./shared.js";import{buildCommentScript as w,NORM_COMMENT_DECORATION as f,normalizeThreadUrn as y}from"./social-api.js";const s=1250;d({site:"linkedin",name:"comment",access:"write",description:"Post a top-level comment on a LinkedIn post via the Voyager API. Dry-run by default; pass --send true to actually publish. Takes a post URL or activity/ugcPost urn.",domain:u,strategy:c.COOKIE,browser:!0,args:[{name:"post",type:"string",required:!0,positional:!0,help:"Post to comment on: a LinkedIn post URL (…/feed/update/… or …/posts/…) or a raw urn:li:activity:… / urn:li:ugcPost:… urn."},{name:"text",fromFile:!0,type:"string",required:!0,help:`Comment body (max ${s} chars).`},{name:"send",type:"bool",required:!1,default:!1,help:"Actually post the comment. Default false = dry-run (validates the session only; nothing is posted)."}],columns:["status","post_urn","comment_urn","text_chars"],func:async(r,n)=>{if(!r)throw new a("Browser session required for linkedin comment");const o=y(n?.post),e=String(n?.text??"").replace(/ /g," ").trim();if(!e)throw new i("--text is required");if(e.length>s)throw new i(`--text must be ${s} characters or fewer (got ${e.length})`);const m=n?.send===!0||n?.send==="true";await r.goto(`https://www.linkedin.com/feed/update/${o}/`);await r.wait(2);if(!m){await p(r,"LinkedIn comment");return[{status:"dry_run",post_urn:o,comment_urn:"(not posted — pass --send true to publish)",text_chars:e.length}]}const t=h(await r.evaluate(w({threadUrn:o,text:e,decorationId:f})));if(!t?.ok){if(t?.stage==="auth"||t?.httpStatus===401||t?.httpStatus===403)throw new l(u,`LinkedIn comment requires an active signed-in LinkedIn browser session (${t?.error||"auth"}).`);throw new a(`LinkedIn comment failed: stage=${t?.stage||"unknown"} http=${t?.httpStatus||"?"} ${t?.error||""}`.trim())}return[{status:"commented",post_urn:o,comment_urn:t.commentUrn||"",text_chars:e.length}]}});
@@ -1,6 +1,6 @@
1
- import{cli as P,Strategy as k}from"@jackwener/opencli/registry";import{ArgumentError as C,AuthRequiredError as T,CommandExecutionError as O}from"@jackwener/opencli/errors";const D="www.linkedin.com";function Z(B){return String(B??"").replace(/[\u00a0\u202f]/g," ").replace(/\s+/g," ").trim()}function K(B){return Z(B).replace(/\s*[•·]\s*(?:1st|2nd|3rd\+?|degree connection).*$/i,"").replace(/\s+LinkedIn.*$/i,"").replace(/\b(p\.?eng\.?|cpa|mba|ph\.?d\.?)\b/ig,"").replace(/[^\p{L}\p{N}\s.'-]+/gu," ").replace(/\s+/g," ").trim().toLowerCase()}function R(B){return K(B).replace(/[.'-]+/g," ").split(/\s+/).map((F)=>F.trim()).filter((F)=>F.length>=2)}function U(B,F){const J=K(B),Q=K(F);if(!J||!Q)return!1;if(J===Q)return!0;if(J.includes(Q)||Q.includes(J))return!0;const V=new Set(R(J)),X=R(Q);if(X.length<2||V.size<2)return!1;const G=X.filter((_)=>V.has(_)).length;return G>=2&&G/X.length>=0.8}function W(B){const F=String(B||"").toLowerCase();return F==="linkedin.com"||F.endsWith(".linkedin.com")}function q(B){const F=Z(B);if(!F)return"";try{const J=new URL(F);if(J.protocol!=="https:"||J.username||J.password||J.port||!W(J.hostname))return"";const Q=J.pathname.match(/^\/in\/([^/]+)\/?$/i);if(!Q||!Q[1])return"";J.hostname="www.linkedin.com";J.hash="";J.search="";if(!J.pathname.endsWith("/"))J.pathname+="/";return J.toString()}catch{return""}}function w(B,F,J=F){const Q=Z(B[F]);if(!Q)throw new C(`${J} is required`);return Q}function v(B,F){const J=q(B);if(!J)throw new C(`${F} must be an exact https://www.linkedin.com/in/<profile>/ URL`);return J}function M(B){if(B&&typeof B==="object"&&"data"in B&&"session"in B)return B.data;return B}function A(B){const F=Z(B);if(F.length>300)throw new C("--note must be 300 characters or fewer for LinkedIn connection requests");return F}function L(B){try{const F=new URL(Z(B),"https://www.linkedin.com");if(F.protocol!=="https:"||F.username||F.password||F.port||!W(F.hostname))return"";if(!/^\/preload\/custom-invite\/?$/i.test(F.pathname))return"";F.hostname="www.linkedin.com";F.hash="";if(!F.pathname.endsWith("/"))F.pathname+="/";return F.toString()}catch{return""}}function S(B,F,J){const Q=Z(F),V=Z(B?.name||""),X=q(J),G=q(B?.url||"");if(B?.authRequired)return{ok:!1,safety:"unsafe_block",connectable:null,blockReason:"auth_required",expectedValue:Q,actualValue:V,observedUrl:G};if(!V)return{ok:!1,safety:"unsafe_block",connectable:null,blockReason:"profile_name_not_found",expectedValue:Q,actualValue:V,observedUrl:G};if(Q&&K(V)!==K(Q))return{ok:!1,safety:"unsafe_block",connectable:null,blockReason:"profile_name_mismatch",expectedValue:Q,actualValue:V,observedUrl:G};if(X&&G&&X!==G)return{ok:!1,safety:"unsafe_block",connectable:null,blockReason:"profile_url_mismatch",expectedValue:X,actualValue:G,observedUrl:G};if(B?.alreadyConnected&&!B?.connectAvailable)return{ok:!1,safety:"routine_non_connectable",connectable:!1,blockReason:"already_connected",expectedValue:Q,actualValue:V,observedUrl:G};if(B?.pending)return{ok:!1,safety:"routine_non_connectable",connectable:!1,blockReason:"connection_pending",expectedValue:Q,actualValue:V,observedUrl:G};if(B?.connectAvailable)return{ok:!0,safety:"connectable",connectable:!0,blockReason:"verified",expectedValue:Q,actualValue:V,observedUrl:G};if(B?.moreAvailable)return{ok:!0,safety:"connectable",connectable:!0,blockReason:"verified_via_more",expectedValue:Q,actualValue:V,observedUrl:G};return{ok:!1,safety:"routine_non_connectable",connectable:!1,blockReason:"connect_button_not_found",expectedValue:Q,actualValue:V,observedUrl:G}}function h(B=""){return String.raw`(() => {
1
+ import{cli as R,Strategy as T}from"@jackwener/opencli/registry";import{ArgumentError as w,AuthRequiredError as k,CommandExecutionError as b}from"@jackwener/opencli/errors";const g="www.linkedin.com";function s(e){return String(e??"").replace(/[\u00a0\u202f]/g," ").replace(/\s+/g," ").trim()}function d(e){return s(e).replace(/\s*[•·]\s*(?:1st|2nd|3rd\+?|degree connection).*$/i,"").replace(/\s+LinkedIn.*$/i,"").replace(/\b(p\.?eng\.?|cpa|mba|ph\.?d\.?)\b/ig,"").replace(/[^\p{L}\p{N}\s.'-]+/gu," ").replace(/\s+/g," ").trim().toLowerCase()}function v(e){return d(e).replace(/[.'-]+/g," ").split(/\s+/).map((t)=>t.trim()).filter((t)=>t.length>=2)}function U(e,t){const o=d(e),a=d(t);if(!o||!a)return!1;if(o===a)return!0;if(o.includes(a)||a.includes(o))return!0;const r=new Set(v(o)),i=v(a);if(i.length<2||r.size<2)return!1;const n=i.filter((m)=>r.has(m)).length;return n>=2&&n/i.length>=0.8}function _(e){const t=String(e||"").toLowerCase();return t==="linkedin.com"||t.endsWith(".linkedin.com")}function p(e){const t=s(e);if(!t)return"";try{const o=new URL(t);if(o.protocol!=="https:"||o.username||o.password||o.port||!_(o.hostname))return"";const a=o.pathname.match(/^\/in\/([^/]+)\/?$/i);if(!a||!a[1])return"";o.hostname="www.linkedin.com";o.hash="";o.search="";if(!o.pathname.endsWith("/"))o.pathname+="/";return o.toString()}catch{return""}}function x(e,t,o=t){const a=s(e[t]);if(!a)throw new w(`${o} is required`);return a}function I(e,t){const o=p(e);if(!o)throw new w(`${t} must be an exact https://www.linkedin.com/in/<profile>/ URL`);return o}function f(e){if(e&&typeof e==="object"&&"data"in e&&"session"in e)return e.data;return e}function y(e){const t=s(e);if(t.length>300)throw new w("--note must be 300 characters or fewer for LinkedIn connection requests");return t}function L(e){try{const t=new URL(s(e),"https://www.linkedin.com");if(t.protocol!=="https:"||t.username||t.password||t.port||!_(t.hostname))return"";if(!/^\/preload\/custom-invite\/?$/i.test(t.pathname))return"";t.hostname="www.linkedin.com";t.hash="";if(!t.pathname.endsWith("/"))t.pathname+="/";return t.toString()}catch{return""}}function A(e,t,o){const a=s(t),r=s(e?.name||""),i=p(o),n=p(e?.url||"");if(e?.authRequired)return{ok:!1,safety:"unsafe_block",connectable:null,blockReason:"auth_required",expectedValue:a,actualValue:r,observedUrl:n};if(!r)return{ok:!1,safety:"unsafe_block",connectable:null,blockReason:"profile_name_not_found",expectedValue:a,actualValue:r,observedUrl:n};if(a&&d(r)!==d(a))return{ok:!1,safety:"unsafe_block",connectable:null,blockReason:"profile_name_mismatch",expectedValue:a,actualValue:r,observedUrl:n};if(i&&n&&i!==n)return{ok:!1,safety:"unsafe_block",connectable:null,blockReason:"profile_url_mismatch",expectedValue:i,actualValue:n,observedUrl:n};if(e?.alreadyConnected&&!e?.connectAvailable)return{ok:!1,safety:"routine_non_connectable",connectable:!1,blockReason:"already_connected",expectedValue:a,actualValue:r,observedUrl:n};if(e?.pending)return{ok:!1,safety:"routine_non_connectable",connectable:!1,blockReason:"connection_pending",expectedValue:a,actualValue:r,observedUrl:n};if(e?.connectAvailable)return{ok:!0,safety:"connectable",connectable:!0,blockReason:"verified",expectedValue:a,actualValue:r,observedUrl:n};if(e?.moreAvailable)return{ok:!0,safety:"connectable",connectable:!0,blockReason:"verified_via_more",expectedValue:a,actualValue:r,observedUrl:n};return{ok:!1,safety:"routine_non_connectable",connectable:!1,blockReason:"connect_button_not_found",expectedValue:a,actualValue:r,observedUrl:n}}function N(e=""){return String.raw`(() => {
2
2
  const clean = (s) => String(s || '').replace(/[\u00a0\u202f]/g, ' ').replace(/\s+/g, ' ').trim();
3
- const expectedName = ${JSON.stringify(B)};
3
+ const expectedName = ${JSON.stringify(e)};
4
4
  const normalizeName = (s) => clean(s)
5
5
  .replace(/\s*[•·]\s*(?:1st|2nd|3rd\+?|degree connection).*$/i, '')
6
6
  .replace(/\s+LinkedIn.*$/i, '')
@@ -82,9 +82,9 @@ import{cli as P,Strategy as k}from"@jackwener/opencli/registry";import{ArgumentE
82
82
  buttonLabels: buttonLabels.slice(0, 30),
83
83
  bodyText: text,
84
84
  };
85
- })()`}function z(B,F){return String.raw`(() => {
86
- const expectedName = ${JSON.stringify(B)};
87
- const expectedUrl = ${JSON.stringify(q(F))};
85
+ })()`}function S(e,t){return String.raw`(() => {
86
+ const expectedName = ${JSON.stringify(e)};
87
+ const expectedUrl = ${JSON.stringify(p(t))};
88
88
  const clean = (s) => String(s || '').replace(/[\u00a0\u202f]/g, ' ').replace(/\s+/g, ' ').trim();
89
89
  const normName = (s) => clean(s)
90
90
  .replace(/\s*[•·]\s*(?:1st|2nd|3rd\+?|degree connection).*$/i, '')
@@ -143,8 +143,8 @@ import{cli as P,Strategy as k}from"@jackwener/opencli/registry";import{ArgumentE
143
143
  if (urlMatches || nameMatches) return { authRequired: false, found: true, matchedName: candidateName, matchedUrl: candidateUrl, visibleNames: visibleNames.slice(0, 20) };
144
144
  }
145
145
  return { authRequired: false, found: false, matchedName: '', matchedUrl: '', visibleNames: visibleNames.slice(0, 20) };
146
- })()`}function E(B){return String.raw`(async () => {
147
- const note = ${JSON.stringify(B)};
146
+ })()`}function q(e){return String.raw`(async () => {
147
+ const note = ${JSON.stringify(e)};
148
148
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
149
149
  const jitter = async (min = 450, max = 1150) => sleep(min + Math.floor(Math.random() * (max - min + 1)));
150
150
  const clean = (s) => String(s || '').replace(/[\u00a0\u202f]/g, ' ').replace(/\s+/g, ' ').trim();
@@ -195,12 +195,12 @@ import{cli as P,Strategy as k}from"@jackwener/opencli/registry";import{ArgumentE
195
195
  send.click();
196
196
  await jitter(1400, 2400);
197
197
  return { ok: true, status: 'sent', reason: 'invitation_sent_with_note' };
198
- })()`}function y(B){return String.raw`(async () => {
198
+ })()`}function O(e){return String.raw`(async () => {
199
199
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
200
200
  const jitter = async (min = 450, max = 1150) => sleep(min + Math.floor(Math.random() * (max - min + 1)));
201
201
  const clean = (s) => String(s || '').replace(/[  ]/g, ' ').replace(/\s+/g, ' ').trim();
202
202
  const visible = (el) => el && el.offsetParent !== null;
203
- const expectedName = ${JSON.stringify(B)};
203
+ const expectedName = ${JSON.stringify(e)};
204
204
  const ariaLabel = (el) => clean(el?.getAttribute('aria-label') || '');
205
205
  const textLabel = (el) => clean(el?.innerText || el?.textContent || '');
206
206
  const tokens = (s) => clean(s).toLowerCase().replace(/[.'-]+/g, ' ').split(/\s+/).filter((t) => t.length >= 2);
@@ -240,5 +240,5 @@ import{cli as P,Strategy as k}from"@jackwener/opencli/registry";import{ArgumentE
240
240
  if (document.querySelector('[role="dialog"]')) return { ok: true, opened: 'dialog' };
241
241
  // Some flows fire the invite immediately without a confirmation dialog.
242
242
  return { ok: true, opened: 'no_dialog' };
243
- })()`}async function I(B,F=""){return M(await B.evaluate(h(F)))}P({site:"linkedin",name:"connect",access:"write",description:"Fail-closed LinkedIn connection request sender that verifies the exact profile before optionally sending a note",domain:D,strategy:k.UI,browser:!0,args:[{name:"profile-url",type:"string",required:!0,positional:!0,help:"Exact LinkedIn profile URL to open and verify"},{name:"expected-name",type:"string",required:!0,help:"Expected visible profile name"},{name:"note",type:"string",required:!1,default:"",help:"Optional connection note, max 300 chars"},{name:"send",type:"bool",required:!1,default:!1,help:"Actually click Send. Default is dry-run verification only."}],columns:["status","recipient","reason","profile_url","note_chars","connectable","delivery_verified","matched_invitation_name","matched_invitation_url","actualValue","blockReason","expectedValue","observedUrl","safety"],func:async(B,F)=>{if(!B)throw new O("Browser session required for linkedin connect");const J=v(w(F,"profile-url","--profile-url"),"--profile-url"),Q=w(F,"expected-name","--expected-name"),V=A(F.note||"");await B.goto(J);await B.wait(6);let X=await I(B,Q);for(let Y=0;Y<8;Y+=1){if(X?.name&&(X.connectAvailable||X.alreadyConnected||X.pending||X.moreAvailable))break;await B.wait(2);X=await I(B,Q)}const G=S(X,Q,J);if(G.blockReason==="auth_required")throw new T(D,"LinkedIn connect requires an active signed-in LinkedIn browser session.");if(!G.ok&&G.safety==="routine_non_connectable")return[{status:"not_connectable",recipient:G.actualValue,reason:G.blockReason,profile_url:G.observedUrl,note_chars:V.length,connectable:!1}];if(!G.ok)throw new O(`LinkedIn connect blocked: ${G.blockReason}`,`Expected ${G.expectedValue}; actual ${G.actualValue||"not_visible"} at ${G.observedUrl||"url_not_available"}
244
- Buttons: ${(X?.buttonLabels||[]).join(" | ")}`);if(!F.send)return[{status:"connectable_dry_run",recipient:G.actualValue,reason:G.blockReason,profile_url:G.observedUrl,note_chars:V.length,connectable:!0}];const _=X?.connectHref||"";if(_){const Y=L(_);if(!Y)throw new O("LinkedIn connect blocked: invalid_connect_link");await B.goto(Y);await B.wait(6)}else{const Y=M(await B.evaluate(y(Q)));if(!Y?.ok)throw new O(`LinkedIn connect blocked: ${Y?.reason||"connect_control_not_found"}`);await B.wait(3)}let $=M(await B.evaluate(E(V)));if($?.reason==="invite_dialog_not_found"){await B.wait(5);$=M(await B.evaluate(E(V)))}if(!$?.ok&&$?.reason==="invite_dialog_not_found"&&!_)$={ok:!0,status:"sent",reason:"invitation_sent_no_dialog"};if(!$?.ok)throw new O(`LinkedIn connect blocked: ${$?.reason||"send_failed"}`);await B.wait(8);let j=null;for(let Y=0;Y<3;Y+=1){await B.goto("https://www.linkedin.com/mynetwork/invitation-manager/sent/");await B.wait(Y===0?6:4);j=M(await B.evaluate(z(Q,J)));if(j?.found||j?.authRequired)break;if(Y<2)await B.wait(5)}if(j?.authRequired)throw new T(D,"LinkedIn sent-invitations verification requires an active signed-in LinkedIn browser session.");const H=Boolean(j?.found);return[{status:H?"sent_verified":"send_unverified",recipient:G.actualValue,reason:H?"sent_invitation_verified":"sent_invitation_not_found_after_retries",profile_url:G.observedUrl,note_chars:V.length,connectable:!0,delivery_verified:H,matched_invitation_name:j?.matchedName||"",matched_invitation_url:j?.matchedUrl||""}]}});export const __test__={normalizeWhitespace:Z,normalizeName:K,matchInvitationName:U,canonicalizeLinkedInProfileUrl:q,canonicalizeLinkedInInviteUrl:L,unwrapEvaluateResult:M,clampNote:A,assessProfileSafety:S,buildProfileProbeScript:h,buildSentInvitationsProbeScript:z};
243
+ })()`}async function C(e,t=""){return f(await e.evaluate(N(t)))}R({site:"linkedin",name:"connect",access:"write",description:"Fail-closed LinkedIn connection request sender that verifies the exact profile before optionally sending a note",domain:g,strategy:T.UI,browser:!0,args:[{name:"profile-url",type:"string",required:!0,positional:!0,help:"Exact LinkedIn profile URL to open and verify"},{name:"expected-name",type:"string",required:!0,help:"Expected visible profile name"},{name:"note",type:"string",required:!1,default:"",help:"Optional connection note, max 300 chars"},{name:"send",type:"bool",required:!1,default:!1,help:"Actually click Send. Default is dry-run verification only."}],columns:["status","recipient","reason","profile_url","note_chars","connectable","delivery_verified","matched_invitation_name","matched_invitation_url","actualValue","blockReason","expectedValue","observedUrl","safety"],func:async(e,t)=>{if(!e)throw new b("Browser session required for linkedin connect");const o=I(x(t,"profile-url","--profile-url"),"--profile-url"),a=x(t,"expected-name","--expected-name"),r=y(t.note||"");await e.goto(o);await e.wait(6);let i=await C(e,a);for(let l=0;l<8;l+=1){if(i?.name&&(i.connectAvailable||i.alreadyConnected||i.pending||i.moreAvailable))break;await e.wait(2);i=await C(e,a)}const n=A(i,a,o);if(n.blockReason==="auth_required")throw new k(g,"LinkedIn connect requires an active signed-in LinkedIn browser session.");if(!n.ok&&n.safety==="routine_non_connectable")return[{status:"not_connectable",recipient:n.actualValue,reason:n.blockReason,profile_url:n.observedUrl,note_chars:r.length,connectable:!1}];if(!n.ok)throw new b(`LinkedIn connect blocked: ${n.blockReason}`,`Expected ${n.expectedValue}; actual ${n.actualValue||"not_visible"} at ${n.observedUrl||"url_not_available"}
244
+ Buttons: ${(i?.buttonLabels||[]).join(" | ")}`);if(!t.send)return[{status:"connectable_dry_run",recipient:n.actualValue,reason:n.blockReason,profile_url:n.observedUrl,note_chars:r.length,connectable:!0}];const m=i?.connectHref||"";if(m){const l=L(m);if(!l)throw new b("LinkedIn connect blocked: invalid_connect_link");await e.goto(l);await e.wait(6)}else{const l=f(await e.evaluate(O(a)));if(!l?.ok)throw new b(`LinkedIn connect blocked: ${l?.reason||"connect_control_not_found"}`);await e.wait(3)}let c=f(await e.evaluate(q(r)));if(c?.reason==="invite_dialog_not_found"){await e.wait(5);c=f(await e.evaluate(q(r)))}if(!c?.ok&&c?.reason==="invite_dialog_not_found"&&!m)c={ok:!0,status:"sent",reason:"invitation_sent_no_dialog"};if(!c?.ok)throw new b(`LinkedIn connect blocked: ${c?.reason||"send_failed"}`);await e.wait(8);let u=null;for(let l=0;l<3;l+=1){await e.goto("https://www.linkedin.com/mynetwork/invitation-manager/sent/");await e.wait(l===0?6:4);u=f(await e.evaluate(S(a,o)));if(u?.found||u?.authRequired)break;if(l<2)await e.wait(5)}if(u?.authRequired)throw new k(g,"LinkedIn sent-invitations verification requires an active signed-in LinkedIn browser session.");const h=Boolean(u?.found);return[{status:h?"sent_verified":"send_unverified",recipient:n.actualValue,reason:h?"sent_invitation_verified":"sent_invitation_not_found_after_retries",profile_url:n.observedUrl,note_chars:r.length,connectable:!0,delivery_verified:h,matched_invitation_name:u?.matchedName||"",matched_invitation_url:u?.matchedUrl||""}]}});export const __test__={normalizeWhitespace:s,normalizeName:d,matchInvitationName:U,canonicalizeLinkedInProfileUrl:p,canonicalizeLinkedInInviteUrl:L,unwrapEvaluateResult:f,clampNote:y,assessProfileSafety:A,buildProfileProbeScript:N,buildSentInvitationsProbeScript:S};
@@ -1,7 +1,7 @@
1
- import{cli as j,Strategy as G}from"@jackwener/opencli/registry";import{ArgumentError as Z,AuthRequiredError as V,CommandExecutionError as Y}from"@jackwener/opencli/errors";import{LINKEDIN_DOMAIN as q,unwrapEvaluateResult as k}from"./shared.js";import{isLocalImagePath as P,localImageToDataUri as h}from"../_shared/article/images.js";const x=3000,B=9,C=10485760,D={anyone:{visibleToConnectionsOnly:!1,label:"ANYONE"},connections:{visibleToConnectionsOnly:!0,label:"CONNECTIONS"}};function L(Q){const J=String(Q??"anyone").trim().toLowerCase(),z=D[J];if(!z)throw new Z(`--visibility 只能是 anyone 或 connections(收到 "${Q}")`);return z}function R(Q){return String(Q??"").split(",").map((J)=>J.trim()).filter(Boolean)}async function X(Q){const J=[];for(const z of Q)if(P(z)){const{dataUri:$,bytes:W,mime:f}=await h(z);if(W>C)throw new Z(`图片过大:${z}(${(W/1024/1024).toFixed(1)}MB,上限 10MB)`);J.push({src:$,filename:z.split(/[\\/]/).pop()||"image",mime:f})}else if(/^https?:\/\//i.test(z))J.push({src:z,filename:z.split("/").pop()||"image",mime:""});else throw new Z(`无法识别的图片项:${z}(需本机绝对路径或 http(s) URL)`);return J}function O({content:Q,images:J,visibleToConnectionsOnly:z}){return`(async () => {
2
- const IMAGES = ${JSON.stringify(J)};
3
- const CONTENT = ${JSON.stringify(Q)};
4
- const VISIBLE_TO_CONNECTIONS_ONLY = ${JSON.stringify(z)};
1
+ import{cli as y,Strategy as b}from"@jackwener/opencli/registry";import{ArgumentError as n,AuthRequiredError as m,CommandExecutionError as p}from"@jackwener/opencli/errors";import{LINKEDIN_DOMAIN as l,unwrapEvaluateResult as h}from"./shared.js";import{isLocalImagePath as w,localImageToDataUri as S}from"../_shared/article/images.js";const c=3000,u=9,I=10485760,v={anyone:{visibleToConnectionsOnly:!1,label:"ANYONE"},connections:{visibleToConnectionsOnly:!0,label:"CONNECTIONS"}};function _(s){const i=String(s??"anyone").trim().toLowerCase(),e=v[i];if(!e)throw new n(`--visibility 只能是 anyone 或 connections(收到 "${s}")`);return e}function O(s){return String(s??"").split(",").map((i)=>i.trim()).filter(Boolean)}async function k(s){const i=[];for(const e of s)if(w(e)){const{dataUri:r,bytes:a,mime:o}=await S(e);if(a>I)throw new n(`图片过大:${e}(${(a/1024/1024).toFixed(1)}MB,上限 10MB)`);i.push({src:r,filename:e.split(/[\\/]/).pop()||"image",mime:o})}else if(/^https?:\/\//i.test(e))i.push({src:e,filename:e.split("/").pop()||"image",mime:""});else throw new n(`无法识别的图片项:${e}(需本机绝对路径或 http(s) URL)`);return i}function N({content:s,images:i,visibleToConnectionsOnly:e}){return`(async () => {
2
+ const IMAGES = ${JSON.stringify(i)};
3
+ const CONTENT = ${JSON.stringify(s)};
4
+ const VISIBLE_TO_CONNECTIONS_ONLY = ${JSON.stringify(e)};
5
5
 
6
6
  const jsessionRaw = (document.cookie.split('; ').find((c) => c.startsWith('JSESSIONID=')) || '').split('=')[1] || '';
7
7
  const csrf = jsessionRaw.replace(/^"|"$/g, '');
@@ -110,4 +110,4 @@ import{cli as j,Strategy as G}from"@jackwener/opencli/registry";import{ArgumentE
110
110
  const d = await res.json();
111
111
  const mini = d && d.miniProfile;
112
112
  return { ok: Boolean(mini && mini.publicIdentifier), public_id: mini ? String(mini.publicIdentifier || '') : '' };
113
- })()`}j({site:"linkedin",name:"create",access:"write",description:"Publish a post to your LinkedIn feed via the Voyager API. Supports plain text plus images and visibility scope. Dry-run by default; pass --send true to actually publish.",domain:q,strategy:G.COOKIE,browser:!0,args:[{name:"content",fromFile:!0,type:"string",required:!0,positional:!0,help:`Post body text (max ${x} chars). Emojis and line breaks allowed.`},{name:"image",type:"string",required:!1,help:`Up to ${B} images: comma-separated local file paths and/or http(s) URLs. Local paths ≤10MB each (jpg/png/gif).`},{name:"visibility",type:"string",required:!1,default:"anyone",help:"Who can see the post: anyone (public, default) or connections (1st-degree only)."},{name:"send",type:"bool",required:!1,default:!1,help:"Actually publish. Default false = dry-run (verifies the signed-in session only; no post is created)."}],columns:["status","content_chars","images","visibility","activity_urn"],func:async(Q,J)=>{if(!Q)throw new Y("Browser session required for linkedin create");const z=String(J?.content??"").replace(/ /g," ").trim();if(!z)throw new Z("content is required");if(z.length>x)throw new Z(`content must be ${x} characters or fewer (got ${z.length})`);const $=L(J?.visibility),W=R(J?.image);if(W.length>B)throw new Z(`最多 ${B} 张图片(收到 ${W.length})`);const f=await X(W),H=J?.send===!0||J?.send==="true";await Q.goto("https://www.linkedin.com/feed/");await Q.wait(3);const U=k(await Q.evaluate(T()));if(!U?.ok)throw new V(q,`LinkedIn create requires an active signed-in LinkedIn browser session (${U?.error||"probe_failed"}).`);if(!H)return[{status:"dry_run",content_chars:z.length,images:f.length,visibility:$.label,activity_urn:"(not published — pass --send true to publish)"}];const F=k(await Q.evaluate(O({content:z,images:f,visibleToConnectionsOnly:$.visibleToConnectionsOnly})));if(!F?.ok){if(F?.stage==="auth"||F?.httpStatus===401||F?.httpStatus===403)throw new V(q,"LinkedIn create: session rejected by Voyager API — re-login in the desktop client.");const K=[`stage=${F?.stage||"unknown"}`,F?.index!=null?`image#${F.index}`:"",F?.httpStatus?`http=${F.httpStatus}`:"",F?.error?`error=${F.error}`:"",F?.raw?`raw=${F.raw}`:""].filter(Boolean).join(" ");throw new Y(`LinkedIn create failed: ${K}`)}return[{status:"published",content_chars:z.length,images:F.images??f.length,visibility:$.label,activity_urn:F.activityUrn||F.updateUrn||""}]}});
113
+ })()`}y({site:"linkedin",name:"create",access:"write",description:"Publish a post to your LinkedIn feed via the Voyager API. Supports plain text plus images and visibility scope. Dry-run by default; pass --send true to actually publish.",domain:l,strategy:b.COOKIE,browser:!0,args:[{name:"content",fromFile:!0,type:"string",required:!0,positional:!0,help:`Post body text (max ${c} chars). Emojis and line breaks allowed.`},{name:"image",type:"string",required:!1,help:`Up to ${u} images: comma-separated local file paths and/or http(s) URLs. Local paths ≤10MB each (jpg/png/gif).`},{name:"visibility",type:"string",required:!1,default:"anyone",help:"Who can see the post: anyone (public, default) or connections (1st-degree only)."},{name:"send",type:"bool",required:!1,default:!1,help:"Actually publish. Default false = dry-run (verifies the signed-in session only; no post is created)."}],columns:["status","content_chars","images","visibility","activity_urn"],func:async(s,i)=>{if(!s)throw new p("Browser session required for linkedin create");const e=String(i?.content??"").replace(/ /g," ").trim();if(!e)throw new n("content is required");if(e.length>c)throw new n(`content must be ${c} characters or fewer (got ${e.length})`);const r=_(i?.visibility),a=O(i?.image);if(a.length>u)throw new n(`最多 ${u} 张图片(收到 ${a.length})`);const o=await k(a),f=i?.send===!0||i?.send==="true";await s.goto("https://www.linkedin.com/feed/");await s.wait(3);const d=h(await s.evaluate(T()));if(!d?.ok)throw new m(l,`LinkedIn create requires an active signed-in LinkedIn browser session (${d?.error||"probe_failed"}).`);if(!f)return[{status:"dry_run",content_chars:e.length,images:o.length,visibility:r.label,activity_urn:"(not published — pass --send true to publish)"}];const t=h(await s.evaluate(N({content:e,images:o,visibleToConnectionsOnly:r.visibleToConnectionsOnly})));if(!t?.ok){if(t?.stage==="auth"||t?.httpStatus===401||t?.httpStatus===403)throw new m(l,"LinkedIn create: session rejected by Voyager API — re-login in the desktop client.");const g=[`stage=${t?.stage||"unknown"}`,t?.index!=null?`image#${t.index}`:"",t?.httpStatus?`http=${t.httpStatus}`:"",t?.error?`error=${t.error}`:"",t?.raw?`raw=${t.raw}`:""].filter(Boolean).join(" ");throw new p(`LinkedIn create failed: ${g}`)}return[{status:"published",content_chars:e.length,images:t.images??o.length,visibility:r.label,activity_urn:t.activityUrn||t.updateUrn||""}]}});
@@ -1 +1 @@
1
- import{cli as T,Strategy as U}from"@jackwener/opencli/registry";import{ArgumentError as V,AuthRequiredError as W,CommandExecutionError as J}from"@jackwener/opencli/errors";import{LINKEDIN_DOMAIN as Q,unwrapEvaluateResult as X}from"./shared.js";import{buildFollowScript as Y}from"./social-api.js";T({site:"linkedin",name:"follow",access:"write",description:"Follow or unfollow a LinkedIn person or company page via the Voyager API. Following subscribes to their posts without a connection request (use `linkedin connect` for that). Takes a profile/company URL or urn.",domain:Q,strategy:U.COOKIE,browser:!0,args:[{name:"target",type:"string",required:!0,positional:!0,help:"Who to follow. A person MUST be given as a profile URL (…/in/<handle>) or urn:li:fsd_profile:… urn. A company can be a company URL (…/company/<name>), a bare company name (resolved as a company, never a person), or a urn:li:fsd_company:… urn."},{name:"unfollow",type:"bool",required:!1,default:!1,help:"Unfollow instead of follow."}],columns:["status","entity_urn"],func:async(B,G)=>{if(!B)throw new J("Browser session required for linkedin follow");const H=String(G?.target??"").trim();if(!H)throw new V("target is required (profile/company URL or urn)");const P=G?.unfollow===!0||G?.unfollow==="true";await B.goto("https://www.linkedin.com/feed/");await B.wait(2);const z=X(await B.evaluate(Y({target:H,following:!P})));if(!z?.ok){if(z?.stage==="auth"||z?.httpStatus===401||z?.httpStatus===403)throw new W(Q,`LinkedIn follow requires an active signed-in LinkedIn browser session (${z?.error||"auth"}).`);if(z?.stage==="resolve")throw new J(`LinkedIn follow could not resolve "${H}" to a person or company. Pass a /in/<handle> URL, a /company/<name> URL, or a urn.`);throw new J(`LinkedIn follow failed: stage=${z?.stage||"unknown"} http=${z?.httpStatus||"?"} ${z?.error||""}`.trim())}return[{status:P?"unfollowed":"followed",entity_urn:z.entity_urn||""}]}});
1
+ import{cli as l,Strategy as s}from"@jackwener/opencli/registry";import{ArgumentError as u,AuthRequiredError as w,CommandExecutionError as t}from"@jackwener/opencli/errors";import{LINKEDIN_DOMAIN as i,unwrapEvaluateResult as f}from"./shared.js";import{buildFollowScript as p}from"./social-api.js";l({site:"linkedin",name:"follow",access:"write",description:"Follow or unfollow a LinkedIn person or company page via the Voyager API. Following subscribes to their posts without a connection request (use `linkedin connect` for that). Takes a profile/company URL or urn.",domain:i,strategy:s.COOKIE,browser:!0,args:[{name:"target",type:"string",required:!0,positional:!0,help:"Who to follow. A person MUST be given as a profile URL (…/in/<handle>) or urn:li:fsd_profile:… urn. A company can be a company URL (…/company/<name>), a bare company name (resolved as a company, never a person), or a urn:li:fsd_company:… urn."},{name:"unfollow",type:"bool",required:!1,default:!1,help:"Unfollow instead of follow."}],columns:["status","entity_urn"],func:async(e,n)=>{if(!e)throw new t("Browser session required for linkedin follow");const r=String(n?.target??"").trim();if(!r)throw new u("target is required (profile/company URL or urn)");const a=n?.unfollow===!0||n?.unfollow==="true";await e.goto("https://www.linkedin.com/feed/");await e.wait(2);const o=f(await e.evaluate(p({target:r,following:!a})));if(!o?.ok){if(o?.stage==="auth"||o?.httpStatus===401||o?.httpStatus===403)throw new w(i,`LinkedIn follow requires an active signed-in LinkedIn browser session (${o?.error||"auth"}).`);if(o?.stage==="resolve")throw new t(`LinkedIn follow could not resolve "${r}" to a person or company. Pass a /in/<handle> URL, a /company/<name> URL, or a urn.`);throw new t(`LinkedIn follow failed: stage=${o?.stage||"unknown"} http=${o?.httpStatus||"?"} ${o?.error||""}`.trim())}return[{status:a?"unfollowed":"followed",entity_urn:o.entity_urn||""}]}});