publishport-opencli 1.0.20 → 1.0.22

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 (1045) 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 +75 -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.d.ts +14 -1
  952. package/dist/src/browser/base-page.js +25 -25
  953. package/dist/src/browser/bridge.js +1 -1
  954. package/dist/src/browser/cdp.js +1 -1
  955. package/dist/src/browser/daemon-client.js +1 -1
  956. package/dist/src/browser/daemon-lifecycle.js +7 -7
  957. package/dist/src/browser/dom-helpers.d.ts +24 -0
  958. package/dist/src/browser/dom-helpers.js +36 -36
  959. package/dist/src/browser/dom-snapshot.js +19 -19
  960. package/dist/src/browser/errors.js +3 -3
  961. package/dist/src/browser/extract.js +5 -5
  962. package/dist/src/browser/find.js +13 -13
  963. package/dist/src/browser/fingerprint.js +2 -2
  964. package/dist/src/browser/html-tree.js +6 -6
  965. package/dist/src/browser/managed-chrome.js +1 -1
  966. package/dist/src/browser/network-cache.js +1 -1
  967. package/dist/src/browser/network-key.js +1 -1
  968. package/dist/src/browser/page.js +7 -7
  969. package/dist/src/browser/profile.js +2 -2
  970. package/dist/src/browser/proxy-test.js +8 -8
  971. package/dist/src/browser/shape-filter.js +1 -1
  972. package/dist/src/browser/shape.js +1 -1
  973. package/dist/src/browser/stealth.js +3 -3
  974. package/dist/src/browser/tabs.js +2 -2
  975. package/dist/src/browser/target-errors.js +1 -1
  976. package/dist/src/browser/target-resolver.js +23 -23
  977. package/dist/src/browser/trace.js +2 -2
  978. package/dist/src/browser/utils.js +1 -1
  979. package/dist/src/browser/verify-fixture.js +2 -2
  980. package/dist/src/browser-session-lock.js +1 -1
  981. package/dist/src/build-manifest.js +11 -11
  982. package/dist/src/capabilityRouting.js +1 -1
  983. package/dist/src/cli-argv-preprocess.js +1 -1
  984. package/dist/src/cli.js +32 -32
  985. package/dist/src/commanderAdapter.js +3 -3
  986. package/dist/src/commands/auth.js +3 -3
  987. package/dist/src/commands/daemon.d.ts +3 -1
  988. package/dist/src/commands/daemon.js +1 -1
  989. package/dist/src/completion-fast.js +1 -1
  990. package/dist/src/completion.js +1 -1
  991. package/dist/src/constants.js +1 -1
  992. package/dist/src/convention-audit.js +2 -2
  993. package/dist/src/daemon-utils.js +1 -1
  994. package/dist/src/daemon.js +1 -1
  995. package/dist/src/discovery.js +2 -2
  996. package/dist/src/doctor.js +9 -9
  997. package/dist/src/download/article-download.js +15 -15
  998. package/dist/src/download/index.js +4 -4
  999. package/dist/src/download/media-download.js +1 -1
  1000. package/dist/src/download/progress.js +3 -3
  1001. package/dist/src/electron-apps.js +1 -1
  1002. package/dist/src/errors.js +2 -2
  1003. package/dist/src/execution.js +2 -2
  1004. package/dist/src/external.js +1 -1
  1005. package/dist/src/help.js +8 -8
  1006. package/dist/src/hooks.js +1 -1
  1007. package/dist/src/interceptor.js +21 -21
  1008. package/dist/src/launcher.js +7 -7
  1009. package/dist/src/logger.js +8 -8
  1010. package/dist/src/main.js +7 -7
  1011. package/dist/src/observation/artifact.js +5 -5
  1012. package/dist/src/observation/retention.js +1 -1
  1013. package/dist/src/output.js +2 -2
  1014. package/dist/src/package-paths.js +1 -1
  1015. package/dist/src/pipeline/executor.js +1 -1
  1016. package/dist/src/pipeline/registry.js +1 -1
  1017. package/dist/src/pipeline/steps/browser.js +1 -1
  1018. package/dist/src/pipeline/steps/download.js +1 -1
  1019. package/dist/src/pipeline/steps/fetch.js +6 -6
  1020. package/dist/src/pipeline/steps/intercept.js +1 -1
  1021. package/dist/src/pipeline/steps/tap.js +17 -17
  1022. package/dist/src/pipeline/steps/transform.js +1 -1
  1023. package/dist/src/pipeline/template.js +1 -1
  1024. package/dist/src/plugin-manifest.js +1 -1
  1025. package/dist/src/plugin-scaffold.js +19 -19
  1026. package/dist/src/plugin.js +12 -12
  1027. package/dist/src/rate-limit.js +1 -1
  1028. package/dist/src/registry.js +1 -1
  1029. package/dist/src/runtime-detect.js +1 -1
  1030. package/dist/src/runtime.js +1 -1
  1031. package/dist/src/scripts/framework.js +1 -1
  1032. package/dist/src/scripts/interact.js +1 -1
  1033. package/dist/src/scripts/store.js +1 -1
  1034. package/dist/src/serialization.js +2 -2
  1035. package/dist/src/session-lease.js +1 -1
  1036. package/dist/src/snapshotFormatter.js +2 -2
  1037. package/dist/src/tui.js +12 -12
  1038. package/dist/src/types.d.ts +2 -1
  1039. package/dist/src/user-runtime.js +1 -1
  1040. package/dist/src/utils.d.ts +12 -0
  1041. package/dist/src/utils.js +4 -4
  1042. package/dist/src/validate.js +2 -2
  1043. package/dist/src/verify.js +2 -2
  1044. package/dist/src/version.js +1 -1
  1045. package/package.json +1 -1
@@ -1,55 +1,55 @@
1
- import{cli as D,Strategy as T}from"@jackwener/opencli/registry";import{ArgumentError as y,CommandExecutionError as R}from"@jackwener/opencli/errors";import{authHeadersFragment as j,resolveShortIdFragment as B}from"./in-page.js";import{dispatchEvaluateResult as U}from"./errors.js";import{SLOCK_SITE as h,SLOCK_DOMAIN as K,SLOCK_HOME_URL as C,SLOCK_API_BASE as W}from"./shared.js";import{UUID_RE as H,classifyTarget as L}from"./resolve.js";D({site:h,name:"message-send",access:"write",description:"Send a message to a channel, DM, or thread (content sent verbatim)",domain:K,strategy:T.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"target",positional:!0,required:!0,help:'"#channel", "#channel:msgIdOrShort", "dm:@name", "dm:<uuid>", or channel UUID'},{name:"content",fromFile:!0,positional:!0,required:!0,help:"Message body (sent verbatim, no marker)"},{name:"dry-run",type:"bool",default:!1,help:"Print the planned payload without sending"},{name:"as-task",type:"bool",default:!1,help:"Create the message as a task (asTask)"},{name:"attach",help:"Comma-separated attachmentId UUIDs (upload separately first)"},{name:"server",help:"Override active server (slug or id)"}],columns:["target","channelId","content","result","messageId"],func:async(f,Q)=>{const q=String(Q.target??"").trim();if(!q)throw new y("target required");const Y=String(Q.content??""),V=!!Q["as-task"],Z=String(Q.attach??"").split(",").map((G)=>G.trim()).filter(Boolean);for(const G of Z)if(!H.test(G))throw new y(`--attach expects attachmentId UUIDs; "${G}" is not a UUID`);let $;try{$=L(q)}catch(G){throw new y(G.message)}const X={asTask:V,attachmentIds:Z};if(Q["dry-run"])return[{target:q,channelId:"(not resolved in dry-run)",content:Y,result:V?"dry-run (asTask)":"dry-run",messageId:null}];await f.goto(C);const J=P(q,Y,$,Q.server,X),N=await f.evaluate(`(async () => { ${J} })()`),z=U(N)[0]??{},b=z.id??z.messageId;if(!b)throw new R("Slock message-send succeeded without returning a message id; refusing to report a sent row.");return[{target:q,channelId:z.channelId??"",content:Y,result:"sent",messageId:b}]}});function P(f,Q,q,Y,V={}){const Z=Y??null,$=JSON.stringify(Q),X=[];if(V.asTask)X.push("asTask: true");if(Array.isArray(V.attachmentIds)&&V.attachmentIds.length)X.push(`attachmentIds: ${JSON.stringify(V.attachmentIds)}`);const J=X.length?", "+X.join(", "):"",N=j({serverScoped:!0,serverIdOverride:Z}),F=`
1
+ import{cli as w,Strategy as y}from"@jackwener/opencli/registry";import{ArgumentError as f,CommandExecutionError as S}from"@jackwener/opencli/errors";import{authHeadersFragment as k,resolveShortIdFragment as O}from"./in-page.js";import{dispatchEvaluateResult as v}from"./errors.js";import{SLOCK_SITE as C,SLOCK_DOMAIN as b,SLOCK_HOME_URL as N,SLOCK_API_BASE as a}from"./shared.js";import{UUID_RE as g,classifyTarget as J}from"./resolve.js";w({site:C,name:"message-send",access:"write",description:"Send a message to a channel, DM, or thread (content sent verbatim)",domain:b,strategy:y.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"target",positional:!0,required:!0,help:'"#channel", "#channel:msgIdOrShort", "dm:@name", "dm:<uuid>", or channel UUID'},{name:"content",fromFile:!0,positional:!0,required:!0,help:"Message body (sent verbatim, no marker)"},{name:"dry-run",type:"bool",default:!1,help:"Print the planned payload without sending"},{name:"as-task",type:"bool",default:!1,help:"Create the message as a task (asTask)"},{name:"attach",help:"Comma-separated attachmentId UUIDs (upload separately first)"},{name:"server",help:"Override active server (slug or id)"}],columns:["target","channelId","content","result","messageId"],func:async(l,n)=>{const e=String(n.target??"").trim();if(!e)throw new f("target required");const i=String(n.content??""),r=!!n["as-task"],o=String(n.attach??"").split(",").map((s)=>s.trim()).filter(Boolean);for(const s of o)if(!g.test(s))throw new f(`--attach expects attachmentId UUIDs; "${s}" is not a UUID`);let c;try{c=J(e)}catch(s){throw new f(s.message)}const d={asTask:r,attachmentIds:o};if(n["dry-run"])return[{target:e,channelId:"(not resolved in dry-run)",content:i,result:r?"dry-run (asTask)":"dry-run",messageId:null}];await l.goto(N);const u=T(e,i,c,n.server,d),m=await l.evaluate(`(async () => { ${u} })()`),t=v(m)[0]??{},h=t.id??t.messageId;if(!h)throw new S("Slock message-send succeeded without returning a message id; refusing to report a sent row.");return[{target:e,channelId:t.channelId??"",content:i,result:"sent",messageId:h}]}});function T(l,n,e,i,r={}){const o=i??null,c=JSON.stringify(n),d=[];if(r.asTask)d.push("asTask: true");if(Array.isArray(r.attachmentIds)&&r.attachmentIds.length)d.push(`attachmentIds: ${JSON.stringify(r.attachmentIds)}`);const u=d.length?", "+d.join(", "):"",m=k({serverScoped:!0,serverIdOverride:o}),p=`
2
2
  if (!channelId) return { kind: 'http', status: 500, where:'/messages (target resolved without channelId)' };
3
- const mres = await fetch('${W}/messages', { method:'POST', credentials:'include', headers, body: JSON.stringify({ channelId, content: ${$}${J} }) });
3
+ const mres = await fetch('${a}/messages', { method:'POST', credentials:'include', headers, body: JSON.stringify({ channelId, content: ${c}${u} }) });
4
4
  if (!mres.ok) return { kind: mres.status===401?'auth':'http', status: mres.status, where:'/messages' };
5
5
  const m = await mres.json();
6
6
  const messageId = m.id ?? m.messageId;
7
7
  if (!messageId) return { kind: 'http', status: 200, where:'/messages (no message id in response)' };
8
8
  return { kind: 'ok', rows: [{ id: messageId, channelId }] };
9
- `;let z="";if(q.kind==="channel-uuid")z=`let channelId = ${JSON.stringify(q.channelId)};`;else if(q.kind==="channel-name")z=`
10
- const cres = await fetch('${W}/channels/', { credentials:'include', headers });
9
+ `;let t="";if(e.kind==="channel-uuid")t=`let channelId = ${JSON.stringify(e.channelId)};`;else if(e.kind==="channel-name")t=`
10
+ const cres = await fetch('${a}/channels/', { credentials:'include', headers });
11
11
  if (!cres.ok) return { kind: cres.status===401?'auth':'http', status: cres.status, where:'/channels/' };
12
12
  const carr = await cres.json();
13
- const hit = (Array.isArray(carr)?carr:(carr.channels||carr.data||[])).find((c) => (c.name||c.slug||'').toLowerCase() === ${JSON.stringify(q.name)});
14
- if (!hit) return { kind: 'unresolvable', detail: 'no channel matches ' + ${JSON.stringify(q.name)} };
13
+ const hit = (Array.isArray(carr)?carr:(carr.channels||carr.data||[])).find((c) => (c.name||c.slug||'').toLowerCase() === ${JSON.stringify(e.name)});
14
+ if (!hit) return { kind: 'unresolvable', detail: 'no channel matches ' + ${JSON.stringify(e.name)} };
15
15
  let channelId = hit.id;
16
- `;else if(q.kind==="dm-uuid")z=`
17
- const dres = await fetch('${W}/channels/dm', { method:'POST', credentials:'include', headers, body: JSON.stringify({ userId: ${JSON.stringify(q.userId)} }) });
16
+ `;else if(e.kind==="dm-uuid")t=`
17
+ const dres = await fetch('${a}/channels/dm', { method:'POST', credentials:'include', headers, body: JSON.stringify({ userId: ${JSON.stringify(e.userId)} }) });
18
18
  if (!dres.ok) return { kind: dres.status===401?'auth':'http', status: dres.status, where:'/channels/dm' };
19
19
  const dd = await dres.json();
20
20
  let channelId = dd.channelId ?? dd.id;
21
21
  if (!channelId) return { kind: 'http', status: 500, where: '/channels/dm (no id in response)' };
22
- `;else if(q.kind==="dm-name")z=`
23
- const sres2 = await fetch('${W}/servers/' + encodeURIComponent(sid) + '/members', { credentials:'include', headers });
22
+ `;else if(e.kind==="dm-name")t=`
23
+ const sres2 = await fetch('${a}/servers/' + encodeURIComponent(sid) + '/members', { credentials:'include', headers });
24
24
  if (!sres2.ok) return { kind: sres2.status===401?'auth':'http', status: sres2.status, where:'/servers/:id/members' };
25
25
  const mlist = await sres2.json();
26
26
  const marr = Array.isArray(mlist) ? mlist : (mlist.members || mlist.data || []);
27
- const mh = marr.find((u) => (u.username||u.name||u.displayName||'').toLowerCase() === ${JSON.stringify(q.name.toLowerCase())});
28
- if (!mh) return { kind: 'unresolvable', detail: 'no member @' + ${JSON.stringify(q.name)} };
29
- const dres = await fetch('${W}/channels/dm', { method:'POST', credentials:'include', headers, body: JSON.stringify({ userId: mh.userId ?? mh.id }) });
27
+ const mh = marr.find((u) => (u.username||u.name||u.displayName||'').toLowerCase() === ${JSON.stringify(e.name.toLowerCase())});
28
+ if (!mh) return { kind: 'unresolvable', detail: 'no member @' + ${JSON.stringify(e.name)} };
29
+ const dres = await fetch('${a}/channels/dm', { method:'POST', credentials:'include', headers, body: JSON.stringify({ userId: mh.userId ?? mh.id }) });
30
30
  if (!dres.ok) return { kind: dres.status===401?'auth':'http', status: dres.status, where:'/channels/dm' };
31
31
  const dd = await dres.json();
32
32
  let channelId = dd.channelId ?? dd.id;
33
33
  if (!channelId) return { kind: 'http', status: 500, where: '/channels/dm (no id in response)' };
34
- `;else if(q.kind==="thread"){const b=H.test(q.parentTarget),G=JSON.stringify(q.parentTarget.replace(/^#/,"").toLowerCase()),M=JSON.stringify(q.parentMsgId);z=`
34
+ `;else if(e.kind==="thread"){const h=g.test(e.parentTarget),s=JSON.stringify(e.parentTarget.replace(/^#/,"").toLowerCase()),I=JSON.stringify(e.parentMsgId);t=`
35
35
  let parentChannelId;
36
- if (${b}) {
37
- parentChannelId = ${JSON.stringify(q.parentTarget)};
36
+ if (${h}) {
37
+ parentChannelId = ${JSON.stringify(e.parentTarget)};
38
38
  } else {
39
- const cres = await fetch('${W}/channels/', { credentials:'include', headers });
39
+ const cres = await fetch('${a}/channels/', { credentials:'include', headers });
40
40
  if (!cres.ok) return { kind: cres.status===401?'auth':'http', status: cres.status, where:'/channels/' };
41
41
  const carr = await cres.json();
42
- const hit = (Array.isArray(carr)?carr:(carr.channels||carr.data||[])).find((c) => (c.name||c.slug||'').toLowerCase() === ${G});
43
- if (!hit) return { kind: 'unresolvable', detail: 'no parent channel: ' + ${G} };
42
+ const hit = (Array.isArray(carr)?carr:(carr.channels||carr.data||[])).find((c) => (c.name||c.slug||'').toLowerCase() === ${s});
43
+ if (!hit) return { kind: 'unresolvable', detail: 'no parent channel: ' + ${s} };
44
44
  parentChannelId = hit.id;
45
45
  }
46
- let fullMsgId = ${M};
47
- ${B({shortIdVar:"fullMsgId",parentChannelIdVar:"parentChannelId"})}
48
- const tres = await fetch('${W}/channels/' + encodeURIComponent(parentChannelId) + '/threads', { method:'POST', credentials:'include', headers, body: JSON.stringify({ parentMessageId: fullMsgId }) });
46
+ let fullMsgId = ${I};
47
+ ${O({shortIdVar:"fullMsgId",parentChannelIdVar:"parentChannelId"})}
48
+ const tres = await fetch('${a}/channels/' + encodeURIComponent(parentChannelId) + '/threads', { method:'POST', credentials:'include', headers, body: JSON.stringify({ parentMessageId: fullMsgId }) });
49
49
  if (!tres.ok) return { kind: tres.status===401?'auth':'http', status: tres.status, where:'/channels/:id/threads' };
50
50
  const td = await tres.json();
51
51
  let channelId = td.threadChannelId ?? td.channelId ?? td.id;
52
52
  if (!channelId) return { kind: 'http', status: 500, where:'/channels/:id/threads (no id)' };
53
- `}return`${N}
54
- ${z}
55
- ${F}`}
53
+ `}return`${m}
54
+ ${t}
55
+ ${p}`}
@@ -1 +1 @@
1
- import{cli as d,Strategy as n}from"@jackwener/opencli/registry";import{ArgumentError as i}from"@jackwener/opencli/errors";import{buildFetchSnippet as c}from"./in-page.js";import{dispatchEvaluateResult as u}from"./errors.js";import{SLOCK_SITE as p,SLOCK_DOMAIN as l,SLOCK_HOME_URL as g}from"./shared.js";import{assertMessageIdShape as S}from"./resolve.js";d({site:p,name:"reaction-add",access:"write",description:"Add an emoji reaction to a message (POST /messages/:id/reactions). Idempotent server-side.",domain:l,strategy:n.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"messageId",positional:!0,required:!0,help:"Full messageId UUID (short ids rejected)"},{name:"emoji",positional:!0,required:!0,help:"A single unicode emoji, e.g. \uD83D\uDC4D"},{name:"server",help:"Override active server"}],columns:["messageId","emoji","result"],func:async(s,e)=>{let r;try{r=S(String(e.messageId??""))}catch(m){throw new i(m.message)}const t=String(e.emoji??"").trim();if(!t)throw new i("emoji required (a single unicode emoji)");await s.goto(g);const o=c({method:"POST",path:`/messages/${r}/reactions`,body:{emoji:t},serverScoped:!0,serverIdOverride:e.server}),a=await s.evaluate(`(async () => { ${o} })()`);u(a);return[{messageId:r,emoji:t,result:"added"}]}});
1
+ import{cli as n,Strategy as d}from"@jackwener/opencli/registry";import{ArgumentError as i}from"@jackwener/opencli/errors";import{buildFetchSnippet as c}from"./in-page.js";import{dispatchEvaluateResult as u}from"./errors.js";import{SLOCK_SITE as p,SLOCK_DOMAIN as l,SLOCK_HOME_URL as g}from"./shared.js";import{assertMessageIdShape as S}from"./resolve.js";n({site:p,name:"reaction-add",access:"write",description:"Add an emoji reaction to a message (POST /messages/:id/reactions). Idempotent server-side.",domain:l,strategy:d.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"messageId",positional:!0,required:!0,help:"Full messageId UUID (short ids rejected)"},{name:"emoji",positional:!0,required:!0,help:"A single unicode emoji, e.g. \uD83D\uDC4D"},{name:"server",help:"Override active server"}],columns:["messageId","emoji","result"],func:async(s,e)=>{let r;try{r=S(String(e.messageId??""))}catch(m){throw new i(m.message)}const t=String(e.emoji??"").trim();if(!t)throw new i("emoji required (a single unicode emoji)");await s.goto(g);const o=c({method:"POST",path:`/messages/${r}/reactions`,body:{emoji:t},serverScoped:!0,serverIdOverride:e.server}),a=await s.evaluate(`(async () => { ${o} })()`);u(a);return[{messageId:r,emoji:t,result:"added"}]}});
@@ -1 +1 @@
1
- import{cli as n,Strategy as d}from"@jackwener/opencli/registry";import{ArgumentError as s}from"@jackwener/opencli/errors";import{buildFetchSnippet as c}from"./in-page.js";import{dispatchEvaluateResult as u}from"./errors.js";import{SLOCK_SITE as p,SLOCK_DOMAIN as l,SLOCK_HOME_URL as v}from"./shared.js";import{assertMessageIdShape as g}from"./resolve.js";n({site:p,name:"reaction-remove",access:"write",description:"Remove your emoji reaction from a message (DELETE /messages/:id/reactions).",domain:l,strategy:d.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"messageId",positional:!0,required:!0,help:"Full messageId UUID (short ids rejected)"},{name:"emoji",positional:!0,required:!0,help:"The unicode emoji to remove, e.g. \uD83D\uDC4D"},{name:"server",help:"Override active server"}],columns:["messageId","emoji","result"],func:async(o,e)=>{let r;try{r=g(String(e.messageId??""))}catch(a){throw new s(a.message)}const t=String(e.emoji??"").trim();if(!t)throw new s("emoji required (the unicode emoji to remove)");await o.goto(v);const i=c({method:"DELETE",path:`/messages/${r}/reactions`,body:{emoji:t},serverScoped:!0,serverIdOverride:e.server}),m=await o.evaluate(`(async () => { ${i} })()`);u(m);return[{messageId:r,emoji:t,result:"removed"}]}});
1
+ import{cli as n,Strategy as d}from"@jackwener/opencli/registry";import{ArgumentError as o}from"@jackwener/opencli/errors";import{buildFetchSnippet as c}from"./in-page.js";import{dispatchEvaluateResult as u}from"./errors.js";import{SLOCK_SITE as p,SLOCK_DOMAIN as l,SLOCK_HOME_URL as g}from"./shared.js";import{assertMessageIdShape as v}from"./resolve.js";n({site:p,name:"reaction-remove",access:"write",description:"Remove your emoji reaction from a message (DELETE /messages/:id/reactions).",domain:l,strategy:d.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"messageId",positional:!0,required:!0,help:"Full messageId UUID (short ids rejected)"},{name:"emoji",positional:!0,required:!0,help:"The unicode emoji to remove, e.g. \uD83D\uDC4D"},{name:"server",help:"Override active server"}],columns:["messageId","emoji","result"],func:async(s,e)=>{let r;try{r=v(String(e.messageId??""))}catch(a){throw new o(a.message)}const t=String(e.emoji??"").trim();if(!t)throw new o("emoji required (the unicode emoji to remove)");await s.goto(g);const i=c({method:"DELETE",path:`/messages/${r}/reactions`,body:{emoji:t},serverScoped:!0,serverIdOverride:e.server}),m=await s.evaluate(`(async () => { ${i} })()`);u(m);return[{messageId:r,emoji:t,result:"removed"}]}});
@@ -1 +1 @@
1
- import{ArgumentError as C}from"@jackwener/opencli/errors";export const UUID_RE=/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;export function classifyThreadTarget(q){const B=String(q??"").trim().match(/^(#?[^:]+):([A-Za-z0-9-]{6,})$/);if(!B)return null;return{parentTarget:B[1],parentMsgId:B[2]}}export function classifyTarget(q){const b=String(q??"").trim();if(!b)throw new C('target required: "#channel", "#channel:threadShortId", "dm:@name", "dm:<userId>", or channelId UUID.');if(b.startsWith("dm:")){const z=b.slice(3);if(!z)throw new C('dm target must be "dm:<userId>" or "dm:@name".');if(UUID_RE.test(z))return{kind:"dm-uuid",userId:z};if(z.startsWith("@"))return{kind:"dm-name",name:z.slice(1)};throw new C('dm target must be "dm:<userId-uuid>" or "dm:@name".')}const B=classifyThreadTarget(b);if(B)return{kind:"thread",...B};if(UUID_RE.test(b))return{kind:"channel-uuid",channelId:b};return{kind:"channel-name",name:b.replace(/^#/,"").toLowerCase()}}const L="short ids (the 8-hex `msg=...` form in channel headers) are NOT accepted — use the FULL UUID "+"from `bookmark-list` / `message-read` output.";export function assertMessageIdShape(q){const b=String(q??"").trim();if(!b)throw new C("messageId required");if(!UUID_RE.test(b))throw new C(`messageId "${b}" is not a full UUID. ${L}`);return b}export function parsePositiveInteger(q,b,{defaultValue:B,max:z}={}){const F=q===void 0||q===null||q===""?B:q,G=J(F);if(!Number.isInteger(G)||G<=0||z!==void 0&&G>z){const K=z!==void 0?` between 1 and ${z}`:" as a positive integer";throw new C(`${b} must be${K} (got "${F}")`)}return G}export function parseNonNegativeInteger(q,b,{defaultValue:B}={}){const z=q===void 0||q===null||q===""?B:q,F=J(z);if(!Number.isInteger(F)||F<0)throw new C(`${b} must be a non-negative integer (got "${z}")`);return F}function J(q){if(typeof q==="number")return q;const b=String(q);if(!/^\d+$/.test(b))return NaN;return Number(b)}
1
+ import{ArgumentError as s}from"@jackwener/opencli/errors";export const UUID_RE=/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;export function classifyThreadTarget(t){const r=String(t??"").trim().match(/^(#?[^:]+):([A-Za-z0-9-]{6,})$/);if(!r)return null;return{parentTarget:r[1],parentMsgId:r[2]}}export function classifyTarget(t){const e=String(t??"").trim();if(!e)throw new s('target required: "#channel", "#channel:threadShortId", "dm:@name", "dm:<userId>", or channelId UUID.');if(e.startsWith("dm:")){const n=e.slice(3);if(!n)throw new s('dm target must be "dm:<userId>" or "dm:@name".');if(UUID_RE.test(n))return{kind:"dm-uuid",userId:n};if(n.startsWith("@"))return{kind:"dm-name",name:n.slice(1)};throw new s('dm target must be "dm:<userId-uuid>" or "dm:@name".')}const r=classifyThreadTarget(e);if(r)return{kind:"thread",...r};if(UUID_RE.test(e))return{kind:"channel-uuid",channelId:e};return{kind:"channel-name",name:e.replace(/^#/,"").toLowerCase()}}const u="short ids (the 8-hex `msg=...` form in channel headers) are NOT accepted — use the FULL UUID "+"from `bookmark-list` / `message-read` output.";export function assertMessageIdShape(t){const e=String(t??"").trim();if(!e)throw new s("messageId required");if(!UUID_RE.test(e))throw new s(`messageId "${e}" is not a full UUID. ${u}`);return e}export function parsePositiveInteger(t,e,{defaultValue:r,max:n}={}){const i=t===void 0||t===null||t===""?r:t,o=a(i);if(!Number.isInteger(o)||o<=0||n!==void 0&&o>n){const d=n!==void 0?` between 1 and ${n}`:" as a positive integer";throw new s(`${e} must be${d} (got "${i}")`)}return o}export function parseNonNegativeInteger(t,e,{defaultValue:r}={}){const n=t===void 0||t===null||t===""?r:t,i=a(n);if(!Number.isInteger(i)||i<0)throw new s(`${e} must be a non-negative integer (got "${n}")`);return i}function a(t){if(typeof t==="number")return t;const e=String(t);if(!/^\d+$/.test(e))return NaN;return Number(e)}
@@ -1,4 +1,4 @@
1
- import{cli as o,Strategy as n}from"@jackwener/opencli/registry";import{dispatchEvaluateResult as l}from"./errors.js";import{SLOCK_SITE as c,SLOCK_DOMAIN as u,SLOCK_HOME_URL as g,SLOCK_API_BASE as m}from"./shared.js";o({site:c,name:"server-list",access:"read",description:"List slock servers you belong to; marks active per localStorage slug",domain:u,strategy:n.COOKIE,browser:!0,siteSession:"persistent",args:[],columns:["id","slug","name","active"],func:async(e)=>{await e.goto(g);const a=`
1
+ import{cli as i,Strategy as n}from"@jackwener/opencli/registry";import{dispatchEvaluateResult as l}from"./errors.js";import{SLOCK_SITE as c,SLOCK_DOMAIN as u,SLOCK_HOME_URL as g,SLOCK_API_BASE as m}from"./shared.js";i({site:c,name:"server-list",access:"read",description:"List slock servers you belong to; marks active per localStorage slug",domain:u,strategy:n.COOKIE,browser:!0,siteSession:"persistent",args:[],columns:["id","slug","name","active"],func:async(e)=>{await e.goto(g);const a=`
2
2
  const token = localStorage.getItem('slock_access_token');
3
3
  if (!token) return { kind: 'auth', detail: 'no token' };
4
4
  const res = await fetch('${m}/servers/', { credentials:'include', headers:{authorization:'Bearer '+token,accept:'application/json'} });
@@ -6,4 +6,4 @@ import{cli as o,Strategy as n}from"@jackwener/opencli/registry";import{dispatchE
6
6
  const list = await res.json();
7
7
  const activeSlug = localStorage.getItem('slock_last_server_slug') || null;
8
8
  return { kind: 'ok', rows: Array.isArray(list) ? list : (list.servers || list.data || []), meta: { activeSlug } };
9
- `,s=await e.evaluate(`(async () => { ${a} })()`),r=l(s),i=s.meta?.activeSlug??null;return r.map((t)=>({id:t.id??"",slug:t.slug??"",name:t.name??"",active:t.slug===i}))}});
9
+ `,s=await e.evaluate(`(async () => { ${a} })()`),r=l(s),o=s.meta?.activeSlug??null;return r.map((t)=>({id:t.id??"",slug:t.slug??"",name:t.name??"",active:t.slug===o}))}});
@@ -1,6 +1,6 @@
1
- import{cli as W,Strategy as X}from"@jackwener/opencli/registry";import{ArgumentError as Y,CommandExecutionError as Q}from"@jackwener/opencli/errors";import{authHeadersFragment as Z}from"./in-page.js";import{dispatchEvaluateResult as $}from"./errors.js";import{SLOCK_SITE as B,SLOCK_DOMAIN as D,SLOCK_HOME_URL as F,SLOCK_API_BASE as P}from"./shared.js";import{assertMessageIdShape as U}from"./resolve.js";W({site:B,name:"task-claim",access:"write",description:"Claim a chat task (PATCH /tasks/:id/claim). Requires full task UUID (= message id).",domain:D,strategy:X.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"taskId",positional:!0,required:!0,help:"Full task UUID (= message id; short ids rejected)"},{name:"server",help:"Override active server"}],columns:["taskId","taskStatus","assigneeId","taskNumber"],func:async(J,q)=>{let z;try{z=U(String(q.taskId??""))}catch(b){throw new Y(b.message)}await J.goto(F);const G=`
2
- ${Z({serverScoped:!0,serverIdOverride:q.server})}
3
- const res = await fetch('${P}/tasks/' + encodeURIComponent(${JSON.stringify(z)}) + '/claim', { method:'PATCH', credentials:'include', headers });
1
+ import{cli as o,Strategy as u}from"@jackwener/opencli/registry";import{ArgumentError as d,CommandExecutionError as i}from"@jackwener/opencli/errors";import{authHeadersFragment as c}from"./in-page.js";import{dispatchEvaluateResult as m}from"./errors.js";import{SLOCK_SITE as l,SLOCK_DOMAIN as k,SLOCK_HOME_URL as h,SLOCK_API_BASE as p}from"./shared.js";import{assertMessageIdShape as w}from"./resolve.js";o({site:l,name:"task-claim",access:"write",description:"Claim a chat task (PATCH /tasks/:id/claim). Requires full task UUID (= message id).",domain:k,strategy:u.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"taskId",positional:!0,required:!0,help:"Full task UUID (= message id; short ids rejected)"},{name:"server",help:"Override active server"}],columns:["taskId","taskStatus","assigneeId","taskNumber"],func:async(r,e)=>{let s;try{s=w(String(e.taskId??""))}catch(t){throw new d(t.message)}await r.goto(h);const a=`
2
+ ${c({serverScoped:!0,serverIdOverride:e.server})}
3
+ const res = await fetch('${p}/tasks/' + encodeURIComponent(${JSON.stringify(s)}) + '/claim', { method:'PATCH', credentials:'include', headers });
4
4
  if (res.status === 404) return { kind: 'http', status: 404, where: '/tasks/:id/claim (task not found)' };
5
5
  if (res.status === 403) return { kind: 'http', status: 403, where: '/tasks/:id/claim (forbidden — not your task, terminal status, or channel archived)' };
6
6
  if (res.status === 409) return { kind: 'http', status: 409, where: '/tasks/:id/claim (conflict — already claimed by someone else; use task-unclaim first)' };
@@ -11,4 +11,4 @@ import{cli as W,Strategy as X}from"@jackwener/opencli/registry";import{ArgumentE
11
11
  // resolves to null even though the claim succeeded.
12
12
  const t = (data && data.task) ? data.task : data;
13
13
  return { kind: 'ok', rows: [t] };
14
- `,V=await J.evaluate(`(async () => { ${G} })()`);return $(V).map((b)=>({taskId:f(b,z,"task-claim"),taskStatus:b.taskStatus??b.status??"",assigneeId:b.claimedById??b.assigneeId??null,taskNumber:b.taskNumber??null}))}});function f(J,q,z){const G=J?.id;if(!G)throw new Q(`Slock ${z} succeeded without returning task id ${q}; refusing to report a task row.`);if(G!==q)throw new Q(`Slock ${z} returned task id ${G}, expected ${q}.`);return G}
14
+ `,n=await r.evaluate(`(async () => { ${a} })()`);return m(n).map((t)=>({taskId:f(t,s,"task-claim"),taskStatus:t.taskStatus??t.status??"",assigneeId:t.claimedById??t.assigneeId??null,taskNumber:t.taskNumber??null}))}});function f(r,e,s){const a=r?.id;if(!a)throw new i(`Slock ${s} succeeded without returning task id ${e}; refusing to report a task row.`);if(a!==e)throw new i(`Slock ${s} returned task id ${a}, expected ${e}.`);return a}
@@ -1,21 +1,21 @@
1
- import{cli as b,Strategy as f}from"@jackwener/opencli/registry";import{ArgumentError as W}from"@jackwener/opencli/errors";import{authHeadersFragment as B,resolveShortIdFragment as H}from"./in-page.js";import{dispatchEvaluateResult as M}from"./errors.js";import{SLOCK_SITE as P,SLOCK_DOMAIN as y,SLOCK_HOME_URL as D,SLOCK_API_BASE as X}from"./shared.js";import{UUID_RE as Y,classifyThreadTarget as T}from"./resolve.js";b({site:P,name:"task-convert",access:"write",description:'Convert a message into a chat task (POST /tasks/convert-message). Accepts a message UUID or "#channel:shortId".',domain:y,strategy:f.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"messageId",positional:!0,required:!0,help:'Full message UUID, or "#channel:shortId" (short id expanded via /messages/context)'},{name:"server",help:"Override active server"}],columns:["id","taskNumber","title","taskStatus","channelId"],func:async(Q,V)=>{const z=String(V.messageId??"").trim();if(!z)throw new W("messageId required");let G;if(Y.test(z))G=`const fullMsgId = ${JSON.stringify(z)};`;else{const q=T(z);if(!q)throw new W(`messageId "${z}" is not a UUID or a "#channel:shortId" form`);const x=Y.test(q.parentTarget),J=JSON.stringify(q.parentTarget.replace(/^#/,"").toLowerCase()),N=JSON.stringify(q.parentMsgId);G=`
1
+ import{cli as m,Strategy as g}from"@jackwener/opencli/registry";import{ArgumentError as o}from"@jackwener/opencli/errors";import{authHeadersFragment as p,resolveShortIdFragment as f}from"./in-page.js";import{dispatchEvaluateResult as I}from"./errors.js";import{SLOCK_SITE as k,SLOCK_DOMAIN as w,SLOCK_HOME_URL as v,SLOCK_API_BASE as i}from"./shared.js";import{UUID_RE as c,classifyThreadTarget as S}from"./resolve.js";m({site:k,name:"task-convert",access:"write",description:'Convert a message into a chat task (POST /tasks/convert-message). Accepts a message UUID or "#channel:shortId".',domain:w,strategy:g.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"messageId",positional:!0,required:!0,help:'Full message UUID, or "#channel:shortId" (short id expanded via /messages/context)'},{name:"server",help:"Override active server"}],columns:["id","taskNumber","title","taskStatus","channelId"],func:async(r,n)=>{const t=String(n.messageId??"").trim();if(!t)throw new o("messageId required");let s;if(c.test(t))s=`const fullMsgId = ${JSON.stringify(t)};`;else{const e=S(t);if(!e)throw new o(`messageId "${t}" is not a UUID or a "#channel:shortId" form`);const h=c.test(e.parentTarget),a=JSON.stringify(e.parentTarget.replace(/^#/,"").toLowerCase()),u=JSON.stringify(e.parentMsgId);s=`
2
2
  let parentChannelId;
3
- if (${x}) {
4
- parentChannelId = ${JSON.stringify(q.parentTarget)};
3
+ if (${h}) {
4
+ parentChannelId = ${JSON.stringify(e.parentTarget)};
5
5
  } else {
6
- const cres = await fetch('${X}/channels/', { credentials:'include', headers });
6
+ const cres = await fetch('${i}/channels/', { credentials:'include', headers });
7
7
  if (!cres.ok) return { kind: cres.status===401?'auth':'http', status: cres.status, where:'/channels/' };
8
8
  const carr = await cres.json();
9
- const hit = (Array.isArray(carr)?carr:(carr.channels||carr.data||[])).find((c) => (c.name||c.slug||'').toLowerCase() === ${J});
10
- if (!hit) return { kind: 'unresolvable', detail: 'no channel matches ' + ${J} };
9
+ const hit = (Array.isArray(carr)?carr:(carr.channels||carr.data||[])).find((c) => (c.name||c.slug||'').toLowerCase() === ${a});
10
+ if (!hit) return { kind: 'unresolvable', detail: 'no channel matches ' + ${a} };
11
11
  parentChannelId = hit.id;
12
12
  }
13
- let fullMsgId = ${N};
14
- ${H({shortIdVar:"fullMsgId",parentChannelIdVar:"parentChannelId",contextDescription:J})}
15
- `}await Q.goto(D);const Z=`
16
- ${B({serverScoped:!0,serverIdOverride:V.server})}
17
- ${G}
18
- const res = await fetch('${X}/tasks/convert-message', {
13
+ let fullMsgId = ${u};
14
+ ${f({shortIdVar:"fullMsgId",parentChannelIdVar:"parentChannelId",contextDescription:a})}
15
+ `}await r.goto(v);const d=`
16
+ ${p({serverScoped:!0,serverIdOverride:n.server})}
17
+ ${s}
18
+ const res = await fetch('${i}/tasks/convert-message', {
19
19
  method:'POST', credentials:'include', headers,
20
20
  body: JSON.stringify({ messageId: fullMsgId }),
21
21
  });
@@ -32,4 +32,4 @@ import{cli as b,Strategy as f}from"@jackwener/opencli/registry";import{ArgumentE
32
32
  // command surfaces the inner row instead of all-null columns.
33
33
  const t = (data && data.task) ? data.task : data;
34
34
  return { kind: 'ok', rows: [t] };
35
- `,$=await Q.evaluate(`(async () => { ${Z} })()`);return M($).map((q)=>({id:q.id??"",taskNumber:q.taskNumber??null,title:q.content??q.title??"",taskStatus:q.taskStatus??"todo",channelId:q.channelId??null}))}});
35
+ `,l=await r.evaluate(`(async () => { ${d} })()`);return I(l).map((e)=>({id:e.id??"",taskNumber:e.taskNumber??null,title:e.content??e.title??"",taskStatus:e.taskStatus??"todo",channelId:e.channelId??null}))}});
@@ -1,4 +1,4 @@
1
- import{cli as h,Strategy as l}from"@jackwener/opencli/registry";import{ArgumentError as i}from"@jackwener/opencli/errors";import{authHeadersFragment as u,channelResolveFragment as p}from"./in-page.js";import{dispatchEvaluateResult as m}from"./errors.js";import{SLOCK_SITE as k,SLOCK_DOMAIN as f,SLOCK_HOME_URL as w,SLOCK_API_BASE as b}from"./shared.js";h({site:k,name:"task-create",access:"write",description:"Create a task in a channel (single title; batch 1-50 is server-supported but client surface is single — see backlog R4).",domain:f,strategy:l.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"channel",positional:!0,required:!0,help:"channelId UUID or #name"},{name:"title",positional:!0,required:!0,help:"Task title (single; batch TODO via R4)"},{name:"desc",help:"Optional description body for the task"},{name:"server",help:"Override active server"}],columns:["id","taskNumber","title","taskStatus","channelId"],func:async(a,t)=>{const r=String(t.channel??"").trim();if(!r)throw new i("channel required");const s=String(t.title??"").trim();if(!s)throw new i("title required (non-empty)");const n=t.desc!=null?String(t.desc):"";await a.goto(w);const o=n?{title:s,description:n}:{title:s},c=`
1
+ import{cli as l,Strategy as h}from"@jackwener/opencli/registry";import{ArgumentError as i}from"@jackwener/opencli/errors";import{authHeadersFragment as u,channelResolveFragment as p}from"./in-page.js";import{dispatchEvaluateResult as m}from"./errors.js";import{SLOCK_SITE as k,SLOCK_DOMAIN as f,SLOCK_HOME_URL as w,SLOCK_API_BASE as b}from"./shared.js";l({site:k,name:"task-create",access:"write",description:"Create a task in a channel (single title; batch 1-50 is server-supported but client surface is single — see backlog R4).",domain:f,strategy:h.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"channel",positional:!0,required:!0,help:"channelId UUID or #name"},{name:"title",positional:!0,required:!0,help:"Task title (single; batch TODO via R4)"},{name:"desc",help:"Optional description body for the task"},{name:"server",help:"Override active server"}],columns:["id","taskNumber","title","taskStatus","channelId"],func:async(a,t)=>{const r=String(t.channel??"").trim();if(!r)throw new i("channel required");const s=String(t.title??"").trim();if(!s)throw new i("title required (non-empty)");const n=t.desc!=null?String(t.desc):"";await a.goto(w);const o=n?{title:s,description:n}:{title:s},c=`
2
2
  ${u({serverScoped:!0,serverIdOverride:t.server})}
3
3
  ${p(r)}
4
4
  // Body is always a batch array — N=1 here because the CLI exposes one
@@ -1,9 +1,9 @@
1
- import{cli as Q,Strategy as V}from"@jackwener/opencli/registry";import{ArgumentError as W}from"@jackwener/opencli/errors";import{authHeadersFragment as X}from"./in-page.js";import{dispatchEvaluateResult as Y}from"./errors.js";import{SLOCK_SITE as Z,SLOCK_DOMAIN as $,SLOCK_HOME_URL as x,SLOCK_API_BASE as B}from"./shared.js";import{assertMessageIdShape as D}from"./resolve.js";Q({site:Z,name:"task-delete",access:"write",description:"Delete a chat task (DELETE /tasks/:taskId). Requires --confirm — destructive, irreversible.",domain:$,strategy:V.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"taskId",positional:!0,required:!0,help:"Full task UUID (= message id; short ids rejected)"},{name:"confirm",type:"bool",default:!1,help:"Required acknowledgement: deletion is irreversible"},{name:"server",help:"Override active server"}],columns:["taskId","deleted"],func:async(z,q)=>{let b;try{b=D(String(q.taskId??""))}catch(f){throw new W(f.message)}if(!q.confirm)return[{taskId:b,deleted:!1,note:"no-op: pass --confirm to actually delete (irreversible)"}];await z.goto(x);const G=`
2
- ${X({serverScoped:!0,serverIdOverride:q.server})}
3
- const res = await fetch('${B}/tasks/' + encodeURIComponent(${JSON.stringify(b)}), { method:'DELETE', credentials:'include', headers });
1
+ import{cli as o,Strategy as n}from"@jackwener/opencli/registry";import{ArgumentError as d}from"@jackwener/opencli/errors";import{authHeadersFragment as u}from"./in-page.js";import{dispatchEvaluateResult as l}from"./errors.js";import{SLOCK_SITE as m,SLOCK_DOMAIN as c,SLOCK_HOME_URL as k,SLOCK_API_BASE as p}from"./shared.js";import{assertMessageIdShape as f}from"./resolve.js";o({site:m,name:"task-delete",access:"write",description:"Delete a chat task (DELETE /tasks/:taskId). Requires --confirm — destructive, irreversible.",domain:c,strategy:n.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"taskId",positional:!0,required:!0,help:"Full task UUID (= message id; short ids rejected)"},{name:"confirm",type:"bool",default:!1,help:"Required acknowledgement: deletion is irreversible"},{name:"server",help:"Override active server"}],columns:["taskId","deleted"],func:async(s,r)=>{let e;try{e=f(String(r.taskId??""))}catch(t){throw new d(t.message)}if(!r.confirm)return[{taskId:e,deleted:!1,note:"no-op: pass --confirm to actually delete (irreversible)"}];await s.goto(k);const a=`
2
+ ${u({serverScoped:!0,serverIdOverride:r.server})}
3
+ const res = await fetch('${p}/tasks/' + encodeURIComponent(${JSON.stringify(e)}), { method:'DELETE', credentials:'include', headers });
4
4
  if (res.status === 403) return { kind: 'http', status: 403, where: '/tasks/:taskId (forbidden — not the owner/admin or channel archived)' };
5
5
  if (res.status === 404) return { kind: 'http', status: 404, where: '/tasks/:taskId (task not found)' };
6
6
  if (!res.ok) return { kind: res.status===401?'auth':'http', status: res.status, where:'/tasks/:taskId' };
7
7
  // 204 No Content is common for DELETE; tolerate empty body.
8
- return { kind: 'ok', rows: [{ taskId: ${JSON.stringify(b)}, deleted: true }] };
9
- `,J=await z.evaluate(`(async () => { ${G} })()`);return Y(J).map((f)=>({taskId:f.taskId??b,deleted:f.deleted??!0}))}});
8
+ return { kind: 'ok', rows: [{ taskId: ${JSON.stringify(e)}, deleted: true }] };
9
+ `,i=await s.evaluate(`(async () => { ${a} })()`);return l(i).map((t)=>({taskId:t.taskId??e,deleted:t.deleted??!0}))}});
@@ -1,11 +1,11 @@
1
- import{cli as c,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as i}from"@jackwener/opencli/errors";import{authHeadersFragment as d,channelResolveFragment as h}from"./in-page.js";import{dispatchEvaluateResult as l}from"./errors.js";import{SLOCK_SITE as k,SLOCK_DOMAIN as p,SLOCK_HOME_URL as b,SLOCK_API_BASE as g}from"./shared.js";import{parsePositiveInteger as S}from"./resolve.js";c({site:k,name:"task-get",access:"read",description:"Fetch a task by channel + taskNumber (GET /tasks/channel/:channelId/number/:taskNumber).",domain:p,strategy:m.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"channel",positional:!0,required:!0,help:"channelId UUID or #name"},{name:"number",positional:!0,required:!0,help:'taskNumber (per-channel integer, as shown in "task #N")'},{name:"server",help:"Override active server"}],columns:["id","taskNumber","title","taskStatus","assigneeId"],func:async(r,t)=>{const s=String(t.channel??"").trim();if(!s)throw new i("channel required");const n=String(t.number??"").trim();if(!/^\d+$/.test(n))throw new i(`number "${n}" is not a positive integer`);const a=S(n,"number");await r.goto(b);const o=`
1
+ import{cli as c,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as i}from"@jackwener/opencli/errors";import{authHeadersFragment as d,channelResolveFragment as l}from"./in-page.js";import{dispatchEvaluateResult as h}from"./errors.js";import{SLOCK_SITE as p,SLOCK_DOMAIN as k,SLOCK_HOME_URL as b,SLOCK_API_BASE as S}from"./shared.js";import{parsePositiveInteger as g}from"./resolve.js";c({site:p,name:"task-get",access:"read",description:"Fetch a task by channel + taskNumber (GET /tasks/channel/:channelId/number/:taskNumber).",domain:k,strategy:m.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"channel",positional:!0,required:!0,help:"channelId UUID or #name"},{name:"number",positional:!0,required:!0,help:'taskNumber (per-channel integer, as shown in "task #N")'},{name:"server",help:"Override active server"}],columns:["id","taskNumber","title","taskStatus","assigneeId"],func:async(s,t)=>{const a=String(t.channel??"").trim();if(!a)throw new i("channel required");const n=String(t.number??"").trim();if(!/^\d+$/.test(n))throw new i(`number "${n}" is not a positive integer`);const r=g(n,"number");await s.goto(b);const o=`
2
2
  ${d({serverScoped:!0,serverIdOverride:t.server})}
3
- ${h(s)}
4
- const res = await fetch('${g}/tasks/channel/' + encodeURIComponent(channelId) + '/number/' + encodeURIComponent(${JSON.stringify(String(a))}), { credentials:'include', headers });
5
- if (res.status === 404) return { kind: 'http', status: 404, where: '/tasks/channel/:id/number/:n (task #' + ${JSON.stringify(a)} + ' not found in channel)' };
3
+ ${l(a)}
4
+ const res = await fetch('${S}/tasks/channel/' + encodeURIComponent(channelId) + '/number/' + encodeURIComponent(${JSON.stringify(String(r))}), { credentials:'include', headers });
5
+ if (res.status === 404) return { kind: 'http', status: 404, where: '/tasks/channel/:id/number/:n (task #' + ${JSON.stringify(r)} + ' not found in channel)' };
6
6
  if (!res.ok) return { kind: res.status===401?'auth':'http', status: res.status, where:'/tasks/channel/:id/number/:n' };
7
7
  const data = await res.json().catch(() => ({}));
8
8
  // Single object or {task: ...} wrapped — accept either.
9
9
  const task = data && data.task ? data.task : data;
10
10
  return { kind: 'ok', rows: [task] };
11
- `,u=await r.evaluate(`(async () => { ${o} })()`);return l(u).map((e)=>({id:e.id??"",taskNumber:e.taskNumber??a,title:e.content??e.title??"",taskStatus:e.taskStatus??e.status??"",assigneeId:e.claimedById??e.assigneeId??null}))}});
11
+ `,u=await s.evaluate(`(async () => { ${o} })()`);return h(u).map((e)=>({id:e.id??"",taskNumber:e.taskNumber??r,title:e.content??e.title??"",taskStatus:e.taskStatus??e.status??"",assigneeId:e.claimedById??e.assigneeId??null}))}});
@@ -1,12 +1,12 @@
1
- import{cli as u,Strategy as c}from"@jackwener/opencli/registry";import{ArgumentError as d,CommandExecutionError as l}from"@jackwener/opencli/errors";import{authHeadersFragment as m}from"./in-page.js";import{dispatchEvaluateResult as h}from"./errors.js";import{SLOCK_SITE as p,SLOCK_DOMAIN as v,SLOCK_HOME_URL as k,SLOCK_API_BASE as f}from"./shared.js";const a=["todo","in_progress","in_review","done","closed"];u({site:p,name:"task-list-server",access:"read",description:"List tasks across all channels in the active server (GET /tasks/server). Optional --status filter.",domain:v,strategy:c.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"status",help:`Filter by status: ${a.join("|")}`},{name:"server",help:"Override active server"}],columns:["id","taskNumber","title","taskStatus","channelId","assigneeId"],func:async(n,e)=>{const t=e.status?String(e.status).trim():"";if(t&&!a.includes(t))throw new d(`status "${t}" not in {${a.join("|")}}`);await n.goto(k);const i=`
1
+ import{cli as u,Strategy as d}from"@jackwener/opencli/registry";import{ArgumentError as c,CommandExecutionError as l}from"@jackwener/opencli/errors";import{authHeadersFragment as m}from"./in-page.js";import{dispatchEvaluateResult as p}from"./errors.js";import{SLOCK_SITE as v,SLOCK_DOMAIN as f,SLOCK_HOME_URL as h,SLOCK_API_BASE as k}from"./shared.js";const a=["todo","in_progress","in_review","done","closed"];u({site:v,name:"task-list-server",access:"read",description:"List tasks across all channels in the active server (GET /tasks/server). Optional --status filter.",domain:f,strategy:d.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"status",help:`Filter by status: ${a.join("|")}`},{name:"server",help:"Override active server"}],columns:["id","taskNumber","title","taskStatus","channelId","assigneeId"],func:async(n,e)=>{const s=e.status?String(e.status).trim():"";if(s&&!a.includes(s))throw new c(`status "${s}" not in {${a.join("|")}}`);await n.goto(h);const i=`
2
2
  ${m({serverScoped:!0,serverIdOverride:e.server})}
3
- const status = ${JSON.stringify(t)};
3
+ const status = ${JSON.stringify(s)};
4
4
  const qs = status ? ('?status=' + encodeURIComponent(status)) : '';
5
- const res = await fetch('${f}/tasks/server' + qs, { credentials:'include', headers });
5
+ const res = await fetch('${k}/tasks/server' + qs, { credentials:'include', headers });
6
6
  if (!res.ok) return { kind: res.status===401?'auth':'http', status: res.status, where: '/tasks/server' };
7
7
  const data = await res.json();
8
8
  if (!data || !Array.isArray(data.tasks)) {
9
9
  return { kind: 'http', status: 200, where: '/tasks/server (expected {tasks:[]}, got drift)' };
10
10
  }
11
11
  return { kind: 'ok', rows: data.tasks };
12
- `,o=await n.evaluate(`(async () => { ${i} })()`),r=h(o);if(!Array.isArray(r))throw new l(`expected array of rows from server, got ${typeof r} (contract drift?)`);return r.map((s)=>({id:s.id??"",taskNumber:s.taskNumber??null,title:s.content??s.title??"",taskStatus:s.taskStatus??s.status??"",channelId:s.channelId??null,assigneeId:s.claimedById??s.assigneeId??null}))}});
12
+ `,o=await n.evaluate(`(async () => { ${i} })()`),r=p(o);if(!Array.isArray(r))throw new l(`expected array of rows from server, got ${typeof r} (contract drift?)`);return r.map((t)=>({id:t.id??"",taskNumber:t.taskNumber??null,title:t.content??t.title??"",taskStatus:t.taskStatus??t.status??"",channelId:t.channelId??null,assigneeId:t.claimedById??t.assigneeId??null}))}});
@@ -1,9 +1,9 @@
1
- import{cli as u,Strategy as l}from"@jackwener/opencli/registry";import{ArgumentError as o,CommandExecutionError as h}from"@jackwener/opencli/errors";import{authHeadersFragment as m,channelResolveFragment as p}from"./in-page.js";import{dispatchEvaluateResult as k}from"./errors.js";import{SLOCK_SITE as f,SLOCK_DOMAIN as S,SLOCK_HOME_URL as v,SLOCK_API_BASE as w}from"./shared.js";const r=["todo","in_progress","in_review","done","closed"];u({site:f,name:"task-list",access:"read",description:"List tasks (chat tasks = messages with task fields) attached to a channel. Optional --status filter.",domain:S,strategy:l.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"channel",positional:!0,required:!0,help:"channelId UUID or #name"},{name:"status",help:`Filter by status: ${r.join("|")}`},{name:"server",help:"Override active server"}],columns:["id","taskNumber","title","taskStatus","assigneeId"],func:async(n,s)=>{const i=String(s.channel??"").trim();if(!i)throw new o("channel required");const e=s.status?String(s.status).trim():"";if(e&&!r.includes(e))throw new o(`status "${e}" not in {${r.join("|")}}`);await n.goto(v);const d=`
2
- ${m({serverScoped:!0,serverIdOverride:s.server})}
1
+ import{cli as u,Strategy as l}from"@jackwener/opencli/registry";import{ArgumentError as o,CommandExecutionError as m}from"@jackwener/opencli/errors";import{authHeadersFragment as h,channelResolveFragment as p}from"./in-page.js";import{dispatchEvaluateResult as f}from"./errors.js";import{SLOCK_SITE as S,SLOCK_DOMAIN as k,SLOCK_HOME_URL as w,SLOCK_API_BASE as g}from"./shared.js";const r=["todo","in_progress","in_review","done","closed"];u({site:S,name:"task-list",access:"read",description:"List tasks (chat tasks = messages with task fields) attached to a channel. Optional --status filter.",domain:k,strategy:l.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"channel",positional:!0,required:!0,help:"channelId UUID or #name"},{name:"status",help:`Filter by status: ${r.join("|")}`},{name:"server",help:"Override active server"}],columns:["id","taskNumber","title","taskStatus","assigneeId"],func:async(n,e)=>{const i=String(e.channel??"").trim();if(!i)throw new o("channel required");const s=e.status?String(e.status).trim():"";if(s&&!r.includes(s))throw new o(`status "${s}" not in {${r.join("|")}}`);await n.goto(w);const c=`
2
+ ${h({serverScoped:!0,serverIdOverride:e.server})}
3
3
  ${p(i)}
4
- const status = ${JSON.stringify(e)};
4
+ const status = ${JSON.stringify(s)};
5
5
  const qs = status ? ('?status=' + encodeURIComponent(status)) : '';
6
- const tres = await fetch('${w}/tasks/channel/' + encodeURIComponent(channelId) + qs, { credentials:'include', headers });
6
+ const tres = await fetch('${g}/tasks/channel/' + encodeURIComponent(channelId) + qs, { credentials:'include', headers });
7
7
  if (!tres.ok) return { kind: tres.status===401?'auth':'http', status: tres.status, where: '/tasks/channel/:id' };
8
8
  const data = await tres.json();
9
9
  // Server contract: { tasks: [...] }. Reject anything else as drift.
@@ -11,4 +11,4 @@ import{cli as u,Strategy as l}from"@jackwener/opencli/registry";import{ArgumentE
11
11
  return { kind: 'http', status: 200, where: '/tasks/channel/:id (expected {tasks:[]}, got drift)' };
12
12
  }
13
13
  return { kind: 'ok', rows: data.tasks };
14
- `,c=await n.evaluate(`(async () => { ${d} })()`),a=k(c);if(!Array.isArray(a))throw new h(`expected array of rows from server, got ${typeof a} (contract drift?)`);return a.map((t)=>({id:t.id??"",taskNumber:t.taskNumber??null,title:t.content??t.title??"",taskStatus:t.taskStatus??t.status??"",assigneeId:t.claimedById??t.assigneeId??null}))}});
14
+ `,d=await n.evaluate(`(async () => { ${c} })()`),a=f(d);if(!Array.isArray(a))throw new m(`expected array of rows from server, got ${typeof a} (contract drift?)`);return a.map((t)=>({id:t.id??"",taskNumber:t.taskNumber??null,title:t.content??t.title??"",taskStatus:t.taskStatus??t.status??"",assigneeId:t.claimedById??t.assigneeId??null}))}});
@@ -1,6 +1,6 @@
1
- import{cli as c,Strategy as l}from"@jackwener/opencli/registry";import{ArgumentError as d,CommandExecutionError as i}from"@jackwener/opencli/errors";import{authHeadersFragment as h}from"./in-page.js";import{dispatchEvaluateResult as m}from"./errors.js";import{SLOCK_SITE as f,SLOCK_DOMAIN as S,SLOCK_HOME_URL as p,SLOCK_API_BASE as w}from"./shared.js";import{assertMessageIdShape as I}from"./resolve.js";const o=["todo","in_progress","in_review","done","closed"];c({site:f,name:"task-status",access:"write",description:`Set a task's status (PATCH /tasks/:taskId/status, body {status}). One of ${o.join("|")}.`,domain:S,strategy:l.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"taskId",positional:!0,required:!0,help:"Full task UUID (= message id; short ids rejected)"},{name:"status",positional:!0,required:!0,help:`One of: ${o.join("|")}`},{name:"server",help:"Override active server"}],columns:["taskId","taskStatus","assigneeId","taskNumber"],func:async(e,s)=>{let a;try{a=I(String(s.taskId??""))}catch(n){throw new d(n.message)}const t=String(s.status??"").trim();if(!o.includes(t))throw new d(`status "${t}" not in {${o.join("|")}} — pre-network reject (saves a 400 round-trip).`);await e.goto(p);const r=`
2
- ${h({serverScoped:!0,serverIdOverride:s.server})}
3
- const res = await fetch('${w}/tasks/' + encodeURIComponent(${JSON.stringify(a)}) + '/status', {
1
+ import{cli as c,Strategy as h}from"@jackwener/opencli/registry";import{ArgumentError as d,CommandExecutionError as i}from"@jackwener/opencli/errors";import{authHeadersFragment as l}from"./in-page.js";import{dispatchEvaluateResult as m}from"./errors.js";import{SLOCK_SITE as f,SLOCK_DOMAIN as w,SLOCK_HOME_URL as S,SLOCK_API_BASE as p}from"./shared.js";import{assertMessageIdShape as I}from"./resolve.js";const o=["todo","in_progress","in_review","done","closed"];c({site:f,name:"task-status",access:"write",description:`Set a task's status (PATCH /tasks/:taskId/status, body {status}). One of ${o.join("|")}.`,domain:w,strategy:h.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"taskId",positional:!0,required:!0,help:"Full task UUID (= message id; short ids rejected)"},{name:"status",positional:!0,required:!0,help:`One of: ${o.join("|")}`},{name:"server",help:"Override active server"}],columns:["taskId","taskStatus","assigneeId","taskNumber"],func:async(e,s)=>{let a;try{a=I(String(s.taskId??""))}catch(n){throw new d(n.message)}const t=String(s.status??"").trim();if(!o.includes(t))throw new d(`status "${t}" not in {${o.join("|")}} — pre-network reject (saves a 400 round-trip).`);await e.goto(S);const r=`
2
+ ${l({serverScoped:!0,serverIdOverride:s.server})}
3
+ const res = await fetch('${p}/tasks/' + encodeURIComponent(${JSON.stringify(a)}) + '/status', {
4
4
  method:'PATCH', credentials:'include', headers,
5
5
  body: JSON.stringify({ status: ${JSON.stringify(t)} }),
6
6
  });
@@ -1,6 +1,6 @@
1
- import{cli as o,Strategy as u}from"@jackwener/opencli/registry";import{ArgumentError as d,CommandExecutionError as n}from"@jackwener/opencli/errors";import{authHeadersFragment as c}from"./in-page.js";import{dispatchEvaluateResult as l}from"./errors.js";import{SLOCK_SITE as m,SLOCK_DOMAIN as k,SLOCK_HOME_URL as h,SLOCK_API_BASE as p}from"./shared.js";import{assertMessageIdShape as f}from"./resolve.js";o({site:m,name:"task-unclaim",access:"write",description:"Release ownership of a chat task (PATCH /tasks/:id/unclaim).",domain:k,strategy:u.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"taskId",positional:!0,required:!0,help:"Full task UUID (= message id; short ids rejected)"},{name:"server",help:"Override active server"}],columns:["taskId","taskStatus","assigneeId","taskNumber"],func:async(r,s)=>{let e;try{e=f(String(s.taskId??""))}catch(t){throw new d(t.message)}await r.goto(h);const a=`
1
+ import{cli as o,Strategy as u}from"@jackwener/opencli/registry";import{ArgumentError as d,CommandExecutionError as i}from"@jackwener/opencli/errors";import{authHeadersFragment as c}from"./in-page.js";import{dispatchEvaluateResult as m}from"./errors.js";import{SLOCK_SITE as l,SLOCK_DOMAIN as k,SLOCK_HOME_URL as h,SLOCK_API_BASE as f}from"./shared.js";import{assertMessageIdShape as p}from"./resolve.js";o({site:l,name:"task-unclaim",access:"write",description:"Release ownership of a chat task (PATCH /tasks/:id/unclaim).",domain:k,strategy:u.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"taskId",positional:!0,required:!0,help:"Full task UUID (= message id; short ids rejected)"},{name:"server",help:"Override active server"}],columns:["taskId","taskStatus","assigneeId","taskNumber"],func:async(r,s)=>{let e;try{e=p(String(s.taskId??""))}catch(t){throw new d(t.message)}await r.goto(h);const a=`
2
2
  ${c({serverScoped:!0,serverIdOverride:s.server})}
3
- const res = await fetch('${p}/tasks/' + encodeURIComponent(${JSON.stringify(e)}) + '/unclaim', { method:'PATCH', credentials:'include', headers });
3
+ const res = await fetch('${f}/tasks/' + encodeURIComponent(${JSON.stringify(e)}) + '/unclaim', { method:'PATCH', credentials:'include', headers });
4
4
  if (res.status === 404) return { kind: 'http', status: 404, where: '/tasks/:id/unclaim (task not found)' };
5
5
  if (res.status === 403) return { kind: 'http', status: 403, where: '/tasks/:id/unclaim (forbidden — not the assignee, terminal status, or channel archived)' };
6
6
  // F6 — actionable hint for the most common reason this 409s (task already
@@ -10,4 +10,4 @@ import{cli as o,Strategy as u}from"@jackwener/opencli/registry";import{ArgumentE
10
10
  const data = await res.json().catch(() => ({}));
11
11
  const t = (data && data.task) ? data.task : data;
12
12
  return { kind: 'ok', rows: [t] };
13
- `,i=await r.evaluate(`(async () => { ${a} })()`);return l(i).map((t)=>({taskId:w(t,e,"task-unclaim"),taskStatus:t.taskStatus??t.status??"",assigneeId:t.claimedById??t.assigneeId??null,taskNumber:t.taskNumber??null}))}});function w(r,s,e){const a=r?.id;if(!a)throw new n(`Slock ${e} succeeded without returning task id ${s}; refusing to report a task row.`);if(a!==s)throw new n(`Slock ${e} returned task id ${a}, expected ${s}.`);return a}
13
+ `,n=await r.evaluate(`(async () => { ${a} })()`);return m(n).map((t)=>({taskId:w(t,e,"task-unclaim"),taskStatus:t.taskStatus??t.status??"",assigneeId:t.claimedById??t.assigneeId??null,taskNumber:t.taskNumber??null}))}});function w(r,s,e){const a=r?.id;if(!a)throw new i(`Slock ${e} succeeded without returning task id ${s}; refusing to report a task row.`);if(a!==s)throw new i(`Slock ${e} returned task id ${a}, expected ${s}.`);return a}
@@ -1 +1 @@
1
- import{cli as W,Strategy as X}from"@jackwener/opencli/registry";import{ArgumentError as Y,CommandExecutionError as Z}from"@jackwener/opencli/errors";import{buildFetchSnippet as $}from"./in-page.js";import{dispatchEvaluateResult as b}from"./errors.js";import{SLOCK_SITE as f,SLOCK_DOMAIN as x,SLOCK_HOME_URL as D}from"./shared.js";import{assertMessageIdShape as F}from"./resolve.js";W({site:f,name:"thread-follow",access:"write",description:"Follow the thread on a parent message (POST /channels/threads/follow)",domain:x,strategy:X.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"parentMessageId",positional:!0,required:!0,help:"Full parent messageId UUID (short ids rejected)"},{name:"server",help:"Override active server"}],columns:["parentMessageId","threadChannelId","result"],func:async(B,G)=>{let q;try{q=F(String(G.parentMessageId??""))}catch(V){throw new Y(V.message)}await B.goto(D);const P=$({method:"POST",path:"/channels/threads/follow",body:{parentMessageId:q},serverScoped:!0,serverIdOverride:G.server}),Q=await B.evaluate(`(async () => { ${P} })()`),z=b(Q),J=z?.threadChannelId??z?.channelId??z?.id;if(!J)throw new Z(`Slock thread-follow succeeded without returning a thread channel id for parent message ${q}.`);return[{parentMessageId:q,threadChannelId:J,result:"followed"}]}});
1
+ import{cli as i,Strategy as l}from"@jackwener/opencli/registry";import{ArgumentError as h,CommandExecutionError as c}from"@jackwener/opencli/errors";import{buildFetchSnippet as p}from"./in-page.js";import{dispatchEvaluateResult as m}from"./errors.js";import{SLOCK_SITE as u,SLOCK_DOMAIN as I,SLOCK_HOME_URL as g}from"./shared.js";import{assertMessageIdShape as f}from"./resolve.js";i({site:u,name:"thread-follow",access:"write",description:"Follow the thread on a parent message (POST /channels/threads/follow)",domain:I,strategy:l.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"parentMessageId",positional:!0,required:!0,help:"Full parent messageId UUID (short ids rejected)"},{name:"server",help:"Override active server"}],columns:["parentMessageId","threadChannelId","result"],func:async(t,a)=>{let e;try{e=f(String(a.parentMessageId??""))}catch(d){throw new h(d.message)}await t.goto(g);const o=p({method:"POST",path:"/channels/threads/follow",body:{parentMessageId:e},serverScoped:!0,serverIdOverride:a.server}),n=await t.evaluate(`(async () => { ${o} })()`),r=m(n),s=r?.threadChannelId??r?.channelId??r?.id;if(!s)throw new c(`Slock thread-follow succeeded without returning a thread channel id for parent message ${e}.`);return[{parentMessageId:e,threadChannelId:s,result:"followed"}]}});
@@ -1 +1 @@
1
- import{cli as W,Strategy as X}from"@jackwener/opencli/registry";import{ArgumentError as Y}from"@jackwener/opencli/errors";import{buildFetchSnippet as Z}from"./in-page.js";import{dispatchEvaluateResult as $}from"./errors.js";import{SLOCK_SITE as F,SLOCK_DOMAIN as H,SLOCK_HOME_URL as N}from"./shared.js";import{UUID_RE as T}from"./resolve.js";export function makeThreadStateCommand({name:B,verb:G,resultLabel:J,description:P}){W({site:F,name:B,access:"write",description:P,domain:H,strategy:X.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"threadChannelId",positional:!0,required:!0,help:"Thread channel UUID (from thread-list / message-read)"},{name:"server",help:"Override active server"}],columns:["threadChannelId","result"],func:async(x,z)=>{const q=String(z.threadChannelId??"").trim();if(!T.test(q))throw new Y(`threadChannelId must be a full UUID (got "${q}"). Get it from thread-list or message-read's threadChannelId column.`);await x.goto(N);const Q=Z({method:"POST",path:`/channels/threads/${G}`,body:{threadChannelId:q},serverScoped:!0,serverIdOverride:z.server}),V=await x.evaluate(`(async () => { ${Q} })()`);$(V);return[{threadChannelId:q,result:J}]}})}
1
+ import{cli as h,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as l}from"@jackwener/opencli/errors";import{buildFetchSnippet as u}from"./in-page.js";import{dispatchEvaluateResult as c}from"./errors.js";import{SLOCK_SITE as p,SLOCK_DOMAIN as I,SLOCK_HOME_URL as f}from"./shared.js";import{UUID_RE as C}from"./resolve.js";export function makeThreadStateCommand({name:a,verb:n,resultLabel:s,description:o}){h({site:p,name:a,access:"write",description:o,domain:I,strategy:m.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"threadChannelId",positional:!0,required:!0,help:"Thread channel UUID (from thread-list / message-read)"},{name:"server",help:"Override active server"}],columns:["threadChannelId","result"],func:async(r,t)=>{const e=String(t.threadChannelId??"").trim();if(!C.test(e))throw new l(`threadChannelId must be a full UUID (got "${e}"). Get it from thread-list or message-read's threadChannelId column.`);await r.goto(f);const d=u({method:"POST",path:`/channels/threads/${n}`,body:{threadChannelId:e},serverScoped:!0,serverIdOverride:t.server}),i=await r.evaluate(`(async () => { ${d} })()`);c(i);return[{threadChannelId:e,result:s}]}})}
@@ -1,10 +1,10 @@
1
- import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{CommandExecutionError as Z}from"@jackwener/opencli/errors";import{authHeadersFragment as $}from"./in-page.js";import{dispatchEvaluateResult as b}from"./errors.js";import{SLOCK_SITE as f,SLOCK_DOMAIN as q,SLOCK_HOME_URL as x,SLOCK_API_BASE as Q}from"./shared.js";X({site:f,name:"unread-summary",access:"read",description:"Global unread counts across every server you belong to.",domain:q,strategy:Y.COOKIE,browser:!0,siteSession:"persistent",args:[],columns:["serverId","slug","name","unreadCount"],func:async(J)=>{await J.goto(x);const V=`
2
- ${$({serverScoped:!1})}
3
- const sres = await fetch('${Q}/servers/', { credentials:'include', headers });
1
+ import{cli as n,Strategy as u}from"@jackwener/opencli/registry";import{CommandExecutionError as o}from"@jackwener/opencli/errors";import{authHeadersFragment as i}from"./in-page.js";import{dispatchEvaluateResult as d}from"./errors.js";import{SLOCK_SITE as m,SLOCK_DOMAIN as c,SLOCK_HOME_URL as y,SLOCK_API_BASE as e}from"./shared.js";n({site:m,name:"unread-summary",access:"read",description:"Global unread counts across every server you belong to.",domain:c,strategy:u.COOKIE,browser:!0,siteSession:"persistent",args:[],columns:["serverId","slug","name","unreadCount"],func:async(s)=>{await s.goto(y);const t=`
2
+ ${i({serverScoped:!1})}
3
+ const sres = await fetch('${e}/servers/', { credentials:'include', headers });
4
4
  if (sres.status === 401) return { kind: 'auth', detail: '/servers/ returned 401' };
5
5
  if (!sres.ok) return { kind: 'http', status: sres.status, where:'/servers/' };
6
6
  const servers = await sres.json();
7
- const ures = await fetch('${Q}/servers/unread-summary', { credentials:'include', headers });
7
+ const ures = await fetch('${e}/servers/unread-summary', { credentials:'include', headers });
8
8
  if (ures.status === 401) return { kind: 'auth', detail: '/servers/unread-summary returned 401' };
9
9
  if (!ures.ok) return { kind: 'http', status: ures.status, where:'/servers/unread-summary' };
10
10
  const summary = await ures.json();
@@ -15,4 +15,4 @@ import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{CommandEx
15
15
  return { serverId: u.serverId, slug: s.slug || '', name: s.name || '', unreadCount: u.unreadCount || 0 };
16
16
  });
17
17
  return { kind: 'ok', rows };
18
- `,W=await J.evaluate(`(async () => { ${V} })()`),z=b(W);if(!Array.isArray(z))throw new Z(`expected array of summary rows, got ${typeof z} (contract drift?)`);return z}});
18
+ `,a=await s.evaluate(`(async () => { ${t} })()`),r=d(a);if(!Array.isArray(r))throw new o(`expected array of summary rows, got ${typeof r} (contract drift?)`);return r}});
@@ -1 +1 @@
1
- import{registerSiteAuthCommands as e}from"../_shared/site-auth.js";import{SLOCK_SITE as o,SLOCK_DOMAIN as r,SLOCK_HOME_URL as m}from"./shared.js";import{verifySlockSession as s}from"./auth-verify.js";e({site:o,domain:r,loginUrl:m,verify:(i)=>s(i),columns:["id","name","email"]});
1
+ import{registerSiteAuthCommands as m}from"../_shared/site-auth.js";import{SLOCK_SITE as o,SLOCK_DOMAIN as r,SLOCK_HOME_URL as e}from"./shared.js";import{verifySlockSession as t}from"./auth-verify.js";m({site:o,domain:r,loginUrl:e,verify:(i)=>t(i),columns:["id","name","email"]});
@@ -1,6 +1,6 @@
1
- import{cli as O,Strategy as P}from"@jackwener/opencli/registry";import{ArgumentError as D,CommandExecutionError as Q}from"@jackwener/opencli/errors";function F(f){if(f&&!Array.isArray(f)&&typeof f==="object"&&"session"in f&&"data"in f)return f.data;return f}function G(f){const B=F(f);if(!Array.isArray(B))throw new Q("Unexpected SMZDM search extraction payload shape; expected an array of rows.");return B}function H(f){let B;if(f==null)B=20;else if(typeof f==="number")B=f;else if(typeof f==="string"&&/^[0-9]+$/.test(f))B=Number(f);else B=NaN;if(!Number.isFinite(B)||!Number.isInteger(B))throw new D(`--limit must be an integer between 1 and 100, got ${JSON.stringify(f)}`);if(B<1||B>100)throw new D(`--limit must be between 1 and 100, got ${B}`);return B}function I(f){return`
1
+ import{cli as c,Strategy as a}from"@jackwener/opencli/registry";import{ArgumentError as r,CommandExecutionError as m}from"@jackwener/opencli/errors";function n(t){if(t&&!Array.isArray(t)&&typeof t==="object"&&"session"in t&&"data"in t)return t.data;return t}function o(t){const e=n(t);if(!Array.isArray(e))throw new m("Unexpected SMZDM search extraction payload shape; expected an array of rows.");return e}function i(t){let e;if(t==null)e=20;else if(typeof t==="number")e=t;else if(typeof t==="string"&&/^[0-9]+$/.test(t))e=Number(t);else e=NaN;if(!Number.isFinite(e)||!Number.isInteger(e))throw new r(`--limit must be an integer between 1 and 100, got ${JSON.stringify(t)}`);if(e<1||e>100)throw new r(`--limit must be between 1 and 100, got ${e}`);return e}function l(t){return`
2
2
  (() => {
3
- const limit = ${f};
3
+ const limit = ${t};
4
4
  const items = document.querySelectorAll('li.feed-row-wide');
5
5
  const results = [];
6
6
  const normalizeCount = (text) => {
@@ -68,4 +68,4 @@ import{cli as O,Strategy as P}from"@jackwener/opencli/registry";import{ArgumentE
68
68
  });
69
69
  return results;
70
70
  })()
71
- `}export const smzdmSearchCommand=O({site:"smzdm",name:"search",access:"read",description:"什么值得买搜索好价",domain:"www.smzdm.com",strategy:P.COOKIE,args:[{name:"query",required:!0,positional:!0,help:"Search keyword"},{name:"limit",type:"int",default:20,help:"Number of results"}],columns:["rank","title","price","mall","updated_at","zhi_count","buzhi_count","favorite_count","comments","url"],func:async(f,B)=>{const K=encodeURIComponent(B.query),M=H(B.limit);await f.goto(`https://search.smzdm.com/?c=home&s=${K}&v=b`);return G(await f.evaluate(I(M)))}}),__test__={buildSmzdmSearchJs:I,parseLimit:H,requireSearchRows:G,unwrapEvaluateResult:F};
71
+ `}export const smzdmSearchCommand=c({site:"smzdm",name:"search",access:"read",description:"什么值得买搜索好价",domain:"www.smzdm.com",strategy:a.COOKIE,args:[{name:"query",required:!0,positional:!0,help:"Search keyword"},{name:"limit",type:"int",default:20,help:"Number of results"}],columns:["rank","title","price","mall","updated_at","zhi_count","buzhi_count","favorite_count","comments","url"],func:async(t,e)=>{const s=encodeURIComponent(e.query),u=i(e.limit);await t.goto(`https://search.smzdm.com/?c=home&s=${s}&v=b`);return o(await t.evaluate(l(u)))}}),__test__={buildSmzdmSearchJs:l,parseLimit:i,requireSearchRows:o,unwrapEvaluateResult:n};
@@ -1 +1 @@
1
- import{CliError as $,CommandExecutionError as N}from"@jackwener/opencli/errors";import{cli as b,Strategy as f}from"@jackwener/opencli/registry";import{publishArticle as P,gotoWritePage as R}from"../_shared/article/publish.js";import{SOHU_MPBP_HEADERS_JS as k}from"./mpbp.js";function m(){const Q="0123456789abcdef";let K="";for(let z=0;z<32;z++)K+=Q[Math.floor(Math.random()*Q.length)];return K}export const sohuProfile={home:"https://mp.sohu.com/mpfe/v3/main/first/page?newsType=1",outputFormat:"html",preprocessConfig:{},checkAuth:async(Q)=>{try{const z=await(await fetch("https://mp.sohu.com/mpbp/bp/account/list?_="+Date.now(),{method:"GET",credentials:"include"})).json();if(z.code!==2000000||!z.data?.data?.length)return{isAuthenticated:!1};const L=[];for(const V of z.data.data)if(V.accounts)L.push(...V.accounts);if(!L.length)return{isAuthenticated:!1};const G=L[0],X=L.length>1?G.nickName+"(共"+L.length+"个子账号)":G.nickName;return{isAuthenticated:!0,userId:String(G.id),username:X,avatar:G.avatar||""}}catch(K){return{isAuthenticated:!1,error:String(K&&K.message||K)}}},image:{skip:["sohu.com"],uploadFn:async(Q,K)=>{const L=await(await fetch("https://mp.sohu.com/mpbp/bp/account/list?_="+Date.now(),{method:"GET",credentials:"include"})).json();if(L.code!==2000000||!L.data?.data?.length)throw Error("获取搜狐账号信息失败,请确认已登录搜狐号");const G=[];for(const H of L.data.data)if(H.accounts)G.push(...H.accounts);if(!G.length)throw Error("搜狐号子账号列表为空");const X=String(G[0].id),V=await fetch(Q,{credentials:"omit"});if(!V.ok)throw Error("图片下载失败("+V.status+"):"+Q);const Y=await V.blob(),F=new FormData;F.append("file",Y,"image.jpg");F.append("accountId",X);const W=await(await fetch("https://mp.sohu.com/commons/front/outerUpload/image/file?accountId="+X,{method:"POST",credentials:"include",body:F})).json();if(!W.url)throw Error("搜狐图片上传失败:"+(W.msg||JSON.stringify(W).slice(0,100)));return{url:W.url}}},publish:async(Q,K)=>{const z=Q.params||{},L=await fetch("https://mp.sohu.com/mpbp/bp/account/list?_="+Date.now(),{method:"GET",credentials:"include"}),G=await L.json();if(G.code!==2000000||!G.data?.data?.length)return{ok:!1,stage:"auth",status:L.status,message:"获取搜狐账号信息失败,请确认已登录搜狐号"};const X=[];for(const M of G.data.data)if(M.accounts)X.push(...M.accounts);if(!X.length)return{ok:!1,stage:"auth",status:0,message:"搜狐号子账号列表为空"};const V=Number(X[0].id),Y="0123456789abcdef";let F="";for(let M=0;M<32;M++)F+=Y[Math.floor(Math.random()*Y.length)];const B="100-"+Date.now()+"-"+F,W=Number(z.channelId);if(!Number.isFinite(W)||W<=0)return{ok:!1,stage:"params",status:0,message:"缺少合法 channelId(频道 id),请先用 `sohu channels` 取值"};const H=z.categoryId==null||z.categoryId===""?-1:Number(z.categoryId),_={title:Q.title,brief:typeof z.brief==="string"?z.brief:"",content:Q.content,channelId:W,categoryId:H,id:0,userColumnId:z.userColumnId==null||z.userColumnId==-1?0:Number(z.userColumnId),columnNewsIds:Array.isArray(z.columnNewsIds)?z.columnNewsIds:[],businessCode:0,declareOriginal:Boolean(z.declareOriginal),cover:typeof z.cover==="string"?z.cover:"",topicIds:Array.isArray(z.topicIds)?z.topicIds:[],isAd:0,userLabels:"[]",reprint:!1,customTags:typeof z.customTags==="string"?z.customTags:"",infoResource:0,sourceUrl:"",visibleToLoginedUsers:0,attrIds:Array.isArray(z.attrIds)?z.attrIds:[],accountId:V};if(Q.draftOnly){const M=Object.assign({},_,{auto:!0}),q=await fetch("https://mp.sohu.com/mpbp/bp/news/v4/news/draft/v2?accountId="+V,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json","X-Requested-With":"XMLHttpRequest","dv-id":F,"sp-cm":B},body:JSON.stringify(M)}),A=await q.text();let J=null;try{J=JSON.parse(A)}catch(p){}if(!q.ok||!J||!J.success)return{ok:!1,stage:"draft",status:q.status,message:J&&J.msg||A.slice(0,300)};const y=String(J.data),v="https://mp.sohu.com/mpfe/v4/contentManagement/news/addarticle?spm=smmp.articlelist.0.0&contentStatus=2&id="+y;return{ok:!0,id:y,url:v,draft:!0}}const U=await fetch("https://mp.sohu.com/mpbp/bp/news/v4/news/publish/v2?accountId="+V,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json","X-Requested-With":"XMLHttpRequest","dv-id":F,"sp-cm":B},body:JSON.stringify(_)}),x=await U.text();let Z=null;try{Z=JSON.parse(x)}catch(M){}if(!U.ok||!Z||Z.code!==2000000){let M=Z&&(Z.msg||Z.message)||"";if(!M){const q=[];if(H!==-1)q.push("--category");if(Array.isArray(z.topicIds)&&z.topicIds.length>0)q.push("--topics");if(_.cover)q.push("--cover");M="搜狐发布接口返回非 JSON 错误页(HTTP "+U.status+")。"+(q.length?"实测该 500 多由可选参数触发——去掉 "+q.join(" / ")+"、只保留必填 --channel 重试即可。":"稍后重试;若持续失败,用 `sohu stats` 确认是否已产生重复内容。")}return{ok:!1,stage:"publish",status:U.status,message:M}}if(Z.data!=null&&Object.prototype.toString.call(Z.data)==="[object Object]")return{ok:!1,stage:"origin_check",status:U.status,message:"声明原创触发了原创校验(需在搜狐后台完成原创确认):"+JSON.stringify(Z.data).slice(0,200)};const D=String(Z.data),T="https://mp.sohu.com/mpfe/v4/contentManagement/news/addarticle?spm=smmp.articlelist.0.0&contentStatus=1&id="+D,S="https://www.sohu.com/a/"+D+"_"+V;return{ok:!0,id:D,url:T,publicUrl:S,draft:!1}}},sohuAuthProfile={home:sohuProfile.home,checkAuth:sohuProfile.checkAuth};function j(Q){if(!Q.execute)throw new $("INVALID_INPUT","此命令需要 --execute 才会真正写入。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}async function C(Q){const K=typeof Q.text==="string"?Q.text:void 0,z=typeof Q.file==="string"?Q.file:void 0;if(K&&z)throw new $("INVALID_INPUT","text 和 --file 只能二选一");let L=K??"";if(z){const{readFile:G,stat:X}=await import("node:fs/promises");let V;try{V=await X(z)}catch{throw new $("INVALID_INPUT","文件不存在:"+z)}if(!V.isFile())throw new $("INVALID_INPUT","路径不是可读文本文件:"+z);let Y;try{Y=await G(z)}catch{throw new $("INVALID_INPUT","文件读取失败:"+z)}try{L=new TextDecoder("utf-8",{fatal:!0}).decode(Y)}catch{throw new $("INVALID_INPUT","文件不是合法 UTF-8 编码:"+z)}}if(!L.trim())throw new $("INVALID_INPUT","正文不能为空");return L}function E(Q,K,z,L,G={}){return[{status:"success",outcome:L,message:Q,target_type:K,target:z,...G}]}async function O(Q,K,z){const L="(async () => {try {"+k+"const r = await fetch("+JSON.stringify(K)+', { method: "GET", credentials: "include", headers: HDRS });const t = await r.text();let j = null; try { j = JSON.parse(t); } catch (e) {}return { ok: r.ok, status: r.status, json: j, text: t.slice(0, 300) };} catch (e) { return { ok: false, status: 0, json: null, text: String((e && e.message) || e) }; }})()',G=await Q.evaluate(L);if(!G||!G.ok||!G.json)throw new $("INVALID_INPUT","搜狐"+z+"接口请求失败(HTTP "+(G?G.status:"?")+"):"+(G?G.text:""));if(G.json.success===!1||G.json.code!=null&&G.json.code!==2000000&&G.json.code!==2000)throw new $("INVALID_INPUT","搜狐"+z+"接口返回错误:"+(G.json.msg||G.json.message||"未登录或无权限"));return G.json}async function h(Q){const K=await O(Q,"https://mp.sohu.com/mpbp/bp/account/list?_="+Date.now(),"账号列表"),z=K.data&&K.data.data||[],L=[];for(const G of z)if(G.accounts)L.push(...G.accounts);if(!L.length)throw new $("INVALID_INPUT","搜狐号子账号列表为空,请确认已登录搜狐号");return String(L[0].id)}async function w(Q,K,z){const L=await O(Q,"https://mp.sohu.com/mpbp/bp/account/common/channels-data-api?status=1&accountId="+encodeURIComponent(K),"频道列举"),G=Array.isArray(L)?L:L.data||[],X=G.find((V)=>String(V.name)===String(z));if(!X)throw new $("INVALID_INPUT","未找到频道「"+z+"」,可选:"+(G.map((V)=>V.name).join(" / ")||"(空)")+"。用 `sohu channels` 查看完整列表。");return Number(X.id!=null?X.id:X.channelId)}async function I(Q,K,z,L){const G=await O(Q,"https://mp.sohu.com/mpbp/bp/account/common/channels/"+z+"/categories?accountId="+encodeURIComponent(K),"分类列举"),X=Array.isArray(G)?G:G.data||[],V=X.find((Y)=>String(Y.name)===String(L));if(!V)throw new $("INVALID_INPUT","频道(id="+z+")下未找到分类「"+L+"」,可选:"+(X.map((Y)=>Y.name).join(" / ")||"(该频道无分类)")+"。用 `sohu categories --channel <频道名>` 查看。");return Number(V.id)}async function d(Q,K,z){const L=await O(Q,"https://mp.sohu.com/mpbp/bp/account/column/v2/list?accountId="+encodeURIComponent(K)+"&page=1&size=100","专栏列举"),G=Array.isArray(L)?L:L.data&&(L.data.data||L.data)||L.data||[],X=Array.isArray(G)?G:[],V=X.find((Y)=>String(Y.name)===String(z));if(!V)throw new $("INVALID_INPUT","未找到专栏「"+z+"」,可选:"+(X.map((Y)=>Y.name).join(" / ")||"(你还没有任何专栏)")+"。用 `sohu columns` 查看。");return Number(V.id)}async function i(Q,K,z){const L=z.split(",").map((X)=>X.trim()).filter(Boolean);if(!L.length)return[];const G=[];for(const X of L){const V=await O(Q,"https://mp.sohu.com/mpbp/bp/news/v4/label/topic/search?accountId="+K+"&keyword="+encodeURIComponent(X),"话题搜索"),F=(Array.isArray(V)?V:V.data||[]).find((B)=>String(B.name)===String(X));if(!F)throw new $("INVALID_INPUT","未找到话题「"+X+"」,请用 `sohu topics --keyword "+X+"` 搜索确认确切名称。");G.push(F.id)}return G}b({site:"sohu",name:"article",access:"write",description:"发布文章到搜狐号(HTML 格式,外链图片自动转存到搜狐图床)。默认正式发布,加 --draft 仅存草稿。频道必填,合法值用 `sohu channels` 取。",domain:"mp.sohu.com",strategy:f.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题"},{name:"text",positional:!0,help:"文章正文(默认 Markdown,传 --html 则视为 HTML)"},{name:"file",help:"正文文件路径(UTF-8,Markdown 或 HTML)"},{name:"html",type:"boolean",help:"将正文视为原始 HTML 而非 Markdown"},{name:"channel",help:"频道名(精确匹配,必填),合法值用 `sohu channels` 列举"},{name:"category",help:"分类名(精确匹配,依赖所选频道),合法值用 `sohu categories --channel <频道名>` 列举;不传=不限"},{name:"column",help:"专栏名(精确匹配),合法值用 `sohu columns` 列举;不传=不归属专栏"},{name:"topics",help:"话题名,逗号分隔(每个精确匹配),用 `sohu topics` 搜索取确切名"},{name:"cover",help:"封面图 URL(须为搜狐图床地址);可空"},{name:"brief",help:"文章摘要;可空"},{name:"declare-original",type:"boolean",help:"声明原创(会触发搜狐原创校验,发布将被拦到原创确认流程)"},{name:"draft",type:"boolean",help:"仅保存草稿,不正式发布"},{name:"execute",type:"boolean",help:"实际执行写入操作;不加此参数则拒绝写入(干跑保护)"}],columns:["status","outcome","message","target_type","target","created_target","created_url","public_url"],func:async(Q,K)=>{if(!Q)throw new N("搜狐号文章发布需要浏览器会话");j(K);const z=String(K.title??"").trim();if(!z)throw new $("INVALID_INPUT","文章标题不能为空");const L=await C(K),G=Boolean(K.draft),X=typeof K.channel==="string"?K.channel.trim():"";if(!X)throw new $("INVALID_INPUT","缺少 --channel(频道名)。请先运行 `sohu channels` 取合法频道名再传入,不提供默认值。");await R(Q,sohuProfile.home);const V=await h(Q),Y=await w(Q,V,X);let F=-1;const B=typeof K.category==="string"?K.category.trim():"";if(B)F=await I(Q,V,Y,B);let W=0;const H=typeof K.column==="string"?K.column.trim():"";if(H)W=await d(Q,V,H);let _=[];const U=typeof K.topics==="string"?K.topics.trim():"";if(U)_=await i(Q,V,U);const x={channelId:Y,categoryId:F,userColumnId:W,topicIds:_,cover:typeof K.cover==="string"?K.cover.trim():"",brief:typeof K.brief==="string"?K.brief:"",declareOriginal:Boolean(K["declare-original"])},Z=await P(Q,{title:z,body:L,format:K.html?"html":"markdown",draftOnly:G,profile:sohuProfile,publishParams:x}),D=Z.images.uploaded.length|0,T=Z.images.failed.length|0;let S=Z.draft?"已保存搜狐号草稿":"已正式发布到搜狐号";if(D||T)S+=`;图片:${D} 张已转存${T?`,${T} 张失败`:""}`;return E(S,"article","",Z.draft?"draft":"created",{created_target:(Z.draft?"draft:":"article:")+Z.id,created_url:Z.url,public_url:Z.publicUrl||""})}});export const __test__={sohuProfile,requireExecute:j,buildResultRow:E,resolvePayload:C,generateDeviceId:m};
1
+ import{CliError as u,CommandExecutionError as R}from"@jackwener/opencli/errors";import{cli as D,Strategy as L}from"@jackwener/opencli/registry";import{publishArticle as O,gotoWritePage as x}from"../_shared/article/publish.js";import{SOHU_MPBP_HEADERS_JS as C}from"./mpbp.js";function M(){const s="0123456789abcdef";let n="";for(let t=0;t<32;t++)n+=s[Math.floor(Math.random()*s.length)];return n}export const sohuProfile={home:"https://mp.sohu.com/mpfe/v3/main/first/page?newsType=1",outputFormat:"html",preprocessConfig:{},checkAuth:async(s)=>{try{const t=await(await fetch("https://mp.sohu.com/mpbp/bp/account/list?_="+Date.now(),{method:"GET",credentials:"include"})).json();if(t.code!==2000000||!t.data?.data?.length)return{isAuthenticated:!1};const o=[];for(const a of t.data.data)if(a.accounts)o.push(...a.accounts);if(!o.length)return{isAuthenticated:!1};const e=o[0],c=o.length>1?e.nickName+"(共"+o.length+"个子账号)":e.nickName;return{isAuthenticated:!0,userId:String(e.id),username:c,avatar:e.avatar||""}}catch(n){return{isAuthenticated:!1,error:String(n&&n.message||n)}}},image:{skip:["sohu.com"],uploadFn:async(s,n)=>{const o=await(await fetch("https://mp.sohu.com/mpbp/bp/account/list?_="+Date.now(),{method:"GET",credentials:"include"})).json();if(o.code!==2000000||!o.data?.data?.length)throw Error("获取搜狐账号信息失败,请确认已登录搜狐号");const e=[];for(const f of o.data.data)if(f.accounts)e.push(...f.accounts);if(!e.length)throw Error("搜狐号子账号列表为空");const c=String(e[0].id),a=await fetch(s,{credentials:"omit"});if(!a.ok)throw Error("图片下载失败("+a.status+"):"+s);const r=await a.blob(),l=new FormData;l.append("file",r,"image.jpg");l.append("accountId",c);const p=await(await fetch("https://mp.sohu.com/commons/front/outerUpload/image/file?accountId="+c,{method:"POST",credentials:"include",body:l})).json();if(!p.url)throw Error("搜狐图片上传失败:"+(p.msg||JSON.stringify(p).slice(0,100)));return{url:p.url}}},publish:async(s,n)=>{const t=s.params||{},o=await fetch("https://mp.sohu.com/mpbp/bp/account/list?_="+Date.now(),{method:"GET",credentials:"include"}),e=await o.json();if(e.code!==2000000||!e.data?.data?.length)return{ok:!1,stage:"auth",status:o.status,message:"获取搜狐账号信息失败,请确认已登录搜狐号"};const c=[];for(const d of e.data.data)if(d.accounts)c.push(...d.accounts);if(!c.length)return{ok:!1,stage:"auth",status:0,message:"搜狐号子账号列表为空"};const a=Number(c[0].id),r="0123456789abcdef";let l="";for(let d=0;d<32;d++)l+=r[Math.floor(Math.random()*r.length)];const m="100-"+Date.now()+"-"+l,p=Number(t.channelId);if(!Number.isFinite(p)||p<=0)return{ok:!1,stage:"params",status:0,message:"缺少合法 channelId(频道 id),请先用 `sohu channels` 取值"};const f=t.categoryId==null||t.categoryId===""?-1:Number(t.categoryId),g={title:s.title,brief:typeof t.brief==="string"?t.brief:"",content:s.content,channelId:p,categoryId:f,id:0,userColumnId:t.userColumnId==null||t.userColumnId==-1?0:Number(t.userColumnId),columnNewsIds:Array.isArray(t.columnNewsIds)?t.columnNewsIds:[],businessCode:0,declareOriginal:Boolean(t.declareOriginal),cover:typeof t.cover==="string"?t.cover:"",topicIds:Array.isArray(t.topicIds)?t.topicIds:[],isAd:0,userLabels:"[]",reprint:!1,customTags:typeof t.customTags==="string"?t.customTags:"",infoResource:0,sourceUrl:"",visibleToLoginedUsers:0,attrIds:Array.isArray(t.attrIds)?t.attrIds:[],accountId:a};if(s.draftOnly){const d=Object.assign({},g,{auto:!0}),h=await fetch("https://mp.sohu.com/mpbp/bp/news/v4/news/draft/v2?accountId="+a,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json","X-Requested-With":"XMLHttpRequest","dv-id":l,"sp-cm":m},body:JSON.stringify(d)}),S=await h.text();let y=null;try{y=JSON.parse(S)}catch(F){}if(!h.ok||!y||!y.success)return{ok:!1,stage:"draft",status:h.status,message:y&&y.msg||S.slice(0,300)};const _=String(y.data),U="https://mp.sohu.com/mpfe/v4/contentManagement/news/addarticle?spm=smmp.articlelist.0.0&contentStatus=2&id="+_;return{ok:!0,id:_,url:U,draft:!0}}const I=await fetch("https://mp.sohu.com/mpbp/bp/news/v4/news/publish/v2?accountId="+a,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json","X-Requested-With":"XMLHttpRequest","dv-id":l,"sp-cm":m},body:JSON.stringify(g)}),T=await I.text();let i=null;try{i=JSON.parse(T)}catch(d){}if(!I.ok||!i||i.code!==2000000){let d=i&&(i.msg||i.message)||"";if(!d){const h=[];if(f!==-1)h.push("--category");if(Array.isArray(t.topicIds)&&t.topicIds.length>0)h.push("--topics");if(g.cover)h.push("--cover");d="搜狐发布接口返回非 JSON 错误页(HTTP "+I.status+")。"+(h.length?"实测该 500 多由可选参数触发——去掉 "+h.join(" / ")+"、只保留必填 --channel 重试即可。":"稍后重试;若持续失败,用 `sohu stats` 确认是否已产生重复内容。")}return{ok:!1,stage:"publish",status:I.status,message:d}}if(i.data!=null&&Object.prototype.toString.call(i.data)==="[object Object]")return{ok:!1,stage:"origin_check",status:I.status,message:"声明原创触发了原创校验(需在搜狐后台完成原创确认):"+JSON.stringify(i.data).slice(0,200)};const w=String(i.data),b="https://mp.sohu.com/mpfe/v4/contentManagement/news/addarticle?spm=smmp.articlelist.0.0&contentStatus=1&id="+w,A="https://www.sohu.com/a/"+w+"_"+a;return{ok:!0,id:w,url:b,publicUrl:A,draft:!1}}},sohuAuthProfile={home:sohuProfile.home,checkAuth:sohuProfile.checkAuth};function v(s){if(!s.execute)throw new u("INVALID_INPUT","此命令需要 --execute 才会真正写入。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}async function P(s){const n=typeof s.text==="string"?s.text:void 0,t=typeof s.file==="string"?s.file:void 0;if(n&&t)throw new u("INVALID_INPUT","text 和 --file 只能二选一");let o=n??"";if(t){const{readFile:e,stat:c}=await import("node:fs/promises");let a;try{a=await c(t)}catch{throw new u("INVALID_INPUT","文件不存在:"+t)}if(!a.isFile())throw new u("INVALID_INPUT","路径不是可读文本文件:"+t);let r;try{r=await e(t)}catch{throw new u("INVALID_INPUT","文件读取失败:"+t)}try{o=new TextDecoder("utf-8",{fatal:!0}).decode(r)}catch{throw new u("INVALID_INPUT","文件不是合法 UTF-8 编码:"+t)}}if(!o.trim())throw new u("INVALID_INPUT","正文不能为空");return o}function j(s,n,t,o,e={}){return[{status:"success",outcome:o,message:s,target_type:n,target:t,...e}]}async function N(s,n,t){const o="(async () => {try {"+C+"const r = await fetch("+JSON.stringify(n)+', { method: "GET", credentials: "include", headers: HDRS });const t = await r.text();let j = null; try { j = JSON.parse(t); } catch (e) {}return { ok: r.ok, status: r.status, json: j, text: t.slice(0, 300) };} catch (e) { return { ok: false, status: 0, json: null, text: String((e && e.message) || e) }; }})()',e=await s.evaluate(o);if(!e||!e.ok||!e.json)throw new u("INVALID_INPUT","搜狐"+t+"接口请求失败(HTTP "+(e?e.status:"?")+"):"+(e?e.text:""));if(e.json.success===!1||e.json.code!=null&&e.json.code!==2000000&&e.json.code!==2000)throw new u("INVALID_INPUT","搜狐"+t+"接口返回错误:"+(e.json.msg||e.json.message||"未登录或无权限"));return e.json}async function V(s){const n=await N(s,"https://mp.sohu.com/mpbp/bp/account/list?_="+Date.now(),"账号列表"),t=n.data&&n.data.data||[],o=[];for(const e of t)if(e.accounts)o.push(...e.accounts);if(!o.length)throw new u("INVALID_INPUT","搜狐号子账号列表为空,请确认已登录搜狐号");return String(o[0].id)}async function E(s,n,t){const o=await N(s,"https://mp.sohu.com/mpbp/bp/account/common/channels-data-api?status=1&accountId="+encodeURIComponent(n),"频道列举"),e=Array.isArray(o)?o:o.data||[],c=e.find((a)=>String(a.name)===String(t));if(!c)throw new u("INVALID_INPUT","未找到频道「"+t+"」,可选:"+(e.map((a)=>a.name).join(" / ")||"(空)")+"。用 `sohu channels` 查看完整列表。");return Number(c.id!=null?c.id:c.channelId)}async function H(s,n,t,o){const e=await N(s,"https://mp.sohu.com/mpbp/bp/account/common/channels/"+t+"/categories?accountId="+encodeURIComponent(n),"分类列举"),c=Array.isArray(e)?e:e.data||[],a=c.find((r)=>String(r.name)===String(o));if(!a)throw new u("INVALID_INPUT","频道(id="+t+")下未找到分类「"+o+"」,可选:"+(c.map((r)=>r.name).join(" / ")||"(该频道无分类)")+"。用 `sohu categories --channel <频道名>` 查看。");return Number(a.id)}async function J(s,n,t){const o=await N(s,"https://mp.sohu.com/mpbp/bp/account/column/v2/list?accountId="+encodeURIComponent(n)+"&page=1&size=100","专栏列举"),e=Array.isArray(o)?o:o.data&&(o.data.data||o.data)||o.data||[],c=Array.isArray(e)?e:[],a=c.find((r)=>String(r.name)===String(t));if(!a)throw new u("INVALID_INPUT","未找到专栏「"+t+"」,可选:"+(c.map((r)=>r.name).join(" / ")||"(你还没有任何专栏)")+"。用 `sohu columns` 查看。");return Number(a.id)}async function k(s,n,t){const o=t.split(",").map((c)=>c.trim()).filter(Boolean);if(!o.length)return[];const e=[];for(const c of o){const a=await N(s,"https://mp.sohu.com/mpbp/bp/news/v4/label/topic/search?accountId="+n+"&keyword="+encodeURIComponent(c),"话题搜索"),l=(Array.isArray(a)?a:a.data||[]).find((m)=>String(m.name)===String(c));if(!l)throw new u("INVALID_INPUT","未找到话题「"+c+"」,请用 `sohu topics --keyword "+c+"` 搜索确认确切名称。");e.push(l.id)}return e}D({site:"sohu",name:"article",access:"write",description:"发布文章到搜狐号(HTML 格式,外链图片自动转存到搜狐图床)。默认正式发布,加 --draft 仅存草稿。频道必填,合法值用 `sohu channels` 取。",domain:"mp.sohu.com",strategy:L.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题"},{name:"text",positional:!0,help:"文章正文(默认 Markdown,传 --html 则视为 HTML)"},{name:"file",help:"正文文件路径(UTF-8,Markdown 或 HTML)"},{name:"html",type:"boolean",help:"将正文视为原始 HTML 而非 Markdown"},{name:"channel",help:"频道名(精确匹配,必填),合法值用 `sohu channels` 列举"},{name:"category",help:"分类名(精确匹配,依赖所选频道),合法值用 `sohu categories --channel <频道名>` 列举;不传=不限"},{name:"column",help:"专栏名(精确匹配),合法值用 `sohu columns` 列举;不传=不归属专栏"},{name:"topics",help:"话题名,逗号分隔(每个精确匹配),用 `sohu topics` 搜索取确切名"},{name:"cover",help:"封面图 URL(须为搜狐图床地址);可空"},{name:"brief",help:"文章摘要;可空"},{name:"declare-original",type:"boolean",help:"声明原创(会触发搜狐原创校验,发布将被拦到原创确认流程)"},{name:"draft",type:"boolean",help:"仅保存草稿,不正式发布"},{name:"execute",type:"boolean",help:"实际执行写入操作;不加此参数则拒绝写入(干跑保护)"}],columns:["status","outcome","message","target_type","target","created_target","created_url","public_url"],func:async(s,n)=>{if(!s)throw new R("搜狐号文章发布需要浏览器会话");v(n);const t=String(n.title??"").trim();if(!t)throw new u("INVALID_INPUT","文章标题不能为空");const o=await P(n),e=Boolean(n.draft),c=typeof n.channel==="string"?n.channel.trim():"";if(!c)throw new u("INVALID_INPUT","缺少 --channel(频道名)。请先运行 `sohu channels` 取合法频道名再传入,不提供默认值。");await x(s,sohuProfile.home);const a=await V(s),r=await E(s,a,c);let l=-1;const m=typeof n.category==="string"?n.category.trim():"";if(m)l=await H(s,a,r,m);let p=0;const f=typeof n.column==="string"?n.column.trim():"";if(f)p=await J(s,a,f);let g=[];const I=typeof n.topics==="string"?n.topics.trim():"";if(I)g=await k(s,a,I);const T={channelId:r,categoryId:l,userColumnId:p,topicIds:g,cover:typeof n.cover==="string"?n.cover.trim():"",brief:typeof n.brief==="string"?n.brief:"",declareOriginal:Boolean(n["declare-original"])},i=await O(s,{title:t,body:o,format:n.html?"html":"markdown",draftOnly:e,profile:sohuProfile,publishParams:T}),w=i.images.uploaded.length|0,b=i.images.failed.length|0;let A=i.draft?"已保存搜狐号草稿":"已正式发布到搜狐号";if(w||b)A+=`;图片:${w} 张已转存${b?`,${b} 张失败`:""}`;return j(A,"article","",i.draft?"draft":"created",{created_target:(i.draft?"draft:":"article:")+i.id,created_url:i.url,public_url:i.publicUrl||""})}});export const __test__={sohuProfile,requireExecute:v,buildResultRow:j,resolvePayload:P,generateDeviceId:M};
@@ -1 +1 @@
1
- import{cli as z,Strategy as A}from"@jackwener/opencli/registry";import{CommandExecutionError as B}from"@jackwener/opencli/errors";import{gotoWritePage as D}from"../_shared/article/publish.js";import{sohuProfile as F}from"./article.js";z({site:"sohu",name:"attributes",access:"read",description:"列出搜狐号文章属性候选(id + 名称),供发布时选择文章属性。",domain:"mp.sohu.com",strategy:A.COOKIE,browser:!0,columns:["attr_id","attr_name"],func:async(q)=>{if(!q)throw new B("搜狐号文章属性列举需要浏览器会话");await D(q,F.home);const v=await q.evaluate("(async () => {const r = await fetch('https://mp.sohu.com/mpbp/bp/news/v4/news/attribute', { method: 'GET', credentials: 'include' });const j = await r.json();"+"if (!j || j.success === false) throw new Error('文章属性列举失败:' + ((j && j.msg) || '未登录或无权限'));"+"const raw = (j && j.data) || [];const list = Array.isArray(raw) ? raw : (Array.isArray(raw.data) ? raw.data : []);return list.map(a => ({ attr_id: String(a.id), attr_name: a.name || a.attrName || '' }));})()");return Array.isArray(v)?v:[]}});
1
+ import{cli as a,Strategy as o}from"@jackwener/opencli/registry";import{CommandExecutionError as s}from"@jackwener/opencli/errors";import{gotoWritePage as e}from"../_shared/article/publish.js";import{sohuProfile as i}from"./article.js";a({site:"sohu",name:"attributes",access:"read",description:"列出搜狐号文章属性候选(id + 名称),供发布时选择文章属性。",domain:"mp.sohu.com",strategy:o.COOKIE,browser:!0,columns:["attr_id","attr_name"],func:async(r)=>{if(!r)throw new s("搜狐号文章属性列举需要浏览器会话");await e(r,i.home);const t=await r.evaluate("(async () => {const r = await fetch('https://mp.sohu.com/mpbp/bp/news/v4/news/attribute', { method: 'GET', credentials: 'include' });const j = await r.json();"+"if (!j || j.success === false) throw new Error('文章属性列举失败:' + ((j && j.msg) || '未登录或无权限'));"+"const raw = (j && j.data) || [];const list = Array.isArray(raw) ? raw : (Array.isArray(raw.data) ? raw.data : []);return list.map(a => ({ attr_id: String(a.id), attr_name: a.name || a.attrName || '' }));})()");return Array.isArray(t)?t:[]}});