publishport-opencli 1.0.19 → 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 (1042) hide show
  1. package/cli-manifest.json +35 -0
  2. package/clis/12306/me.js +2 -2
  3. package/clis/12306/orders.js +3 -3
  4. package/clis/12306/passengers.js +3 -3
  5. package/clis/12306/price.js +1 -1
  6. package/clis/12306/stations.js +1 -1
  7. package/clis/12306/train.js +1 -1
  8. package/clis/12306/trains.js +1 -1
  9. package/clis/12306/utils.js +1 -1
  10. package/clis/1688/download.js +1 -1
  11. package/clis/1688/item.js +4 -4
  12. package/clis/1688/search.js +4 -4
  13. package/clis/1688/store.js +4 -4
  14. package/clis/1point3acres/forum.js +1 -1
  15. package/clis/1point3acres/forums.js +1 -1
  16. package/clis/1point3acres/notifications.js +1 -1
  17. package/clis/1point3acres/search.js +1 -1
  18. package/clis/1point3acres/thread.js +2 -2
  19. package/clis/1point3acres/user.js +1 -1
  20. package/clis/1point3acres/utils.js +2 -2
  21. package/clis/36kr/article.js +2 -2
  22. package/clis/36kr/hot.js +2 -2
  23. package/clis/36kr/news.js +1 -1
  24. package/clis/36kr/search.js +2 -2
  25. package/clis/51job/company.js +2 -2
  26. package/clis/51job/detail.js +2 -2
  27. package/clis/51job/hot.js +1 -1
  28. package/clis/51job/search.js +1 -1
  29. package/clis/51job/utils.js +7 -7
  30. package/clis/_atlassian/shared.js +9 -9
  31. package/clis/_shared/article/auth.js +4 -4
  32. package/clis/_shared/article/douban-md2draft.js +4 -4
  33. package/clis/_shared/article/format.js +1 -1
  34. package/clis/_shared/article/images.js +7 -7
  35. package/clis/_shared/article/login.js +1 -1
  36. package/clis/_shared/article/publish.js +11 -11
  37. package/clis/_shared/common.js +1 -1
  38. package/clis/_shared/content-guard.js +1 -1
  39. package/clis/_shared/desktop-commands.js +1 -1
  40. package/clis/_shared/file-inject.js +12 -12
  41. package/clis/_shared/self-hosted-sites.js +2 -2
  42. package/clis/_shared/site-auth.js +1 -1
  43. package/clis/_shared/token-auth.js +2 -2
  44. package/clis/_shared/video-publish.js +9 -9
  45. package/clis/amazon/offer.js +3 -3
  46. package/clis/amazon/product.js +5 -5
  47. package/clis/amazon/shared.js +6 -6
  48. package/clis/antigravity/_actions.js +13 -13
  49. package/clis/antigravity/audit-extras.js +10 -10
  50. package/clis/antigravity/delete.js +1 -1
  51. package/clis/antigravity/model.js +6 -6
  52. package/clis/antigravity/new.js +2 -2
  53. package/clis/antigravity/read.js +2 -2
  54. package/clis/antigravity/rename.js +1 -1
  55. package/clis/antigravity/send.js +3 -3
  56. package/clis/antigravity/serve.js +17 -17
  57. package/clis/antigravity/storage.js +6 -6
  58. package/clis/antigravity/watch.js +2 -2
  59. package/clis/apple-podcasts/episodes.js +1 -1
  60. package/clis/apple-podcasts/top.js +1 -1
  61. package/clis/apple-podcasts/utils.js +1 -1
  62. package/clis/archive/item.js +1 -1
  63. package/clis/archive/search.js +1 -1
  64. package/clis/archive/snapshots.js +1 -1
  65. package/clis/archive/wayback.js +1 -1
  66. package/clis/arxiv/author.js +1 -1
  67. package/clis/arxiv/utils.js +1 -1
  68. package/clis/autohome/brand.js +1 -1
  69. package/clis/autohome/score.js +1 -1
  70. package/clis/autohome/utils.js +1 -1
  71. package/clis/baijiahao/article.js +1 -1
  72. package/clis/baijiahao/lists.js +1 -1
  73. package/clis/baijiahao/login.js +1 -1
  74. package/clis/baijiahao/publish.js +9 -9
  75. package/clis/baijiahao/stats.js +1 -1
  76. package/clis/baijiahao/whoami.js +1 -1
  77. package/clis/band/bands.js +2 -2
  78. package/clis/band/mentions.js +2 -2
  79. package/clis/band/post.js +4 -4
  80. package/clis/band/posts.js +3 -3
  81. package/clis/barchart/flow.js +3 -3
  82. package/clis/barchart/greeks.js +2 -2
  83. package/clis/barchart/quote.js +3 -3
  84. package/clis/bbc/news.js +1 -1
  85. package/clis/bbc/topic.js +1 -1
  86. package/clis/bbc/utils.js +1 -1
  87. package/clis/bilibili/article.js +1 -1
  88. package/clis/bilibili/categories.js +1 -1
  89. package/clis/bilibili/coin.js +1 -1
  90. package/clis/bilibili/comment-del.js +1 -1
  91. package/clis/bilibili/comment-like.js +1 -1
  92. package/clis/bilibili/comment.js +1 -1
  93. package/clis/bilibili/comments.js +1 -1
  94. package/clis/bilibili/dm-list.js +1 -1
  95. package/clis/bilibili/dm-read.js +1 -1
  96. package/clis/bilibili/dm-send.js +1 -1
  97. package/clis/bilibili/download.js +2 -2
  98. package/clis/bilibili/drafts.js +1 -1
  99. package/clis/bilibili/dynamic-post.js +3 -3
  100. package/clis/bilibili/favorite-add.js +1 -1
  101. package/clis/bilibili/favorite.js +1 -1
  102. package/clis/bilibili/feed.js +2 -2
  103. package/clis/bilibili/follow.js +1 -1
  104. package/clis/bilibili/following.js +1 -1
  105. package/clis/bilibili/like.js +1 -1
  106. package/clis/bilibili/partitions.js +1 -1
  107. package/clis/bilibili/stats.js +1 -1
  108. package/clis/bilibili/subtitle.js +3 -3
  109. package/clis/bilibili/summary.js +1 -1
  110. package/clis/bilibili/topics.js +1 -1
  111. package/clis/bilibili/unfollow.js +1 -1
  112. package/clis/bilibili/upload.js +1 -1
  113. package/clis/bilibili/utils.js +10 -10
  114. package/clis/bilibili/video-drafts.js +1 -1
  115. package/clis/bilibili/video.js +1 -1
  116. package/clis/bloomberg/businessweek.js +4 -4
  117. package/clis/bloomberg/news.js +2 -2
  118. package/clis/bloomberg/utils.js +13 -13
  119. package/clis/bluesky/post.js +1 -1
  120. package/clis/bluesky/shared.js +11 -11
  121. package/clis/bluesky/whoami.js +1 -1
  122. package/clis/booking/search.js +2 -2
  123. package/clis/boss/accept.js +1 -1
  124. package/clis/boss/applied.js +1 -1
  125. package/clis/boss/auth.js +1 -1
  126. package/clis/boss/batchgreet.js +1 -1
  127. package/clis/boss/bossinfo.js +1 -1
  128. package/clis/boss/chatlist.js +1 -1
  129. package/clis/boss/chatmsg.js +1 -1
  130. package/clis/boss/cities.js +1 -1
  131. package/clis/boss/detail.js +1 -1
  132. package/clis/boss/exchange.js +1 -1
  133. package/clis/boss/greet.js +1 -1
  134. package/clis/boss/interviews.js +1 -1
  135. package/clis/boss/invite.js +1 -1
  136. package/clis/boss/joblist.js +1 -1
  137. package/clis/boss/mark.js +1 -1
  138. package/clis/boss/me.js +2 -2
  139. package/clis/boss/recommend.js +1 -1
  140. package/clis/boss/resumedelete.js +1 -1
  141. package/clis/boss/resumelist.js +1 -1
  142. package/clis/boss/resumeupload.js +11 -11
  143. package/clis/boss/search.js +1 -1
  144. package/clis/boss/send.js +1 -1
  145. package/clis/boss/sendresume.js +1 -1
  146. package/clis/boss/stats.js +1 -1
  147. package/clis/boss/unread.js +1 -1
  148. package/clis/boss/utils.js +13 -13
  149. package/clis/chaoxing/assignments.js +1 -1
  150. package/clis/chaoxing/exams.js +1 -1
  151. package/clis/chaoxing/utils.js +9 -9
  152. package/clis/chatgpt/ask.js +1 -1
  153. package/clis/chatgpt/auth.js +2 -2
  154. package/clis/chatgpt/detail.js +1 -1
  155. package/clis/chatgpt/image.js +1 -1
  156. package/clis/chatgpt/read.js +1 -1
  157. package/clis/chatgpt/send.js +1 -1
  158. package/clis/chatgpt/utils.js +59 -59
  159. package/clis/chatgpt-app/ask.js +1 -1
  160. package/clis/chatgpt-app/send.js +1 -1
  161. package/clis/chatwise/model.js +6 -6
  162. package/clis/chess/analyze.js +1 -1
  163. package/clis/chess/game.js +1 -1
  164. package/clis/chess/games.js +1 -1
  165. package/clis/chess/stats.js +1 -1
  166. package/clis/chess/utils.js +1 -1
  167. package/clis/claude/ask.js +2 -2
  168. package/clis/claude/detail.js +1 -1
  169. package/clis/claude/new.js +1 -1
  170. package/clis/claude/read.js +1 -1
  171. package/clis/claude/send.js +1 -1
  172. package/clis/claude/utils.js +23 -23
  173. package/clis/cnblogs/article.js +1 -1
  174. package/clis/cnblogs/login.js +1 -1
  175. package/clis/cnblogs/stats.js +7 -7
  176. package/clis/cnblogs/whoami.js +1 -1
  177. package/clis/codex/_actions.js +3 -3
  178. package/clis/codex/archive.js +1 -1
  179. package/clis/codex/ask.js +6 -6
  180. package/clis/codex/model.js +8 -8
  181. package/clis/codex/pin.js +1 -1
  182. package/clis/codex/rename.js +4 -4
  183. package/clis/codex/send.js +3 -3
  184. package/clis/codex/sidebar.js +1 -1
  185. package/clis/coingecko/categories.js +1 -1
  186. package/clis/coingecko/coin.js +1 -1
  187. package/clis/coingecko/derivatives.js +1 -1
  188. package/clis/coingecko/exchanges.js +1 -1
  189. package/clis/coingecko/global.js +1 -1
  190. package/clis/coingecko/trending.js +1 -1
  191. package/clis/confluence/search.js +1 -1
  192. package/clis/coupang/product.js +3 -3
  193. package/clis/coupang/utils.js +1 -1
  194. package/clis/crates/crate.js +1 -1
  195. package/clis/crates/search.js +1 -1
  196. package/clis/crates/utils.js +1 -1
  197. package/clis/csdn/article.js +13 -13
  198. package/clis/csdn/columns.js +1 -1
  199. package/clis/csdn/login.js +1 -1
  200. package/clis/csdn/stats.js +4 -4
  201. package/clis/csdn/whoami.js +1 -1
  202. package/clis/cto51/article.js +1 -1
  203. package/clis/cto51/whoami.js +1 -1
  204. package/clis/ctrip/flight.js +2 -2
  205. package/clis/ctrip/hotel-search.js +3 -3
  206. package/clis/ctrip/hotel-suggest.js +1 -1
  207. package/clis/ctrip/search.js +1 -1
  208. package/clis/ctrip/utils.js +6 -6
  209. package/clis/cursor/ask.js +5 -5
  210. package/clis/cursor/composer.js +2 -2
  211. package/clis/cursor/model.js +4 -4
  212. package/clis/cursor/send.js +2 -2
  213. package/clis/dblp/author.js +1 -1
  214. package/clis/dblp/paper.js +1 -1
  215. package/clis/dblp/search.js +1 -1
  216. package/clis/dblp/utils.js +1 -1
  217. package/clis/dblp/venue.js +1 -1
  218. package/clis/deepseek/ask.js +1 -1
  219. package/clis/deepseek/auth.js +2 -2
  220. package/clis/deepseek/detail.js +1 -1
  221. package/clis/deepseek/new.js +1 -1
  222. package/clis/deepseek/read.js +1 -1
  223. package/clis/deepseek/send.js +7 -7
  224. package/clis/deepseek/utils.js +25 -25
  225. package/clis/defillama/protocol.js +1 -1
  226. package/clis/defillama/protocols.js +1 -1
  227. package/clis/defillama/utils.js +1 -1
  228. package/clis/devto/auth.js +2 -2
  229. package/clis/devto/latest.js +1 -1
  230. package/clis/devto/publish.js +5 -5
  231. package/clis/devto/read.js +2 -2
  232. package/clis/devto/stats.js +3 -3
  233. package/clis/dianping/auth.js +2 -2
  234. package/clis/dianping/cityResolver.js +2 -2
  235. package/clis/dianping/search.js +1 -1
  236. package/clis/dianping/shop.js +1 -1
  237. package/clis/dianping/utils.js +1 -1
  238. package/clis/discord-app/delete.js +3 -3
  239. package/clis/discord-app/read.js +1 -1
  240. package/clis/discord-app/thread-read.js +1 -1
  241. package/clis/discord-web/auth.js +2 -2
  242. package/clis/discord-web/send.js +5 -5
  243. package/clis/dockerhub/image.js +1 -1
  244. package/clis/dockerhub/search.js +1 -1
  245. package/clis/dockerhub/utils.js +1 -1
  246. package/clis/dongchedi/koubei.js +1 -1
  247. package/clis/dongchedi/models.js +1 -1
  248. package/clis/dongchedi/score.js +1 -1
  249. package/clis/dongchedi/search.js +1 -1
  250. package/clis/dongchedi/series.js +1 -1
  251. package/clis/dongchedi/specs.js +1 -1
  252. package/clis/dongchedi/utils.js +1 -1
  253. package/clis/douban/article.js +3 -3
  254. package/clis/douban/auth.js +2 -2
  255. package/clis/douban/download.js +1 -1
  256. package/clis/douban/utils.js +23 -23
  257. package/clis/doubao/auth.js +3 -3
  258. package/clis/doubao/utils.js +39 -39
  259. package/clis/doubao-app/ask.js +1 -1
  260. package/clis/doubao-app/utils.js +4 -4
  261. package/clis/douyin/_shared/browser-fetch.js +7 -7
  262. package/clis/douyin/_shared/draft-cache.js +1 -1
  263. package/clis/douyin/_shared/imagex-upload.js +1 -1
  264. package/clis/douyin/_shared/sts2.js +1 -1
  265. package/clis/douyin/_shared/text-extra.js +1 -1
  266. package/clis/douyin/_shared/tos-upload.js +4 -4
  267. package/clis/douyin/_shared/transcode.js +1 -1
  268. package/clis/douyin/_shared/vod-upload.js +4 -4
  269. package/clis/douyin/draft.js +18 -18
  270. package/clis/douyin/drafts.js +1 -1
  271. package/clis/douyin/publish-image.js +12 -12
  272. package/clis/douyin/publish.js +9 -9
  273. package/clis/douyin/search.js +3 -3
  274. package/clis/douyin/videos.js +1 -1
  275. package/clis/eastmoney/_secid.js +1 -1
  276. package/clis/eastmoney/announcement.js +1 -1
  277. package/clis/eastmoney/article.js +1 -1
  278. package/clis/eastmoney/convertible.js +1 -1
  279. package/clis/eastmoney/etf.js +1 -1
  280. package/clis/eastmoney/holders.js +1 -1
  281. package/clis/eastmoney/index-board.js +1 -1
  282. package/clis/eastmoney/kline.js +1 -1
  283. package/clis/eastmoney/kuaixun.js +1 -1
  284. package/clis/eastmoney/longhu.js +1 -1
  285. package/clis/eastmoney/money-flow.js +1 -1
  286. package/clis/eastmoney/northbound.js +1 -1
  287. package/clis/eastmoney/quote.js +1 -1
  288. package/clis/eastmoney/rank.js +1 -1
  289. package/clis/eastmoney/sectors.js +1 -1
  290. package/clis/endoflife/product.js +1 -1
  291. package/clis/endoflife/utils.js +1 -1
  292. package/clis/facebook/comment.js +8 -8
  293. package/clis/facebook/feed.js +4 -4
  294. package/clis/facebook/like.js +5 -5
  295. package/clis/facebook/notifications.js +3 -3
  296. package/clis/facebook/post.js +11 -11
  297. package/clis/facebook/search.js +3 -3
  298. package/clis/flathub/app.js +1 -1
  299. package/clis/flathub/search.js +1 -1
  300. package/clis/flathub/utils.js +1 -1
  301. package/clis/flomo/memos.js +1 -1
  302. package/clis/gemini/deep-research-result.js +4 -4
  303. package/clis/gemini/deep-research.js +1 -1
  304. package/clis/gemini/detail.js +1 -1
  305. package/clis/gemini/history.js +1 -1
  306. package/clis/gemini/image.js +2 -2
  307. package/clis/gemini/status.js +1 -1
  308. package/clis/gemini/utils.js +43 -43
  309. package/clis/geogebra/hexagon.js +1 -1
  310. package/clis/geogebra/info.js +3 -3
  311. package/clis/geogebra/triangle.js +1 -1
  312. package/clis/geogebra/utils.js +11 -11
  313. package/clis/ghost/login.js +1 -1
  314. package/clis/ghost/shared.js +2 -2
  315. package/clis/gitee/auth.js +2 -2
  316. package/clis/github-trending/repos.js +1 -1
  317. package/clis/google/news.js +1 -1
  318. package/clis/google/search.js +2 -2
  319. package/clis/google/suggest.js +1 -1
  320. package/clis/google/trends.js +1 -1
  321. package/clis/google/utils.js +1 -1
  322. package/clis/goproxy/module.js +1 -1
  323. package/clis/goproxy/utils.js +1 -1
  324. package/clis/goproxy/versions.js +1 -1
  325. package/clis/gov-policy/recent.js +2 -2
  326. package/clis/gov-policy/search.js +2 -2
  327. package/clis/grok/ask.js +1 -1
  328. package/clis/grok/detail.js +1 -1
  329. package/clis/grok/image.js +8 -8
  330. package/clis/grok/pin.js +1 -1
  331. package/clis/grok/send.js +1 -1
  332. package/clis/grok/status.js +1 -1
  333. package/clis/grok/utils.js +21 -21
  334. package/clis/guazi/browse.js +1 -1
  335. package/clis/guazi/car.js +1 -1
  336. package/clis/guazi/utils.js +1 -1
  337. package/clis/hackernews/auth.js +2 -2
  338. package/clis/hackernews/comment.js +8 -8
  339. package/clis/hackernews/read.js +7 -7
  340. package/clis/hackernews/submit.js +7 -7
  341. package/clis/hashnode/auth.js +3 -3
  342. package/clis/hashnode/publish.js +14 -14
  343. package/clis/hf/auth.js +2 -2
  344. package/clis/hf/models.js +1 -1
  345. package/clis/hf/paper.js +1 -1
  346. package/clis/hf/spaces.js +1 -1
  347. package/clis/hf/top.js +1 -1
  348. package/clis/homebrew/cask.js +1 -1
  349. package/clis/homebrew/formula.js +1 -1
  350. package/clis/homebrew/popular.js +1 -1
  351. package/clis/homebrew/utils.js +1 -1
  352. package/clis/huodongxing/events.js +1 -1
  353. package/clis/hupu/detail.js +4 -4
  354. package/clis/hupu/hot.js +3 -3
  355. package/clis/hupu/reply.js +1 -1
  356. package/clis/hupu/search.js +1 -1
  357. package/clis/hupu/unlike.js +1 -1
  358. package/clis/hupu/utils.js +10 -10
  359. package/clis/imdb/person.js +2 -2
  360. package/clis/imdb/reviews.js +3 -3
  361. package/clis/imdb/search.js +2 -2
  362. package/clis/imdb/title.js +1 -1
  363. package/clis/imdb/top.js +1 -1
  364. package/clis/imdb/trending.js +1 -1
  365. package/clis/imdb/utils.js +13 -13
  366. package/clis/imooc/article.js +6 -6
  367. package/clis/imooc/login.js +1 -1
  368. package/clis/imooc/whoami.js +1 -1
  369. package/clis/indeed/job.js +2 -2
  370. package/clis/indeed/search.js +2 -2
  371. package/clis/indeed/utils.js +1 -1
  372. package/clis/infoq/article.js +2 -2
  373. package/clis/infoq/login.js +1 -1
  374. package/clis/infoq/whoami.js +1 -1
  375. package/clis/instagram/_shared/private-publish.js +4 -4
  376. package/clis/instagram/_shared/protocol-capture.js +9 -9
  377. package/clis/instagram/detail.js +3 -3
  378. package/clis/instagram/post.js +25 -25
  379. package/clis/instagram/reel.js +18 -18
  380. package/clis/instagram/story.js +4 -4
  381. package/clis/instagram/user.js +2 -2
  382. package/clis/jd/item.js +65 -65
  383. package/clis/jianshu/article.js +1 -1
  384. package/clis/jianshu/login.js +1 -1
  385. package/clis/jianshu/notebooks.js +1 -1
  386. package/clis/jianshu/whoami.js +1 -1
  387. package/clis/jianyu/search.js +6 -6
  388. package/clis/jianyu/shared/procurement-contract.js +1 -1
  389. package/clis/jike/api.js +6 -6
  390. package/clis/jike/auth.js +3 -3
  391. package/clis/jike/comment.js +1 -1
  392. package/clis/jike/create.js +6 -6
  393. package/clis/jike/feed.js +3 -3
  394. package/clis/jike/like.js +1 -1
  395. package/clis/jike/notifications.js +3 -3
  396. package/clis/jike/repost.js +13 -13
  397. package/clis/jike/search.js +3 -3
  398. package/clis/jimeng/auth.js +2 -2
  399. package/clis/jimeng/generate.js +10 -10
  400. package/clis/jira/shared.js +1 -1
  401. package/clis/juejin/article.js +4 -4
  402. package/clis/juejin/categories.js +1 -1
  403. package/clis/juejin/hot.js +1 -1
  404. package/clis/juejin/login.js +1 -1
  405. package/clis/juejin/recommend.js +1 -1
  406. package/clis/juejin/stats.js +3 -3
  407. package/clis/juejin/tags.js +1 -1
  408. package/clis/juejin/utils.js +1 -1
  409. package/clis/juejin/whoami.js +1 -1
  410. package/clis/ke/utils.js +4 -4
  411. package/clis/kimi/_utils.js +7 -7
  412. package/clis/kimi/audit-extras.js +14 -14
  413. package/clis/kimi/auth.js +3 -3
  414. package/clis/kimi/chat.js +15 -15
  415. package/clis/kimi/storage.js +5 -5
  416. package/clis/kimi/ui.js +13 -13
  417. package/clis/kimi/usage.js +3 -3
  418. package/clis/kuaishou/auth.js +1 -1
  419. package/clis/kuaishou/publish.js +6 -6
  420. package/clis/lesswrong/_helpers.js +5 -5
  421. package/clis/lesswrong/comments.js +5 -5
  422. package/clis/lichess/top.js +1 -1
  423. package/clis/lichess/user.js +1 -1
  424. package/clis/lichess/utils.js +1 -1
  425. package/clis/linkedin/comment.js +1 -1
  426. package/clis/linkedin/connect.js +11 -11
  427. package/clis/linkedin/create.js +5 -5
  428. package/clis/linkedin/follow.js +1 -1
  429. package/clis/linkedin/inbox.js +1 -1
  430. package/clis/linkedin/job-detail.js +3 -3
  431. package/clis/linkedin/like.js +1 -1
  432. package/clis/linkedin/notifications.js +1 -1
  433. package/clis/linkedin/people-search.js +1 -1
  434. package/clis/linkedin/post-comments.js +1 -1
  435. package/clis/linkedin/post-detail.js +1 -1
  436. package/clis/linkedin/profile-analytics.js +1 -1
  437. package/clis/linkedin/profile-api.js +13 -13
  438. package/clis/linkedin/profile-experience.js +1 -1
  439. package/clis/linkedin/profile-projects.js +1 -1
  440. package/clis/linkedin/profile-read.js +3 -3
  441. package/clis/linkedin/reply.js +1 -1
  442. package/clis/linkedin/repost.js +1 -1
  443. package/clis/linkedin/safe-send.js +8 -8
  444. package/clis/linkedin/salesnav-inbox.js +5 -5
  445. package/clis/linkedin/salesnav-message.js +3 -3
  446. package/clis/linkedin/salesnav-search.js +4 -4
  447. package/clis/linkedin/salesnav-thread.js +1 -1
  448. package/clis/linkedin/search-api.js +3 -3
  449. package/clis/linkedin/search.js +8 -8
  450. package/clis/linkedin/social-api.js +31 -31
  451. package/clis/linkedin/timeline.js +3 -3
  452. package/clis/linkedin-learning/search.js +2 -2
  453. package/clis/linkedin-learning/trending.js +2 -2
  454. package/clis/linux-do/feed.js +4 -4
  455. package/clis/linux-do/topic-content.js +8 -8
  456. package/clis/lobsters/domain.js +1 -1
  457. package/clis/lobsters/read.js +7 -7
  458. package/clis/maimai/auth.js +2 -2
  459. package/clis/maimai/search-talents.js +4 -4
  460. package/clis/manus/_utils.js +1 -1
  461. package/clis/mastodon/login.js +1 -1
  462. package/clis/mastodon/post.js +1 -1
  463. package/clis/mastodon/shared.js +12 -12
  464. package/clis/mastodon/whoami.js +1 -1
  465. package/clis/maven/artifact.js +1 -1
  466. package/clis/maven/search.js +1 -1
  467. package/clis/maven/utils.js +1 -1
  468. package/clis/mdn/search.js +1 -1
  469. package/clis/medium/article.js +5 -5
  470. package/clis/medium/login.js +1 -1
  471. package/clis/medium/stats.js +3 -3
  472. package/clis/medium/tag.js +1 -1
  473. package/clis/medium/whoami.js +1 -1
  474. package/clis/mubu/notes.js +1 -1
  475. package/clis/mubu/utils.js +15 -15
  476. package/clis/note/auth.js +2 -2
  477. package/clis/note/note-utils.js +2 -2
  478. package/clis/note/publish.js +8 -8
  479. package/clis/notebooklm/add-source.js +8 -8
  480. package/clis/notebooklm/create.js +1 -1
  481. package/clis/notebooklm/generate-slides.js +1 -1
  482. package/clis/notebooklm/notes-get.js +1 -1
  483. package/clis/notebooklm/rpc.js +8 -8
  484. package/clis/notebooklm/source-fulltext.js +1 -1
  485. package/clis/notebooklm/utils.js +10 -10
  486. package/clis/nowcoder/auth.js +2 -2
  487. package/clis/nowcoder/comment.js +1 -1
  488. package/clis/nowcoder/comments.js +1 -1
  489. package/clis/nowcoder/dm-list.js +1 -1
  490. package/clis/nowcoder/dm-read.js +1 -1
  491. package/clis/nowcoder/dm-send.js +1 -1
  492. package/clis/nowcoder/drafts.js +1 -1
  493. package/clis/nowcoder/inbox.js +1 -1
  494. package/clis/nowcoder/like.js +1 -1
  495. package/clis/nowcoder/my.js +1 -1
  496. package/clis/nowcoder/post.js +1 -1
  497. package/clis/nowcoder/utils.js +13 -13
  498. package/clis/npm/downloads.js +1 -1
  499. package/clis/npm/package.js +1 -1
  500. package/clis/npm/search.js +1 -1
  501. package/clis/npm/utils.js +1 -1
  502. package/clis/nuget/package.js +1 -1
  503. package/clis/nuget/search.js +1 -1
  504. package/clis/nuget/utils.js +1 -1
  505. package/clis/nvd/cve.js +1 -1
  506. package/clis/oeis/search.js +1 -1
  507. package/clis/oeis/sequence.js +1 -1
  508. package/clis/oeis/utils.js +1 -1
  509. package/clis/ones/common.js +6 -6
  510. package/clis/ones/enrich-tasks.js +1 -1
  511. package/clis/ones/my-tasks.js +1 -1
  512. package/clis/ones/resolve-labels.js +1 -1
  513. package/clis/ones/task-helpers.js +1 -1
  514. package/clis/ones/task.js +1 -1
  515. package/clis/ones/worklog.js +7 -7
  516. package/clis/openalex/search.js +1 -1
  517. package/clis/openalex/utils.js +1 -1
  518. package/clis/openalex/work.js +1 -1
  519. package/clis/openfda/drug-label.js +1 -1
  520. package/clis/openfda/food-recall.js +1 -1
  521. package/clis/openfda/utils.js +1 -1
  522. package/clis/openreview/author.js +1 -1
  523. package/clis/openreview/paper.js +1 -1
  524. package/clis/openreview/reviews.js +3 -3
  525. package/clis/openreview/search.js +1 -1
  526. package/clis/openreview/utils.js +1 -1
  527. package/clis/openreview/venue.js +1 -1
  528. package/clis/oschina/article.js +1 -1
  529. package/clis/oschina/catalogs.js +1 -1
  530. package/clis/oschina/login.js +1 -1
  531. package/clis/oschina/stats.js +6 -6
  532. package/clis/oschina/whoami.js +1 -1
  533. package/clis/osv/query.js +1 -1
  534. package/clis/osv/utils.js +1 -1
  535. package/clis/osv/vulnerability.js +1 -1
  536. package/clis/packagist/package.js +1 -1
  537. package/clis/packagist/search.js +1 -1
  538. package/clis/packagist/utils.js +1 -1
  539. package/clis/pinterest/api.js +1 -1
  540. package/clis/pinterest/auth.js +1 -1
  541. package/clis/pinterest/boards.js +1 -1
  542. package/clis/pinterest/client.js +6 -6
  543. package/clis/pinterest/publish.js +5 -5
  544. package/clis/pixiv/auth.js +2 -2
  545. package/clis/pixiv/download.js +1 -1
  546. package/clis/pixiv/illusts.js +1 -1
  547. package/clis/pixiv/search.js +1 -1
  548. package/clis/pixiv/utils.js +3 -3
  549. package/clis/powerchina/auth.js +2 -2
  550. package/clis/powerchina/search.js +1 -1
  551. package/clis/producthunt/browse.js +2 -2
  552. package/clis/producthunt/hot.js +2 -2
  553. package/clis/producthunt/posts.js +1 -1
  554. package/clis/producthunt/today.js +1 -1
  555. package/clis/producthunt/utils.js +1 -1
  556. package/clis/pypi/downloads.js +1 -1
  557. package/clis/pypi/package.js +1 -1
  558. package/clis/pypi/utils.js +1 -1
  559. package/clis/qiita/auth.js +1 -1
  560. package/clis/qiita/gql.js +6 -6
  561. package/clis/qiita/publish.js +4 -4
  562. package/clis/qiita/stats.js +4 -4
  563. package/clis/qoder/_utils.js +16 -16
  564. package/clis/qoder/composer.js +1 -1
  565. package/clis/qoder/quest.js +1 -1
  566. package/clis/qoder/ui.js +14 -14
  567. package/clis/quark/auth.js +2 -2
  568. package/clis/quark/utils.js +2 -2
  569. package/clis/quora/answer-comments.js +3 -3
  570. package/clis/quora/create-answer.js +4 -4
  571. package/clis/quora/create-question.js +3 -3
  572. package/clis/quora/shared.js +17 -17
  573. package/clis/quora/whoami.js +1 -1
  574. package/clis/qwen/ask.js +1 -1
  575. package/clis/qwen/auth.js +3 -3
  576. package/clis/qwen/detail.js +1 -1
  577. package/clis/qwen/image.js +5 -5
  578. package/clis/qwen/status.js +1 -1
  579. package/clis/qwen/utils.js +16 -16
  580. package/clis/reddit/home.js +3 -3
  581. package/clis/reddit/read.js +10 -10
  582. package/clis/reddit/reply.js +4 -4
  583. package/clis/reddit/submit.js +11 -11
  584. package/clis/reddit/subreddit-info.js +3 -3
  585. package/clis/reddit/subscribed.js +4 -4
  586. package/clis/reddit/whoami.js +2 -2
  587. package/clis/rednote/comments.js +1 -1
  588. package/clis/rednote/download.js +1 -1
  589. package/clis/rednote/feed.js +1 -1
  590. package/clis/rednote/note.js +1 -1
  591. package/clis/rednote/notifications.js +2 -2
  592. package/clis/rednote/search.js +2 -2
  593. package/clis/rest-countries/country.js +1 -1
  594. package/clis/rest-countries/region.js +1 -1
  595. package/clis/rest-countries/utils.js +1 -1
  596. package/clis/reuters/article-detail.js +1 -1
  597. package/clis/reuters/auth.js +3 -3
  598. package/clis/reuters/search.js +1 -1
  599. package/clis/reuters/utils.js +4 -4
  600. package/clis/rfc/rfc.js +1 -1
  601. package/clis/rfc/utils.js +1 -1
  602. package/clis/rubygems/gem.js +1 -1
  603. package/clis/rubygems/search.js +1 -1
  604. package/clis/rubygems/utils.js +1 -1
  605. package/clis/segmentfault/article.js +3 -3
  606. package/clis/segmentfault/channels.js +1 -1
  607. package/clis/segmentfault/login.js +1 -1
  608. package/clis/segmentfault/stats.js +4 -4
  609. package/clis/segmentfault/tags.js +1 -1
  610. package/clis/segmentfault/whoami.js +1 -1
  611. package/clis/semanticscholar/citations.js +1 -1
  612. package/clis/semanticscholar/paper.js +1 -1
  613. package/clis/semanticscholar/recommendations.js +1 -1
  614. package/clis/semanticscholar/search.js +1 -1
  615. package/clis/semanticscholar/utils.js +1 -1
  616. package/clis/sinafinance/news.js +1 -1
  617. package/clis/sinafinance/stock-rank.js +1 -1
  618. package/clis/sinafinance/stock.js +1 -1
  619. package/clis/slock/attachment-download.js +1 -1
  620. package/clis/slock/attachment-upload.js +7 -7
  621. package/clis/slock/attachment-url.js +1 -1
  622. package/clis/slock/auth-verify.js +1 -1
  623. package/clis/slock/bookmark-add.js +1 -1
  624. package/clis/slock/bookmark-remove.js +1 -1
  625. package/clis/slock/channel-action.js +1 -1
  626. package/clis/slock/channel-create.js +1 -1
  627. package/clis/slock/channel-files.js +1 -1
  628. package/clis/slock/channel-list.js +1 -1
  629. package/clis/slock/channel-mark.js +1 -1
  630. package/clis/slock/channel-members.js +1 -1
  631. package/clis/slock/channel-unarchive.js +1 -1
  632. package/clis/slock/dm-list.js +1 -1
  633. package/clis/slock/errors.js +1 -1
  634. package/clis/slock/in-page.js +28 -28
  635. package/clis/slock/inbox-done.js +5 -5
  636. package/clis/slock/inbox.js +1 -1
  637. package/clis/slock/message-read.js +22 -22
  638. package/clis/slock/message-search.js +10 -10
  639. package/clis/slock/message-send.js +25 -25
  640. package/clis/slock/reaction-add.js +1 -1
  641. package/clis/slock/reaction-remove.js +1 -1
  642. package/clis/slock/resolve.js +1 -1
  643. package/clis/slock/server-list.js +2 -2
  644. package/clis/slock/task-claim.js +4 -4
  645. package/clis/slock/task-convert.js +13 -13
  646. package/clis/slock/task-create.js +1 -1
  647. package/clis/slock/task-delete.js +5 -5
  648. package/clis/slock/task-get.js +5 -5
  649. package/clis/slock/task-list-server.js +4 -4
  650. package/clis/slock/task-list.js +5 -5
  651. package/clis/slock/task-status.js +3 -3
  652. package/clis/slock/task-unclaim.js +3 -3
  653. package/clis/slock/thread-follow.js +1 -1
  654. package/clis/slock/thread-state.js +1 -1
  655. package/clis/slock/unread-summary.js +5 -5
  656. package/clis/slock/whoami.js +1 -1
  657. package/clis/smzdm/search.js +3 -3
  658. package/clis/sohu/article.js +1 -1
  659. package/clis/sohu/attributes.js +1 -1
  660. package/clis/sohu/categories.js +1 -1
  661. package/clis/sohu/channels.js +1 -1
  662. package/clis/sohu/columns.js +1 -1
  663. package/clis/sohu/login.js +1 -1
  664. package/clis/sohu/stats.js +3 -3
  665. package/clis/sohu/topics.js +1 -1
  666. package/clis/sohu/whoami.js +1 -1
  667. package/clis/spotify/spotify.js +1 -1
  668. package/clis/stackoverflow/read.js +6 -6
  669. package/clis/stackoverflow/related.js +1 -1
  670. package/clis/stackoverflow/tag.js +1 -1
  671. package/clis/stackoverflow/user.js +1 -1
  672. package/clis/stackoverflow/utils.js +1 -1
  673. package/clis/steam/app.js +1 -1
  674. package/clis/steam/search.js +1 -1
  675. package/clis/steam/utils.js +1 -1
  676. package/clis/substack/auth.js +2 -2
  677. package/clis/substack/post-utils.js +2 -2
  678. package/clis/substack/publish.js +5 -5
  679. package/clis/suno/auth.js +2 -2
  680. package/clis/suno/download.js +5 -5
  681. package/clis/suno/generate.js +3 -3
  682. package/clis/suno/list.js +1 -1
  683. package/clis/suno/status.js +1 -1
  684. package/clis/suno/utils.js +29 -29
  685. package/clis/telegram/send.js +7 -7
  686. package/clis/telegram/shared.js +2 -2
  687. package/clis/telegram/whoami.js +1 -1
  688. package/clis/test-utils.js +1 -1
  689. package/clis/threads/post.js +23 -23
  690. package/clis/threads/shared.js +3 -3
  691. package/clis/threads/whoami.js +1 -1
  692. package/clis/tieba/hot.js +3 -3
  693. package/clis/tieba/posts.js +1 -1
  694. package/clis/tieba/read.js +2 -2
  695. package/clis/tieba/search.js +3 -3
  696. package/clis/tieba/utils.js +1 -1
  697. package/clis/tiktok/comment.js +2 -2
  698. package/clis/tiktok/creator-videos.js +3 -3
  699. package/clis/tiktok/explore.js +3 -3
  700. package/clis/tiktok/follow.js +8 -8
  701. package/clis/tiktok/following.js +4 -4
  702. package/clis/tiktok/friends.js +7 -7
  703. package/clis/tiktok/live.js +3 -3
  704. package/clis/tiktok/notifications.js +6 -6
  705. package/clis/tiktok/publish.js +16 -16
  706. package/clis/tiktok/unfollow.js +4 -4
  707. package/clis/tiktok/user.js +2 -2
  708. package/clis/tiktok/utils.js +1 -1
  709. package/clis/toutiao/article.js +1 -1
  710. package/clis/toutiao/articles.js +2 -2
  711. package/clis/toutiao/auth.js +2 -2
  712. package/clis/toutiao/hot.js +1 -1
  713. package/clis/toutiao/recommend.js +1 -1
  714. package/clis/toutiao/utils.js +2 -2
  715. package/clis/trae-solo/_actions.js +4 -4
  716. package/clis/trae-solo/_fs.js +5 -5
  717. package/clis/trae-solo/_state.js +2 -2
  718. package/clis/trae-solo/automation.js +4 -4
  719. package/clis/trae-solo/mode.js +4 -4
  720. package/clis/trae-solo/model.js +4 -4
  721. package/clis/trae-solo/renderer-storage.js +4 -4
  722. package/clis/trae-solo/settings.js +1 -1
  723. package/clis/trae-solo/skill-fs.js +1 -1
  724. package/clis/trae-solo/skill.js +12 -12
  725. package/clis/trae-solo/state-fs.js +2 -2
  726. package/clis/trae-solo/task-fs.js +5 -5
  727. package/clis/trae-solo/workspaces-fs.js +1 -1
  728. package/clis/tumblr/auth.js +2 -2
  729. package/clis/tumblr/publish.js +3 -3
  730. package/clis/tvmaze/search.js +1 -1
  731. package/clis/tvmaze/show.js +1 -1
  732. package/clis/tvmaze/utils.js +1 -1
  733. package/clis/twitter/accept.js +7 -7
  734. package/clis/twitter/article.js +7 -7
  735. package/clis/twitter/bookmark-folder.js +3 -3
  736. package/clis/twitter/bookmark-folders.js +3 -3
  737. package/clis/twitter/bookmarks.js +4 -4
  738. package/clis/twitter/delete.js +5 -5
  739. package/clis/twitter/device-follow.js +3 -3
  740. package/clis/twitter/dm-list.js +1 -1
  741. package/clis/twitter/dm-read.js +1 -1
  742. package/clis/twitter/dm-send.js +5 -5
  743. package/clis/twitter/dm-shared.js +3 -3
  744. package/clis/twitter/download.js +6 -6
  745. package/clis/twitter/followers.js +5 -5
  746. package/clis/twitter/following.js +2 -2
  747. package/clis/twitter/like.js +3 -3
  748. package/clis/twitter/likes.js +8 -8
  749. package/clis/twitter/list-add-core.js +9 -9
  750. package/clis/twitter/list-create.js +5 -5
  751. package/clis/twitter/list-remove-core.js +9 -9
  752. package/clis/twitter/list-tweets.js +7 -7
  753. package/clis/twitter/lists.js +6 -6
  754. package/clis/twitter/notifications.js +2 -2
  755. package/clis/twitter/post.js +24 -24
  756. package/clis/twitter/profile.js +7 -7
  757. package/clis/twitter/quote.js +7 -7
  758. package/clis/twitter/reply-dm.js +7 -7
  759. package/clis/twitter/reply.js +12 -12
  760. package/clis/twitter/retweet.js +3 -3
  761. package/clis/twitter/scheduled-delete.js +3 -3
  762. package/clis/twitter/scheduled-list.js +2 -2
  763. package/clis/twitter/scheduled-utils.js +3 -3
  764. package/clis/twitter/search.js +5 -5
  765. package/clis/twitter/shared.js +6 -6
  766. package/clis/twitter/thread.js +4 -4
  767. package/clis/twitter/timeline.js +3 -3
  768. package/clis/twitter/trending.js +2 -2
  769. package/clis/twitter/tweets.js +11 -11
  770. package/clis/twitter/unlike.js +3 -3
  771. package/clis/twitter/unretweet.js +3 -3
  772. package/clis/twitter/utils.js +6 -6
  773. package/clis/upwork/detail.js +2 -2
  774. package/clis/upwork/feed.js +2 -2
  775. package/clis/upwork/search.js +2 -2
  776. package/clis/upwork/utils.js +1 -1
  777. package/clis/v2ex/auth.js +2 -2
  778. package/clis/v2ex/daily.js +3 -3
  779. package/clis/v2ex/me.js +2 -2
  780. package/clis/v2ex/notifications.js +2 -2
  781. package/clis/vk/post.js +1 -1
  782. package/clis/vk/shared.js +2 -2
  783. package/clis/vk/whoami.js +1 -1
  784. package/clis/web/read.js +8 -8
  785. package/clis/wechat-channels/auth.js +2 -2
  786. package/clis/wechat-channels/publish.js +30 -30
  787. package/clis/weibo/article.js +1 -1
  788. package/clis/weibo/auth.js +3 -3
  789. package/clis/weibo/comments.js +1 -1
  790. package/clis/weibo/delete.js +2 -2
  791. package/clis/weibo/feed.js +3 -3
  792. package/clis/weibo/hot.js +1 -1
  793. package/clis/weibo/publish.js +10 -10
  794. package/clis/weibo/search.js +2 -2
  795. package/clis/weibo/user-posts.js +3 -3
  796. package/clis/weibo/user.js +2 -2
  797. package/clis/weibo/utils.js +3 -3
  798. package/clis/weixin/article.js +1 -1
  799. package/clis/weixin/create-draft.js +26 -26
  800. package/clis/weixin/download.js +2 -2
  801. package/clis/weixin/login.js +1 -1
  802. package/clis/weixin/search.js +2 -2
  803. package/clis/weixin/stats.js +3 -3
  804. package/clis/weixin/whoami.js +1 -1
  805. package/clis/weread/ai-outline.js +2 -2
  806. package/clis/weread/book-search.js +2 -2
  807. package/clis/weread/book.js +2 -2
  808. package/clis/weread/notebooks.js +1 -1
  809. package/clis/weread/search.js +1 -1
  810. package/clis/weread/shelf.js +1 -1
  811. package/clis/weread/utils.js +6 -6
  812. package/clis/weread-official/book.js +1 -1
  813. package/clis/weread-official/discover.js +1 -1
  814. package/clis/weread-official/list-apis.js +1 -1
  815. package/clis/weread-official/notes.js +1 -1
  816. package/clis/weread-official/readdata.js +1 -1
  817. package/clis/weread-official/review.js +1 -1
  818. package/clis/weread-official/search.js +1 -1
  819. package/clis/weread-official/shelf.js +1 -1
  820. package/clis/weread-official/utils.js +1 -1
  821. package/clis/wikidata/entity.js +1 -1
  822. package/clis/wikidata/search.js +1 -1
  823. package/clis/wikidata/utils.js +1 -1
  824. package/clis/wikipedia/page.js +1 -1
  825. package/clis/wikipedia/trending.js +1 -1
  826. package/clis/wikipedia/utils.js +1 -1
  827. package/clis/wordpress/login.js +1 -1
  828. package/clis/wordpress/publish.js +1 -1
  829. package/clis/wordpress/shared.js +3 -3
  830. package/clis/wordpress/whoami.js +1 -1
  831. package/clis/woshipm/article.js +1 -1
  832. package/clis/woshipm/login.js +1 -1
  833. package/clis/woshipm/stats.js +4 -4
  834. package/clis/woshipm/whoami.js +1 -1
  835. package/clis/wttr/current.js +1 -1
  836. package/clis/wttr/forecast.js +1 -1
  837. package/clis/wttr/utils.js +1 -1
  838. package/clis/xianyu/collect.js +1 -1
  839. package/clis/xianyu/inbox.js +1 -1
  840. package/clis/xianyu/item-stats.js +2 -2
  841. package/clis/xianyu/location.js +1 -1
  842. package/clis/xianyu/manage.js +1 -1
  843. package/clis/xianyu/messages.js +1 -1
  844. package/clis/xianyu/mtop.js +5 -5
  845. package/clis/xianyu/order.js +1 -1
  846. package/clis/xianyu/promote-stats.js +2 -2
  847. package/clis/xianyu/publish.js +17 -17
  848. package/clis/xianyu/rate.js +1 -1
  849. package/clis/xianyu/reply.js +1 -1
  850. package/clis/xianyu/search.js +8 -8
  851. package/clis/xianyu/seller-data.js +1 -1
  852. package/clis/xianyu/seller-list.js +1 -1
  853. package/clis/xianyu/user.js +1 -1
  854. package/clis/xiaoe/catalog.js +2 -2
  855. package/clis/xiaoe/content.js +2 -2
  856. package/clis/xiaoe/courses.js +2 -2
  857. package/clis/xiaohongshu/ask.js +6 -6
  858. package/clis/xiaohongshu/comments.js +6 -6
  859. package/clis/xiaohongshu/creator-note-detail.js +7 -7
  860. package/clis/xiaohongshu/creator-notes-summary.js +1 -1
  861. package/clis/xiaohongshu/creator-notes.js +13 -13
  862. package/clis/xiaohongshu/creator-profile.js +2 -2
  863. package/clis/xiaohongshu/creator-stats.js +2 -2
  864. package/clis/xiaohongshu/delete-note.js +7 -7
  865. package/clis/xiaohongshu/download.js +4 -4
  866. package/clis/xiaohongshu/feed.js +2 -2
  867. package/clis/xiaohongshu/follow.js +3 -3
  868. package/clis/xiaohongshu/human.js +3 -3
  869. package/clis/xiaohongshu/note-helpers.js +1 -1
  870. package/clis/xiaohongshu/note.js +2 -2
  871. package/clis/xiaohongshu/notifications.js +1 -1
  872. package/clis/xiaohongshu/publish-video.js +8 -8
  873. package/clis/xiaohongshu/publish.js +59 -59
  874. package/clis/xiaohongshu/search.js +8 -8
  875. package/clis/xiaohongshu/unfollow.js +4 -4
  876. package/clis/xiaohongshu/user-helpers.js +1 -1
  877. package/clis/xiaohongshu/user.js +2 -2
  878. package/clis/xiaoyuzhou/auth.js +3 -3
  879. package/clis/xiaoyuzhou/download.js +1 -1
  880. package/clis/xiaoyuzhou/utils.js +1 -1
  881. package/clis/xueqiu/article.js +4 -4
  882. package/clis/xueqiu/comments.js +4 -4
  883. package/clis/xueqiu/danjuan-utils.js +4 -4
  884. package/clis/xueqiu/earnings-date.js +1 -1
  885. package/clis/xueqiu/events.js +3 -3
  886. package/clis/xueqiu/hashtags.js +3 -3
  887. package/clis/xueqiu/stocks.js +3 -3
  888. package/clis/xueqiu/users.js +3 -3
  889. package/clis/xueqiu/utils.js +3 -3
  890. package/clis/yahoo-finance/quote.js +1 -1
  891. package/clis/yollomi/background.js +1 -1
  892. package/clis/yollomi/edit.js +1 -1
  893. package/clis/yollomi/face-swap.js +1 -1
  894. package/clis/yollomi/generate.js +1 -1
  895. package/clis/yollomi/object-remover.js +1 -1
  896. package/clis/yollomi/remove-bg.js +1 -1
  897. package/clis/yollomi/restore.js +1 -1
  898. package/clis/yollomi/try-on.js +1 -1
  899. package/clis/yollomi/upload.js +4 -4
  900. package/clis/yollomi/upscale.js +1 -1
  901. package/clis/yollomi/utils.js +4 -4
  902. package/clis/yollomi/video.js +1 -1
  903. package/clis/youtube/channel.js +4 -4
  904. package/clis/youtube/feed.js +2 -2
  905. package/clis/youtube/like.js +5 -5
  906. package/clis/youtube/playlist.js +7 -7
  907. package/clis/youtube/publish.js +11 -11
  908. package/clis/youtube/search.js +3 -3
  909. package/clis/youtube/subscribe.js +7 -7
  910. package/clis/youtube/subscriptions.js +1 -1
  911. package/clis/youtube/transcript-group.js +2 -2
  912. package/clis/youtube/transcript.js +13 -13
  913. package/clis/youtube/unlike.js +5 -5
  914. package/clis/youtube/unsubscribe.js +7 -7
  915. package/clis/youtube/utils.js +3 -3
  916. package/clis/youtube/video.js +4 -4
  917. package/clis/youtube/watch-later.js +2 -2
  918. package/clis/yuanbao/ask.js +18 -18
  919. package/clis/yuanbao/detail.js +1 -1
  920. package/clis/yuanbao/read.js +1 -1
  921. package/clis/yuanbao/shared.js +9 -9
  922. package/clis/yuanbao/status.js +1 -1
  923. package/clis/yuque/article.js +1 -1
  924. package/clis/yuque/whoami.js +1 -1
  925. package/clis/zhihu/answer-comments.js +2 -2
  926. package/clis/zhihu/answer-detail.js +3 -3
  927. package/clis/zhihu/answer.js +1 -1
  928. package/clis/zhihu/article-transform.js +1 -1
  929. package/clis/zhihu/article.js +1 -1
  930. package/clis/zhihu/auth.js +2 -2
  931. package/clis/zhihu/collection.js +3 -3
  932. package/clis/zhihu/collections.js +3 -3
  933. package/clis/zhihu/download.js +2 -2
  934. package/clis/zhihu/image-profile.js +6 -6
  935. package/clis/zhihu/paginate.js +3 -3
  936. package/clis/zhihu/pin.js +4 -4
  937. package/clis/zhihu/question.js +3 -3
  938. package/clis/zhihu/recommend.js +3 -3
  939. package/clis/zhihu/search.js +3 -3
  940. package/clis/zhihu/stats.js +3 -3
  941. package/clis/zhihu/user-arg.js +1 -1
  942. package/clis/zhihu/write-shared.js +7 -7
  943. package/clis/zlibrary/utils.js +6 -6
  944. package/clis/zsxq/auth.js +3 -3
  945. package/clis/zsxq/search.js +1 -1
  946. package/clis/zsxq/topic.js +1 -1
  947. package/clis/zsxq/utils.js +5 -5
  948. package/dist/src/adapter-source.js +1 -1
  949. package/dist/src/browser/analyze.js +1 -1
  950. package/dist/src/browser/article-extract.js +2 -2
  951. package/dist/src/browser/ax-snapshot.js +2 -2
  952. package/dist/src/browser/base-page.js +25 -25
  953. package/dist/src/browser/bridge.js +1 -1
  954. package/dist/src/browser/cdp.js +1 -1
  955. package/dist/src/browser/daemon-client.js +1 -1
  956. package/dist/src/browser/daemon-lifecycle.js +7 -7
  957. package/dist/src/browser/dom-helpers.js +35 -35
  958. package/dist/src/browser/dom-snapshot.js +19 -19
  959. package/dist/src/browser/errors.js +3 -3
  960. package/dist/src/browser/extract.js +5 -5
  961. package/dist/src/browser/find.js +13 -13
  962. package/dist/src/browser/fingerprint.js +2 -2
  963. package/dist/src/browser/html-tree.js +6 -6
  964. package/dist/src/browser/managed-chrome.js +1 -1
  965. package/dist/src/browser/network-cache.js +1 -1
  966. package/dist/src/browser/network-key.js +1 -1
  967. package/dist/src/browser/page.js +7 -7
  968. package/dist/src/browser/profile.js +2 -2
  969. package/dist/src/browser/proxy-test.js +8 -8
  970. package/dist/src/browser/shape-filter.js +1 -1
  971. package/dist/src/browser/shape.js +1 -1
  972. package/dist/src/browser/stealth.js +3 -3
  973. package/dist/src/browser/tabs.js +2 -2
  974. package/dist/src/browser/target-errors.js +1 -1
  975. package/dist/src/browser/target-resolver.js +23 -23
  976. package/dist/src/browser/trace.js +2 -2
  977. package/dist/src/browser/utils.js +1 -1
  978. package/dist/src/browser/verify-fixture.js +2 -2
  979. package/dist/src/browser-session-lock.js +1 -1
  980. package/dist/src/build-manifest.js +11 -11
  981. package/dist/src/capabilityRouting.js +1 -1
  982. package/dist/src/cli-argv-preprocess.js +1 -1
  983. package/dist/src/cli.js +32 -32
  984. package/dist/src/commanderAdapter.js +3 -3
  985. package/dist/src/commands/auth.js +3 -3
  986. package/dist/src/commands/daemon.js +1 -1
  987. package/dist/src/completion-fast.js +1 -1
  988. package/dist/src/completion.js +1 -1
  989. package/dist/src/constants.js +1 -1
  990. package/dist/src/convention-audit.js +2 -2
  991. package/dist/src/daemon-utils.js +1 -1
  992. package/dist/src/daemon.js +1 -1
  993. package/dist/src/discovery.js +2 -2
  994. package/dist/src/doctor.js +9 -9
  995. package/dist/src/download/article-download.js +15 -15
  996. package/dist/src/download/index.js +4 -4
  997. package/dist/src/download/media-download.js +1 -1
  998. package/dist/src/download/progress.js +3 -3
  999. package/dist/src/electron-apps.js +1 -1
  1000. package/dist/src/errors.js +2 -2
  1001. package/dist/src/execution.js +2 -2
  1002. package/dist/src/external.js +1 -1
  1003. package/dist/src/help.js +8 -8
  1004. package/dist/src/hooks.js +1 -1
  1005. package/dist/src/interceptor.js +21 -21
  1006. package/dist/src/launcher.js +7 -7
  1007. package/dist/src/logger.js +8 -8
  1008. package/dist/src/main.js +7 -7
  1009. package/dist/src/observation/artifact.js +5 -5
  1010. package/dist/src/observation/retention.js +1 -1
  1011. package/dist/src/output.js +2 -2
  1012. package/dist/src/package-paths.js +1 -1
  1013. package/dist/src/pipeline/executor.js +1 -1
  1014. package/dist/src/pipeline/registry.js +1 -1
  1015. package/dist/src/pipeline/steps/browser.js +1 -1
  1016. package/dist/src/pipeline/steps/download.js +1 -1
  1017. package/dist/src/pipeline/steps/fetch.js +6 -6
  1018. package/dist/src/pipeline/steps/intercept.js +1 -1
  1019. package/dist/src/pipeline/steps/tap.js +17 -17
  1020. package/dist/src/pipeline/steps/transform.js +1 -1
  1021. package/dist/src/pipeline/template.js +1 -1
  1022. package/dist/src/plugin-manifest.js +1 -1
  1023. package/dist/src/plugin-scaffold.js +19 -19
  1024. package/dist/src/plugin.js +12 -12
  1025. package/dist/src/rate-limit.js +1 -1
  1026. package/dist/src/registry.js +1 -1
  1027. package/dist/src/runtime-detect.js +1 -1
  1028. package/dist/src/runtime.js +1 -1
  1029. package/dist/src/scripts/framework.js +1 -1
  1030. package/dist/src/scripts/interact.js +1 -1
  1031. package/dist/src/scripts/store.js +1 -1
  1032. package/dist/src/serialization.js +2 -2
  1033. package/dist/src/session-lease.js +1 -1
  1034. package/dist/src/snapshotFormatter.js +2 -2
  1035. package/dist/src/tui.js +12 -12
  1036. package/dist/src/user-runtime.js +1 -1
  1037. package/dist/src/utils.d.ts +12 -0
  1038. package/dist/src/utils.js +4 -4
  1039. package/dist/src/validate.js +2 -2
  1040. package/dist/src/verify.js +2 -2
  1041. package/dist/src/version.js +1 -1
  1042. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
- import{cli as N,Strategy as P}from"@jackwener/opencli/registry";import{ArgumentError as Q,CommandExecutionError as L,selectorError as T}from"@jackwener/opencli/errors";import{unwrapEvaluateResult as J}from"./_actions.js";N({site:"antigravity",name:"model",access:"write",description:"Read or switch the active model in Antigravity. Without arguments, reports the current model. With <name> (substring, case-insensitive), switches.",domain:"127.0.0.1",strategy:P.UI,browser:!0,args:[{name:"name",required:!1,positional:!0,help:"Substring (case-insensitive) of target model name. Omit to read current."},{name:"list",type:"boolean",default:!1,help:"List models in the picker (does not switch)"}],columns:["Status","Model"],func:async(F,G)=>{const K=String(G.name||"").trim().toLowerCase(),H=G.list===!0||G.list==="true",B=(D)=>String(D||"").trim().replace(/\s+/g," ").toLowerCase(),I=J(await F.evaluate(`(function() {
1
+ import{cli as m,Strategy as h}from"@jackwener/opencli/registry";import{ArgumentError as b,CommandExecutionError as u,selectorError as g}from"@jackwener/opencli/errors";import{unwrapEvaluateResult as l}from"./_actions.js";m({site:"antigravity",name:"model",access:"write",description:"Read or switch the active model in Antigravity. Without arguments, reports the current model. With <name> (substring, case-insensitive), switches.",domain:"127.0.0.1",strategy:h.UI,browser:!0,args:[{name:"name",required:!1,positional:!0,help:"Substring (case-insensitive) of target model name. Omit to read current."},{name:"list",type:"boolean",default:!1,help:"List models in the picker (does not switch)"}],columns:["Status","Model"],func:async(i,o)=>{const c=String(o.name||"").trim().toLowerCase(),a=o.list===!0||o.list==="true",n=(r)=>String(r||"").trim().replace(/\s+/g," ").toLowerCase(),s=l(await i.evaluate(`(function() {
2
2
  const btn = document.querySelector('button[aria-label^="Select model, current:"]');
3
3
  if (!btn) return '';
4
4
  const aria = btn.getAttribute('aria-label') || '';
5
5
  const m = aria.match(/current:\\s*(.*)$/i);
6
6
  return m ? m[1].trim() : (btn.textContent || '').trim();
7
- })()`));if(!I)throw T('Antigravity model button (button[aria-label^="Select model, current:"]). Make sure a chat is open in the foreground.');if(!K&&!H)return[{Status:"Active",Model:I}];const M=JSON.stringify(K),h=J(await F.evaluate(`(async () => {
7
+ })()`));if(!s)throw g('Antigravity model button (button[aria-label^="Select model, current:"]). Make sure a chat is open in the foreground.');if(!c&&!a)return[{Status:"Active",Model:s}];const d=JSON.stringify(c),e=l(await i.evaluate(`(async () => {
8
8
  const wait = (ms) => new Promise((r) => setTimeout(r, ms));
9
9
  const trigger = document.querySelector('button[aria-label^="Select model, current:"]');
10
10
  if (!trigger) return { ok: false, reason: 'trigger missing' };
@@ -41,8 +41,8 @@ import{cli as N,Strategy as P}from"@jackwener/opencli/registry";import{ArgumentE
41
41
  }
42
42
 
43
43
  const labels = rows.map((r) => (r.innerText || r.textContent || '').trim().slice(0, 80));
44
- const target = ${M};
45
- const listOnly = ${H?"true":"false"};
44
+ const target = ${d};
45
+ const listOnly = ${a?"true":"false"};
46
46
  if (!target || listOnly) {
47
47
  // Close picker (Esc) and return list.
48
48
  document.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: 'Escape' }));
@@ -81,10 +81,10 @@ import{cli as N,Strategy as P}from"@jackwener/opencli/registry";import{ArgumentE
81
81
  } catch {}
82
82
  });
83
83
  return { ok: true, switched: true, chosen: chosenLabel, labels };
84
- })()`));if(!h.ok){if(h.reason==="Ambiguous model match.")throw new Q(h.detail||"Ambiguous model match.");throw new L(h.reason,h.detail||"")}if(H)return h.labels.map((D)=>({Status:D.startsWith(I.slice(0,20))?"Active":"Available",Model:D}));await F.wait(0.8);let q="";for(let D=0;D<8;D+=1){q=J(await F.evaluate(`(function() {
84
+ })()`));if(!e.ok){if(e.reason==="Ambiguous model match.")throw new b(e.detail||"Ambiguous model match.");throw new u(e.reason,e.detail||"")}if(a)return e.labels.map((r)=>({Status:r.startsWith(s.slice(0,20))?"Active":"Available",Model:r}));await i.wait(0.8);let t="";for(let r=0;r<8;r+=1){t=l(await i.evaluate(`(function() {
85
85
  const btn = document.querySelector('button[aria-label^="Select model, current:"]');
86
86
  if (!btn) return '';
87
87
  const aria = btn.getAttribute('aria-label') || '';
88
88
  const m = aria.match(/current:\\s*(.*)$/i);
89
89
  return m ? m[1].trim() : (btn.textContent || '').trim();
90
- })()`));if(B(q)&&(B(h.chosen).includes(B(q))||B(q).includes(B(h.chosen))))return[{Status:"switched",Model:q}];if(B(q)===B(h.chosen))return[{Status:"switched",Model:q}];await F.wait(0.4)}throw new L(`Could not verify Antigravity model switched to ${h.chosen}.`,`Read back current model: ${q||"(empty)"}`)}});
90
+ })()`));if(n(t)&&(n(e.chosen).includes(n(t))||n(t).includes(n(e.chosen))))return[{Status:"switched",Model:t}];if(n(t)===n(e.chosen))return[{Status:"switched",Model:t}];await i.wait(0.4)}throw new u(`Could not verify Antigravity model switched to ${e.chosen}.`,`Read back current model: ${t||"(empty)"}`)}});
@@ -1,4 +1,4 @@
1
- import{cli as d,Strategy as f}from"@jackwener/opencli/registry";export const newCommand=d({site:"antigravity",name:"new",access:"read",description:"Start a new conversation / clear context in Antigravity",domain:"localhost",strategy:f.UI,browser:!0,args:[],columns:["status"],func:async(b)=>{await b.evaluate(`
1
+ import{cli as n,Strategy as a}from"@jackwener/opencli/registry";export const newCommand=n({site:"antigravity",name:"new",access:"read",description:"Start a new conversation / clear context in Antigravity",domain:"localhost",strategy:a.UI,browser:!0,args:[],columns:["status"],func:async(t)=>{await t.evaluate(`
2
2
  async () => {
3
3
  const btn = document.querySelector('[data-tooltip-id="new-conversation-tooltip"]');
4
4
  if (!btn) throw new Error('Could not find New Conversation button');
@@ -6,4 +6,4 @@ import{cli as d,Strategy as f}from"@jackwener/opencli/registry";export const new
6
6
  // In case it's disabled, we must check, but we'll try to click it anyway
7
7
  btn.click();
8
8
  }
9
- `);await b.wait(0.5);return[{status:"Successfully started a new conversation"}]}});
9
+ `);await t.wait(0.5);return[{status:"Successfully started a new conversation"}]}});
@@ -1,4 +1,4 @@
1
- import{cli as q,Strategy as v}from"@jackwener/opencli/registry";export const readCommand=q({site:"antigravity",name:"read",access:"read",description:"Read the latest chat messages from Antigravity AI",domain:"localhost",strategy:v.UI,browser:!0,args:[{name:"last",help:"Number of recent messages to read (not fully implemented due to generic structure, currently returns full history text or latest chunk)"}],columns:["role","content"],func:async(d,z)=>{const m=await d.evaluate(`
1
+ import{cli as n,Strategy as r}from"@jackwener/opencli/registry";export const readCommand=n({site:"antigravity",name:"read",access:"read",description:"Read the latest chat messages from Antigravity AI",domain:"localhost",strategy:r.UI,browser:!0,args:[{name:"last",help:"Number of recent messages to read (not fully implemented due to generic structure, currently returns full history text or latest chunk)"}],columns:["role","content"],func:async(e,a)=>{const t=await e.evaluate(`
2
2
  async () => {
3
3
  const container = document.getElementById('conversation');
4
4
  if (!container) throw new Error('Could not find conversation container');
@@ -7,4 +7,4 @@ import{cli as q,Strategy as v}from"@jackwener/opencli/registry";export const rea
7
7
  // In Electron/Chromium, innerText preserves basic visual line breaks nicely
8
8
  return container.innerText;
9
9
  }
10
- `);return[{role:"history",content:String(m).trim()}]}});
10
+ `);return[{role:"history",content:String(t).trim()}]}});
@@ -1 +1 @@
1
- import{cli as b,Strategy as q}from"@jackwener/opencli/registry";import{CommandExecutionError as z}from"@jackwener/opencli/errors";import{conversationTargetArgs as B}from"./_actions.js";b({site:"antigravity",name:"rename",access:"write",description:"Rename an Antigravity conversation by ID (NOT YET IMPLEMENTED — see source comment).",domain:"127.0.0.1",strategy:q.UI,browser:!0,args:[...B,{name:"title",positional:!0,type:"string",required:!0,help:"New title"}],columns:["status"],func:async()=>{throw new z("antigravity rename is not yet implemented — first attempt caused the conversation to be removed from the sidebar instead of renamed. Use the Antigravity UI to rename until this is fixed.","")}});
1
+ import{cli as e,Strategy as t}from"@jackwener/opencli/registry";import{CommandExecutionError as r}from"@jackwener/opencli/errors";import{conversationTargetArgs as i}from"./_actions.js";e({site:"antigravity",name:"rename",access:"write",description:"Rename an Antigravity conversation by ID (NOT YET IMPLEMENTED — see source comment).",domain:"127.0.0.1",strategy:t.UI,browser:!0,args:[...i,{name:"title",positional:!0,type:"string",required:!0,help:"New title"}],columns:["status"],func:async()=>{throw new r("antigravity rename is not yet implemented — first attempt caused the conversation to be removed from the sidebar instead of renamed. Use the Antigravity UI to rename until this is fixed.","")}});
@@ -1,4 +1,4 @@
1
- import{cli as v,Strategy as z}from"@jackwener/opencli/registry";export const sendCommand=v({site:"antigravity",name:"send",access:"write",description:"Send a message to Antigravity AI via the internal Lexical editor",domain:"localhost",strategy:z.UI,browser:!0,args:[{name:"message",fromFile:!0,help:"The message text to send",required:!0,positional:!0}],columns:["Status","Message"],func:async(d,q)=>{const f=q.message;await d.evaluate(`
1
+ import{cli as a,Strategy as r}from"@jackwener/opencli/registry";export const sendCommand=a({site:"antigravity",name:"send",access:"write",description:"Send a message to Antigravity AI via the internal Lexical editor",domain:"localhost",strategy:r.UI,browser:!0,args:[{name:"message",fromFile:!0,help:"The message text to send",required:!0,positional:!0}],columns:["Status","Message"],func:async(e,n)=>{const t=n.message;await e.evaluate(`
2
2
  async () => {
3
3
  const container = document.getElementById('antigravity.agentSidePanelInputBox');
4
4
  if (!container) throw new Error('Could not find antigravity.agentSidePanelInputBox');
@@ -6,6 +6,6 @@ import{cli as v,Strategy as z}from"@jackwener/opencli/registry";export const sen
6
6
  if (!editor) throw new Error('Could not find Antigravity input box');
7
7
 
8
8
  editor.focus();
9
- document.execCommand('insertText', false, ${JSON.stringify(f)});
9
+ document.execCommand('insertText', false, ${JSON.stringify(t)});
10
10
  }
11
- `);await d.wait(0.5);await d.pressKey("Enter");return[{Status:"Sent successfully",Message:f}]}});
11
+ `);await e.wait(0.5);await e.pressKey("Enter");return[{Status:"Sent successfully",Message:t}]}});
@@ -1,12 +1,12 @@
1
- import{createServer as E}from"node:http";import{CDPBridge as R}from"@jackwener/opencli/browser/cdp";import{resolveElectronEndpoint as w}from"@jackwener/opencli/launcher";import{EXIT_CODES as j,getErrorMessage as M}from"@jackwener/opencli/errors";function k(){const J="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";let Q="msg_";for(let W=0;W<24;W++)Q+=J[Math.floor(Math.random()*J.length)];return Q}function H(J){return Math.max(1,Math.ceil(J.length/3))}function C(J){if(typeof J==="string")return J;return J.filter((Q)=>Q.type==="text"&&Q.text).map((Q)=>Q.text).join(`
2
- `)}function q(J){return new Promise((Q,W)=>{const Y=[];J.on("data",(K)=>Y.push(K));J.on("end",()=>Q(Buffer.concat(Y).toString("utf-8")));J.on("error",W)})}function F(J,Q,W){const Y=JSON.stringify(W);J.writeHead(Q,{"Content-Type":"application/json","Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, x-api-key, anthropic-version, Authorization"});J.end(Y)}function D(J){return new Promise((Q)=>setTimeout(Q,J))}function S(J,Q,W){if(J===void 0)return W;const Y=typeof J==="number"?J:parseInt(String(J),10);if(Number.isNaN(Y)||Y<=0){console.error(`[serve] Invalid ${Q}="${J}", using default ${W}s`);return W}return Y}function f(J,Q){return S(process.env[J],J,Q)}async function v(J){await J.evaluate(`
1
+ import{createServer as I}from"node:http";import{CDPBridge as x}from"@jackwener/opencli/browser/cdp";import{resolveElectronEndpoint as A}from"@jackwener/opencli/launcher";import{EXIT_CODES as P,getErrorMessage as N}from"@jackwener/opencli/errors";function _(){const e="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";let t="msg_";for(let n=0;n<24;n++)t+=e[Math.floor(Math.random()*e.length)];return t}function v(e){return Math.max(1,Math.ceil(e.length/3))}function O(e){if(typeof e==="string")return e;return e.filter((t)=>t.type==="text"&&t.text).map((t)=>t.text).join(`
2
+ `)}function M(e){return new Promise((t,n)=>{const r=[];e.on("data",(c)=>r.push(c));e.on("end",()=>t(Buffer.concat(r).toString("utf-8")));e.on("error",n)})}function y(e,t,n){const r=JSON.stringify(n);e.writeHead(t,{"Content-Type":"application/json","Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, x-api-key, anthropic-version, Authorization"});e.end(r)}function f(e){return new Promise((t)=>setTimeout(t,e))}function C(e,t,n){if(e===void 0)return n;const r=typeof e==="number"?e:parseInt(String(e),10);if(Number.isNaN(r)||r<=0){console.error(`[serve] Invalid ${t}="${e}", using default ${n}s`);return n}return r}function b(e,t){return C(process.env[e],e,t)}async function k(e){await e.evaluate(`
3
3
  (() => {
4
4
  const btn = document.querySelector('[data-tooltip-id="new-conversation-tooltip"]');
5
5
  if (btn) btn.click();
6
6
  })()
7
- `);await D(1000)}async function h(J,Q){let W="claude sonnet 4.6";const Y=Q.toLowerCase();if(Y.includes("sonnet"))W="claude sonnet 4.6";else if(Y.includes("opus"))W="claude opus 4.6";else if(Y.includes("gemini")&&Y.includes("pro"))W="gemini 3.1 pro (high)";else if(Y.includes("gemini")&&Y.includes("flash"))W="gemini 3 flash";else if(Y.includes("gpt"))W="gpt-oss 120b";try{await J.evaluate(`
7
+ `);await f(1000)}async function B(e,t){let n="claude sonnet 4.6";const r=t.toLowerCase();if(r.includes("sonnet"))n="claude sonnet 4.6";else if(r.includes("opus"))n="claude opus 4.6";else if(r.includes("gemini")&&r.includes("pro"))n="gemini 3.1 pro (high)";else if(r.includes("gemini")&&r.includes("flash"))n="gemini 3 flash";else if(r.includes("gpt"))n="gpt-oss 120b";try{await e.evaluate(`
8
8
  async () => {
9
- const targetModelName = ${JSON.stringify(W)};
9
+ const targetModelName = ${JSON.stringify(n)};
10
10
  const trigger = document.querySelector('div[aria-haspopup="dialog"] > div[tabindex="0"]');
11
11
  if (!trigger) return; // Silent fail if UI changed
12
12
 
@@ -26,13 +26,13 @@ import{createServer as E}from"node:http";import{CDPBridge as R}from"@jackwener/o
26
26
  trigger.click();
27
27
  }
28
28
  }
29
- `);await D(500)}catch(K){console.error(`[serve] Warning: Could not switch to model ${W}:`,K)}}async function m(J){const Q=await J.evaluate(`
29
+ `);await f(500)}catch(c){console.error(`[serve] Warning: Could not switch to model ${n}:`,c)}}async function D(e){const t=await e.evaluate(`
30
30
  (() => {
31
31
  // Look for a cancel/stop button in the UI
32
32
  const cancelBtn = document.querySelector('button[aria-label*="cancel" i], button[aria-label*="stop" i], button[title*="cancel" i], button[title*="stop" i]');
33
33
  return !!cancelBtn;
34
34
  })()
35
- `);return Boolean(Q)}function y(J,Q=0){if(!J||Q>12)return null;const W=Array.from(J.children).filter((Y)=>Y.innerText?.trim().length>5);if(W.length>=2)return J;if(W.length===1)return y(W[0],Q+1);return J}async function V(J){const Q=await J.evaluate(`
35
+ `);return Boolean(t)}function R(e,t=0){if(!e||t>12)return null;const n=Array.from(e.children).filter((r)=>r.innerText?.trim().length>5);if(n.length>=2)return e;if(n.length===1)return R(n[0],t+1);return e}async function E(e){const t=await e.evaluate(`
36
36
  (() => {
37
37
  const container = document.getElementById('conversation');
38
38
  if (!container) return '';
@@ -41,7 +41,7 @@ import{createServer as E}from"node:http";import{CDPBridge as R}from"@jackwener/o
41
41
  const chatContent = container.children[0];
42
42
  return chatContent ? chatContent.innerText : container.innerText;
43
43
  })()
44
- `);return String(Q??"")}async function x(J,Q){const W=await J.evaluate(`
44
+ `);return String(t??"")}async function U(e,t){const n=await e.evaluate(`
45
45
  (() => {
46
46
  const conv = document.getElementById('conversation')?.children[0];
47
47
  const scroll = conv?.querySelector('.overflow-y-auto');
@@ -69,15 +69,15 @@ import{createServer as E}from"node:http";import{CDPBridge as R}from"@jackwener/o
69
69
  const last = msgs[msgs.length - 1];
70
70
  return last.innerText || '';
71
71
  })()
72
- `);let Y=String(W??"").trim();if(Q&&Y.startsWith(Q))Y=Y.slice(Q.length).trim();Y=Y.replace(/^Thought for[^\n]*\n+/i,"").trim();Y=Y.replace(/\s*\bCopy\b\s*$/m,"").trim();const K=Math.floor(Y.length/2),$=Y.slice(0,K).trim(),A=Y.slice(K).trim();if($&&$===A)Y=$;return Y}async function T(J,Q,W){if(!W){await J.evaluate(`
72
+ `);let r=String(n??"").trim();if(t&&r.startsWith(t))r=r.slice(t.length).trim();r=r.replace(/^Thought for[^\n]*\n+/i,"").trim();r=r.replace(/\s*\bCopy\b\s*$/m,"").trim();const c=Math.floor(r.length/2),i=r.slice(0,c).trim(),a=r.slice(c).trim();if(i&&i===a)r=i;return r}async function G(e,t,n){if(!n){await e.evaluate(`
73
73
  (() => {
74
74
  const container = document.getElementById('antigravity.agentSidePanelInputBox');
75
75
  const editor = container?.querySelector('[data-lexical-editor="true"]');
76
76
  if (!editor) throw new Error('Could not find input box');
77
77
  editor.focus();
78
- document.execCommand('insertText', false, ${JSON.stringify(Q)});
78
+ document.execCommand('insertText', false, ${JSON.stringify(t)});
79
79
  })()
80
- `);await D(500);await J.pressKey("Enter");return}const Y=await J.evaluate(`
80
+ `);await f(500);await e.pressKey("Enter");return}const r=await e.evaluate(`
81
81
  (() => {
82
82
  const container = document.getElementById('antigravity.agentSidePanelInputBox');
83
83
  if (!container) throw new Error('Could not find antigravity.agentSidePanelInputBox');
@@ -86,12 +86,12 @@ import{createServer as E}from"node:http";import{CDPBridge as R}from"@jackwener/o
86
86
  const r = editor.getBoundingClientRect();
87
87
  return JSON.stringify({ x: r.left + r.width / 2, y: r.top + r.height / 2 });
88
88
  })()
89
- `),{x:K,y:$}=JSON.parse(String(Y));await W.send("Input.dispatchMouseEvent",{type:"mousePressed",x:K,y:$,button:"left",clickCount:1});await D(50);await W.send("Input.dispatchMouseEvent",{type:"mouseReleased",x:K,y:$,button:"left",clickCount:1});await D(200);await W.send("Input.insertText",{text:Q});await D(300);await W.send("Input.dispatchKeyEvent",{type:"keyDown",key:"Enter",code:"Enter",windowsVirtualKeyCode:13,nativeVirtualKeyCode:13});await D(50);await W.send("Input.dispatchKeyEvent",{type:"keyUp",key:"Enter",code:"Enter",windowsVirtualKeyCode:13,nativeVirtualKeyCode:13})}async function u(J,Q,W={}){const Y=W.timeout??120000,K=W.pollInterval??500,$=Date.now()+Y;await D(1000);let A=!1,P=Q,O=0;const G=4;let U=0;while(Date.now()<$){try{const Z=await m(J),z=await V(J),B=z!==Q&&z.length>0;if(Z){A=!0;O=0}else{if(A){await D(500);return J}if(B)if(z===P){O++;if(O>=G)return J}else{O=0;P=z}}}catch(Z){const z=Z.message||String(Z),B=/closed|lost|not open|websocket/i.test(z);if(W.reconnect&&B&&U<2){U++;console.error(`[serve] CDP session loss detected (${z}), attempting to reconnect (${U}/2)...`);try{J=await W.reconnect();O=0;P=Q;continue}catch(X){console.error(`[serve] Reconnection failed: ${X.message}`);throw Z}}throw Z}await D(K)}throw Error(`Timeout waiting for Antigravity reply after ${Y/1000}s`)}async function b(J,Q,W={}){const{bridge:Y,timeout:K,reconnect:$}=W,A=J.messages.filter((Z)=>Z.role==="user");if(A.length===0)throw Error("No user message found in request");const P=A[A.length-1],O=C(P.content);if(!O.trim())throw Error("Empty user message");if(J.messages.length===1){console.error("[serve] New session detected (1 message). Starting new conversation in UI.");await v(Q)}if(J.model)await h(Q,J.model);const G=await V(Q);console.error(`[serve] Sending: "${O.slice(0,80)}${O.length>80?"...":""}"`);await T(Q,O,Y);console.error("[serve] Waiting for reply...");Q=await u(Q,G,{timeout:K,reconnect:$});const U=await x(Q,O);console.error(`[serve] Got reply: "${U.slice(0,80)}${U.length>80?"...":""}"`);return{id:k(),type:"message",role:"assistant",content:[{type:"text",text:U}],model:J.model??"antigravity",stop_reason:"end_turn",stop_sequence:null,usage:{input_tokens:H(O),output_tokens:H(U)}}}export async function startServe(J={}){const Q=J.port??8082,W=f("OPENCLI_ANTIGRAVITY_TIMEOUT",120),K=S(J.timeout,"--timeout",W)*1000;console.error(`[serve] Starting Antigravity API proxy on port ${Q} (timeout: ${K/1000}s)`);let $=null,A=null,P=!1;async function O(){if(A)try{await A.evaluate("1+1");return A}catch{console.error("[serve] CDP connection lost, reconnecting...");$?.close().catch(()=>{});$=null;A=null}const Z=await w("antigravity");if(process.env.OPENCLI_CDP_TARGET)console.error(`[serve] Using OPENCLI_CDP_TARGET=${process.env.OPENCLI_CDP_TARGET}`);try{const _=(await(await fetch(`${Z.replace(/\/$/,"")}/json`)).json()).filter((L)=>L.type==="page");console.error(`[serve] Available targets: ${_.map((L)=>`"${L.title}"`).join(", ")}`)}catch{}console.error(`[serve] Connecting via CDP (target pattern: "${process.env.OPENCLI_CDP_TARGET}")...`);$=new R;try{A=await $.connect({timeout:15000,cdpEndpoint:Z})}catch(B){$=null;const X=M(B),L=(B instanceof Error?B.cause:void 0)?.code==="ECONNREFUSED"||X.includes("ECONNREFUSED");throw Error(L?`Cannot connect to Antigravity at ${Z}.
89
+ `),{x:c,y:i}=JSON.parse(String(r));await n.send("Input.dispatchMouseEvent",{type:"mousePressed",x:c,y:i,button:"left",clickCount:1});await f(50);await n.send("Input.dispatchMouseEvent",{type:"mouseReleased",x:c,y:i,button:"left",clickCount:1});await f(200);await n.send("Input.insertText",{text:t});await f(300);await n.send("Input.dispatchKeyEvent",{type:"keyDown",key:"Enter",code:"Enter",windowsVirtualKeyCode:13,nativeVirtualKeyCode:13});await f(50);await n.send("Input.dispatchKeyEvent",{type:"keyUp",key:"Enter",code:"Enter",windowsVirtualKeyCode:13,nativeVirtualKeyCode:13})}async function L(e,t,n={}){const r=n.timeout??120000,c=n.pollInterval??500,i=Date.now()+r;await f(1000);let a=!1,p=t,l=0;const w=4;let u=0;while(Date.now()<i){try{const o=await D(e),s=await E(e),m=s!==t&&s.length>0;if(o){a=!0;l=0}else{if(a){await f(500);return e}if(m)if(s===p){l++;if(l>=w)return e}else{l=0;p=s}}}catch(o){const s=o.message||String(o),m=/closed|lost|not open|websocket/i.test(s);if(n.reconnect&&m&&u<2){u++;console.error(`[serve] CDP session loss detected (${s}), attempting to reconnect (${u}/2)...`);try{e=await n.reconnect();l=0;p=t;continue}catch(d){console.error(`[serve] Reconnection failed: ${d.message}`);throw o}}throw o}await f(c)}throw Error(`Timeout waiting for Antigravity reply after ${r/1000}s`)}async function j(e,t,n={}){const{bridge:r,timeout:c,reconnect:i}=n,a=e.messages.filter((o)=>o.role==="user");if(a.length===0)throw Error("No user message found in request");const p=a[a.length-1],l=O(p.content);if(!l.trim())throw Error("Empty user message");if(e.messages.length===1){console.error("[serve] New session detected (1 message). Starting new conversation in UI.");await k(t)}if(e.model)await B(t,e.model);const w=await E(t);console.error(`[serve] Sending: "${l.slice(0,80)}${l.length>80?"...":""}"`);await G(t,l,r);console.error("[serve] Waiting for reply...");t=await L(t,w,{timeout:c,reconnect:i});const u=await U(t,l);console.error(`[serve] Got reply: "${u.slice(0,80)}${u.length>80?"...":""}"`);return{id:_(),type:"message",role:"assistant",content:[{type:"text",text:u}],model:e.model??"antigravity",stop_reason:"end_turn",stop_sequence:null,usage:{input_tokens:v(l),output_tokens:v(u)}}}export async function startServe(e={}){const t=e.port??8082,n=b("OPENCLI_ANTIGRAVITY_TIMEOUT",120),c=C(e.timeout,"--timeout",n)*1000;console.error(`[serve] Starting Antigravity API proxy on port ${t} (timeout: ${c/1000}s)`);let i=null,a=null,p=!1;async function l(){if(a)try{await a.evaluate("1+1");return a}catch{console.error("[serve] CDP connection lost, reconnecting...");i?.close().catch(()=>{});i=null;a=null}const o=await A("antigravity");if(process.env.OPENCLI_CDP_TARGET)console.error(`[serve] Using OPENCLI_CDP_TARGET=${process.env.OPENCLI_CDP_TARGET}`);try{const g=(await(await fetch(`${o.replace(/\/$/,"")}/json`)).json()).filter((h)=>h.type==="page");console.error(`[serve] Available targets: ${g.map((h)=>`"${h.title}"`).join(", ")}`)}catch{}console.error(`[serve] Connecting via CDP (target pattern: "${process.env.OPENCLI_CDP_TARGET}")...`);i=new x;try{a=await i.connect({timeout:15000,cdpEndpoint:o})}catch(m){i=null;const d=N(m),h=(m instanceof Error?m.cause:void 0)?.code==="ECONNREFUSED"||d.includes("ECONNREFUSED");throw Error(h?`Cannot connect to Antigravity at ${o}.
90
90
  1. Make sure Antigravity is running
91
- 2. Launch with: --remote-debugging-port=9234`:`CDP connection failed: ${X}`)}console.error("[serve] ✅ CDP connected.");if(!await A.evaluate(`
91
+ 2. Launch with: --remote-debugging-port=9234`:`CDP connection failed: ${d}`)}console.error("[serve] ✅ CDP connected.");if(!await a.evaluate(`
92
92
  (() => !!document.getElementById('conversation') || !!document.getElementById('antigravity.agentSidePanelInputBox'))()
93
- `))console.error("[serve] ⚠️ Warning: chat UI elements not found in this target. Try setting OPENCLI_CDP_TARGET to the correct window title.");return A}const G=E(async(Z,z)=>{if(Z.method==="OPTIONS"){z.writeHead(204,{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, x-api-key, anthropic-version, Authorization"});z.end();return}const X=(Z.url??"/").split("?")[0];try{if(Z.method==="GET"&&X==="/v1/models"){F(z,200,{data:[{id:"antigravity",object:"model",created:Math.floor(Date.now()/1000),owned_by:"antigravity"}]});return}if(Z.method==="POST"&&X==="/v1/messages"){if(P){F(z,429,{type:"error",error:{type:"rate_limit_error",message:"Another request is currently being processed. Antigravity can only handle one request at a time."}});return}P=!0;try{const _=await q(Z),L=JSON.parse(_);if(L.stream){F(z,400,{type:"error",error:{type:"invalid_request_error",message:'Streaming is not supported. Set "stream": false.'}});return}const I=await O(),N=await b(L,I,{bridge:$,timeout:K,reconnect:O});F(z,200,N)}finally{P=!1}return}if(Z.method==="GET"&&(X==="/"||X==="/health")){F(z,200,{ok:!0,cdpConnected:A!==null});return}F(z,404,{type:"error",error:{type:"not_found_error",message:`Not found: ${X}`}})}catch(_){console.error("[serve] Error:",_ instanceof Error?_.message:_);F(z,500,{type:"error",error:{type:"api_error",message:_ instanceof Error?_.message:"Internal server error"}})}});G.listen(Q,"127.0.0.1",()=>{console.error(`
94
- [serve] ✅ Antigravity API proxy running at http://127.0.0.1:${Q}`);console.error("[serve] Compatible with Anthropic /v1/messages API");console.error("[serve] CDP connection will be established on first request.");console.error(`
95
- [serve] Usage with Claude Code:`);console.error(` ANTHROPIC_BASE_URL=http://localhost:${Q} claude
96
- `)});const U=()=>{console.error(`
97
- [serve] Shutting down...`);$?.close().catch(()=>{});G.close();process.exit(j.SUCCESS)};process.on("SIGTERM",U);process.on("SIGINT",U);await new Promise(()=>{})}
93
+ `))console.error("[serve] ⚠️ Warning: chat UI elements not found in this target. Try setting OPENCLI_CDP_TARGET to the correct window title.");return a}const w=I(async(o,s)=>{if(o.method==="OPTIONS"){s.writeHead(204,{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, x-api-key, anthropic-version, Authorization"});s.end();return}const d=(o.url??"/").split("?")[0];try{if(o.method==="GET"&&d==="/v1/models"){y(s,200,{data:[{id:"antigravity",object:"model",created:Math.floor(Date.now()/1000),owned_by:"antigravity"}]});return}if(o.method==="POST"&&d==="/v1/messages"){if(p){y(s,429,{type:"error",error:{type:"rate_limit_error",message:"Another request is currently being processed. Antigravity can only handle one request at a time."}});return}p=!0;try{const g=await M(o),h=JSON.parse(g);if(h.stream){y(s,400,{type:"error",error:{type:"invalid_request_error",message:'Streaming is not supported. Set "stream": false.'}});return}const T=await l(),S=await j(h,T,{bridge:i,timeout:c,reconnect:l});y(s,200,S)}finally{p=!1}return}if(o.method==="GET"&&(d==="/"||d==="/health")){y(s,200,{ok:!0,cdpConnected:a!==null});return}y(s,404,{type:"error",error:{type:"not_found_error",message:`Not found: ${d}`}})}catch(g){console.error("[serve] Error:",g instanceof Error?g.message:g);y(s,500,{type:"error",error:{type:"api_error",message:g instanceof Error?g.message:"Internal server error"}})}});w.listen(t,"127.0.0.1",()=>{console.error(`
94
+ [serve] ✅ Antigravity API proxy running at http://127.0.0.1:${t}`);console.error("[serve] Compatible with Anthropic /v1/messages API");console.error("[serve] CDP connection will be established on first request.");console.error(`
95
+ [serve] Usage with Claude Code:`);console.error(` ANTHROPIC_BASE_URL=http://localhost:${t} claude
96
+ `)});const u=()=>{console.error(`
97
+ [serve] Shutting down...`);i?.close().catch(()=>{});w.close();process.exit(P.SUCCESS)};process.on("SIGTERM",u);process.on("SIGINT",u);await new Promise(()=>{})}
@@ -1,12 +1,12 @@
1
- import*as J from"node:fs";import*as q from"node:path";import*as b from"node:os";import{execFileSync as f}from"node:child_process";import{cli as B,Strategy as I}from"@jackwener/opencli/registry";import{ArgumentError as h,CommandExecutionError as D,EmptyResultError as K}from"@jackwener/opencli/errors";import{unwrapEvaluateResult as P}from"./_actions.js";const W=["Index","Key","Bytes","Name","Preview","Database","Version","Kind","Path","Workspace Id","Folder","Modified","Field","Value"],y=q.join(b.homedir(),"Library/Application Support/Antigravity"),L=q.join(y,"User"),x=q.join(L,"globalStorage/state.vscdb"),M=q.join(L,"workspaceStorage"),U=q.join(L,"settings.json");function v(H,z){if(!J.existsSync(H))throw new D(`state.vscdb not found: ${H}`,"Has Antigravity been run at least once?");try{return f("/usr/bin/sqlite3",[H,z],{encoding:"utf-8",maxBuffer:67108864})}catch(Z){throw new D(`sqlite3 failed on ${q.basename(H)}: ${Z.message}`,"The DB may be locked by a running Antigravity instance. Try closing it or wait a few seconds.")}}function G(H){return v(H,"SELECT key FROM ItemTable ORDER BY key;").split(`
2
- `).map((Z)=>Z.trim()).filter(Boolean)}function C(H,z){const Z=z.replace(/'/g,"''"),Y=v(H,`SELECT value FROM ItemTable WHERE key = '${Z}';`).trim();if(!Y)return null;try{return JSON.parse(Y)}catch{return Y}}function T(H){const z=H?.workspace?String(H.workspace).trim():"";if(!z)return x;const Z=q.join(M,z,"state.vscdb");if(!J.existsSync(Z))throw new D(`Workspace state.vscdb not found: ${Z}`,"List workspace ids with `ppcli antigravity workspaces-list`.");return Z}B({site:"antigravity",name:"storage-keys",access:"read",description:"List localStorage / sessionStorage keys on the Antigravity renderer (CDP).",domain:"127.0.0.1",strategy:I.UI,browser:!0,args:[{name:"storage",required:!1,default:"local",help:'"local" or "session"'},{name:"filter",required:!1,help:"Case-insensitive substring filter"},{name:"limit",type:"int",required:!1,default:100,help:"Max rows to return"}],columns:W,func:async(H,z)=>{const Z=String(z?.storage||"local").trim().toLowerCase();if(Z!=="local"&&Z!=="session")throw new h("storage",'must be "local" or "session"');const Y=Z==="session"?"sessionStorage":"localStorage",X=P(await H.evaluate(`(() => {
3
- const s = ${Y};
1
+ import*as c from"node:fs";import*as d from"node:path";import*as O from"node:os";import{execFileSync as N}from"node:child_process";import{cli as u,Strategy as y}from"@jackwener/opencli/registry";import{ArgumentError as S,CommandExecutionError as p,EmptyResultError as g}from"@jackwener/opencli/errors";import{unwrapEvaluateResult as h}from"./_actions.js";const m=["Index","Key","Bytes","Name","Preview","Database","Version","Kind","Path","Workspace Id","Folder","Modified","Field","Value"],q=d.join(O.homedir(),"Library/Application Support/Antigravity"),k=d.join(q,"User"),A=d.join(k,"globalStorage/state.vscdb"),w=d.join(k,"workspaceStorage"),v=d.join(k,"settings.json");function x(t,e){if(!c.existsSync(t))throw new p(`state.vscdb not found: ${t}`,"Has Antigravity been run at least once?");try{return N("/usr/bin/sqlite3",[t,e],{encoding:"utf-8",maxBuffer:67108864})}catch(i){throw new p(`sqlite3 failed on ${d.basename(t)}: ${i.message}`,"The DB may be locked by a running Antigravity instance. Try closing it or wait a few seconds.")}}function C(t){return x(t,"SELECT key FROM ItemTable ORDER BY key;").split(`
2
+ `).map((i)=>i.trim()).filter(Boolean)}function I(t,e){const i=e.replace(/'/g,"''"),r=x(t,`SELECT value FROM ItemTable WHERE key = '${i}';`).trim();if(!r)return null;try{return JSON.parse(r)}catch{return r}}function L(t){const e=t?.workspace?String(t.workspace).trim():"";if(!e)return A;const i=d.join(w,e,"state.vscdb");if(!c.existsSync(i))throw new p(`Workspace state.vscdb not found: ${i}`,"List workspace ids with `ppcli antigravity workspaces-list`.");return i}u({site:"antigravity",name:"storage-keys",access:"read",description:"List localStorage / sessionStorage keys on the Antigravity renderer (CDP).",domain:"127.0.0.1",strategy:y.UI,browser:!0,args:[{name:"storage",required:!1,default:"local",help:'"local" or "session"'},{name:"filter",required:!1,help:"Case-insensitive substring filter"},{name:"limit",type:"int",required:!1,default:100,help:"Max rows to return"}],columns:m,func:async(t,e)=>{const i=String(e?.storage||"local").trim().toLowerCase();if(i!=="local"&&i!=="session")throw new S("storage",'must be "local" or "session"');const r=i==="session"?"sessionStorage":"localStorage",s=h(await t.evaluate(`(() => {
3
+ const s = ${r};
4
4
  const out = [];
5
5
  for (let i = 0; i < s.length; i++) {
6
6
  const k = s.key(i); const v = s.getItem(k) || '';
7
7
  out.push({ k, bytes: v.length });
8
8
  }
9
9
  return out;
10
- })()`)),$=z?.filter?String(z.filter).toLowerCase():null,F=$?X.filter((V)=>V.k.toLowerCase().includes($)):X;if(!F.length)throw new K("antigravity storage-keys",$?`No keys match "${$}".`:`${Y} is empty.`);F.sort((V,j)=>V.k.localeCompare(j.k));const Q=Number.isInteger(z?.limit)&&z.limit>0?z.limit:100;return F.slice(0,Q).map((V,j)=>({Index:j+1,Key:V.k,Bytes:V.bytes}))}});B({site:"antigravity",name:"storage-get",access:"read",description:"Read a single localStorage / sessionStorage value on the Antigravity renderer.",domain:"127.0.0.1",strategy:I.UI,browser:!0,args:[{name:"key",positional:!0,required:!0,help:"Storage key name"},{name:"storage",required:!1,default:"local",help:'"local" or "session"'},{name:"max-bytes",type:"int",required:!1,default:4000,help:"Truncate value to this many chars"}],columns:W,func:async(H,z)=>{const Z=String(z?.key||"").trim();if(!Z)throw new h("key","is required");const X=String(z?.storage||"local").trim().toLowerCase()==="session"?"sessionStorage":"localStorage",$=P(await H.evaluate(`${X}.getItem(${JSON.stringify(Z)})`));if($===null)throw new D(`Key not found in ${X}: ${Z}`,"");const F=Number.isInteger(z["max-bytes"])&&z["max-bytes"]>0?z["max-bytes"]:4000;let Q=$,V="string";try{Q=JSON.parse($);V=Array.isArray(Q)?"array":typeof Q}catch{}const j=V==="string"?Q:JSON.stringify(Q,null,2),N=j.length>F;return[{Field:"Key",Value:Z},{Field:"Store",Value:X},{Field:"Type",Value:V},{Field:"Size",Value:`${j.length} chars${N?" (truncated)":""}`},{Field:"Value",Value:N?j.slice(0,F)+`
11
- ...(truncated)`:j}]}});B({site:"antigravity",name:"cookies",access:"read",description:"List cookies on the Antigravity renderer (JS-visible via document.cookie).",domain:"127.0.0.1",strategy:I.UI,browser:!0,args:[],columns:W,func:async(H)=>{const z=P(await H.evaluate("document.cookie"));if(!z)throw new K("antigravity cookies","document.cookie is empty.");return z.split("; ").map((Y)=>{const X=Y.indexOf("=");if(X<0)return{name:Y,value:""};return{name:Y.slice(0,X),value:Y.slice(X+1)}}).map((Y,X)=>({Index:X+1,Name:Y.name,Bytes:Y.value.length,Preview:Y.value.slice(0,40)+(Y.value.length>40?"…":"")}))}});B({site:"antigravity",name:"idb-list",access:"read",description:"List IndexedDB databases on the Antigravity renderer.",domain:"127.0.0.1",strategy:I.UI,browser:!0,args:[],columns:W,func:async(H)=>{const z=P(await H.evaluate("(async () => indexedDB.databases ? await indexedDB.databases() : [])()"));if(!Array.isArray(z)||!z.length)throw new K("antigravity idb-list","No IndexedDB databases.");return z.map((Z,Y)=>({Index:Y+1,Database:Z.name||"(unnamed)",Version:String(Z.version||"")}))}});B({site:"antigravity",name:"state-keys",access:"read",description:"List keys in Antigravity's globalStorage state.vscdb (VSCode-style). Pass --workspace <id> to query a per-workspace DB. Works while Antigravity is closed.",domain:"localhost",strategy:I.LOCAL,browser:!1,args:[{name:"filter",required:!1,help:"Case-insensitive substring filter over keys"},{name:"workspace",required:!1,help:"Workspace id (from workspaces-list) to query per-workspace DB"},{name:"limit",type:"int",required:!1,default:200,help:"Max rows to return"}],columns:W,func:async(H)=>{const z=T(H),Z=G(z),Y=H?.filter?String(H.filter).toLowerCase():null,X=Y?Z.filter((F)=>F.toLowerCase().includes(Y)):Z;if(!X.length)throw new K("antigravity state-keys",Y?`No keys match "${Y}".`:"No keys.");const $=Number.isInteger(H?.limit)&&H.limit>0?H.limit:200;return X.slice(0,$).map((F,Q)=>({Index:Q+1,Key:F}))}});B({site:"antigravity",name:"state-get",access:"read",description:"Read one value from Antigravity's state.vscdb. Pass --workspace <id> for per-workspace.",domain:"localhost",strategy:I.LOCAL,browser:!1,args:[{name:"key",positional:!0,required:!0,help:"Storage key name"},{name:"workspace",required:!1,help:"Workspace id (from workspaces-list) to query per-workspace DB"},{name:"max-bytes",type:"int",required:!1,default:8000,help:"Truncate value to this many chars"}],columns:W,func:async(H)=>{const z=String(H?.key||"").trim();if(!z)throw new h("key","is required");const Z=T(H),Y=C(Z,z);if(Y===null)throw new D(`Key not found: ${z}`,"");const X=Number.isInteger(H["max-bytes"])&&H["max-bytes"]>0?H["max-bytes"]:8000,$=typeof Y==="string"?Y:JSON.stringify(Y,null,2),F=$.length>X;return[{Field:"Key",Value:z},{Field:"Type",Value:typeof Y==="string"?"string":Array.isArray(Y)?"array":typeof Y},{Field:"Size",Value:`${$.length} chars${F?" (truncated)":""}`},{Field:"Value",Value:F?$.slice(0,X)+`
12
- ...(truncated)`:$}]}});B({site:"antigravity",name:"recent-paths",access:"read",description:"Show Antigravity's recently-opened folders/files (history.recentlyOpenedPathsList).",domain:"localhost",strategy:I.LOCAL,browser:!1,args:[{name:"limit",type:"int",required:!1,default:20,help:"Max rows to return"}],columns:W,func:async(H)=>{const z=C(x,"history.recentlyOpenedPathsList");if(!z)throw new K("antigravity recent-paths","No recent paths recorded.");const Z=z.entries||[];if(!Z.length)throw new K("antigravity recent-paths","Recent paths list is empty.");const Y=Number.isInteger(H?.limit)&&H.limit>0?H.limit:20;return Z.slice(0,Y).map((X,$)=>{let F="other",Q=JSON.stringify(X).slice(0,200);if(X.folderUri){F="folder";Q=decodeURI(String(X.folderUri).replace(/^file:\/\//,""))}else if(X.fileUri){F="file";Q=decodeURI(String(X.fileUri).replace(/^file:\/\//,""))}else if(X.workspace?.configPath){F="workspace";Q=decodeURI(String(X.workspace.configPath).replace(/^file:\/\//,""))}return{Index:$+1,Kind:F,Path:Q}})}});B({site:"antigravity",name:"workspaces-list",access:"read",description:"List Antigravity workspaceStorage entries (each represents a previously-opened folder).",domain:"localhost",strategy:I.LOCAL,browser:!1,args:[{name:"limit",type:"int",required:!1,default:50,help:"Max rows to return"}],columns:W,func:async(H)=>{if(!J.existsSync(M))throw new D(`workspaceStorage not found: ${M}`,"");const z=J.readdirSync(M).filter((X)=>{const $=q.join(M,X);return J.statSync($).isDirectory()});if(!z.length)throw new K("antigravity workspaces-list","No workspace storage.");const Z=z.map((X)=>{const $=q.join(M,X),F=q.join($,"workspace.json");let Q="(no workspace.json)";if(J.existsSync(F))try{const V=JSON.parse(J.readFileSync(F,"utf-8"));if(V.folder)Q=decodeURI(V.folder.replace(/^file:\/\//,""));else if(V.workspace)Q="(multi-folder) "+decodeURI(V.workspace.replace(/^file:\/\//,""))}catch{Q="(invalid workspace.json)"}return{id:X,folder:Q,mtime:J.statSync($).mtimeMs}}).sort((X,$)=>$.mtime-X.mtime),Y=Number.isInteger(H?.limit)&&H.limit>0?H.limit:50;return Z.slice(0,Y).map((X,$)=>({Index:$+1,"Workspace Id":X.id,Folder:X.folder.slice(0,120),Modified:new Date(X.mtime).toISOString().replace("T"," ").slice(0,19)}))}});B({site:"antigravity",name:"settings-read",access:"read",description:"Read Antigravity's user settings.json (theme, proxy, agCockpit, tfa.system.autoAccept, etc.).",domain:"localhost",strategy:I.LOCAL,browser:!1,args:[],columns:W,func:async()=>{if(!J.existsSync(U))throw new D(`settings.json not found: ${U}`,"");const z=J.readFileSync(U,"utf-8").replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,"").replace(/([^:"])\/\/.*$/gm,"$1").replace(/,(\s*[}\]])/g,"$1");let Z;try{Z=JSON.parse(z)}catch(X){throw new D(`Failed to parse settings.json: ${X.message}`,"")}const Y=[];for(const[X,$]of Object.entries(Z))Y.push({Field:X,Value:typeof $==="object"?JSON.stringify($):String($)});return Y}});
10
+ })()`)),a=e?.filter?String(e.filter).toLowerCase():null,n=a?s.filter((l)=>l.k.toLowerCase().includes(a)):s;if(!n.length)throw new g("antigravity storage-keys",a?`No keys match "${a}".`:`${r} is empty.`);n.sort((l,f)=>l.k.localeCompare(f.k));const o=Number.isInteger(e?.limit)&&e.limit>0?e.limit:100;return n.slice(0,o).map((l,f)=>({Index:f+1,Key:l.k,Bytes:l.bytes}))}});u({site:"antigravity",name:"storage-get",access:"read",description:"Read a single localStorage / sessionStorage value on the Antigravity renderer.",domain:"127.0.0.1",strategy:y.UI,browser:!0,args:[{name:"key",positional:!0,required:!0,help:"Storage key name"},{name:"storage",required:!1,default:"local",help:'"local" or "session"'},{name:"max-bytes",type:"int",required:!1,default:4000,help:"Truncate value to this many chars"}],columns:m,func:async(t,e)=>{const i=String(e?.key||"").trim();if(!i)throw new S("key","is required");const s=String(e?.storage||"local").trim().toLowerCase()==="session"?"sessionStorage":"localStorage",a=h(await t.evaluate(`${s}.getItem(${JSON.stringify(i)})`));if(a===null)throw new p(`Key not found in ${s}: ${i}`,"");const n=Number.isInteger(e["max-bytes"])&&e["max-bytes"]>0?e["max-bytes"]:4000;let o=a,l="string";try{o=JSON.parse(a);l=Array.isArray(o)?"array":typeof o}catch{}const f=l==="string"?o:JSON.stringify(o,null,2),b=f.length>n;return[{Field:"Key",Value:i},{Field:"Store",Value:s},{Field:"Type",Value:l},{Field:"Size",Value:`${f.length} chars${b?" (truncated)":""}`},{Field:"Value",Value:b?f.slice(0,n)+`
11
+ ...(truncated)`:f}]}});u({site:"antigravity",name:"cookies",access:"read",description:"List cookies on the Antigravity renderer (JS-visible via document.cookie).",domain:"127.0.0.1",strategy:y.UI,browser:!0,args:[],columns:m,func:async(t)=>{const e=h(await t.evaluate("document.cookie"));if(!e)throw new g("antigravity cookies","document.cookie is empty.");return e.split("; ").map((r)=>{const s=r.indexOf("=");if(s<0)return{name:r,value:""};return{name:r.slice(0,s),value:r.slice(s+1)}}).map((r,s)=>({Index:s+1,Name:r.name,Bytes:r.value.length,Preview:r.value.slice(0,40)+(r.value.length>40?"…":"")}))}});u({site:"antigravity",name:"idb-list",access:"read",description:"List IndexedDB databases on the Antigravity renderer.",domain:"127.0.0.1",strategy:y.UI,browser:!0,args:[],columns:m,func:async(t)=>{const e=h(await t.evaluate("(async () => indexedDB.databases ? await indexedDB.databases() : [])()"));if(!Array.isArray(e)||!e.length)throw new g("antigravity idb-list","No IndexedDB databases.");return e.map((i,r)=>({Index:r+1,Database:i.name||"(unnamed)",Version:String(i.version||"")}))}});u({site:"antigravity",name:"state-keys",access:"read",description:"List keys in Antigravity's globalStorage state.vscdb (VSCode-style). Pass --workspace <id> to query a per-workspace DB. Works while Antigravity is closed.",domain:"localhost",strategy:y.LOCAL,browser:!1,args:[{name:"filter",required:!1,help:"Case-insensitive substring filter over keys"},{name:"workspace",required:!1,help:"Workspace id (from workspaces-list) to query per-workspace DB"},{name:"limit",type:"int",required:!1,default:200,help:"Max rows to return"}],columns:m,func:async(t)=>{const e=L(t),i=C(e),r=t?.filter?String(t.filter).toLowerCase():null,s=r?i.filter((n)=>n.toLowerCase().includes(r)):i;if(!s.length)throw new g("antigravity state-keys",r?`No keys match "${r}".`:"No keys.");const a=Number.isInteger(t?.limit)&&t.limit>0?t.limit:200;return s.slice(0,a).map((n,o)=>({Index:o+1,Key:n}))}});u({site:"antigravity",name:"state-get",access:"read",description:"Read one value from Antigravity's state.vscdb. Pass --workspace <id> for per-workspace.",domain:"localhost",strategy:y.LOCAL,browser:!1,args:[{name:"key",positional:!0,required:!0,help:"Storage key name"},{name:"workspace",required:!1,help:"Workspace id (from workspaces-list) to query per-workspace DB"},{name:"max-bytes",type:"int",required:!1,default:8000,help:"Truncate value to this many chars"}],columns:m,func:async(t)=>{const e=String(t?.key||"").trim();if(!e)throw new S("key","is required");const i=L(t),r=I(i,e);if(r===null)throw new p(`Key not found: ${e}`,"");const s=Number.isInteger(t["max-bytes"])&&t["max-bytes"]>0?t["max-bytes"]:8000,a=typeof r==="string"?r:JSON.stringify(r,null,2),n=a.length>s;return[{Field:"Key",Value:e},{Field:"Type",Value:typeof r==="string"?"string":Array.isArray(r)?"array":typeof r},{Field:"Size",Value:`${a.length} chars${n?" (truncated)":""}`},{Field:"Value",Value:n?a.slice(0,s)+`
12
+ ...(truncated)`:a}]}});u({site:"antigravity",name:"recent-paths",access:"read",description:"Show Antigravity's recently-opened folders/files (history.recentlyOpenedPathsList).",domain:"localhost",strategy:y.LOCAL,browser:!1,args:[{name:"limit",type:"int",required:!1,default:20,help:"Max rows to return"}],columns:m,func:async(t)=>{const e=I(A,"history.recentlyOpenedPathsList");if(!e)throw new g("antigravity recent-paths","No recent paths recorded.");const i=e.entries||[];if(!i.length)throw new g("antigravity recent-paths","Recent paths list is empty.");const r=Number.isInteger(t?.limit)&&t.limit>0?t.limit:20;return i.slice(0,r).map((s,a)=>{let n="other",o=JSON.stringify(s).slice(0,200);if(s.folderUri){n="folder";o=decodeURI(String(s.folderUri).replace(/^file:\/\//,""))}else if(s.fileUri){n="file";o=decodeURI(String(s.fileUri).replace(/^file:\/\//,""))}else if(s.workspace?.configPath){n="workspace";o=decodeURI(String(s.workspace.configPath).replace(/^file:\/\//,""))}return{Index:a+1,Kind:n,Path:o}})}});u({site:"antigravity",name:"workspaces-list",access:"read",description:"List Antigravity workspaceStorage entries (each represents a previously-opened folder).",domain:"localhost",strategy:y.LOCAL,browser:!1,args:[{name:"limit",type:"int",required:!1,default:50,help:"Max rows to return"}],columns:m,func:async(t)=>{if(!c.existsSync(w))throw new p(`workspaceStorage not found: ${w}`,"");const e=c.readdirSync(w).filter((s)=>{const a=d.join(w,s);return c.statSync(a).isDirectory()});if(!e.length)throw new g("antigravity workspaces-list","No workspace storage.");const i=e.map((s)=>{const a=d.join(w,s),n=d.join(a,"workspace.json");let o="(no workspace.json)";if(c.existsSync(n))try{const l=JSON.parse(c.readFileSync(n,"utf-8"));if(l.folder)o=decodeURI(l.folder.replace(/^file:\/\//,""));else if(l.workspace)o="(multi-folder) "+decodeURI(l.workspace.replace(/^file:\/\//,""))}catch{o="(invalid workspace.json)"}return{id:s,folder:o,mtime:c.statSync(a).mtimeMs}}).sort((s,a)=>a.mtime-s.mtime),r=Number.isInteger(t?.limit)&&t.limit>0?t.limit:50;return i.slice(0,r).map((s,a)=>({Index:a+1,"Workspace Id":s.id,Folder:s.folder.slice(0,120),Modified:new Date(s.mtime).toISOString().replace("T"," ").slice(0,19)}))}});u({site:"antigravity",name:"settings-read",access:"read",description:"Read Antigravity's user settings.json (theme, proxy, agCockpit, tfa.system.autoAccept, etc.).",domain:"localhost",strategy:y.LOCAL,browser:!1,args:[],columns:m,func:async()=>{if(!c.existsSync(v))throw new p(`settings.json not found: ${v}`,"");const e=c.readFileSync(v,"utf-8").replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,"").replace(/([^:"])\/\/.*$/gm,"$1").replace(/,(\s*[}\]])/g,"$1");let i;try{i=JSON.parse(e)}catch(s){throw new p(`Failed to parse settings.json: ${s.message}`,"")}const r=[];for(const[s,a]of Object.entries(i))r.push({Field:s,Value:typeof a==="object"?JSON.stringify(a):String(a)});return r}});
@@ -1,6 +1,6 @@
1
- import{cli as C,Strategy as D}from"@jackwener/opencli/registry";export const watchCommand=C({site:"antigravity",name:"watch",access:"read",description:"Stream new chat messages from Antigravity in real-time",domain:"localhost",strategy:D.UI,browser:!0,args:[{name:"timeout",type:"int",required:!1,default:86400,help:"Max seconds to keep watching (default: 86400 — 24h)"}],columns:[],func:async(B)=>{console.log("Watching Antigravity chat... (Press Ctrl+C to stop)");let b=0;while(!0){const A=await B.evaluate(`
1
+ import{cli as s,Strategy as r}from"@jackwener/opencli/registry";export const watchCommand=s({site:"antigravity",name:"watch",access:"read",description:"Stream new chat messages from Antigravity in real-time",domain:"localhost",strategy:r.UI,browser:!0,args:[{name:"timeout",type:"int",required:!1,default:86400,help:"Max seconds to keep watching (default: 86400 — 24h)"}],columns:[],func:async(o)=>{console.log("Watching Antigravity chat... (Press Ctrl+C to stop)");let t=0;while(!0){const a=await o.evaluate(`
2
2
  async () => {
3
3
  const container = document.getElementById('conversation');
4
4
  return container ? container.innerText : '';
5
5
  }
6
- `),q=A.length;if(q>b){const z=A.substring(b);if(z.trim().length>0)process.stdout.write(z);b=q}else if(q<b){b=q;console.log("\\n--- Conversation Cleared/Changed ---\\n");process.stdout.write(A)}await new Promise((z)=>setTimeout(z,500))}}});
6
+ `),e=a.length;if(e>t){const n=a.substring(t);if(n.trim().length>0)process.stdout.write(n);t=e}else if(e<t){t=e;console.log("\\n--- Conversation Cleared/Changed ---\\n");process.stdout.write(a)}await new Promise((n)=>setTimeout(n,500))}}});
@@ -1 +1 @@
1
- import{cli as z,Strategy as A}from"@jackwener/opencli/registry";import{CliError as B}from"@jackwener/opencli/errors";import{itunesFetch as G,formatDuration as H,formatDate as I}from"./utils.js";z({site:"apple-podcasts",name:"episodes",access:"read",description:"List recent episodes of an Apple Podcast (use ID from search)",strategy:A.PUBLIC,browser:!1,args:[{name:"id",positional:!0,required:!0,help:"Podcast ID (collectionId from search output)"},{name:"limit",type:"int",default:15,help:"Max episodes to show"}],columns:["title","duration","date"],func:async(q)=>{const v=Math.max(1,Math.min(Number(q.limit),200)),x=((await G(`/lookup?id=${q.id}&entity=podcastEpisode&limit=${v+1}`)).results??[]).filter((b)=>b.kind==="podcast-episode");if(!x.length)throw new B("NOT_FOUND","No episodes found","Check the podcast ID from: ppcli apple-podcasts search <keyword>");return x.slice(0,v).map((b)=>({title:b.trackName,duration:H(b.trackTimeMillis),date:I(b.releaseDate)}))}});
1
+ import{cli as a,Strategy as s}from"@jackwener/opencli/registry";import{CliError as r}from"@jackwener/opencli/errors";import{itunesFetch as d,formatDuration as c,formatDate as p}from"./utils.js";a({site:"apple-podcasts",name:"episodes",access:"read",description:"List recent episodes of an Apple Podcast (use ID from search)",strategy:s.PUBLIC,browser:!1,args:[{name:"id",positional:!0,required:!0,help:"Podcast ID (collectionId from search output)"},{name:"limit",type:"int",default:15,help:"Max episodes to show"}],columns:["title","duration","date"],func:async(e)=>{const i=Math.max(1,Math.min(Number(e.limit),200)),o=((await d(`/lookup?id=${e.id}&entity=podcastEpisode&limit=${i+1}`)).results??[]).filter((t)=>t.kind==="podcast-episode");if(!o.length)throw new r("NOT_FOUND","No episodes found","Check the podcast ID from: ppcli apple-podcasts search <keyword>");return o.slice(0,i).map((t)=>({title:t.trackName,duration:c(t.trackTimeMillis),date:p(t.releaseDate)}))}});
@@ -1 +1 @@
1
- import{cli as J,Strategy as K}from"@jackwener/opencli/registry";import{CliError as z}from"@jackwener/opencli/errors";const N="https://rss.marketingtools.apple.com/api/v2",Q=15000;J({site:"apple-podcasts",name:"top",access:"read",description:"Top podcasts chart on Apple Podcasts",strategy:K.PUBLIC,browser:!1,args:[{name:"limit",type:"int",default:20,help:"Number of podcasts (max 100)"},{name:"country",default:"us",help:"Country code (e.g. us, cn, gb, jp)"}],columns:["rank","title","author","id"],func:async(B)=>{const F=Math.max(1,Math.min(Number(B.limit),100)),v=String(B.country||"us").trim().toLowerCase(),G=`${N}/${v}/podcasts/top/${F}/podcasts.json`;let h;try{h=await fetch(G,{signal:AbortSignal.timeout(Q)})}catch(f){const x=f?.cause?.code??f?.message??"unknown network error";throw new z("FETCH_ERROR",`Unable to reach Apple Podcasts charts for ${v.toUpperCase()}`,`Apple charts may be temporarily unavailable (${x}). Try again later.`)}if(!h.ok)throw new z("FETCH_ERROR",`Charts API HTTP ${h.status}`,`Check country code: ${v}`);const D=(await h.json())?.feed?.results;if(!D?.length)throw new z("NOT_FOUND","No chart data found","Try a different country code");return D.map((f,x)=>({rank:x+1,title:f.name,author:f.artistName,id:f.id}))}});
1
+ import{cli as l,Strategy as p}from"@jackwener/opencli/registry";import{CliError as r}from"@jackwener/opencli/errors";const u="https://rss.marketingtools.apple.com/api/v2",m=15000;l({site:"apple-podcasts",name:"top",access:"read",description:"Top podcasts chart on Apple Podcasts",strategy:p.PUBLIC,browser:!1,args:[{name:"limit",type:"int",default:20,help:"Number of podcasts (max 100)"},{name:"country",default:"us",help:"Country code (e.g. us, cn, gb, jp)"}],columns:["rank","title","author","id"],func:async(s)=>{const c=Math.max(1,Math.min(Number(s.limit),100)),e=String(s.country||"us").trim().toLowerCase(),i=`${u}/${e}/podcasts/top/${c}/podcasts.json`;let a;try{a=await fetch(i,{signal:AbortSignal.timeout(m)})}catch(t){const o=t?.cause?.code??t?.message??"unknown network error";throw new r("FETCH_ERROR",`Unable to reach Apple Podcasts charts for ${e.toUpperCase()}`,`Apple charts may be temporarily unavailable (${o}). Try again later.`)}if(!a.ok)throw new r("FETCH_ERROR",`Charts API HTTP ${a.status}`,`Check country code: ${e}`);const n=(await a.json())?.feed?.results;if(!n?.length)throw new r("NOT_FOUND","No chart data found","Try a different country code");return n.map((t,o)=>({rank:o+1,title:t.name,author:t.artistName,id:t.id}))}});
@@ -1 +1 @@
1
- import{CliError as y}from"@jackwener/opencli/errors";const z="https://itunes.apple.com";export async function itunesFetch(b){const q=await fetch(`${z}${b}`);if(!q.ok)throw new y("FETCH_ERROR",`iTunes API HTTP ${q.status}`,"Check your search term or podcast ID");return q.json()}export function formatDuration(b){if(!b||!Number.isFinite(b))return"-";const q=Math.round(b/1000),v=Math.floor(q/60),x=q%60;return`${v}:${String(x).padStart(2,"0")}`}export function formatDate(b){if(!b)return"-";return b.slice(0,10)}
1
+ import{CliError as e}from"@jackwener/opencli/errors";const c="https://itunes.apple.com";export async function itunesFetch(t){const r=await fetch(`${c}${t}`);if(!r.ok)throw new e("FETCH_ERROR",`iTunes API HTTP ${r.status}`,"Check your search term or podcast ID");return r.json()}export function formatDuration(t){if(!t||!Number.isFinite(t))return"-";const r=Math.round(t/1000),o=Math.floor(r/60),n=r%60;return`${o}:${String(n).padStart(2,"0")}`}export function formatDate(t){if(!t)return"-";return t.slice(0,10)}
@@ -1 +1 @@
1
- import{cli as U,Strategy as V}from"@jackwener/opencli/registry";import{ArgumentError as K,CommandExecutionError as v,EmptyResultError as W}from"@jackwener/opencli/errors";const L=/^[A-Za-z0-9._-]+$/;U({site:"archive",name:"item",access:"read",description:"Fetch metadata for a single Internet Archive item by identifier.",domain:"archive.org",strategy:V.PUBLIC,browser:!1,args:[{name:"identifier",positional:!0,required:!0,help:'Archive item identifier (e.g. "open-syllabus", "FinalFantasy2_356").'}],columns:["identifier","title","creator","date","mediatype","collection","description","file_count","url"],func:async(J)=>{const q=String(J.identifier??"").trim();if(!q)throw new K("archive item identifier cannot be empty","Example: ppcli archive item open-syllabus");if(!L.test(q))throw new K(`archive item identifier "${J.identifier}" is not valid`,'Archive item identifiers may only contain letters, digits, ".", "_", "-".');const M=`https://archive.org/metadata/${encodeURIComponent(q)}`;let G;try{G=await fetch(M,{headers:{Accept:"application/json","User-Agent":"ppcli/1.0 (+https://github.com/jackwener/OpenCLI)"}})}catch(B){throw new v(`archive item request failed: ${B?.message||B}`)}if(!G.ok)throw new v(`archive item failed: HTTP ${G.status}`);let H;try{H=await G.json()}catch(B){throw new v(`archive item returned malformed JSON: ${B?.message||B}`)}const b=H?.metadata;if(!b||typeof b!=="object"||!b.identifier)throw new W("archive item",`No public metadata for "${q}" on archive.org.`);const z=String(b.identifier);if(!L.test(z))throw new v("archive item returned malformed payload: metadata.identifier is not stable");if(z!==q)throw new v(`archive item returned metadata for "${z}" instead of "${q}"`);const O=Array.isArray(b.creator)?b.creator.join(", "):String(b.creator??""),P=Array.isArray(b.collection)?b.collection.join(", "):String(b.collection??""),Q=Array.isArray(b.description)?b.description.join(" "):String(b.description??"");if(!Array.isArray(H.files))throw new v("archive item returned malformed payload: files must be an array");return[{identifier:z,title:String(b.title??""),creator:O,date:b.date?String(b.date).slice(0,10):"",mediatype:String(b.mediatype??""),collection:P,description:Q,file_count:H.files.length,url:`https://archive.org/details/${z}`}]}});
1
+ import{cli as p,Strategy as y}from"@jackwener/opencli/registry";import{ArgumentError as s,CommandExecutionError as i,EmptyResultError as u}from"@jackwener/opencli/errors";const d=/^[A-Za-z0-9._-]+$/;p({site:"archive",name:"item",access:"read",description:"Fetch metadata for a single Internet Archive item by identifier.",domain:"archive.org",strategy:y.PUBLIC,browser:!1,args:[{name:"identifier",positional:!0,required:!0,help:'Archive item identifier (e.g. "open-syllabus", "FinalFantasy2_356").'}],columns:["identifier","title","creator","date","mediatype","collection","description","file_count","url"],func:async(c)=>{const t=String(c.identifier??"").trim();if(!t)throw new s("archive item identifier cannot be empty","Example: ppcli archive item open-syllabus");if(!d.test(t))throw new s(`archive item identifier "${c.identifier}" is not valid`,'Archive item identifiers may only contain letters, digits, ".", "_", "-".');const l=`https://archive.org/metadata/${encodeURIComponent(t)}`;let n;try{n=await fetch(l,{headers:{Accept:"application/json","User-Agent":"ppcli/1.0 (+https://github.com/jackwener/OpenCLI)"}})}catch(a){throw new i(`archive item request failed: ${a?.message||a}`)}if(!n.ok)throw new i(`archive item failed: HTTP ${n.status}`);let o;try{o=await n.json()}catch(a){throw new i(`archive item returned malformed JSON: ${a?.message||a}`)}const e=o?.metadata;if(!e||typeof e!=="object"||!e.identifier)throw new u("archive item",`No public metadata for "${t}" on archive.org.`);const r=String(e.identifier);if(!d.test(r))throw new i("archive item returned malformed payload: metadata.identifier is not stable");if(r!==t)throw new i(`archive item returned metadata for "${r}" instead of "${t}"`);const m=Array.isArray(e.creator)?e.creator.join(", "):String(e.creator??""),f=Array.isArray(e.collection)?e.collection.join(", "):String(e.collection??""),h=Array.isArray(e.description)?e.description.join(" "):String(e.description??"");if(!Array.isArray(o.files))throw new i("archive item returned malformed payload: files must be an array");return[{identifier:r,title:String(e.title??""),creator:m,date:e.date?String(e.date).slice(0,10):"",mediatype:String(e.mediatype??""),collection:f,description:h,file_count:o.files.length,url:`https://archive.org/details/${r}`}]}});
@@ -1 +1 @@
1
- import{cli as g,Strategy as b}from"@jackwener/opencli/registry";import{ArgumentError as o,CommandExecutionError as a,EmptyResultError as S}from"@jackwener/opencli/errors";const m=["downloads","date","addeddate","week","title"],A={added:"addeddate",published:"date"},h=["texts","movies","audio","software","image","web","data","collection"],$=/^[A-Za-z0-9._-]+$/;g({site:"archive",name:"search",access:"read",description:"Search Internet Archive items across books, movies, audio, software, and web.",domain:"archive.org",strategy:b.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:"Full-text query (matches title, description, creator, subject)."},{name:"mediatype",type:"string",required:!1,help:`Restrict to mediatype: ${h.join(", ")}`},{name:"sort",type:"string",default:"downloads",help:`Sort key: ${m.join(", ")}`},{name:"limit",type:"int",default:20,help:"Max items (max 100; one API page)."}],columns:["rank","identifier","title","creator","date","mediatype","downloads","url"],func:async(r)=>{const l=String(r.sort??"downloads").toLowerCase(),u=A[l]??l;if(!m.includes(u))throw new o(`archive search sort must be one of ${m.join(", ")}`);if(r.mediatype&&!h.includes(String(r.mediatype)))throw new o(`archive search mediatype must be one of ${h.join(", ")}`);const i=Number(r.limit??20);if(!Number.isInteger(i)||i<=0)throw new o("archive search limit must be a positive integer");if(i>100)throw new o("archive search limit must be <= 100");const n=String(r.query??"").trim();if(!n)throw new o("archive search query must not be empty");const f=r.mediatype?`(${n}) AND mediatype:${r.mediatype}`:n,t=new URL("https://archive.org/advancedsearch.php");t.searchParams.set("q",f);t.searchParams.set("output","json");t.searchParams.set("rows",String(i));t.searchParams.set("sort[]",`${u} desc`);for(const e of["identifier","title","creator","date","mediatype","downloads"])t.searchParams.append("fl[]",e);let c;try{c=await fetch(t,{headers:{Accept:"application/json","User-Agent":"ppcli/1.0 (+https://github.com/jackwener/OpenCLI)"}})}catch(e){throw new a(`archive search request failed: ${e?.message||e}`)}if(!c.ok)throw new a(`archive search failed: HTTP ${c.status}`);let p;try{p=await c.json()}catch(e){throw new a(`archive search returned malformed JSON: ${e?.message||e}`)}const d=p?.response?.docs;if(!Array.isArray(d))throw new a("archive search returned malformed payload: response.docs must be an array");if(d.length===0)throw new S("archive search",`No items match "${n}" on archive.org.`);return d.slice(0,i).map((e,y)=>{const s=String(e.identifier??"");if(!$.test(s))throw new a("archive search returned malformed payload: result row is missing a stable identifier");const w=Number(e.downloads??0);if(!Number.isFinite(w))throw new a(`archive search returned malformed payload for "${s}": downloads must be numeric`);const v=Array.isArray(e.creator)?e.creator.join(", "):String(e.creator??"");return{rank:y+1,identifier:s,title:String(e.title??""),creator:v,date:e.date?String(e.date).slice(0,10):"",mediatype:String(e.mediatype??""),downloads:w,url:s?`https://archive.org/details/${s}`:""}})}});
1
+ import{cli as v,Strategy as b}from"@jackwener/opencli/registry";import{ArgumentError as s,CommandExecutionError as a,EmptyResultError as S}from"@jackwener/opencli/errors";const m=["downloads","date","addeddate","week","title"],A={added:"addeddate",published:"date"},h=["texts","movies","audio","software","image","web","data","collection"],I=/^[A-Za-z0-9._-]+$/;v({site:"archive",name:"search",access:"read",description:"Search Internet Archive items across books, movies, audio, software, and web.",domain:"archive.org",strategy:b.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:"Full-text query (matches title, description, creator, subject)."},{name:"mediatype",type:"string",required:!1,help:`Restrict to mediatype: ${h.join(", ")}`},{name:"sort",type:"string",default:"downloads",help:`Sort key: ${m.join(", ")}`},{name:"limit",type:"int",default:20,help:"Max items (max 100; one API page)."}],columns:["rank","identifier","title","creator","date","mediatype","downloads","url"],func:async(t)=>{const l=String(t.sort??"downloads").toLowerCase(),u=A[l]??l;if(!m.includes(u))throw new s(`archive search sort must be one of ${m.join(", ")}`);if(t.mediatype&&!h.includes(String(t.mediatype)))throw new s(`archive search mediatype must be one of ${h.join(", ")}`);const i=Number(t.limit??20);if(!Number.isInteger(i)||i<=0)throw new s("archive search limit must be a positive integer");if(i>100)throw new s("archive search limit must be <= 100");const n=String(t.query??"").trim();if(!n)throw new s("archive search query must not be empty");const f=t.mediatype?`(${n}) AND mediatype:${t.mediatype}`:n,r=new URL("https://archive.org/advancedsearch.php");r.searchParams.set("q",f);r.searchParams.set("output","json");r.searchParams.set("rows",String(i));r.searchParams.set("sort[]",`${u} desc`);for(const e of["identifier","title","creator","date","mediatype","downloads"])r.searchParams.append("fl[]",e);let c;try{c=await fetch(r,{headers:{Accept:"application/json","User-Agent":"ppcli/1.0 (+https://github.com/jackwener/OpenCLI)"}})}catch(e){throw new a(`archive search request failed: ${e?.message||e}`)}if(!c.ok)throw new a(`archive search failed: HTTP ${c.status}`);let p;try{p=await c.json()}catch(e){throw new a(`archive search returned malformed JSON: ${e?.message||e}`)}const d=p?.response?.docs;if(!Array.isArray(d))throw new a("archive search returned malformed payload: response.docs must be an array");if(d.length===0)throw new S("archive search",`No items match "${n}" on archive.org.`);return d.slice(0,i).map((e,y)=>{const o=String(e.identifier??"");if(!I.test(o))throw new a("archive search returned malformed payload: result row is missing a stable identifier");const w=Number(e.downloads??0);if(!Number.isFinite(w))throw new a(`archive search returned malformed payload for "${o}": downloads must be numeric`);const g=Array.isArray(e.creator)?e.creator.join(", "):String(e.creator??"");return{rank:y+1,identifier:o,title:String(e.title??""),creator:g,date:e.date?String(e.date).slice(0,10):"",mediatype:String(e.mediatype??""),downloads:w,url:o?`https://archive.org/details/${o}`:""}})}});
@@ -1 +1 @@
1
- import{cli as R,Strategy as S}from"@jackwener/opencli/registry";import{ArgumentError as N,CommandExecutionError as G,EmptyResultError as W}from"@jackwener/opencli/errors";function X(B,F){if(!B||!F)return"";return`https://web.archive.org/web/${B}/${F}`}function O(B,F){const H=B[F];if(!Number.isInteger(H))throw new G(`archive snapshots returned malformed CDX payload: missing "${F}" column`);return H}R({site:"archive",name:"snapshots",access:"read",description:"List Wayback Machine snapshots over time for a URL via the CDX API.",domain:"archive.org",strategy:S.PUBLIC,browser:!1,args:[{name:"url",positional:!0,required:!0,help:"URL to look up (with or without scheme)."},{name:"from",type:"string",required:!1,help:"Earliest year/timestamp (YYYY[MM[DD[hh[mm[ss]]]]])"},{name:"to",type:"string",required:!1,help:"Latest year/timestamp (YYYY[MM[DD[hh[mm[ss]]]]])"},{name:"limit",type:"int",default:20,help:"Max snapshots to return (max 1000)."}],columns:["timestamp","snapshot_url","status","mimetype","original_url"],func:async(B)=>{const F=String(B.url??"").trim();if(!F)throw new N("archive snapshots url cannot be empty","Example: ppcli archive snapshots wikipedia.org");const H=Number(B.limit??20);if(!Number.isInteger(H)||H<=0)throw new N("archive snapshots limit must be a positive integer");if(H>1000)throw new N("archive snapshots limit must be <= 1000");for(const z of["from","to"]){const I=B[z];if(I!=null&&!/^\d{4,14}$/.test(String(I)))throw new N(`archive snapshots ${z} must be a digit-only timestamp (YYYY[MM[DD[hh[mm[ss]]]]])`)}const J=new URL("http://web.archive.org/cdx/search/cdx");J.searchParams.set("url",F);J.searchParams.set("output","json");J.searchParams.set("limit",String(H));if(B.from)J.searchParams.set("from",String(B.from));if(B.to)J.searchParams.set("to",String(B.to));let L;try{L=await fetch(J,{headers:{Accept:"application/json","User-Agent":"ppcli/1.0 (+https://github.com/jackwener/OpenCLI)"}})}catch(z){throw new G(`archive snapshots request failed: ${z?.message||z}`)}if(!L.ok)throw new G(`archive snapshots failed: HTTP ${L.status}`);let M;try{M=await L.json()}catch(z){throw new G(`archive snapshots returned malformed JSON: ${z?.message||z}`)}if(!Array.isArray(M))throw new G("archive snapshots returned malformed CDX payload: top-level payload must be an array");if(M.length<2)throw new W("archive snapshots",`No Wayback snapshots for "${F}".`);const[V,...Y]=M;if(!Array.isArray(V))throw new G("archive snapshots returned malformed CDX payload: header row must be an array");const K={};V.forEach((z,I)=>{K[z]=I});const Z=O(K,"timestamp"),_=O(K,"original"),$=O(K,"statuscode"),D=O(K,"mimetype");return Y.slice(0,H).map((z)=>{if(!Array.isArray(z))throw new G("archive snapshots returned malformed CDX payload: snapshot row must be an array");const I=String(z[Z]??""),P=String(z[_]??""),Q=z[$],T=z[D];if(!/^\d{14}$/.test(I)||!P)throw new G("archive snapshots returned malformed CDX payload: snapshot row is missing timestamp/original URL");if(Q==null||T==null||String(Q)===""||String(T)==="")throw new G("archive snapshots returned malformed CDX payload: snapshot row is missing statuscode/mimetype");return{timestamp:I,snapshot_url:X(I,P),status:String(Q),mimetype:String(T),original_url:P}})}});
1
+ import{cli as C,Strategy as D}from"@jackwener/opencli/registry";import{ArgumentError as c,CommandExecutionError as s,EmptyResultError as S}from"@jackwener/opencli/errors";function Y(e,r){if(!e||!r)return"";return`https://web.archive.org/web/${e}/${r}`}function p(e,r){const a=e[r];if(!Number.isInteger(a))throw new s(`archive snapshots returned malformed CDX payload: missing "${r}" column`);return a}C({site:"archive",name:"snapshots",access:"read",description:"List Wayback Machine snapshots over time for a URL via the CDX API.",domain:"archive.org",strategy:D.PUBLIC,browser:!1,args:[{name:"url",positional:!0,required:!0,help:"URL to look up (with or without scheme)."},{name:"from",type:"string",required:!1,help:"Earliest year/timestamp (YYYY[MM[DD[hh[mm[ss]]]]])"},{name:"to",type:"string",required:!1,help:"Latest year/timestamp (YYYY[MM[DD[hh[mm[ss]]]]])"},{name:"limit",type:"int",default:20,help:"Max snapshots to return (max 1000)."}],columns:["timestamp","snapshot_url","status","mimetype","original_url"],func:async(e)=>{const r=String(e.url??"").trim();if(!r)throw new c("archive snapshots url cannot be empty","Example: ppcli archive snapshots wikipedia.org");const a=Number(e.limit??20);if(!Number.isInteger(a)||a<=0)throw new c("archive snapshots limit must be a positive integer");if(a>1000)throw new c("archive snapshots limit must be <= 1000");for(const t of["from","to"]){const i=e[t];if(i!=null&&!/^\d{4,14}$/.test(String(i)))throw new c(`archive snapshots ${t} must be a digit-only timestamp (YYYY[MM[DD[hh[mm[ss]]]]])`)}const o=new URL("http://web.archive.org/cdx/search/cdx");o.searchParams.set("url",r);o.searchParams.set("output","json");o.searchParams.set("limit",String(a));if(e.from)o.searchParams.set("from",String(e.from));if(e.to)o.searchParams.set("to",String(e.to));let m;try{m=await fetch(o,{headers:{Accept:"application/json","User-Agent":"ppcli/1.0 (+https://github.com/jackwener/OpenCLI)"}})}catch(t){throw new s(`archive snapshots request failed: ${t?.message||t}`)}if(!m.ok)throw new s(`archive snapshots failed: HTTP ${m.status}`);let h;try{h=await m.json()}catch(t){throw new s(`archive snapshots returned malformed JSON: ${t?.message||t}`)}if(!Array.isArray(h))throw new s("archive snapshots returned malformed CDX payload: top-level payload must be an array");if(h.length<2)throw new S("archive snapshots",`No Wayback snapshots for "${r}".`);const[f,...w]=h;if(!Array.isArray(f))throw new s("archive snapshots returned malformed CDX payload: header row must be an array");const n={};f.forEach((t,i)=>{n[t]=i});const y=p(n,"timestamp"),g=p(n,"original"),v=p(n,"statuscode"),b=p(n,"mimetype");return w.slice(0,a).map((t)=>{if(!Array.isArray(t))throw new s("archive snapshots returned malformed CDX payload: snapshot row must be an array");const i=String(t[y]??""),l=String(t[g]??""),u=t[v],d=t[b];if(!/^\d{14}$/.test(i)||!l)throw new s("archive snapshots returned malformed CDX payload: snapshot row is missing timestamp/original URL");if(u==null||d==null||String(u)===""||String(d)==="")throw new s("archive snapshots returned malformed CDX payload: snapshot row is missing statuscode/mimetype");return{timestamp:i,snapshot_url:Y(i,l),status:String(u),mimetype:String(d),original_url:l}})}});
@@ -1 +1 @@
1
- import{cli as L,Strategy as N}from"@jackwener/opencli/registry";import{ArgumentError as K,CommandExecutionError as G,EmptyResultError as O}from"@jackwener/opencli/errors";function P(q){const b=String(q).replace(/[^0-9]/g,"");if(!/^\d{4,14}$/.test(b)||b.length%2!==0&&b.length!==4)throw new K("archive wayback timestamp must be YYYY[MM[DD[hh[mm[ss]]]]] or an ISO date");return b}L({site:"archive",name:"wayback",access:"read",description:"Look up the closest Wayback Machine snapshot for a URL.",domain:"archive.org",strategy:N.PUBLIC,browser:!1,args:[{name:"url",positional:!0,required:!0,help:"URL to look up (with or without scheme)."},{name:"timestamp",type:"string",required:!1,help:"Target timestamp (YYYY[MM[DD[hh[mm[ss]]]]] or ISO date). Defaults to most recent snapshot."}],columns:["original_url","requested_timestamp","snapshot_timestamp","snapshot_url","status"],func:async(q)=>{const b=String(q.url??"").trim();if(!b)throw new K("archive wayback url cannot be empty","Example: ppcli archive wayback wikipedia.org");const H=q.timestamp?P(q.timestamp):"",I=new URL("https://archive.org/wayback/available");I.searchParams.set("url",b);if(H)I.searchParams.set("timestamp",H);let F;try{F=await fetch(I,{headers:{Accept:"application/json","User-Agent":"ppcli/1.0 (+https://github.com/jackwener/OpenCLI)"}})}catch(B){throw new G(`archive wayback request failed: ${B?.message||B}`)}if(!F.ok)throw new G(`archive wayback failed: HTTP ${F.status}`);let J;try{J=await F.json()}catch(B){throw new G(`archive wayback returned malformed JSON: ${B?.message||B}`)}const f=J?.archived_snapshots?.closest;if(!f||!f.available)throw new O("archive wayback",`No Wayback snapshot for "${b}".`);if(typeof f.url!=="string"||!f.url||!/^\d{14}$/.test(String(f.timestamp??"")))throw new G("archive wayback returned malformed payload: closest snapshot is missing url/timestamp");return[{original_url:String(J.url??b),requested_timestamp:H,snapshot_timestamp:String(f.timestamp??""),snapshot_url:String(f.url),status:String(f.status??"")}]}});
1
+ import{cli as p,Strategy as h}from"@jackwener/opencli/registry";import{ArgumentError as c,CommandExecutionError as i,EmptyResultError as l}from"@jackwener/opencli/errors";function u(a){const t=String(a).replace(/[^0-9]/g,"");if(!/^\d{4,14}$/.test(t)||t.length%2!==0&&t.length!==4)throw new c("archive wayback timestamp must be YYYY[MM[DD[hh[mm[ss]]]]] or an ISO date");return t}p({site:"archive",name:"wayback",access:"read",description:"Look up the closest Wayback Machine snapshot for a URL.",domain:"archive.org",strategy:h.PUBLIC,browser:!1,args:[{name:"url",positional:!0,required:!0,help:"URL to look up (with or without scheme)."},{name:"timestamp",type:"string",required:!1,help:"Target timestamp (YYYY[MM[DD[hh[mm[ss]]]]] or ISO date). Defaults to most recent snapshot."}],columns:["original_url","requested_timestamp","snapshot_timestamp","snapshot_url","status"],func:async(a)=>{const t=String(a.url??"").trim();if(!t)throw new c("archive wayback url cannot be empty","Example: ppcli archive wayback wikipedia.org");const o=a.timestamp?u(a.timestamp):"",n=new URL("https://archive.org/wayback/available");n.searchParams.set("url",t);if(o)n.searchParams.set("timestamp",o);let s;try{s=await fetch(n,{headers:{Accept:"application/json","User-Agent":"ppcli/1.0 (+https://github.com/jackwener/OpenCLI)"}})}catch(r){throw new i(`archive wayback request failed: ${r?.message||r}`)}if(!s.ok)throw new i(`archive wayback failed: HTTP ${s.status}`);let m;try{m=await s.json()}catch(r){throw new i(`archive wayback returned malformed JSON: ${r?.message||r}`)}const e=m?.archived_snapshots?.closest;if(!e||!e.available)throw new l("archive wayback",`No Wayback snapshot for "${t}".`);if(typeof e.url!=="string"||!e.url||!/^\d{14}$/.test(String(e.timestamp??"")))throw new i("archive wayback returned malformed payload: closest snapshot is missing url/timestamp");return[{original_url:String(m.url??t),requested_timestamp:o,snapshot_timestamp:String(e.timestamp??""),snapshot_url:String(e.url),status:String(e.status??"")}]}});
@@ -1 +1 @@
1
- import{cli as I,Strategy as J}from"@jackwener/opencli/registry";import{ArgumentError as K,EmptyResultError as M}from"@jackwener/opencli/errors";import{arxivFetch as N,normalizeArxivLimit as O,parseEntries as P}from"./utils.js";I({site:"arxiv",name:"author",access:"read",description:"List arXiv papers by a given author (newest first)",strategy:J.PUBLIC,browser:!1,args:[{name:"author",positional:!0,required:!0,help:'Author name (e.g. "Yoshua Bengio" or "Y Bengio")'},{name:"limit",type:"int",default:20,help:"Max papers to return (max 50)"}],columns:["id","title","authors","published","primary_category","url"],func:async(B)=>{const f=String(B.author||"").trim();if(!f)throw new K("arxiv author cannot be empty",'Example: ppcli arxiv author "Yoshua Bengio"');const D=O(B.limit,20,50),G=encodeURIComponent(`au:"${f}"`),H=await N(`search_query=${G}&max_results=${D}&sortBy=submittedDate&sortOrder=descending`),C=P(H);if(!C.length)throw new M("arxiv author",`No papers found for author "${f}". Try alternate spellings (e.g. initials).`);return C.map((b)=>({id:b.id,title:b.title,authors:b.authors,published:b.published,primary_category:b.primary_category,url:b.url}))}});
1
+ import{cli as n,Strategy as u}from"@jackwener/opencli/registry";import{ArgumentError as l,EmptyResultError as m}from"@jackwener/opencli/errors";import{arxivFetch as p,normalizeArxivLimit as h,parseEntries as c}from"./utils.js";n({site:"arxiv",name:"author",access:"read",description:"List arXiv papers by a given author (newest first)",strategy:u.PUBLIC,browser:!1,args:[{name:"author",positional:!0,required:!0,help:'Author name (e.g. "Yoshua Bengio" or "Y Bengio")'},{name:"limit",type:"int",default:20,help:"Max papers to return (max 50)"}],columns:["id","title","authors","published","primary_category","url"],func:async(e)=>{const t=String(e.author||"").trim();if(!t)throw new l("arxiv author cannot be empty",'Example: ppcli arxiv author "Yoshua Bengio"');const a=h(e.limit,20,50),o=encodeURIComponent(`au:"${t}"`),s=await p(`search_query=${o}&max_results=${a}&sortBy=submittedDate&sortOrder=descending`),i=c(s);if(!i.length)throw new m("arxiv author",`No papers found for author "${t}". Try alternate spellings (e.g. initials).`);return i.map((r)=>({id:r.id,title:r.title,authors:r.authors,published:r.published,primary_category:r.primary_category,url:r.url}))}});
@@ -1 +1 @@
1
- import{ArgumentError as Z,CommandExecutionError as j}from"@jackwener/opencli/errors";export const ARXIV_BASE="https://export.arxiv.org/api/query";const w=/^[a-z]+(?:-[a-z]+)*(?:\.[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)?$/;export async function arxivFetch(z){const q=await fetch(`${ARXIV_BASE}?${z}`);if(!q.ok)throw new j(`arXiv API HTTP ${q.status}`,"Check your search term or paper ID");return q.text()}export function normalizeArxivLimit(z,q,F,J="limit"){const K=Number(z??q);if(!Number.isInteger(K)||K<=0)throw new Z(`arxiv ${J} must be a positive integer`);if(K>F)throw new Z(`arxiv ${J} must be <= ${F}`);return K}export function normalizeArxivCategory(z){const q=String(z||"").trim();if(!w.test(q))throw new Z(`Invalid arXiv category "${z}". Examples: cs.CL, cs.LG, math.PR, q-bio.NC, physics.comp-ph`);return q}function U(z){return z.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&#39;/g,"'")}function Q(z,q){const F=z.match(new RegExp(`<${q}[^>]*>([\\s\\S]*?)<\\/${q}>`));return F?F[1].trim():""}function B(z,q){const F=new RegExp(`<${q}[^>]*>([\\s\\S]*?)<\\/${q}>`,"g"),J=[];let D;while((D=F.exec(z))!==null)J.push(D[1].trim());return J}function G(z,q,F){const J=z.match(new RegExp(`<${q}\\b[^>]*?\\b${F}="([^"]*)"`));return J?J[1]:""}function H(z,q,F){const J=new RegExp(`<${q}\\b[^>]*?\\b${F}="([^"]*)"`,"g"),D=[];let K;while((K=J.exec(z))!==null)D.push(K[1]);return D}function M(z,q){const F=/<link\b([^>]*)\/?>/g;let J;while((J=F.exec(z))!==null){const D=J[1];if(new RegExp(`\\brel="${q}"`).test(D)){const K=D.match(/\bhref="([^"]*)"/);if(K)return K[1]}}return""}export function parseEntries(z){const q=/<entry>([\s\S]*?)<\/entry>/g,F=[];let J;while((J=q.exec(z))!==null){const D=J[1],W=Q(D,"id").replace(/^https?:\/\/arxiv\.org\/abs\//,"").replace(/v\d+$/,""),$=M(D,"related")||`https://arxiv.org/pdf/${W}`;F.push({id:W,title:U(Q(D,"title").replace(/\s+/g," ")),authors:U(B(D,"name").join(", ")),abstract:U(Q(D,"summary").replace(/\s+/g," ")),published:Q(D,"published").slice(0,10),updated:Q(D,"updated").slice(0,10),primary_category:G(D,"arxiv:primary_category","term"),categories:H(D,"category","term").join(", "),comment:U(Q(D,"arxiv:comment").replace(/\s+/g," ")),pdf:$,url:`https://arxiv.org/abs/${W}`})}return F}
1
+ import{ArgumentError as p,CommandExecutionError as u}from"@jackwener/opencli/errors";export const ARXIV_BASE="https://export.arxiv.org/api/query";const m=/^[a-z]+(?:-[a-z]+)*(?:\.[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)?$/;export async function arxivFetch(e){const t=await fetch(`${ARXIV_BASE}?${e}`);if(!t.ok)throw new u(`arXiv API HTTP ${t.status}`,"Check your search term or paper ID");return t.text()}export function normalizeArxivLimit(e,t,n,i="limit"){const c=Number(e??t);if(!Number.isInteger(c)||c<=0)throw new p(`arxiv ${i} must be a positive integer`);if(c>n)throw new p(`arxiv ${i} must be <= ${n}`);return c}export function normalizeArxivCategory(e){const t=String(e||"").trim();if(!m.test(t))throw new p(`Invalid arXiv category "${e}". Examples: cs.CL, cs.LG, math.PR, q-bio.NC, physics.comp-ph`);return t}function a(e){return e.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&#39;/g,"'")}function o(e,t){const n=e.match(new RegExp(`<${t}[^>]*>([\\s\\S]*?)<\\/${t}>`));return n?n[1].trim():""}function x(e,t){const n=new RegExp(`<${t}[^>]*>([\\s\\S]*?)<\\/${t}>`,"g"),i=[];let r;while((r=n.exec(e))!==null)i.push(r[1].trim());return i}function g(e,t,n){const i=e.match(new RegExp(`<${t}\\b[^>]*?\\b${n}="([^"]*)"`));return i?i[1]:""}function h(e,t,n){const i=new RegExp(`<${t}\\b[^>]*?\\b${n}="([^"]*)"`,"g"),r=[];let c;while((c=i.exec(e))!==null)r.push(c[1]);return r}function f(e,t){const n=/<link\b([^>]*)\/?>/g;let i;while((i=n.exec(e))!==null){const r=i[1];if(new RegExp(`\\brel="${t}"`).test(r)){const c=r.match(/\bhref="([^"]*)"/);if(c)return c[1]}}return""}export function parseEntries(e){const t=/<entry>([\s\S]*?)<\/entry>/g,n=[];let i;while((i=t.exec(e))!==null){const r=i[1],s=o(r,"id").replace(/^https?:\/\/arxiv\.org\/abs\//,"").replace(/v\d+$/,""),l=f(r,"related")||`https://arxiv.org/pdf/${s}`;n.push({id:s,title:a(o(r,"title").replace(/\s+/g," ")),authors:a(x(r,"name").join(", ")),abstract:a(o(r,"summary").replace(/\s+/g," ")),published:o(r,"published").slice(0,10),updated:o(r,"updated").slice(0,10),primary_category:g(r,"arxiv:primary_category","term"),categories:h(r,"category","term").join(", "),comment:a(o(r,"arxiv:comment").replace(/\s+/g," ")),pdf:l,url:`https://arxiv.org/abs/${s}`})}return n}
@@ -1 +1 @@
1
- import{cli as j,Strategy as x}from"@jackwener/opencli/registry";import{AH_BASE as D,BRAND_COLUMNS as C,CommandExecutionError as H,EmptyResultError as L,ahFetch as O,clean as F,requireLimit as q,requireStableId as y,requireText as R,resolveBrandInitial as _}from"./utils.js";export function parseBrandSeries(K,f,X){const V=String(K||"").match(/<dl[^>]*>[\s\S]*?<\/dl>/g);if(!V)throw new H("autohome brand catalog returned an unexpected HTML shape; expected brand <dl> blocks.");const z=String(f||"").replace(/[·\s]/g,"");let W=K;if(z){W=null;for(const Q of V){const G=Q.match(/<dt>[\s\S]*?<div>\s*<a[^>]*>([^<]+)<\/a>/),J=G?F(G[1]).replace(/[·\s]/g,""):"";if(J&&(J===z||J.startsWith(z)||z.startsWith(J))){W=Q;break}}if(!W)return[]}const P=[],T=/<li id="s(\d+)">([\s\S]*?)<\/li>/g;let Y;while((Y=T.exec(W))!==null){const Q=y(Y[1],`autohome brand row ${P.length+1}`),G=Y[2],J=G.match(/<h4>\s*<a[^>]*>([^<]+)<\/a>/)||G.match(/<a[^>]*>([^<]+)<\/a>/),U=R(J&&J[1],`autohome brand row ${P.length+1} name`),v=G.match(/指导价[::]\s*<[^>]*>([^<]+)</)||G.match(/指导价[::]\s*([^<]+)</);let Z=F(v&&v[1]);if(/暂无|未上市|停售/.test(Z))Z="";P.push({series_id:Q,name:U,price:Z,url:`${D}/${Q}/`});if(P.length>=X)break}return P}j({site:"autohome",name:"brand",access:"read",aliases:["series"],description:"汽车之家按品牌列出全部车系 + 厂商指导价(免登录)",strategy:x.PUBLIC,browser:!1,args:[{name:"brand",required:!0,positional:!0,help:"品牌名(宝马 / 比亚迪 / 理想 / 丰田 …)或车系目录首字母 A-Z"},{name:"limit",type:"int",default:60,help:"返回的车系数量(最多 120)"}],columns:C,func:async(K)=>{const f=String(K.brand||"").trim(),X=_(f),$=q(K.limit,60,120),V=await O(`${D}/grade/carhtml/${X}.html`,`brand ${f}`),z=parseBrandSeries(V,/^[A-Za-z]$/.test(f)?"":f,$);if(z.length===0)throw new L(`autohome brand ${f}`,`No series found for '${f}'. Check the brand name spelling (simplified Chinese), or try a single A-Z catalog letter.`);return z}});
1
+ import{cli as w,Strategy as S}from"@jackwener/opencli/registry";import{AH_BASE as p,BRAND_COLUMNS as k,CommandExecutionError as x,EmptyResultError as y,ahFetch as A,clean as b,requireLimit as B,requireStableId as C,requireText as E,resolveBrandInitial as M}from"./utils.js";export function parseBrandSeries(n,e,l){const o=String(n||"").match(/<dl[^>]*>[\s\S]*?<\/dl>/g);if(!o)throw new x("autohome brand catalog returned an unexpected HTML shape; expected brand <dl> blocks.");const t=String(e||"").replace(/[·\s]/g,"");let c=n;if(t){c=null;for(const i of o){const r=i.match(/<dt>[\s\S]*?<div>\s*<a[^>]*>([^<]+)<\/a>/),a=r?b(r[1]).replace(/[·\s]/g,""):"";if(a&&(a===t||a.startsWith(t)||t.startsWith(a))){c=i;break}}if(!c)return[]}const s=[],f=/<li id="s(\d+)">([\s\S]*?)<\/li>/g;let m;while((m=f.exec(c))!==null){const i=C(m[1],`autohome brand row ${s.length+1}`),r=m[2],a=r.match(/<h4>\s*<a[^>]*>([^<]+)<\/a>/)||r.match(/<a[^>]*>([^<]+)<\/a>/),g=E(a&&a[1],`autohome brand row ${s.length+1} name`),u=r.match(/指导价[::]\s*<[^>]*>([^<]+)</)||r.match(/指导价[::]\s*([^<]+)</);let d=b(u&&u[1]);if(/暂无|未上市|停售/.test(d))d="";s.push({series_id:i,name:g,price:d,url:`${p}/${i}/`});if(s.length>=l)break}return s}w({site:"autohome",name:"brand",access:"read",aliases:["series"],description:"汽车之家按品牌列出全部车系 + 厂商指导价(免登录)",strategy:S.PUBLIC,browser:!1,args:[{name:"brand",required:!0,positional:!0,help:"品牌名(宝马 / 比亚迪 / 理想 / 丰田 …)或车系目录首字母 A-Z"},{name:"limit",type:"int",default:60,help:"返回的车系数量(最多 120)"}],columns:k,func:async(n)=>{const e=String(n.brand||"").trim(),l=M(e),h=B(n.limit,60,120),o=await A(`${p}/grade/carhtml/${l}.html`,`brand ${e}`),t=parseBrandSeries(o,/^[A-Za-z]$/.test(e)?"":e,h);if(t.length===0)throw new y(`autohome brand ${e}`,`No series found for '${e}'. Check the brand name spelling (simplified Chinese), or try a single A-Z catalog letter.`);return t}});
@@ -1 +1 @@
1
- import{cli as F,Strategy as L}from"@jackwener/opencli/registry";import{AH_KOUBEI_BASE as $,SCORE_COLUMNS as M,CommandExecutionError as N,EmptyResultError as k,assertPlainObject as q,ahFetch as H,clean as W,extractPageProps as K,normalizeSeriesId as R}from"./utils.js";function Z(T){const J=Number(T);return Number.isFinite(J)?J:null}export function parseScore(T,J){const D=q(T?.baseData,"autohome baseData"),X=T&&T.qualityData||{},Y=(Array.isArray(D.cmpSeriesScore)?D.cmpSeriesScore:[]).map((G)=>{const V=W(G.seriesname||G.seriesName),z=G.average||G.score;return V?`${V}(${z})`:""}).filter(Boolean).slice(0,4).join(", "),Q=[["series_id",String(J)],["name",W(D.seriesname)],["brand",W(D.brandName)],["level",W(D.levelname)],["guide_price",D.pricerange?`${W(D.pricerange)}万`:""],["overall",Z(D.average??D.seriesAverage)]];for(const G of Array.isArray(D.seriesScoreList)?D.seriesScoreList:[]){const V=W(G.typeName);if(V)Q.push([V,Z(G.score)])}Q.push(["pph_每百车故障",Z(X.pph)]);Q.push(["review_users",Z(X.userCount)]);Q.push(["competitors",Y]);Q.push(["url",`${$}/${J}`]);return Q.map(([G,V])=>({field:G,value:V}))}F({site:"autohome",name:"score",access:"read",aliases:["koubei","rating"],description:"汽车之家车系口碑评分(总分 + 各维度 + 故障率PPH + 竞品对比,免登录)",strategy:L.PUBLIC,browser:!1,args:[{name:"series_id",required:!0,positional:!0,help:"车系 ID(来自 brand 的 series_id,或 k.autohome.com.cn/<id> URL)"}],columns:M,func:async(T)=>{const J=R(T.series_id),D=await H(`${$}/${J}`,`score ${J}`),X=K(D);if(!X)throw new N(`autohome score ${J}`,"No koubei data found — the series id may be wrong, or Autohome changed its page.");const Y=parseScore(X,J),Q=Object.fromEntries(Y.map((G)=>[G.field,G.value]));if(!Q.name&&Q.overall==null)throw new k(`autohome score ${J}`,"This series has no koubei rating yet.");return Y}});
1
+ import{cli as p,Strategy as h}from"@jackwener/opencli/registry";import{AH_KOUBEI_BASE as u,SCORE_COLUMNS as d,CommandExecutionError as b,EmptyResultError as f,assertPlainObject as g,ahFetch as S,clean as i,extractPageProps as y,normalizeSeriesId as _}from"./utils.js";function m(a){const s=Number(a);return Number.isFinite(s)?s:null}export function parseScore(a,s){const e=g(a?.baseData,"autohome baseData"),n=a&&a.qualityData||{},c=(Array.isArray(e.cmpSeriesScore)?e.cmpSeriesScore:[]).map((r)=>{const t=i(r.seriesname||r.seriesName),l=r.average||r.score;return t?`${t}(${l})`:""}).filter(Boolean).slice(0,4).join(", "),o=[["series_id",String(s)],["name",i(e.seriesname)],["brand",i(e.brandName)],["level",i(e.levelname)],["guide_price",e.pricerange?`${i(e.pricerange)}万`:""],["overall",m(e.average??e.seriesAverage)]];for(const r of Array.isArray(e.seriesScoreList)?e.seriesScoreList:[]){const t=i(r.typeName);if(t)o.push([t,m(r.score)])}o.push(["pph_每百车故障",m(n.pph)]);o.push(["review_users",m(n.userCount)]);o.push(["competitors",c]);o.push(["url",`${u}/${s}`]);return o.map(([r,t])=>({field:r,value:t}))}p({site:"autohome",name:"score",access:"read",aliases:["koubei","rating"],description:"汽车之家车系口碑评分(总分 + 各维度 + 故障率PPH + 竞品对比,免登录)",strategy:h.PUBLIC,browser:!1,args:[{name:"series_id",required:!0,positional:!0,help:"车系 ID(来自 brand 的 series_id,或 k.autohome.com.cn/<id> URL)"}],columns:d,func:async(a)=>{const s=_(a.series_id),e=await S(`${u}/${s}`,`score ${s}`),n=y(e);if(!n)throw new b(`autohome score ${s}`,"No koubei data found — the series id may be wrong, or Autohome changed its page.");const c=parseScore(n,s),o=Object.fromEntries(c.map((r)=>[r.field,r.value]));if(!o.name&&o.overall==null)throw new f(`autohome score ${s}`,"This series has no koubei rating yet.");return c}});
@@ -1 +1 @@
1
- import{ArgumentError,CommandExecutionError,EmptyResultError}from"@jackwener/opencli/errors";export const AH_BASE="https://www.autohome.com.cn",AH_KOUBEI_BASE="https://k.autohome.com.cn";const K="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36";export const BRAND_COLUMNS=["series_id","name","price","url"],SCORE_COLUMNS=["field","value"],BRAND_INITIAL={奥迪:"A",阿斯顿马丁:"A",阿尔法罗密欧:"A",阿维塔:"A",埃安:"A",极狐:"A",宝马:"B",奔驰:"B",比亚迪:"B",别克:"B",本田:"B",标致:"B",保时捷:"B",宝骏:"B",北京:"B",北汽:"B",宾利:"B",北京现代:"B",长安:"C",长城:"C",长安启源:"C",长安欧尚:"C",传祺:"C",大众:"D",东风:"D",道奇:"D",东风风行:"D",东风小康:"D",法拉利:"F",福特:"F",丰田:"F",菲亚特:"F",福田:"F",方程豹:"F",飞凡:"F",广汽:"G",广汽丰田:"G",广汽本田:"G",高合:"G",哈弗:"H",红旗:"H",海马:"H",悍马:"H",哈飞:"H",华晨:"H",吉利:"J",捷豹:"J",极氪:"J",江淮:"J",几何:"J",捷途:"J",金杯:"J",江铃:"J",吉普:"J",极石:"J",凯迪拉克:"K",克莱斯勒:"K",开瑞:"K",凯翼:"K",兰博基尼:"L",路虎:"L",雷克萨斯:"L",林肯:"L",铃木:"L",劳斯莱斯:"L",雷诺:"L",理想:"L",领克:"L",零跑:"L",路特斯:"L",岚图:"L",猎豹:"L",马自达:"M",迈巴赫:"M",名爵:"M",玛莎拉蒂:"M",迈凯伦:"M",哪吒:"N",欧拉:"O",奇瑞:"Q",起亚:"Q",日产:"R",荣威:"R",斯巴鲁:"S",斯柯达:"S",三菱:"S",上汽大通:"S",思皓:"S",赛力斯:"S",smart:"S",特斯拉:"T",腾势:"T",坦克:"T",沃尔沃:"W",五菱:"W",蔚来:"W",威马:"W",魏牌:"W",问界:"W",现代:"X",雪佛兰:"X",雪铁龙:"X",小鹏:"X",星途:"X",小米:"X",英菲尼迪:"Y",一汽:"Y",野马:"Y",仰望:"Y",智己:"Z",中华:"Z",众泰:"Z"};export function resolveBrandInitial(q){const z=String(q||"").trim();if(!z)throw new ArgumentError("brand must be a non-empty value");if(/^[A-Za-z]$/.test(z))return z.toUpperCase();const F=z.replace(/[·\s]/g,"");if(BRAND_INITIAL[F])return BRAND_INITIAL[F];if(BRAND_INITIAL[z])return BRAND_INITIAL[z];throw new ArgumentError("brand",`unknown brand '${q}'. Pass a known Chinese brand name (e.g. 宝马 / 比亚迪 / 理想) or a single A-Z catalog letter.`)}export function normalizeSeriesId(q){const z=String(q||"").trim();if(!z)throw new ArgumentError("series_id must be a non-empty value");const F=z.match(/\/(?:s)?(\d+)(?:\/|$|\.)/)||z.match(/^s?(\d+)$/);if(!F)throw new ArgumentError(`'${q}' does not look like an autohome series id (a number, or a k.autohome.com.cn/<id> URL)`);return F[1]}export function clean(q){return String(q==null?"":q).replace(/\s+/g," ").trim()}export function requireLimit(q,z,F){const G=q==null||q===""?z:q,J=typeof G==="number"?G:Number(String(G).trim());if(!Number.isInteger(J)||J<1||J>F)throw new ArgumentError(`limit must be an integer between 1 and ${F}`);return J}export function requireStableId(q,z){const F=String(q??"").trim();if(!/^\d+$/.test(F))throw new CommandExecutionError(`${z} did not include a stable numeric id.`);return F}export function requireText(q,z){const F=clean(q);if(!F)throw new CommandExecutionError(`${z} did not include a stable text value.`);return F}export function assertPlainObject(q,z){if(!q||typeof q!=="object"||Array.isArray(q))throw new CommandExecutionError(`${z} returned an unexpected payload shape; expected an object.`);return q}export async function ahFetch(q,z){let F;try{F=await fetch(q,{headers:{"User-Agent":K,Referer:`${AH_BASE}/`,"Accept-Language":"zh-CN,zh;q=0.9"}})}catch(G){throw new CommandExecutionError(`autohome ${z} network error: ${G?.message||G}`)}if(!F.ok)throw new CommandExecutionError(`autohome ${z} HTTP ${F.status}`);return F.text()}export function extractPageProps(q){const z=String(q||"").match(/<script id="__NEXT_DATA__"[^>]*>([\s\S]*?)<\/script>/);if(!z)return null;try{const F=JSON.parse(z[1]);return F&&F.props&&F.props.pageProps||null}catch{return null}}export{ArgumentError,CommandExecutionError,EmptyResultError};
1
+ import{ArgumentError,CommandExecutionError,EmptyResultError}from"@jackwener/opencli/errors";export const AH_BASE="https://www.autohome.com.cn",AH_KOUBEI_BASE="https://k.autohome.com.cn";const i="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36";export const BRAND_COLUMNS=["series_id","name","price","url"],SCORE_COLUMNS=["field","value"],BRAND_INITIAL={奥迪:"A",阿斯顿马丁:"A",阿尔法罗密欧:"A",阿维塔:"A",埃安:"A",极狐:"A",宝马:"B",奔驰:"B",比亚迪:"B",别克:"B",本田:"B",标致:"B",保时捷:"B",宝骏:"B",北京:"B",北汽:"B",宾利:"B",北京现代:"B",长安:"C",长城:"C",长安启源:"C",长安欧尚:"C",传祺:"C",大众:"D",东风:"D",道奇:"D",东风风行:"D",东风小康:"D",法拉利:"F",福特:"F",丰田:"F",菲亚特:"F",福田:"F",方程豹:"F",飞凡:"F",广汽:"G",广汽丰田:"G",广汽本田:"G",高合:"G",哈弗:"H",红旗:"H",海马:"H",悍马:"H",哈飞:"H",华晨:"H",吉利:"J",捷豹:"J",极氪:"J",江淮:"J",几何:"J",捷途:"J",金杯:"J",江铃:"J",吉普:"J",极石:"J",凯迪拉克:"K",克莱斯勒:"K",开瑞:"K",凯翼:"K",兰博基尼:"L",路虎:"L",雷克萨斯:"L",林肯:"L",铃木:"L",劳斯莱斯:"L",雷诺:"L",理想:"L",领克:"L",零跑:"L",路特斯:"L",岚图:"L",猎豹:"L",马自达:"M",迈巴赫:"M",名爵:"M",玛莎拉蒂:"M",迈凯伦:"M",哪吒:"N",欧拉:"O",奇瑞:"Q",起亚:"Q",日产:"R",荣威:"R",斯巴鲁:"S",斯柯达:"S",三菱:"S",上汽大通:"S",思皓:"S",赛力斯:"S",smart:"S",特斯拉:"T",腾势:"T",坦克:"T",沃尔沃:"W",五菱:"W",蔚来:"W",威马:"W",魏牌:"W",问界:"W",现代:"X",雪佛兰:"X",雪铁龙:"X",小鹏:"X",星途:"X",小米:"X",英菲尼迪:"Y",一汽:"Y",野马:"Y",仰望:"Y",智己:"Z",中华:"Z",众泰:"Z"};export function resolveBrandInitial(e){const t=String(e||"").trim();if(!t)throw new ArgumentError("brand must be a non-empty value");if(/^[A-Za-z]$/.test(t))return t.toUpperCase();const r=t.replace(/[·\s]/g,"");if(BRAND_INITIAL[r])return BRAND_INITIAL[r];if(BRAND_INITIAL[t])return BRAND_INITIAL[t];throw new ArgumentError("brand",`unknown brand '${e}'. Pass a known Chinese brand name (e.g. 宝马 / 比亚迪 / 理想) or a single A-Z catalog letter.`)}export function normalizeSeriesId(e){const t=String(e||"").trim();if(!t)throw new ArgumentError("series_id must be a non-empty value");const r=t.match(/\/(?:s)?(\d+)(?:\/|$|\.)/)||t.match(/^s?(\d+)$/);if(!r)throw new ArgumentError(`'${e}' does not look like an autohome series id (a number, or a k.autohome.com.cn/<id> URL)`);return r[1]}export function clean(e){return String(e==null?"":e).replace(/\s+/g," ").trim()}export function requireLimit(e,t,r){const n=e==null||e===""?t:e,o=typeof n==="number"?n:Number(String(n).trim());if(!Number.isInteger(o)||o<1||o>r)throw new ArgumentError(`limit must be an integer between 1 and ${r}`);return o}export function requireStableId(e,t){const r=String(e??"").trim();if(!/^\d+$/.test(r))throw new CommandExecutionError(`${t} did not include a stable numeric id.`);return r}export function requireText(e,t){const r=clean(e);if(!r)throw new CommandExecutionError(`${t} did not include a stable text value.`);return r}export function assertPlainObject(e,t){if(!e||typeof e!=="object"||Array.isArray(e))throw new CommandExecutionError(`${t} returned an unexpected payload shape; expected an object.`);return e}export async function ahFetch(e,t){let r;try{r=await fetch(e,{headers:{"User-Agent":i,Referer:`${AH_BASE}/`,"Accept-Language":"zh-CN,zh;q=0.9"}})}catch(n){throw new CommandExecutionError(`autohome ${t} network error: ${n?.message||n}`)}if(!r.ok)throw new CommandExecutionError(`autohome ${t} HTTP ${r.status}`);return r.text()}export function extractPageProps(e){const t=String(e||"").match(/<script id="__NEXT_DATA__"[^>]*>([\s\S]*?)<\/script>/);if(!t)return null;try{const r=JSON.parse(t[1]);return r&&r.props&&r.props.pageProps||null}catch{return null}}export{ArgumentError,CommandExecutionError,EmptyResultError};