@zenalexa/unicli 0.215.1 → 0.216.2

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 (407) hide show
  1. package/AGENTS.md +15 -15
  2. package/README.md +233 -389
  3. package/README.zh-CN.md +235 -362
  4. package/dist/adapters/1688/assets.d.ts +2 -0
  5. package/dist/adapters/1688/assets.d.ts.map +1 -0
  6. package/dist/adapters/1688/assets.js +102 -0
  7. package/dist/adapters/1688/assets.js.map +1 -0
  8. package/dist/adapters/51job/jobs.d.ts +2 -0
  9. package/dist/adapters/51job/jobs.d.ts.map +1 -0
  10. package/dist/adapters/51job/jobs.js +292 -0
  11. package/dist/adapters/51job/jobs.js.map +1 -0
  12. package/dist/adapters/_shared/browser-tools.d.ts +10 -0
  13. package/dist/adapters/_shared/browser-tools.d.ts.map +1 -0
  14. package/dist/adapters/_shared/browser-tools.js +42 -0
  15. package/dist/adapters/_shared/browser-tools.js.map +1 -0
  16. package/dist/adapters/antigravity/extra.d.ts +2 -0
  17. package/dist/adapters/antigravity/extra.d.ts.map +1 -0
  18. package/dist/adapters/antigravity/extra.js +52 -0
  19. package/dist/adapters/antigravity/extra.js.map +1 -0
  20. package/dist/adapters/baidu-scholar/search.d.ts +2 -0
  21. package/dist/adapters/baidu-scholar/search.d.ts.map +1 -0
  22. package/dist/adapters/baidu-scholar/search.js +34 -0
  23. package/dist/adapters/baidu-scholar/search.js.map +1 -0
  24. package/dist/adapters/bilibili/compat.d.ts +2 -0
  25. package/dist/adapters/bilibili/compat.d.ts.map +1 -0
  26. package/dist/adapters/bilibili/compat.js +114 -0
  27. package/dist/adapters/bilibili/compat.js.map +1 -0
  28. package/dist/adapters/chatgpt/image.d.ts +2 -0
  29. package/dist/adapters/chatgpt/image.d.ts.map +1 -0
  30. package/dist/adapters/chatgpt/image.js +81 -0
  31. package/dist/adapters/chatgpt/image.js.map +1 -0
  32. package/dist/adapters/chatgpt-app/chatgpt-app.d.ts +2 -0
  33. package/dist/adapters/chatgpt-app/chatgpt-app.d.ts.map +1 -0
  34. package/dist/adapters/chatgpt-app/chatgpt-app.js +9 -0
  35. package/dist/adapters/chatgpt-app/chatgpt-app.js.map +1 -0
  36. package/dist/adapters/chatwise/extra.d.ts +2 -0
  37. package/dist/adapters/chatwise/extra.d.ts.map +1 -0
  38. package/dist/adapters/chatwise/extra.js +35 -0
  39. package/dist/adapters/chatwise/extra.js.map +1 -0
  40. package/dist/adapters/codex/extra.d.ts +2 -0
  41. package/dist/adapters/codex/extra.d.ts.map +1 -0
  42. package/dist/adapters/codex/extra.js +35 -0
  43. package/dist/adapters/codex/extra.js.map +1 -0
  44. package/dist/adapters/deepseek/web.d.ts +2 -0
  45. package/dist/adapters/deepseek/web.d.ts.map +1 -0
  46. package/dist/adapters/deepseek/web.js +187 -0
  47. package/dist/adapters/deepseek/web.js.map +1 -0
  48. package/dist/adapters/doubao/web.d.ts +2 -0
  49. package/dist/adapters/doubao/web.d.ts.map +1 -0
  50. package/dist/adapters/doubao/web.js +138 -0
  51. package/dist/adapters/doubao/web.js.map +1 -0
  52. package/dist/adapters/eastmoney/market-data.d.ts +2 -0
  53. package/dist/adapters/eastmoney/market-data.d.ts.map +1 -0
  54. package/dist/adapters/eastmoney/market-data.js +753 -0
  55. package/dist/adapters/eastmoney/market-data.js.map +1 -0
  56. package/dist/adapters/gitee/user.d.ts +2 -0
  57. package/dist/adapters/gitee/user.d.ts.map +1 -0
  58. package/dist/adapters/gitee/user.js +54 -0
  59. package/dist/adapters/gitee/user.js.map +1 -0
  60. package/dist/adapters/google-scholar/cite.d.ts +2 -0
  61. package/dist/adapters/google-scholar/cite.d.ts.map +1 -0
  62. package/dist/adapters/google-scholar/cite.js +82 -0
  63. package/dist/adapters/google-scholar/cite.js.map +1 -0
  64. package/dist/adapters/google-scholar/profile.d.ts +2 -0
  65. package/dist/adapters/google-scholar/profile.d.ts.map +1 -0
  66. package/dist/adapters/google-scholar/profile.js +80 -0
  67. package/dist/adapters/google-scholar/profile.js.map +1 -0
  68. package/dist/adapters/google-scholar/search.d.ts +2 -0
  69. package/dist/adapters/google-scholar/search.d.ts.map +1 -0
  70. package/dist/adapters/google-scholar/search.js +54 -0
  71. package/dist/adapters/google-scholar/search.js.map +1 -0
  72. package/dist/adapters/gov-law/laws.d.ts +2 -0
  73. package/dist/adapters/gov-law/laws.d.ts.map +1 -0
  74. package/dist/adapters/gov-law/laws.js +58 -0
  75. package/dist/adapters/gov-law/laws.js.map +1 -0
  76. package/dist/adapters/gov-policy/policy.d.ts +2 -0
  77. package/dist/adapters/gov-policy/policy.d.ts.map +1 -0
  78. package/dist/adapters/gov-policy/policy.js +58 -0
  79. package/dist/adapters/gov-policy/policy.js.map +1 -0
  80. package/dist/adapters/jd/commerce.d.ts +2 -0
  81. package/dist/adapters/jd/commerce.d.ts.map +1 -0
  82. package/dist/adapters/jd/commerce.js +133 -0
  83. package/dist/adapters/jd/commerce.js.map +1 -0
  84. package/dist/adapters/jianyu/detail.d.ts +2 -0
  85. package/dist/adapters/jianyu/detail.d.ts.map +1 -0
  86. package/dist/adapters/jianyu/detail.js +27 -0
  87. package/dist/adapters/jianyu/detail.js.map +1 -0
  88. package/dist/adapters/jimeng/workspace.d.ts +2 -0
  89. package/dist/adapters/jimeng/workspace.d.ts.map +1 -0
  90. package/dist/adapters/jimeng/workspace.js +49 -0
  91. package/dist/adapters/jimeng/workspace.js.map +1 -0
  92. package/dist/adapters/ke/rent-transaction.d.ts +2 -0
  93. package/dist/adapters/ke/rent-transaction.d.ts.map +1 -0
  94. package/dist/adapters/ke/rent-transaction.js +63 -0
  95. package/dist/adapters/ke/rent-transaction.js.map +1 -0
  96. package/dist/adapters/linux-do/search.d.ts +2 -0
  97. package/dist/adapters/linux-do/search.d.ts.map +1 -0
  98. package/dist/adapters/linux-do/search.js +75 -0
  99. package/dist/adapters/linux-do/search.js.map +1 -0
  100. package/dist/adapters/linux-do/topic-content.d.ts +2 -0
  101. package/dist/adapters/linux-do/topic-content.d.ts.map +1 -0
  102. package/dist/adapters/linux-do/topic-content.js +32 -0
  103. package/dist/adapters/linux-do/topic-content.js.map +1 -0
  104. package/dist/adapters/maimai/talents.d.ts +2 -0
  105. package/dist/adapters/maimai/talents.d.ts.map +1 -0
  106. package/dist/adapters/maimai/talents.js +64 -0
  107. package/dist/adapters/maimai/talents.js.map +1 -0
  108. package/dist/adapters/mubu/docs.d.ts +2 -0
  109. package/dist/adapters/mubu/docs.d.ts.map +1 -0
  110. package/dist/adapters/mubu/docs.js +96 -0
  111. package/dist/adapters/mubu/docs.js.map +1 -0
  112. package/dist/adapters/nowcoder/nowcoder.d.ts +2 -0
  113. package/dist/adapters/nowcoder/nowcoder.d.ts.map +1 -0
  114. package/dist/adapters/nowcoder/nowcoder.js +480 -0
  115. package/dist/adapters/nowcoder/nowcoder.js.map +1 -0
  116. package/dist/adapters/powerchina/search.d.ts +2 -0
  117. package/dist/adapters/powerchina/search.d.ts.map +1 -0
  118. package/dist/adapters/powerchina/search.js +41 -0
  119. package/dist/adapters/powerchina/search.js.map +1 -0
  120. package/dist/adapters/quark/actions.d.ts +2 -0
  121. package/dist/adapters/quark/actions.d.ts.map +1 -0
  122. package/dist/adapters/quark/actions.js +151 -0
  123. package/dist/adapters/quark/actions.js.map +1 -0
  124. package/dist/adapters/reddit/browser-utils.d.ts +7 -0
  125. package/dist/adapters/reddit/browser-utils.d.ts.map +1 -0
  126. package/dist/adapters/reddit/browser-utils.js +68 -0
  127. package/dist/adapters/reddit/browser-utils.js.map +1 -0
  128. package/dist/adapters/reddit/listings.d.ts +2 -0
  129. package/dist/adapters/reddit/listings.d.ts.map +1 -0
  130. package/dist/adapters/reddit/listings.js +193 -0
  131. package/dist/adapters/reddit/listings.js.map +1 -0
  132. package/dist/adapters/reddit/search.d.ts +2 -0
  133. package/dist/adapters/reddit/search.d.ts.map +1 -0
  134. package/dist/adapters/reddit/search.js +66 -0
  135. package/dist/adapters/reddit/search.js.map +1 -0
  136. package/dist/adapters/spotify/api.d.ts +2 -0
  137. package/dist/adapters/spotify/api.d.ts.map +1 -0
  138. package/dist/adapters/spotify/api.js +252 -0
  139. package/dist/adapters/spotify/api.js.map +1 -0
  140. package/dist/adapters/taobao/commerce.d.ts +2 -0
  141. package/dist/adapters/taobao/commerce.d.ts.map +1 -0
  142. package/dist/adapters/taobao/commerce.js +130 -0
  143. package/dist/adapters/taobao/commerce.js.map +1 -0
  144. package/dist/adapters/tdx/hot-rank.d.ts +2 -0
  145. package/dist/adapters/tdx/hot-rank.d.ts.map +1 -0
  146. package/dist/adapters/tdx/hot-rank.js +34 -0
  147. package/dist/adapters/tdx/hot-rank.js.map +1 -0
  148. package/dist/adapters/ths/hot-rank.d.ts +2 -0
  149. package/dist/adapters/ths/hot-rank.d.ts.map +1 -0
  150. package/dist/adapters/ths/hot-rank.js +34 -0
  151. package/dist/adapters/ths/hot-rank.js.map +1 -0
  152. package/dist/adapters/toutiao/articles.d.ts +2 -0
  153. package/dist/adapters/toutiao/articles.d.ts.map +1 -0
  154. package/dist/adapters/toutiao/articles.js +41 -0
  155. package/dist/adapters/toutiao/articles.js.map +1 -0
  156. package/dist/adapters/twitter/lists-extra.d.ts +2 -0
  157. package/dist/adapters/twitter/lists-extra.d.ts.map +1 -0
  158. package/dist/adapters/twitter/lists-extra.js +125 -0
  159. package/dist/adapters/twitter/lists-extra.js.map +1 -0
  160. package/dist/adapters/uiverse/components.d.ts +2 -0
  161. package/dist/adapters/uiverse/components.d.ts.map +1 -0
  162. package/dist/adapters/uiverse/components.js +138 -0
  163. package/dist/adapters/uiverse/components.js.map +1 -0
  164. package/dist/adapters/wanfang/search.d.ts +2 -0
  165. package/dist/adapters/wanfang/search.d.ts.map +1 -0
  166. package/dist/adapters/wanfang/search.js +34 -0
  167. package/dist/adapters/wanfang/search.js.map +1 -0
  168. package/dist/adapters/weixin/drafts.d.ts +2 -0
  169. package/dist/adapters/weixin/drafts.d.ts.map +1 -0
  170. package/dist/adapters/weixin/drafts.js +69 -0
  171. package/dist/adapters/weixin/drafts.js.map +1 -0
  172. package/dist/adapters/weread/ai-outline.d.ts +2 -0
  173. package/dist/adapters/weread/ai-outline.d.ts.map +1 -0
  174. package/dist/adapters/weread/ai-outline.js +28 -0
  175. package/dist/adapters/weread/ai-outline.js.map +1 -0
  176. package/dist/adapters/xiaoyuzhou/media.d.ts +2 -0
  177. package/dist/adapters/xiaoyuzhou/media.d.ts.map +1 -0
  178. package/dist/adapters/xiaoyuzhou/media.js +105 -0
  179. package/dist/adapters/xiaoyuzhou/media.js.map +1 -0
  180. package/dist/adapters/xueqiu/extra.d.ts +2 -0
  181. package/dist/adapters/xueqiu/extra.d.ts.map +1 -0
  182. package/dist/adapters/xueqiu/extra.js +74 -0
  183. package/dist/adapters/xueqiu/extra.js.map +1 -0
  184. package/dist/adapters/youtube/personal.d.ts +2 -0
  185. package/dist/adapters/youtube/personal.d.ts.map +1 -0
  186. package/dist/adapters/youtube/personal.js +183 -0
  187. package/dist/adapters/youtube/personal.js.map +1 -0
  188. package/dist/adapters/zhihu/actions.d.ts +2 -0
  189. package/dist/adapters/zhihu/actions.d.ts.map +1 -0
  190. package/dist/adapters/zhihu/actions.js +110 -0
  191. package/dist/adapters/zhihu/actions.js.map +1 -0
  192. package/dist/browser/adapter-authoring.d.ts.map +1 -1
  193. package/dist/browser/adapter-authoring.js +3 -3
  194. package/dist/browser/adapter-authoring.js.map +1 -1
  195. package/dist/browser/bridge.d.ts.map +1 -1
  196. package/dist/browser/bridge.js +2 -3
  197. package/dist/browser/bridge.js.map +1 -1
  198. package/dist/browser/daemon-client.d.ts.map +1 -1
  199. package/dist/browser/daemon-client.js +17 -5
  200. package/dist/browser/daemon-client.js.map +1 -1
  201. package/dist/browser/network-cache.js +2 -2
  202. package/dist/browser/network-cache.js.map +1 -1
  203. package/dist/browser/site-memory.d.ts.map +1 -1
  204. package/dist/browser/site-memory.js +11 -8
  205. package/dist/browser/site-memory.js.map +1 -1
  206. package/dist/browser/target-errors.d.ts +2 -2
  207. package/dist/browser/target-errors.js +2 -2
  208. package/dist/browser/verify-fixture.d.ts.map +1 -1
  209. package/dist/browser/verify-fixture.js +2 -2
  210. package/dist/browser/verify-fixture.js.map +1 -1
  211. package/dist/cli.d.ts.map +1 -1
  212. package/dist/cli.js +9 -4
  213. package/dist/cli.js.map +1 -1
  214. package/dist/commands/agents.d.ts.map +1 -1
  215. package/dist/commands/agents.js +5 -2
  216. package/dist/commands/agents.js.map +1 -1
  217. package/dist/commands/auth.d.ts.map +1 -1
  218. package/dist/commands/auth.js +8 -2
  219. package/dist/commands/auth.js.map +1 -1
  220. package/dist/commands/browser-operator-runtime.d.ts.map +1 -1
  221. package/dist/commands/browser-operator-runtime.js +2 -2
  222. package/dist/commands/browser-operator-runtime.js.map +1 -1
  223. package/dist/commands/browser-operator.d.ts.map +1 -1
  224. package/dist/commands/browser-operator.js +2 -2
  225. package/dist/commands/browser-operator.js.map +1 -1
  226. package/dist/commands/describe.d.ts +2 -2
  227. package/dist/commands/describe.d.ts.map +1 -1
  228. package/dist/commands/describe.js +14 -3
  229. package/dist/commands/describe.js.map +1 -1
  230. package/dist/commands/dispatch.d.ts.map +1 -1
  231. package/dist/commands/dispatch.js +7 -6
  232. package/dist/commands/dispatch.js.map +1 -1
  233. package/dist/commands/explore.js +2 -2
  234. package/dist/commands/explore.js.map +1 -1
  235. package/dist/commands/generate.js +3 -3
  236. package/dist/commands/generate.js.map +1 -1
  237. package/dist/commands/health.d.ts.map +1 -1
  238. package/dist/commands/health.js +4 -10
  239. package/dist/commands/health.js.map +1 -1
  240. package/dist/commands/migrate.d.ts +9 -9
  241. package/dist/commands/migrate.d.ts.map +1 -1
  242. package/dist/commands/migrate.js +22 -22
  243. package/dist/commands/migrate.js.map +1 -1
  244. package/dist/commands/repair.d.ts.map +1 -1
  245. package/dist/commands/repair.js +9 -4
  246. package/dist/commands/repair.js.map +1 -1
  247. package/dist/commands/search.d.ts +3 -3
  248. package/dist/commands/search.js +4 -4
  249. package/dist/commands/skills.d.ts +3 -0
  250. package/dist/commands/skills.d.ts.map +1 -1
  251. package/dist/commands/skills.js +8 -4
  252. package/dist/commands/skills.js.map +1 -1
  253. package/dist/commands/synthesize.js +2 -2
  254. package/dist/commands/synthesize.js.map +1 -1
  255. package/dist/discovery/aliases.d.ts.map +1 -1
  256. package/dist/discovery/aliases.js +69 -0
  257. package/dist/discovery/aliases.js.map +1 -1
  258. package/dist/discovery/loader.d.ts.map +1 -1
  259. package/dist/discovery/loader.js +130 -0
  260. package/dist/discovery/loader.js.map +1 -1
  261. package/dist/engine/kernel/execute.d.ts.map +1 -1
  262. package/dist/engine/kernel/execute.js +27 -4
  263. package/dist/engine/kernel/execute.js.map +1 -1
  264. package/dist/engine/user-home.d.ts +9 -0
  265. package/dist/engine/user-home.d.ts.map +1 -0
  266. package/dist/engine/user-home.js +12 -0
  267. package/dist/engine/user-home.js.map +1 -0
  268. package/dist/fast-path.d.ts +14 -0
  269. package/dist/fast-path.d.ts.map +1 -0
  270. package/dist/fast-path.js +565 -0
  271. package/dist/fast-path.js.map +1 -0
  272. package/dist/hub/index.d.ts +1 -1
  273. package/dist/hub/index.d.ts.map +1 -1
  274. package/dist/hub/index.js +28 -17
  275. package/dist/hub/index.js.map +1 -1
  276. package/dist/main.js +6 -3
  277. package/dist/main.js.map +1 -1
  278. package/dist/manifest-compact.txt +11 -11
  279. package/dist/manifest-search.json +1 -1
  280. package/dist/manifest.json +27600 -1016
  281. package/dist/mcp/tools.js +1 -1
  282. package/dist/mcp/tools.js.map +1 -1
  283. package/dist/output/error-map.d.ts.map +1 -1
  284. package/dist/output/error-map.js +16 -5
  285. package/dist/output/error-map.js.map +1 -1
  286. package/dist/protocol/acp.js +1 -1
  287. package/dist/protocol/acp.js.map +1 -1
  288. package/dist/registry.d.ts +3 -0
  289. package/dist/registry.d.ts.map +1 -1
  290. package/dist/registry.js +34 -1
  291. package/dist/registry.js.map +1 -1
  292. package/dist/runtime/usage-ledger.d.ts +6 -7
  293. package/dist/runtime/usage-ledger.d.ts.map +1 -1
  294. package/dist/runtime/usage-ledger.js +6 -7
  295. package/dist/runtime/usage-ledger.js.map +1 -1
  296. package/dist/types.d.ts +2 -0
  297. package/dist/types.d.ts.map +1 -1
  298. package/dist/types.js.map +1 -1
  299. package/package.json +12 -6
  300. package/src/adapters/1688/assets.ts +114 -0
  301. package/src/adapters/51job/jobs.ts +327 -0
  302. package/src/adapters/_shared/browser-tools.ts +59 -0
  303. package/src/adapters/antigravity/extra.ts +53 -0
  304. package/src/adapters/baidu-scholar/search.ts +38 -0
  305. package/src/adapters/bilibili/compat.ts +132 -0
  306. package/src/adapters/binance/asks.yaml +41 -0
  307. package/src/adapters/binance/depth.yaml +41 -0
  308. package/src/adapters/binance/gainers.yaml +42 -0
  309. package/src/adapters/binance/hot.yaml +1 -1
  310. package/src/adapters/binance/kline.yaml +1 -1
  311. package/src/adapters/binance/klines.yaml +46 -0
  312. package/src/adapters/binance/losers.yaml +42 -0
  313. package/src/adapters/binance/pairs.yaml +38 -0
  314. package/src/adapters/binance/price.yaml +32 -0
  315. package/src/adapters/binance/prices.yaml +30 -0
  316. package/src/adapters/binance/ticker.yaml +2 -2
  317. package/src/adapters/binance/top.yaml +46 -0
  318. package/src/adapters/binance/trades.yaml +42 -0
  319. package/src/adapters/chatgpt/image.ts +84 -0
  320. package/src/adapters/chatgpt-app/chatgpt-app.ts +11 -0
  321. package/src/adapters/chatwise/extra.ts +36 -0
  322. package/src/adapters/codex/extra.ts +36 -0
  323. package/src/adapters/deepseek/web.ts +203 -0
  324. package/src/adapters/doubao/web.ts +154 -0
  325. package/src/adapters/eastmoney/market-data.ts +829 -0
  326. package/src/adapters/excel/insert-image.yaml +80 -0
  327. package/src/adapters/excel/insert-link.yaml +90 -0
  328. package/src/adapters/excel/list.yaml +63 -0
  329. package/src/adapters/excel/read.yaml +74 -0
  330. package/src/adapters/excel/set-cell.yaml +77 -0
  331. package/src/adapters/excel/set-font.yaml +87 -0
  332. package/src/adapters/excel/status.yaml +29 -0
  333. package/src/adapters/gh/search-repos.yaml +62 -0
  334. package/src/adapters/gitee/user.ts +59 -0
  335. package/src/adapters/google-scholar/cite.ts +95 -0
  336. package/src/adapters/google-scholar/profile.ts +91 -0
  337. package/src/adapters/google-scholar/search.ts +58 -0
  338. package/src/adapters/gov-law/laws.ts +61 -0
  339. package/src/adapters/gov-policy/policy.ts +61 -0
  340. package/src/adapters/imessage/contact.yaml +7 -2
  341. package/src/adapters/imessage/recent.yaml +7 -2
  342. package/src/adapters/imessage/search.yaml +7 -2
  343. package/src/adapters/jd/commerce.ts +142 -0
  344. package/src/adapters/jianyu/detail.ts +28 -0
  345. package/src/adapters/jimeng/workspace.ts +53 -0
  346. package/src/adapters/ke/rent-transaction.ts +70 -0
  347. package/src/adapters/linux-do/search.ts +92 -0
  348. package/src/adapters/linux-do/topic-content.ts +45 -0
  349. package/src/adapters/maimai/talents.ts +65 -0
  350. package/src/adapters/mubu/docs.ts +107 -0
  351. package/src/adapters/nowcoder/nowcoder.ts +570 -0
  352. package/src/adapters/powerchina/search.ts +45 -0
  353. package/src/adapters/powerpoint/add-slide.yaml +93 -0
  354. package/src/adapters/powerpoint/insert-image.yaml +71 -0
  355. package/src/adapters/powerpoint/insert-link.yaml +94 -0
  356. package/src/adapters/powerpoint/list.yaml +58 -0
  357. package/src/adapters/powerpoint/set-font.yaml +101 -0
  358. package/src/adapters/powerpoint/slides.yaml +73 -0
  359. package/src/adapters/powerpoint/status.yaml +29 -0
  360. package/src/adapters/quark/actions.ts +169 -0
  361. package/src/adapters/reddit/browser-utils.ts +93 -0
  362. package/src/adapters/reddit/listings.ts +223 -0
  363. package/src/adapters/reddit/search.ts +74 -0
  364. package/src/adapters/spotify/api.ts +292 -0
  365. package/src/adapters/taobao/commerce.ts +134 -0
  366. package/src/adapters/tdx/hot-rank.ts +35 -0
  367. package/src/adapters/ths/hot-rank.ts +35 -0
  368. package/src/adapters/toutiao/articles.ts +45 -0
  369. package/src/adapters/twitter/lists-extra.ts +139 -0
  370. package/src/adapters/uiverse/components.ts +154 -0
  371. package/src/adapters/vercel/list.yaml +2 -1
  372. package/src/adapters/wanfang/search.ts +38 -0
  373. package/src/adapters/weixin/drafts.ts +74 -0
  374. package/src/adapters/weread/ai-outline.ts +32 -0
  375. package/src/adapters/word/insert-image.yaml +73 -0
  376. package/src/adapters/word/insert-link.yaml +82 -0
  377. package/src/adapters/word/insert-text.yaml +72 -0
  378. package/src/adapters/word/list.yaml +63 -0
  379. package/src/adapters/word/read.yaml +63 -0
  380. package/src/adapters/word/set-font.yaml +97 -0
  381. package/src/adapters/word/status.yaml +29 -0
  382. package/src/adapters/xiaoyuzhou/media.ts +139 -0
  383. package/src/adapters/xueqiu/extra.ts +78 -0
  384. package/src/adapters/youtube/personal.ts +215 -0
  385. package/src/adapters/zhihu/actions.ts +111 -0
  386. package/src/hub/external-clis-harness.yaml +211 -0
  387. package/src/hub/index.ts +29 -25
  388. package/src/adapters/linux-do/search.yaml +0 -44
  389. package/src/adapters/meituan/hot.yaml +0 -34
  390. package/src/adapters/reddit/frontpage.test.ts +0 -15
  391. package/src/adapters/reddit/frontpage.yaml +0 -41
  392. package/src/adapters/reddit/hot.test.ts +0 -15
  393. package/src/adapters/reddit/hot.yaml +0 -41
  394. package/src/adapters/reddit/new.test.ts +0 -15
  395. package/src/adapters/reddit/new.yaml +0 -42
  396. package/src/adapters/reddit/popular.test.ts +0 -15
  397. package/src/adapters/reddit/popular.yaml +0 -41
  398. package/src/adapters/reddit/rising.test.ts +0 -15
  399. package/src/adapters/reddit/rising.yaml +0 -41
  400. package/src/adapters/reddit/search.test.ts +0 -15
  401. package/src/adapters/reddit/search.yaml +0 -52
  402. package/src/adapters/reddit/subreddit.test.ts +0 -15
  403. package/src/adapters/reddit/subreddit.yaml +0 -50
  404. package/src/adapters/reddit/top.test.ts +0 -15
  405. package/src/adapters/reddit/top.yaml +0 -48
  406. package/src/adapters/reddit/trending.test.ts +0 -15
  407. package/src/adapters/reddit/trending.yaml +0 -33
@@ -0,0 +1,32 @@
1
+ import { cli, Strategy } from "../../registry.js";
2
+ import type { IPage } from "../../types.js";
3
+ import { str, visibleText } from "../_shared/browser-tools.js";
4
+
5
+ cli({
6
+ site: "weread",
7
+ name: "ai-outline",
8
+ description: "Extract WeRead AI outline or visible book outline",
9
+ domain: "weread.qq.com",
10
+ strategy: Strategy.COOKIE,
11
+ browser: true,
12
+ args: [{ name: "bookId", type: "str", required: true, positional: true }],
13
+ columns: ["bookId", "outline", "url"],
14
+ func: async (page, kwargs) => {
15
+ const p = page as IPage;
16
+ const bookId = str(kwargs.bookId);
17
+ await p.goto(
18
+ `https://weread.qq.com/web/reader/${encodeURIComponent(bookId)}`,
19
+ {
20
+ settleMs: 2500,
21
+ },
22
+ );
23
+ await p.evaluate(`(() => {
24
+ const candidates = [...document.querySelectorAll('button, a, span')];
25
+ const node = candidates.find((el) => /AI|大纲|目录|总结/.test(el.textContent || ''));
26
+ if (node) node.click();
27
+ })()`);
28
+ await p.wait(1);
29
+ const text = await visibleText(p);
30
+ return [{ bookId, outline: text.slice(0, 8000), url: await p.url() }];
31
+ },
32
+ });
@@ -0,0 +1,73 @@
1
+ site: word
2
+ name: insert-image
3
+ description: Insert a local image into the active Microsoft Word document
4
+ type: desktop
5
+ strategy: public
6
+ binary: osascript
7
+ detect: "test $(uname) = Darwin"
8
+
9
+ args:
10
+ path:
11
+ type: str
12
+ required: true
13
+ positional: true
14
+ description: Local image path to embed
15
+
16
+ pipeline:
17
+ - exec:
18
+ command: osascript
19
+ args:
20
+ - "-e"
21
+ - |
22
+ on replace_text(theText, searchString, replacementString)
23
+ set AppleScript's text item delimiters to searchString
24
+ set parts to text items of (theText as text)
25
+ set AppleScript's text item delimiters to replacementString
26
+ set outText to parts as text
27
+ set AppleScript's text item delimiters to ""
28
+ return outText
29
+ end replace_text
30
+
31
+ on json_string(valueText)
32
+ set s to valueText as text
33
+ set s to my replace_text(s, "\\", "\\\\")
34
+ set s to my replace_text(s, "\"", "\\\"")
35
+ set s to my replace_text(s, return, "\\n")
36
+ set s to my replace_text(s, linefeed, "\\n")
37
+ set s to my replace_text(s, tab, "\\t")
38
+ return "\"" & s & "\""
39
+ end json_string
40
+
41
+ set imagePath to system attribute "UNICLI_IMAGE_PATH"
42
+
43
+ try
44
+ do shell script "test -f " & quoted form of imagePath
45
+ with timeout of 10 seconds
46
+ tell application "Microsoft Word"
47
+ activate
48
+ if (count documents) is 0 then make new document
49
+ set d to active document
50
+ set docRange to text object of d
51
+ set endPos to (end of content of docRange) - 1
52
+ if endPos < 0 then set endPos to 0
53
+ set insertionRange to create range d start endPos end endPos
54
+ make new inline picture at insertionRange with properties {file name:imagePath, link to file:false, save with document:true}
55
+ return "[{\"app\":\"Microsoft Word\",\"name\":" & my json_string(name of d as text) & ",\"path\":" & my json_string(imagePath) & ",\"embedded\":true,\"inline_pictures\":" & (count inline pictures of d) & "}]"
56
+ end tell
57
+ end timeout
58
+ on error errMsg number errNum
59
+ return "[{\"ok\":false,\"code\":\"office_automation_unavailable\",\"message\":" & my json_string(errMsg) & ",\"number\":" & errNum & "}]"
60
+ end try
61
+ env:
62
+ UNICLI_IMAGE_PATH: "${{ args.path }}"
63
+ parse: json
64
+ timeout: 15000
65
+
66
+ columns: [app, name, path, embedded, inline_pictures]
67
+
68
+ capabilities: ["subprocess.exec"]
69
+ minimum_capability: subprocess.exec
70
+ trust: user
71
+ confidentiality: private
72
+ quarantine: false
73
+ schema_version: v2
@@ -0,0 +1,82 @@
1
+ site: word
2
+ name: insert-link
3
+ description: Insert a native hyperlink field into the active Microsoft Word document
4
+ type: desktop
5
+ strategy: public
6
+ binary: osascript
7
+ detect: "test $(uname) = Darwin"
8
+
9
+ args:
10
+ url:
11
+ type: str
12
+ required: true
13
+ positional: true
14
+ description: Link URL or file URL to insert
15
+ text:
16
+ type: str
17
+ required: false
18
+ default: ""
19
+ description: Display text; defaults to the URL
20
+
21
+ pipeline:
22
+ - exec:
23
+ command: osascript
24
+ args:
25
+ - "-e"
26
+ - |
27
+ on replace_text(theText, searchString, replacementString)
28
+ set AppleScript's text item delimiters to searchString
29
+ set parts to text items of (theText as text)
30
+ set AppleScript's text item delimiters to replacementString
31
+ set outText to parts as text
32
+ set AppleScript's text item delimiters to ""
33
+ return outText
34
+ end replace_text
35
+
36
+ on json_string(valueText)
37
+ set s to valueText as text
38
+ set s to my replace_text(s, "\\", "\\\\")
39
+ set s to my replace_text(s, "\"", "\\\"")
40
+ set s to my replace_text(s, return, "\\n")
41
+ set s to my replace_text(s, linefeed, "\\n")
42
+ set s to my replace_text(s, tab, "\\t")
43
+ return "\"" & s & "\""
44
+ end json_string
45
+
46
+ set linkUrl to system attribute "UNICLI_URL"
47
+ set linkText to system attribute "UNICLI_TEXT"
48
+ if linkText is "" then set linkText to linkUrl
49
+
50
+ try
51
+ with timeout of 10 seconds
52
+ tell application "Microsoft Word"
53
+ activate
54
+ if (count documents) is 0 then make new document
55
+ set d to active document
56
+ set docRange to text object of d
57
+ set endPos to (end of content of docRange) - 1
58
+ if endPos < 0 then set endPos to 0
59
+ set insertionRange to create range d start endPos end endPos
60
+ set fieldCode to "HYPERLINK " & quote & linkUrl & quote
61
+ set linkField to create new field text range insertionRange field text fieldCode preserve formatting false
62
+ set content of result range of linkField to linkText
63
+ return "[{\"app\":\"Microsoft Word\",\"name\":" & my json_string(name of d as text) & ",\"url\":" & my json_string(linkUrl) & ",\"text\":" & my json_string(linkText) & "}]"
64
+ end tell
65
+ end timeout
66
+ on error errMsg number errNum
67
+ return "[{\"ok\":false,\"code\":\"office_automation_unavailable\",\"message\":" & my json_string(errMsg) & ",\"number\":" & errNum & "}]"
68
+ end try
69
+ env:
70
+ UNICLI_URL: "${{ args.url }}"
71
+ UNICLI_TEXT: "${{ args.text }}"
72
+ parse: json
73
+ timeout: 15000
74
+
75
+ columns: [app, name, url, text]
76
+
77
+ capabilities: ["subprocess.exec"]
78
+ minimum_capability: subprocess.exec
79
+ trust: user
80
+ confidentiality: private
81
+ quarantine: false
82
+ schema_version: v2
@@ -0,0 +1,72 @@
1
+ site: word
2
+ name: insert-text
3
+ description: Append text to the active Microsoft Word document, creating one if needed
4
+ type: desktop
5
+ strategy: public
6
+ binary: osascript
7
+ detect: "test $(uname) = Darwin"
8
+
9
+ args:
10
+ text:
11
+ type: str
12
+ required: true
13
+ positional: true
14
+ description: Text to append to the active document
15
+
16
+ pipeline:
17
+ - exec:
18
+ command: osascript
19
+ args:
20
+ - "-e"
21
+ - |
22
+ on replace_text(theText, searchString, replacementString)
23
+ set AppleScript's text item delimiters to searchString
24
+ set parts to text items of (theText as text)
25
+ set AppleScript's text item delimiters to replacementString
26
+ set outText to parts as text
27
+ set AppleScript's text item delimiters to ""
28
+ return outText
29
+ end replace_text
30
+
31
+ on json_string(valueText)
32
+ set s to valueText as text
33
+ set s to my replace_text(s, "\\", "\\\\")
34
+ set s to my replace_text(s, "\"", "\\\"")
35
+ set s to my replace_text(s, return, "\\n")
36
+ set s to my replace_text(s, linefeed, "\\n")
37
+ set s to my replace_text(s, tab, "\\t")
38
+ return "\"" & s & "\""
39
+ end json_string
40
+
41
+ set insertText to system attribute "UNICLI_TEXT"
42
+ try
43
+ with timeout of 20 seconds
44
+ tell application "Microsoft Word"
45
+ activate
46
+ if (count documents) is 0 then make new document
47
+ set d to active document
48
+ set docName to name of d as text
49
+ set docRange to text object of d
50
+ set endPos to (end of content of docRange) - 1
51
+ if endPos < 0 then set endPos to 0
52
+ set insertionRange to create range d start endPos end endPos
53
+ set content of insertionRange to insertText
54
+ return "[{\"app\":\"Microsoft Word\",\"name\":" & my json_string(docName) & ",\"inserted_chars\":" & (length of insertText) & "}]"
55
+ end tell
56
+ end timeout
57
+ on error errMsg number errNum
58
+ return "[{\"ok\":false,\"code\":\"office_automation_unavailable\",\"message\":" & my json_string(errMsg) & ",\"number\":" & errNum & "}]"
59
+ end try
60
+ env:
61
+ UNICLI_TEXT: "${{ args.text }}"
62
+ parse: json
63
+ timeout: 30000
64
+
65
+ columns: [app, name, inserted_chars]
66
+
67
+ capabilities: ["subprocess.exec"]
68
+ minimum_capability: subprocess.exec
69
+ trust: user
70
+ confidentiality: private
71
+ quarantine: false
72
+ schema_version: v2
@@ -0,0 +1,63 @@
1
+ site: word
2
+ name: list
3
+ description: List open Microsoft Word documents
4
+ type: desktop
5
+ strategy: public
6
+ binary: osascript
7
+ detect: "test $(uname) = Darwin"
8
+
9
+ pipeline:
10
+ - exec:
11
+ command: osascript
12
+ args:
13
+ - "-e"
14
+ - |
15
+ on replace_text(theText, searchString, replacementString)
16
+ set AppleScript's text item delimiters to searchString
17
+ set parts to text items of (theText as text)
18
+ set AppleScript's text item delimiters to replacementString
19
+ set outText to parts as text
20
+ set AppleScript's text item delimiters to ""
21
+ return outText
22
+ end replace_text
23
+
24
+ on json_string(valueText)
25
+ set s to valueText as text
26
+ set s to my replace_text(s, "\\", "\\\\")
27
+ set s to my replace_text(s, "\"", "\\\"")
28
+ set s to my replace_text(s, return, "\\n")
29
+ set s to my replace_text(s, linefeed, "\\n")
30
+ set s to my replace_text(s, tab, "\\t")
31
+ return "\"" & s & "\""
32
+ end json_string
33
+
34
+ on json_bool(valueBool)
35
+ if valueBool then return "true"
36
+ return "false"
37
+ end json_bool
38
+
39
+ if not application "Microsoft Word" is running then return "[]"
40
+
41
+ tell application "System Events"
42
+ tell process "Microsoft Word"
43
+ set windowCount to count windows
44
+ set outText to "["
45
+ repeat with i from 1 to windowCount
46
+ set docName to name of window i as text
47
+ if i > 1 then set outText to outText & ","
48
+ set outText to outText & "{\"index\":" & i & ",\"name\":" & my json_string(docName) & ",\"path\":\"\",\"saved\":" & my json_bool(false) & ",\"source\":\"window\"}"
49
+ end repeat
50
+ end tell
51
+ return outText & "]"
52
+ end tell
53
+ parse: json
54
+ timeout: 30000
55
+
56
+ columns: [index, name, path, saved, source]
57
+
58
+ capabilities: ["subprocess.exec"]
59
+ minimum_capability: subprocess.exec
60
+ trust: user
61
+ confidentiality: private
62
+ quarantine: false
63
+ schema_version: v2
@@ -0,0 +1,63 @@
1
+ site: word
2
+ name: read
3
+ description: Read text from the active Microsoft Word document
4
+ type: desktop
5
+ strategy: public
6
+ binary: osascript
7
+ detect: "test $(uname) = Darwin"
8
+
9
+ pipeline:
10
+ - exec:
11
+ command: osascript
12
+ args:
13
+ - "-e"
14
+ - |
15
+ on replace_text(theText, searchString, replacementString)
16
+ set AppleScript's text item delimiters to searchString
17
+ set parts to text items of (theText as text)
18
+ set AppleScript's text item delimiters to replacementString
19
+ set outText to parts as text
20
+ set AppleScript's text item delimiters to ""
21
+ return outText
22
+ end replace_text
23
+
24
+ on json_string(valueText)
25
+ set s to valueText as text
26
+ set s to my replace_text(s, "\\", "\\\\")
27
+ set s to my replace_text(s, "\"", "\\\"")
28
+ set s to my replace_text(s, return, "\\n")
29
+ set s to my replace_text(s, linefeed, "\\n")
30
+ set s to my replace_text(s, tab, "\\t")
31
+ return "\"" & s & "\""
32
+ end json_string
33
+
34
+ if not application "Microsoft Word" is running then return "[]"
35
+
36
+ try
37
+ with timeout of 10 seconds
38
+ tell application "Microsoft Word"
39
+ if (count documents) is 0 then return "[]"
40
+ set d to active document
41
+ set docName to name of d as text
42
+ try
43
+ set bodyText to content of text object of d as text
44
+ on error
45
+ set bodyText to ""
46
+ end try
47
+ return "[{\"name\":" & my json_string(docName) & ",\"text\":" & my json_string(bodyText) & "}]"
48
+ end tell
49
+ end timeout
50
+ on error errMsg number errNum
51
+ return "[{\"ok\":false,\"code\":\"office_automation_unavailable\",\"message\":" & my json_string(errMsg) & ",\"number\":" & errNum & "}]"
52
+ end try
53
+ parse: json
54
+ timeout: 30000
55
+
56
+ columns: [name, text]
57
+
58
+ capabilities: ["subprocess.exec"]
59
+ minimum_capability: subprocess.exec
60
+ trust: user
61
+ confidentiality: private
62
+ quarantine: false
63
+ schema_version: v2
@@ -0,0 +1,97 @@
1
+ site: word
2
+ name: set-font
3
+ description: Apply a font to the active Microsoft Word document or matching text
4
+ type: desktop
5
+ strategy: public
6
+ binary: osascript
7
+ detect: "test $(uname) = Darwin"
8
+
9
+ args:
10
+ font:
11
+ type: str
12
+ required: true
13
+ positional: true
14
+ description: Font family to apply
15
+ size:
16
+ type: str
17
+ required: false
18
+ default: ""
19
+ description: Optional font size in points
20
+ text:
21
+ type: str
22
+ required: false
23
+ default: ""
24
+ description: Optional text to match; defaults to the whole document
25
+
26
+ pipeline:
27
+ - exec:
28
+ command: osascript
29
+ args:
30
+ - "-e"
31
+ - |
32
+ on replace_text(theText, searchString, replacementString)
33
+ set AppleScript's text item delimiters to searchString
34
+ set parts to text items of (theText as text)
35
+ set AppleScript's text item delimiters to replacementString
36
+ set outText to parts as text
37
+ set AppleScript's text item delimiters to ""
38
+ return outText
39
+ end replace_text
40
+
41
+ on json_string(valueText)
42
+ set s to valueText as text
43
+ set s to my replace_text(s, "\\", "\\\\")
44
+ set s to my replace_text(s, "\"", "\\\"")
45
+ set s to my replace_text(s, return, "\\n")
46
+ set s to my replace_text(s, linefeed, "\\n")
47
+ set s to my replace_text(s, tab, "\\t")
48
+ return "\"" & s & "\""
49
+ end json_string
50
+
51
+ set fontName to system attribute "UNICLI_FONT"
52
+ set sizeText to system attribute "UNICLI_SIZE"
53
+ set targetText to system attribute "UNICLI_TEXT"
54
+
55
+ try
56
+ with timeout of 10 seconds
57
+ tell application "Microsoft Word"
58
+ if (count documents) is 0 then return "[]"
59
+ set d to active document
60
+ set targetRange to text object of d
61
+ if targetText is not "" then
62
+ set bodyText to content of targetRange as text
63
+ if bodyText does not contain targetText then error "Target text not found in active Word document"
64
+ set AppleScript's text item delimiters to targetText
65
+ set parts to text items of bodyText
66
+ set startPos to length of item 1 of parts
67
+ set endPos to startPos + (length of targetText)
68
+ set AppleScript's text item delimiters to ""
69
+ set targetRange to create range d start startPos end endPos
70
+ end if
71
+ set f to font object of targetRange
72
+ set name of f to fontName
73
+ try
74
+ set east asian name of f to fontName
75
+ end try
76
+ if sizeText is not "" then set font size of f to (sizeText as real)
77
+ return "[{\"app\":\"Microsoft Word\",\"name\":" & my json_string(name of d as text) & ",\"font\":" & my json_string(fontName) & ",\"size\":" & my json_string(sizeText) & ",\"target_chars\":" & (length of targetText) & "}]"
78
+ end tell
79
+ end timeout
80
+ on error errMsg number errNum
81
+ return "[{\"ok\":false,\"code\":\"office_automation_unavailable\",\"message\":" & my json_string(errMsg) & ",\"number\":" & errNum & "}]"
82
+ end try
83
+ env:
84
+ UNICLI_FONT: "${{ args.font }}"
85
+ UNICLI_SIZE: "${{ args.size }}"
86
+ UNICLI_TEXT: "${{ args.text }}"
87
+ parse: json
88
+ timeout: 15000
89
+
90
+ columns: [app, name, font, size, target_chars]
91
+
92
+ capabilities: ["subprocess.exec"]
93
+ minimum_capability: subprocess.exec
94
+ trust: user
95
+ confidentiality: private
96
+ quarantine: false
97
+ schema_version: v2
@@ -0,0 +1,29 @@
1
+ site: word
2
+ name: status
3
+ description: Check Microsoft Word running state without enumerating documents
4
+ type: desktop
5
+ strategy: public
6
+ binary: osascript
7
+ detect: "test $(uname) = Darwin"
8
+
9
+ pipeline:
10
+ - exec:
11
+ command: osascript
12
+ args:
13
+ - "-l"
14
+ - "JavaScript"
15
+ - "-e"
16
+ - |
17
+ var app = Application('Microsoft Word');
18
+ JSON.stringify([{ app: 'Microsoft Word', bundle_id: app.id(), running: app.running() }]);
19
+ parse: json
20
+ timeout: 10000
21
+
22
+ columns: [app, bundle_id, running]
23
+
24
+ capabilities: ["subprocess.exec"]
25
+ minimum_capability: subprocess.exec
26
+ trust: user
27
+ confidentiality: private
28
+ quarantine: false
29
+ schema_version: v2
@@ -0,0 +1,139 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { basename, join } from "node:path";
4
+ import { cli, Strategy } from "../../registry.js";
5
+ import { str } from "../_shared/browser-tools.js";
6
+
7
+ interface XiaoyuzhouCredentials {
8
+ access_token?: string;
9
+ device_id?: string;
10
+ }
11
+
12
+ interface XiaoyuzhouEpisode {
13
+ title?: string;
14
+ media?: {
15
+ source?: {
16
+ url?: string;
17
+ };
18
+ };
19
+ enclosure?: {
20
+ url?: string;
21
+ };
22
+ audio?: {
23
+ url?: string;
24
+ };
25
+ }
26
+
27
+ async function readCredentials(): Promise<XiaoyuzhouCredentials> {
28
+ if (process.env.XIAOYUZHOU_ACCESS_TOKEN) {
29
+ return {
30
+ access_token: process.env.XIAOYUZHOU_ACCESS_TOKEN,
31
+ device_id: process.env.XIAOYUZHOU_DEVICE_ID,
32
+ };
33
+ }
34
+ try {
35
+ const { readFile } = await import("node:fs/promises");
36
+ const text = await readFile(
37
+ join(homedir(), ".unicli", "xiaoyuzhou.json"),
38
+ "utf8",
39
+ );
40
+ return JSON.parse(text) as XiaoyuzhouCredentials;
41
+ } catch {
42
+ return {};
43
+ }
44
+ }
45
+
46
+ async function apiPost<T>(
47
+ path: string,
48
+ body: Record<string, unknown>,
49
+ ): Promise<T> {
50
+ const credentials = await readCredentials();
51
+ const headers: Record<string, string> = {
52
+ "content-type": "application/json",
53
+ "user-agent": "Mozilla/5.0 (compatible; Uni-CLI)",
54
+ };
55
+ if (credentials.access_token) {
56
+ headers.authorization = `Bearer ${credentials.access_token}`;
57
+ }
58
+ if (credentials.device_id) {
59
+ headers["x-jike-device-id"] = credentials.device_id;
60
+ }
61
+ const response = await fetch(`https://api.xiaoyuzhoufm.com${path}`, {
62
+ method: "POST",
63
+ headers,
64
+ body: JSON.stringify(body),
65
+ });
66
+ if (!response.ok) {
67
+ throw new Error(`xiaoyuzhou request failed: HTTP ${response.status}`);
68
+ }
69
+ return (await response.json()) as T;
70
+ }
71
+
72
+ async function episode(eid: string): Promise<XiaoyuzhouEpisode> {
73
+ const data = await apiPost<{ data?: XiaoyuzhouEpisode }>("/v1/episode/get", {
74
+ eid,
75
+ });
76
+ return data.data ?? {};
77
+ }
78
+
79
+ function audioUrl(item: XiaoyuzhouEpisode): string {
80
+ return (
81
+ item.media?.source?.url ?? item.enclosure?.url ?? item.audio?.url ?? ""
82
+ );
83
+ }
84
+
85
+ cli({
86
+ site: "xiaoyuzhou",
87
+ name: "download",
88
+ description: "Download Xiaoyuzhou episode audio",
89
+ domain: "xiaoyuzhou.fm",
90
+ strategy: Strategy.COOKIE,
91
+ args: [
92
+ { name: "eid", type: "str", required: true, positional: true },
93
+ { name: "output", type: "str", default: "./xiaoyuzhou" },
94
+ ],
95
+ columns: ["title", "path", "bytes"],
96
+ func: async (_page, kwargs) => {
97
+ const eid = str(kwargs.eid);
98
+ const item = await episode(eid);
99
+ const url = audioUrl(item);
100
+ if (!url) throw new Error("Episode audio URL not found");
101
+ const output = str(kwargs.output, "./xiaoyuzhou");
102
+ await mkdir(output, { recursive: true });
103
+ const response = await fetch(url);
104
+ const bytes = Buffer.from(await response.arrayBuffer());
105
+ const name = basename(new URL(url).pathname) || `${eid}.mp3`;
106
+ const path = join(output, name);
107
+ await writeFile(path, bytes);
108
+ return [{ title: item.title ?? "", path, bytes: bytes.length }];
109
+ },
110
+ });
111
+
112
+ cli({
113
+ site: "xiaoyuzhou",
114
+ name: "transcript",
115
+ description: "Download Xiaoyuzhou transcript JSON and extracted text",
116
+ domain: "xiaoyuzhou.fm",
117
+ strategy: Strategy.COOKIE,
118
+ args: [
119
+ { name: "eid", type: "str", required: true, positional: true },
120
+ { name: "output", type: "str", default: "./xiaoyuzhou-transcripts" },
121
+ ],
122
+ columns: ["eid", "path", "text"],
123
+ func: async (_page, kwargs) => {
124
+ const eid = str(kwargs.eid);
125
+ const output = str(kwargs.output, "./xiaoyuzhou-transcripts");
126
+ const data = await apiPost<Record<string, unknown>>(
127
+ "/v1/episode/transcript",
128
+ { eid },
129
+ );
130
+ await mkdir(output, { recursive: true });
131
+ const path = join(output, `${eid}.json`);
132
+ await writeFile(path, JSON.stringify(data, null, 2));
133
+ const text = JSON.stringify(data)
134
+ .replace(/[{}"\\[\\],:]/g, " ")
135
+ .replace(/\s+/g, " ")
136
+ .trim();
137
+ return [{ eid, path, text: text.slice(0, 8000) }];
138
+ },
139
+ });