publishport-opencli 1.0.20 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1041) hide show
  1. package/clis/12306/me.js +2 -2
  2. package/clis/12306/orders.js +3 -3
  3. package/clis/12306/passengers.js +3 -3
  4. package/clis/12306/price.js +1 -1
  5. package/clis/12306/stations.js +1 -1
  6. package/clis/12306/train.js +1 -1
  7. package/clis/12306/trains.js +1 -1
  8. package/clis/12306/utils.js +1 -1
  9. package/clis/1688/download.js +1 -1
  10. package/clis/1688/item.js +4 -4
  11. package/clis/1688/search.js +4 -4
  12. package/clis/1688/store.js +4 -4
  13. package/clis/1point3acres/forum.js +1 -1
  14. package/clis/1point3acres/forums.js +1 -1
  15. package/clis/1point3acres/notifications.js +1 -1
  16. package/clis/1point3acres/search.js +1 -1
  17. package/clis/1point3acres/thread.js +2 -2
  18. package/clis/1point3acres/user.js +1 -1
  19. package/clis/1point3acres/utils.js +2 -2
  20. package/clis/36kr/article.js +2 -2
  21. package/clis/36kr/hot.js +2 -2
  22. package/clis/36kr/news.js +1 -1
  23. package/clis/36kr/search.js +2 -2
  24. package/clis/51job/company.js +2 -2
  25. package/clis/51job/detail.js +2 -2
  26. package/clis/51job/hot.js +1 -1
  27. package/clis/51job/search.js +1 -1
  28. package/clis/51job/utils.js +7 -7
  29. package/clis/_atlassian/shared.js +9 -9
  30. package/clis/_shared/article/auth.js +4 -4
  31. package/clis/_shared/article/douban-md2draft.js +4 -4
  32. package/clis/_shared/article/format.js +1 -1
  33. package/clis/_shared/article/images.js +7 -7
  34. package/clis/_shared/article/login.js +1 -1
  35. package/clis/_shared/article/publish.js +11 -11
  36. package/clis/_shared/common.js +1 -1
  37. package/clis/_shared/content-guard.js +1 -1
  38. package/clis/_shared/desktop-commands.js +1 -1
  39. package/clis/_shared/file-inject.js +12 -12
  40. package/clis/_shared/self-hosted-sites.js +2 -2
  41. package/clis/_shared/site-auth.js +1 -1
  42. package/clis/_shared/token-auth.js +2 -2
  43. package/clis/_shared/video-publish.js +9 -9
  44. package/clis/amazon/offer.js +3 -3
  45. package/clis/amazon/product.js +5 -5
  46. package/clis/amazon/shared.js +6 -6
  47. package/clis/antigravity/_actions.js +13 -13
  48. package/clis/antigravity/audit-extras.js +10 -10
  49. package/clis/antigravity/delete.js +1 -1
  50. package/clis/antigravity/model.js +6 -6
  51. package/clis/antigravity/new.js +2 -2
  52. package/clis/antigravity/read.js +2 -2
  53. package/clis/antigravity/rename.js +1 -1
  54. package/clis/antigravity/send.js +3 -3
  55. package/clis/antigravity/serve.js +17 -17
  56. package/clis/antigravity/storage.js +6 -6
  57. package/clis/antigravity/watch.js +2 -2
  58. package/clis/apple-podcasts/episodes.js +1 -1
  59. package/clis/apple-podcasts/top.js +1 -1
  60. package/clis/apple-podcasts/utils.js +1 -1
  61. package/clis/archive/item.js +1 -1
  62. package/clis/archive/search.js +1 -1
  63. package/clis/archive/snapshots.js +1 -1
  64. package/clis/archive/wayback.js +1 -1
  65. package/clis/arxiv/author.js +1 -1
  66. package/clis/arxiv/utils.js +1 -1
  67. package/clis/autohome/brand.js +1 -1
  68. package/clis/autohome/score.js +1 -1
  69. package/clis/autohome/utils.js +1 -1
  70. package/clis/baijiahao/article.js +1 -1
  71. package/clis/baijiahao/lists.js +1 -1
  72. package/clis/baijiahao/login.js +1 -1
  73. package/clis/baijiahao/publish.js +9 -9
  74. package/clis/baijiahao/stats.js +1 -1
  75. package/clis/baijiahao/whoami.js +1 -1
  76. package/clis/band/bands.js +2 -2
  77. package/clis/band/mentions.js +2 -2
  78. package/clis/band/post.js +4 -4
  79. package/clis/band/posts.js +3 -3
  80. package/clis/barchart/flow.js +3 -3
  81. package/clis/barchart/greeks.js +2 -2
  82. package/clis/barchart/quote.js +3 -3
  83. package/clis/bbc/news.js +1 -1
  84. package/clis/bbc/topic.js +1 -1
  85. package/clis/bbc/utils.js +1 -1
  86. package/clis/bilibili/article.js +1 -1
  87. package/clis/bilibili/categories.js +1 -1
  88. package/clis/bilibili/coin.js +1 -1
  89. package/clis/bilibili/comment-del.js +1 -1
  90. package/clis/bilibili/comment-like.js +1 -1
  91. package/clis/bilibili/comment.js +1 -1
  92. package/clis/bilibili/comments.js +1 -1
  93. package/clis/bilibili/dm-list.js +1 -1
  94. package/clis/bilibili/dm-read.js +1 -1
  95. package/clis/bilibili/dm-send.js +1 -1
  96. package/clis/bilibili/download.js +2 -2
  97. package/clis/bilibili/drafts.js +1 -1
  98. package/clis/bilibili/dynamic-post.js +3 -3
  99. package/clis/bilibili/favorite-add.js +1 -1
  100. package/clis/bilibili/favorite.js +1 -1
  101. package/clis/bilibili/feed.js +2 -2
  102. package/clis/bilibili/follow.js +1 -1
  103. package/clis/bilibili/following.js +1 -1
  104. package/clis/bilibili/like.js +1 -1
  105. package/clis/bilibili/partitions.js +1 -1
  106. package/clis/bilibili/stats.js +1 -1
  107. package/clis/bilibili/subtitle.js +3 -3
  108. package/clis/bilibili/summary.js +1 -1
  109. package/clis/bilibili/topics.js +1 -1
  110. package/clis/bilibili/unfollow.js +1 -1
  111. package/clis/bilibili/upload.js +1 -1
  112. package/clis/bilibili/utils.js +10 -10
  113. package/clis/bilibili/video-drafts.js +1 -1
  114. package/clis/bilibili/video.js +1 -1
  115. package/clis/bloomberg/businessweek.js +4 -4
  116. package/clis/bloomberg/news.js +2 -2
  117. package/clis/bloomberg/utils.js +13 -13
  118. package/clis/bluesky/post.js +1 -1
  119. package/clis/bluesky/shared.js +11 -11
  120. package/clis/bluesky/whoami.js +1 -1
  121. package/clis/booking/search.js +2 -2
  122. package/clis/boss/accept.js +1 -1
  123. package/clis/boss/applied.js +1 -1
  124. package/clis/boss/auth.js +1 -1
  125. package/clis/boss/batchgreet.js +1 -1
  126. package/clis/boss/bossinfo.js +1 -1
  127. package/clis/boss/chatlist.js +1 -1
  128. package/clis/boss/chatmsg.js +1 -1
  129. package/clis/boss/cities.js +1 -1
  130. package/clis/boss/detail.js +1 -1
  131. package/clis/boss/exchange.js +1 -1
  132. package/clis/boss/greet.js +1 -1
  133. package/clis/boss/interviews.js +1 -1
  134. package/clis/boss/invite.js +1 -1
  135. package/clis/boss/joblist.js +1 -1
  136. package/clis/boss/mark.js +1 -1
  137. package/clis/boss/me.js +2 -2
  138. package/clis/boss/recommend.js +1 -1
  139. package/clis/boss/resumedelete.js +1 -1
  140. package/clis/boss/resumelist.js +1 -1
  141. package/clis/boss/resumeupload.js +11 -11
  142. package/clis/boss/search.js +1 -1
  143. package/clis/boss/send.js +1 -1
  144. package/clis/boss/sendresume.js +1 -1
  145. package/clis/boss/stats.js +1 -1
  146. package/clis/boss/unread.js +1 -1
  147. package/clis/boss/utils.js +13 -13
  148. package/clis/chaoxing/assignments.js +1 -1
  149. package/clis/chaoxing/exams.js +1 -1
  150. package/clis/chaoxing/utils.js +9 -9
  151. package/clis/chatgpt/ask.js +1 -1
  152. package/clis/chatgpt/auth.js +2 -2
  153. package/clis/chatgpt/detail.js +1 -1
  154. package/clis/chatgpt/image.js +1 -1
  155. package/clis/chatgpt/read.js +1 -1
  156. package/clis/chatgpt/send.js +1 -1
  157. package/clis/chatgpt/utils.js +59 -59
  158. package/clis/chatgpt-app/ask.js +1 -1
  159. package/clis/chatgpt-app/send.js +1 -1
  160. package/clis/chatwise/model.js +6 -6
  161. package/clis/chess/analyze.js +1 -1
  162. package/clis/chess/game.js +1 -1
  163. package/clis/chess/games.js +1 -1
  164. package/clis/chess/stats.js +1 -1
  165. package/clis/chess/utils.js +1 -1
  166. package/clis/claude/ask.js +2 -2
  167. package/clis/claude/detail.js +1 -1
  168. package/clis/claude/new.js +1 -1
  169. package/clis/claude/read.js +1 -1
  170. package/clis/claude/send.js +1 -1
  171. package/clis/claude/utils.js +23 -23
  172. package/clis/cnblogs/article.js +1 -1
  173. package/clis/cnblogs/login.js +1 -1
  174. package/clis/cnblogs/stats.js +7 -7
  175. package/clis/cnblogs/whoami.js +1 -1
  176. package/clis/codex/_actions.js +3 -3
  177. package/clis/codex/archive.js +1 -1
  178. package/clis/codex/ask.js +6 -6
  179. package/clis/codex/model.js +8 -8
  180. package/clis/codex/pin.js +1 -1
  181. package/clis/codex/rename.js +4 -4
  182. package/clis/codex/send.js +3 -3
  183. package/clis/codex/sidebar.js +1 -1
  184. package/clis/coingecko/categories.js +1 -1
  185. package/clis/coingecko/coin.js +1 -1
  186. package/clis/coingecko/derivatives.js +1 -1
  187. package/clis/coingecko/exchanges.js +1 -1
  188. package/clis/coingecko/global.js +1 -1
  189. package/clis/coingecko/trending.js +1 -1
  190. package/clis/confluence/search.js +1 -1
  191. package/clis/coupang/product.js +3 -3
  192. package/clis/coupang/utils.js +1 -1
  193. package/clis/crates/crate.js +1 -1
  194. package/clis/crates/search.js +1 -1
  195. package/clis/crates/utils.js +1 -1
  196. package/clis/csdn/article.js +13 -13
  197. package/clis/csdn/columns.js +1 -1
  198. package/clis/csdn/login.js +1 -1
  199. package/clis/csdn/stats.js +4 -4
  200. package/clis/csdn/whoami.js +1 -1
  201. package/clis/cto51/article.js +1 -1
  202. package/clis/cto51/whoami.js +1 -1
  203. package/clis/ctrip/flight.js +2 -2
  204. package/clis/ctrip/hotel-search.js +3 -3
  205. package/clis/ctrip/hotel-suggest.js +1 -1
  206. package/clis/ctrip/search.js +1 -1
  207. package/clis/ctrip/utils.js +6 -6
  208. package/clis/cursor/ask.js +5 -5
  209. package/clis/cursor/composer.js +2 -2
  210. package/clis/cursor/model.js +4 -4
  211. package/clis/cursor/send.js +2 -2
  212. package/clis/dblp/author.js +1 -1
  213. package/clis/dblp/paper.js +1 -1
  214. package/clis/dblp/search.js +1 -1
  215. package/clis/dblp/utils.js +1 -1
  216. package/clis/dblp/venue.js +1 -1
  217. package/clis/deepseek/ask.js +1 -1
  218. package/clis/deepseek/auth.js +2 -2
  219. package/clis/deepseek/detail.js +1 -1
  220. package/clis/deepseek/new.js +1 -1
  221. package/clis/deepseek/read.js +1 -1
  222. package/clis/deepseek/send.js +7 -7
  223. package/clis/deepseek/utils.js +25 -25
  224. package/clis/defillama/protocol.js +1 -1
  225. package/clis/defillama/protocols.js +1 -1
  226. package/clis/defillama/utils.js +1 -1
  227. package/clis/devto/auth.js +2 -2
  228. package/clis/devto/latest.js +1 -1
  229. package/clis/devto/publish.js +5 -5
  230. package/clis/devto/read.js +2 -2
  231. package/clis/devto/stats.js +3 -3
  232. package/clis/dianping/auth.js +2 -2
  233. package/clis/dianping/cityResolver.js +2 -2
  234. package/clis/dianping/search.js +1 -1
  235. package/clis/dianping/shop.js +1 -1
  236. package/clis/dianping/utils.js +1 -1
  237. package/clis/discord-app/delete.js +3 -3
  238. package/clis/discord-app/read.js +1 -1
  239. package/clis/discord-app/thread-read.js +1 -1
  240. package/clis/discord-web/auth.js +2 -2
  241. package/clis/discord-web/send.js +5 -5
  242. package/clis/dockerhub/image.js +1 -1
  243. package/clis/dockerhub/search.js +1 -1
  244. package/clis/dockerhub/utils.js +1 -1
  245. package/clis/dongchedi/koubei.js +1 -1
  246. package/clis/dongchedi/models.js +1 -1
  247. package/clis/dongchedi/score.js +1 -1
  248. package/clis/dongchedi/search.js +1 -1
  249. package/clis/dongchedi/series.js +1 -1
  250. package/clis/dongchedi/specs.js +1 -1
  251. package/clis/dongchedi/utils.js +1 -1
  252. package/clis/douban/article.js +3 -3
  253. package/clis/douban/auth.js +2 -2
  254. package/clis/douban/download.js +1 -1
  255. package/clis/douban/utils.js +23 -23
  256. package/clis/doubao/auth.js +3 -3
  257. package/clis/doubao/utils.js +39 -39
  258. package/clis/doubao-app/ask.js +1 -1
  259. package/clis/doubao-app/utils.js +4 -4
  260. package/clis/douyin/_shared/browser-fetch.js +7 -7
  261. package/clis/douyin/_shared/draft-cache.js +1 -1
  262. package/clis/douyin/_shared/imagex-upload.js +1 -1
  263. package/clis/douyin/_shared/sts2.js +1 -1
  264. package/clis/douyin/_shared/text-extra.js +1 -1
  265. package/clis/douyin/_shared/tos-upload.js +4 -4
  266. package/clis/douyin/_shared/transcode.js +1 -1
  267. package/clis/douyin/_shared/vod-upload.js +4 -4
  268. package/clis/douyin/draft.js +18 -18
  269. package/clis/douyin/drafts.js +1 -1
  270. package/clis/douyin/publish-image.js +12 -12
  271. package/clis/douyin/publish.js +9 -9
  272. package/clis/douyin/search.js +3 -3
  273. package/clis/douyin/videos.js +1 -1
  274. package/clis/eastmoney/_secid.js +1 -1
  275. package/clis/eastmoney/announcement.js +1 -1
  276. package/clis/eastmoney/article.js +1 -1
  277. package/clis/eastmoney/convertible.js +1 -1
  278. package/clis/eastmoney/etf.js +1 -1
  279. package/clis/eastmoney/holders.js +1 -1
  280. package/clis/eastmoney/index-board.js +1 -1
  281. package/clis/eastmoney/kline.js +1 -1
  282. package/clis/eastmoney/kuaixun.js +1 -1
  283. package/clis/eastmoney/longhu.js +1 -1
  284. package/clis/eastmoney/money-flow.js +1 -1
  285. package/clis/eastmoney/northbound.js +1 -1
  286. package/clis/eastmoney/quote.js +1 -1
  287. package/clis/eastmoney/rank.js +1 -1
  288. package/clis/eastmoney/sectors.js +1 -1
  289. package/clis/endoflife/product.js +1 -1
  290. package/clis/endoflife/utils.js +1 -1
  291. package/clis/facebook/comment.js +8 -8
  292. package/clis/facebook/feed.js +4 -4
  293. package/clis/facebook/like.js +5 -5
  294. package/clis/facebook/notifications.js +3 -3
  295. package/clis/facebook/post.js +11 -11
  296. package/clis/facebook/search.js +3 -3
  297. package/clis/flathub/app.js +1 -1
  298. package/clis/flathub/search.js +1 -1
  299. package/clis/flathub/utils.js +1 -1
  300. package/clis/flomo/memos.js +1 -1
  301. package/clis/gemini/deep-research-result.js +4 -4
  302. package/clis/gemini/deep-research.js +1 -1
  303. package/clis/gemini/detail.js +1 -1
  304. package/clis/gemini/history.js +1 -1
  305. package/clis/gemini/image.js +2 -2
  306. package/clis/gemini/status.js +1 -1
  307. package/clis/gemini/utils.js +43 -43
  308. package/clis/geogebra/hexagon.js +1 -1
  309. package/clis/geogebra/info.js +3 -3
  310. package/clis/geogebra/triangle.js +1 -1
  311. package/clis/geogebra/utils.js +11 -11
  312. package/clis/ghost/login.js +1 -1
  313. package/clis/ghost/shared.js +2 -2
  314. package/clis/gitee/auth.js +2 -2
  315. package/clis/github-trending/repos.js +1 -1
  316. package/clis/google/news.js +1 -1
  317. package/clis/google/search.js +2 -2
  318. package/clis/google/suggest.js +1 -1
  319. package/clis/google/trends.js +1 -1
  320. package/clis/google/utils.js +1 -1
  321. package/clis/goproxy/module.js +1 -1
  322. package/clis/goproxy/utils.js +1 -1
  323. package/clis/goproxy/versions.js +1 -1
  324. package/clis/gov-policy/recent.js +2 -2
  325. package/clis/gov-policy/search.js +2 -2
  326. package/clis/grok/ask.js +1 -1
  327. package/clis/grok/detail.js +1 -1
  328. package/clis/grok/image.js +8 -8
  329. package/clis/grok/pin.js +1 -1
  330. package/clis/grok/send.js +1 -1
  331. package/clis/grok/status.js +1 -1
  332. package/clis/grok/utils.js +21 -21
  333. package/clis/guazi/browse.js +1 -1
  334. package/clis/guazi/car.js +1 -1
  335. package/clis/guazi/utils.js +1 -1
  336. package/clis/hackernews/auth.js +2 -2
  337. package/clis/hackernews/comment.js +8 -8
  338. package/clis/hackernews/read.js +7 -7
  339. package/clis/hackernews/submit.js +7 -7
  340. package/clis/hashnode/auth.js +3 -3
  341. package/clis/hashnode/publish.js +14 -14
  342. package/clis/hf/auth.js +2 -2
  343. package/clis/hf/models.js +1 -1
  344. package/clis/hf/paper.js +1 -1
  345. package/clis/hf/spaces.js +1 -1
  346. package/clis/hf/top.js +1 -1
  347. package/clis/homebrew/cask.js +1 -1
  348. package/clis/homebrew/formula.js +1 -1
  349. package/clis/homebrew/popular.js +1 -1
  350. package/clis/homebrew/utils.js +1 -1
  351. package/clis/huodongxing/events.js +1 -1
  352. package/clis/hupu/detail.js +4 -4
  353. package/clis/hupu/hot.js +3 -3
  354. package/clis/hupu/reply.js +1 -1
  355. package/clis/hupu/search.js +1 -1
  356. package/clis/hupu/unlike.js +1 -1
  357. package/clis/hupu/utils.js +10 -10
  358. package/clis/imdb/person.js +2 -2
  359. package/clis/imdb/reviews.js +3 -3
  360. package/clis/imdb/search.js +2 -2
  361. package/clis/imdb/title.js +1 -1
  362. package/clis/imdb/top.js +1 -1
  363. package/clis/imdb/trending.js +1 -1
  364. package/clis/imdb/utils.js +13 -13
  365. package/clis/imooc/article.js +6 -6
  366. package/clis/imooc/login.js +1 -1
  367. package/clis/imooc/whoami.js +1 -1
  368. package/clis/indeed/job.js +2 -2
  369. package/clis/indeed/search.js +2 -2
  370. package/clis/indeed/utils.js +1 -1
  371. package/clis/infoq/article.js +2 -2
  372. package/clis/infoq/login.js +1 -1
  373. package/clis/infoq/whoami.js +1 -1
  374. package/clis/instagram/_shared/private-publish.js +4 -4
  375. package/clis/instagram/_shared/protocol-capture.js +9 -9
  376. package/clis/instagram/detail.js +3 -3
  377. package/clis/instagram/post.js +25 -25
  378. package/clis/instagram/reel.js +18 -18
  379. package/clis/instagram/story.js +4 -4
  380. package/clis/instagram/user.js +2 -2
  381. package/clis/jd/item.js +65 -65
  382. package/clis/jianshu/article.js +1 -1
  383. package/clis/jianshu/login.js +1 -1
  384. package/clis/jianshu/notebooks.js +1 -1
  385. package/clis/jianshu/whoami.js +1 -1
  386. package/clis/jianyu/search.js +6 -6
  387. package/clis/jianyu/shared/procurement-contract.js +1 -1
  388. package/clis/jike/api.js +6 -6
  389. package/clis/jike/auth.js +3 -3
  390. package/clis/jike/comment.js +1 -1
  391. package/clis/jike/create.js +6 -6
  392. package/clis/jike/feed.js +3 -3
  393. package/clis/jike/like.js +1 -1
  394. package/clis/jike/notifications.js +3 -3
  395. package/clis/jike/repost.js +13 -13
  396. package/clis/jike/search.js +3 -3
  397. package/clis/jimeng/auth.js +2 -2
  398. package/clis/jimeng/generate.js +10 -10
  399. package/clis/jira/shared.js +1 -1
  400. package/clis/juejin/article.js +4 -4
  401. package/clis/juejin/categories.js +1 -1
  402. package/clis/juejin/hot.js +1 -1
  403. package/clis/juejin/login.js +1 -1
  404. package/clis/juejin/recommend.js +1 -1
  405. package/clis/juejin/stats.js +3 -3
  406. package/clis/juejin/tags.js +1 -1
  407. package/clis/juejin/utils.js +1 -1
  408. package/clis/juejin/whoami.js +1 -1
  409. package/clis/ke/utils.js +4 -4
  410. package/clis/kimi/_utils.js +7 -7
  411. package/clis/kimi/audit-extras.js +14 -14
  412. package/clis/kimi/auth.js +3 -3
  413. package/clis/kimi/chat.js +15 -15
  414. package/clis/kimi/storage.js +5 -5
  415. package/clis/kimi/ui.js +13 -13
  416. package/clis/kimi/usage.js +3 -3
  417. package/clis/kuaishou/auth.js +1 -1
  418. package/clis/kuaishou/publish.js +6 -6
  419. package/clis/lesswrong/_helpers.js +5 -5
  420. package/clis/lesswrong/comments.js +5 -5
  421. package/clis/lichess/top.js +1 -1
  422. package/clis/lichess/user.js +1 -1
  423. package/clis/lichess/utils.js +1 -1
  424. package/clis/linkedin/comment.js +1 -1
  425. package/clis/linkedin/connect.js +11 -11
  426. package/clis/linkedin/create.js +5 -5
  427. package/clis/linkedin/follow.js +1 -1
  428. package/clis/linkedin/inbox.js +1 -1
  429. package/clis/linkedin/job-detail.js +3 -3
  430. package/clis/linkedin/like.js +1 -1
  431. package/clis/linkedin/notifications.js +1 -1
  432. package/clis/linkedin/people-search.js +1 -1
  433. package/clis/linkedin/post-comments.js +1 -1
  434. package/clis/linkedin/post-detail.js +1 -1
  435. package/clis/linkedin/profile-analytics.js +1 -1
  436. package/clis/linkedin/profile-api.js +13 -13
  437. package/clis/linkedin/profile-experience.js +1 -1
  438. package/clis/linkedin/profile-projects.js +1 -1
  439. package/clis/linkedin/profile-read.js +3 -3
  440. package/clis/linkedin/reply.js +1 -1
  441. package/clis/linkedin/repost.js +1 -1
  442. package/clis/linkedin/safe-send.js +8 -8
  443. package/clis/linkedin/salesnav-inbox.js +5 -5
  444. package/clis/linkedin/salesnav-message.js +3 -3
  445. package/clis/linkedin/salesnav-search.js +4 -4
  446. package/clis/linkedin/salesnav-thread.js +1 -1
  447. package/clis/linkedin/search-api.js +3 -3
  448. package/clis/linkedin/search.js +8 -8
  449. package/clis/linkedin/social-api.js +31 -31
  450. package/clis/linkedin/timeline.js +3 -3
  451. package/clis/linkedin-learning/search.js +2 -2
  452. package/clis/linkedin-learning/trending.js +2 -2
  453. package/clis/linux-do/feed.js +4 -4
  454. package/clis/linux-do/topic-content.js +8 -8
  455. package/clis/lobsters/domain.js +1 -1
  456. package/clis/lobsters/read.js +7 -7
  457. package/clis/maimai/auth.js +2 -2
  458. package/clis/maimai/search-talents.js +4 -4
  459. package/clis/manus/_utils.js +1 -1
  460. package/clis/mastodon/login.js +1 -1
  461. package/clis/mastodon/post.js +1 -1
  462. package/clis/mastodon/shared.js +12 -12
  463. package/clis/mastodon/whoami.js +1 -1
  464. package/clis/maven/artifact.js +1 -1
  465. package/clis/maven/search.js +1 -1
  466. package/clis/maven/utils.js +1 -1
  467. package/clis/mdn/search.js +1 -1
  468. package/clis/medium/article.js +5 -5
  469. package/clis/medium/login.js +1 -1
  470. package/clis/medium/stats.js +3 -3
  471. package/clis/medium/tag.js +1 -1
  472. package/clis/medium/whoami.js +1 -1
  473. package/clis/mubu/notes.js +1 -1
  474. package/clis/mubu/utils.js +15 -15
  475. package/clis/note/auth.js +2 -2
  476. package/clis/note/note-utils.js +2 -2
  477. package/clis/note/publish.js +8 -8
  478. package/clis/notebooklm/add-source.js +8 -8
  479. package/clis/notebooklm/create.js +1 -1
  480. package/clis/notebooklm/generate-slides.js +1 -1
  481. package/clis/notebooklm/notes-get.js +1 -1
  482. package/clis/notebooklm/rpc.js +8 -8
  483. package/clis/notebooklm/source-fulltext.js +1 -1
  484. package/clis/notebooklm/utils.js +10 -10
  485. package/clis/nowcoder/auth.js +2 -2
  486. package/clis/nowcoder/comment.js +1 -1
  487. package/clis/nowcoder/comments.js +1 -1
  488. package/clis/nowcoder/dm-list.js +1 -1
  489. package/clis/nowcoder/dm-read.js +1 -1
  490. package/clis/nowcoder/dm-send.js +1 -1
  491. package/clis/nowcoder/drafts.js +1 -1
  492. package/clis/nowcoder/inbox.js +1 -1
  493. package/clis/nowcoder/like.js +1 -1
  494. package/clis/nowcoder/my.js +1 -1
  495. package/clis/nowcoder/post.js +1 -1
  496. package/clis/nowcoder/utils.js +13 -13
  497. package/clis/npm/downloads.js +1 -1
  498. package/clis/npm/package.js +1 -1
  499. package/clis/npm/search.js +1 -1
  500. package/clis/npm/utils.js +1 -1
  501. package/clis/nuget/package.js +1 -1
  502. package/clis/nuget/search.js +1 -1
  503. package/clis/nuget/utils.js +1 -1
  504. package/clis/nvd/cve.js +1 -1
  505. package/clis/oeis/search.js +1 -1
  506. package/clis/oeis/sequence.js +1 -1
  507. package/clis/oeis/utils.js +1 -1
  508. package/clis/ones/common.js +6 -6
  509. package/clis/ones/enrich-tasks.js +1 -1
  510. package/clis/ones/my-tasks.js +1 -1
  511. package/clis/ones/resolve-labels.js +1 -1
  512. package/clis/ones/task-helpers.js +1 -1
  513. package/clis/ones/task.js +1 -1
  514. package/clis/ones/worklog.js +7 -7
  515. package/clis/openalex/search.js +1 -1
  516. package/clis/openalex/utils.js +1 -1
  517. package/clis/openalex/work.js +1 -1
  518. package/clis/openfda/drug-label.js +1 -1
  519. package/clis/openfda/food-recall.js +1 -1
  520. package/clis/openfda/utils.js +1 -1
  521. package/clis/openreview/author.js +1 -1
  522. package/clis/openreview/paper.js +1 -1
  523. package/clis/openreview/reviews.js +3 -3
  524. package/clis/openreview/search.js +1 -1
  525. package/clis/openreview/utils.js +1 -1
  526. package/clis/openreview/venue.js +1 -1
  527. package/clis/oschina/article.js +1 -1
  528. package/clis/oschina/catalogs.js +1 -1
  529. package/clis/oschina/login.js +1 -1
  530. package/clis/oschina/stats.js +6 -6
  531. package/clis/oschina/whoami.js +1 -1
  532. package/clis/osv/query.js +1 -1
  533. package/clis/osv/utils.js +1 -1
  534. package/clis/osv/vulnerability.js +1 -1
  535. package/clis/packagist/package.js +1 -1
  536. package/clis/packagist/search.js +1 -1
  537. package/clis/packagist/utils.js +1 -1
  538. package/clis/pinterest/api.js +1 -1
  539. package/clis/pinterest/auth.js +1 -1
  540. package/clis/pinterest/boards.js +1 -1
  541. package/clis/pinterest/client.js +6 -6
  542. package/clis/pinterest/publish.js +5 -5
  543. package/clis/pixiv/auth.js +2 -2
  544. package/clis/pixiv/download.js +1 -1
  545. package/clis/pixiv/illusts.js +1 -1
  546. package/clis/pixiv/search.js +1 -1
  547. package/clis/pixiv/utils.js +3 -3
  548. package/clis/powerchina/auth.js +2 -2
  549. package/clis/powerchina/search.js +1 -1
  550. package/clis/producthunt/browse.js +2 -2
  551. package/clis/producthunt/hot.js +2 -2
  552. package/clis/producthunt/posts.js +1 -1
  553. package/clis/producthunt/today.js +1 -1
  554. package/clis/producthunt/utils.js +1 -1
  555. package/clis/pypi/downloads.js +1 -1
  556. package/clis/pypi/package.js +1 -1
  557. package/clis/pypi/utils.js +1 -1
  558. package/clis/qiita/auth.js +1 -1
  559. package/clis/qiita/gql.js +6 -6
  560. package/clis/qiita/publish.js +4 -4
  561. package/clis/qiita/stats.js +4 -4
  562. package/clis/qoder/_utils.js +16 -16
  563. package/clis/qoder/composer.js +1 -1
  564. package/clis/qoder/quest.js +1 -1
  565. package/clis/qoder/ui.js +14 -14
  566. package/clis/quark/auth.js +2 -2
  567. package/clis/quark/utils.js +2 -2
  568. package/clis/quora/answer-comments.js +3 -3
  569. package/clis/quora/create-answer.js +4 -4
  570. package/clis/quora/create-question.js +3 -3
  571. package/clis/quora/shared.js +17 -17
  572. package/clis/quora/whoami.js +1 -1
  573. package/clis/qwen/ask.js +1 -1
  574. package/clis/qwen/auth.js +3 -3
  575. package/clis/qwen/detail.js +1 -1
  576. package/clis/qwen/image.js +5 -5
  577. package/clis/qwen/status.js +1 -1
  578. package/clis/qwen/utils.js +16 -16
  579. package/clis/reddit/home.js +3 -3
  580. package/clis/reddit/read.js +10 -10
  581. package/clis/reddit/reply.js +4 -4
  582. package/clis/reddit/submit.js +11 -11
  583. package/clis/reddit/subreddit-info.js +3 -3
  584. package/clis/reddit/subscribed.js +4 -4
  585. package/clis/reddit/whoami.js +2 -2
  586. package/clis/rednote/comments.js +1 -1
  587. package/clis/rednote/download.js +1 -1
  588. package/clis/rednote/feed.js +1 -1
  589. package/clis/rednote/note.js +1 -1
  590. package/clis/rednote/notifications.js +2 -2
  591. package/clis/rednote/search.js +2 -2
  592. package/clis/rest-countries/country.js +1 -1
  593. package/clis/rest-countries/region.js +1 -1
  594. package/clis/rest-countries/utils.js +1 -1
  595. package/clis/reuters/article-detail.js +1 -1
  596. package/clis/reuters/auth.js +3 -3
  597. package/clis/reuters/search.js +1 -1
  598. package/clis/reuters/utils.js +4 -4
  599. package/clis/rfc/rfc.js +1 -1
  600. package/clis/rfc/utils.js +1 -1
  601. package/clis/rubygems/gem.js +1 -1
  602. package/clis/rubygems/search.js +1 -1
  603. package/clis/rubygems/utils.js +1 -1
  604. package/clis/segmentfault/article.js +3 -3
  605. package/clis/segmentfault/channels.js +1 -1
  606. package/clis/segmentfault/login.js +1 -1
  607. package/clis/segmentfault/stats.js +4 -4
  608. package/clis/segmentfault/tags.js +1 -1
  609. package/clis/segmentfault/whoami.js +1 -1
  610. package/clis/semanticscholar/citations.js +1 -1
  611. package/clis/semanticscholar/paper.js +1 -1
  612. package/clis/semanticscholar/recommendations.js +1 -1
  613. package/clis/semanticscholar/search.js +1 -1
  614. package/clis/semanticscholar/utils.js +1 -1
  615. package/clis/sinafinance/news.js +1 -1
  616. package/clis/sinafinance/stock-rank.js +1 -1
  617. package/clis/sinafinance/stock.js +1 -1
  618. package/clis/slock/attachment-download.js +1 -1
  619. package/clis/slock/attachment-upload.js +7 -7
  620. package/clis/slock/attachment-url.js +1 -1
  621. package/clis/slock/auth-verify.js +1 -1
  622. package/clis/slock/bookmark-add.js +1 -1
  623. package/clis/slock/bookmark-remove.js +1 -1
  624. package/clis/slock/channel-action.js +1 -1
  625. package/clis/slock/channel-create.js +1 -1
  626. package/clis/slock/channel-files.js +1 -1
  627. package/clis/slock/channel-list.js +1 -1
  628. package/clis/slock/channel-mark.js +1 -1
  629. package/clis/slock/channel-members.js +1 -1
  630. package/clis/slock/channel-unarchive.js +1 -1
  631. package/clis/slock/dm-list.js +1 -1
  632. package/clis/slock/errors.js +1 -1
  633. package/clis/slock/in-page.js +28 -28
  634. package/clis/slock/inbox-done.js +5 -5
  635. package/clis/slock/inbox.js +1 -1
  636. package/clis/slock/message-read.js +22 -22
  637. package/clis/slock/message-search.js +10 -10
  638. package/clis/slock/message-send.js +25 -25
  639. package/clis/slock/reaction-add.js +1 -1
  640. package/clis/slock/reaction-remove.js +1 -1
  641. package/clis/slock/resolve.js +1 -1
  642. package/clis/slock/server-list.js +2 -2
  643. package/clis/slock/task-claim.js +4 -4
  644. package/clis/slock/task-convert.js +13 -13
  645. package/clis/slock/task-create.js +1 -1
  646. package/clis/slock/task-delete.js +5 -5
  647. package/clis/slock/task-get.js +5 -5
  648. package/clis/slock/task-list-server.js +4 -4
  649. package/clis/slock/task-list.js +5 -5
  650. package/clis/slock/task-status.js +3 -3
  651. package/clis/slock/task-unclaim.js +3 -3
  652. package/clis/slock/thread-follow.js +1 -1
  653. package/clis/slock/thread-state.js +1 -1
  654. package/clis/slock/unread-summary.js +5 -5
  655. package/clis/slock/whoami.js +1 -1
  656. package/clis/smzdm/search.js +3 -3
  657. package/clis/sohu/article.js +1 -1
  658. package/clis/sohu/attributes.js +1 -1
  659. package/clis/sohu/categories.js +1 -1
  660. package/clis/sohu/channels.js +1 -1
  661. package/clis/sohu/columns.js +1 -1
  662. package/clis/sohu/login.js +1 -1
  663. package/clis/sohu/stats.js +3 -3
  664. package/clis/sohu/topics.js +1 -1
  665. package/clis/sohu/whoami.js +1 -1
  666. package/clis/spotify/spotify.js +1 -1
  667. package/clis/stackoverflow/read.js +6 -6
  668. package/clis/stackoverflow/related.js +1 -1
  669. package/clis/stackoverflow/tag.js +1 -1
  670. package/clis/stackoverflow/user.js +1 -1
  671. package/clis/stackoverflow/utils.js +1 -1
  672. package/clis/steam/app.js +1 -1
  673. package/clis/steam/search.js +1 -1
  674. package/clis/steam/utils.js +1 -1
  675. package/clis/substack/auth.js +2 -2
  676. package/clis/substack/post-utils.js +2 -2
  677. package/clis/substack/publish.js +5 -5
  678. package/clis/suno/auth.js +2 -2
  679. package/clis/suno/download.js +5 -5
  680. package/clis/suno/generate.js +3 -3
  681. package/clis/suno/list.js +1 -1
  682. package/clis/suno/status.js +1 -1
  683. package/clis/suno/utils.js +29 -29
  684. package/clis/telegram/send.js +7 -7
  685. package/clis/telegram/shared.js +2 -2
  686. package/clis/telegram/whoami.js +1 -1
  687. package/clis/test-utils.js +1 -1
  688. package/clis/threads/post.js +23 -23
  689. package/clis/threads/shared.js +3 -3
  690. package/clis/threads/whoami.js +1 -1
  691. package/clis/tieba/hot.js +3 -3
  692. package/clis/tieba/posts.js +1 -1
  693. package/clis/tieba/read.js +2 -2
  694. package/clis/tieba/search.js +3 -3
  695. package/clis/tieba/utils.js +1 -1
  696. package/clis/tiktok/comment.js +2 -2
  697. package/clis/tiktok/creator-videos.js +3 -3
  698. package/clis/tiktok/explore.js +3 -3
  699. package/clis/tiktok/follow.js +8 -8
  700. package/clis/tiktok/following.js +4 -4
  701. package/clis/tiktok/friends.js +7 -7
  702. package/clis/tiktok/live.js +3 -3
  703. package/clis/tiktok/notifications.js +6 -6
  704. package/clis/tiktok/publish.js +17 -17
  705. package/clis/tiktok/unfollow.js +4 -4
  706. package/clis/tiktok/user.js +2 -2
  707. package/clis/tiktok/utils.js +1 -1
  708. package/clis/toutiao/article.js +1 -1
  709. package/clis/toutiao/articles.js +2 -2
  710. package/clis/toutiao/auth.js +2 -2
  711. package/clis/toutiao/hot.js +1 -1
  712. package/clis/toutiao/recommend.js +1 -1
  713. package/clis/toutiao/utils.js +2 -2
  714. package/clis/trae-solo/_actions.js +4 -4
  715. package/clis/trae-solo/_fs.js +5 -5
  716. package/clis/trae-solo/_state.js +2 -2
  717. package/clis/trae-solo/automation.js +4 -4
  718. package/clis/trae-solo/mode.js +4 -4
  719. package/clis/trae-solo/model.js +4 -4
  720. package/clis/trae-solo/renderer-storage.js +4 -4
  721. package/clis/trae-solo/settings.js +1 -1
  722. package/clis/trae-solo/skill-fs.js +1 -1
  723. package/clis/trae-solo/skill.js +12 -12
  724. package/clis/trae-solo/state-fs.js +2 -2
  725. package/clis/trae-solo/task-fs.js +5 -5
  726. package/clis/trae-solo/workspaces-fs.js +1 -1
  727. package/clis/tumblr/auth.js +2 -2
  728. package/clis/tumblr/publish.js +3 -3
  729. package/clis/tvmaze/search.js +1 -1
  730. package/clis/tvmaze/show.js +1 -1
  731. package/clis/tvmaze/utils.js +1 -1
  732. package/clis/twitter/accept.js +7 -7
  733. package/clis/twitter/article.js +7 -7
  734. package/clis/twitter/bookmark-folder.js +3 -3
  735. package/clis/twitter/bookmark-folders.js +3 -3
  736. package/clis/twitter/bookmarks.js +4 -4
  737. package/clis/twitter/delete.js +5 -5
  738. package/clis/twitter/device-follow.js +3 -3
  739. package/clis/twitter/dm-list.js +1 -1
  740. package/clis/twitter/dm-read.js +1 -1
  741. package/clis/twitter/dm-send.js +5 -5
  742. package/clis/twitter/dm-shared.js +3 -3
  743. package/clis/twitter/download.js +6 -6
  744. package/clis/twitter/followers.js +5 -5
  745. package/clis/twitter/following.js +2 -2
  746. package/clis/twitter/like.js +3 -3
  747. package/clis/twitter/likes.js +8 -8
  748. package/clis/twitter/list-add-core.js +9 -9
  749. package/clis/twitter/list-create.js +5 -5
  750. package/clis/twitter/list-remove-core.js +9 -9
  751. package/clis/twitter/list-tweets.js +7 -7
  752. package/clis/twitter/lists.js +6 -6
  753. package/clis/twitter/notifications.js +2 -2
  754. package/clis/twitter/post.js +24 -24
  755. package/clis/twitter/profile.js +7 -7
  756. package/clis/twitter/quote.js +7 -7
  757. package/clis/twitter/reply-dm.js +7 -7
  758. package/clis/twitter/reply.js +12 -12
  759. package/clis/twitter/retweet.js +3 -3
  760. package/clis/twitter/scheduled-delete.js +3 -3
  761. package/clis/twitter/scheduled-list.js +2 -2
  762. package/clis/twitter/scheduled-utils.js +3 -3
  763. package/clis/twitter/search.js +5 -5
  764. package/clis/twitter/shared.js +6 -6
  765. package/clis/twitter/thread.js +4 -4
  766. package/clis/twitter/timeline.js +3 -3
  767. package/clis/twitter/trending.js +2 -2
  768. package/clis/twitter/tweets.js +11 -11
  769. package/clis/twitter/unlike.js +3 -3
  770. package/clis/twitter/unretweet.js +3 -3
  771. package/clis/twitter/utils.js +6 -6
  772. package/clis/upwork/detail.js +2 -2
  773. package/clis/upwork/feed.js +2 -2
  774. package/clis/upwork/search.js +2 -2
  775. package/clis/upwork/utils.js +1 -1
  776. package/clis/v2ex/auth.js +2 -2
  777. package/clis/v2ex/daily.js +3 -3
  778. package/clis/v2ex/me.js +2 -2
  779. package/clis/v2ex/notifications.js +2 -2
  780. package/clis/vk/post.js +1 -1
  781. package/clis/vk/shared.js +2 -2
  782. package/clis/vk/whoami.js +1 -1
  783. package/clis/web/read.js +8 -8
  784. package/clis/wechat-channels/auth.js +2 -2
  785. package/clis/wechat-channels/publish.js +30 -30
  786. package/clis/weibo/article.js +1 -1
  787. package/clis/weibo/auth.js +3 -3
  788. package/clis/weibo/comments.js +1 -1
  789. package/clis/weibo/delete.js +2 -2
  790. package/clis/weibo/feed.js +3 -3
  791. package/clis/weibo/hot.js +1 -1
  792. package/clis/weibo/publish.js +10 -10
  793. package/clis/weibo/search.js +2 -2
  794. package/clis/weibo/user-posts.js +3 -3
  795. package/clis/weibo/user.js +2 -2
  796. package/clis/weibo/utils.js +3 -3
  797. package/clis/weixin/article.js +1 -1
  798. package/clis/weixin/create-draft.js +26 -26
  799. package/clis/weixin/download.js +2 -2
  800. package/clis/weixin/login.js +1 -1
  801. package/clis/weixin/search.js +2 -2
  802. package/clis/weixin/stats.js +3 -3
  803. package/clis/weixin/whoami.js +1 -1
  804. package/clis/weread/ai-outline.js +2 -2
  805. package/clis/weread/book-search.js +2 -2
  806. package/clis/weread/book.js +2 -2
  807. package/clis/weread/notebooks.js +1 -1
  808. package/clis/weread/search.js +1 -1
  809. package/clis/weread/shelf.js +1 -1
  810. package/clis/weread/utils.js +6 -6
  811. package/clis/weread-official/book.js +1 -1
  812. package/clis/weread-official/discover.js +1 -1
  813. package/clis/weread-official/list-apis.js +1 -1
  814. package/clis/weread-official/notes.js +1 -1
  815. package/clis/weread-official/readdata.js +1 -1
  816. package/clis/weread-official/review.js +1 -1
  817. package/clis/weread-official/search.js +1 -1
  818. package/clis/weread-official/shelf.js +1 -1
  819. package/clis/weread-official/utils.js +1 -1
  820. package/clis/wikidata/entity.js +1 -1
  821. package/clis/wikidata/search.js +1 -1
  822. package/clis/wikidata/utils.js +1 -1
  823. package/clis/wikipedia/page.js +1 -1
  824. package/clis/wikipedia/trending.js +1 -1
  825. package/clis/wikipedia/utils.js +1 -1
  826. package/clis/wordpress/login.js +1 -1
  827. package/clis/wordpress/publish.js +1 -1
  828. package/clis/wordpress/shared.js +3 -3
  829. package/clis/wordpress/whoami.js +1 -1
  830. package/clis/woshipm/article.js +1 -1
  831. package/clis/woshipm/login.js +1 -1
  832. package/clis/woshipm/stats.js +4 -4
  833. package/clis/woshipm/whoami.js +1 -1
  834. package/clis/wttr/current.js +1 -1
  835. package/clis/wttr/forecast.js +1 -1
  836. package/clis/wttr/utils.js +1 -1
  837. package/clis/xianyu/collect.js +1 -1
  838. package/clis/xianyu/inbox.js +1 -1
  839. package/clis/xianyu/item-stats.js +2 -2
  840. package/clis/xianyu/location.js +1 -1
  841. package/clis/xianyu/manage.js +1 -1
  842. package/clis/xianyu/messages.js +1 -1
  843. package/clis/xianyu/mtop.js +5 -5
  844. package/clis/xianyu/order.js +1 -1
  845. package/clis/xianyu/promote-stats.js +2 -2
  846. package/clis/xianyu/publish.js +17 -17
  847. package/clis/xianyu/rate.js +1 -1
  848. package/clis/xianyu/reply.js +1 -1
  849. package/clis/xianyu/search.js +8 -8
  850. package/clis/xianyu/seller-data.js +1 -1
  851. package/clis/xianyu/seller-list.js +1 -1
  852. package/clis/xianyu/user.js +1 -1
  853. package/clis/xiaoe/catalog.js +2 -2
  854. package/clis/xiaoe/content.js +2 -2
  855. package/clis/xiaoe/courses.js +2 -2
  856. package/clis/xiaohongshu/ask.js +6 -6
  857. package/clis/xiaohongshu/comments.js +6 -6
  858. package/clis/xiaohongshu/creator-note-detail.js +7 -7
  859. package/clis/xiaohongshu/creator-notes-summary.js +1 -1
  860. package/clis/xiaohongshu/creator-notes.js +13 -13
  861. package/clis/xiaohongshu/creator-profile.js +2 -2
  862. package/clis/xiaohongshu/creator-stats.js +2 -2
  863. package/clis/xiaohongshu/delete-note.js +7 -7
  864. package/clis/xiaohongshu/download.js +4 -4
  865. package/clis/xiaohongshu/feed.js +2 -2
  866. package/clis/xiaohongshu/follow.js +3 -3
  867. package/clis/xiaohongshu/human.js +3 -3
  868. package/clis/xiaohongshu/note-helpers.js +1 -1
  869. package/clis/xiaohongshu/note.js +2 -2
  870. package/clis/xiaohongshu/notifications.js +1 -1
  871. package/clis/xiaohongshu/publish-video.js +8 -8
  872. package/clis/xiaohongshu/publish.js +59 -59
  873. package/clis/xiaohongshu/search.js +8 -8
  874. package/clis/xiaohongshu/unfollow.js +4 -4
  875. package/clis/xiaohongshu/user-helpers.js +1 -1
  876. package/clis/xiaohongshu/user.js +2 -2
  877. package/clis/xiaoyuzhou/auth.js +3 -3
  878. package/clis/xiaoyuzhou/download.js +1 -1
  879. package/clis/xiaoyuzhou/utils.js +1 -1
  880. package/clis/xueqiu/article.js +4 -4
  881. package/clis/xueqiu/comments.js +4 -4
  882. package/clis/xueqiu/danjuan-utils.js +4 -4
  883. package/clis/xueqiu/earnings-date.js +1 -1
  884. package/clis/xueqiu/events.js +3 -3
  885. package/clis/xueqiu/hashtags.js +3 -3
  886. package/clis/xueqiu/stocks.js +3 -3
  887. package/clis/xueqiu/users.js +3 -3
  888. package/clis/xueqiu/utils.js +3 -3
  889. package/clis/yahoo-finance/quote.js +1 -1
  890. package/clis/yollomi/background.js +1 -1
  891. package/clis/yollomi/edit.js +1 -1
  892. package/clis/yollomi/face-swap.js +1 -1
  893. package/clis/yollomi/generate.js +1 -1
  894. package/clis/yollomi/object-remover.js +1 -1
  895. package/clis/yollomi/remove-bg.js +1 -1
  896. package/clis/yollomi/restore.js +1 -1
  897. package/clis/yollomi/try-on.js +1 -1
  898. package/clis/yollomi/upload.js +4 -4
  899. package/clis/yollomi/upscale.js +1 -1
  900. package/clis/yollomi/utils.js +4 -4
  901. package/clis/yollomi/video.js +1 -1
  902. package/clis/youtube/channel.js +4 -4
  903. package/clis/youtube/feed.js +2 -2
  904. package/clis/youtube/like.js +5 -5
  905. package/clis/youtube/playlist.js +7 -7
  906. package/clis/youtube/publish.js +11 -11
  907. package/clis/youtube/search.js +3 -3
  908. package/clis/youtube/subscribe.js +7 -7
  909. package/clis/youtube/subscriptions.js +1 -1
  910. package/clis/youtube/transcript-group.js +2 -2
  911. package/clis/youtube/transcript.js +13 -13
  912. package/clis/youtube/unlike.js +5 -5
  913. package/clis/youtube/unsubscribe.js +7 -7
  914. package/clis/youtube/utils.js +3 -3
  915. package/clis/youtube/video.js +4 -4
  916. package/clis/youtube/watch-later.js +2 -2
  917. package/clis/yuanbao/ask.js +18 -18
  918. package/clis/yuanbao/detail.js +1 -1
  919. package/clis/yuanbao/read.js +1 -1
  920. package/clis/yuanbao/shared.js +9 -9
  921. package/clis/yuanbao/status.js +1 -1
  922. package/clis/yuque/article.js +1 -1
  923. package/clis/yuque/whoami.js +1 -1
  924. package/clis/zhihu/answer-comments.js +2 -2
  925. package/clis/zhihu/answer-detail.js +3 -3
  926. package/clis/zhihu/answer.js +1 -1
  927. package/clis/zhihu/article-transform.js +1 -1
  928. package/clis/zhihu/article.js +1 -1
  929. package/clis/zhihu/auth.js +2 -2
  930. package/clis/zhihu/collection.js +3 -3
  931. package/clis/zhihu/collections.js +3 -3
  932. package/clis/zhihu/download.js +2 -2
  933. package/clis/zhihu/image-profile.js +6 -6
  934. package/clis/zhihu/paginate.js +3 -3
  935. package/clis/zhihu/pin.js +4 -4
  936. package/clis/zhihu/question.js +3 -3
  937. package/clis/zhihu/recommend.js +3 -3
  938. package/clis/zhihu/search.js +3 -3
  939. package/clis/zhihu/stats.js +3 -3
  940. package/clis/zhihu/user-arg.js +1 -1
  941. package/clis/zhihu/write-shared.js +7 -7
  942. package/clis/zlibrary/utils.js +6 -6
  943. package/clis/zsxq/auth.js +3 -3
  944. package/clis/zsxq/search.js +1 -1
  945. package/clis/zsxq/topic.js +1 -1
  946. package/clis/zsxq/utils.js +5 -5
  947. package/dist/src/adapter-source.js +1 -1
  948. package/dist/src/browser/analyze.js +1 -1
  949. package/dist/src/browser/article-extract.js +2 -2
  950. package/dist/src/browser/ax-snapshot.js +2 -2
  951. package/dist/src/browser/base-page.js +25 -25
  952. package/dist/src/browser/bridge.js +1 -1
  953. package/dist/src/browser/cdp.js +1 -1
  954. package/dist/src/browser/daemon-client.js +1 -1
  955. package/dist/src/browser/daemon-lifecycle.js +7 -7
  956. package/dist/src/browser/dom-helpers.js +35 -35
  957. package/dist/src/browser/dom-snapshot.js +19 -19
  958. package/dist/src/browser/errors.js +3 -3
  959. package/dist/src/browser/extract.js +5 -5
  960. package/dist/src/browser/find.js +13 -13
  961. package/dist/src/browser/fingerprint.js +2 -2
  962. package/dist/src/browser/html-tree.js +6 -6
  963. package/dist/src/browser/managed-chrome.js +1 -1
  964. package/dist/src/browser/network-cache.js +1 -1
  965. package/dist/src/browser/network-key.js +1 -1
  966. package/dist/src/browser/page.js +7 -7
  967. package/dist/src/browser/profile.js +2 -2
  968. package/dist/src/browser/proxy-test.js +8 -8
  969. package/dist/src/browser/shape-filter.js +1 -1
  970. package/dist/src/browser/shape.js +1 -1
  971. package/dist/src/browser/stealth.js +3 -3
  972. package/dist/src/browser/tabs.js +2 -2
  973. package/dist/src/browser/target-errors.js +1 -1
  974. package/dist/src/browser/target-resolver.js +23 -23
  975. package/dist/src/browser/trace.js +2 -2
  976. package/dist/src/browser/utils.js +1 -1
  977. package/dist/src/browser/verify-fixture.js +2 -2
  978. package/dist/src/browser-session-lock.js +1 -1
  979. package/dist/src/build-manifest.js +11 -11
  980. package/dist/src/capabilityRouting.js +1 -1
  981. package/dist/src/cli-argv-preprocess.js +1 -1
  982. package/dist/src/cli.js +32 -32
  983. package/dist/src/commanderAdapter.js +3 -3
  984. package/dist/src/commands/auth.js +3 -3
  985. package/dist/src/commands/daemon.js +1 -1
  986. package/dist/src/completion-fast.js +1 -1
  987. package/dist/src/completion.js +1 -1
  988. package/dist/src/constants.js +1 -1
  989. package/dist/src/convention-audit.js +2 -2
  990. package/dist/src/daemon-utils.js +1 -1
  991. package/dist/src/daemon.js +1 -1
  992. package/dist/src/discovery.js +2 -2
  993. package/dist/src/doctor.js +9 -9
  994. package/dist/src/download/article-download.js +15 -15
  995. package/dist/src/download/index.js +4 -4
  996. package/dist/src/download/media-download.js +1 -1
  997. package/dist/src/download/progress.js +3 -3
  998. package/dist/src/electron-apps.js +1 -1
  999. package/dist/src/errors.js +2 -2
  1000. package/dist/src/execution.js +2 -2
  1001. package/dist/src/external.js +1 -1
  1002. package/dist/src/help.js +8 -8
  1003. package/dist/src/hooks.js +1 -1
  1004. package/dist/src/interceptor.js +21 -21
  1005. package/dist/src/launcher.js +7 -7
  1006. package/dist/src/logger.js +8 -8
  1007. package/dist/src/main.js +7 -7
  1008. package/dist/src/observation/artifact.js +5 -5
  1009. package/dist/src/observation/retention.js +1 -1
  1010. package/dist/src/output.js +2 -2
  1011. package/dist/src/package-paths.js +1 -1
  1012. package/dist/src/pipeline/executor.js +1 -1
  1013. package/dist/src/pipeline/registry.js +1 -1
  1014. package/dist/src/pipeline/steps/browser.js +1 -1
  1015. package/dist/src/pipeline/steps/download.js +1 -1
  1016. package/dist/src/pipeline/steps/fetch.js +6 -6
  1017. package/dist/src/pipeline/steps/intercept.js +1 -1
  1018. package/dist/src/pipeline/steps/tap.js +17 -17
  1019. package/dist/src/pipeline/steps/transform.js +1 -1
  1020. package/dist/src/pipeline/template.js +1 -1
  1021. package/dist/src/plugin-manifest.js +1 -1
  1022. package/dist/src/plugin-scaffold.js +19 -19
  1023. package/dist/src/plugin.js +12 -12
  1024. package/dist/src/rate-limit.js +1 -1
  1025. package/dist/src/registry.js +1 -1
  1026. package/dist/src/runtime-detect.js +1 -1
  1027. package/dist/src/runtime.js +1 -1
  1028. package/dist/src/scripts/framework.js +1 -1
  1029. package/dist/src/scripts/interact.js +1 -1
  1030. package/dist/src/scripts/store.js +1 -1
  1031. package/dist/src/serialization.js +2 -2
  1032. package/dist/src/session-lease.js +1 -1
  1033. package/dist/src/snapshotFormatter.js +2 -2
  1034. package/dist/src/tui.js +12 -12
  1035. package/dist/src/user-runtime.js +1 -1
  1036. package/dist/src/utils.d.ts +12 -0
  1037. package/dist/src/utils.js +4 -4
  1038. package/dist/src/validate.js +2 -2
  1039. package/dist/src/verify.js +2 -2
  1040. package/dist/src/version.js +1 -1
  1041. package/package.json +1 -1
@@ -1,9 +1,9 @@
1
- import{CliError as Q}from"@jackwener/opencli/errors";export const API_PREFIX="/project/api/project";export function getOnesBaseUrl(){const D=process.env.ONES_BASE_URL?.trim().replace(/\/+$/,"");if(!D)throw new Q("CONFIG","Missing ONES_BASE_URL","Set ONES_BASE_URL to your deployment origin, e.g. https://your-team.ones.cn (no trailing slash).");return D}export function onesApiUrl(D){const K=getOnesBaseUrl(),q=D.replace(/^\/+/,"");return`${K}${API_PREFIX}/${q}`}export async function gotoOnesHome(D){await D.goto(getOnesBaseUrl(),{waitUntil:"load"});await D.wait(2)}function G(D,K){const x={Referer:getOnesBaseUrl()};if(D){const L=process.env.ONES_USER_ID?.trim()||process.env.ONES_USER_UUID?.trim()||process.env.Ones_User_Id?.trim(),N=process.env.ONES_AUTH_TOKEN?.trim()||process.env.Ones_Auth_Token?.trim();if(L&&N){x["Ones-User-Id"]=L;x["Ones-Auth-Token"]=N}}if(K)x["Content-Type"]="application/json";return x}export function summarizeOnesError(D,K){if(K&&typeof K==="object"){const q=K,x=[];if(typeof q.type==="string")x.push(q.type);if(typeof q.reason==="string")x.push(q.reason);if(typeof q.errcode==="string")x.push(q.errcode);if(typeof q.message==="string")x.push(q.message);if(q.code!==void 0&&q.code!==null)x.push(`code=${String(q.code)}`);if(x.length)return x.filter(Boolean).join(" · ")}return D===401?"Unauthorized":`HTTP ${D}`}function M(D,K){if(K===null||typeof K!=="object")return;const q=K;if(Array.isArray(q.groups))return;if(!(typeof q.reason==="string"&&q.reason.length>0||typeof q.errcode==="string"&&q.errcode.length>0||typeof q.type==="string"&&q.type.length>0))return;const L=summarizeOnesError(200,K);throw new Q("FETCH_ERROR",`ONES ${D}: ${L}`,"若 query 不合法会返回 ServerError;可试 ppcli ones tasks(空 must)或检查筛选器文档。响应全文可用 -v 或临时打日志。")}export async function onesFetchInPageWithMeta(D,K,q={}){if(!q.skipGoto)await gotoOnesHome(D);const x=onesApiUrl(K),L=(q.method??"GET").toUpperCase(),N=q.auth!==!1,S=q.body??null,V=G(N,S!==null||L==="POST"||L==="PUT"||L==="PATCH"),Y=JSON.stringify(x),Z=JSON.stringify(L),$=JSON.stringify(V),j=S===null?"null":JSON.stringify(S);return await D.evaluate(`
1
+ import{CliError as i}from"@jackwener/opencli/errors";export const API_PREFIX="/project/api/project";export function getOnesBaseUrl(){const r=process.env.ONES_BASE_URL?.trim().replace(/\/+$/,"");if(!r)throw new i("CONFIG","Missing ONES_BASE_URL","Set ONES_BASE_URL to your deployment origin, e.g. https://your-team.ones.cn (no trailing slash).");return r}export function onesApiUrl(r){const n=getOnesBaseUrl(),e=r.replace(/^\/+/,"");return`${n}${API_PREFIX}/${e}`}export async function gotoOnesHome(r){await r.goto(getOnesBaseUrl(),{waitUntil:"load"});await r.wait(2)}function d(r,n){const t={Referer:getOnesBaseUrl()};if(r){const s=process.env.ONES_USER_ID?.trim()||process.env.ONES_USER_UUID?.trim()||process.env.Ones_User_Id?.trim(),o=process.env.ONES_AUTH_TOKEN?.trim()||process.env.Ones_Auth_Token?.trim();if(s&&o){t["Ones-User-Id"]=s;t["Ones-Auth-Token"]=o}}if(n)t["Content-Type"]="application/json";return t}export function summarizeOnesError(r,n){if(n&&typeof n==="object"){const e=n,t=[];if(typeof e.type==="string")t.push(e.type);if(typeof e.reason==="string")t.push(e.reason);if(typeof e.errcode==="string")t.push(e.errcode);if(typeof e.message==="string")t.push(e.message);if(e.code!==void 0&&e.code!==null)t.push(`code=${String(e.code)}`);if(t.length)return t.filter(Boolean).join(" · ")}return r===401?"Unauthorized":`HTTP ${r}`}function E(r,n){if(n===null||typeof n!=="object")return;const e=n;if(Array.isArray(e.groups))return;if(!(typeof e.reason==="string"&&e.reason.length>0||typeof e.errcode==="string"&&e.errcode.length>0||typeof e.type==="string"&&e.type.length>0))return;const s=summarizeOnesError(200,n);throw new i("FETCH_ERROR",`ONES ${r}: ${s}`,"若 query 不合法会返回 ServerError;可试 ppcli ones tasks(空 must)或检查筛选器文档。响应全文可用 -v 或临时打日志。")}export async function onesFetchInPageWithMeta(r,n,e={}){if(!e.skipGoto)await gotoOnesHome(r);const t=onesApiUrl(n),s=(e.method??"GET").toUpperCase(),o=e.auth!==!1,c=e.body??null,u=d(o,c!==null||s==="POST"||s==="PUT"||s==="PATCH"),a=JSON.stringify(t),p=JSON.stringify(s),l=JSON.stringify(u),f=c===null?"null":JSON.stringify(c);return await r.evaluate(`
2
2
  (async () => {
3
- const url = ${Y};
4
- const method = ${Z};
5
- const headers = ${$};
6
- const body = ${j};
3
+ const url = ${a};
4
+ const method = ${p};
5
+ const headers = ${l};
6
+ const body = ${f};
7
7
  const init = {
8
8
  method,
9
9
  headers: { ...headers },
@@ -20,4 +20,4 @@ import{CliError as Q}from"@jackwener/opencli/errors";export const API_PREFIX="/p
20
20
  }
21
21
  return { ok: res.ok, status: res.status, parsed };
22
22
  })()
23
- `)}export async function resolveOnesUserUuid(D,K){const q=process.env.ONES_USER_ID?.trim()||process.env.ONES_USER_UUID?.trim()||process.env.Ones_User_Id?.trim();if(q)return q;const x=await onesFetchInPage(D,"users/me",{skipGoto:K?.skipGoto}),L=x.user&&typeof x.user==="object"?x.user:x;if(!L||typeof L.uuid!=="string")throw new Q("FETCH_ERROR","Could not read current user uuid from users/me","Set ONES_USER_ID or ensure Chrome is logged in; try: ppcli ones me -f json");return String(L.uuid)}export async function onesFetchInPage(D,K,q={}){const x=await onesFetchInPageWithMeta(D,K,q);if(!x.ok){const L=summarizeOnesError(x.status,x.parsed),N=x.status===401?"在 Chrome 中打开 ONES 并登录;或先执行 ppcli ones login 后按提示 export ONES_USER_ID / ONES_AUTH_TOKEN;并确认 ONES_BASE_URL 与浏览器地址一致。":"检查 ONES_BASE_URL、VPN/内网,以及实例是否仍为 Project API 路径。";throw new Q("FETCH_ERROR",`ONES ${K}: ${L}`,N)}if(K.includes("/filters/peek"))M(K,x.parsed);return x.parsed}
23
+ `)}export async function resolveOnesUserUuid(r,n){const e=process.env.ONES_USER_ID?.trim()||process.env.ONES_USER_UUID?.trim()||process.env.Ones_User_Id?.trim();if(e)return e;const t=await onesFetchInPage(r,"users/me",{skipGoto:n?.skipGoto}),s=t.user&&typeof t.user==="object"?t.user:t;if(!s||typeof s.uuid!=="string")throw new i("FETCH_ERROR","Could not read current user uuid from users/me","Set ONES_USER_ID or ensure Chrome is logged in; try: ppcli ones me -f json");return String(s.uuid)}export async function onesFetchInPage(r,n,e={}){const t=await onesFetchInPageWithMeta(r,n,e);if(!t.ok){const s=summarizeOnesError(t.status,t.parsed),o=t.status===401?"在 Chrome 中打开 ONES 并登录;或先执行 ppcli ones login 后按提示 export ONES_USER_ID / ONES_AUTH_TOKEN;并确认 ONES_BASE_URL 与浏览器地址一致。":"检查 ONES_BASE_URL、VPN/内网,以及实例是否仍为 Project API 路径。";throw new i("FETCH_ERROR",`ONES ${n}: ${s}`,o)}if(n.includes("/filters/peek"))E(n,t.parsed);return t.parsed}
@@ -1 +1 @@
1
- import{onesFetchInPage as m}from"./common.js";const c=40;export async function enrichPeekEntriesWithDetails(u,f,n,d){const r=[...new Set(n.map((t)=>String(t.uuid??"").trim()).filter(Boolean))];if(r.length===0)return n;const e=new Map;try{for(let t=0;t<r.length;t+=c){const i=r.slice(t,t+c),s=await m(u,`team/${f}/tasks/info`,{method:"POST",body:JSON.stringify({ids:i}),skipGoto:d}),l=Array.isArray(s.tasks)?s.tasks:[];for(const o of l){const a=String(o.uuid??"");if(a)e.set(a,o)}}}catch{return n}if(e.size===0)return n;return n.map((t)=>{const i=String(t.uuid??""),s=i?e.get(i):void 0;return s?{...t,...s}:t})}
1
+ import{onesFetchInPage as g}from"./common.js";const c=40;export async function enrichPeekEntriesWithDetails(u,d,n,f){const r=[...new Set(n.map((t)=>String(t.uuid??"").trim()).filter(Boolean))];if(r.length===0)return n;const o=new Map;try{for(let t=0;t<r.length;t+=c){const s=r.slice(t,t+c),i=await g(u,`team/${d}/tasks/info`,{method:"POST",body:JSON.stringify({ids:s}),skipGoto:f}),l=Array.isArray(i.tasks)?i.tasks:[];for(const e of l){const a=String(e.uuid??"");if(a)o.set(a,e)}}}catch{return n}if(o.size===0)return n;return n.map((t)=>{const s=String(t.uuid??""),i=s?o.get(s):void 0;return i?{...t,...i}:t})}
@@ -1 +1 @@
1
- import{cli as H,Strategy as I}from"@jackwener/opencli/registry";import{CliError as S}from"@jackwener/opencli/errors";import{gotoOnesHome as W,onesFetchInPage as B,resolveOnesUserUuid as f}from"./common.js";import{enrichPeekEntriesWithDetails as v}from"./enrich-tasks.js";import{resolveTaskListLabels as E}from"./resolve-labels.js";import{defaultPeekBody as F,flattenPeekGroups as L,mapTaskEntry as b,parsePeekLimit as A}from"./task-helpers.js";function $(x){return{must:[{equal:{assign:x}}]}}function C(x){return{must:[{in:{"field_values.field004":[x]}}]}}function D(x){return{must:[{equal:{owner:x}}]}}function O(x){const M=new Set,z=[];for(const J of x){const K=String(J.uuid??"");if(!K||M.has(K))continue;M.add(K);z.push(J)}return z}async function X(x,M,z,J){const K=`team/${M}/filters/peek`,N=F(z),Q=await B(x,K,{method:"POST",body:JSON.stringify(N),skipGoto:!0});return L(Q,J)}H({site:"ones",name:"my-tasks",access:"read",description:"ONES — my work items (filters/peek + strict must query). Default: assignee=me. Use --mode if your site uses field004 for assignee.",domain:"ones.cn",strategy:I.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"team",type:"str",required:!1,positional:!0,help:"Team UUID from URL …/team/<uuid>/…, or set ONES_TEAM_UUID"},{name:"limit",type:"int",default:100,help:"Max rows (default 100, max 500)"},{name:"mode",type:"str",default:"assign",choices:["assign","field004","owner","both"],help:"assign=负责人(顶层 assign);field004=负责人(筛选器示例里的 field004);owner=创建者;both=负责人∪创建者(两次 peek 去重)"}],columns:["title","status","project","uuid","updated","工时"],func:async(x,M)=>{const z=M.team?.trim()||process.env.ONES_TEAM_UUID?.trim()||process.env.ONES_TEAM_ID?.trim();if(!z)throw new S("CONFIG","team UUID required","Pass team from URL …/team/<team>/… or set ONES_TEAM_UUID.");const J=A(M.limit,100),K=String(M.mode??"assign");await W(x);const N=await f(x,{skipGoto:!0});let Q=[];if(K==="both"){const R=Math.min(500,J*2),Y=await X(x,z,$(N),R),V=await X(x,z,D(N),R);Q=O([...Y,...V]).slice(0,J)}else{const Y=(()=>{switch(K){case"field004":return C(N);case"owner":return D(N);case"assign":default:return $(N)}})();try{Q=await X(x,z,Y,J)}catch(V){const Z=V instanceof Error?V.message:"";if(K==="assign"&&(Z.includes("ServerError")||Z.includes("801")||Z.includes("Params is invalid")))Q=await X(x,z,C(N),J);else throw V}}const _=await v(x,z,Q,!0),G=await E(x,z,_,!0);return _.map((R)=>b(R,G))}});
1
+ import{cli as h,Strategy as U}from"@jackwener/opencli/registry";import{CliError as g}from"@jackwener/opencli/errors";import{gotoOnesHome as k,onesFetchInPage as E,resolveOnesUserUuid as O}from"./common.js";import{enrichPeekEntriesWithDetails as S}from"./enrich-tasks.js";import{resolveTaskListLabels as b}from"./resolve-labels.js";import{defaultPeekBody as q,flattenPeekGroups as I,mapTaskEntry as T,parsePeekLimit as _}from"./task-helpers.js";function f(e){return{must:[{equal:{assign:e}}]}}function p(e){return{must:[{in:{"field_values.field004":[e]}}]}}function y(e){return{must:[{equal:{owner:e}}]}}function v(e){const i=new Set,t=[];for(const s of e){const r=String(s.uuid??"");if(!r||i.has(r))continue;i.add(r);t.push(s)}return t}async function c(e,i,t,s){const r=`team/${i}/filters/peek`,n=q(t),a=await E(e,r,{method:"POST",body:JSON.stringify(n),skipGoto:!0});return I(a,s)}h({site:"ones",name:"my-tasks",access:"read",description:"ONES — my work items (filters/peek + strict must query). Default: assignee=me. Use --mode if your site uses field004 for assignee.",domain:"ones.cn",strategy:U.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"team",type:"str",required:!1,positional:!0,help:"Team UUID from URL …/team/<uuid>/…, or set ONES_TEAM_UUID"},{name:"limit",type:"int",default:100,help:"Max rows (default 100, max 500)"},{name:"mode",type:"str",default:"assign",choices:["assign","field004","owner","both"],help:"assign=负责人(顶层 assign);field004=负责人(筛选器示例里的 field004);owner=创建者;both=负责人∪创建者(两次 peek 去重)"}],columns:["title","status","project","uuid","updated","工时"],func:async(e,i)=>{const t=i.team?.trim()||process.env.ONES_TEAM_UUID?.trim()||process.env.ONES_TEAM_ID?.trim();if(!t)throw new g("CONFIG","team UUID required","Pass team from URL …/team/<team>/… or set ONES_TEAM_UUID.");const s=_(i.limit,100),r=String(i.mode??"assign");await k(e);const n=await O(e,{skipGoto:!0});let a=[];if(r==="both"){const o=Math.min(500,s*2),m=await c(e,t,f(n),o),u=await c(e,t,y(n),o);a=v([...m,...u]).slice(0,s)}else{const m=(()=>{switch(r){case"field004":return p(n);case"owner":return y(n);case"assign":default:return f(n)}})();try{a=await c(e,t,m,s)}catch(u){const l=u instanceof Error?u.message:"";if(r==="assign"&&(l.includes("ServerError")||l.includes("801")||l.includes("Params is invalid")))a=await c(e,t,p(n),s);else throw u}}const d=await S(e,t,a,!0),w=await b(e,t,d,!0);return d.map((o)=>T(o,w))}});
@@ -1 +1 @@
1
- import{onesFetchInPage as m}from"./common.js";import{getTaskProjectRawId as h}from"./task-helpers.js";export async function loadTaskStatusLabels(n,a,r){const o=new Map;try{const s=await m(n,`team/${a}/task_statuses`,{method:"GET",skipGoto:r}),e=Array.isArray(s.task_statuses)?s.task_statuses:[];for(const t of e){const c=String(t.uuid??""),i=String(t.name??"");if(c&&i)o.set(c,i)}}catch{}return o}const f=25;export async function loadProjectLabels(n,a,r,o){const s=new Map,e=[...new Set(r.filter(Boolean))];if(e.length===0)return s;try{for(let t=0;t<e.length;t+=f){const i=e.slice(t,t+f).map(encodeURIComponent).join(","),y=`team/${a}/projects/info?ids=${i}`,u=await m(n,y,{method:"GET",skipGoto:o}),j=Array.isArray(u.projects)?u.projects:[];for(const p of j){const l=String(p.uuid??""),d=String(p.name??"");if(l&&d)s.set(l,d)}}}catch{}return s}export async function resolveTaskListLabels(n,a,r,o){const s=r.map((c)=>h(c)).filter(Boolean),[e,t]=await Promise.all([loadTaskStatusLabels(n,a,o),loadProjectLabels(n,a,s,o)]);return{statusByUuid:e,projectByUuid:t}}
1
+ import{onesFetchInPage as m}from"./common.js";import{getTaskProjectRawId as h}from"./task-helpers.js";export async function loadTaskStatusLabels(n,a,r){const o=new Map;try{const s=await m(n,`team/${a}/task_statuses`,{method:"GET",skipGoto:r}),e=Array.isArray(s.task_statuses)?s.task_statuses:[];for(const t of e){const c=String(t.uuid??""),i=String(t.name??"");if(c&&i)o.set(c,i)}}catch{}return o}const f=25;export async function loadProjectLabels(n,a,r,o){const s=new Map,e=[...new Set(r.filter(Boolean))];if(e.length===0)return s;try{for(let t=0;t<e.length;t+=f){const i=e.slice(t,t+f).map(encodeURIComponent).join(","),y=`team/${a}/projects/info?ids=${i}`,p=await m(n,y,{method:"GET",skipGoto:o}),j=Array.isArray(p.projects)?p.projects:[];for(const l of j){const u=String(l.uuid??""),d=String(l.name??"");if(u&&d)s.set(u,d)}}}catch{}return s}export async function resolveTaskListLabels(n,a,r,o){const s=r.map((c)=>h(c)).filter(Boolean),[e,t]=await Promise.all([loadTaskStatusLabels(n,a,o),loadProjectLabels(n,a,s,o)]);return{statusByUuid:e,projectByUuid:t}}
@@ -1 +1 @@
1
- import{CliError as E}from"@jackwener/opencli/errors";function H(B){if(!Array.isArray(B))return"";for(const D of B){if(!D||typeof D!=="object")continue;const G=D;if(!String(G.field_uuid??"").startsWith("field"))continue;const J=G.value;if(typeof J==="string"&&J.trim())return J.trim();if(Array.isArray(J)&&J.length&&typeof J[0]==="string"&&J[0].trim())return J[0].trim()}return""}export function pickTaskTitle(B){for(const K of["summary","name","title","subject"]){const J=B[K];if(typeof J==="string"&&J.trim())return J.trim()}const D=H(B.field_values);if(D)return D;const G=B.field_values;if(G&&typeof G==="object"&&!Array.isArray(G)){const K=G;for(const J of["field001","field002","field003"]){const N=K[J];if(typeof N==="string"&&N.trim())return N.trim()}}return""}export function ellipsizeCell(B,D=64){const G=B.trim();if(G.length<=D)return G;return`${G.slice(0,D-1)}…`}export function briefUuid(B,D=6,G=4){if(!B)return"";if(B.length<=D+G+1)return B;return`${B.slice(0,D)}…${B.slice(-G)}`}export function formatStamp(B){if(B==null||B==="")return"";const D=Number(B);if(Number.isNaN(D))return String(B);const G=D>100000000000000?Math.floor(D/1000):D>1000000000000?D:D*1000;try{return new Date(G).toISOString().replace("T"," ").slice(0,19)}catch{return String(B)}}export function flattenPeekGroups(B,D){if(!Array.isArray(B.groups))throw new E("FETCH_ERROR","Unexpected filters/peek response (missing groups)","Try -f json; check team UUID and API version.");const G=B.groups,K=[];for(const J of G){const N=Array.isArray(J.entries)?J.entries:[];for(const Q of N){K.push(Q);if(K.length>=D)break}if(K.length>=D)break}return K.slice(0,D)}function Y(B,D){if(!Array.isArray(B))return"";for(const G of B){if(!G||typeof G!=="object")continue;const K=G;if(String(K.field_uuid??"")!==D)continue;const J=K.value;if(typeof J==="string")return J;if(Array.isArray(J)&&J[0]!=null)return String(J[0])}return""}function Z(B){const D=B.field_values;return D&&typeof D==="object"&&!Array.isArray(D)?D:null}export function getTaskStatusRawId(B){const D=B.field_values,G=Z(B);if(typeof B.status_uuid==="string")return B.status_uuid;return Y(D,"field016")||(G?String(G.field016??""):"")}export function getTaskProjectRawId(B){const D=B.field_values,G=Z(B);if(typeof B.project_uuid==="string")return B.project_uuid;return Y(D,"field006")||(G?String(G.field006??""):"")}export function onesManhourScale(){const B=Number(process.env.ONES_MANHOUR_SCALE?.trim());if(Number.isFinite(B)&&B>0)return B;return 1e5}export function hoursToOnesManhourRaw(B){if(!Number.isFinite(B)||B<=0)return 0;return Math.max(1,Math.round(B*onesManhourScale()))}function V(B){if(!Number.isFinite(B))return"";const D=Math.round(B*1e6)/1e6,G=Math.round(D);if(Math.abs(D-G)<0.00001)return`${G}h`;const K=Math.round(D*10)/10;return Number.isInteger(K)?`${K}h`:`${K.toFixed(1)}h`}function X(B,D){if(D==null||D==="")return null;const G=Number(D);if(!Number.isFinite(G))return null;const K=G/onesManhourScale();return`${B}${V(K)}`}export function formatTaskManhourSummary(B){const D=[],G=X("估",B.assess_manhour),K=X("登",B.total_manhour),J=X("余",B.remaining_manhour);if(G)D.push(G);if(K)D.push(K);if(J)D.push(J);return D.length?D.join(" "):"—"}export function mapTaskEntry(B,D){const G=getTaskStatusRawId(B),K=getTaskProjectRawId(B),J=String(B.uuid??""),N=ellipsizeCell(pickTaskTitle(B)),Q=(W)=>W.length>14?briefUuid(W):W,_=D?.statusByUuid?.get(G)??Q(G),$=D?.projectByUuid?.get(K)??Q(K);return{title:N,status:ellipsizeCell(_,20),project:ellipsizeCell($,40),uuid:J,updated:formatStamp(B.server_update_stamp),工时:ellipsizeCell(formatTaskManhourSummary(B),36)}}export function defaultPeekBody(B){return{with_boards:!1,boards:null,query:B,group_by:"",sort:[{create_time:{order:"desc"}}],include_subtasks:!1,include_status_uuid:!0,include_issue_type:!1,include_project_uuid:!0,is_show_derive:!1}}export function parsePeekLimit(B,D){const G=Number.parseInt(String(B??""),10);if(!Number.isFinite(G)||G<=0)return D;return Math.max(1,Math.min(500,G))}
1
+ import{CliError as d}from"@jackwener/opencli/errors";function m(t){if(!Array.isArray(t))return"";for(const r of t){if(!r||typeof r!=="object")continue;const e=r;if(!String(e.field_uuid??"").startsWith("field"))continue;const n=e.value;if(typeof n==="string"&&n.trim())return n.trim();if(Array.isArray(n)&&n.length&&typeof n[0]==="string"&&n[0].trim())return n[0].trim()}return""}export function pickTaskTitle(t){for(const i of["summary","name","title","subject"]){const n=t[i];if(typeof n==="string"&&n.trim())return n.trim()}const r=m(t.field_values);if(r)return r;const e=t.field_values;if(e&&typeof e==="object"&&!Array.isArray(e)){const i=e;for(const n of["field001","field002","field003"]){const o=i[n];if(typeof o==="string"&&o.trim())return o.trim()}}return""}export function ellipsizeCell(t,r=64){const e=t.trim();if(e.length<=r)return e;return`${e.slice(0,r-1)}…`}export function briefUuid(t,r=6,e=4){if(!t)return"";if(t.length<=r+e+1)return t;return`${t.slice(0,r)}…${t.slice(-e)}`}export function formatStamp(t){if(t==null||t==="")return"";const r=Number(t);if(Number.isNaN(r))return String(t);const e=r>100000000000000?Math.floor(r/1000):r>1000000000000?r:r*1000;try{return new Date(e).toISOString().replace("T"," ").slice(0,19)}catch{return String(t)}}export function flattenPeekGroups(t,r){if(!Array.isArray(t.groups))throw new d("FETCH_ERROR","Unexpected filters/peek response (missing groups)","Try -f json; check team UUID and API version.");const e=t.groups,i=[];for(const n of e){const o=Array.isArray(n.entries)?n.entries:[];for(const u of o){i.push(u);if(i.length>=r)break}if(i.length>=r)break}return i.slice(0,r)}function c(t,r){if(!Array.isArray(t))return"";for(const e of t){if(!e||typeof e!=="object")continue;const i=e;if(String(i.field_uuid??"")!==r)continue;const n=i.value;if(typeof n==="string")return n;if(Array.isArray(n)&&n[0]!=null)return String(n[0])}return""}function a(t){const r=t.field_values;return r&&typeof r==="object"&&!Array.isArray(r)?r:null}export function getTaskStatusRawId(t){const r=t.field_values,e=a(t);if(typeof t.status_uuid==="string")return t.status_uuid;return c(r,"field016")||(e?String(e.field016??""):"")}export function getTaskProjectRawId(t){const r=t.field_values,e=a(t);if(typeof t.project_uuid==="string")return t.project_uuid;return c(r,"field006")||(e?String(e.field006??""):"")}export function onesManhourScale(){const t=Number(process.env.ONES_MANHOUR_SCALE?.trim());if(Number.isFinite(t)&&t>0)return t;return 1e5}export function hoursToOnesManhourRaw(t){if(!Number.isFinite(t)||t<=0)return 0;return Math.max(1,Math.round(t*onesManhourScale()))}function g(t){if(!Number.isFinite(t))return"";const r=Math.round(t*1e6)/1e6,e=Math.round(r);if(Math.abs(r-e)<0.00001)return`${e}h`;const i=Math.round(r*10)/10;return Number.isInteger(i)?`${i}h`:`${i.toFixed(1)}h`}function f(t,r){if(r==null||r==="")return null;const e=Number(r);if(!Number.isFinite(e))return null;const i=e/onesManhourScale();return`${t}${g(i)}`}export function formatTaskManhourSummary(t){const r=[],e=f("估",t.assess_manhour),i=f("登",t.total_manhour),n=f("余",t.remaining_manhour);if(e)r.push(e);if(i)r.push(i);if(n)r.push(n);return r.length?r.join(" "):"—"}export function mapTaskEntry(t,r){const e=getTaskStatusRawId(t),i=getTaskProjectRawId(t),n=String(t.uuid??""),o=ellipsizeCell(pickTaskTitle(t)),u=(s)=>s.length>14?briefUuid(s):s,l=r?.statusByUuid?.get(e)??u(e),p=r?.projectByUuid?.get(i)??u(i);return{title:o,status:ellipsizeCell(l,20),project:ellipsizeCell(p,40),uuid:n,updated:formatStamp(t.server_update_stamp),工时:ellipsizeCell(formatTaskManhourSummary(t),36)}}export function defaultPeekBody(t){return{with_boards:!1,boards:null,query:t,group_by:"",sort:[{create_time:{order:"desc"}}],include_subtasks:!1,include_status_uuid:!0,include_issue_type:!1,include_project_uuid:!0,is_show_derive:!1}}export function parsePeekLimit(t,r){const e=Number.parseInt(String(t??""),10);if(!Number.isFinite(e)||e<=0)return r;return Math.max(1,Math.min(500,e))}
package/clis/ones/task.js CHANGED
@@ -1 +1 @@
1
- import{cli as M,Strategy as Q}from"@jackwener/opencli/registry";import{CliError as x}from"@jackwener/opencli/errors";import{onesFetchInPage as R}from"./common.js";import{formatStamp as V}from"./task-helpers.js";M({site:"ones",name:"task",access:"read",description:"ONES — work item detail (GET team/:team/task/:id/info); id is URL segment after …/task/",domain:"ones.cn",strategy:Q.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"id",type:"str",required:!0,positional:!0,help:"Work item UUID (often 16 chars) from …/task/<id>"},{name:"team",type:"str",required:!1,help:"Team UUID (8 chars from …/team/<team>/…), or set ONES_TEAM_UUID"}],columns:["uuid","summary","number","status_uuid","assign","owner","project_uuid","updated"],func:async(J,z)=>{const B=String(z.id??"").trim();if(!B)throw new x("CONFIG","task id required","Pass the work item uuid from the URL path …/task/<id>");const H=z.team?.trim()||process.env.ONES_TEAM_UUID?.trim()||process.env.ONES_TEAM_ID?.trim();if(!H)throw new x("CONFIG","team UUID required","Use --team <teamUUID> or set ONES_TEAM_UUID (from …/team/<team>/…).");const K=`team/${H}/task/${encodeURIComponent(B)}/info`,q=await R(J,K,{method:"GET"});if(typeof q.uuid!=="string"){const L=typeof q.reason==="string"?q.reason:"Use -f json to inspect response; check id length (often 16) and team.";throw new x("FETCH_ERROR",`ONES task info: ${L}`,"Confirm task uuid and team match the browser URL.")}return[{uuid:String(q.uuid),summary:String(q.summary??""),number:q.number!=null?String(q.number):"",status_uuid:String(q.status_uuid??""),assign:String(q.assign??""),owner:String(q.owner??""),project_uuid:String(q.project_uuid??""),updated:V(q.server_update_stamp)}]}});
1
+ import{cli as m,Strategy as u}from"@jackwener/opencli/registry";import{CliError as e}from"@jackwener/opencli/errors";import{onesFetchInPage as d}from"./common.js";import{formatStamp as p}from"./task-helpers.js";m({site:"ones",name:"task",access:"read",description:"ONES — work item detail (GET team/:team/task/:id/info); id is URL segment after …/task/",domain:"ones.cn",strategy:u.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"id",type:"str",required:!0,positional:!0,help:"Work item UUID (often 16 chars) from …/task/<id>"},{name:"team",type:"str",required:!1,help:"Team UUID (8 chars from …/team/<team>/…), or set ONES_TEAM_UUID"}],columns:["uuid","summary","number","status_uuid","assign","owner","project_uuid","updated"],func:async(s,r)=>{const a=String(r.id??"").trim();if(!a)throw new e("CONFIG","task id required","Pass the work item uuid from the URL path …/task/<id>");const i=r.team?.trim()||process.env.ONES_TEAM_UUID?.trim()||process.env.ONES_TEAM_ID?.trim();if(!i)throw new e("CONFIG","team UUID required","Use --team <teamUUID> or set ONES_TEAM_UUID (from …/team/<team>/…).");const n=`team/${i}/task/${encodeURIComponent(a)}/info`,t=await d(s,n,{method:"GET"});if(typeof t.uuid!=="string"){const o=typeof t.reason==="string"?t.reason:"Use -f json to inspect response; check id length (often 16) and team.";throw new e("FETCH_ERROR",`ONES task info: ${o}`,"Confirm task uuid and team match the browser URL.")}return[{uuid:String(t.uuid),summary:String(t.summary??""),number:t.number!=null?String(t.number):"",status_uuid:String(t.status_uuid??""),assign:String(t.assign??""),owner:String(t.owner??""),project_uuid:String(t.project_uuid??""),updated:p(t.server_update_stamp)}]}});
@@ -1,14 +1,14 @@
1
- import{cli as H,Strategy as b}from"@jackwener/opencli/registry";import{CliError as $}from"@jackwener/opencli/errors";import{gotoOnesHome as S,onesFetchInPageWithMeta as R,resolveOnesUserUuid as M,summarizeOnesError as T}from"./common.js";import{hoursToOnesManhourRaw as y}from"./task-helpers.js";function f(K,V){if(!K||typeof K!=="object")return V>=400?`HTTP ${V}`:null;const J=K;if(Array.isArray(J.errors)&&J.errors.length>0){const Q=J.errors[0];if(Q&&typeof Q==="object"){const X=String(Q.message??"").trim();if(X)return X}return"graphql errors"}if(J.data&&typeof J.data==="object"){const Q=J.data;if(Q.addManhour&&typeof Q.addManhour==="object"){if(!String(Q.addManhour.key??"").trim())return"addManhour returned empty key"}}if(Array.isArray(J.bad_tasks)&&J.bad_tasks.length>0){const Q=J.bad_tasks[0];return String(Q.desc??Q.code??JSON.stringify(Q))}if(typeof J.reason==="string"&&J.reason.trim())return J.reason.trim();const N=J.code;if(N!==void 0&&N!==null){const Q=Number(N);if(Number.isFinite(Q)&&Q!==200&&Q!==0)return`code=${String(N)}`}const Z=J.errcode;if(typeof Z==="string"&&Z&&Z!=="OK")return Z;return null}function I(K){if(!K.ok)return T(K.status,K.parsed);return f(K.parsed,K.status)}function h(){const K=new Date,V=K.getFullYear(),J=String(K.getMonth()+1).padStart(2,"0"),N=String(K.getDate()).padStart(2,"0");return`${V}-${J}-${N}`}function k(K){return/^\d{4}-\d{2}-\d{2}$/.test(K)}function w(K){const J=new Date(`${K}T00:00:00`).getTime();if(!Number.isFinite(J))return 0;return Math.floor(J/1000)}function v(K){if(!K||typeof K!=="object")return null;const J=Number(K.total_manhour);return Number.isFinite(J)?J:null}export function buildAddManhourGraphqlBody(K){const{ownerId:V,taskId:J,startTime:N,rawManhour:Z,note:Q}=K,X=JSON.stringify(Q),x=JSON.stringify(V),G=JSON.stringify(J);return JSON.stringify({query:`mutation AddManhour {
1
+ import{cli as E,Strategy as T}from"@jackwener/opencli/registry";import{CliError as d}from"@jackwener/opencli/errors";import{gotoOnesHome as _,onesFetchInPageWithMeta as k,resolveOnesUserUuid as A,summarizeOnesError as F}from"./common.js";import{hoursToOnesManhourRaw as q}from"./task-helpers.js";function G(e,n){if(!e||typeof e!=="object")return n>=400?`HTTP ${n}`:null;const t=e;if(Array.isArray(t.errors)&&t.errors.length>0){const o=t.errors[0];if(o&&typeof o==="object"){const a=String(o.message??"").trim();if(a)return a}return"graphql errors"}if(t.data&&typeof t.data==="object"){const o=t.data;if(o.addManhour&&typeof o.addManhour==="object"){if(!String(o.addManhour.key??"").trim())return"addManhour returned empty key"}}if(Array.isArray(t.bad_tasks)&&t.bad_tasks.length>0){const o=t.bad_tasks[0];return String(o.desc??o.code??JSON.stringify(o))}if(typeof t.reason==="string"&&t.reason.trim())return t.reason.trim();const r=t.code;if(r!==void 0&&r!==null){const o=Number(r);if(Number.isFinite(o)&&o!==200&&o!==0)return`code=${String(r)}`}const s=t.errcode;if(typeof s==="string"&&s&&s!=="OK")return s;return null}function J(e){if(!e.ok)return F(e.status,e.parsed);return G(e.parsed,e.status)}function C(){const e=new Date,n=e.getFullYear(),t=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0");return`${n}-${t}-${r}`}function Y(e){return/^\d{4}-\d{2}-\d{2}$/.test(e)}function R(e){const t=new Date(`${e}T00:00:00`).getTime();if(!Number.isFinite(t))return 0;return Math.floor(t/1000)}function N(e){if(!e||typeof e!=="object")return null;const t=Number(e.total_manhour);return Number.isFinite(t)?t:null}export function buildAddManhourGraphqlBody(e){const{ownerId:n,taskId:t,startTime:r,rawManhour:s,note:o}=e,a=JSON.stringify(o),u=JSON.stringify(n),m=JSON.stringify(t);return JSON.stringify({query:`mutation AddManhour {
2
2
  addManhour(
3
3
  mode: "simple"
4
- owner: ${x}
5
- task: ${G}
4
+ owner: ${u}
5
+ task: ${m}
6
6
  type: "recorded"
7
- start_time: ${N}
8
- hours: ${Z}
9
- description: ${X}
7
+ start_time: ${r}
8
+ hours: ${s}
9
+ description: ${a}
10
10
  customData: {}
11
11
  ) {
12
12
  key
13
13
  }
14
- }`})}H({site:"ones",name:"worklog",access:"write",description:"ONES — log work hours on a task (defaults to today; use --date to backfill; endpoint falls back by deployment).",domain:"ones.cn",strategy:b.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"task",type:"str",required:!0,positional:!0,help:"Work item UUID (usually 16 chars), from my-tasks or browser URL …/task/<id>"},{name:"hours",type:"str",required:!0,positional:!0,help:"Hours to log for this entry (e.g. 2 or 1.5), converted with ONES_MANHOUR_SCALE"},{name:"team",type:"str",required:!1,help:"Team UUID from URL …/team/<uuid>/…, or set ONES_TEAM_UUID"},{name:"date",type:"str",required:!1,help:"Entry date YYYY-MM-DD, defaults to today (local timezone); use for backfill"},{name:"note",type:"str",required:!1,help:"Optional note (written to description/desc)"},{name:"owner",type:"str",required:!1,help:"Owner user UUID (defaults to current logged-in user)"}],columns:["task","date","hours","owner","endpoint"],func:async(K,V)=>{const J=String(V.task??"").trim();if(!J)throw new $("CONFIG","task uuid required","Pass the work item uuid from ppcli ones my-tasks or the URL.");const N=V.team?.trim()||process.env.ONES_TEAM_UUID?.trim()||process.env.ONES_TEAM_ID?.trim();if(!N)throw new $("CONFIG","team UUID required","Pass --team or set ONES_TEAM_UUID (from …/team/<team>/…).");const Z=Number(String(V.hours??"").replace(/,/g,""));if(!Number.isFinite(Z)||Z<=0||Z>1000)throw new $("CONFIG","hours must be a positive number (hours)","Example: ppcli ones worklog <taskUUID> 2 --team <teamUUID>");const X=V.date?.trim()||h();if(!k(X))throw new $("CONFIG","invalid --date","Use YYYY-MM-DD, e.g. 2026-03-24.");const x=String(V.note??"").trim(),G=y(Z),U=w(X);if(!U)throw new $("CONFIG","invalid date for start_time",`Could not parse date ${X}.`);await S(K);const q=V.owner?.trim()||await M(K,{skipGoto:!0}),z={owner:q,manhour:G,start_date:X,end_date:X,desc:x},Y={owner:q,allManhour:G,startDate:X,endDate:X,desc:x},_=encodeURIComponent(J),A=buildAddManhourGraphqlBody({ownerId:q,taskId:J,startTime:U,rawManhour:G,note:x}),O=[{path:`team/${N}/items/graphql`,body:A},{path:`team/${N}/task/${_}/manhours/add`,body:JSON.stringify(z)},{path:`team/${N}/task/${_}/manhours/add`,body:JSON.stringify(Y)},{path:`team/${N}/task/${_}/manhours/add`,body:JSON.stringify({manhours:[z]})},{path:`team/${N}/task/${_}/manhours/add`,body:JSON.stringify({manhours:[Y]})},{path:`team/${N}/task/${_}/manhour/add`,body:JSON.stringify(z)},{path:`team/${N}/task/${_}/manhour/add`,body:JSON.stringify(Y)},{path:`team/${N}/tasks/update3`,body:JSON.stringify({tasks:[{uuid:J,manhours:[z]}]})}],W=await R(K,`team/${N}/task/${_}/info`,{method:"GET",skipGoto:!0}),B=W.ok?v(W.parsed):null;let D="";for(const{path:P,body:C}of O){const E=await R(K,P,{method:"POST",body:C,skipGoto:!0}),j=I(E);if(!j){const F=await R(K,`team/${N}/task/${_}/info`,{method:"GET",skipGoto:!0});if(F.ok){const L=v(F.parsed);if(B===null?L!==null:L!==null&&Math.abs(L-B)>=1)return[{task:J,date:X,hours:String(Z),owner:q,endpoint:P}];D=`no effect (total_manhour ${String(B)} -> ${String(L)})`;continue}return[{task:J,date:X,hours:String(Z),owner:q,endpoint:P}]}D=j}throw new $("FETCH_ERROR",`ONES worklog: all endpoints failed (last: ${D})`)}});
14
+ }`})}E({site:"ones",name:"worklog",access:"write",description:"ONES — log work hours on a task (defaults to today; use --date to backfill; endpoint falls back by deployment).",domain:"ones.cn",strategy:T.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"task",type:"str",required:!0,positional:!0,help:"Work item UUID (usually 16 chars), from my-tasks or browser URL …/task/<id>"},{name:"hours",type:"str",required:!0,positional:!0,help:"Hours to log for this entry (e.g. 2 or 1.5), converted with ONES_MANHOUR_SCALE"},{name:"team",type:"str",required:!1,help:"Team UUID from URL …/team/<uuid>/…, or set ONES_TEAM_UUID"},{name:"date",type:"str",required:!1,help:"Entry date YYYY-MM-DD, defaults to today (local timezone); use for backfill"},{name:"note",type:"str",required:!1,help:"Optional note (written to description/desc)"},{name:"owner",type:"str",required:!1,help:"Owner user UUID (defaults to current logged-in user)"}],columns:["task","date","hours","owner","endpoint"],func:async(e,n)=>{const t=String(n.task??"").trim();if(!t)throw new d("CONFIG","task uuid required","Pass the work item uuid from ppcli ones my-tasks or the URL.");const r=n.team?.trim()||process.env.ONES_TEAM_UUID?.trim()||process.env.ONES_TEAM_ID?.trim();if(!r)throw new d("CONFIG","team UUID required","Pass --team or set ONES_TEAM_UUID (from …/team/<team>/…).");const s=Number(String(n.hours??"").replace(/,/g,""));if(!Number.isFinite(s)||s<=0||s>1000)throw new d("CONFIG","hours must be a positive number (hours)","Example: ppcli ones worklog <taskUUID> 2 --team <teamUUID>");const a=n.date?.trim()||C();if(!Y(a))throw new d("CONFIG","invalid --date","Use YYYY-MM-DD, e.g. 2026-03-24.");const u=String(n.note??"").trim(),m=q(s),w=R(a);if(!w)throw new d("CONFIG","invalid date for start_time",`Could not parse date ${a}.`);await _(e);const c=n.owner?.trim()||await A(e,{skipGoto:!0}),l={owner:c,manhour:m,start_date:a,end_date:a,desc:u},h={owner:c,allManhour:m,startDate:a,endDate:a,desc:u},i=encodeURIComponent(t),M=buildAddManhourGraphqlBody({ownerId:c,taskId:t,startTime:w,rawManhour:m,note:u}),U=[{path:`team/${r}/items/graphql`,body:M},{path:`team/${r}/task/${i}/manhours/add`,body:JSON.stringify(l)},{path:`team/${r}/task/${i}/manhours/add`,body:JSON.stringify(h)},{path:`team/${r}/task/${i}/manhours/add`,body:JSON.stringify({manhours:[l]})},{path:`team/${r}/task/${i}/manhours/add`,body:JSON.stringify({manhours:[h]})},{path:`team/${r}/task/${i}/manhour/add`,body:JSON.stringify(l)},{path:`team/${r}/task/${i}/manhour/add`,body:JSON.stringify(h)},{path:`team/${r}/tasks/update3`,body:JSON.stringify({tasks:[{uuid:t,manhours:[l]}]})}],S=await k(e,`team/${r}/task/${i}/info`,{method:"GET",skipGoto:!0}),p=S.ok?N(S.parsed):null;let y="";for(const{path:g,body:I}of U){const D=await k(e,g,{method:"POST",body:I,skipGoto:!0}),b=J(D);if(!b){const O=await k(e,`team/${r}/task/${i}/info`,{method:"GET",skipGoto:!0});if(O.ok){const f=N(O.parsed);if(p===null?f!==null:f!==null&&Math.abs(f-p)>=1)return[{task:t,date:a,hours:String(s),owner:c,endpoint:g}];y=`no effect (total_manhour ${String(p)} -> ${String(f)})`;continue}return[{task:t,date:a,hours:String(s),owner:c,endpoint:g}]}y=b}throw new d("FETCH_ERROR",`ONES worklog: all endpoints failed (last: ${y})`)}});
@@ -1 +1 @@
1
- import{cli as u,Strategy as y}from"@jackwener/opencli/registry";import{EmptyResultError as h}from"@jackwener/opencli/errors";import{OPENALEX_BASE as d,appendMailto as m,bareDoi as _,bareId as g,openalexFetch as x,requireBoundedInt as b,requireString as A}from"./utils.js";const f=["id","doi","title","publication_year","publication_date","cited_by_count","authorships","primary_location","open_access","type"].join(",");u({site:"openalex",name:"search",access:"read",description:"Search OpenAlex Works (papers, books, preprints) by keyword",domain:"api.openalex.org",strategy:y.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search text (e.g. "transformers", "open access scholarly")'},{name:"limit",type:"int",default:20,help:"Max works (1-200, single OpenAlex page)"}],columns:["rank","id","title","year","citations","firstAuthor","venue","openAccess","type","doi","url"],func:async(t)=>{const o=A(t.query,"query"),i=b(t.limit,20,200),s=m(`${d}/works?search=${encodeURIComponent(o)}&per-page=${i}&select=${f}`),a=await x(s,"openalex search"),n=Array.isArray(a?.results)?a.results:[];if(!n.length)throw new h("openalex search",`No OpenAlex works matched "${o}".`);return n.slice(0,i).map((e,p)=>{const l=Array.isArray(e.authorships)&&e.authorships.length?String(e.authorships[0]?.author?.display_name??"").trim():"",c=String(e.primary_location?.source?.display_name??"").trim(),r=g(e.id);return{rank:p+1,id:r,title:String(e.title??"").trim(),year:e.publication_year!=null?Number(e.publication_year):null,citations:e.cited_by_count!=null?Number(e.cited_by_count):null,firstAuthor:l,venue:c,openAccess:Boolean(e.open_access?.is_oa),type:String(e.type??"").trim(),doi:_(e.doi),url:r?`https://openalex.org/${r}`:""}})}});
1
+ import{cli as u,Strategy as y}from"@jackwener/opencli/registry";import{EmptyResultError as m}from"@jackwener/opencli/errors";import{OPENALEX_BASE as d,appendMailto as h,bareDoi as _,bareId as b,openalexFetch as g,requireBoundedInt as A,requireString as x}from"./utils.js";const S=["id","doi","title","publication_year","publication_date","cited_by_count","authorships","primary_location","open_access","type"].join(",");u({site:"openalex",name:"search",access:"read",description:"Search OpenAlex Works (papers, books, preprints) by keyword",domain:"api.openalex.org",strategy:y.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search text (e.g. "transformers", "open access scholarly")'},{name:"limit",type:"int",default:20,help:"Max works (1-200, single OpenAlex page)"}],columns:["rank","id","title","year","citations","firstAuthor","venue","openAccess","type","doi","url"],func:async(t)=>{const o=x(t.query,"query"),i=A(t.limit,20,200),s=h(`${d}/works?search=${encodeURIComponent(o)}&per-page=${i}&select=${S}`),a=await g(s,"openalex search"),n=Array.isArray(a?.results)?a.results:[];if(!n.length)throw new m("openalex search",`No OpenAlex works matched "${o}".`);return n.slice(0,i).map((e,l)=>{const c=Array.isArray(e.authorships)&&e.authorships.length?String(e.authorships[0]?.author?.display_name??"").trim():"",p=String(e.primary_location?.source?.display_name??"").trim(),r=b(e.id);return{rank:l+1,id:r,title:String(e.title??"").trim(),year:e.publication_year!=null?Number(e.publication_year):null,citations:e.cited_by_count!=null?Number(e.cited_by_count):null,firstAuthor:c,venue:p,openAccess:Boolean(e.open_access?.is_oa),type:String(e.type??"").trim(),doi:_(e.doi),url:r?`https://openalex.org/${r}`:""}})}});
@@ -1 +1 @@
1
- import{ArgumentError as L,CommandExecutionError as N,EmptyResultError as S}from"@jackwener/opencli/errors";export const OPENALEX_BASE="https://api.openalex.org";const T="opencli-openalex-adapter (+https://github.com/jackwener/OpenCLI)",X=/^W\d{4,}$/,P=/^10\.\S+$/;export function requireString(G,z){const H=String(G??"").trim();if(!H)throw new L(`openalex ${z} cannot be empty`);return H}export function requireBoundedInt(G,z,H,J="limit"){const F=G??z,M=typeof F==="number"?F:Number(F);if(!Number.isInteger(M)||M<=0)throw new L(`openalex ${J} must be a positive integer`);if(M>H)throw new L(`openalex ${J} must be <= ${H}`);return M}export function requireWorkRef(G){const z=String(G??"").trim();if(!z)throw new L('openalex work id is required (e.g. "W2741809807", "10.7717/peerj.4375")');const H=z.match(/^https?:\/\/(?:api\.)?openalex\.org\/(?:works\/)?([WAaSCFwIPwT]\d+)/i);if(H){const F=H[1].toUpperCase();if(F[0]!=="W")throw new L(`openalex work id "${G}" must be a Work (W…) ID, got "${F[0]}…"`);return F}if(X.test(z.toUpperCase()))return z.toUpperCase();if(/^doi:/i.test(z)){const F=z.replace(/^doi:/i,"").trim();if(P.test(F))return`doi:${F}`}const J=z.match(/^https?:\/\/(?:dx\.)?doi\.org\/(.+)$/i);if(J&&P.test(J[1]))return`doi:${J[1]}`;if(P.test(z))return`doi:${z}`;throw new L(`openalex work id "${G}" is not recognised`,'Use a Work id ("W2741809807"), a DOI ("10.7717/peerj.4375"), or a full openalex.org / doi.org URL.')}export async function openalexFetch(G,z){let H;try{H=await fetch(G,{headers:{"user-agent":T,accept:"application/json"}})}catch(F){throw new N(`${z} request failed: ${F?.message??F}`,"Check that api.openalex.org is reachable from this network.")}if(H.status===404)throw new S(z,`OpenAlex returned 404 for ${G}.`);if(H.status===429)throw new N(`${z} returned HTTP 429 (rate limited)`,"OpenAlex throttles unauthenticated traffic; wait a few seconds and retry, or set OPENALEX_MAILTO.");if(!H.ok){let F="";try{const Q=(await H.text()).match(/"message"\s*:\s*"([^"]+)"/);if(Q)F=` (${Q[1]})`}catch{}throw new N(`${z} returned HTTP ${H.status}${F}`)}let J;try{J=await H.json()}catch(F){throw new N(`${z} returned malformed JSON: ${F?.message??F}`)}return J}export function bareId(G){const z=String(G??"").trim();if(!z)return"";return z.replace(/^https?:\/\/(?:api\.)?openalex\.org\//i,"").replace(/^works\//i,"")}export function bareDoi(G){const z=String(G??"").trim();if(!z)return"";return z.replace(/^https?:\/\/(?:dx\.)?doi\.org\//i,"")}export function reconstructAbstract(G){if(!G||typeof G!=="object")return"";const z=[];for(const[H,J]of Object.entries(G)){if(!Array.isArray(J))continue;for(const F of J)if(Number.isInteger(F)&&F>=0&&F<1e5)z[F]=H}return z.filter(Boolean).join(" ").replace(/\s+/g," ").trim()}export function appendMailto(G){const z=process.env.OPENALEX_MAILTO?.trim();if(!z)return G;const H=G.includes("?")?"&":"?";return`${G}${H}mailto=${encodeURIComponent(z)}`}
1
+ import{ArgumentError as i,CommandExecutionError as a,EmptyResultError as u}from"@jackwener/opencli/errors";export const OPENALEX_BASE="https://api.openalex.org";const f="opencli-openalex-adapter (+https://github.com/jackwener/OpenCLI)",d=/^W\d{4,}$/,c=/^10\.\S+$/;export function requireString(r,t){const o=String(r??"").trim();if(!o)throw new i(`openalex ${t} cannot be empty`);return o}export function requireBoundedInt(r,t,o,n="limit"){const e=r??t,s=typeof e==="number"?e:Number(e);if(!Number.isInteger(s)||s<=0)throw new i(`openalex ${n} must be a positive integer`);if(s>o)throw new i(`openalex ${n} must be <= ${o}`);return s}export function requireWorkRef(r){const t=String(r??"").trim();if(!t)throw new i('openalex work id is required (e.g. "W2741809807", "10.7717/peerj.4375")');const o=t.match(/^https?:\/\/(?:api\.)?openalex\.org\/(?:works\/)?([WAaSCFwIPwT]\d+)/i);if(o){const e=o[1].toUpperCase();if(e[0]!=="W")throw new i(`openalex work id "${r}" must be a Work (W…) ID, got "${e[0]}…"`);return e}if(d.test(t.toUpperCase()))return t.toUpperCase();if(/^doi:/i.test(t)){const e=t.replace(/^doi:/i,"").trim();if(c.test(e))return`doi:${e}`}const n=t.match(/^https?:\/\/(?:dx\.)?doi\.org\/(.+)$/i);if(n&&c.test(n[1]))return`doi:${n[1]}`;if(c.test(t))return`doi:${t}`;throw new i(`openalex work id "${r}" is not recognised`,'Use a Work id ("W2741809807"), a DOI ("10.7717/peerj.4375"), or a full openalex.org / doi.org URL.')}export async function openalexFetch(r,t){let o;try{o=await fetch(r,{headers:{"user-agent":f,accept:"application/json"}})}catch(e){throw new a(`${t} request failed: ${e?.message??e}`,"Check that api.openalex.org is reachable from this network.")}if(o.status===404)throw new u(t,`OpenAlex returned 404 for ${r}.`);if(o.status===429)throw new a(`${t} returned HTTP 429 (rate limited)`,"OpenAlex throttles unauthenticated traffic; wait a few seconds and retry, or set OPENALEX_MAILTO.");if(!o.ok){let e="";try{const p=(await o.text()).match(/"message"\s*:\s*"([^"]+)"/);if(p)e=` (${p[1]})`}catch{}throw new a(`${t} returned HTTP ${o.status}${e}`)}let n;try{n=await o.json()}catch(e){throw new a(`${t} returned malformed JSON: ${e?.message??e}`)}return n}export function bareId(r){const t=String(r??"").trim();if(!t)return"";return t.replace(/^https?:\/\/(?:api\.)?openalex\.org\//i,"").replace(/^works\//i,"")}export function bareDoi(r){const t=String(r??"").trim();if(!t)return"";return t.replace(/^https?:\/\/(?:dx\.)?doi\.org\//i,"")}export function reconstructAbstract(r){if(!r||typeof r!=="object")return"";const t=[];for(const[o,n]of Object.entries(r)){if(!Array.isArray(n))continue;for(const e of n)if(Number.isInteger(e)&&e>=0&&e<1e5)t[e]=o}return t.filter(Boolean).join(" ").replace(/\s+/g," ").trim()}export function appendMailto(r){const t=process.env.OPENALEX_MAILTO?.trim();if(!t)return r;const o=r.includes("?")?"&":"?";return`${r}${o}mailto=${encodeURIComponent(t)}`}
@@ -1 +1 @@
1
- import{cli as l,Strategy as p}from"@jackwener/opencli/registry";import{OPENALEX_BASE as d,appendMailto as u,bareDoi as _,bareId as g,openalexFetch as m,reconstructAbstract as b,requireWorkRef as y}from"./utils.js";const f=["id","doi","title","publication_year","publication_date","cited_by_count","authorships","primary_location","open_access","type","referenced_works","related_works","language","abstract_inverted_index"].join(",");l({site:"openalex",name:"work",access:"read",description:"Fetch a single OpenAlex Work (paper / preprint / book) — metadata + abstract",domain:"api.openalex.org",strategy:p.PUBLIC,browser:!1,args:[{name:"id",positional:!0,required:!0,help:'OpenAlex Work id ("W2741809807"), DOI ("10.7717/peerj.4375"), or full URL'}],columns:["id","title","type","year","date","language","authors","venue","citations","openAccess","openAccessUrl","referencedCount","doi","abstract","url"],func:async(t)=>{const o=y(t.id),a=u(`${d}/works/${encodeURIComponent(o)}?select=${f}`),e=await m(a,"openalex work"),n=Array.isArray(e.authorships)?e.authorships.map((c)=>String(c?.author?.display_name??"").trim()).filter(Boolean).join(", "):"",i=String(e.primary_location?.source?.display_name??"").trim(),r=g(e.id),s=String(e.open_access?.oa_url??"").trim();return[{id:r,title:String(e.title??"").trim(),type:String(e.type??"").trim(),year:e.publication_year!=null?Number(e.publication_year):null,date:String(e.publication_date??"").trim(),language:String(e.language??"").trim(),authors:n,venue:i,citations:e.cited_by_count!=null?Number(e.cited_by_count):null,openAccess:Boolean(e.open_access?.is_oa),openAccessUrl:s,referencedCount:Array.isArray(e.referenced_works)?e.referenced_works.length:null,doi:_(e.doi),abstract:b(e.abstract_inverted_index),url:r?`https://openalex.org/${r}`:""}]}});
1
+ import{cli as l,Strategy as p}from"@jackwener/opencli/registry";import{OPENALEX_BASE as u,appendMailto as d,bareDoi as _,bareId as m,openalexFetch as y,reconstructAbstract as g,requireWorkRef as b}from"./utils.js";const h=["id","doi","title","publication_year","publication_date","cited_by_count","authorships","primary_location","open_access","type","referenced_works","related_works","language","abstract_inverted_index"].join(",");l({site:"openalex",name:"work",access:"read",description:"Fetch a single OpenAlex Work (paper / preprint / book) — metadata + abstract",domain:"api.openalex.org",strategy:p.PUBLIC,browser:!1,args:[{name:"id",positional:!0,required:!0,help:'OpenAlex Work id ("W2741809807"), DOI ("10.7717/peerj.4375"), or full URL'}],columns:["id","title","type","year","date","language","authors","venue","citations","openAccess","openAccessUrl","referencedCount","doi","abstract","url"],func:async(t)=>{const a=b(t.id),o=d(`${u}/works/${encodeURIComponent(a)}?select=${h}`),e=await y(o,"openalex work"),n=Array.isArray(e.authorships)?e.authorships.map((c)=>String(c?.author?.display_name??"").trim()).filter(Boolean).join(", "):"",i=String(e.primary_location?.source?.display_name??"").trim(),r=m(e.id),s=String(e.open_access?.oa_url??"").trim();return[{id:r,title:String(e.title??"").trim(),type:String(e.type??"").trim(),year:e.publication_year!=null?Number(e.publication_year):null,date:String(e.publication_date??"").trim(),language:String(e.language??"").trim(),authors:n,venue:i,citations:e.cited_by_count!=null?Number(e.cited_by_count):null,openAccess:Boolean(e.open_access?.is_oa),openAccessUrl:s,referencedCount:Array.isArray(e.referenced_works)?e.referenced_works.length:null,doi:_(e.doi),abstract:g(e.abstract_inverted_index),url:r?`https://openalex.org/${r}`:""}]}});
@@ -1 +1 @@
1
- import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{EmptyResultError as Z}from"@jackwener/opencli/errors";import{OPENFDA_BASE as $,firstOrNull as v,joinOrNull as C,openfdaFetch as D,requireBoundedInt as I,requireString as P}from"./utils.js";X({site:"openfda",name:"drug-label",access:"read",description:"Search FDA-approved drug labels (brand or generic name)",domain:"fda.gov",strategy:Y.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Brand or generic drug name (e.g. "aspirin", "lisinopril")'},{name:"limit",type:"int",default:5,help:"Max rows (1-25, default 5; openFDA caps anonymous tier at 25/page)"}],columns:["rank","id","brandName","genericName","manufacturer","productType","route","productNdc","pharmClass","purpose","indications","warnings","dosage","effectiveTime"],func:async(H)=>{const G=P(H.query,"query"),L=I(H.limit,5,25),M=`openfda.brand_name:"${G}"`,Q=`openfda.generic_name:"${G}"`,T=`${encodeURIComponent(M)}+OR+${encodeURIComponent(Q)}`,U=`${$}/drug/label.json?search=${T}&limit=${L}`,J=await D(U,"openfda drug-label"),K=Array.isArray(J?.results)?J.results:[];if(!K.length)throw new Z("openfda drug-label",`openFDA returned no labels matching "${G}".`);return K.map((z,V)=>{const x=z?.openfda??{},W=v(x.pharm_class_epc)??v(x.pharm_class_moa)??v(x.pharm_class_cs)??v(x.pharm_class_pe);return{rank:V+1,id:z?.id??null,brandName:v(x.brand_name),genericName:v(x.generic_name),manufacturer:v(x.manufacturer_name),productType:v(x.product_type),route:C(x.route),productNdc:v(x.product_ndc),pharmClass:W,purpose:v(z.purpose),indications:v(z.indications_and_usage),warnings:v(z.warnings),dosage:v(z.dosage_and_administration),effectiveTime:z?.effective_time??null}})}});
1
+ import{cli as g,Strategy as f}from"@jackwener/opencli/registry";import{EmptyResultError as _}from"@jackwener/opencli/errors";import{OPENFDA_BASE as y,firstOrNull as e,joinOrNull as h,openfdaFetch as b,requireBoundedInt as N,requireString as w}from"./utils.js";g({site:"openfda",name:"drug-label",access:"read",description:"Search FDA-approved drug labels (brand or generic name)",domain:"fda.gov",strategy:f.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Brand or generic drug name (e.g. "aspirin", "lisinopril")'},{name:"limit",type:"int",default:5,help:"Max rows (1-25, default 5; openFDA caps anonymous tier at 25/page)"}],columns:["rank","id","brandName","genericName","manufacturer","productType","route","productNdc","pharmClass","purpose","indications","warnings","dosage","effectiveTime"],func:async(o)=>{const n=w(o.query,"query"),s=N(o.limit,5,25),c=`openfda.brand_name:"${n}"`,d=`openfda.generic_name:"${n}"`,u=`${encodeURIComponent(c)}+OR+${encodeURIComponent(d)}`,p=`${y}/drug/label.json?search=${u}&limit=${s}`,t=await b(p,"openfda drug-label"),i=Array.isArray(t?.results)?t.results:[];if(!i.length)throw new _("openfda drug-label",`openFDA returned no labels matching "${n}".`);return i.map((a,l)=>{const r=a?.openfda??{},m=e(r.pharm_class_epc)??e(r.pharm_class_moa)??e(r.pharm_class_cs)??e(r.pharm_class_pe);return{rank:l+1,id:a?.id??null,brandName:e(r.brand_name),genericName:e(r.generic_name),manufacturer:e(r.manufacturer_name),productType:e(r.product_type),route:h(r.route),productNdc:e(r.product_ndc),pharmClass:m,purpose:e(a.purpose),indications:e(a.indications_and_usage),warnings:e(a.warnings),dosage:e(a.dosage_and_administration),effectiveTime:a?.effective_time??null}})}});
@@ -1 +1 @@
1
- import{cli as Q,Strategy as T}from"@jackwener/opencli/registry";import{EmptyResultError as U}from"@jackwener/opencli/errors";import{OPENFDA_BASE as V,openfdaFetch as W,requireBoundedInt as X}from"./utils.js";Q({site:"openfda",name:"food-recall",access:"read",description:"FDA food recall and enforcement actions (most recent first)",domain:"fda.gov",strategy:T.PUBLIC,browser:!1,args:[{name:"query",help:'Free-text Lucene query (e.g. "salmonella", "listeria"); default: all recent recalls'},{name:"status",help:'Filter by status: "Ongoing", "Completed", "Terminated"'},{name:"classification",help:'Filter by class: "Class I" (most serious), "Class II", "Class III"'},{name:"limit",type:"int",default:10,help:"Max rows (1-100, default 10; openFDA caps anonymous tier at 100/page)"}],columns:["rank","recallNumber","status","classification","voluntary","recallingFirm","city","state","country","productDescription","reasonForRecall","productQuantity","distributionPattern","reportDate","recallInitiationDate","terminationDate"],func:async(x)=>{const C=X(x.limit,10,100),z=[];if(x.query)z.push(String(x.query).trim());if(x.status)z.push(`status:"${String(x.status).trim()}"`);if(x.classification)z.push(`classification:"${String(x.classification).trim()}"`);const J=z.length?`search=${z.map((v)=>encodeURIComponent(v)).join("+AND+")}&limit=${C}`:`limit=${C}`,K=`${V}/food/enforcement.json?${J}`,G=await W(K,"openfda food-recall"),H=Array.isArray(G?.results)?G.results:[];if(!H.length)throw new U("openfda food-recall","openFDA returned no food recall records matching the filter.");return H.map((v,M)=>({rank:M+1,recallNumber:v?.recall_number??null,status:v?.status??null,classification:v?.classification??null,voluntary:v?.voluntary_mandated??null,recallingFirm:v?.recalling_firm??null,city:v?.city??null,state:v?.state??null,country:v?.country??null,productDescription:v?.product_description??null,reasonForRecall:v?.reason_for_recall??null,productQuantity:v?.product_quantity??null,distributionPattern:v?.distribution_pattern??null,reportDate:v?.report_date??null,recallInitiationDate:v?.recall_initiation_date??null,terminationDate:v?.termination_date??null}))}});
1
+ import{cli as c,Strategy as u}from"@jackwener/opencli/registry";import{EmptyResultError as m}from"@jackwener/opencli/errors";import{OPENFDA_BASE as d,openfdaFetch as p,requireBoundedInt as f}from"./utils.js";c({site:"openfda",name:"food-recall",access:"read",description:"FDA food recall and enforcement actions (most recent first)",domain:"fda.gov",strategy:u.PUBLIC,browser:!1,args:[{name:"query",help:'Free-text Lucene query (e.g. "salmonella", "listeria"); default: all recent recalls'},{name:"status",help:'Filter by status: "Ongoing", "Completed", "Terminated"'},{name:"classification",help:'Filter by class: "Class I" (most serious), "Class II", "Class III"'},{name:"limit",type:"int",default:10,help:"Max rows (1-100, default 10; openFDA caps anonymous tier at 100/page)"}],columns:["rank","recallNumber","status","classification","voluntary","recallingFirm","city","state","country","productDescription","reasonForRecall","productQuantity","distributionPattern","reportDate","recallInitiationDate","terminationDate"],func:async(e)=>{const a=f(e.limit,10,100),n=[];if(e.query)n.push(String(e.query).trim());if(e.status)n.push(`status:"${String(e.status).trim()}"`);if(e.classification)n.push(`classification:"${String(e.classification).trim()}"`);const o=n.length?`search=${n.map((t)=>encodeURIComponent(t)).join("+AND+")}&limit=${a}`:`limit=${a}`,r=`${d}/food/enforcement.json?${o}`,l=await p(r,"openfda food-recall"),i=Array.isArray(l?.results)?l.results:[];if(!i.length)throw new m("openfda food-recall","openFDA returned no food recall records matching the filter.");return i.map((t,s)=>({rank:s+1,recallNumber:t?.recall_number??null,status:t?.status??null,classification:t?.classification??null,voluntary:t?.voluntary_mandated??null,recallingFirm:t?.recalling_firm??null,city:t?.city??null,state:t?.state??null,country:t?.country??null,productDescription:t?.product_description??null,reasonForRecall:t?.reason_for_recall??null,productQuantity:t?.product_quantity??null,distributionPattern:t?.distribution_pattern??null,reportDate:t?.report_date??null,recallInitiationDate:t?.recall_initiation_date??null,terminationDate:t?.termination_date??null}))}});
@@ -1 +1 @@
1
- import{ArgumentError as H,EmptyResultError as I,CommandExecutionError as G}from"@jackwener/opencli/errors";export const OPENFDA_BASE="https://api.fda.gov";const J="opencli-openfda/1.0";export function requireString(q,z){if(typeof q!=="string"||!q.trim())throw new H(`--${z} is required`);return q.trim()}export function requireBoundedInt(q,z,B,F="limit"){const D=q==null||q===""?z:Number(q);if(!Number.isInteger(D)||D<1||D>B)throw new H(`--${F} must be an integer between 1 and ${B}`);return D}export async function openfdaFetch(q,z){let B;try{B=await fetch(q,{headers:{"User-Agent":J,accept:"application/json"}})}catch(D){throw new G(`${z} request failed: ${D.message}`)}if(B.status===404)throw new I(z,`${z} returned 404 (no matches).`);if(B.status===429)throw new G(`${z} rate-limited (HTTP 429); back off and retry.`);if(!B.ok)throw new G(`${z} returned HTTP ${B.status}.`);let F;try{F=await B.json()}catch(D){throw new G(`${z} returned non-JSON body: ${D.message}`)}return F}export function firstOrNull(q){if(!Array.isArray(q)||!q.length)return null;const z=q[0];if(typeof z!=="string")return z??null;const B=z.trim();return B.length?B:null}export function joinOrNull(q,z=5){if(!Array.isArray(q)||!q.length)return null;return q.slice(0,z).map(String).join(", ")}
1
+ import{ArgumentError as s,EmptyResultError as u,CommandExecutionError as i}from"@jackwener/opencli/errors";export const OPENFDA_BASE="https://api.fda.gov";const c="opencli-openfda/1.0";export function requireString(t,r){if(typeof t!=="string"||!t.trim())throw new s(`--${r} is required`);return t.trim()}export function requireBoundedInt(t,r,e,o="limit"){const n=t==null||t===""?r:Number(t);if(!Number.isInteger(n)||n<1||n>e)throw new s(`--${o} must be an integer between 1 and ${e}`);return n}export async function openfdaFetch(t,r){let e;try{e=await fetch(t,{headers:{"User-Agent":c,accept:"application/json"}})}catch(n){throw new i(`${r} request failed: ${n.message}`)}if(e.status===404)throw new u(r,`${r} returned 404 (no matches).`);if(e.status===429)throw new i(`${r} rate-limited (HTTP 429); back off and retry.`);if(!e.ok)throw new i(`${r} returned HTTP ${e.status}.`);let o;try{o=await e.json()}catch(n){throw new i(`${r} returned non-JSON body: ${n.message}`)}return o}export function firstOrNull(t){if(!Array.isArray(t)||!t.length)return null;const r=t[0];if(typeof r!=="string")return r??null;const e=r.trim();return e.length?e:null}export function joinOrNull(t,r=5){if(!Array.isArray(t)||!t.length)return null;return t.slice(0,r).map(String).join(", ")}
@@ -1 +1 @@
1
- import{cli as u,Strategy as l}from"@jackwener/opencli/registry";import{EmptyResultError as d}from"@jackwener/opencli/errors";import{noteToRow as h,openreviewFetch as f,requireBoundedInt as c,requireProfileId as m}from"./utils.js";u({site:"openreview",name:"author",access:"read",description:"List OpenReview submissions by an author profile id (newest first)",domain:"openreview.net",strategy:l.PUBLIC,browser:!1,args:[{name:"profile",positional:!0,required:!0,help:'OpenReview profile id (e.g. "~Yoshua_Bengio1"). Find it on the author profile URL on openreview.net.'},{name:"limit",type:"int",default:50,help:"Max submissions (1-1000)"}],columns:["rank","id","title","authors","venue","pdate","url"],func:async(t)=>{const i=m(t.profile),o=c(t.limit,50,1000),s=`/notes?content.authorids=${encodeURIComponent(i)}&limit=${o}&sort=cdate:desc`,r=await f(s,`openreview author ${i}`),n=Array.isArray(r?.notes)?r.notes:[];if(!n.length)throw new d("openreview author",`No OpenReview submissions found for profile "${i}". Confirm the id format (~First_LastN) and that the profile has public submissions.`);return n.slice(0,o).map((a,p)=>{const e=h(a);return{rank:p+1,id:e.id,title:e.title,authors:e.authors,venue:e.venue,pdate:e.pdate,url:e.url}})}});
1
+ import{cli as p,Strategy as l}from"@jackwener/opencli/registry";import{EmptyResultError as d}from"@jackwener/opencli/errors";import{noteToRow as m,openreviewFetch as f,requireBoundedInt as h,requireProfileId as c}from"./utils.js";p({site:"openreview",name:"author",access:"read",description:"List OpenReview submissions by an author profile id (newest first)",domain:"openreview.net",strategy:l.PUBLIC,browser:!1,args:[{name:"profile",positional:!0,required:!0,help:'OpenReview profile id (e.g. "~Yoshua_Bengio1"). Find it on the author profile URL on openreview.net.'},{name:"limit",type:"int",default:50,help:"Max submissions (1-1000)"}],columns:["rank","id","title","authors","venue","pdate","url"],func:async(o)=>{const t=c(o.profile),i=h(o.limit,50,1000),s=`/notes?content.authorids=${encodeURIComponent(t)}&limit=${i}&sort=cdate:desc`,r=await f(s,`openreview author ${t}`),n=Array.isArray(r?.notes)?r.notes:[];if(!n.length)throw new d("openreview author",`No OpenReview submissions found for profile "${t}". Confirm the id format (~First_LastN) and that the profile has public submissions.`);return n.slice(0,i).map((a,u)=>{const e=m(a);return{rank:u+1,id:e.id,title:e.title,authors:e.authors,venue:e.venue,pdate:e.pdate,url:e.url}})}});
@@ -1 +1 @@
1
- import{cli as i,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as s}from"@jackwener/opencli/errors";import{noteToRow as d,openreviewFetch as u,requireForumId as m}from"./utils.js";i({site:"openreview",name:"paper",access:"read",description:"Show full metadata for a single OpenReview paper",domain:"openreview.net",strategy:p.PUBLIC,browser:!1,args:[{name:"id",positional:!0,required:!0,help:'OpenReview note id (e.g. "5sRnsubyAK")'}],columns:["id","title","authors","keywords","venue","venueid","primary_area","abstract","pdate","pdf","url"],func:async(a)=>{const r=m(a.id),n=`/notes?id=${encodeURIComponent(r)}`,t=await u(n,`openreview paper ${r}`),o=Array.isArray(t?.notes)?t.notes:[];if(!o.length)throw new s("openreview",`No paper found with id "${r}". Confirm the forum/note id from openreview.net.`);const e=d(o[0]);return[{id:e.id,title:e.title,authors:e.authors,keywords:e.keywords,venue:e.venue,venueid:e.venueid,primary_area:e.primary_area,abstract:e.abstract,pdate:e.pdate,pdf:e.pdf,url:e.url}]}});
1
+ import{cli as i,Strategy as s}from"@jackwener/opencli/registry";import{EmptyResultError as p}from"@jackwener/opencli/errors";import{noteToRow as d,openreviewFetch as u,requireForumId as m}from"./utils.js";i({site:"openreview",name:"paper",access:"read",description:"Show full metadata for a single OpenReview paper",domain:"openreview.net",strategy:s.PUBLIC,browser:!1,args:[{name:"id",positional:!0,required:!0,help:'OpenReview note id (e.g. "5sRnsubyAK")'}],columns:["id","title","authors","keywords","venue","venueid","primary_area","abstract","pdate","pdf","url"],func:async(n)=>{const r=m(n.id),a=`/notes?id=${encodeURIComponent(r)}`,t=await u(a,`openreview paper ${r}`),o=Array.isArray(t?.notes)?t.notes:[];if(!o.length)throw new p("openreview",`No paper found with id "${r}". Confirm the forum/note id from openreview.net.`);const e=d(o[0]);return[{id:e.id,title:e.title,authors:e.authors,keywords:e.keywords,venue:e.venue,venueid:e.venueid,primary_area:e.primary_area,abstract:e.abstract,pdate:e.pdate,pdf:e.pdf,url:e.url}]}});
@@ -1,4 +1,4 @@
1
- import{cli as _,Strategy as A}from"@jackwener/opencli/registry";import{ArgumentError as N,EmptyResultError as T}from"@jackwener/opencli/errors";import{coerceInt as k,openreviewFetch as $,readContent as Y,requireForumId as b}from"./utils.js";const j=[["summary","Summary"],["strengths","Strengths"],["weaknesses","Weaknesses"],["questions","Questions"],["comment","Comment"],["rebuttal","Rebuttal"],["decision","Decision"],["recommendation","Recommendation"],["title","Title"],["abstract","Abstract"],["withdrawal_confirmation","Withdrawal confirmation"]];function C(B){if(!Array.isArray(B))return"";for(const z of B){const G=String(z).match(/\/-\/([^/]+)$/);if(G)return G[1]}return""}function J(B,z){if(z)return"PAPER";const G=C(B?.invitations).toLowerCase();if(G.includes("decision"))return"DECISION";if(G.includes("withdrawal"))return"WITHDRAWAL";if(G.includes("rebuttal"))return"REBUTTAL";if(G.includes("meta"))return"META_REVIEW";if(G.includes("review"))return"REVIEW";if(G.includes("comment"))return"COMMENT";return G?G.toUpperCase():"NOTE"}function R(B){if(!Array.isArray(B)||!B.length)return"";const z=String(B[0]);if(z.startsWith("~"))return z.replace(/^~/,"").replace(/\d+$/,"").replace(/_/g," ").trim();const G=z.split("/");return G[G.length-1]||z}function w(B){const z=[];for(const[G,Q]of j){const K=Y(B,G);if(K===void 0||K===null)continue;const U=(Array.isArray(K)?K.join(", "):String(K)).replace(/\r\n/g,`
2
- `).trim();if(!U)continue;z.push(`${Q}: ${U}`)}return z.join(`
1
+ import{cli as y,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentError as A,EmptyResultError as E}from"@jackwener/opencli/errors";import{coerceInt as S,openreviewFetch as l,readContent as m,requireForumId as I}from"./utils.js";const R=[["summary","Summary"],["strengths","Strengths"],["weaknesses","Weaknesses"],["questions","Questions"],["comment","Comment"],["rebuttal","Rebuttal"],["decision","Decision"],["recommendation","Recommendation"],["title","Title"],["abstract","Abstract"],["withdrawal_confirmation","Withdrawal confirmation"]];function C(t){if(!Array.isArray(t))return"";for(const e of t){const n=String(e).match(/\/-\/([^/]+)$/);if(n)return n[1]}return""}function b(t,e){if(e)return"PAPER";const n=C(t?.invitations).toLowerCase();if(n.includes("decision"))return"DECISION";if(n.includes("withdrawal"))return"WITHDRAWAL";if(n.includes("rebuttal"))return"REBUTTAL";if(n.includes("meta"))return"META_REVIEW";if(n.includes("review"))return"REVIEW";if(n.includes("comment"))return"COMMENT";return n?n.toUpperCase():"NOTE"}function N(t){if(!Array.isArray(t)||!t.length)return"";const e=String(t[0]);if(e.startsWith("~"))return e.replace(/^~/,"").replace(/\d+$/,"").replace(/_/g," ").trim();const n=e.split("/");return n[n.length-1]||e}function T(t){const e=[];for(const[n,i]of R){const o=m(t,n);if(o===void 0||o===null)continue;const s=(Array.isArray(o)?o.join(", "):String(o)).replace(/\r\n/g,`
2
+ `).trim();if(!s)continue;e.push(`${i}: ${s}`)}return e.join(`
3
3
 
4
- `)}function E(B,z){if(B.length<=z)return B;return`${B.slice(0,z-3)}...`}_({site:"openreview",name:"reviews",access:"read",description:"Show full review thread (paper + reviews + decisions) for an OpenReview forum",domain:"openreview.net",strategy:A.PUBLIC,browser:!1,args:[{name:"forum",positional:!0,required:!0,help:"OpenReview forum id (same as paper id)"},{name:"max-length",type:"int",default:4000,help:"Per-row text truncation (min 200)"}],columns:["type","author","rating","confidence","text"],func:async(B)=>{const z=b(B.forum,"forum"),G=B["max-length"]??B.maxLength??4000,Q=k(G);if(!Number.isInteger(Q)||Q<200)throw new N("openreview reviews max-length must be an integer >= 200");const K=await $(`/notes?id=${encodeURIComponent(z)}`,`openreview paper ${z}`),U=(Array.isArray(K?.notes)?K.notes:[])[0];if(!U)throw new T("openreview",`No forum found with id "${z}". Confirm the forum id from openreview.net.`);const Z=await $(`/notes?forum=${encodeURIComponent(z)}&details=replies&limit=1000`,`openreview reviews ${z}`),D=[...Array.isArray(Z?.notes)?Z.notes.filter((H)=>H?.id!==z):[]].sort((H,V)=>(H?.cdate??0)-(V?.cdate??0));return[U,...D].map((H)=>{const V=H?.id===z,M=J(H,V),O=R(H?.signatures),W=Y(H?.content,"rating"),X=Y(H?.content,"confidence"),P=E(w(H?.content),Q);return{type:M,author:O,rating:W===void 0||W===null?"":String(W),confidence:X===void 0||X===null?"":String(X),text:P}})}});
4
+ `)}function x(t,e){if(t.length<=e)return t;return`${t.slice(0,e-3)}...`}y({site:"openreview",name:"reviews",access:"read",description:"Show full review thread (paper + reviews + decisions) for an OpenReview forum",domain:"openreview.net",strategy:v.PUBLIC,browser:!1,args:[{name:"forum",positional:!0,required:!0,help:"OpenReview forum id (same as paper id)"},{name:"max-length",type:"int",default:4000,help:"Per-row text truncation (min 200)"}],columns:["type","author","rating","confidence","text"],func:async(t)=>{const e=I(t.forum,"forum"),n=t["max-length"]??t.maxLength??4000,i=S(n);if(!Number.isInteger(i)||i<200)throw new A("openreview reviews max-length must be an integer >= 200");const o=await l(`/notes?id=${encodeURIComponent(e)}`,`openreview paper ${e}`),s=(Array.isArray(o?.notes)?o.notes:[])[0];if(!s)throw new E("openreview",`No forum found with id "${e}". Confirm the forum id from openreview.net.`);const f=await l(`/notes?forum=${encodeURIComponent(e)}&details=replies&limit=1000`,`openreview reviews ${e}`),p=[...Array.isArray(f?.notes)?f.notes.filter((r)=>r?.id!==e):[]].sort((r,a)=>(r?.cdate??0)-(a?.cdate??0));return[s,...p].map((r)=>{const a=r?.id===e,w=b(r,a),h=N(r?.signatures),c=m(r?.content,"rating"),u=m(r?.content,"confidence"),g=x(T(r?.content),i);return{type:w,author:h,rating:c===void 0||c===null?"":String(c),confidence:u===void 0||u===null?"":String(u),text:g}})}});
@@ -1 +1 @@
1
- import{cli as u,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as c,EmptyResultError as l}from"@jackwener/opencli/errors";import{noteToRow as d,openreviewFetch as w,requireBoundedInt as h}from"./utils.js";u({site:"openreview",name:"search",access:"read",description:"Search OpenReview papers by free-text query",domain:"openreview.net",strategy:m.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g. "diffusion model")'},{name:"limit",type:"int",default:25,help:"Max results (max 50)"}],columns:["rank","id","title","authors","venue","pdate","url"],func:async(t)=>{const r=String(t.query??"").trim();if(!r)throw new c("openreview search query cannot be empty");const n=h(t.limit,25,50),a=`/notes/search?term=${encodeURIComponent(r)}&type=terms&limit=${n}`,o=await w(a,"openreview search"),i=Array.isArray(o?.notes)?o.notes:[];if(!i.length)throw new l("openreview",`No papers found for "${r}". Try a different keyword.`);return i.slice(0,n).map((s,p)=>{const e=d(s);return{rank:p+1,id:e.id,title:e.title,authors:e.authors,venue:e.venue,pdate:e.pdate,url:e.url}})}});
1
+ import{cli as u,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as c,EmptyResultError as l}from"@jackwener/opencli/errors";import{noteToRow as d,openreviewFetch as w,requireBoundedInt as y}from"./utils.js";u({site:"openreview",name:"search",access:"read",description:"Search OpenReview papers by free-text query",domain:"openreview.net",strategy:m.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g. "diffusion model")'},{name:"limit",type:"int",default:25,help:"Max results (max 50)"}],columns:["rank","id","title","authors","venue","pdate","url"],func:async(t)=>{const r=String(t.query??"").trim();if(!r)throw new c("openreview search query cannot be empty");const n=y(t.limit,25,50),a=`/notes/search?term=${encodeURIComponent(r)}&type=terms&limit=${n}`,o=await w(a,"openreview search"),i=Array.isArray(o?.notes)?o.notes:[];if(!i.length)throw new l("openreview",`No papers found for "${r}". Try a different keyword.`);return i.slice(0,n).map((s,p)=>{const e=d(s);return{rank:p+1,id:e.id,title:e.title,authors:e.authors,venue:e.venue,pdate:e.pdate,url:e.url}})}});
@@ -1 +1 @@
1
- import{ArgumentError as U,CommandExecutionError as Z}from"@jackwener/opencli/errors";export const OPENREVIEW_API="https://api2.openreview.net",OPENREVIEW_BASE="https://openreview.net";const $=/^[A-Za-z0-9_-]{6,20}$/;export function coerceInt(z){if(z===void 0||z===null||z==="")return NaN;const q=typeof z==="number"?z:Number(z);return Number.isFinite(q)&&Number.isInteger(q)?q:NaN}export function requireBoundedInt(z,q,G,J="limit"){const Q=coerceInt(z??q);if(!Number.isInteger(Q)||Q<=0)throw new U(`openreview ${J} must be a positive integer`);if(Q>G)throw new U(`openreview ${J} must be <= ${G}`);return Q}export function requireNonNegativeInt(z,q,G="offset"){const H=coerceInt(z??q);if(!Number.isInteger(H)||H<0)throw new U(`openreview ${G} must be a non-negative integer`);return H}export function requireForumId(z,q="id"){const G=String(z??"").trim();if(!G)throw new U(`openreview ${q} is required`);if(!$.test(G))throw new U(`openreview ${q} "${z}" is not a valid forum id (expected 6-20 chars of [A-Za-z0-9_-])`);return G}const F=/^~(?=.*\p{L})[\p{L}\p{M}0-9._-]+\d+$/u;export function requireProfileId(z,q="profile"){const G=String(z??"").trim();if(!G)throw new U(`openreview ${q} is required`);if(!F.test(G))throw new U(`openreview ${q} "${z}" is not a valid profile id (expected "~First_Last1" or similar; find it on the author's openreview.net profile URL)`);return G}export async function openreviewFetch(z,q){const G=`${OPENREVIEW_API}${z}`;let J;try{J=await fetch(G)}catch(K){throw new Z(`Network failure fetching ${q}: ${K?.message??K}`,"Check your network connection and try again.")}if(J.status===404)return null;if(!J.ok){let K="";try{K=(await J.text()).slice(0,200)}catch{}throw new Z(`OpenReview API HTTP ${J.status} for ${q}${K?` (${K})`:""}`,"The OpenReview API may be down or rate-limiting.")}let H;try{H=await J.json()}catch(K){throw new Z(`Malformed JSON from OpenReview for ${q}: ${K?.message??K}`,"Try again or report this as an OpenReview API bug.")}const Q=Array.isArray(H?.errors)?H.errors.filter(Boolean):[],X=typeof H?.error==="string"?H.error.trim():"";if(Q.length||X){const K=X||Q.map((Y)=>{if(typeof Y==="string")return Y;if(Y?.message)return String(Y.message);return JSON.stringify(Y)}).join("; ");throw new Z(`OpenReview API error for ${q}: ${K}`,"The OpenReview API returned an application-level error.")}return H}export function formatDate(z){if(typeof z!=="number"||!Number.isFinite(z)||z<=0)return"";return new Date(z).toISOString().slice(0,10)}export function readContent(z,q){const G=z?.[q]?.value;if(G===void 0||G===null)return;return G}export function absolutePdf(z){const q=String(z??"").trim();if(!q)return"";if(/^https?:\/\//.test(q))return q;if(q.startsWith("/"))return`${OPENREVIEW_BASE}${q}`;return`${OPENREVIEW_BASE}/${q}`}function M(z){return String(z||"").replace(/^~/,"").replace(/\d+$/,"").replace(/_/g," ").trim()}export function noteToRow(z){const q=z?.content??{},G=z?.id??"",J=readContent(q,"authors"),H=readContent(q,"authorids");let Q="";if(Array.isArray(J)&&J.length)Q=J.join(", ");else if(Array.isArray(H)&&H.length)Q=H.map(M).join(", ");const X=readContent(q,"keywords"),K=Array.isArray(X)?X.join(", "):String(X??"");return{id:G,title:String(readContent(q,"title")??"").replace(/\s+/g," ").trim(),authors:Q,keywords:K,venue:String(readContent(q,"venue")??"").trim(),venueid:String(readContent(q,"venueid")??"").trim(),primary_area:String(readContent(q,"primary_area")??"").trim(),abstract:String(readContent(q,"abstract")??"").replace(/\s+/g," ").trim(),pdate:formatDate(z?.pdate??z?.cdate),pdf:absolutePdf(readContent(q,"pdf")),url:G?`${OPENREVIEW_BASE}/forum?id=${G}`:""}}
1
+ import{ArgumentError as a,CommandExecutionError as p}from"@jackwener/opencli/errors";export const OPENREVIEW_API="https://api2.openreview.net",OPENREVIEW_BASE="https://openreview.net";const f=/^[A-Za-z0-9_-]{6,20}$/;export function coerceInt(r){if(r===void 0||r===null||r==="")return NaN;const e=typeof r==="number"?r:Number(r);return Number.isFinite(e)&&Number.isInteger(e)?e:NaN}export function requireBoundedInt(r,e,t,i="limit"){const s=coerceInt(r??e);if(!Number.isInteger(s)||s<=0)throw new a(`openreview ${i} must be a positive integer`);if(s>t)throw new a(`openreview ${i} must be <= ${t}`);return s}export function requireNonNegativeInt(r,e,t="offset"){const n=coerceInt(r??e);if(!Number.isInteger(n)||n<0)throw new a(`openreview ${t} must be a non-negative integer`);return n}export function requireForumId(r,e="id"){const t=String(r??"").trim();if(!t)throw new a(`openreview ${e} is required`);if(!f.test(t))throw new a(`openreview ${e} "${r}" is not a valid forum id (expected 6-20 chars of [A-Za-z0-9_-])`);return t}const w=/^~(?=.*\p{L})[\p{L}\p{M}0-9._-]+\d+$/u;export function requireProfileId(r,e="profile"){const t=String(r??"").trim();if(!t)throw new a(`openreview ${e} is required`);if(!w.test(t))throw new a(`openreview ${e} "${r}" is not a valid profile id (expected "~First_Last1" or similar; find it on the author's openreview.net profile URL)`);return t}export async function openreviewFetch(r,e){const t=`${OPENREVIEW_API}${r}`;let i;try{i=await fetch(t)}catch(o){throw new p(`Network failure fetching ${e}: ${o?.message??o}`,"Check your network connection and try again.")}if(i.status===404)return null;if(!i.ok){let o="";try{o=(await i.text()).slice(0,200)}catch{}throw new p(`OpenReview API HTTP ${i.status} for ${e}${o?` (${o})`:""}`,"The OpenReview API may be down or rate-limiting.")}let n;try{n=await i.json()}catch(o){throw new p(`Malformed JSON from OpenReview for ${e}: ${o?.message??o}`,"Try again or report this as an OpenReview API bug.")}const s=Array.isArray(n?.errors)?n.errors.filter(Boolean):[],u=typeof n?.error==="string"?n.error.trim():"";if(s.length||u){const o=u||s.map((c)=>{if(typeof c==="string")return c;if(c?.message)return String(c.message);return JSON.stringify(c)}).join("; ");throw new p(`OpenReview API error for ${e}: ${o}`,"The OpenReview API returned an application-level error.")}return n}export function formatDate(r){if(typeof r!=="number"||!Number.isFinite(r)||r<=0)return"";return new Date(r).toISOString().slice(0,10)}export function readContent(r,e){const t=r?.[e]?.value;if(t===void 0||t===null)return;return t}export function absolutePdf(r){const e=String(r??"").trim();if(!e)return"";if(/^https?:\/\//.test(e))return e;if(e.startsWith("/"))return`${OPENREVIEW_BASE}${e}`;return`${OPENREVIEW_BASE}/${e}`}function d(r){return String(r||"").replace(/^~/,"").replace(/\d+$/,"").replace(/_/g," ").trim()}export function noteToRow(r){const e=r?.content??{},t=r?.id??"",i=readContent(e,"authors"),n=readContent(e,"authorids");let s="";if(Array.isArray(i)&&i.length)s=i.join(", ");else if(Array.isArray(n)&&n.length)s=n.map(d).join(", ");const u=readContent(e,"keywords"),o=Array.isArray(u)?u.join(", "):String(u??"");return{id:t,title:String(readContent(e,"title")??"").replace(/\s+/g," ").trim(),authors:s,keywords:o,venue:String(readContent(e,"venue")??"").trim(),venueid:String(readContent(e,"venueid")??"").trim(),primary_area:String(readContent(e,"primary_area")??"").trim(),abstract:String(readContent(e,"abstract")??"").replace(/\s+/g," ").trim(),pdate:formatDate(r?.pdate??r?.cdate),pdf:absolutePdf(readContent(e,"pdf")),url:t?`${OPENREVIEW_BASE}/forum?id=${t}`:""}}
@@ -1 +1 @@
1
- import{cli as p,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as f,EmptyResultError as d}from"@jackwener/opencli/errors";import{noteToRow as v,openreviewFetch as w,requireBoundedInt as h,requireNonNegativeInt as y}from"./utils.js";p({site:"openreview",name:"venue",access:"read",description:'List papers at an OpenReview venue (e.g. "ICLR 2024 oral" or full invitation id)',domain:"openreview.net",strategy:m.PUBLIC,browser:!1,args:[{name:"venue",positional:!0,required:!0,help:'Venue name ("ICLR 2024 oral") or invitation ("ICLR.cc/2025/Conference/-/Submission")'},{name:"limit",type:"int",default:25,help:"Max results (max 200)"},{name:"offset",type:"int",default:0,help:"Pagination offset"}],columns:["rank","id","title","authors","keywords","primary_area","pdate","pdf","url"],func:async(n)=>{const t=String(n.venue??"").trim();if(!t)throw new f("openreview venue cannot be empty");const i=h(n.limit,25,200),o=y(n.offset,0),r=t.includes("/-/"),l=`/notes?${r?`invitation=${encodeURIComponent(t)}`:`content.venue=${encodeURIComponent(t)}`}&limit=${i}&offset=${o}`,a=await w(l,`openreview venue ${t}`),s=Array.isArray(a?.notes)?a.notes:[];if(!s.length)throw new d("openreview",`No papers found at venue "${t}". ${r?'Check the invitation id (e.g. "ICLR.cc/2025/Conference/-/Submission").':'Try a venue text like "ICLR 2024 oral" or pass a full invitation id.'}`);return s.slice(0,i).map((u,c)=>{const e=v(u);return{rank:o+c+1,id:e.id,title:e.title,authors:e.authors,keywords:e.keywords,primary_area:e.primary_area,pdate:e.pdate,pdf:e.pdf,url:e.url}})}});
1
+ import{cli as c,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as f,EmptyResultError as d}from"@jackwener/opencli/errors";import{noteToRow as v,openreviewFetch as w,requireBoundedInt as y,requireNonNegativeInt as h}from"./utils.js";c({site:"openreview",name:"venue",access:"read",description:'List papers at an OpenReview venue (e.g. "ICLR 2024 oral" or full invitation id)',domain:"openreview.net",strategy:m.PUBLIC,browser:!1,args:[{name:"venue",positional:!0,required:!0,help:'Venue name ("ICLR 2024 oral") or invitation ("ICLR.cc/2025/Conference/-/Submission")'},{name:"limit",type:"int",default:25,help:"Max results (max 200)"},{name:"offset",type:"int",default:0,help:"Pagination offset"}],columns:["rank","id","title","authors","keywords","primary_area","pdate","pdf","url"],func:async(n)=>{const t=String(n.venue??"").trim();if(!t)throw new f("openreview venue cannot be empty");const i=y(n.limit,25,200),o=h(n.offset,0),r=t.includes("/-/"),p=`/notes?${r?`invitation=${encodeURIComponent(t)}`:`content.venue=${encodeURIComponent(t)}`}&limit=${i}&offset=${o}`,a=await w(p,`openreview venue ${t}`),s=Array.isArray(a?.notes)?a.notes:[];if(!s.length)throw new d("openreview",`No papers found at venue "${t}". ${r?'Check the invitation id (e.g. "ICLR.cc/2025/Conference/-/Submission").':'Try a venue text like "ICLR 2024 oral" or pass a full invitation id.'}`);return s.slice(0,i).map((u,l)=>{const e=v(u);return{rank:o+l+1,id:e.id,title:e.title,authors:e.authors,keywords:e.keywords,primary_area:e.primary_area,pdate:e.pdate,pdf:e.pdf,url:e.url}})}});
@@ -1 +1 @@
1
- import{CliError as W,CommandExecutionError as F}from"@jackwener/opencli/errors";import{cli as O,Strategy as _}from"@jackwener/opencli/registry";import{readFile as q,stat as T}from"node:fs/promises";import{publishArticle as j}from"../_shared/article/publish.js";export const oschinaProfile={home:"https://my.oschina.net",outputFormat:"markdown",image:{spec:{url:"https://apiv1.oschina.net/oschinapi/ai/creation/project/uploadDetail",method:"POST",bodyType:"binary-multipart",fileField:"file",fileName:"image",body:{},responsePath:"result"},skip:["apiv1.oschina.net","oscimg.oschina.net","static.oschina.net"]},checkAuth:async()=>{const G=await fetch("https://apiv1.oschina.net/oschinapi/user/myDetails",{credentials:"include"});if(!G.ok)return{isAuthenticated:!1,error:"HTTP "+G.status};let z=null;try{z=await G.json()}catch(V){return{isAuthenticated:!1,error:"解析响应失败"}}if(!z||!z.success||!z.result||!z.result.userId)return{isAuthenticated:!1,error:z&&z.message||"未登录"};const B=String(z.result.userId),K=z.result.userVo&&z.result.userVo.name||B,M=z.result.userVo&&z.result.userVo.portraitUrl||"";return{isAuthenticated:!0,userId:B,username:K,avatar:M}},publish:async(G)=>{const z=G.params||{};let B="",K="";try{const H=await fetch("https://apiv1.oschina.net/oschinapi/user/myDetails",{credentials:"include"});if(!H.ok)return{ok:!1,stage:"auth",status:H.status,message:"获取开源中国用户信息失败:HTTP "+H.status+"(登录态可能已失效,请在客户端重新登录)"};const L=await H.json();if(L&&L.success&&L.result&&L.result.userId)B=String(L.result.userId);else K=L&&L.message||"myDetails 未返回 userId(登录态可能已失效或为匿名)"}catch(H){return{ok:!1,stage:"auth",message:"校验开源中国登录态时请求异常:"+String(H&&H.message||H)}}if(!B)return{ok:!1,stage:"auth",message:"未登录开源中国,无法获取用户 ID"+(K?":"+K:"")};let M=0;if(z.category){let H=[];try{const Y=await(await fetch("https://apiv1.oschina.net/oschinapi/blog_catalog/list_by_user",{credentials:"include"})).json();H=Y&&Y.result||[]}catch(J){return{ok:!1,stage:"category",message:"获取开源中国博客分类失败:"+String(J&&J.message||J)}}const L=H.find((J)=>String(J.name)===String(z.category));if(!L)return{ok:!1,stage:"category",message:"未找到博客分类「"+z.category+"」,可选:"+(H.map((J)=>J.name).join(" / ")||"(你还没有任何分类)")};M=L.id}if(G.draftOnly){const H=await fetch("https://apiv1.oschina.net/oschinapi/api/draft/save_draft",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:G.title,user:Number(B),content:G.content,contentType:1,catalog:M,originUrl:"",privacy:!0,disableComment:!1})}),L=await H.text();let J=null;try{J=JSON.parse(L)}catch(S){}if(!H.ok||!J||!J.success||!J.result||!J.result.id)return{ok:!1,stage:"save_draft",status:H.status,message:J&&J.message||L.slice(0,300)};const Y=String(J.result.id);return{ok:!0,draft:!0,id:Y,url:"https://my.oschina.net/u/"+B+"/blog/ai-write/draft/"+Y}}const V=await fetch("https://apiv1.oschina.net/oschinapi/blog/web/add",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:G.title,content:G.content,contentType:1,type:"1",originUrl:"",catalog:M,privacy:!1,disableComment:!1,isAiRelated:!1,user:Number(B)})}),Q=await V.text();let U=null;try{U=JSON.parse(Q)}catch(H){}if(!V.ok||!U||U.code!==200||U.result==null)return{ok:!1,stage:"publish",status:V.status,message:U&&(U.message||U.msg)||Q.slice(0,300)};const X=String(U.result);return{ok:!0,draft:!1,id:X,url:"https://my.oschina.net/u/"+B+"/blog/"+X}}};function Z(G){if(!G.execute)throw new W("INVALID_INPUT","发布开源中国文章需要 --execute 参数。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}function $(G,z,B,K,M={}){return[{status:"success",outcome:K,message:G,target_type:z,target:B,...M}]}async function A(G){const z=typeof G.text==="string"?G.text:void 0,B=typeof G.file==="string"?G.file:void 0;if(z&&B)throw new W("INVALID_INPUT","正文和文件路径只能二选一,不能同时指定");let K=z??"";if(B){let M;try{M=await T(B)}catch{throw new W("INVALID_INPUT","文件不存在:"+B)}if(!M.isFile())throw new W("INVALID_INPUT","必须指定可读的文本文件:"+B);let V;try{V=await q(B)}catch{throw new W("INVALID_INPUT","文件读取失败:"+B)}try{K=new TextDecoder("utf-8",{fatal:!0}).decode(V)}catch{throw new W("INVALID_INPUT","文件编码不是 UTF-8:"+B)}}if(!K.trim())throw new W("INVALID_INPUT","文章正文不能为空");return K}O({site:"oschina",name:"article",access:"write",description:"发布文章到开源中国博客。默认正式发布,加 --draft 仅存草稿。正文默认 Markdown,外链图片自动转存到开源中国图床。",domain:"my.oschina.net",strategy:_.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题"},{name:"text",positional:!0,help:"文章正文(默认 Markdown;--html 表示原始 HTML)"},{name:"file",help:"从文件读取正文(UTF-8,默认 Markdown)"},{name:"html",type:"boolean",help:"将正文视为原始 HTML 而非 Markdown"},{name:"category",help:"个人博客分类名(精确匹配),合法值用 `oschina catalogs` 列举;可空=不分类"},{name:"draft",type:"boolean",help:"仅存草稿,不发布"},{name:"execute",type:"boolean",help:"真正执行写操作;不加此参数命令拒绝写入"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(G,z)=>{if(!G)throw new F("开源中国文章发布需要浏览器会话");Z(z);const B=String(z.title??"").trim();if(!B)throw new W("INVALID_INPUT","文章标题不能为空");const K=await A(z),M=Boolean(z.draft),V={category:typeof z.category==="string"?z.category.trim():""},Q=await j(G,{title:B,body:K,format:z.html?"html":"markdown",draftOnly:M,profile:oschinaProfile,publishParams:V}),U=Q.images.uploaded.length|0,X=Q.images.failed.length|0;let H=Q.draft?"已保存到开源中国草稿箱":"已正式发布到开源中国博客";if(U||X)H+=`·图片:${U} 张已转存${X?`,${X} 张失败`:""}`;if(!Q.draft)H+="。已按公开发布提交;开源中国对新账号/新文章有站方审核,过审前它不会出现在公开列表,"+"此时 stats 的 is_private 会显示「是」——这是审核中,不是发布失败,请勿重发,稍后回查即可";return $(H,"article","",Q.draft?"draft":"created",{created_target:(Q.draft?"draft:":"article:")+Q.id,created_url:Q.url})}});export const __test__={oschinaProfile,requireExecute:Z,buildResultRow:$,resolvePayload:A};
1
+ import{CliError as d,CommandExecutionError as y}from"@jackwener/opencli/errors";import{cli as w,Strategy as I}from"@jackwener/opencli/registry";import{readFile as b,stat as N}from"node:fs/promises";import{publishArticle as T}from"../_shared/article/publish.js";export const oschinaProfile={home:"https://my.oschina.net",outputFormat:"markdown",image:{spec:{url:"https://apiv1.oschina.net/oschinapi/ai/creation/project/uploadDetail",method:"POST",bodyType:"binary-multipart",fileField:"file",fileName:"image",body:{},responsePath:"result"},skip:["apiv1.oschina.net","oscimg.oschina.net","static.oschina.net"]},checkAuth:async()=>{const a=await fetch("https://apiv1.oschina.net/oschinapi/user/myDetails",{credentials:"include"});if(!a.ok)return{isAuthenticated:!1,error:"HTTP "+a.status};let t=null;try{t=await a.json()}catch(u){return{isAuthenticated:!1,error:"解析响应失败"}}if(!t||!t.success||!t.result||!t.result.userId)return{isAuthenticated:!1,error:t&&t.message||"未登录"};const e=String(t.result.userId),i=t.result.userVo&&t.result.userVo.name||e,o=t.result.userVo&&t.result.userVo.portraitUrl||"";return{isAuthenticated:!0,userId:e,username:i,avatar:o}},publish:async(a)=>{const t=a.params||{};let e="",i="";try{const s=await fetch("https://apiv1.oschina.net/oschinapi/user/myDetails",{credentials:"include"});if(!s.ok)return{ok:!1,stage:"auth",status:s.status,message:"获取开源中国用户信息失败:HTTP "+s.status+"(登录态可能已失效,请在客户端重新登录)"};const n=await s.json();if(n&&n.success&&n.result&&n.result.userId)e=String(n.result.userId);else i=n&&n.message||"myDetails 未返回 userId(登录态可能已失效或为匿名)"}catch(s){return{ok:!1,stage:"auth",message:"校验开源中国登录态时请求异常:"+String(s&&s.message||s)}}if(!e)return{ok:!1,stage:"auth",message:"未登录开源中国,无法获取用户 ID"+(i?":"+i:"")};let o=0;if(t.category){let s=[];try{const f=await(await fetch("https://apiv1.oschina.net/oschinapi/blog_catalog/list_by_user",{credentials:"include"})).json();s=f&&f.result||[]}catch(r){return{ok:!1,stage:"category",message:"获取开源中国博客分类失败:"+String(r&&r.message||r)}}const n=s.find((r)=>String(r.name)===String(t.category));if(!n)return{ok:!1,stage:"category",message:"未找到博客分类「"+t.category+"」,可选:"+(s.map((r)=>r.name).join(" / ")||"(你还没有任何分类)")};o=n.id}if(a.draftOnly){const s=await fetch("https://apiv1.oschina.net/oschinapi/api/draft/save_draft",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:a.title,user:Number(e),content:a.content,contentType:1,catalog:o,originUrl:"",privacy:!0,disableComment:!1})}),n=await s.text();let r=null;try{r=JSON.parse(n)}catch(_){}if(!s.ok||!r||!r.success||!r.result||!r.result.id)return{ok:!1,stage:"save_draft",status:s.status,message:r&&r.message||n.slice(0,300)};const f=String(r.result.id);return{ok:!0,draft:!0,id:f,url:"https://my.oschina.net/u/"+e+"/blog/ai-write/draft/"+f}}const u=await fetch("https://apiv1.oschina.net/oschinapi/blog/web/add",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:a.title,content:a.content,contentType:1,type:"1",originUrl:"",catalog:o,privacy:!1,disableComment:!1,isAiRelated:!1,user:Number(e)})}),c=await u.text();let l=null;try{l=JSON.parse(c)}catch(s){}if(!u.ok||!l||l.code!==200||l.result==null)return{ok:!1,stage:"publish",status:u.status,message:l&&(l.message||l.msg)||c.slice(0,300)};const h=String(l.result);return{ok:!0,draft:!1,id:h,url:"https://my.oschina.net/u/"+e+"/blog/"+h}}};function p(a){if(!a.execute)throw new d("INVALID_INPUT","发布开源中国文章需要 --execute 参数。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}function m(a,t,e,i,o={}){return[{status:"success",outcome:i,message:a,target_type:t,target:e,...o}]}async function g(a){const t=typeof a.text==="string"?a.text:void 0,e=typeof a.file==="string"?a.file:void 0;if(t&&e)throw new d("INVALID_INPUT","正文和文件路径只能二选一,不能同时指定");let i=t??"";if(e){let o;try{o=await N(e)}catch{throw new d("INVALID_INPUT","文件不存在:"+e)}if(!o.isFile())throw new d("INVALID_INPUT","必须指定可读的文本文件:"+e);let u;try{u=await b(e)}catch{throw new d("INVALID_INPUT","文件读取失败:"+e)}try{i=new TextDecoder("utf-8",{fatal:!0}).decode(u)}catch{throw new d("INVALID_INPUT","文件编码不是 UTF-8:"+e)}}if(!i.trim())throw new d("INVALID_INPUT","文章正文不能为空");return i}w({site:"oschina",name:"article",access:"write",description:"发布文章到开源中国博客。默认正式发布,加 --draft 仅存草稿。正文默认 Markdown,外链图片自动转存到开源中国图床。",domain:"my.oschina.net",strategy:I.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题"},{name:"text",positional:!0,help:"文章正文(默认 Markdown;--html 表示原始 HTML)"},{name:"file",help:"从文件读取正文(UTF-8,默认 Markdown)"},{name:"html",type:"boolean",help:"将正文视为原始 HTML 而非 Markdown"},{name:"category",help:"个人博客分类名(精确匹配),合法值用 `oschina catalogs` 列举;可空=不分类"},{name:"draft",type:"boolean",help:"仅存草稿,不发布"},{name:"execute",type:"boolean",help:"真正执行写操作;不加此参数命令拒绝写入"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(a,t)=>{if(!a)throw new y("开源中国文章发布需要浏览器会话");p(t);const e=String(t.title??"").trim();if(!e)throw new d("INVALID_INPUT","文章标题不能为空");const i=await g(t),o=Boolean(t.draft),u={category:typeof t.category==="string"?t.category.trim():""},c=await T(a,{title:e,body:i,format:t.html?"html":"markdown",draftOnly:o,profile:oschinaProfile,publishParams:u}),l=c.images.uploaded.length|0,h=c.images.failed.length|0;let s=c.draft?"已保存到开源中国草稿箱":"已正式发布到开源中国博客";if(l||h)s+=`·图片:${l} 张已转存${h?`,${h} 张失败`:""}`;if(!c.draft)s+="。已按公开发布提交;开源中国对新账号/新文章有站方审核,过审前它不会出现在公开列表,"+"此时 stats 的 is_private 会显示「是」——这是审核中,不是发布失败,请勿重发,稍后回查即可";return m(s,"article","",c.draft?"draft":"created",{created_target:(c.draft?"draft:":"article:")+c.id,created_url:c.url})}});export const __test__={oschinaProfile,requireExecute:p,buildResultRow:m,resolvePayload:g};
@@ -1 +1 @@
1
- import{cli as z,Strategy as B}from"@jackwener/opencli/registry";import{CommandExecutionError as F}from"@jackwener/opencli/errors";import{gotoWritePage as G}from"../_shared/article/publish.js";import{oschinaProfile as H}from"./article.js";z({site:"oschina",name:"catalogs",access:"read",description:"列出当前用户的开源中国个人博客分类(id + 名称),供 `oschina article --category` 取合法分类名。",domain:"my.oschina.net",strategy:B.COOKIE,browser:!0,columns:["catalog_id","catalog_name"],func:async(q)=>{if(!q)throw new F("开源中国分类列举需要浏览器会话");await G(q,H.home);const v=await q.evaluate("(async () => {const r = await fetch('https://apiv1.oschina.net/oschinapi/blog_catalog/list_by_user', { credentials: 'include' });const j = await r.json();return ((j && j.result) || []).map(c => ({ catalog_id: String(c.id), catalog_name: c.name || '' }));})()");return Array.isArray(v)?v:[]}});
1
+ import{cli as o,Strategy as r}from"@jackwener/opencli/registry";import{CommandExecutionError as i}from"@jackwener/opencli/errors";import{gotoWritePage as c}from"../_shared/article/publish.js";import{oschinaProfile as e}from"./article.js";o({site:"oschina",name:"catalogs",access:"read",description:"列出当前用户的开源中国个人博客分类(id + 名称),供 `oschina article --category` 取合法分类名。",domain:"my.oschina.net",strategy:r.COOKIE,browser:!0,columns:["catalog_id","catalog_name"],func:async(a)=>{if(!a)throw new i("开源中国分类列举需要浏览器会话");await c(a,e.home);const t=await a.evaluate("(async () => {const r = await fetch('https://apiv1.oschina.net/oschinapi/blog_catalog/list_by_user', { credentials: 'include' });const j = await r.json();return ((j && j.result) || []).map(c => ({ catalog_id: String(c.id), catalog_name: c.name || '' }));})()");return Array.isArray(t)?t:[]}});
@@ -1 +1 @@
1
- import{registerArticleLogin as k}from"../_shared/article/login.js";import{oschinaProfile as b}from"./article.js";k({site:"oschina",domain:"oschina.net",profile:{home:b.home,originRe:b.originRe,checkAuth:b.checkAuth},loginDescription:"打开开源中国登录页并等待浏览器完成登录(供桌面客户端引导登录)。"});
1
+ import{registerArticleLogin as o}from"../_shared/article/login.js";import{oschinaProfile as i}from"./article.js";o({site:"oschina",domain:"oschina.net",profile:{home:i.home,originRe:i.originRe,checkAuth:i.checkAuth},loginDescription:"打开开源中国登录页并等待浏览器完成登录(供桌面客户端引导登录)。"});
@@ -1,10 +1,10 @@
1
- import{cli as Y,Strategy as $}from"@jackwener/opencli/registry";import{CliError as I}from"@jackwener/opencli/errors";const J=10,X=30;function Z(h,H){return`
1
+ import{cli as p,Strategy as f}from"@jackwener/opencli/registry";import{CliError as g}from"@jackwener/opencli/errors";const w=10,S=30;function b(t,o){return`
2
2
  async () => {
3
3
  const API = 'https://apiv1.oschina.net/oschinapi';
4
- const LIMIT = ${JSON.stringify(h)};
5
- const USER_ARG = ${JSON.stringify(H)};
6
- const PAGE_SIZE = ${J};
7
- const MAX_PAGES = ${X};
4
+ const LIMIT = ${JSON.stringify(t)};
5
+ const USER_ARG = ${JSON.stringify(o)};
6
+ const PAGE_SIZE = ${w};
7
+ const MAX_PAGES = ${S};
8
8
  const getJson = async (url) => {
9
9
  const resp = await fetch(url, { credentials: 'include' });
10
10
  const text = await resp.text();
@@ -51,4 +51,4 @@ import{cli as Y,Strategy as $}from"@jackwener/opencli/registry";import{CliError
51
51
  }
52
52
  return out;
53
53
  }
54
- `}function j(h){if(h&&typeof h==="object"&&!Array.isArray(h)&&"session"in h&&"data"in h)return h.data;return h}function U(h){return typeof h==="number"&&Number.isFinite(h)?h:""}function W(h,H,Q,T,q){const F=h.id!=null?String(h.id):"",N=T&&F?T.get(F):null,B=(z)=>h[z]!=null?h[z]:N?N[z]:void 0,K=Number(B("type")),O={};for(const[z,D]of Object.entries({reply_count:U(B("replyCount")),state:B("state"),as_recomm:h.asRecomm,detritus:B("detritus"),scheduled_time:h.scheduledTime,scheduled_state:h.scheduledState,summary:typeof B("detail")==="string"?String(B("detail")).slice(0,80):void 0}))if(D!==void 0&&D!==null&&D!=="")O[z]=D;if(Q==="已发布"&&!(q||N))O.visibility_note="未出现在公开列表:可能是站方审核中(新账号/新文章常见),也可能是该文设为私密;请稍后回查再判定";return{id:F,type:"博客",title:h.title!=null?String(h.title):"",url:F&&H?`https://my.oschina.net/u/${H}/blog/${F}`:"",published_at:B("createTime")||"",views:U(B("viewCount")),likes:U(B("voteCount")),comments:U(B("commentCount")),collects:"",shares:"",origin:K===2?"转载":K===1?"原创":"",is_private:Q!=="已发布"?"":q||N?"否":"是",recommended:Number(B("recomm"))===1?"推荐":"",top:Number(B("asTop"))===1?"置顶":"",status:Q,extra:Object.keys(O).length?JSON.stringify(O):""}}Y({site:"oschina",name:"stats",access:"read",description:"开源中国博客数据(每篇阅读/点赞/评论等全量运营指标)",domain:"my.oschina.net",strategy:$.COOKIE,browser:!0,args:[{name:"limit",type:"number",default:20,help:"返回条数"},{name:"user",help:"查看指定用户 ID 的公开博客数据(默认当前登录账号,含私密与定时博客)"}],columns:["id","type","title","url","published_at","views","likes","comments","collects","shares","origin","is_private","recommended","top","status","extra"],func:async(h,H)=>{const Q=Number(H.limit)||20,T=H.user!=null&&String(H.user).trim()!==""?String(H.user).trim():"";await h.goto("https://my.oschina.net/");await h.wait(1);const q=j(await h.evaluate(Z(Q,T)));if(!q||typeof q!=="object")throw Error("开源中国页面取数失败:未拿到任何响应,请确认 Chrome 已打开且能访问 my.oschina.net。");if(q.notLoggedIn)throw Error("未登录开源中国:user/myDetails 未返回用户信息。请先在 Chrome 中登录 my.oschina.net(可用 ppcli oschina login)。");const F=String(q.targetUser||q.me||""),N=q.pub&&q.pub.rows||[];if(q.pub&&q.pub.error)throw Error("获取开源中国博客公开列表失败:"+q.pub.error);const B=new Map(N.filter((z)=>z&&z.id!=null).map((z)=>[String(z.id),z])),K=[],O=new Set;if(q.isSelf){if(q.mine&&q.mine.error)throw Error("获取开源中国「我的创作」博客列表失败:"+q.mine.error);for(const z of q.mine&&q.mine.rows||[]){const D=W(z,F,"已发布",B);if(D.id)O.add(D.id);K.push(D)}for(const z of N){const D=z&&z.id!=null?String(z.id):"";if(!D||O.has(D))continue;O.add(D);K.push(W(z,F,"已发布",null,!0))}for(const z of q.scheduled&&q.scheduled.rows||[])K.push(W(z,F,"已定时未发布",null,!1))}else for(const z of N)K.push(W(z,F,"已发布",null,!0));if(K.length===0)throw new I("EMPTY_RESULT",q.isSelf?"当前开源中国账号没有任何博客(已发布/定时均为空)。":`用户 ${F} 没有任何公开博客。`,q.isSelf?"发布过内容后再来查看数据(ppcli oschina article)。":"请确认用户 ID 是否正确。");return K.slice(0,Q)}});
54
+ `}function y(t){if(t&&typeof t==="object"&&!Array.isArray(t)&&"session"in t&&"data"in t)return t.data;return t}function m(t){return typeof t==="number"&&Number.isFinite(t)?t:""}function h(t,o,l,d,e){const i=t.id!=null?String(t.id):"",a=d&&i?d.get(i):null,r=(s)=>t[s]!=null?t[s]:a?a[s]:void 0,u=Number(r("type")),c={};for(const[s,n]of Object.entries({reply_count:m(r("replyCount")),state:r("state"),as_recomm:t.asRecomm,detritus:r("detritus"),scheduled_time:t.scheduledTime,scheduled_state:t.scheduledState,summary:typeof r("detail")==="string"?String(r("detail")).slice(0,80):void 0}))if(n!==void 0&&n!==null&&n!=="")c[s]=n;if(l==="已发布"&&!(e||a))c.visibility_note="未出现在公开列表:可能是站方审核中(新账号/新文章常见),也可能是该文设为私密;请稍后回查再判定";return{id:i,type:"博客",title:t.title!=null?String(t.title):"",url:i&&o?`https://my.oschina.net/u/${o}/blog/${i}`:"",published_at:r("createTime")||"",views:m(r("viewCount")),likes:m(r("voteCount")),comments:m(r("commentCount")),collects:"",shares:"",origin:u===2?"转载":u===1?"原创":"",is_private:l!=="已发布"?"":e||a?"否":"是",recommended:Number(r("recomm"))===1?"推荐":"",top:Number(r("asTop"))===1?"置顶":"",status:l,extra:Object.keys(c).length?JSON.stringify(c):""}}p({site:"oschina",name:"stats",access:"read",description:"开源中国博客数据(每篇阅读/点赞/评论等全量运营指标)",domain:"my.oschina.net",strategy:f.COOKIE,browser:!0,args:[{name:"limit",type:"number",default:20,help:"返回条数"},{name:"user",help:"查看指定用户 ID 的公开博客数据(默认当前登录账号,含私密与定时博客)"}],columns:["id","type","title","url","published_at","views","likes","comments","collects","shares","origin","is_private","recommended","top","status","extra"],func:async(t,o)=>{const l=Number(o.limit)||20,d=o.user!=null&&String(o.user).trim()!==""?String(o.user).trim():"";await t.goto("https://my.oschina.net/");await t.wait(1);const e=y(await t.evaluate(b(l,d)));if(!e||typeof e!=="object")throw Error("开源中国页面取数失败:未拿到任何响应,请确认 Chrome 已打开且能访问 my.oschina.net。");if(e.notLoggedIn)throw Error("未登录开源中国:user/myDetails 未返回用户信息。请先在 Chrome 中登录 my.oschina.net(可用 ppcli oschina login)。");const i=String(e.targetUser||e.me||""),a=e.pub&&e.pub.rows||[];if(e.pub&&e.pub.error)throw Error("获取开源中国博客公开列表失败:"+e.pub.error);const r=new Map(a.filter((s)=>s&&s.id!=null).map((s)=>[String(s.id),s])),u=[],c=new Set;if(e.isSelf){if(e.mine&&e.mine.error)throw Error("获取开源中国「我的创作」博客列表失败:"+e.mine.error);for(const s of e.mine&&e.mine.rows||[]){const n=h(s,i,"已发布",r);if(n.id)c.add(n.id);u.push(n)}for(const s of a){const n=s&&s.id!=null?String(s.id):"";if(!n||c.has(n))continue;c.add(n);u.push(h(s,i,"已发布",null,!0))}for(const s of e.scheduled&&e.scheduled.rows||[])u.push(h(s,i,"已定时未发布",null,!1))}else for(const s of a)u.push(h(s,i,"已发布",null,!0));if(u.length===0)throw new g("EMPTY_RESULT",e.isSelf?"当前开源中国账号没有任何博客(已发布/定时均为空)。":`用户 ${i} 没有任何公开博客。`,e.isSelf?"发布过内容后再来查看数据(ppcli oschina article)。":"请确认用户 ID 是否正确。");return u.slice(0,l)}});
@@ -1 +1 @@
1
- import{cli as v,Strategy as x}from"@jackwener/opencli/registry";import{checkLogin as z,cookieQuickCheck as A}from"../_shared/article/auth.js";import{oschinaProfile as m}from"./article.js";const B={home:m.home,checkAuth:m.checkAuth};v({site:"oschina",name:"whoami",access:"read",description:"查询当前开源中国登录账号信息(登录状态 / 用户 ID / 用户名)。",domain:"my.oschina.net",strategy:x.COOKIE,browser:!0,columns:["logged_in","user_id","username"],authStatus:{quickCheck:A("https://my.oschina.net",["oscid"])},func:async(q)=>{const b=await z(q,B);return[{logged_in:b.isAuthenticated,user_id:b.userId||"",username:b.username||""}]}});
1
+ import{cli as t,Strategy as c}from"@jackwener/opencli/registry";import{checkLogin as r,cookieQuickCheck as s}from"../_shared/article/auth.js";import{oschinaProfile as i}from"./article.js";const n={home:i.home,checkAuth:i.checkAuth};t({site:"oschina",name:"whoami",access:"read",description:"查询当前开源中国登录账号信息(登录状态 / 用户 ID / 用户名)。",domain:"my.oschina.net",strategy:c.COOKIE,browser:!0,columns:["logged_in","user_id","username"],authStatus:{quickCheck:s("https://my.oschina.net",["oscid"])},func:async(o)=>{const e=await r(o,n);return[{logged_in:e.isAuthenticated,user_id:e.userId||"",username:e.username||""}]}});
package/clis/osv/query.js CHANGED
@@ -1 +1 @@
1
- import{cli as g,Strategy as v}from"@jackwener/opencli/registry";import{EmptyResultError as k}from"@jackwener/opencli/errors";import{OSV_BASE as h,osvPost as b,requireBoundedInt as S,requireEcosystem as q,requireString as P,severityLabel as w,trimDate as m}from"./utils.js";g({site:"osv",name:"query",access:"read",description:"OSV.dev vulnerabilities affecting a package (optionally pinned to a version)",domain:"osv.dev",strategy:v.PUBLIC,browser:!1,args:[{name:"package",positional:!0,type:"string",required:!0,help:'Package name (e.g. "lodash", "django")'},{name:"ecosystem",type:"string",required:!0,help:"OSV ecosystem (npm / PyPI / Go / Maven / NuGet / RubyGems / crates.io / Packagist / ...)"},{name:"version",type:"string",required:!1,help:'Pin to a specific version (e.g. "4.17.20"); omit for all known vulns'},{name:"limit",type:"int",default:30,help:"Max rows to return (1-200)"}],columns:["rank","id","summary","severity","aliases","published","modified","affectedPackages","url"],func:async(i)=>{const r=P(i.package,"package"),a=q(i.ecosystem),p=S(i.limit,30,200,"limit"),s={package:{name:r,ecosystem:a}};if(i.version!=null&&String(i.version).trim()!=="")s.version=String(i.version).trim();const n=await b(`${h}/v1/query`,s,`osv query ${a}:${r}`),o=Array.isArray(n?.vulns)?n.vulns:[];if(o.length===0)throw new k("osv query",`OSV.dev returned no vulnerabilities for ${a}:${r}${s.version?`@${s.version}`:""}.`);return o.slice().sort((e,t)=>String(t?.published??"").localeCompare(String(e?.published??""))).slice(0,p).map((e,t)=>{const y=Array.isArray(e.affected)?e.affected:[],l=[];for(const c of y){const u=c?.package?.ecosystem,d=c?.package?.name;if(u&&d)l.push(`${u}:${d}`)}const f=Array.isArray(e.aliases)?e.aliases.filter(Boolean):[];return{rank:t+1,id:String(e.id??""),summary:String(e.summary??"").trim(),severity:w(e),aliases:f.join(", "),published:m(e.published),modified:m(e.modified),affectedPackages:l.join(", "),url:e.id?`https://osv.dev/vulnerability/${e.id}`:""}})}});
1
+ import{cli as g,Strategy as v}from"@jackwener/opencli/registry";import{EmptyResultError as k}from"@jackwener/opencli/errors";import{OSV_BASE as h,osvPost as S,requireBoundedInt as b,requireEcosystem as q,requireString as P,severityLabel as A,trimDate as d}from"./utils.js";g({site:"osv",name:"query",access:"read",description:"OSV.dev vulnerabilities affecting a package (optionally pinned to a version)",domain:"osv.dev",strategy:v.PUBLIC,browser:!1,args:[{name:"package",positional:!0,type:"string",required:!0,help:'Package name (e.g. "lodash", "django")'},{name:"ecosystem",type:"string",required:!0,help:"OSV ecosystem (npm / PyPI / Go / Maven / NuGet / RubyGems / crates.io / Packagist / ...)"},{name:"version",type:"string",required:!1,help:'Pin to a specific version (e.g. "4.17.20"); omit for all known vulns'},{name:"limit",type:"int",default:30,help:"Max rows to return (1-200)"}],columns:["rank","id","summary","severity","aliases","published","modified","affectedPackages","url"],func:async(i)=>{const s=P(i.package,"package"),t=q(i.ecosystem),p=b(i.limit,30,200,"limit"),r={package:{name:s,ecosystem:t}};if(i.version!=null&&String(i.version).trim()!=="")r.version=String(i.version).trim();const o=await S(`${h}/v1/query`,r,`osv query ${t}:${s}`),n=Array.isArray(o?.vulns)?o.vulns:[];if(n.length===0)throw new k("osv query",`OSV.dev returned no vulnerabilities for ${t}:${s}${r.version?`@${r.version}`:""}.`);return n.slice().sort((e,a)=>String(a?.published??"").localeCompare(String(e?.published??""))).slice(0,p).map((e,a)=>{const y=Array.isArray(e.affected)?e.affected:[],l=[];for(const c of y){const m=c?.package?.ecosystem,u=c?.package?.name;if(m&&u)l.push(`${m}:${u}`)}const f=Array.isArray(e.aliases)?e.aliases.filter(Boolean):[];return{rank:a+1,id:String(e.id??""),summary:String(e.summary??"").trim(),severity:A(e),aliases:f.join(", "),published:d(e.published),modified:d(e.modified),affectedPackages:l.join(", "),url:e.id?`https://osv.dev/vulnerability/${e.id}`:""}})}});