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,7 +1,7 @@
1
- import*as J from"node:fs";import*as p from"node:os";import*as B from"node:path";import{execSync as e,execFileSync as S}from"node:child_process";import{fileURLToPath as k}from"node:url";import{PLUGINS_DIR as T}from"./discovery.js";import{getErrorMessage as U,PluginError as x}from"./errors.js";import{log as w}from"./logger.js";import{isRecord as b}from"./utils.js";import{readPluginManifest as F,isMonorepo as y,getEnabledPlugins as qq,checkCompatibility as O,getCompatibilityRange as M}from"./plugin-manifest.js";const N=process.platform==="win32",d="local:";function a(){return process.env.HOME||process.env.USERPROFILE||p.homedir()}export function getLockFilePath(){return B.join(a(),".ppcli","plugins.lock.json")}export function getMonoreposDir(){return B.join(a(),".ppcli","monorepos")}function h(q){if(!q)return;if(q.startsWith(d))return{kind:"local",path:B.resolve(q.slice(d.length))};return{kind:"git",url:q}}function isLocalPluginSource(q){return h(q)?.kind==="local"}function toStoredPluginSource(q){if(q.kind==="local")return`${d}${B.resolve(q.path)}`;return q.url}function toLocalPluginSource(q){return toStoredPluginSource({kind:"local",path:q})}function Kq(q){if(!b(q))return;if(typeof q.name!=="string"||typeof q.subPath!=="string")return;return{name:q.name,subPath:q.subPath}}function Qq(q,K){if(typeof q==="string"){const Q=h(q);if(!Q)return;if(Q.kind==="git"&&K)return{kind:"monorepo",url:Q.url,repoName:K.name,subPath:K.subPath};return Q}if(!b(q)||typeof q.kind!=="string")return;switch(q.kind){case"git":return typeof q.url==="string"?{kind:"git",url:q.url}:void 0;case"local":return typeof q.path==="string"?{kind:"local",path:B.resolve(q.path)}:void 0;case"monorepo":return typeof q.url==="string"&&typeof q.repoName==="string"&&typeof q.subPath==="string"?{kind:"monorepo",url:q.url,repoName:q.repoName,subPath:q.subPath}:void 0;default:return}}function Vq(q){if(!b(q))return;const K=Kq(q.monorepo),Q=Qq(q.source,K);if(!Q)return;if(typeof q.commitHash!=="string"||typeof q.installedAt!=="string")return;const V={source:Q,commitHash:q.commitHash,installedAt:q.installedAt};if(typeof q.updatedAt==="string")V.updatedAt=q.updatedAt;return V}function resolvePluginSource(q,K){if(q)return q.source;return h(_q(K))}function resolveStoredPluginSource(q,K){const Q=resolvePluginSource(q,K);return Q?toStoredPluginSource(Q):void 0}function moveDir(q,K,Q=J){try{Q.renameSync(q,K)}catch(V){if(V.code==="EXDEV"){try{Q.cpSync(q,K,{recursive:!0})}catch(Y){try{Q.rmSync(K,{recursive:!0,force:!0})}catch{}throw Y}Q.rmSync(q,{recursive:!0,force:!0})}else throw V}}function L(q,K){const Q=`${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;return B.join(B.dirname(q),`.${B.basename(q)}.${K}-${Q}`)}function Yq(q){const K=B.join(p.tmpdir(),`opencli-clone-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);try{S("git",["clone","--depth","1",q,K],{encoding:"utf-8",stdio:["pipe","pipe","pipe"]})}catch(Q){throw new x(`Failed to clone plugin: ${U(Q)}`,"Check the repository URL and your network connection.")}return K}function m(q,K){const Q=Yq(q);try{return K(Q)}finally{try{J.rmSync(Q,{recursive:!0,force:!0})}catch{}}}function Zq(q,K){const Q=resolvePluginSource(q,K);if(!Q||Q.kind==="local")throw Error(`Unable to determine remote source for plugin at ${K}`);return Q.url}function D(q){try{J.lstatSync(q);return!0}catch{return!1}}function C(q,K){const Q=B.resolve(q,K);if(!Q.startsWith(q+B.sep)&&Q!==q)throw new x(`Plugin path "${K}" escapes repo root.`);return Q}function f(q){try{if(J.lstatSync(q).isSymbolicLink()){J.unlinkSync(q);return}J.rmSync(q,{recursive:!0,force:!0})}catch{}}class i{#K=[];#q=!1;track(q){this.#K.push(q);return q}commit(){if(this.#q)return;this.#q=!0;for(const q of this.#K)q.finalize()}rollback(){if(this.#q)return;this.#q=!0;for(const q of[...this.#K].reverse())q.rollback()}}function s(q){const K=new i;try{const Q=q(K);K.commit();return Q}catch(Q){K.rollback();throw Q}}function n(q,K,Q=J){const V=Q.existsSync(K);Q.mkdirSync(B.dirname(K),{recursive:!0});const Y=L(K,"tmp"),Z=V?L(K,"bak"):null;let X=!1;try{moveDir(q,Y,Q);if(Z)Q.renameSync(K,Z);Q.renameSync(Y,K)}catch($){try{Q.rmSync(Y,{recursive:!0,force:!0})}catch{}if(Z&&!Q.existsSync(K))try{Q.renameSync(Z,K)}catch{}throw $}return{finalize(){if(X)return;X=!0;if(Z)try{Q.rmSync(Z,{recursive:!0,force:!0})}catch{}},rollback(){if(X)return;X=!0;try{Q.rmSync(K,{recursive:!0,force:!0})}catch{}if(Z)try{Q.renameSync(Z,K)}catch{}try{Q.rmSync(Y,{recursive:!0,force:!0})}catch{}}}}function $q(q,K){const Q=D(K);if(Q&&!isSymlinkSync(K))throw Error(`Expected monorepo plugin link at ${K} to be a symlink`);J.mkdirSync(B.dirname(K),{recursive:!0});const V=L(K,"tmp"),Y=Q?L(K,"bak"):null,Z=N?"junction":"dir";let X=!1;try{J.symlinkSync(q,V,Z);if(Y)J.renameSync(K,Y);J.renameSync(V,K)}catch($){f(V);if(Y&&!D(K))try{J.renameSync(Y,K)}catch{}throw $}return{finalize(){if(X)return;X=!0;if(Y)f(Y)},rollback(){if(X)return;X=!0;f(K);if(Y&&!D(K))try{J.renameSync(Y,K)}catch{}f(V)}}}function readLockFileWithWriter(q=writeLockFile){try{const K=J.readFileSync(getLockFilePath(),"utf-8"),Q=JSON.parse(K);if(!b(Q))return{};const V={};let Y=!1;for(const[Z,X]of Object.entries(Q)){const $=Vq(X);if(!$){Y=!0;continue}V[Z]=$;if(JSON.stringify(X)!==JSON.stringify($))Y=!0}if(Y)try{q(V)}catch{}return V}catch{return{}}}export function readLockFile(){return readLockFileWithWriter(writeLockFile)}function writeLockFileWithFs(q,K=J){const Q=getLockFilePath();K.mkdirSync(B.dirname(Q),{recursive:!0});const V=L(Q,"tmp");try{K.writeFileSync(V,JSON.stringify(q,null,2)+`
2
- `);K.renameSync(V,Q)}catch(Y){try{K.rmSync(V,{force:!0})}catch{}throw Y}}export function writeLockFile(q){writeLockFileWithFs(q,J)}export function getCommitHash(q){try{return S("git",["rev-parse","HEAD"],{cwd:q,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return}}export function validatePluginStructure(q){const K=[];if(!J.existsSync(q))return{valid:!1,errors:["Plugin directory does not exist"]};const Q=J.readdirSync(q),V=Q.some((Z)=>Z.endsWith(".ts")&&!Z.endsWith(".d.ts")&&!Z.endsWith(".test.ts")),Y=Q.some((Z)=>Z.endsWith(".js")&&!Z.endsWith(".d.js"));if(!V&&!Y)K.push("No command files found in plugin directory. A plugin must contain at least one .ts or .js command file.");if(V){const Z=B.join(q,"package.json");if(!J.existsSync(Z))K.push('Plugin contains .ts files but no package.json. A package.json with "type": "module" and "@jackwener/opencli" peer dependency is required for TS plugins.');else try{if(JSON.parse(J.readFileSync(Z,"utf-8")).type!=="module")K.push('Plugin package.json must have "type": "module" for TypeScript plugins.')}catch{K.push("Plugin package.json is malformed or invalid JSON.")}}return{valid:K.length===0,errors:K}}function Xq(q){const K=B.join(q,"package.json");if(!J.existsSync(K))return!1;try{const Q=JSON.parse(J.readFileSync(K,"utf-8"));return Q.dependencies!=null&&Object.keys(Q.dependencies).length>0}catch{return!1}}function installDependencies(q){const K=B.join(q,"package.json");if(!J.existsSync(K))return;try{S("npm",["install","--omit=dev","--ignore-scripts"],{cwd:q,encoding:"utf-8",stdio:["pipe","pipe","pipe"],...N&&{shell:!0}})}catch(Q){throw new x(`npm install failed in ${q}: ${U(Q)}`,"Check your network connection and npm configuration.")}}function g(q){xq(q);Tq(q)}function o(q){installDependencies(q);g(q)}function postInstallMonorepoLifecycle(q,K){installDependencies(q);for(const Q of K){if(Q!==q&&Xq(Q))installDependencies(Q);g(Q)}}function l(q){const K=validatePluginStructure(q);if(!K.valid)throw new x(`Invalid plugin structure:
3
- - ${K.errors.join(`
4
- - `)}`);o(q)}function R(q,K,Q){q[K]={...Q,installedAt:Q.installedAt??new Date().toISOString()}}function r(q,K,Q){s((V)=>{V.track(n(q,K));Q(getCommitHash(K))})}function t(q,K,Q,V,Y){s((Z)=>{if(V){J.mkdirSync(V.parentDir,{recursive:!0});Z.track(n(V.stagingDir,q))}const X=getCommitHash(q);for(const $ of Q){const A=B.join(K,$.name),z=C(q,$.subPath);Z.track($q(z,A))}Y?.(X)})}export function installPlugin(q){const K=parseSource(q);if(!K)throw Error(`Invalid plugin source: "${q}"
1
+ import*as a from"node:fs";import*as C from"node:os";import*as l from"node:path";import{execSync as nn,execFileSync as U}from"node:child_process";import{fileURLToPath as R}from"node:url";import{PLUGINS_DIR as y}from"./discovery.js";import{getErrorMessage as v,PluginError as h}from"./errors.js";import{log as S}from"./logger.js";import{isRecord as A}from"./utils.js";import{readPluginManifest as P,isMonorepo as D,getEnabledPlugins as tn,checkCompatibility as j,getCompatibilityRange as x}from"./plugin-manifest.js";const w=process.platform==="win32",T="local:";function B(){return process.env.HOME||process.env.USERPROFILE||C.homedir()}export function getLockFilePath(){return l.join(B(),".ppcli","plugins.lock.json")}export function getMonoreposDir(){return l.join(B(),".ppcli","monorepos")}function H(n){if(!n)return;if(n.startsWith(T))return{kind:"local",path:l.resolve(n.slice(T.length))};return{kind:"git",url:n}}function isLocalPluginSource(n){return H(n)?.kind==="local"}function toStoredPluginSource(n){if(n.kind==="local")return`${T}${l.resolve(n.path)}`;return n.url}function toLocalPluginSource(n){return toStoredPluginSource({kind:"local",path:n})}function en(n){if(!A(n))return;if(typeof n.name!=="string"||typeof n.subPath!=="string")return;return{name:n.name,subPath:n.subPath}}function rn(n,t){if(typeof n==="string"){const e=H(n);if(!e)return;if(e.kind==="git"&&t)return{kind:"monorepo",url:e.url,repoName:t.name,subPath:t.subPath};return e}if(!A(n)||typeof n.kind!=="string")return;switch(n.kind){case"git":return typeof n.url==="string"?{kind:"git",url:n.url}:void 0;case"local":return typeof n.path==="string"?{kind:"local",path:l.resolve(n.path)}:void 0;case"monorepo":return typeof n.url==="string"&&typeof n.repoName==="string"&&typeof n.subPath==="string"?{kind:"monorepo",url:n.url,repoName:n.repoName,subPath:n.subPath}:void 0;default:return}}function on(n){if(!A(n))return;const t=en(n.monorepo),e=rn(n.source,t);if(!e)return;if(typeof n.commitHash!=="string"||typeof n.installedAt!=="string")return;const i={source:e,commitHash:n.commitHash,installedAt:n.installedAt};if(typeof n.updatedAt==="string")i.updatedAt=n.updatedAt;return i}function resolvePluginSource(n,t){if(n)return n.source;return H(yn(t))}function resolveStoredPluginSource(n,t){const e=resolvePluginSource(n,t);return e?toStoredPluginSource(e):void 0}function moveDir(n,t,e=a){try{e.renameSync(n,t)}catch(i){if(i.code==="EXDEV"){try{e.cpSync(n,t,{recursive:!0})}catch(r){try{e.rmSync(t,{recursive:!0,force:!0})}catch{}throw r}e.rmSync(n,{recursive:!0,force:!0})}else throw i}}function F(n,t){const e=`${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;return l.join(l.dirname(n),`.${l.basename(n)}.${t}-${e}`)}function sn(n){const t=l.join(C.tmpdir(),`opencli-clone-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);try{U("git",["clone","--depth","1",n,t],{encoding:"utf-8",stdio:["pipe","pipe","pipe"]})}catch(e){throw new h(`Failed to clone plugin: ${v(e)}`,"Check the repository URL and your network connection.")}return t}function J(n,t){const e=sn(n);try{return t(e)}finally{try{a.rmSync(e,{recursive:!0,force:!0})}catch{}}}function cn(n,t){const e=resolvePluginSource(n,t);if(!e||e.kind==="local")throw Error(`Unable to determine remote source for plugin at ${t}`);return e.url}function W(n){try{a.lstatSync(n);return!0}catch{return!1}}function E(n,t){const e=l.resolve(n,t);if(!e.startsWith(n+l.sep)&&e!==n)throw new h(`Plugin path "${t}" escapes repo root.`);return e}function M(n){try{if(a.lstatSync(n).isSymbolicLink()){a.unlinkSync(n);return}a.rmSync(n,{recursive:!0,force:!0})}catch{}}class Z{#t=[];#n=!1;track(n){this.#t.push(n);return n}commit(){if(this.#n)return;this.#n=!0;for(const n of this.#t)n.finalize()}rollback(){if(this.#n)return;this.#n=!0;for(const n of[...this.#t].reverse())n.rollback()}}function G(n){const t=new Z;try{const e=n(t);t.commit();return e}catch(e){t.rollback();throw e}}function X(n,t,e=a){const i=e.existsSync(t);e.mkdirSync(l.dirname(t),{recursive:!0});const r=F(t,"tmp"),o=i?F(t,"bak"):null;let c=!1;try{moveDir(n,r,e);if(o)e.renameSync(t,o);e.renameSync(r,t)}catch(s){try{e.rmSync(r,{recursive:!0,force:!0})}catch{}if(o&&!e.existsSync(t))try{e.renameSync(o,t)}catch{}throw s}return{finalize(){if(c)return;c=!0;if(o)try{e.rmSync(o,{recursive:!0,force:!0})}catch{}},rollback(){if(c)return;c=!0;try{e.rmSync(t,{recursive:!0,force:!0})}catch{}if(o)try{e.renameSync(o,t)}catch{}try{e.rmSync(r,{recursive:!0,force:!0})}catch{}}}}function an(n,t){const e=W(t);if(e&&!isSymlinkSync(t))throw Error(`Expected monorepo plugin link at ${t} to be a symlink`);a.mkdirSync(l.dirname(t),{recursive:!0});const i=F(t,"tmp"),r=e?F(t,"bak"):null,o=w?"junction":"dir";let c=!1;try{a.symlinkSync(n,i,o);if(r)a.renameSync(t,r);a.renameSync(i,t)}catch(s){M(i);if(r&&!W(t))try{a.renameSync(r,t)}catch{}throw s}return{finalize(){if(c)return;c=!0;if(r)M(r)},rollback(){if(c)return;c=!0;M(t);if(r&&!W(t))try{a.renameSync(r,t)}catch{}M(i)}}}function readLockFileWithWriter(n=writeLockFile){try{const t=a.readFileSync(getLockFilePath(),"utf-8"),e=JSON.parse(t);if(!A(e))return{};const i={};let r=!1;for(const[o,c]of Object.entries(e)){const s=on(c);if(!s){r=!0;continue}i[o]=s;if(JSON.stringify(c)!==JSON.stringify(s))r=!0}if(r)try{n(i)}catch{}return i}catch{return{}}}export function readLockFile(){return readLockFileWithWriter(writeLockFile)}function writeLockFileWithFs(n,t=a){const e=getLockFilePath();t.mkdirSync(l.dirname(e),{recursive:!0});const i=F(e,"tmp");try{t.writeFileSync(i,JSON.stringify(n,null,2)+`
2
+ `);t.renameSync(i,e)}catch(r){try{t.rmSync(i,{force:!0})}catch{}throw r}}export function writeLockFile(n){writeLockFileWithFs(n,a)}export function getCommitHash(n){try{return U("git",["rev-parse","HEAD"],{cwd:n,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return}}export function validatePluginStructure(n){const t=[];if(!a.existsSync(n))return{valid:!1,errors:["Plugin directory does not exist"]};const e=a.readdirSync(n),i=e.some((o)=>o.endsWith(".ts")&&!o.endsWith(".d.ts")&&!o.endsWith(".test.ts")),r=e.some((o)=>o.endsWith(".js")&&!o.endsWith(".d.js"));if(!i&&!r)t.push("No command files found in plugin directory. A plugin must contain at least one .ts or .js command file.");if(i){const o=l.join(n,"package.json");if(!a.existsSync(o))t.push('Plugin contains .ts files but no package.json. A package.json with "type": "module" and "@jackwener/opencli" peer dependency is required for TS plugins.');else try{if(JSON.parse(a.readFileSync(o,"utf-8")).type!=="module")t.push('Plugin package.json must have "type": "module" for TypeScript plugins.')}catch{t.push("Plugin package.json is malformed or invalid JSON.")}}return{valid:t.length===0,errors:t}}function ln(n){const t=l.join(n,"package.json");if(!a.existsSync(t))return!1;try{const e=JSON.parse(a.readFileSync(t,"utf-8"));return e.dependencies!=null&&Object.keys(e.dependencies).length>0}catch{return!1}}function installDependencies(n){const t=l.join(n,"package.json");if(!a.existsSync(t))return;try{U("npm",["install","--omit=dev","--ignore-scripts"],{cwd:n,encoding:"utf-8",stdio:["pipe","pipe","pipe"],...w&&{shell:!0}})}catch(e){throw new h(`npm install failed in ${n}: ${v(e)}`,"Check your network connection and npm configuration.")}}function O(n){Sn(n);kn(n)}function V(n){installDependencies(n);O(n)}function postInstallMonorepoLifecycle(n,t){installDependencies(n);for(const e of t){if(e!==n&&ln(e))installDependencies(e);O(e)}}function K(n){const t=validatePluginStructure(n);if(!t.valid)throw new h(`Invalid plugin structure:
3
+ - ${t.errors.join(`
4
+ - `)}`);V(n)}function L(n,t,e){n[t]={...e,installedAt:e.installedAt??new Date().toISOString()}}function Q(n,t,e){G((i)=>{i.track(X(n,t));e(getCommitHash(t))})}function Y(n,t,e,i,r){G((o)=>{if(i){a.mkdirSync(i.parentDir,{recursive:!0});o.track(X(i.stagingDir,n))}const c=getCommitHash(n);for(const s of e){const u=l.join(t,s.name),p=E(n,s.subPath);o.track(an(p,u))}r?.(c)})}export function installPlugin(n){const t=parseSource(n);if(!t)throw Error(`Invalid plugin source: "${n}"
5
5
  Supported formats:
6
6
  github:user/repo
7
7
  github:user/repo/subplugin
@@ -10,11 +10,11 @@ Supported formats:
10
10
  ssh://git@<host>/<path>/repo.git
11
11
  git@<host>:user/repo.git
12
12
  file:///absolute/path
13
- /absolute/path`);const{name:Q,subPlugin:V}=K;if(K.type==="local")return installLocalPlugin(K.localPath,Q);return m(K.cloneUrl,(Y)=>{const Z=F(Y),X=M(Z);if(X&&!O(X))throw Error(`Plugin requires ppcli ${X}, but current version is incompatible.`);if(Z&&y(Z))return Aq(Y,K.cloneUrl,Q,Z,V);return Jq(Y,K.cloneUrl,Q,Z)})}function Jq(q,K,Q,V){const Y=V?.name??Q,Z=B.join(T,Y);if(J.existsSync(Z))throw new x(`Plugin "${Y}" is already installed at ${Z}`,'Use "ppcli plugin uninstall" first, or pick a different name.');l(q);r(q,Z,(X)=>{const $=readLockFile();if(X){R($,Y,{source:{kind:"git",url:K},commitHash:X});writeLockFile($)}});return Y}function installLocalPlugin(q,K){if(!J.existsSync(q))throw new x(`Local plugin path does not exist: ${q}`);if(!J.statSync(q).isDirectory())throw new x(`Local plugin path is not a directory: ${q}`);const V=F(q),Y=M(V);if(Y&&!O(Y))throw new x(`Plugin requires ppcli ${Y}, but current version is incompatible.`,"Upgrade ppcli to a compatible version.");const Z=V?.name??K,X=B.join(T,Z);if(J.existsSync(X))throw new x(`Plugin "${Z}" is already installed at ${X}`,'Use "ppcli plugin uninstall" first, or pick a different name.');const $=validatePluginStructure(q);if(!$.valid)throw new x(`Invalid plugin structure:
14
- - ${$.errors.join(`
15
- - `)}`);J.mkdirSync(T,{recursive:!0});const A=B.resolve(q),z=N?"junction":"dir";J.symlinkSync(A,X,z);installDependencies(q);g(q);const j=readLockFile(),G=getCommitHash(q);R(j,Z,{source:{kind:"local",path:A},commitHash:G??"local"});writeLockFile(j);return Z}function Bq(q,K,Q,V){const Y=J.realpathSync(K),Z=validatePluginStructure(Y);if(!Z.valid)w.warn(`Plugin "${q}" structure invalid:
16
- - ${Z.errors.join(`
17
- - `)}`);o(Y);R(Q,q,{source:V?.source??{kind:"local",path:Y},commitHash:getCommitHash(Y)??"local",installedAt:V?.installedAt??new Date().toISOString(),updatedAt:new Date().toISOString()});writeLockFile(Q)}function Aq(q,K,Q,V,Y){const Z=getMonoreposDir(),X=B.join(Z,Q),$=J.existsSync(X),A=$?X:q,z=$?F(X):V;if(!z||!y(z))throw new x(`Monorepo manifest missing or invalid at ${A}`);let j=qq(z);if(Y){j=j.filter((W)=>W.name===Y);if(j.length===0){if(z.plugins?.[Y])throw new x(`Sub-plugin "${Y}" is disabled in the manifest.`);throw new x(`Sub-plugin "${Y}" not found in monorepo. Available: ${Object.keys(z.plugins??{}).join(", ")}`)}}const G=[],I=readLockFile(),_=[];J.mkdirSync(T,{recursive:!0});for(const{name:W,entry:H}of j){const v=M(H);if(v&&!O(v)){w.warn(`Skipping "${W}": requires ppcli ${v}`);continue}let P;try{P=C(A,H.path)}catch{w.warn(`Skipping "${W}": path "${H.path}" escapes repo root.`);continue}if(!J.existsSync(P)){w.warn(`Skipping "${W}": path "${H.path}" not found in repo.`);continue}const u=validatePluginStructure(P);if(!u.valid){w.warn(`Skipping "${W}": invalid structure — ${u.errors.join(", ")}`);continue}const c=B.join(T,W);if(J.existsSync(c)){w.warn(`Skipping "${W}": already installed at ${c}`);continue}_.push({name:W,entry:H})}if(_.length===0)return G;const E=_.map(({name:W,entry:H})=>({name:W,subPath:H.path}));if($)postInstallMonorepoLifecycle(X,_.map((W)=>C(X,W.entry.path)));else postInstallMonorepoLifecycle(q,_.map((W)=>C(q,W.entry.path)));t(X,T,E,$?void 0:{stagingDir:q,parentDir:Z},(W)=>{for(const{name:H,entry:v}of _){if(W)R(I,H,{source:{kind:"monorepo",url:K,repoName:Q,subPath:v.path},commitHash:W});G.push(H)}writeLockFile(I)});return G}function zq(q,K,Q,V,Y){const Z=[];for(const[X,$]of Object.entries(K)){if($.source.kind!=="monorepo"||$.source.repoName!==q)continue;const A=Q.plugins?.[X];if(!A||A.disabled)throw Error(`Installed sub-plugin "${X}" no longer exists in ${V}`);const z=M(A);if(z&&!O(z))throw Error(`Sub-plugin "${X}" requires ppcli ${z}`);const j=C(Y,A.path),G=validatePluginStructure(j);if(!G.valid)throw Error(`Updated sub-plugin "${X}" is invalid:
18
- - ${G.errors.join(`
19
- - `)}`);Z.push({name:X,lockEntry:$,manifestEntry:A})}return Z}function jq(q,K,Q,V,Y){for(const Z of K){if(!Y)continue;R(q,Z.name,{...Z.lockEntry,source:{kind:"monorepo",url:Q,repoName:V,subPath:Z.manifestEntry.path},commitHash:Y,updatedAt:new Date().toISOString()})}}function Wq(q,K,Q,V,Y){if(!Y)return;R(q,K,{source:{kind:"git",url:Q},commitHash:Y,installedAt:V?.installedAt??new Date().toISOString(),updatedAt:new Date().toISOString()})}export function uninstallPlugin(q){const K=B.join(T,q);if(!D(K))throw Error(`Plugin "${q}" is not installed.`);const Q=readLockFile(),V=Q[q];if(isSymlinkSync(K))J.unlinkSync(K);else J.rmSync(K,{recursive:!0,force:!0});if(V?.source.kind==="monorepo"){delete Q[q];const Z=V.source.repoName;if(!Object.values(Q).some(($)=>$.source.kind==="monorepo"&&$.source.repoName===Z)){const $=B.join(getMonoreposDir(),Z);try{J.rmSync($,{recursive:!0,force:!0})}catch{}}}else if(Q[q])delete Q[q];writeLockFile(Q)}function isSymlinkSync(q){try{return J.lstatSync(q).isSymbolicLink()}catch{return!1}}export function updatePlugin(q){const K=B.join(T,q);if(!J.existsSync(K))throw Error(`Plugin "${q}" is not installed.`);const Q=readLockFile(),V=Q[q],Y=resolvePluginSource(V,K);if(Y?.kind==="local"){Bq(q,K,Q,V);return}if(Y?.kind==="monorepo"){const X=B.join(getMonoreposDir(),Y.repoName),$=Y.repoName,A=Y.url;m(A,(z)=>{const j=F(z);if(!j||!y(j))throw Error(`Updated source is no longer a monorepo: ${A}`);const G=M(j);if(G&&!O(G))throw Error(`Plugin requires ppcli ${G}, but current version is incompatible.`);const I=zq($,Q,j,A,z);if(I.length>0)postInstallMonorepoLifecycle(z,I.map((_)=>C(z,_.manifestEntry.path)));t(X,T,I.map((_)=>({name:_.name,subPath:_.manifestEntry.path})),{stagingDir:z,parentDir:B.dirname(X)},(_)=>{jq(Q,I,A,$,_);writeLockFile(Q)})});return}const Z=Zq(V,K);m(Z,(X)=>{const $=F(X);if($&&y($))throw Error(`Updated source is now a monorepo: ${Z}`);const A=M($);if(A&&!O(A))throw Error(`Plugin requires ppcli ${A}, but current version is incompatible.`);l(X);r(X,K,(z)=>{Wq(Q,q,Z,Q[q],z);if(z)writeLockFile(Q)})})}export function updateAllPlugins(){return listPlugins().map((q)=>{try{updatePlugin(q.name);return{name:q.name,success:!0}}catch(K){return{name:q.name,success:!1,error:U(K)}}})}export function listPlugins(){if(!J.existsSync(T))return[];const q=J.readdirSync(T,{withFileTypes:!0}),K=readLockFile(),Q=[];for(const V of q){const Y=B.join(T,V.name);if(!(V.isDirectory()||isSymlinkSync(Y)))continue;const X=Gq(Y),$=K[V.name],A=F(Y);let z=A?.description,j=A?.version;if($?.source.kind==="monorepo"&&!z){const I=B.join(getMonoreposDir(),$.source.repoName),E=F(I)?.plugins?.[V.name];if(E){z=z??E.description;j=j??E.version}}const G=resolveStoredPluginSource($,Y);Q.push({name:V.name,path:Y,commands:X,source:G,version:j??$?.commitHash?.slice(0,7),installedAt:$?.installedAt,monorepoName:$?.source.kind==="monorepo"?$.source.repoName:void 0,description:z})}return Q}function Gq(q){try{const K=J.readdirSync(q);return[...new Set(K.filter((V)=>V.endsWith(".ts")&&!V.endsWith(".d.ts")&&!V.endsWith(".test.ts")||V.endsWith(".js")&&!V.endsWith(".d.js")).map((V)=>B.basename(V,B.extname(V))))]}catch{return[]}}function _q(q){try{return S("git",["config","--get","remote.origin.url"],{cwd:q,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return}}function parseSource(q){if(q.startsWith("file://"))try{const $=B.resolve(k(q));return{type:"local",localPath:$,name:B.basename($).replace(/^opencli-plugin-/,"")}}catch{return null}if(B.isAbsolute(q)){const $=B.resolve(q);return{type:"local",localPath:$,name:B.basename($).replace(/^opencli-plugin-/,"")}}const K=q.match(/^github:([\w.-]+)\/([\w.-]+)\/([\w.-]+)$/);if(K){const[,$,A,z]=K,j=A.replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:`https://github.com/${$}/${A}.git`,name:j,subPlugin:z}}const Q=q.match(/^github:([\w.-]+)\/([\w.-]+)$/);if(Q){const[,$,A]=Q,z=A.replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:`https://github.com/${$}/${A}.git`,name:z}}const V=q.match(/^https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+?)(?:\.git)?$/);if(V){const[,$,A]=V,z=A.replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:`https://github.com/${$}/${A}.git`,name:z}}const Y=q.match(/^ssh:\/\/[^/]+\/(.*?)(?:\.git)?$/);if(Y){const j=Y[1].split("/").pop().replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:q,name:j}}const Z=q.match(/^git@[^:]+:(.+?)(?:\.git)?$/);if(Z){const j=Z[1].split("/").pop().replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:q,name:j}}const X=q.match(/^https?:\/\/[^/]+\/(.+?)(?:\.git)?$/);if(X){const j=X[1].split("/").pop().replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:q.endsWith(".git")?q:`${q}.git`,name:j}}return null}function xq(q){try{const K=resolveHostOpencliRoot(),Q=B.join(q,"node_modules","@jackwener","opencli");if(J.existsSync(Q))J.rmSync(Q,{recursive:!0,force:!0});J.mkdirSync(B.dirname(Q),{recursive:!0});const V=N?"junction":"dir";J.symlinkSync(K,Q,V);w.debug(`Linked host ppcli into plugin: ${Q} → ${K}`)}catch(K){w.warn(`Failed to link host ppcli into plugin: ${U(K)}`)}}export function resolveEsbuildBin(){const q=resolveHostOpencliRoot();if(N){const Q=B.join(q,"node_modules",".bin","esbuild.cmd");if(J.existsSync(Q))return Q}if(!N)try{const Q=import.meta.resolve("esbuild/package.json");if(Q.startsWith("file://")){const V=k(Q),Y=J.readFileSync(V,"utf8"),Z=JSON.parse(Y);if(Z.bin&&typeof Z.bin==="object"&&Z.bin.esbuild){const X=B.resolve(B.dirname(V),Z.bin.esbuild);if(J.existsSync(X))return X}else if(typeof Z.bin==="string"){const X=B.resolve(B.dirname(V),Z.bin);if(J.existsSync(X))return X}}}catch{}const K=B.join(q,"node_modules",".bin","esbuild");if(J.existsSync(K))return K;try{const V=e(N?"where esbuild":"which esbuild",{encoding:"utf-8",stdio:"pipe"}).trim().split(`
20
- `)[0].trim();if(V&&J.existsSync(V))return V}catch{}return null}function resolveHostOpencliRoot(q=k(import.meta.url)){let K=B.dirname(q);while(!0){const Q=B.join(K,"package.json");if(J.existsSync(Q))try{if(JSON.parse(J.readFileSync(Q,"utf-8"))?.name==="@jackwener/opencli")return K}catch{}const V=B.dirname(K);if(V===K)break;K=V}return B.resolve(B.dirname(q),"..")}function Tq(q){try{const K=resolveEsbuildBin();if(!K){w.warn("esbuild not found. TS plugin files will not be transpiled and may fail to load. Install esbuild (`npm i -g esbuild`) or ensure it is available in the ppcli host node_modules.");return}const V=J.readdirSync(q).filter((Y)=>Y.endsWith(".ts")&&!Y.endsWith(".d.ts")&&!Y.endsWith(".test.ts"));for(const Y of V){const Z=Y.replace(/\.ts$/,".js"),X=B.join(q,Z);if(J.existsSync(X))continue;try{S(K,[Y,`--outfile=${Z}`,"--format=esm","--platform=node"],{cwd:q,encoding:"utf-8",stdio:["pipe","pipe","pipe"],...N&&{shell:!0}});w.debug(`Transpiled plugin file: ${Y} → ${Z}`)}catch($){w.warn(`Failed to transpile ${Y}: ${U($)}`)}}}catch(K){w.warn(`TS transpilation setup failed: ${U(K)}`)}}export{resolveHostOpencliRoot as _resolveHostOpencliRoot,resolveEsbuildBin as _resolveEsbuildBin,getCommitHash as _getCommitHash,installDependencies as _installDependencies,parseSource as _parseSource,postInstallMonorepoLifecycle as _postInstallMonorepoLifecycle,readLockFile as _readLockFile,readLockFileWithWriter as _readLockFileWithWriter,updateAllPlugins as _updateAllPlugins,validatePluginStructure as _validatePluginStructure,writeLockFile as _writeLockFile,writeLockFileWithFs as _writeLockFileWithFs,isSymlinkSync as _isSymlinkSync,getMonoreposDir as _getMonoreposDir,installLocalPlugin as _installLocalPlugin,isLocalPluginSource as _isLocalPluginSource,moveDir as _moveDir,resolvePluginSource as _resolvePluginSource,resolveStoredPluginSource as _resolveStoredPluginSource,toStoredPluginSource as _toStoredPluginSource,toLocalPluginSource as _toLocalPluginSource};
13
+ /absolute/path`);const{name:e,subPlugin:i}=t;if(t.type==="local")return installLocalPlugin(t.localPath,e);return J(t.cloneUrl,(r)=>{const o=P(r),c=x(o);if(c&&!j(c))throw Error(`Plugin requires ppcli ${c}, but current version is incompatible.`);if(o&&D(o))return dn(r,t.cloneUrl,e,o,i);return un(r,t.cloneUrl,e,o)})}function un(n,t,e,i){const r=i?.name??e,o=l.join(y,r);if(a.existsSync(o))throw new h(`Plugin "${r}" is already installed at ${o}`,'Use "ppcli plugin uninstall" first, or pick a different name.');K(n);Q(n,o,(c)=>{const s=readLockFile();if(c){L(s,r,{source:{kind:"git",url:t},commitHash:c});writeLockFile(s)}});return r}function installLocalPlugin(n,t){if(!a.existsSync(n))throw new h(`Local plugin path does not exist: ${n}`);if(!a.statSync(n).isDirectory())throw new h(`Local plugin path is not a directory: ${n}`);const i=P(n),r=x(i);if(r&&!j(r))throw new h(`Plugin requires ppcli ${r}, but current version is incompatible.`,"Upgrade ppcli to a compatible version.");const o=i?.name??t,c=l.join(y,o);if(a.existsSync(c))throw new h(`Plugin "${o}" is already installed at ${c}`,'Use "ppcli plugin uninstall" first, or pick a different name.');const s=validatePluginStructure(n);if(!s.valid)throw new h(`Invalid plugin structure:
14
+ - ${s.errors.join(`
15
+ - `)}`);a.mkdirSync(y,{recursive:!0});const u=l.resolve(n),p=w?"junction":"dir";a.symlinkSync(u,c,p);installDependencies(n);O(n);const d=readLockFile(),m=getCommitHash(n);L(d,o,{source:{kind:"local",path:u},commitHash:m??"local"});writeLockFile(d);return o}function pn(n,t,e,i){const r=a.realpathSync(t),o=validatePluginStructure(r);if(!o.valid)S.warn(`Plugin "${n}" structure invalid:
16
+ - ${o.errors.join(`
17
+ - `)}`);V(r);L(e,n,{source:i?.source??{kind:"local",path:r},commitHash:getCommitHash(r)??"local",installedAt:i?.installedAt??new Date().toISOString(),updatedAt:new Date().toISOString()});writeLockFile(e)}function dn(n,t,e,i,r){const o=getMonoreposDir(),c=l.join(o,e),s=a.existsSync(c),u=s?c:n,p=s?P(c):i;if(!p||!D(p))throw new h(`Monorepo manifest missing or invalid at ${u}`);let d=tn(p);if(r){d=d.filter((f)=>f.name===r);if(d.length===0){if(p.plugins?.[r])throw new h(`Sub-plugin "${r}" is disabled in the manifest.`);throw new h(`Sub-plugin "${r}" not found in monorepo. Available: ${Object.keys(p.plugins??{}).join(", ")}`)}}const m=[],b=readLockFile(),g=[];a.mkdirSync(y,{recursive:!0});for(const{name:f,entry:k}of d){const _=x(k);if(_&&!j(_)){S.warn(`Skipping "${f}": requires ppcli ${_}`);continue}let I;try{I=E(u,k.path)}catch{S.warn(`Skipping "${f}": path "${k.path}" escapes repo root.`);continue}if(!a.existsSync(I)){S.warn(`Skipping "${f}": path "${k.path}" not found in repo.`);continue}const z=validatePluginStructure(I);if(!z.valid){S.warn(`Skipping "${f}": invalid structure — ${z.errors.join(", ")}`);continue}const q=l.join(y,f);if(a.existsSync(q)){S.warn(`Skipping "${f}": already installed at ${q}`);continue}g.push({name:f,entry:k})}if(g.length===0)return m;const N=g.map(({name:f,entry:k})=>({name:f,subPath:k.path}));if(s)postInstallMonorepoLifecycle(c,g.map((f)=>E(c,f.entry.path)));else postInstallMonorepoLifecycle(n,g.map((f)=>E(n,f.entry.path)));Y(c,y,N,s?void 0:{stagingDir:n,parentDir:o},(f)=>{for(const{name:k,entry:_}of g){if(f)L(b,k,{source:{kind:"monorepo",url:t,repoName:e,subPath:_.path},commitHash:f});m.push(k)}writeLockFile(b)});return m}function fn(n,t,e,i,r){const o=[];for(const[c,s]of Object.entries(t)){if(s.source.kind!=="monorepo"||s.source.repoName!==n)continue;const u=e.plugins?.[c];if(!u||u.disabled)throw Error(`Installed sub-plugin "${c}" no longer exists in ${i}`);const p=x(u);if(p&&!j(p))throw Error(`Sub-plugin "${c}" requires ppcli ${p}`);const d=E(r,u.path),m=validatePluginStructure(d);if(!m.valid)throw Error(`Updated sub-plugin "${c}" is invalid:
18
+ - ${m.errors.join(`
19
+ - `)}`);o.push({name:c,lockEntry:s,manifestEntry:u})}return o}function mn(n,t,e,i,r){for(const o of t){if(!r)continue;L(n,o.name,{...o.lockEntry,source:{kind:"monorepo",url:e,repoName:i,subPath:o.manifestEntry.path},commitHash:r,updatedAt:new Date().toISOString()})}}function gn(n,t,e,i,r){if(!r)return;L(n,t,{source:{kind:"git",url:e},commitHash:r,installedAt:i?.installedAt??new Date().toISOString(),updatedAt:new Date().toISOString()})}export function uninstallPlugin(n){const t=l.join(y,n);if(!W(t))throw Error(`Plugin "${n}" is not installed.`);const e=readLockFile(),i=e[n];if(isSymlinkSync(t))a.unlinkSync(t);else a.rmSync(t,{recursive:!0,force:!0});if(i?.source.kind==="monorepo"){delete e[n];const o=i.source.repoName;if(!Object.values(e).some((s)=>s.source.kind==="monorepo"&&s.source.repoName===o)){const s=l.join(getMonoreposDir(),o);try{a.rmSync(s,{recursive:!0,force:!0})}catch{}}}else if(e[n])delete e[n];writeLockFile(e)}function isSymlinkSync(n){try{return a.lstatSync(n).isSymbolicLink()}catch{return!1}}export function updatePlugin(n){const t=l.join(y,n);if(!a.existsSync(t))throw Error(`Plugin "${n}" is not installed.`);const e=readLockFile(),i=e[n],r=resolvePluginSource(i,t);if(r?.kind==="local"){pn(n,t,e,i);return}if(r?.kind==="monorepo"){const c=l.join(getMonoreposDir(),r.repoName),s=r.repoName,u=r.url;J(u,(p)=>{const d=P(p);if(!d||!D(d))throw Error(`Updated source is no longer a monorepo: ${u}`);const m=x(d);if(m&&!j(m))throw Error(`Plugin requires ppcli ${m}, but current version is incompatible.`);const b=fn(s,e,d,u,p);if(b.length>0)postInstallMonorepoLifecycle(p,b.map((g)=>E(p,g.manifestEntry.path)));Y(c,y,b.map((g)=>({name:g.name,subPath:g.manifestEntry.path})),{stagingDir:p,parentDir:l.dirname(c)},(g)=>{mn(e,b,u,s,g);writeLockFile(e)})});return}const o=cn(i,t);J(o,(c)=>{const s=P(c);if(s&&D(s))throw Error(`Updated source is now a monorepo: ${o}`);const u=x(s);if(u&&!j(u))throw Error(`Plugin requires ppcli ${u}, but current version is incompatible.`);K(c);Q(c,t,(p)=>{gn(e,n,o,e[n],p);if(p)writeLockFile(e)})})}export function updateAllPlugins(){return listPlugins().map((n)=>{try{updatePlugin(n.name);return{name:n.name,success:!0}}catch(t){return{name:n.name,success:!1,error:v(t)}}})}export function listPlugins(){if(!a.existsSync(y))return[];const n=a.readdirSync(y,{withFileTypes:!0}),t=readLockFile(),e=[];for(const i of n){const r=l.join(y,i.name);if(!(i.isDirectory()||isSymlinkSync(r)))continue;const c=hn(r),s=t[i.name],u=P(r);let p=u?.description,d=u?.version;if(s?.source.kind==="monorepo"&&!p){const b=l.join(getMonoreposDir(),s.source.repoName),N=P(b)?.plugins?.[i.name];if(N){p=p??N.description;d=d??N.version}}const m=resolveStoredPluginSource(s,r);e.push({name:i.name,path:r,commands:c,source:m,version:d??s?.commitHash?.slice(0,7),installedAt:s?.installedAt,monorepoName:s?.source.kind==="monorepo"?s.source.repoName:void 0,description:p})}return e}function hn(n){try{const t=a.readdirSync(n);return[...new Set(t.filter((i)=>i.endsWith(".ts")&&!i.endsWith(".d.ts")&&!i.endsWith(".test.ts")||i.endsWith(".js")&&!i.endsWith(".d.js")).map((i)=>l.basename(i,l.extname(i))))]}catch{return[]}}function yn(n){try{return U("git",["config","--get","remote.origin.url"],{cwd:n,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return}}function parseSource(n){if(n.startsWith("file://"))try{const s=l.resolve(R(n));return{type:"local",localPath:s,name:l.basename(s).replace(/^opencli-plugin-/,"")}}catch{return null}if(l.isAbsolute(n)){const s=l.resolve(n);return{type:"local",localPath:s,name:l.basename(s).replace(/^opencli-plugin-/,"")}}const t=n.match(/^github:([\w.-]+)\/([\w.-]+)\/([\w.-]+)$/);if(t){const[,s,u,p]=t,d=u.replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:`https://github.com/${s}/${u}.git`,name:d,subPlugin:p}}const e=n.match(/^github:([\w.-]+)\/([\w.-]+)$/);if(e){const[,s,u]=e,p=u.replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:`https://github.com/${s}/${u}.git`,name:p}}const i=n.match(/^https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+?)(?:\.git)?$/);if(i){const[,s,u]=i,p=u.replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:`https://github.com/${s}/${u}.git`,name:p}}const r=n.match(/^ssh:\/\/[^/]+\/(.*?)(?:\.git)?$/);if(r){const d=r[1].split("/").pop().replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:n,name:d}}const o=n.match(/^git@[^:]+:(.+?)(?:\.git)?$/);if(o){const d=o[1].split("/").pop().replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:n,name:d}}const c=n.match(/^https?:\/\/[^/]+\/(.+?)(?:\.git)?$/);if(c){const d=c[1].split("/").pop().replace(/^opencli-plugin-/,"");return{type:"git",cloneUrl:n.endsWith(".git")?n:`${n}.git`,name:d}}return null}function Sn(n){try{const t=resolveHostOpencliRoot(),e=l.join(n,"node_modules","@jackwener","opencli");if(a.existsSync(e))a.rmSync(e,{recursive:!0,force:!0});a.mkdirSync(l.dirname(e),{recursive:!0});const i=w?"junction":"dir";a.symlinkSync(t,e,i);S.debug(`Linked host ppcli into plugin: ${e} → ${t}`)}catch(t){S.warn(`Failed to link host ppcli into plugin: ${v(t)}`)}}export function resolveEsbuildBin(){const n=resolveHostOpencliRoot();if(w){const e=l.join(n,"node_modules",".bin","esbuild.cmd");if(a.existsSync(e))return e}if(!w)try{const e=import.meta.resolve("esbuild/package.json");if(e.startsWith("file://")){const i=R(e),r=a.readFileSync(i,"utf8"),o=JSON.parse(r);if(o.bin&&typeof o.bin==="object"&&o.bin.esbuild){const c=l.resolve(l.dirname(i),o.bin.esbuild);if(a.existsSync(c))return c}else if(typeof o.bin==="string"){const c=l.resolve(l.dirname(i),o.bin);if(a.existsSync(c))return c}}}catch{}const t=l.join(n,"node_modules",".bin","esbuild");if(a.existsSync(t))return t;try{const i=nn(w?"where esbuild":"which esbuild",{encoding:"utf-8",stdio:"pipe"}).trim().split(`
20
+ `)[0].trim();if(i&&a.existsSync(i))return i}catch{}return null}function resolveHostOpencliRoot(n=R(import.meta.url)){let t=l.dirname(n);while(!0){const e=l.join(t,"package.json");if(a.existsSync(e))try{if(JSON.parse(a.readFileSync(e,"utf-8"))?.name==="@jackwener/opencli")return t}catch{}const i=l.dirname(t);if(i===t)break;t=i}return l.resolve(l.dirname(n),"..")}function kn(n){try{const t=resolveEsbuildBin();if(!t){S.warn("esbuild not found. TS plugin files will not be transpiled and may fail to load. Install esbuild (`npm i -g esbuild`) or ensure it is available in the ppcli host node_modules.");return}const i=a.readdirSync(n).filter((r)=>r.endsWith(".ts")&&!r.endsWith(".d.ts")&&!r.endsWith(".test.ts"));for(const r of i){const o=r.replace(/\.ts$/,".js"),c=l.join(n,o);if(a.existsSync(c))continue;try{U(t,[r,`--outfile=${o}`,"--format=esm","--platform=node"],{cwd:n,encoding:"utf-8",stdio:["pipe","pipe","pipe"],...w&&{shell:!0}});S.debug(`Transpiled plugin file: ${r} → ${o}`)}catch(s){S.warn(`Failed to transpile ${r}: ${v(s)}`)}}}catch(t){S.warn(`TS transpilation setup failed: ${v(t)}`)}}export{resolveHostOpencliRoot as _resolveHostOpencliRoot,resolveEsbuildBin as _resolveEsbuildBin,getCommitHash as _getCommitHash,installDependencies as _installDependencies,parseSource as _parseSource,postInstallMonorepoLifecycle as _postInstallMonorepoLifecycle,readLockFile as _readLockFile,readLockFileWithWriter as _readLockFileWithWriter,updateAllPlugins as _updateAllPlugins,validatePluginStructure as _validatePluginStructure,writeLockFile as _writeLockFile,writeLockFileWithFs as _writeLockFileWithFs,isSymlinkSync as _isSymlinkSync,getMonoreposDir as _getMonoreposDir,installLocalPlugin as _installLocalPlugin,isLocalPluginSource as _isLocalPluginSource,moveDir as _moveDir,resolvePluginSource as _resolvePluginSource,resolveStoredPluginSource as _resolveStoredPluginSource,toStoredPluginSource as _toStoredPluginSource,toLocalPluginSource as _toLocalPluginSource};
@@ -1,2 +1,2 @@
1
- import*as m from"node:fs";import*as p from"node:os";import*as f from"node:path";import $ from"js-yaml";import{ConfigError as s,RateLimitError as v,getErrorMessage as S}from"./errors.js";import{isRecord as l}from"./utils.js";const g="rate-limits.yaml",x="rate-limit-state.json";export function getRateLimitConfigPath(t=p.homedir()){return f.join(t,".ppcli",g)}export function getRateLimitStatePath(t=p.homedir()){return f.join(t,".ppcli",x)}export function enforceRateLimit(t,e={}){const r=e.configPath??getRateLimitConfigPath(),n=findRateLimitRule(t,r);if(!n)return;const o=e.statePath??getRateLimitStatePath(),i=e.now??Date.now(),a=M(o),c=Array.isArray(a.commands[t])?a.commands[t]:[],h=i-n.windowMs,u=c.filter((d)=>Number.isFinite(d)&&d>h);if(u.length>=n.limit){const d=Math.min(...u),b=Math.max(0,d+n.windowMs-i);a.commands[t]=u;y(o,a);throw new v(t,b,r)}a.commands[t]=[...u,i];y(o,a)}export function findRateLimitRule(t,e=getRateLimitConfigPath()){return loadRateLimitRules(e).find((n)=>n.command===t)??null}export function loadRateLimitRules(t=getRateLimitConfigPath()){if(!m.existsSync(t))return[];let e;try{e=$.load(m.readFileSync(t,"utf-8"))??{}}catch(n){throw new s(`Failed to parse ${t}: ${S(n)}`,"Fix the YAML syntax or remove the file to disable command rate limits.")}if(!l(e))throw new s(`Invalid ${t}: root value must be an object with a rules array.`);const r=e.rules;if(r===void 0)return[];if(!Array.isArray(r))throw new s(`Invalid ${t}: rules must be an array.`);return r.map((n,o)=>F(n,o,t))}function F(t,e,r){const n=`${r} rules[${e}]`;if(!l(t))throw new s(`Invalid ${n}: rule must be an object.`);const o=typeof t.command==="string"?t.command.trim():"";if(!o)throw new s(`Invalid ${n}: command must be a non-empty string.`);const i=Number(t.limit);if(!Number.isInteger(i)||i<=0)throw new s(`Invalid ${n}: limit must be a positive integer.`);if(typeof t.window!=="string"&&typeof t.window!=="number")throw new s(`Invalid ${n}: window must be a duration like 10m, 1h, or 500ms.`);return{command:o,limit:i,windowMs:I(t.window,`${n}.window`)}}function I(t,e){const r=String(t).trim(),n=/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/.exec(r);if(!n)throw new s(`Invalid ${e}: expected a duration like 10m, 1h, or 500ms.`);const o=Number.parseFloat(n[1]),i=n[2]??"ms",c=Math.round(o*(i==="h"?3600000:i==="m"?60000:i==="s"?1000:1));if(!Number.isFinite(c)||c<=0)throw new s(`Invalid ${e}: duration must be greater than zero.`);return c}function M(t){if(!m.existsSync(t))return w();try{const e=JSON.parse(m.readFileSync(t,"utf-8"));if(!l(e)||!l(e.commands))return w();const r={};for(const[n,o]of Object.entries(e.commands)){if(!Array.isArray(o))continue;r[n]=o.filter((i)=>typeof i==="number"&&Number.isFinite(i))}return{version:1,commands:r}}catch{return w()}}function y(t,e){m.mkdirSync(f.dirname(t),{recursive:!0});const r=`${t}.${process.pid}.${Date.now()}.tmp`;m.writeFileSync(r,JSON.stringify(e,null,2)+`
1
+ import*as m from"node:fs";import*as p from"node:os";import*as f from"node:path";import v from"js-yaml";import{ConfigError as s,RateLimitError as S,getErrorMessage as g}from"./errors.js";import{isRecord as l}from"./utils.js";const x="rate-limits.yaml",F="rate-limit-state.json";export function getRateLimitConfigPath(t=p.homedir()){return f.join(t,".ppcli",x)}export function getRateLimitStatePath(t=p.homedir()){return f.join(t,".ppcli",F)}export function enforceRateLimit(t,e={}){const r=e.configPath??getRateLimitConfigPath(),n=findRateLimitRule(t,r);if(!n)return;const o=e.statePath??getRateLimitStatePath(),i=e.now??Date.now(),a=A(o),c=Array.isArray(a.commands[t])?a.commands[t]:[],h=i-n.windowMs,u=c.filter((d)=>Number.isFinite(d)&&d>h);if(u.length>=n.limit){const d=Math.min(...u),b=Math.max(0,d+n.windowMs-i);a.commands[t]=u;y(o,a);throw new S(t,b,r)}a.commands[t]=[...u,i];y(o,a)}export function findRateLimitRule(t,e=getRateLimitConfigPath()){return loadRateLimitRules(e).find((n)=>n.command===t)??null}export function loadRateLimitRules(t=getRateLimitConfigPath()){if(!m.existsSync(t))return[];let e;try{e=v.load(m.readFileSync(t,"utf-8"))??{}}catch(n){throw new s(`Failed to parse ${t}: ${g(n)}`,"Fix the YAML syntax or remove the file to disable command rate limits.")}if(!l(e))throw new s(`Invalid ${t}: root value must be an object with a rules array.`);const r=e.rules;if(r===void 0)return[];if(!Array.isArray(r))throw new s(`Invalid ${t}: rules must be an array.`);return r.map((n,o)=>I(n,o,t))}function I(t,e,r){const n=`${r} rules[${e}]`;if(!l(t))throw new s(`Invalid ${n}: rule must be an object.`);const o=typeof t.command==="string"?t.command.trim():"";if(!o)throw new s(`Invalid ${n}: command must be a non-empty string.`);const i=Number(t.limit);if(!Number.isInteger(i)||i<=0)throw new s(`Invalid ${n}: limit must be a positive integer.`);if(typeof t.window!=="string"&&typeof t.window!=="number")throw new s(`Invalid ${n}: window must be a duration like 10m, 1h, or 500ms.`);return{command:o,limit:i,windowMs:M(t.window,`${n}.window`)}}function M(t,e){const r=String(t).trim(),n=/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/.exec(r);if(!n)throw new s(`Invalid ${e}: expected a duration like 10m, 1h, or 500ms.`);const o=Number.parseFloat(n[1]),i=n[2]??"ms",c=Math.round(o*(i==="h"?3600000:i==="m"?60000:i==="s"?1000:1));if(!Number.isFinite(c)||c<=0)throw new s(`Invalid ${e}: duration must be greater than zero.`);return c}function A(t){if(!m.existsSync(t))return w();try{const e=JSON.parse(m.readFileSync(t,"utf-8"));if(!l(e)||!l(e.commands))return w();const r={};for(const[n,o]of Object.entries(e.commands)){if(!Array.isArray(o))continue;r[n]=o.filter((i)=>typeof i==="number"&&Number.isFinite(i))}return{version:1,commands:r}}catch{return w()}}function y(t,e){m.mkdirSync(f.dirname(t),{recursive:!0});const r=`${t}.${process.pid}.${Date.now()}.tmp`;m.writeFileSync(r,JSON.stringify(e,null,2)+`
2
2
  `,"utf-8");m.renameSync(r,t)}function w(){return{version:1,commands:{}}}
@@ -1 +1 @@
1
- export var Strategy;(function(j){j.PUBLIC="public";j.LOCAL="local";j.COOKIE="cookie";j.INTERCEPT="intercept";j.UI="ui"})(Strategy||(Strategy={}));const J=globalThis.__opencli_registry__??=new Map;export function cli(j){const q={site:j.site,name:j.name,aliases:j.aliases,description:j.description??"",access:j.access,example:j.example,domain:j.domain,strategy:j.strategy,browser:j.browser,args:j.args??[],columns:j.columns,func:j.func,pipeline:j.pipeline,footerExtra:j.footerExtra,validateArgs:j.validateArgs,navigateBefore:j.navigateBefore,siteSession:j.siteSession,defaultWindowMode:j.defaultWindowMode,defaultFormat:j.defaultFormat,authStatus:j.authStatus};registerCommand(q);return J.get(fullName(q))}export function getRegistry(){return J}export function fullName(j){return`${j.site}/${j.name}`}export function strategyLabel(j){return j.strategy??Strategy.PUBLIC}function M(j){const q=j.args.filter((I)=>I.fromFile);if(q.length===0)return;const G=`${j.site}/${j.name}`;if(q.length>1)throw Error(`Command ${G}: 只能有一个 fromFile 参数,当前有 ${q.map((I)=>I.name).join(", ")}`);const D=q[0],H=typeof D.fromFile==="string"?D.fromFile:"file",E=j.args.find((I)=>I.name===H);if(E){if(E.generatedFileFor===D.name)return;throw Error(`Command ${G}: fromFile 想生成的 --${H} 与已有参数重名;`+`给 ${D.name} 的 fromFile 指定别的名字(如 '${D.name}-file')`)}const L=D.positional?`<${D.name}>`:`--${D.name}`;j.args=j.args.map((I)=>I===D?{...I,required:!1,requiredUnlessFile:I.required===!0}:I);j.args.push({name:H,generatedFileFor:D.name,help:`从本机文件读取${D.name}(UTF-8),与 ${L} 二选一。`+"长正文建议走文件:命令行上只剩短参数,不受 shell 引号 / 换行 / 编码影响"})}function O(j){Q(j);R(j);M(j);const q=j.strategy??(j.browser===!1?Strategy.PUBLIC:Strategy.COOKIE),G=j.browser??(q!==Strategy.PUBLIC&&q!==Strategy.LOCAL);let D=j.navigateBefore;if(D===void 0){if(q===Strategy.COOKIE&&j.domain)D=`https://${j.domain}`;else if(q!==Strategy.PUBLIC&&q!==Strategy.LOCAL)D=!0}return G?{...j,strategy:q,browser:!0,navigateBefore:D}:{...j,strategy:q,browser:!1,navigateBefore:D}}function Q(j){if(j.access==="read"||j.access==="write")return;const q=`${j.site}/${j.name}`;throw Error(`Command ${q} must declare access: 'read' | 'write'`)}function R(j){if(j.siteSession===void 0)return;const q=`${j.site}/${j.name}`;if(j.siteSession!=="ephemeral"&&j.siteSession!=="persistent")throw Error(`Command ${q} siteSession must be one of: ephemeral, persistent`)}export function registerCommand(j){const q=O(j),G=fullName(q),D=J.get(G);if(D?.aliases)for(const E of D.aliases)J.delete(`${D.site}/${E}`);const H=T(q.aliases,q.name);q.aliases=H.length>0?H:void 0;J.set(G,q);for(const E of H)J.set(`${q.site}/${E}`,q)}function T(j,q){if(!Array.isArray(j)||j.length===0)return[];const G=new Set,D=[];for(const H of j){const E=typeof H==="string"?H.trim():"";if(!E||E===q||G.has(E))continue;G.add(E);D.push(E)}return D}
1
+ export var Strategy;(function(e){e.PUBLIC="public";e.LOCAL="local";e.COOKIE="cookie";e.INTERCEPT="intercept";e.UI="ui"})(Strategy||(Strategy={}));const o=globalThis.__opencli_registry__??=new Map;export function cli(e){const n={site:e.site,name:e.name,aliases:e.aliases,description:e.description??"",access:e.access,example:e.example,domain:e.domain,strategy:e.strategy,browser:e.browser,args:e.args??[],columns:e.columns,func:e.func,pipeline:e.pipeline,footerExtra:e.footerExtra,validateArgs:e.validateArgs,navigateBefore:e.navigateBefore,siteSession:e.siteSession,defaultWindowMode:e.defaultWindowMode,defaultFormat:e.defaultFormat,authStatus:e.authStatus};registerCommand(n);return o.get(fullName(n))}export function getRegistry(){return o}export function fullName(e){return`${e.site}/${e.name}`}export function strategyLabel(e){return e.strategy??Strategy.PUBLIC}function f(e){const n=e.args.filter((a)=>a.fromFile);if(n.length===0)return;const t=`${e.site}/${e.name}`;if(n.length>1)throw Error(`Command ${t}: 只能有一个 fromFile 参数,当前有 ${n.map((a)=>a.name).join(", ")}`);const r=n[0],s=typeof r.fromFile==="string"?r.fromFile:"file",i=e.args.find((a)=>a.name===s);if(i){if(i.generatedFileFor===r.name)return;throw Error(`Command ${t}: fromFile 想生成的 --${s} 与已有参数重名;`+`给 ${r.name} 的 fromFile 指定别的名字(如 '${r.name}-file')`)}const l=r.positional?`<${r.name}>`:`--${r.name}`;e.args=e.args.map((a)=>a===r?{...a,required:!1,requiredUnlessFile:a.required===!0}:a);e.args.push({name:s,generatedFileFor:r.name,help:`从本机文件读取${r.name}(UTF-8),与 ${l} 二选一。`+"长正文建议走文件:命令行上只剩短参数,不受 shell 引号 / 换行 / 编码影响"})}function u(e){c(e);m(e);f(e);const n=e.strategy??(e.browser===!1?Strategy.PUBLIC:Strategy.COOKIE),t=e.browser??(n!==Strategy.PUBLIC&&n!==Strategy.LOCAL);let r=e.navigateBefore;if(r===void 0){if(n===Strategy.COOKIE&&e.domain)r=`https://${e.domain}`;else if(n!==Strategy.PUBLIC&&n!==Strategy.LOCAL)r=!0}return t?{...e,strategy:n,browser:!0,navigateBefore:r}:{...e,strategy:n,browser:!1,navigateBefore:r}}function c(e){if(e.access==="read"||e.access==="write")return;const n=`${e.site}/${e.name}`;throw Error(`Command ${n} must declare access: 'read' | 'write'`)}function m(e){if(e.siteSession===void 0)return;const n=`${e.site}/${e.name}`;if(e.siteSession!=="ephemeral"&&e.siteSession!=="persistent")throw Error(`Command ${n} siteSession must be one of: ephemeral, persistent`)}export function registerCommand(e){const n=u(e),t=fullName(n),r=o.get(t);if(r?.aliases)for(const i of r.aliases)o.delete(`${r.site}/${i}`);const s=g(n.aliases,n.name);n.aliases=s.length>0?s:void 0;o.set(t,n);for(const i of s)o.set(`${n.site}/${i}`,n)}function g(e,n){if(!Array.isArray(e)||e.length===0)return[];const t=new Set,r=[];for(const s of e){const i=typeof s==="string"?s.trim():"";if(!i||i===n||t.has(i))continue;t.add(i);r.push(i)}return r}
@@ -1 +1 @@
1
- export const MIN_SUPPORTED_NODE_MAJOR=20;export function detectRuntime(){return globalThis.Bun!==void 0?"bun":"node"}export function getRuntimeVersion(){const k=globalThis.Bun;return k?k.version:process.version}export function getRuntimeLabel(){return`${detectRuntime()} ${getRuntimeVersion()}`}export function parseNodeMajor(k){const q=/^v?(\d+)\./.exec(String(k).trim());if(!q)return null;const w=Number(q[1]);return Number.isInteger(w)?w:null}export function isSupportedNodeVersion(k=process.version){const q=parseNodeMajor(k);return q!==null&&q>=MIN_SUPPORTED_NODE_MAJOR}
1
+ export const MIN_SUPPORTED_NODE_MAJOR=20;export function detectRuntime(){return globalThis.Bun!==void 0?"bun":"node"}export function getRuntimeVersion(){const n=globalThis.Bun;return n?n.version:process.version}export function getRuntimeLabel(){return`${detectRuntime()} ${getRuntimeVersion()}`}export function parseNodeMajor(n){const e=/^v?(\d+)\./.exec(String(n).trim());if(!e)return null;const r=Number(e[1]);return Number.isInteger(r)?r:null}export function isSupportedNodeVersion(n=process.version){const e=parseNodeMajor(n);return e!==null&&e>=MIN_SUPPORTED_NODE_MAJOR}
@@ -1 +1 @@
1
- import{BrowserBridge as X,CDPBridge as Y}from"./browser/index.js";import{TimeoutError as Z}from"./errors.js";import{isElectronApp as $}from"./electron-apps.js";import{DEFAULT_BROWSER_COMMAND_TIMEOUT,DEFAULT_BROWSER_CONNECT_TIMEOUT}from"./browser/config.js";export{DEFAULT_BROWSER_COMMAND_TIMEOUT,DEFAULT_BROWSER_CONNECT_TIMEOUT};export function getBrowserFactory(z){if(z&&$(z))return Y;return X}export async function runWithTimeout(z,G){const q=G.label??"Operation";return withTimeoutMs(z,G.timeout*1000,()=>new Z(q,G.timeout,G.hint))}export function withTimeoutMs(z,G,q="Operation timed out"){const H=typeof q==="string"?()=>Error(q):q;return new Promise((J,Q)=>{const V=setTimeout(()=>Q(H()),G);z.then((K)=>{clearTimeout(V);J(K)},(K)=>{clearTimeout(V);Q(K)})})}export async function browserSession(z,G,q={}){const H=new z;try{const J=await H.connect({timeout:DEFAULT_BROWSER_CONNECT_TIMEOUT,session:q.session,cdpEndpoint:q.cdpEndpoint,contextId:q.contextId,idleTimeout:q.idleTimeout,windowMode:q.windowMode,surface:q.surface,siteSession:q.siteSession,initScript:q.initScript,proxyAuth:q.proxyAuth});return await G(J)}finally{await H.close().catch(()=>{})}}
1
+ import{BrowserBridge as s,CDPBridge as m}from"./browser/index.js";import{TimeoutError as a}from"./errors.js";import{isElectronApp as w}from"./electron-apps.js";import{DEFAULT_BROWSER_COMMAND_TIMEOUT,DEFAULT_BROWSER_CONNECT_TIMEOUT}from"./browser/config.js";export{DEFAULT_BROWSER_COMMAND_TIMEOUT,DEFAULT_BROWSER_CONNECT_TIMEOUT};export function getBrowserFactory(t){if(t&&w(t))return m;return s}export async function runWithTimeout(t,i){const e=i.label??"Operation";return withTimeoutMs(t,i.timeout*1000,()=>new a(e,i.timeout,i.hint))}export function withTimeoutMs(t,i,e="Operation timed out"){const o=typeof e==="string"?()=>Error(e):e;return new Promise((r,c)=>{const u=setTimeout(()=>c(o()),i);t.then((n)=>{clearTimeout(u);r(n)},(n)=>{clearTimeout(u);c(n)})})}export async function browserSession(t,i,e={}){const o=new t;try{const r=await o.connect({timeout:DEFAULT_BROWSER_CONNECT_TIMEOUT,session:e.session,cdpEndpoint:e.cdpEndpoint,contextId:e.contextId,idleTimeout:e.idleTimeout,windowMode:e.windowMode,surface:e.surface,siteSession:e.siteSession,initScript:e.initScript,proxyAuth:e.proxyAuth});return await i(r)}finally{await o.close().catch(()=>{})}}
@@ -1 +1 @@
1
- export function detectFramework(){const e={};try{const t=document.querySelector("#app"),r=window;e.vue3=!!(t&&t.__vue_app__);e.vue2=!!(t&&t.__vue__);e.react=!!r.__REACT_DEVTOOLS_GLOBAL_HOOK__||!!document.querySelector("[data-reactroot]");e.nextjs=!!r.__NEXT_DATA__;e.nuxt=!!r.__NUXT__;if(e.vue3&&t?.__vue_app__){const _=t.__vue_app__.config?.globalProperties;e.pinia=!!(_&&_.$pinia);e.vuex=!!(_&&_.$store)}}catch{}return e}
1
+ export function detectFramework(){const _={};try{const e=document.querySelector("#app"),o=window;_.vue3=!!(e&&e.__vue_app__);_.vue2=!!(e&&e.__vue__);_.react=!!o.__REACT_DEVTOOLS_GLOBAL_HOOK__||!!document.querySelector("[data-reactroot]");_.nextjs=!!o.__NEXT_DATA__;_.nuxt=!!o.__NUXT__;if(_.vue3&&e?.__vue_app__){const t=e.__vue_app__.config?.globalProperties;_.pinia=!!(t&&t.$pinia);_.vuex=!!(t&&t.$store)}}catch{}return _}
@@ -1 +1 @@
1
- export async function interactFuzz(){const q=(f)=>new Promise((h)=>setTimeout(h,f)),u=Array.from(document.querySelectorAll('button, [role="button"], [role="tab"], .tab, .btn, a[href="javascript:void(0)"], a[href="#"]')).slice(0,15);let j=0;for(const f of u)try{const h=f.getBoundingClientRect();if(h.width>0&&h.height>0){f.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window}));j++;await q(300)}}catch{}return j}
1
+ export async function interactFuzz(){const n=(e)=>new Promise((t)=>setTimeout(t,e)),o=Array.from(document.querySelectorAll('button, [role="button"], [role="tab"], .tab, .btn, a[href="javascript:void(0)"], a[href="#"]')).slice(0,15);let c=0;for(const e of o)try{const t=e.getBoundingClientRect();if(t.width>0&&t.height>0){e.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window}));c++;await n(300)}}catch{}return c}
@@ -1 +1 @@
1
- export function discoverStores(){const s=[];try{const c=document.querySelector("#app");if(!c?.__vue_app__)return s;const r=c.__vue_app__.config?.globalProperties,a=r?.$pinia;if(a?._s)a._s.forEach((o,n)=>{const t=[],i=[];for(const e in o)try{if(e.startsWith("$")||e.startsWith("_"))continue;if(typeof o[e]==="function")t.push(e);else i.push(e)}catch{}s.push({type:"pinia",id:n,actions:t.slice(0,20),stateKeys:i.slice(0,15)})});const p=r?.$store;if(p?._modules?.root?._children){const o=p._modules.root._children;for(const[n,t]of Object.entries(o)){const i=Object.keys(t._rawModule?.actions??{}).slice(0,20),e=Object.keys(t.state??{}).slice(0,15);s.push({type:"vuex",id:n,actions:i,stateKeys:e})}}}catch{}return s}
1
+ export function discoverStores(){const e=[];try{const i=document.querySelector("#app");if(!i?.__vue_app__)return e;const r=i.__vue_app__.config?.globalProperties,a=r?.$pinia;if(a?._s)a._s.forEach((o,n)=>{const s=[],c=[];for(const t in o)try{if(t.startsWith("$")||t.startsWith("_"))continue;if(typeof o[t]==="function")s.push(t);else c.push(t)}catch{}e.push({type:"pinia",id:n,actions:s.slice(0,20),stateKeys:c.slice(0,15)})});const p=r?.$store;if(p?._modules?.root?._children){const o=p._modules.root._children;for(const[n,s]of Object.entries(o)){const c=Object.keys(s._rawModule?.actions??{}).slice(0,20),t=Object.keys(s.state??{}).slice(0,15);e.push({type:"vuex",id:n,actions:c,stateKeys:t})}}}catch{}return e}
@@ -1,4 +1,4 @@
1
- import{fullName as J,strategyLabel as K}from"./registry.js";export function serializeArg(k){return{name:k.name,type:k.type??"string",required:!!k.required,valueRequired:!!k.valueRequired,positional:!!k.positional,choices:k.choices??[],default:k.default??null,help:k.help??""}}export function serializeCommand(k){return{command:J(k),site:k.site,name:k.name,aliases:k.aliases??[],description:k.description,access:k.access,strategy:K(k),browser:!!k.browser,args:k.args.map(serializeArg),columns:k.columns??[],domain:k.domain??null,example:formatCommandExample(k),defaultFormat:k.defaultFormat??null,siteSession:k.siteSession??null}}export function formatArgSummary(k){return k.map((v)=>{if(v.positional)return v.required?`<${v.name}>`:`[${v.name}]`;return v.required?`--${v.name}`:`[--${v.name}]`}).join(" ")}function M(k){if(k.length<=4)return k.join(", ");return`${k.slice(0,4).join(", ")}, ... (+${k.length-4} more)`}function F(k){return`<${k}>`}export function formatCommandExample(k){if(k.example?.trim())return k.example.trim();const v=["ppcli",k.site,k.name],D=(q)=>q.required||q.requiredUnlessFile;for(const q of k.args)if(q.positional&&D(q))v.push(F(q.name));for(const q of k.args){if(q.positional||!D(q))continue;v.push(`--${q.name}`);if(q.type!=="bool"&&q.type!=="boolean")v.push(F(q.name))}v.push("-f","yaml");return v.join(" ")}export function formatRegistryHelpText(k){const v=[],D=k.args.filter((B)=>B.choices?.length);for(const B of D){const H=B.positional?`<${B.name}>`:`--${B.name}`,I=B.default!=null?` (default: ${B.default})`:"";v.push(` ${H}: ${M(B.choices)}${I}`)}const q=[];q.push(`Access: ${k.access}`);q.push(`Browser: ${k.browser?"yes":"no"}`);if(k.domain)q.push(`Domain: ${k.domain}`);if(k.defaultFormat)q.push(`Default format: ${k.defaultFormat}`);if(k.aliases?.length)q.push(`Aliases: ${k.aliases.join(", ")}`);v.push(q.join(" | "));v.push(`Example: ${formatCommandExample(k)}`);if(k.columns?.length)v.push(`Output columns: ${k.columns.join(", ")}`);return`
2
- `+v.join(`
1
+ import{fullName as l,strategyLabel as u}from"./registry.js";export function serializeArg(e){return{name:e.name,type:e.type??"string",required:!!e.required,valueRequired:!!e.valueRequired,positional:!!e.positional,choices:e.choices??[],default:e.default??null,help:e.help??""}}export function serializeCommand(e){return{command:l(e),site:e.site,name:e.name,aliases:e.aliases??[],description:e.description,access:e.access,strategy:u(e),browser:!!e.browser,args:e.args.map(serializeArg),columns:e.columns??[],domain:e.domain??null,example:formatCommandExample(e),defaultFormat:e.defaultFormat??null,siteSession:e.siteSession??null}}export function formatArgSummary(e){return e.map((o)=>{if(o.positional)return o.required?`<${o.name}>`:`[${o.name}]`;return o.required?`--${o.name}`:`[--${o.name}]`}).join(" ")}function p(e){if(e.length<=4)return e.join(", ");return`${e.slice(0,4).join(", ")}, ... (+${e.length-4} more)`}function r(e){return`<${e}>`}export function formatCommandExample(e){if(e.example?.trim())return e.example.trim();const o=["ppcli",e.site,e.name],t=(n)=>n.required||n.requiredUnlessFile;for(const n of e.args)if(n.positional&&t(n))o.push(r(n.name));for(const n of e.args){if(n.positional||!t(n))continue;o.push(`--${n.name}`);if(n.type!=="bool"&&n.type!=="boolean")o.push(r(n.name))}o.push("-f","yaml");return o.join(" ")}export function formatRegistryHelpText(e){const o=[],t=e.args.filter((s)=>s.choices?.length);for(const s of t){const i=s.positional?`<${s.name}>`:`--${s.name}`,a=s.default!=null?` (default: ${s.default})`:"";o.push(` ${i}: ${p(s.choices)}${a}`)}const n=[];n.push(`Access: ${e.access}`);n.push(`Browser: ${e.browser?"yes":"no"}`);if(e.domain)n.push(`Domain: ${e.domain}`);if(e.defaultFormat)n.push(`Default format: ${e.defaultFormat}`);if(e.aliases?.length)n.push(`Aliases: ${e.aliases.join(", ")}`);o.push(n.join(" | "));o.push(`Example: ${formatCommandExample(e)}`);if(e.columns?.length)o.push(`Output columns: ${e.columns.join(", ")}`);return`
2
+ `+o.join(`
3
3
  `)+`
4
4
  `}
@@ -1 +1 @@
1
- export const SESSION_LEASE_TTL_MS=45000,SESSION_BUSY_CODE="session_busy";export function getSessionLeaseKey(q,b,j){return`${q}␟${b}␟${encodeURIComponent(j)}`}export function parsePidFromRunId(q){const b=/^run_(\d+)_/.exec(q);if(!b)return null;const j=Number(b[1]);return Number.isInteger(j)&&j>0?j:null}export function isSessionLeaseCommand(q){return q.surface==="adapter"&&q.siteSession==="persistent"&&q.access==="write"&&typeof q.session==="string"&&q.session.length>0&&typeof q.runId==="string"&&q.runId.length>0}export class SessionLeaseRegistry{ttlMs;leases=new Map;constructor(q=SESSION_LEASE_TTL_MS){this.ttlMs=q}touch(q,b){const j=this.leases.get(q),z=j!==void 0&&(b.now-j.lastSeenAt<=this.ttlMs||b.hasPendingWork?.(j.runId)===!0);if(j!==void 0&&z&&j.runId!==b.runId)return{granted:!1,holder:j};const G=j!==void 0&&j.runId===b.runId?{...j,command:b.command,lastSeenAt:b.now}:{runId:b.runId,command:b.command,pid:parsePidFromRunId(b.runId),startedAt:b.now,lastSeenAt:b.now};this.leases.set(q,G);return{granted:!0,holder:G}}heartbeat(q,b,j){const z=this.leases.get(q);if(z!==void 0&&z.runId===b)z.lastSeenAt=j}releaseByRunId(q){for(const[b,j]of this.leases)if(j.runId===q)this.leases.delete(b)}get(q,b){const j=this.leases.get(q);if(j===void 0)return;if(b-j.lastSeenAt>this.ttlMs){this.leases.delete(q);return}return j}list(q,b){const j=[];for(const[z,G]of this.leases)if(q-G.lastSeenAt<=this.ttlMs||b?.(G.runId)===!0)j.push({key:z,...G});return j}}export function buildSessionBusyFailure(q,b,j){const z=Math.max(0,Math.round((j-b.startedAt)/1000)),G=b.pid!=null?`${b.command} (pid ${b.pid})`:b.command,H=b.pid!=null?`Wait for it to finish, or stop it with \`kill ${b.pid}\` if it is stuck.`:"Wait for it to finish, or stop that process if it is stuck.";return{message:`Session "${q}" is busy: ${G} has been driving it for ${z}s.`,errorCode:SESSION_BUSY_CODE,errorHint:`${H} Read-only commands are not blocked.`,status:409}}
1
+ export const SESSION_LEASE_TTL_MS=45000,SESSION_BUSY_CODE="session_busy";export function getSessionLeaseKey(s,e,t){return`${s}␟${e}␟${encodeURIComponent(t)}`}export function parsePidFromRunId(s){const e=/^run_(\d+)_/.exec(s);if(!e)return null;const t=Number(e[1]);return Number.isInteger(t)&&t>0?t:null}export function isSessionLeaseCommand(s){return s.surface==="adapter"&&s.siteSession==="persistent"&&s.access==="write"&&typeof s.session==="string"&&s.session.length>0&&typeof s.runId==="string"&&s.runId.length>0}export class SessionLeaseRegistry{ttlMs;leases=new Map;constructor(s=SESSION_LEASE_TTL_MS){this.ttlMs=s}touch(s,e){const t=this.leases.get(s),n=t!==void 0&&(e.now-t.lastSeenAt<=this.ttlMs||e.hasPendingWork?.(t.runId)===!0);if(t!==void 0&&n&&t.runId!==e.runId)return{granted:!1,holder:t};const r=t!==void 0&&t.runId===e.runId?{...t,command:e.command,lastSeenAt:e.now}:{runId:e.runId,command:e.command,pid:parsePidFromRunId(e.runId),startedAt:e.now,lastSeenAt:e.now};this.leases.set(s,r);return{granted:!0,holder:r}}heartbeat(s,e,t){const n=this.leases.get(s);if(n!==void 0&&n.runId===e)n.lastSeenAt=t}releaseByRunId(s){for(const[e,t]of this.leases)if(t.runId===s)this.leases.delete(e)}get(s,e){const t=this.leases.get(s);if(t===void 0)return;if(e-t.lastSeenAt>this.ttlMs){this.leases.delete(s);return}return t}list(s,e){const t=[];for(const[n,r]of this.leases)if(s-r.lastSeenAt<=this.ttlMs||e?.(r.runId)===!0)t.push({key:n,...r});return t}}export function buildSessionBusyFailure(s,e,t){const n=Math.max(0,Math.round((t-e.startedAt)/1000)),r=e.pid!=null?`${e.command} (pid ${e.pid})`:e.command,o=e.pid!=null?`Wait for it to finish, or stop it with \`kill ${e.pid}\` if it is stuck.`:"Wait for it to finish, or stop that process if it is stuck.";return{message:`Session "${s}" is busy: ${r} has been driving it for ${n}s.`,errorCode:SESSION_BUSY_CODE,errorHint:`${o} Read-only commands are not blocked.`,status:409}}
@@ -1,3 +1,3 @@
1
- const D=200,S=new Set(["none","presentation","separator","paragraph","tooltip","status"]),m=new Set(["contentinfo"]),O=new Set(["button","link","textbox","checkbox","radio","combobox","tab","menuitem","option","switch","slider","spinbutton","searchbox"]),A=new Set(["main","navigation","banner","heading","search","region","list","listitem","article","complementary","group","toolbar","tablist"]),U=new Set(["list","listitem","group","toolbar","tablist","navigation","region","complementary","search","article","paragraph","figure"]),C=new Set(["•","·","|","—","-","/","\\"]),N=["googleadservices.com/pagead/","alb.reddit.com/cr?","doubleclick.net/","cm.bilibili.com/cm/api/fees/"],_=["回到顶部","back to top","scroll to top","go to top"];function R(W){let q=W;if(q.startsWith("'")&&q.endsWith("':"))q=q.slice(1,-2)+":";else if(q.startsWith("'")&&q.endsWith("'"))q=q.slice(1,-1);const $=q.match(/^([a-zA-Z]+)\b/),V=$?$[1].toLowerCase():"",H=q.match(/"([^"]*)"/),P=H?H[1]:"";let K=q;K=K.replace(/"[^"]*"/g,'""');K=K.replace(/\[[^\]]*\]/g,"");const b=K.lastIndexOf(":");let F="";if(b!==-1){if(K.slice(b+1).trim().length>0){const G=q.lastIndexOf(":");if(G!==-1)F=q.slice(G+1).trim()}}return{role:V,text:P,hasText:P.length>0||F.length>0,trailingText:F}}function g(W){let q=W;if(q.startsWith("'")&&(q.endsWith("':")||q.endsWith("'")))if(q.endsWith("':"))q=q.slice(1,-2)+":";else q=q.slice(1,-1);const $=q.split('"');for(let H=0;H<$.length;H+=2)$[H]=$[H].replace(/\s*\[[^\]]*\]/g,"");return $.join('"').replace(/\s{2,}/g," ").trim()}function j(W){return/^\/[a-zA-Z]+:/.test(W)}function I(W){return C.has(W.trim())}function L(W,q){const $=(W+" "+q).toLowerCase();if($.includes("sponsored")||$.includes("advertisement"))return!0;if($.includes("广告"))return!0;for(const V of N)if(W.includes(V)||q.includes(V))return!0;return!1}function E(W){const q=W.toLowerCase();return _.some(($)=>q.includes($))}function u(W,q,$,V){if(S.has(W))return!0;if(W==="generic"&&!q)return!0;if(W==="img"&&!q)return!0;if((W==="generic"||W==="text")&&q){if(I(V||$))return!0}return!1}export function formatSnapshot(W,q={}){if(!W||typeof W!=="string")return"";const $=q.maxTextLength??D,V=W.split(`
2
- `),H=[];let P=0,K=-1;for(let Y=0;Y<V.length;Y++){const z=V[Y];if(!z.trim())continue;const Q=z.length-z.trimStart().length,Z=Math.floor(Q/2);if(K>=0){if(Z>K)continue;K=-1}let J=z.trimStart();if(J.startsWith("- "))J=J.slice(2);if(j(J))continue;if(q.maxDepth!==void 0&&Z>q.maxDepth)continue;const{role:v,text:f,hasText:k,trailingText:B}=R(J);if(u(v,k,f,B))continue;if(m.has(v)){K=Z;continue}if(L(f,B)||E(f)){K=Z;continue}J=g(J);const w=O.has(v),M=A.has(v);if(q.interactive&&!w&&!M&&!k)continue;if(q.compact)J=J.replace(/\s*\[.*?\]\s*/g," ").replace(/\s+/g," ").trim();if($>0&&J.length>$)J=J.slice(0,$)+"…";if(w){P++;J=`[@${P}] ${J}`}H.push({depth:Z,content:J,role:v,text:f,trailingText:B,isInteractive:w,isLandmark:M})}const b=[];for(let Y=0;Y<H.length;Y++){const z=H[Y];if(z.role==="generic"||z.role==="text"){let Q;for(let Z=b.length-1;Z>=0;Z--){if(b[Z].depth<z.depth){Q=b[Z];break}if(b[Z].depth===z.depth)break}if(Q){const Z=z.trailingText||z.text;if(Z&&Q.text&&Z===Q.text)continue}}if(z.role==="heading"&&z.text){const Q=H[Y+1];if(Q&&Q.role==="link"&&Q.text===z.text&&Q.depth===z.depth+1){b.push(z);Y++;continue}}if(z.role==="link"&&z.text){const Q=H[Y+1];if(Q&&Q.role==="link"&&Q.text===z.text&&Q.depth===z.depth+1)continue}b.push(z)}let F=b,X=!0;while(X){X=!1;const Y=[];for(let z=0;z<F.length;z++){const Q=F[z];if(U.has(Q.role)&&!Q.text&&!Q.trailingText){let Z=!1;for(let J=z+1;J<F.length;J++){if(F[J].depth<=Q.depth)break;if(F[J].depth>Q.depth){Z=!0;break}}if(!Z){X=!0;continue}}Y.push(Q)}F=Y}const G=[];for(let Y=0;Y<F.length;Y++){const z=F[Y];if(U.has(z.role)&&!z.text&&!z.trailingText){let Q=0,Z=-1;for(let J=Y+1;J<F.length;J++){if(F[J].depth<=z.depth)break;if(F[J].depth===z.depth+1){Q++;if(Q===1)Z=J}}if(Q===1&&Z!==-1){const J=F[Z];let v=!1;for(let f=Z+1;f<F.length;f++){if(F[f].depth<=J.depth)break;if(F[f].depth>J.depth){v=!0;break}}if(!v){G.push({...z,content:z.content.replace(/:$/,"")+" > "+J.content,role:J.role,text:J.text,trailingText:J.trailingText,isInteractive:J.isInteractive});Y++;continue}}}G.push(z)}return G.map((Y)=>" ".repeat(Y.depth)+Y.content).join(`
1
+ const k=200,A=new Set(["none","presentation","separator","paragraph","tooltip","status"]),I=new Set(["contentinfo"]),R=new Set(["button","link","textbox","checkbox","radio","combobox","tab","menuitem","option","switch","slider","spinbutton","searchbox"]),O=new Set(["main","navigation","banner","heading","search","region","list","listitem","article","complementary","group","toolbar","tablist"]),S=new Set(["list","listitem","group","toolbar","tablist","navigation","region","complementary","search","article","paragraph","figure"]),_=new Set(["•","·","|","—","-","/","\\"]),C=["googleadservices.com/pagead/","alb.reddit.com/cr?","doubleclick.net/","cm.bilibili.com/cm/api/fees/"],N=["回到顶部","back to top","scroll to top","go to top"];function w(o){let t=o;if(t.startsWith("'")&&t.endsWith("':"))t=t.slice(1,-2)+":";else if(t.startsWith("'")&&t.endsWith("'"))t=t.slice(1,-1);const c=t.match(/^([a-zA-Z]+)\b/),f=c?c[1].toLowerCase():"",a=t.match(/"([^"]*)"/),x=a?a[1]:"";let h=t;h=h.replace(/"[^"]*"/g,'""');h=h.replace(/\[[^\]]*\]/g,"");const u=h.lastIndexOf(":");let l="";if(u!==-1){if(h.slice(u+1).trim().length>0){const g=t.lastIndexOf(":");if(g!==-1)l=t.slice(g+1).trim()}}return{role:f,text:x,hasText:x.length>0||l.length>0,trailingText:l}}function W(o){let t=o;if(t.startsWith("'")&&(t.endsWith("':")||t.endsWith("'")))if(t.endsWith("':"))t=t.slice(1,-2)+":";else t=t.slice(1,-1);const c=t.split('"');for(let a=0;a<c.length;a+=2)c[a]=c[a].replace(/\s*\[[^\]]*\]/g,"");return c.join('"').replace(/\s{2,}/g," ").trim()}function v(o){return/^\/[a-zA-Z]+:/.test(o)}function D(o){return _.has(o.trim())}function j(o,t){const c=(o+" "+t).toLowerCase();if(c.includes("sponsored")||c.includes("advertisement"))return!0;if(c.includes("广告"))return!0;for(const f of C)if(o.includes(f)||t.includes(f))return!0;return!1}function y(o){const t=o.toLowerCase();return N.some((c)=>t.includes(c))}function M(o,t,c,f){if(A.has(o))return!0;if(o==="generic"&&!t)return!0;if(o==="img"&&!t)return!0;if((o==="generic"||o==="text")&&t){if(D(f||c))return!0}return!1}export function formatSnapshot(o,t={}){if(!o||typeof o!=="string")return"";const c=t.maxTextLength??k,f=o.split(`
2
+ `),a=[];let x=0,h=-1;for(let r=0;r<f.length;r++){const e=f[r];if(!e.trim())continue;const i=e.length-e.trimStart().length,s=Math.floor(i/2);if(h>=0){if(s>h)continue;h=-1}let n=e.trimStart();if(n.startsWith("- "))n=n.slice(2);if(v(n))continue;if(t.maxDepth!==void 0&&s>t.maxDepth)continue;const{role:d,text:p,hasText:E,trailingText:b}=w(n);if(M(d,E,p,b))continue;if(I.has(d)){h=s;continue}if(j(p,b)||y(p)){h=s;continue}n=W(n);const T=R.has(d),L=O.has(d);if(t.interactive&&!T&&!L&&!E)continue;if(t.compact)n=n.replace(/\s*\[.*?\]\s*/g," ").replace(/\s+/g," ").trim();if(c>0&&n.length>c)n=n.slice(0,c)+"…";if(T){x++;n=`[@${x}] ${n}`}a.push({depth:s,content:n,role:d,text:p,trailingText:b,isInteractive:T,isLandmark:L})}const u=[];for(let r=0;r<a.length;r++){const e=a[r];if(e.role==="generic"||e.role==="text"){let i;for(let s=u.length-1;s>=0;s--){if(u[s].depth<e.depth){i=u[s];break}if(u[s].depth===e.depth)break}if(i){const s=e.trailingText||e.text;if(s&&i.text&&s===i.text)continue}}if(e.role==="heading"&&e.text){const i=a[r+1];if(i&&i.role==="link"&&i.text===e.text&&i.depth===e.depth+1){u.push(e);r++;continue}}if(e.role==="link"&&e.text){const i=a[r+1];if(i&&i.role==="link"&&i.text===e.text&&i.depth===e.depth+1)continue}u.push(e)}let l=u,m=!0;while(m){m=!1;const r=[];for(let e=0;e<l.length;e++){const i=l[e];if(S.has(i.role)&&!i.text&&!i.trailingText){let s=!1;for(let n=e+1;n<l.length;n++){if(l[n].depth<=i.depth)break;if(l[n].depth>i.depth){s=!0;break}}if(!s){m=!0;continue}}r.push(i)}l=r}const g=[];for(let r=0;r<l.length;r++){const e=l[r];if(S.has(e.role)&&!e.text&&!e.trailingText){let i=0,s=-1;for(let n=r+1;n<l.length;n++){if(l[n].depth<=e.depth)break;if(l[n].depth===e.depth+1){i++;if(i===1)s=n}}if(i===1&&s!==-1){const n=l[s];let d=!1;for(let p=s+1;p<l.length;p++){if(l[p].depth<=n.depth)break;if(l[p].depth>n.depth){d=!0;break}}if(!d){g.push({...e,content:e.content.replace(/:$/,"")+" > "+n.content,role:n.role,text:n.text,trailingText:n.trailingText,isInteractive:n.isInteractive});r++;continue}}}g.push(e)}return g.map((r)=>" ".repeat(r.depth)+r.content).join(`
3
3
  `)}
package/dist/src/tui.js CHANGED
@@ -1,16 +1,16 @@
1
- import{EXIT_CODES as j}from"./errors.js";export async function checkboxPrompt(Q,P={}){if(Q.length===0)return[];const{stdin:B,stdout:J}=process;if(!B.isTTY)return Q.filter((z)=>z.checked).map((z)=>z.value);let G=0;const F=Q.map((z)=>({...z}));function U(){let z="";if(P.title)z+=`
2
- ${P.title}
1
+ import{EXIT_CODES as k}from"./errors.js";export async function checkboxPrompt(f,l={}){if(f.length===0)return[];const{stdin:n,stdout:s}=process;if(!n.isTTY)return f.filter((e)=>e.checked).map((e)=>e.value);let c=0;const r=f.map((e)=>({...e}));function d(){let e="";if(l.title)e+=`
2
+ ${l.title}
3
3
 
4
- `;for(let K=0;K<F.length;K++){const L=F[K],A=K===G?"❯":" ",V=L.checked?"◉":"○",W=L.status??"";z+=` ${A} ${V} ${L.label}${W?` ${W}`:""}
5
- `}z+=`
4
+ `;for(let o=0;o<r.length;o++){const a=r[o],t=o===c?"❯":" ",h=a.checked?"◉":"○",w=a.status??"";e+=` ${t} ${h} ${a.label}${w?` ${w}`:""}
5
+ `}e+=`
6
6
  ↑↓ navigate · Space toggle · a all · Enter confirm · q cancel
7
- `;return z}return new Promise((z)=>{const K=B.isRaw;B.setRawMode(!0);B.resume();J.write("\x1B[?25l");let L=!0;function A(){if(!L){const Z=U().split(`
8
- `).length;J.write(`\x1B[${Z}A\x1B[J`)}L=!1;J.write(U())}function V(){B.setRawMode(K??!1);B.pause();B.removeListener("data",W);const Z=U().split(`
9
- `).length;J.write(`\x1B[${Z}A\x1B[J`);J.write("\x1B[?25h")}function W(Z){const H=Z.toString();if(H==="\x1B[A"||H==="k"){G=(G-1+F.length)%F.length;A();return}if(H==="\x1B[B"||H==="j"){G=(G+1)%F.length;A();return}if(H===" "){F[G].checked=!F[G].checked;A();return}if(H==="\t"){F[G].checked=!F[G].checked;G=(G+1)%F.length;A();return}if(H==="a"){const $=F.every((M)=>M.checked);for(const M of F)M.checked=!$;A();return}if(H==="\r"||H===`
10
- `){V();const $=F.filter((M)=>M.checked).map((M)=>M.value);J.write(` ✓ ${$.length} file(s) selected
7
+ `;return e}return new Promise((e)=>{const o=n.isRaw;n.setRawMode(!0);n.resume();s.write("\x1B[?25l");let a=!0;function t(){if(!a){const p=d().split(`
8
+ `).length;s.write(`\x1B[${p}A\x1B[J`)}a=!1;s.write(d())}function h(){n.setRawMode(o??!1);n.pause();n.removeListener("data",w);const p=d().split(`
9
+ `).length;s.write(`\x1B[${p}A\x1B[J`);s.write("\x1B[?25h")}function w(p){const i=p.toString();if(i==="\x1B[A"||i==="k"){c=(c-1+r.length)%r.length;t();return}if(i==="\x1B[B"||i==="j"){c=(c+1)%r.length;t();return}if(i===" "){r[c].checked=!r[c].checked;t();return}if(i==="\t"){r[c].checked=!r[c].checked;c=(c+1)%r.length;t();return}if(i==="a"){const x=r.every((u)=>u.checked);for(const u of r)u.checked=!x;t();return}if(i==="\r"||i===`
10
+ `){h();const x=r.filter((u)=>u.checked).map((u)=>u.value);s.write(` ✓ ${x.length} file(s) selected
11
11
 
12
- `);z($);return}if(H==="q"||H==="\x1B"){V();J.write(` ✗ Cancelled
12
+ `);e(x);return}if(i==="q"||i==="\x1B"){h();s.write(` ✗ Cancelled
13
13
 
14
- `);z([]);return}if(H==="\x03"){V();process.exit(j.INTERRUPTED)}}B.on("data",W);A()})}export async function confirmPrompt(Q,P=!0){const{stdin:B,stdout:J}=process;if(!B.isTTY)return P;const G=P?"[Y/n]":"[y/N]";J.write(` ${Q} ${G} `);return new Promise((F)=>{const U=B.isRaw;B.setRawMode(!0);B.resume();function z(){B.setRawMode(U??!1);B.pause();B.removeListener("data",K);J.write(`
15
- `)}function K(L){const A=L.toString();if(A==="\x03"){z();process.exit(j.INTERRUPTED)}if(A==="\r"||A===`
16
- `){z();F(P);return}if(A==="y"||A==="Y"){z();F(!0);return}if(A==="n"||A==="N"||A==="q"||A==="\x1B"){z();F(!1);return}}B.on("data",K)})}
14
+ `);e([]);return}if(i==="\x03"){h();process.exit(k.INTERRUPTED)}}n.on("data",w);t()})}export async function confirmPrompt(f,l=!0){const{stdin:n,stdout:s}=process;if(!n.isTTY)return l;const c=l?"[Y/n]":"[y/N]";s.write(` ${f} ${c} `);return new Promise((r)=>{const d=n.isRaw;n.setRawMode(!0);n.resume();function e(){n.setRawMode(d??!1);n.pause();n.removeListener("data",o);s.write(`
15
+ `)}function o(a){const t=a.toString();if(t==="\x03"){e();process.exit(k.INTERRUPTED)}if(t==="\r"||t===`
16
+ `){e();r(l);return}if(t==="y"||t==="Y"){e();r(!0);return}if(t==="n"||t==="N"||t==="q"||t==="\x1B"){e();r(!1);return}}n.on("data",o)})}
@@ -1 +1 @@
1
- import*as j from"node:fs";import*as H from"node:os";import*as v from"node:path";export const LEGACY_USER_DIR_NAME=".opencli",USER_DIR_NAME=".ppcli";function B(k){try{j.lstatSync(k);return!0}catch{return!1}}function F(k,b){const q=j.lstatSync(k);if(q.isDirectory()){let w=0;if(!B(b)){j.mkdirSync(b,{recursive:!0,mode:q.mode});w++}else if(!j.lstatSync(b).isDirectory())return 0;for(const z of j.readdirSync(k))try{w+=F(v.join(k,z),v.join(b,z))}catch{}return w}if(B(b))return 0;j.mkdirSync(v.dirname(b),{recursive:!0});if(q.isSymbolicLink())j.symlinkSync(j.readlinkSync(k),b,process.platform==="win32"?"junction":void 0);else if(q.isFile()){j.copyFileSync(k,b,j.constants.COPYFILE_EXCL);j.chmodSync(b,q.mode)}else return 0;return 1}export function migrateLegacyUserRuntime(k=H.homedir()){try{const b=v.join(k,LEGACY_USER_DIR_NAME);if(!j.existsSync(b))return 0;return F(b,v.join(k,USER_DIR_NAME))}catch{return 0}}
1
+ import*as i from"node:fs";import*as f from"node:os";import*as e from"node:path";export const LEGACY_USER_DIR_NAME=".opencli",USER_DIR_NAME=".ppcli";function s(r){try{i.lstatSync(r);return!0}catch{return!1}}function y(r,n){const t=i.lstatSync(r);if(t.isDirectory()){let c=0;if(!s(n)){i.mkdirSync(n,{recursive:!0,mode:t.mode});c++}else if(!i.lstatSync(n).isDirectory())return 0;for(const o of i.readdirSync(r))try{c+=y(e.join(r,o),e.join(n,o))}catch{}return c}if(s(n))return 0;i.mkdirSync(e.dirname(n),{recursive:!0});if(t.isSymbolicLink())i.symlinkSync(i.readlinkSync(r),n,process.platform==="win32"?"junction":void 0);else if(t.isFile()){i.copyFileSync(r,n,i.constants.COPYFILE_EXCL);i.chmodSync(n,t.mode)}else return 0;return 1}export function migrateLegacyUserRuntime(r=f.homedir()){try{const n=e.join(r,LEGACY_USER_DIR_NAME);if(!i.existsSync(n))return 0;return y(n,e.join(r,USER_DIR_NAME))}catch{return 0}}
@@ -55,3 +55,15 @@ export declare function parseJsonOrThrowLoginWall(response: Response, opts?: {
55
55
  *
56
56
  * The Node side then calls `throwIfLoginWall(res, { url })` on the result. */
57
57
  export declare const BROWSER_JSON_SNIFF_FN = "\nasync function fetchJsonOrLoginWall(input, init) {\n const r = await fetch(input, init);\n const contentType = r.headers.get('content-type') || '';\n const text = await r.text();\n const trimmed = text.replace(/^\\s+/, '');\n const looksLikeHtml =\n contentType.toLowerCase().includes('text/html')\n || /^<(?:!doctype|html|head|body|title)(?:[\\s>/]|$)/i.test(trimmed);\n if (looksLikeHtml) {\n return {\n __loginWall: true,\n status: r.status,\n url: r.url || (typeof input === 'string' ? input : ''),\n contentType,\n bodyPreview: trimmed.slice(0, 100),\n };\n }\n if (!r.ok) {\n return { error: r.status };\n }\n try {\n return JSON.parse(text);\n } catch (err) {\n throw new Error(\n 'JSON parse failed (status=' + r.status + ', body[0..50]=' + JSON.stringify(trimmed.slice(0, 50)) + '): '\n + (err && err.message ? err.message : String(err))\n );\n }\n}\n";
58
+ /** [pp-only] 记下正文文件所在目录;传 null 清空。由 resolveFileBackedArg 调用。 */
59
+ export declare function setContentBaseDir(dir: string | null): void;
60
+ /** [pp-only] 取正文文件所在目录(没有走 --file 时为 null)。 */
61
+ export declare function getContentBaseDir(): string | null;
62
+ /**
63
+ * [pp-only] 解析正文里引用的本机相对路径。
64
+ *
65
+ * 顺序:① 正文文件所在目录(作者的心智模型)→ ② CLI cwd(老行为兜底)。
66
+ * ①存在才用①,否则回退②——这样「正文和图放一起」和「图放在 cwd」两种摆法都能发出去,
67
+ * 且绝不会因为新逻辑把原本能用的路径解析坏。绝对路径原样返回。
68
+ */
69
+ export declare function resolveContentPath(p: string): string;
package/dist/src/utils.js CHANGED
@@ -1,8 +1,8 @@
1
- import*as X from"node:fs";import*as Z from"node:path";import C from"turndown";import{LoginWallError as Y}from"./errors.js";export function isRecord(q){return typeof q==="object"&&q!==null&&!Array.isArray(q)}export async function mapConcurrent(q,z,D){const G=Array(q.length);let A=0;async function V(){while(A<q.length){const Q=A++;G[Q]=await D(q[Q],Q)}}const K=Array.from({length:Math.min(z,q.length)},()=>V());await Promise.all(K);return G}export function sleep(q){return new Promise((z)=>setTimeout(z,q))}export async function saveBase64ToFile(q,z){const D=Z.dirname(z);await X.promises.mkdir(D,{recursive:!0});await X.promises.writeFile(z,Buffer.from(q,"base64"))}export function createMarkdownConverter(q){const z=new C({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});z.addRule("linebreak",{filter:"br",replacement:()=>`
2
- `});if(q)q(z);return z}export function htmlToMarkdown(q,z){return createMarkdownConverter(z).turndown(q||"").replace(/\u00a0/g," ").replace(/\n{4,}/g,`
1
+ import*as l from"node:fs";import*as s from"node:path";import m from"turndown";import{LoginWallError as f}from"./errors.js";export function isRecord(t){return typeof t==="object"&&t!==null&&!Array.isArray(t)}export async function mapConcurrent(t,e,r){const o=Array(t.length);let n=0;async function u(){while(n<t.length){const a=n++;o[a]=await r(t[a],a)}}const i=Array.from({length:Math.min(e,t.length)},()=>u());await Promise.all(i);return o}export function sleep(t){return new Promise((e)=>setTimeout(e,t))}export async function saveBase64ToFile(t,e){const r=s.dirname(e);await l.promises.mkdir(r,{recursive:!0});await l.promises.writeFile(e,Buffer.from(t,"base64"))}export function createMarkdownConverter(t){const e=new m({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});e.addRule("linebreak",{filter:"br",replacement:()=>`
2
+ `});if(t)t(e);return e}export function htmlToMarkdown(t,e){return createMarkdownConverter(e).turndown(t||"").replace(/\u00a0/g," ").replace(/\n{4,}/g,`
3
3
 
4
4
 
5
- `).replace(/[ \t]+$/gm,"").trim()}function H(q){return typeof q==="object"&&q!==null&&q.__loginWall===!0&&typeof q.status==="number"}export function throwIfLoginWall(q,z={}){if(H(q))throw new Y(`Server returned HTML instead of JSON (status=${q.status}). Likely a login wall, rate limit, or WAF challenge.`,q.status,z.url||q.url||"",q.bodyPreview);return q}export async function parseJsonOrThrowLoginWall(q,z={}){const D=q.headers.get("content-type")||"",G=await q.text(),A=G.trimStart();if(D.toLowerCase().includes("text/html")||/^<(?:!doctype|html|head|body|title)(?:[\s>/]|$)/i.test(A))throw new Y(`Server returned HTML instead of JSON (status=${q.status}). Likely a login wall, rate limit, or WAF challenge.`,q.status,z.url||q.url||"",A.slice(0,100));try{return JSON.parse(G)}catch(K){throw Error(`JSON parse failed (status=${q.status}, body[0..50]=${JSON.stringify(A.slice(0,50))}): `+(K instanceof Error?K.message:String(K)))}}export const BROWSER_JSON_SNIFF_FN=`
5
+ `).replace(/[ \t]+$/gm,"").trim()}function d(t){return typeof t==="object"&&t!==null&&t.__loginWall===!0&&typeof t.status==="number"}export function throwIfLoginWall(t,e={}){if(d(t))throw new f(`Server returned HTML instead of JSON (status=${t.status}). Likely a login wall, rate limit, or WAF challenge.`,t.status,e.url||t.url||"",t.bodyPreview);return t}export async function parseJsonOrThrowLoginWall(t,e={}){const r=t.headers.get("content-type")||"",o=await t.text(),n=o.trimStart();if(r.toLowerCase().includes("text/html")||/^<(?:!doctype|html|head|body|title)(?:[\s>/]|$)/i.test(n))throw new f(`Server returned HTML instead of JSON (status=${t.status}). Likely a login wall, rate limit, or WAF challenge.`,t.status,e.url||t.url||"",n.slice(0,100));try{return JSON.parse(o)}catch(i){throw Error(`JSON parse failed (status=${t.status}, body[0..50]=${JSON.stringify(n.slice(0,50))}): `+(i instanceof Error?i.message:String(i)))}}export const BROWSER_JSON_SNIFF_FN=`
6
6
  async function fetchJsonOrLoginWall(input, init) {
7
7
  const r = await fetch(input, init);
8
8
  const contentType = r.headers.get('content-type') || '';
@@ -32,4 +32,4 @@ async function fetchJsonOrLoginWall(input, init) {
32
32
  );
33
33
  }
34
34
  }
35
- `;
35
+ `;const c="PP_CONTENT_BASE_DIR";export function setContentBaseDir(t){if(t)process.env[c]=t;else delete process.env[c]}export function getContentBaseDir(){return process.env[c]||null}export function resolveContentPath(t){if(s.isAbsolute(t))return t;const e=getContentBaseDir();if(e){const r=s.resolve(e,t);if(l.existsSync(r))return r}return s.resolve(t)}
@@ -1,3 +1,3 @@
1
- import{getRegistry as O,fullName as M}from"./registry.js";import{getRegisteredStepNames as Q}from"./pipeline/registry.js";function U(){return new Set(Q())}export function validateClisWithTarget(q,F){const x=O(),B=[];let I=0,H=0;if(x.size===0)return{ok:!0,results:[{label:"(registry)",errors:[],warnings:["Registry is empty — no commands discovered. Did discoverClis() run?"]}],errors:0,warnings:1,commands:0};let D=F;if(F?.includes("/")){const G=x.get(F);if(G)D=M(G)}const E=new Set;for(const[G,J]of x){if(E.has(J))continue;if(G!==M(J))continue;E.add(J);if(D){if(D.includes("/")){if(G!==D)continue}else if(J.site!==D)continue}const L=V(J);B.push(L);I+=L.errors.length;H+=L.warnings.length}return{ok:I===0,results:B,errors:I,warnings:H,commands:B.length}}function V(q){const F=M(q),x=[],B=[];if(!q.description)B.push("Missing description");if(q.browser&&!q.domain)B.push('Browser command without "domain" — authenticated browser context may not work');if(Array.isArray(q.pipeline)){const H=U();for(let D=0;D<q.pipeline.length;D++){const E=q.pipeline[D];if(E&&typeof E==="object"){for(const G of Object.keys(E))if(!H.has(G))B.push(`Pipeline step ${D}: unknown step name "${G}" (did you mean one of: ${[...H].join(", ")}?)`)}}}const I=q;if(!q.func&&!q.pipeline&&!I._lazy)x.push('Command has neither "func" nor "pipeline" — it cannot execute');if(q.args&&q.args.length>0){const H=new Set;let D=!1;for(const E of q.args){if(H.has(E.name))x.push(`Duplicate arg name "${E.name}"`);H.add(E.name);if(E.positional&&D)B.push(`Positional arg "${E.name}" appears after named args`);if(!E.positional)D=!0}}return{label:F,errors:x,warnings:B}}export function renderValidationReport(q){const F=[`ppcli validate: ${q.ok?"PASS":"FAIL"}`,`Checked ${q.commands} command(s)`,`Errors: ${q.errors} Warnings: ${q.warnings}`];for(const x of q.results)if(x.errors.length>0||x.warnings.length>0){F.push(`
2
- ${x.label}:`);for(const B of x.errors)F.push(` ❌ ${B}`);for(const B of x.warnings)F.push(` ⚠️ ${B}`)}return F.join(`
1
+ import{getRegistry as p,fullName as u}from"./registry.js";import{getRegisteredStepNames as g}from"./pipeline/registry.js";function m(){return new Set(g())}export function validateClisWithTarget(e,r){const n=p(),s=[];let l=0,a=0;if(n.size===0)return{ok:!0,results:[{label:"(registry)",errors:[],warnings:["Registry is empty — no commands discovered. Did discoverClis() run?"]}],errors:0,warnings:1,commands:0};let i=r;if(r?.includes("/")){const t=n.get(r);if(t)i=u(t)}const o=new Set;for(const[t,f]of n){if(o.has(f))continue;if(t!==u(f))continue;o.add(f);if(i){if(i.includes("/")){if(t!==i)continue}else if(f.site!==i)continue}const c=h(f);s.push(c);l+=c.errors.length;a+=c.warnings.length}return{ok:l===0,results:s,errors:l,warnings:a,commands:s.length}}function h(e){const r=u(e),n=[],s=[];if(!e.description)s.push("Missing description");if(e.browser&&!e.domain)s.push('Browser command without "domain" — authenticated browser context may not work');if(Array.isArray(e.pipeline)){const a=m();for(let i=0;i<e.pipeline.length;i++){const o=e.pipeline[i];if(o&&typeof o==="object"){for(const t of Object.keys(o))if(!a.has(t))s.push(`Pipeline step ${i}: unknown step name "${t}" (did you mean one of: ${[...a].join(", ")}?)`)}}}const l=e;if(!e.func&&!e.pipeline&&!l._lazy)n.push('Command has neither "func" nor "pipeline" — it cannot execute');if(e.args&&e.args.length>0){const a=new Set;let i=!1;for(const o of e.args){if(a.has(o.name))n.push(`Duplicate arg name "${o.name}"`);a.add(o.name);if(o.positional&&i)s.push(`Positional arg "${o.name}" appears after named args`);if(!o.positional)i=!0}}return{label:r,errors:n,warnings:s}}export function renderValidationReport(e){const r=[`ppcli validate: ${e.ok?"PASS":"FAIL"}`,`Checked ${e.commands} command(s)`,`Errors: ${e.errors} Warnings: ${e.warnings}`];for(const n of e.results)if(n.errors.length>0||n.warnings.length>0){r.push(`
2
+ ${n.label}:`);for(const s of n.errors)r.push(` ❌ ${s}`);for(const s of n.warnings)r.push(` ⚠️ ${s}`)}return r.join(`
3
3
  `)}
@@ -1,2 +1,2 @@
1
- import{validateClisWithTarget as I,renderValidationReport as J}from"./validate.js";import{spawn as K}from"node:child_process";import*as L from"node:fs";import*as H from"node:path";export async function verifyClis(q){const y=I([q.builtinClis,q.userClis],q.target);let z=null;if(q.smoke)z=await M(q.builtinClis);return{ok:y.ok&&(z?.ok??!0),validation:y,smoke:z}}export function renderVerifyReport(q){const y=J(q.validation);if(!q.smoke)return y;const z=q.smoke.ok?"PASS":"FAIL",B=q.smoke.executed?"executed":"skipped";return`${y}
2
- Smoke: ${z} (${B}) — ${q.smoke.summary}`}async function M(q){const y=H.resolve(q,".."),z=H.join(y,"tests","smoke");if(!L.existsSync(z))return{requested:!0,executed:!1,ok:!1,summary:"Smoke tests are unavailable in this package/environment."};const B=process.platform==="win32"?"npx.cmd":"npx";return new Promise((F)=>{const E=K(B,["vitest","run","tests/smoke/","--reporter=dot"],{cwd:y,env:{...process.env},stdio:["ignore","pipe","pipe"]});let G="";E.stderr.on("data",(A)=>{G+=A.toString()});E.on("error",(A)=>{F({requested:!0,executed:!1,ok:!1,summary:`Failed to start smoke tests: ${A.message}`})});E.on("close",(A)=>{F({requested:!0,executed:!0,ok:A===0,summary:A===0?"tests/smoke passed":G.trim()||`vitest exited with code ${A}`})})})}
1
+ import{validateClisWithTarget as u,renderValidationReport as c}from"./validate.js";import{spawn as d}from"node:child_process";import*as l from"node:fs";import*as m from"node:path";export async function verifyClis(e){const t=u([e.builtinClis,e.userClis],e.target);let s=null;if(e.smoke)s=await k(e.builtinClis);return{ok:t.ok&&(s?.ok??!0),validation:t,smoke:s}}export function renderVerifyReport(e){const t=c(e.validation);if(!e.smoke)return t;const s=e.smoke.ok?"PASS":"FAIL",o=e.smoke.executed?"executed":"skipped";return`${t}
2
+ Smoke: ${s} (${o}) — ${e.smoke.summary}`}async function k(e){const t=m.resolve(e,".."),s=m.join(t,"tests","smoke");if(!l.existsSync(s))return{requested:!0,executed:!1,ok:!1,summary:"Smoke tests are unavailable in this package/environment."};const o=process.platform==="win32"?"npx.cmd":"npx";return new Promise((n)=>{const i=d(o,["vitest","run","tests/smoke/","--reporter=dot"],{cwd:t,env:{...process.env},stdio:["ignore","pipe","pipe"]});let a="";i.stderr.on("data",(r)=>{a+=r.toString()});i.on("error",(r)=>{n({requested:!0,executed:!1,ok:!1,summary:`Failed to start smoke tests: ${r.message}`})});i.on("close",(r)=>{n({requested:!0,executed:!0,ok:r===0,summary:r===0?"tests/smoke passed":a.trim()||`vitest exited with code ${r}`})})})}
@@ -1 +1 @@
1
- import*as q from"node:fs";import*as b from"node:path";import{fileURLToPath as x}from"node:url";const y=b.dirname(x(import.meta.url));let j=b.resolve(y,"..");if(!q.existsSync(b.join(j,"package.json")))j=b.resolve(j,"..");const z=b.join(j,"package.json");export const PKG_VERSION=(()=>{try{return JSON.parse(q.readFileSync(z,"utf-8")).version}catch{return"0.0.0"}})();
1
+ import*as e from"node:fs";import*as r from"node:path";import{fileURLToPath as t}from"node:url";const a=r.dirname(t(import.meta.url));let o=r.resolve(a,"..");if(!e.existsSync(r.join(o,"package.json")))o=r.resolve(o,"..");const n=r.join(o,"package.json");export const PKG_VERSION=(()=>{try{return JSON.parse(e.readFileSync(n,"utf-8")).version}catch{return"0.0.0"}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "publishport-opencli",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "provenance": false