@zenalexa/unicli 0.220.1 → 0.221.1

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 (586) hide show
  1. package/AGENTS.md +35 -13
  2. package/README.md +18 -16
  3. package/README.zh-CN.md +18 -16
  4. package/dist/adapters/acl-anthology/papers.d.ts +16 -0
  5. package/dist/adapters/acl-anthology/papers.d.ts.map +1 -0
  6. package/dist/adapters/acl-anthology/papers.js +135 -0
  7. package/dist/adapters/acl-anthology/papers.js.map +1 -0
  8. package/dist/adapters/arxiv/papers.js +2 -0
  9. package/dist/adapters/arxiv/papers.js.map +1 -1
  10. package/dist/adapters/baidu-scholar/search.js +5 -0
  11. package/dist/adapters/baidu-scholar/search.js.map +1 -1
  12. package/dist/adapters/bilibili/comments.js +66 -4
  13. package/dist/adapters/bilibili/comments.js.map +1 -1
  14. package/dist/adapters/bilibili/compat.js +2 -2
  15. package/dist/adapters/bilibili/compat.js.map +1 -1
  16. package/dist/adapters/bilibili/download.js +4 -4
  17. package/dist/adapters/bilibili/download.js.map +1 -1
  18. package/dist/adapters/bilibili/wbi.d.ts.map +1 -1
  19. package/dist/adapters/bilibili/wbi.js +3 -3
  20. package/dist/adapters/bilibili/wbi.js.map +1 -1
  21. package/dist/adapters/cipo/_shared.d.ts +21 -0
  22. package/dist/adapters/cipo/_shared.d.ts.map +1 -0
  23. package/dist/adapters/cipo/_shared.js +67 -0
  24. package/dist/adapters/cipo/_shared.js.map +1 -0
  25. package/dist/adapters/cipo/get.d.ts +19 -0
  26. package/dist/adapters/cipo/get.d.ts.map +1 -0
  27. package/dist/adapters/cipo/get.js +140 -0
  28. package/dist/adapters/cipo/get.js.map +1 -0
  29. package/dist/adapters/cipo/legal-status.d.ts +19 -0
  30. package/dist/adapters/cipo/legal-status.d.ts.map +1 -0
  31. package/dist/adapters/cipo/legal-status.js +111 -0
  32. package/dist/adapters/cipo/legal-status.js.map +1 -0
  33. package/dist/adapters/cipo/search.d.ts +20 -0
  34. package/dist/adapters/cipo/search.d.ts.map +1 -0
  35. package/dist/adapters/cipo/search.js +148 -0
  36. package/dist/adapters/cipo/search.js.map +1 -0
  37. package/dist/adapters/cnipa/_shared.d.ts +47 -0
  38. package/dist/adapters/cnipa/_shared.d.ts.map +1 -0
  39. package/dist/adapters/cnipa/_shared.js +97 -0
  40. package/dist/adapters/cnipa/_shared.js.map +1 -0
  41. package/dist/adapters/cnipa/get.d.ts +19 -0
  42. package/dist/adapters/cnipa/get.d.ts.map +1 -0
  43. package/dist/adapters/cnipa/get.js +149 -0
  44. package/dist/adapters/cnipa/get.js.map +1 -0
  45. package/dist/adapters/cnipa/legal-status.d.ts +19 -0
  46. package/dist/adapters/cnipa/legal-status.d.ts.map +1 -0
  47. package/dist/adapters/cnipa/legal-status.js +119 -0
  48. package/dist/adapters/cnipa/legal-status.js.map +1 -0
  49. package/dist/adapters/cnipa/search.d.ts +21 -0
  50. package/dist/adapters/cnipa/search.d.ts.map +1 -0
  51. package/dist/adapters/cnipa/search.js +170 -0
  52. package/dist/adapters/cnipa/search.js.map +1 -0
  53. package/dist/adapters/crossref/works.d.ts +42 -0
  54. package/dist/adapters/crossref/works.d.ts.map +1 -0
  55. package/dist/adapters/crossref/works.js +157 -0
  56. package/dist/adapters/crossref/works.js.map +1 -0
  57. package/dist/adapters/cvf/papers.d.ts +17 -0
  58. package/dist/adapters/cvf/papers.d.ts.map +1 -0
  59. package/dist/adapters/cvf/papers.js +124 -0
  60. package/dist/adapters/cvf/papers.js.map +1 -0
  61. package/dist/adapters/dblp/publications.js +4 -0
  62. package/dist/adapters/dblp/publications.js.map +1 -1
  63. package/dist/adapters/espacenet/_shared.d.ts +21 -0
  64. package/dist/adapters/espacenet/_shared.d.ts.map +1 -0
  65. package/dist/adapters/espacenet/_shared.js +67 -0
  66. package/dist/adapters/espacenet/_shared.js.map +1 -0
  67. package/dist/adapters/espacenet/family.d.ts +19 -0
  68. package/dist/adapters/espacenet/family.d.ts.map +1 -0
  69. package/dist/adapters/espacenet/family.js +118 -0
  70. package/dist/adapters/espacenet/family.js.map +1 -0
  71. package/dist/adapters/espacenet/get.d.ts +19 -0
  72. package/dist/adapters/espacenet/get.d.ts.map +1 -0
  73. package/dist/adapters/espacenet/get.js +130 -0
  74. package/dist/adapters/espacenet/get.js.map +1 -0
  75. package/dist/adapters/espacenet/legal-status.d.ts +19 -0
  76. package/dist/adapters/espacenet/legal-status.d.ts.map +1 -0
  77. package/dist/adapters/espacenet/legal-status.js +110 -0
  78. package/dist/adapters/espacenet/legal-status.js.map +1 -0
  79. package/dist/adapters/espacenet/search.d.ts +20 -0
  80. package/dist/adapters/espacenet/search.d.ts.map +1 -0
  81. package/dist/adapters/espacenet/search.js +165 -0
  82. package/dist/adapters/espacenet/search.js.map +1 -0
  83. package/dist/adapters/facebook/subtitles.d.ts +9 -0
  84. package/dist/adapters/facebook/subtitles.d.ts.map +1 -0
  85. package/dist/adapters/facebook/subtitles.js +42 -0
  86. package/dist/adapters/facebook/subtitles.js.map +1 -0
  87. package/dist/adapters/fips/_shared.d.ts +21 -0
  88. package/dist/adapters/fips/_shared.d.ts.map +1 -0
  89. package/dist/adapters/fips/_shared.js +77 -0
  90. package/dist/adapters/fips/_shared.js.map +1 -0
  91. package/dist/adapters/fips/get.d.ts +19 -0
  92. package/dist/adapters/fips/get.d.ts.map +1 -0
  93. package/dist/adapters/fips/get.js +139 -0
  94. package/dist/adapters/fips/get.js.map +1 -0
  95. package/dist/adapters/fips/search.d.ts +20 -0
  96. package/dist/adapters/fips/search.d.ts.map +1 -0
  97. package/dist/adapters/fips/search.js +148 -0
  98. package/dist/adapters/fips/search.js.map +1 -0
  99. package/dist/adapters/freepatentsonline-web/_shared.d.ts +72 -0
  100. package/dist/adapters/freepatentsonline-web/_shared.d.ts.map +1 -0
  101. package/dist/adapters/freepatentsonline-web/_shared.js +216 -0
  102. package/dist/adapters/freepatentsonline-web/_shared.js.map +1 -0
  103. package/dist/adapters/freepatentsonline-web/get.d.ts +21 -0
  104. package/dist/adapters/freepatentsonline-web/get.d.ts.map +1 -0
  105. package/dist/adapters/freepatentsonline-web/get.js +127 -0
  106. package/dist/adapters/freepatentsonline-web/get.js.map +1 -0
  107. package/dist/adapters/freepatentsonline-web/search.d.ts +22 -0
  108. package/dist/adapters/freepatentsonline-web/search.d.ts.map +1 -0
  109. package/dist/adapters/freepatentsonline-web/search.js +149 -0
  110. package/dist/adapters/freepatentsonline-web/search.js.map +1 -0
  111. package/dist/adapters/google-patents-web/_shared.d.ts +110 -0
  112. package/dist/adapters/google-patents-web/_shared.d.ts.map +1 -0
  113. package/dist/adapters/google-patents-web/_shared.js +164 -0
  114. package/dist/adapters/google-patents-web/_shared.js.map +1 -0
  115. package/dist/adapters/google-patents-web/get.d.ts +36 -0
  116. package/dist/adapters/google-patents-web/get.d.ts.map +1 -0
  117. package/dist/adapters/google-patents-web/get.js +187 -0
  118. package/dist/adapters/google-patents-web/get.js.map +1 -0
  119. package/dist/adapters/google-patents-web/search.d.ts +23 -0
  120. package/dist/adapters/google-patents-web/search.d.ts.map +1 -0
  121. package/dist/adapters/google-patents-web/search.js +169 -0
  122. package/dist/adapters/google-patents-web/search.js.map +1 -0
  123. package/dist/adapters/google-scholar/cite.js +1 -0
  124. package/dist/adapters/google-scholar/cite.js.map +1 -1
  125. package/dist/adapters/google-scholar/profile.js +5 -0
  126. package/dist/adapters/google-scholar/profile.js.map +1 -1
  127. package/dist/adapters/google-scholar/search.js +5 -0
  128. package/dist/adapters/google-scholar/search.js.map +1 -1
  129. package/dist/adapters/hf/paper.js +1 -0
  130. package/dist/adapters/hf/paper.js.map +1 -1
  131. package/dist/adapters/inpi-br/_shared.d.ts +21 -0
  132. package/dist/adapters/inpi-br/_shared.d.ts.map +1 -0
  133. package/dist/adapters/inpi-br/_shared.js +67 -0
  134. package/dist/adapters/inpi-br/_shared.js.map +1 -0
  135. package/dist/adapters/inpi-br/get.d.ts +19 -0
  136. package/dist/adapters/inpi-br/get.d.ts.map +1 -0
  137. package/dist/adapters/inpi-br/get.js +142 -0
  138. package/dist/adapters/inpi-br/get.js.map +1 -0
  139. package/dist/adapters/inpi-br/search.d.ts +20 -0
  140. package/dist/adapters/inpi-br/search.d.ts.map +1 -0
  141. package/dist/adapters/inpi-br/search.js +154 -0
  142. package/dist/adapters/inpi-br/search.js.map +1 -0
  143. package/dist/adapters/instagram/subtitles.d.ts +9 -0
  144. package/dist/adapters/instagram/subtitles.d.ts.map +1 -0
  145. package/dist/adapters/instagram/subtitles.js +42 -0
  146. package/dist/adapters/instagram/subtitles.js.map +1 -0
  147. package/dist/adapters/mastodon/statuses.d.ts +40 -0
  148. package/dist/adapters/mastodon/statuses.d.ts.map +1 -0
  149. package/dist/adapters/mastodon/statuses.js +153 -0
  150. package/dist/adapters/mastodon/statuses.js.map +1 -0
  151. package/dist/adapters/neurips/proceedings.d.ts +17 -0
  152. package/dist/adapters/neurips/proceedings.d.ts.map +1 -0
  153. package/dist/adapters/neurips/proceedings.js +112 -0
  154. package/dist/adapters/neurips/proceedings.js.map +1 -0
  155. package/dist/adapters/openalex/works.d.ts.map +1 -1
  156. package/dist/adapters/openalex/works.js +32 -0
  157. package/dist/adapters/openalex/works.js.map +1 -1
  158. package/dist/adapters/openreview/papers.js +5 -0
  159. package/dist/adapters/openreview/papers.js.map +1 -1
  160. package/dist/adapters/pmlr/proceedings.d.ts +35 -0
  161. package/dist/adapters/pmlr/proceedings.d.ts.map +1 -0
  162. package/dist/adapters/pmlr/proceedings.js +139 -0
  163. package/dist/adapters/pmlr/proceedings.js.map +1 -0
  164. package/dist/adapters/pubmed/articles.js +5 -0
  165. package/dist/adapters/pubmed/articles.js.map +1 -1
  166. package/dist/adapters/reddit/comments.d.ts +9 -0
  167. package/dist/adapters/reddit/comments.d.ts.map +1 -0
  168. package/dist/adapters/reddit/comments.js +124 -0
  169. package/dist/adapters/reddit/comments.js.map +1 -0
  170. package/dist/adapters/semantic-scholar/papers.d.ts +36 -0
  171. package/dist/adapters/semantic-scholar/papers.d.ts.map +1 -0
  172. package/dist/adapters/semantic-scholar/papers.js +214 -0
  173. package/dist/adapters/semantic-scholar/papers.js.map +1 -0
  174. package/dist/adapters/threads/post.d.ts +32 -0
  175. package/dist/adapters/threads/post.d.ts.map +1 -0
  176. package/dist/adapters/threads/post.js +287 -0
  177. package/dist/adapters/threads/post.js.map +1 -0
  178. package/dist/adapters/tiktok/subtitles.d.ts +9 -0
  179. package/dist/adapters/tiktok/subtitles.d.ts.map +1 -0
  180. package/dist/adapters/tiktok/subtitles.js +42 -0
  181. package/dist/adapters/tiktok/subtitles.js.map +1 -0
  182. package/dist/adapters/twitter/accept.js +2 -2
  183. package/dist/adapters/twitter/accept.js.map +1 -1
  184. package/dist/adapters/twitter/browser-fallback.d.ts +26 -0
  185. package/dist/adapters/twitter/browser-fallback.d.ts.map +1 -0
  186. package/dist/adapters/twitter/browser-fallback.js +93 -0
  187. package/dist/adapters/twitter/browser-fallback.js.map +1 -0
  188. package/dist/adapters/twitter/browser-state.d.ts +11 -0
  189. package/dist/adapters/twitter/browser-state.d.ts.map +1 -0
  190. package/dist/adapters/twitter/browser-state.js +46 -0
  191. package/dist/adapters/twitter/browser-state.js.map +1 -0
  192. package/dist/adapters/twitter/client.d.ts.map +1 -1
  193. package/dist/adapters/twitter/client.js +36 -13
  194. package/dist/adapters/twitter/client.js.map +1 -1
  195. package/dist/adapters/twitter/reply-dm.js +2 -2
  196. package/dist/adapters/twitter/reply-dm.js.map +1 -1
  197. package/dist/adapters/twitter/reply.js +1 -0
  198. package/dist/adapters/twitter/reply.js.map +1 -1
  199. package/dist/adapters/twitter/search.js +11 -18
  200. package/dist/adapters/twitter/search.js.map +1 -1
  201. package/dist/adapters/twitter/thread.d.ts +14 -0
  202. package/dist/adapters/twitter/thread.d.ts.map +1 -1
  203. package/dist/adapters/twitter/thread.js +28 -2
  204. package/dist/adapters/twitter/thread.js.map +1 -1
  205. package/dist/adapters/twitter/trending.js +13 -59
  206. package/dist/adapters/twitter/trending.js.map +1 -1
  207. package/dist/adapters/unpaywall/works.d.ts +33 -0
  208. package/dist/adapters/unpaywall/works.d.ts.map +1 -0
  209. package/dist/adapters/unpaywall/works.js +101 -0
  210. package/dist/adapters/unpaywall/works.js.map +1 -0
  211. package/dist/adapters/xiaohongshu/browser-state.d.ts +19 -0
  212. package/dist/adapters/xiaohongshu/browser-state.d.ts.map +1 -0
  213. package/dist/adapters/xiaohongshu/browser-state.js +67 -0
  214. package/dist/adapters/xiaohongshu/browser-state.js.map +1 -0
  215. package/dist/adapters/xiaohongshu/comments.js +28 -5
  216. package/dist/adapters/xiaohongshu/comments.js.map +1 -1
  217. package/dist/adapters/xiaohongshu/download.js +49 -11
  218. package/dist/adapters/xiaohongshu/download.js.map +1 -1
  219. package/dist/adapters/xiaohongshu/search.d.ts.map +1 -1
  220. package/dist/adapters/xiaohongshu/search.js +11 -5
  221. package/dist/adapters/xiaohongshu/search.js.map +1 -1
  222. package/dist/adapters/xiaohongshu/trending.d.ts +9 -0
  223. package/dist/adapters/xiaohongshu/trending.d.ts.map +1 -0
  224. package/dist/adapters/xiaohongshu/trending.js +94 -0
  225. package/dist/adapters/xiaohongshu/trending.js.map +1 -0
  226. package/dist/adapters/youtube/comments.d.ts +80 -0
  227. package/dist/adapters/youtube/comments.d.ts.map +1 -1
  228. package/dist/adapters/youtube/comments.js +108 -12
  229. package/dist/adapters/youtube/comments.js.map +1 -1
  230. package/dist/adapters/youtube/subtitles.d.ts +9 -0
  231. package/dist/adapters/youtube/subtitles.d.ts.map +1 -0
  232. package/dist/adapters/youtube/subtitles.js +42 -0
  233. package/dist/adapters/youtube/subtitles.js.map +1 -0
  234. package/dist/adapters/yt-dlp/subtitles.d.ts +9 -0
  235. package/dist/adapters/yt-dlp/subtitles.d.ts.map +1 -0
  236. package/dist/adapters/yt-dlp/subtitles.js +41 -0
  237. package/dist/adapters/yt-dlp/subtitles.js.map +1 -0
  238. package/dist/adapters/zhihu/answer-detail.d.ts +39 -0
  239. package/dist/adapters/zhihu/answer-detail.d.ts.map +1 -0
  240. package/dist/adapters/zhihu/answer-detail.js +204 -0
  241. package/dist/adapters/zhihu/answer-detail.js.map +1 -0
  242. package/dist/adapters/zhihu/comment.d.ts +9 -0
  243. package/dist/adapters/zhihu/comment.d.ts.map +1 -0
  244. package/dist/adapters/zhihu/comment.js +149 -0
  245. package/dist/adapters/zhihu/comment.js.map +1 -0
  246. package/dist/adapters/zhihu/recommend.d.ts +36 -0
  247. package/dist/adapters/zhihu/recommend.d.ts.map +1 -0
  248. package/dist/adapters/zhihu/recommend.js +151 -0
  249. package/dist/adapters/zhihu/recommend.js.map +1 -0
  250. package/dist/browser/bridge.d.ts.map +1 -1
  251. package/dist/browser/bridge.js +14 -3
  252. package/dist/browser/bridge.js.map +1 -1
  253. package/dist/browser/daemon-client.d.ts +6 -0
  254. package/dist/browser/daemon-client.d.ts.map +1 -1
  255. package/dist/browser/daemon-client.js +75 -15
  256. package/dist/browser/daemon-client.js.map +1 -1
  257. package/dist/browser/daemon.js +39 -15
  258. package/dist/browser/daemon.js.map +1 -1
  259. package/dist/browser/protocol.d.ts +1 -0
  260. package/dist/browser/protocol.d.ts.map +1 -1
  261. package/dist/browser/protocol.js +1 -0
  262. package/dist/browser/protocol.js.map +1 -1
  263. package/dist/cli.d.ts.map +1 -1
  264. package/dist/cli.js +21 -1
  265. package/dist/cli.js.map +1 -1
  266. package/dist/commands/approvals.d.ts.map +1 -1
  267. package/dist/commands/approvals.js +1 -37
  268. package/dist/commands/approvals.js.map +1 -1
  269. package/dist/commands/browser/index.d.ts.map +1 -1
  270. package/dist/commands/browser/index.js +7 -2
  271. package/dist/commands/browser/index.js.map +1 -1
  272. package/dist/commands/daemon.d.ts.map +1 -1
  273. package/dist/commands/daemon.js +7 -3
  274. package/dist/commands/daemon.js.map +1 -1
  275. package/dist/commands/dispatch.d.ts.map +1 -1
  276. package/dist/commands/dispatch.js +27 -3
  277. package/dist/commands/dispatch.js.map +1 -1
  278. package/dist/commands/do.d.ts +30 -0
  279. package/dist/commands/do.d.ts.map +1 -0
  280. package/dist/commands/do.js +248 -0
  281. package/dist/commands/do.js.map +1 -0
  282. package/dist/commands/extract.d.ts +34 -0
  283. package/dist/commands/extract.d.ts.map +1 -0
  284. package/dist/commands/extract.js +316 -0
  285. package/dist/commands/extract.js.map +1 -0
  286. package/dist/commands/patent-doctor.d.ts +48 -0
  287. package/dist/commands/patent-doctor.d.ts.map +1 -0
  288. package/dist/commands/patent-doctor.js +109 -0
  289. package/dist/commands/patent-doctor.js.map +1 -0
  290. package/dist/commands/patent.d.ts +78 -0
  291. package/dist/commands/patent.d.ts.map +1 -0
  292. package/dist/commands/patent.js +919 -0
  293. package/dist/commands/patent.js.map +1 -0
  294. package/dist/commands/scholar.d.ts +33 -0
  295. package/dist/commands/scholar.d.ts.map +1 -0
  296. package/dist/commands/scholar.js +494 -0
  297. package/dist/commands/scholar.js.map +1 -0
  298. package/dist/commands/search.d.ts.map +1 -1
  299. package/dist/commands/search.js +2 -5
  300. package/dist/commands/search.js.map +1 -1
  301. package/dist/commands/social.d.ts +19 -0
  302. package/dist/commands/social.d.ts.map +1 -0
  303. package/dist/commands/social.js +236 -0
  304. package/dist/commands/social.js.map +1 -0
  305. package/dist/core/registry.d.ts +1 -1
  306. package/dist/core/registry.d.ts.map +1 -1
  307. package/dist/core/registry.js +11 -2
  308. package/dist/core/registry.js.map +1 -1
  309. package/dist/discovery/aliases.d.ts +2 -2
  310. package/dist/discovery/aliases.d.ts.map +1 -1
  311. package/dist/discovery/aliases.js +182 -11
  312. package/dist/discovery/aliases.js.map +1 -1
  313. package/dist/discovery/intents.d.ts +10 -0
  314. package/dist/discovery/intents.d.ts.map +1 -0
  315. package/dist/discovery/intents.js +255 -0
  316. package/dist/discovery/intents.js.map +1 -0
  317. package/dist/discovery/loader.d.ts.map +1 -1
  318. package/dist/discovery/loader.js +4 -0
  319. package/dist/discovery/loader.js.map +1 -1
  320. package/dist/discovery/search.d.ts +4 -1
  321. package/dist/discovery/search.d.ts.map +1 -1
  322. package/dist/discovery/search.js +28 -140
  323. package/dist/discovery/search.js.map +1 -1
  324. package/dist/engine/approval-presenter.d.ts +10 -0
  325. package/dist/engine/approval-presenter.d.ts.map +1 -0
  326. package/dist/engine/approval-presenter.js +45 -0
  327. package/dist/engine/approval-presenter.js.map +1 -0
  328. package/dist/engine/approval-store.d.ts +4 -0
  329. package/dist/engine/approval-store.d.ts.map +1 -1
  330. package/dist/engine/approval-store.js +85 -11
  331. package/dist/engine/approval-store.js.map +1 -1
  332. package/dist/engine/auth/oauth2-cc.d.ts +67 -0
  333. package/dist/engine/auth/oauth2-cc.d.ts.map +1 -0
  334. package/dist/engine/auth/oauth2-cc.js +120 -0
  335. package/dist/engine/auth/oauth2-cc.js.map +1 -0
  336. package/dist/engine/cookies.d.ts +10 -0
  337. package/dist/engine/cookies.d.ts.map +1 -1
  338. package/dist/engine/cookies.js +64 -0
  339. package/dist/engine/cookies.js.map +1 -1
  340. package/dist/engine/download.d.ts +5 -0
  341. package/dist/engine/download.d.ts.map +1 -1
  342. package/dist/engine/download.js +11 -4
  343. package/dist/engine/download.js.map +1 -1
  344. package/dist/engine/executor.d.ts +1 -0
  345. package/dist/engine/executor.d.ts.map +1 -1
  346. package/dist/engine/executor.js +25 -0
  347. package/dist/engine/executor.js.map +1 -1
  348. package/dist/engine/framework.d.ts +5 -5
  349. package/dist/engine/framework.js +5 -5
  350. package/dist/engine/harden.d.ts +1 -1
  351. package/dist/engine/harden.js +1 -1
  352. package/dist/engine/kernel/stages.d.ts.map +1 -1
  353. package/dist/engine/kernel/stages.js +2 -1
  354. package/dist/engine/kernel/stages.js.map +1 -1
  355. package/dist/engine/normalizer/patent-envelope.d.ts +61 -0
  356. package/dist/engine/normalizer/patent-envelope.d.ts.map +1 -0
  357. package/dist/engine/normalizer/patent-envelope.js +132 -0
  358. package/dist/engine/normalizer/patent-envelope.js.map +1 -0
  359. package/dist/engine/research.d.ts +5 -7
  360. package/dist/engine/research.d.ts.map +1 -1
  361. package/dist/engine/research.js +6 -9
  362. package/dist/engine/research.js.map +1 -1
  363. package/dist/engine/steps/browser-helpers.d.ts +2 -2
  364. package/dist/engine/steps/browser-helpers.d.ts.map +1 -1
  365. package/dist/engine/steps/browser-helpers.js +39 -16
  366. package/dist/engine/steps/browser-helpers.js.map +1 -1
  367. package/dist/engine/steps/download.d.ts +1 -0
  368. package/dist/engine/steps/download.d.ts.map +1 -1
  369. package/dist/engine/steps/download.js +3 -1
  370. package/dist/engine/steps/download.js.map +1 -1
  371. package/dist/engine/steps/index.d.ts +2 -0
  372. package/dist/engine/steps/index.d.ts.map +1 -1
  373. package/dist/engine/steps/index.js +2 -0
  374. package/dist/engine/steps/index.js.map +1 -1
  375. package/dist/engine/steps/oauth2-token.d.ts +41 -0
  376. package/dist/engine/steps/oauth2-token.d.ts.map +1 -0
  377. package/dist/engine/steps/oauth2-token.js +115 -0
  378. package/dist/engine/steps/oauth2-token.js.map +1 -0
  379. package/dist/engine/steps/select-xml.d.ts +34 -0
  380. package/dist/engine/steps/select-xml.d.ts.map +1 -0
  381. package/dist/engine/steps/select-xml.js +222 -0
  382. package/dist/engine/steps/select-xml.js.map +1 -0
  383. package/dist/engine/template.d.ts.map +1 -1
  384. package/dist/engine/template.js +7 -0
  385. package/dist/engine/template.js.map +1 -1
  386. package/dist/engine/transport/mcp-browser.d.ts +128 -0
  387. package/dist/engine/transport/mcp-browser.d.ts.map +1 -0
  388. package/dist/engine/transport/mcp-browser.js +120 -0
  389. package/dist/engine/transport/mcp-browser.js.map +1 -0
  390. package/dist/fast-path/handlers/approvals.d.ts +11 -0
  391. package/dist/fast-path/handlers/approvals.d.ts.map +1 -0
  392. package/dist/fast-path/handlers/approvals.js +136 -0
  393. package/dist/fast-path/handlers/approvals.js.map +1 -0
  394. package/dist/fast-path/handlers/discovery.d.ts.map +1 -1
  395. package/dist/fast-path/handlers/discovery.js +17 -3
  396. package/dist/fast-path/handlers/discovery.js.map +1 -1
  397. package/dist/fast-path/manifest.d.ts +1 -0
  398. package/dist/fast-path/manifest.d.ts.map +1 -1
  399. package/dist/fast-path/manifest.js.map +1 -1
  400. package/dist/fast-path.d.ts.map +1 -1
  401. package/dist/fast-path.js +3 -0
  402. package/dist/fast-path.js.map +1 -1
  403. package/dist/index.d.ts +23 -0
  404. package/dist/index.d.ts.map +1 -0
  405. package/dist/index.js +38 -0
  406. package/dist/index.js.map +1 -0
  407. package/dist/manifest-compact.txt +13 -11
  408. package/dist/manifest-search.json +1 -1
  409. package/dist/manifest.json +2560 -103
  410. package/dist/mcp/handler.d.ts.map +1 -1
  411. package/dist/mcp/handler.js +14 -2
  412. package/dist/mcp/handler.js.map +1 -1
  413. package/dist/mcp/tools.d.ts.map +1 -1
  414. package/dist/mcp/tools.js +11 -3
  415. package/dist/mcp/tools.js.map +1 -1
  416. package/dist/output/auth-guidance.d.ts +14 -0
  417. package/dist/output/auth-guidance.d.ts.map +1 -0
  418. package/dist/output/auth-guidance.js +50 -0
  419. package/dist/output/auth-guidance.js.map +1 -0
  420. package/dist/output/error-map.d.ts +1 -1
  421. package/dist/output/error-map.d.ts.map +1 -1
  422. package/dist/output/error-map.js +28 -4
  423. package/dist/output/error-map.js.map +1 -1
  424. package/dist/output/next-actions.d.ts.map +1 -1
  425. package/dist/output/next-actions.js +19 -3
  426. package/dist/output/next-actions.js.map +1 -1
  427. package/dist/registry.d.ts +19 -1
  428. package/dist/registry.d.ts.map +1 -1
  429. package/dist/registry.js +10 -0
  430. package/dist/registry.js.map +1 -1
  431. package/dist/social/browser-errors.d.ts +13 -0
  432. package/dist/social/browser-errors.d.ts.map +1 -0
  433. package/dist/social/browser-errors.js +36 -0
  434. package/dist/social/browser-errors.js.map +1 -0
  435. package/dist/social/capabilities.d.ts +29 -0
  436. package/dist/social/capabilities.d.ts.map +1 -0
  437. package/dist/social/capabilities.js +448 -0
  438. package/dist/social/capabilities.js.map +1 -0
  439. package/dist/social/comments.d.ts +26 -0
  440. package/dist/social/comments.d.ts.map +1 -0
  441. package/dist/social/comments.js +97 -0
  442. package/dist/social/comments.js.map +1 -0
  443. package/dist/social/video-text.d.ts +27 -0
  444. package/dist/social/video-text.d.ts.map +1 -0
  445. package/dist/social/video-text.js +140 -0
  446. package/dist/social/video-text.js.map +1 -0
  447. package/dist/types/patent.d.ts +160 -0
  448. package/dist/types/patent.d.ts.map +1 -0
  449. package/dist/types/patent.js +16 -0
  450. package/dist/types/patent.js.map +1 -0
  451. package/dist/types/scholarly.d.ts +49 -0
  452. package/dist/types/scholarly.d.ts.map +1 -0
  453. package/dist/types/scholarly.js +16 -0
  454. package/dist/types/scholarly.js.map +1 -0
  455. package/dist/types.d.ts +12 -0
  456. package/dist/types.d.ts.map +1 -1
  457. package/dist/types.js.map +1 -1
  458. package/package.json +9 -4
  459. package/server.json +3 -3
  460. package/skills/unicli/SKILL.md +1 -1
  461. package/skills/unicli-claude-code/SKILL.md +1 -1
  462. package/skills/unicli-hermes/SKILL.md +1 -1
  463. package/src/adapters/acl-anthology/papers.ts +157 -0
  464. package/src/adapters/arxiv/download.yaml +1 -1
  465. package/src/adapters/arxiv/paper.yaml +1 -1
  466. package/src/adapters/arxiv/papers.ts +2 -0
  467. package/src/adapters/arxiv/search.yaml +1 -1
  468. package/src/adapters/arxiv/trending.yaml +1 -1
  469. package/src/adapters/baidu-scholar/search.ts +5 -0
  470. package/src/adapters/bilibili/comments-tree.test.ts +41 -0
  471. package/src/adapters/bilibili/comments.ts +78 -4
  472. package/src/adapters/bilibili/compat.ts +5 -2
  473. package/src/adapters/bilibili/download.ts +7 -4
  474. package/src/adapters/bilibili/wbi.ts +6 -3
  475. package/src/adapters/brave/search.yaml +53 -0
  476. package/src/adapters/cipo/_shared.ts +98 -0
  477. package/src/adapters/cipo/get.ts +188 -0
  478. package/src/adapters/cipo/legal-status.ts +148 -0
  479. package/src/adapters/cipo/search.ts +195 -0
  480. package/src/adapters/cnipa/_shared.ts +138 -0
  481. package/src/adapters/cnipa/get.ts +199 -0
  482. package/src/adapters/cnipa/legal-status.ts +162 -0
  483. package/src/adapters/cnipa/search.ts +229 -0
  484. package/src/adapters/crossref/works.ts +209 -0
  485. package/src/adapters/cvf/papers.ts +136 -0
  486. package/src/adapters/dblp/publications.ts +4 -0
  487. package/src/adapters/dpma/get.yaml +67 -0
  488. package/src/adapters/dpma/search.yaml +77 -0
  489. package/src/adapters/duckduckgo/search.yaml +54 -0
  490. package/src/adapters/duckduckgo/suggest.yaml +52 -0
  491. package/src/adapters/epo/family.yaml +69 -0
  492. package/src/adapters/epo/get.yaml +74 -0
  493. package/src/adapters/epo/legal-status.yaml +63 -0
  494. package/src/adapters/epo/search.yaml +84 -0
  495. package/src/adapters/espacenet/_shared.ts +98 -0
  496. package/src/adapters/espacenet/family.ts +161 -0
  497. package/src/adapters/espacenet/get.ts +185 -0
  498. package/src/adapters/espacenet/legal-status.ts +151 -0
  499. package/src/adapters/espacenet/search.ts +229 -0
  500. package/src/adapters/facebook/subtitles.ts +44 -0
  501. package/src/adapters/fips/_shared.ts +109 -0
  502. package/src/adapters/fips/get.ts +186 -0
  503. package/src/adapters/fips/search.ts +195 -0
  504. package/src/adapters/freepatentsonline-web/_shared.ts +273 -0
  505. package/src/adapters/freepatentsonline-web/get.ts +144 -0
  506. package/src/adapters/freepatentsonline-web/search.ts +170 -0
  507. package/src/adapters/google-patents-bq/prior-art.yaml +80 -0
  508. package/src/adapters/google-patents-bq/search.yaml +97 -0
  509. package/src/adapters/google-patents-web/_shared.ts +242 -0
  510. package/src/adapters/google-patents-web/get.ts +224 -0
  511. package/src/adapters/google-patents-web/search.ts +196 -0
  512. package/src/adapters/google-scholar/cite.ts +1 -0
  513. package/src/adapters/google-scholar/profile.ts +5 -0
  514. package/src/adapters/google-scholar/search.ts +5 -0
  515. package/src/adapters/hf/paper.test.ts +10 -0
  516. package/src/adapters/hf/paper.ts +1 -0
  517. package/src/adapters/hf/top.yaml +1 -1
  518. package/src/adapters/huggingface-papers/daily.yaml +1 -1
  519. package/src/adapters/huggingface-papers/search.yaml +1 -1
  520. package/src/adapters/inpi-br/_shared.ts +98 -0
  521. package/src/adapters/inpi-br/get.ts +193 -0
  522. package/src/adapters/inpi-br/search.ts +206 -0
  523. package/src/adapters/inpi-fr/get.yaml +62 -0
  524. package/src/adapters/inpi-fr/search.yaml +74 -0
  525. package/src/adapters/instagram/subtitles.ts +44 -0
  526. package/src/adapters/ipaustralia/get.yaml +67 -0
  527. package/src/adapters/ipaustralia/search.yaml +74 -0
  528. package/src/adapters/jpo/get.yaml +63 -0
  529. package/src/adapters/jpo/search.yaml +76 -0
  530. package/src/adapters/kipris/get.yaml +69 -0
  531. package/src/adapters/kipris/legal-status.yaml +58 -0
  532. package/src/adapters/kipris/search.yaml +79 -0
  533. package/src/adapters/lens/get.yaml +64 -0
  534. package/src/adapters/lens/search.yaml +82 -0
  535. package/src/adapters/mastodon/statuses.test.ts +82 -0
  536. package/src/adapters/mastodon/statuses.ts +208 -0
  537. package/src/adapters/neurips/proceedings.ts +126 -0
  538. package/src/adapters/openalex/works.ts +33 -0
  539. package/src/adapters/openreview/papers.ts +5 -0
  540. package/src/adapters/patsnap/get.yaml +65 -0
  541. package/src/adapters/patsnap/search.yaml +77 -0
  542. package/src/adapters/pmlr/proceedings.ts +167 -0
  543. package/src/adapters/pqai/prior-art.yaml +59 -0
  544. package/src/adapters/pqai/search.yaml +60 -0
  545. package/src/adapters/pubmed/articles.ts +5 -0
  546. package/src/adapters/reddit/comments-tree.test.ts +79 -0
  547. package/src/adapters/reddit/comments.ts +159 -0
  548. package/src/adapters/semantic-scholar/papers.ts +268 -0
  549. package/src/adapters/threads/post.test.ts +64 -0
  550. package/src/adapters/threads/post.ts +366 -0
  551. package/src/adapters/threads/user.yaml +73 -0
  552. package/src/adapters/tiktok/subtitles.ts +44 -0
  553. package/src/adapters/twitter/accept.ts +5 -2
  554. package/src/adapters/twitter/browser-fallback.ts +138 -0
  555. package/src/adapters/twitter/browser-state.ts +74 -0
  556. package/src/adapters/twitter/client.ts +51 -21
  557. package/src/adapters/twitter/reply-dm.ts +5 -2
  558. package/src/adapters/twitter/reply.ts +1 -0
  559. package/src/adapters/twitter/search.ts +12 -38
  560. package/src/adapters/twitter/thread.test.ts +43 -0
  561. package/src/adapters/twitter/thread.ts +44 -2
  562. package/src/adapters/twitter/trending.ts +14 -95
  563. package/src/adapters/ukipo/info.yaml +43 -0
  564. package/src/adapters/unpaywall/works.ts +138 -0
  565. package/src/adapters/uspto/get.yaml +67 -0
  566. package/src/adapters/uspto/legal-status.yaml +58 -0
  567. package/src/adapters/uspto/search.yaml +88 -0
  568. package/src/adapters/wipo-patentscope/info.yaml +43 -0
  569. package/src/adapters/xiaohongshu/browser-state.ts +95 -0
  570. package/src/adapters/xiaohongshu/comments.ts +29 -6
  571. package/src/adapters/xiaohongshu/download.ts +60 -11
  572. package/src/adapters/xiaohongshu/search.ts +18 -6
  573. package/src/adapters/xiaohongshu/trending.ts +112 -0
  574. package/src/adapters/yahoo/search.yaml +52 -0
  575. package/src/adapters/youtube/comments-microformat.test.ts +35 -0
  576. package/src/adapters/youtube/comments-tree.test.ts +74 -0
  577. package/src/adapters/youtube/comments.ts +166 -12
  578. package/src/adapters/youtube/subtitles.ts +44 -0
  579. package/src/adapters/yt-dlp/subtitles.ts +43 -0
  580. package/src/adapters/zhihu/answer-detail.test.ts +83 -0
  581. package/src/adapters/zhihu/answer-detail.ts +275 -0
  582. package/src/adapters/zhihu/comment-tree.test.ts +57 -0
  583. package/src/adapters/zhihu/comment.ts +186 -0
  584. package/src/adapters/zhihu/recommend.test.ts +65 -0
  585. package/src/adapters/zhihu/recommend.ts +207 -0
  586. package/src/adapters/zotero/search.yaml +1 -1
@@ -0,0 +1,138 @@
1
+ /**
2
+ * @owner src::adapters::unpaywall::works
3
+ * @does Registers Unpaywall DOI open-access lookup for PDF availability.
4
+ * @needs api.unpaywall.org v2, UNPAYWALL_EMAIL or --email, src/registry.ts
5
+ * @feeds src/commands/scholar.ts via scholar.pdf and scholar.get
6
+ * @breaks Missing email is an explicit invalid-input error; Unpaywall drift surfaces as adapter error, never as a fabricated PDF.
7
+ * @invariants Only DOI-shaped references are accepted; best_oa_location is preferred for PDF and landing URLs.
8
+ * @side-effects HTTPS egress to api.unpaywall.org only
9
+ * @perf O(1) per DOI
10
+ * @concurrency safe
11
+ * @test tests/unit/adapters/scholar-sources.test.ts
12
+ * @stability experimental
13
+ * @since 2026-05-19
14
+ */
15
+
16
+ import { cli, Strategy } from "../../registry.js";
17
+ import type { ScholarlyWorkRecord } from "../../types/scholarly.js";
18
+
19
+ const API = "https://api.unpaywall.org/v2";
20
+
21
+ interface OaLocation {
22
+ url_for_pdf?: unknown;
23
+ url_for_landing_page?: unknown;
24
+ host_type?: unknown;
25
+ version?: unknown;
26
+ license?: unknown;
27
+ }
28
+
29
+ interface UnpaywallWork {
30
+ doi?: unknown;
31
+ title?: unknown;
32
+ is_oa?: unknown;
33
+ oa_status?: unknown;
34
+ best_oa_location?: OaLocation | null;
35
+ }
36
+
37
+ function str(value: unknown): string {
38
+ return typeof value === "string" ? value.trim() : "";
39
+ }
40
+
41
+ function bareDoi(value: unknown): string {
42
+ return str(value)
43
+ .replace(/^doi:/i, "")
44
+ .replace(/^https?:\/\/(?:dx\.)?doi\.org\//i, "");
45
+ }
46
+
47
+ export function requireUnpaywallDoi(value: unknown): string {
48
+ const doi = bareDoi(value);
49
+ if (!/^10\.\S+\/\S+/.test(doi)) {
50
+ throw new Error(
51
+ `unpaywall DOI "${String(value ?? "")}" is not recognised.`,
52
+ );
53
+ }
54
+ return doi;
55
+ }
56
+
57
+ function requireEmail(value: unknown): string {
58
+ const email = str(value) || process.env.UNPAYWALL_EMAIL?.trim() || "";
59
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
60
+ throw new Error("unpaywall lookup requires --email or UNPAYWALL_EMAIL.");
61
+ }
62
+ return email;
63
+ }
64
+
65
+ export function mapUnpaywallWork(
66
+ work: UnpaywallWork,
67
+ source: string,
68
+ ): ScholarlyWorkRecord {
69
+ const doi = requireUnpaywallDoi(work.doi);
70
+ const best = work.best_oa_location ?? {};
71
+ return {
72
+ id: doi,
73
+ title: str(work.title),
74
+ doi,
75
+ is_open_access: work.is_oa === true,
76
+ oa_status: str(work.oa_status) || undefined,
77
+ pdf_url: str(best.url_for_pdf) || undefined,
78
+ landing_url: str(best.url_for_landing_page) || `https://doi.org/${doi}`,
79
+ type:
80
+ [str(best.host_type), str(best.version), str(best.license)]
81
+ .filter(Boolean)
82
+ .join(":") || undefined,
83
+ source_adapter: source,
84
+ source_url: str(best.url_for_landing_page) || `https://doi.org/${doi}`,
85
+ retrieved_at: new Date().toISOString(),
86
+ };
87
+ }
88
+
89
+ async function fetchUnpaywall(
90
+ doi: string,
91
+ email: string,
92
+ ): Promise<UnpaywallWork> {
93
+ const response = await fetch(
94
+ `${API}/${encodeURIComponent(doi)}?email=${encodeURIComponent(email)}`,
95
+ {
96
+ headers: {
97
+ Accept: "application/json",
98
+ "User-Agent":
99
+ "unicli-unpaywall/1.0 (https://github.com/olo-dot-io/Uni-CLI)",
100
+ },
101
+ },
102
+ );
103
+ if (response.status === 404)
104
+ throw new Error(`Unpaywall returned no result for ${doi}.`);
105
+ if (response.status === 422)
106
+ throw new Error("Unpaywall rejected the email parameter.");
107
+ if (response.status === 429) throw new Error("Unpaywall returned HTTP 429.");
108
+ if (!response.ok)
109
+ throw new Error(`Unpaywall returned HTTP ${response.status}.`);
110
+ return response.json() as Promise<UnpaywallWork>;
111
+ }
112
+
113
+ cli({
114
+ site: "unpaywall",
115
+ name: "oa",
116
+ description: "Find open-access PDF availability for a DOI via Unpaywall",
117
+ domain: "api.unpaywall.org",
118
+ strategy: Strategy.PUBLIC,
119
+ args: [
120
+ { name: "doi", type: "str", required: true, positional: true },
121
+ { name: "email", type: "str", description: "Unpaywall requester email" },
122
+ ],
123
+ columns: [
124
+ "id",
125
+ "title",
126
+ "doi",
127
+ "is_open_access",
128
+ "oa_status",
129
+ "pdf_url",
130
+ "source_url",
131
+ ],
132
+ capabilities: ["http.fetch", "scholar.get", "scholar.pdf"],
133
+ func: async (_page, kwargs) => {
134
+ const doi = requireUnpaywallDoi(kwargs.doi ?? kwargs.id ?? kwargs.ref);
135
+ const email = requireEmail(kwargs.email);
136
+ return [mapUnpaywallWork(await fetchUnpaywall(doi, email), "unpaywall")];
137
+ },
138
+ });
@@ -0,0 +1,67 @@
1
+ # @owner src::adapters::uspto::get
2
+ # @does Fetch a single USPTO patent/application by application number via the ODP detail endpoint.
3
+ # @needs src/engine/steps/fetch.ts, src/engine/steps/map.ts
4
+ # @feeds src/commands/patent.ts
5
+ # @breaks throws PipelineError on 401/403 (missing/invalid X-API-KEY), 404 (number not found) or 5xx
6
+ # @invariants output row conforms to PatentRecord; publication_number is canonicalized to ST.16 form
7
+ # @side-effects reads env USPTO_ODP_API_KEY; HTTPS egress to api.uspto.gov
8
+ # @perf single request
9
+ # @concurrency safe
10
+ # @test none yet
11
+ # @stability stable
12
+ # @since 2026-05-18
13
+ # @verification blocked-by-key — needs USPTO_ODP_API_KEY
14
+ site: uspto
15
+ name: get
16
+ description: Fetch a USPTO patent/application by application number
17
+ domain: api.uspto.gov
18
+ type: web-api
19
+ strategy: public
20
+ lint_listing_detail: skip
21
+
22
+ args:
23
+ application_number:
24
+ type: str
25
+ required: true
26
+ positional: true
27
+ description: USPTO application number (e.g. 16/123,456 with or without slash)
28
+
29
+ pipeline:
30
+ - fetch:
31
+ url: "https://api.uspto.gov/api/v1/patent/applications/${{ args.application_number | replace('/', '') | replace(',', '') }}"
32
+ method: GET
33
+ headers:
34
+ Accept: application/json
35
+ X-API-KEY: "${{ env.USPTO_ODP_API_KEY || '' }}"
36
+
37
+ # ODP single-record detail endpoint returns the same `applicationMetaData`
38
+ # envelope as search, plus a richer `patentTermAdjustment` / `inventor` /
39
+ # `applicant` set on the detail path. Every field reference below maps to a
40
+ # documented ODP path; adapters do not synthesise.
41
+ - map:
42
+ publication_number: "${{ item.applicationMetaData && item.applicationMetaData.earliestPublicationNumber ? ('US-' + item.applicationMetaData.earliestPublicationNumber) : ('US-' + (item.applicationNumberText || '')) }}"
43
+ application_number: "${{ item.applicationNumberText || '' }}"
44
+ title: "${{ item.applicationMetaData ? (item.applicationMetaData.inventionTitle || '') : '' }}"
45
+ abstract: "${{ item.applicationMetaData ? (item.applicationMetaData.abstractText || '') : '' }}"
46
+ filing_date: "${{ item.applicationMetaData ? (item.applicationMetaData.filingDate || '') : '' }}"
47
+ publication_date: "${{ item.applicationMetaData ? (item.applicationMetaData.earliestPublicationDate || '') : '' }}"
48
+ grant_date: "${{ item.applicationMetaData ? (item.applicationMetaData.grantDate || '') : '' }}"
49
+ priority_date: "${{ item.applicationMetaData ? (item.applicationMetaData.firstInventorToFileIndicator ? item.applicationMetaData.filingDate : (item.applicationMetaData.earliestPriorityDate || '')) : '' }}"
50
+ kind_code: "${{ (item.applicationMetaData && item.applicationMetaData.earliestPublicationNumber) ? (item.applicationMetaData.earliestPublicationNumber.match(/[A-Z]\\d?$/) || [''])[0] : '' }}"
51
+ inventors: "${{ JSON.stringify((item.applicationMetaData && item.applicationMetaData.inventorBag) ? item.applicationMetaData.inventorBag.map(p => ({ name: p.inventorNameText || ((p.firstName || '') + ' ' + (p.lastName || '')).trim(), country: p.countryCode || undefined })) : []) }}"
52
+ assignees: "${{ JSON.stringify((item.applicationMetaData && item.applicationMetaData.applicantBag) ? item.applicationMetaData.applicantBag.map(p => ({ name: p.applicantNameText || p.organizationNameText || '', country: p.countryCode || undefined })) : []) }}"
53
+ classifications: "${{ JSON.stringify((item.applicationMetaData && item.applicationMetaData.cpcClassificationBag) ? item.applicationMetaData.cpcClassificationBag.map(c => ({ scheme: 'cpc', code: c.cpcSymbol || c })) : []) }}"
54
+ legal_status: "${{ item.applicationMetaData ? (item.applicationMetaData.applicationStatusDescriptionText || '') : '' }}"
55
+ source_adapter: uspto
56
+ source_url: "${{ 'https://ppubs.uspto.gov/dirsearch-public/patents/' + (item.applicationNumberText || '') }}"
57
+ retrieved_at: ""
58
+
59
+ columns: [publication_number, title, filing_date, publication_date]
60
+
61
+ # schema-v2 metadata
62
+ capabilities: ["http.fetch", "patent.get"]
63
+ minimum_capability: http.fetch
64
+ trust: public
65
+ confidentiality: public
66
+ quarantine: false
67
+ schema_version: v2
@@ -0,0 +1,58 @@
1
+ # @owner src::adapters::uspto::legal-status
2
+ # @does Fetch USPTO transaction history (PAIR) for an application — used to derive legal-status (issued, abandoned, pending, etc.).
3
+ # @needs src/engine/steps/fetch.ts, src/engine/steps/select.ts, src/engine/steps/map.ts
4
+ # @feeds src/commands/patent.ts
5
+ # @breaks throws PipelineError on 401/403/404
6
+ # @invariants output rows conform to PatentRecord; legal_status carries the latest transaction description
7
+ # @side-effects reads env USPTO_ODP_API_KEY; HTTPS egress to api.uspto.gov
8
+ # @perf single request
9
+ # @concurrency safe
10
+ # @test none yet
11
+ # @stability stable
12
+ # @since 2026-05-18
13
+ # @verification blocked-by-key — needs USPTO_ODP_API_KEY
14
+ site: uspto
15
+ name: legal-status
16
+ description: Legal-status / transaction history of a USPTO application
17
+ domain: api.uspto.gov
18
+ type: web-api
19
+ strategy: public
20
+ lint_listing_detail: skip
21
+
22
+ args:
23
+ application_number:
24
+ type: str
25
+ required: true
26
+ positional: true
27
+ description: USPTO application number
28
+
29
+ pipeline:
30
+ - fetch:
31
+ url: "https://api.uspto.gov/api/v1/patent/applications/${{ args.application_number | replace('/', '') | replace(',', '') }}/transactions"
32
+ method: GET
33
+ headers:
34
+ Accept: application/json
35
+ X-API-KEY: "${{ env.USPTO_ODP_API_KEY || '' }}"
36
+
37
+ - select: eventDataBag
38
+
39
+ # Each row is a transaction event; the ODP `transactions` endpoint returns
40
+ # eventCode + eventDescriptionText + eventDate per transaction.
41
+ - map:
42
+ publication_number: "${{ 'US-' + (args.application_number || '') }}"
43
+ application_number: "${{ args.application_number }}"
44
+ legal_status: "${{ (item.eventCode || '') + (item.eventDescriptionText ? (' ' + item.eventDescriptionText) : '') }}"
45
+ filing_date: "${{ item.eventDate || '' }}"
46
+ source_adapter: uspto
47
+ source_url: "${{ 'https://ppubs.uspto.gov/dirsearch-public/patents/' + (args.application_number || '') }}"
48
+ retrieved_at: ""
49
+
50
+ columns: [publication_number, legal_status, filing_date]
51
+
52
+ # schema-v2 metadata
53
+ capabilities: ["http.fetch", "patent.legal-status"]
54
+ minimum_capability: http.fetch
55
+ trust: public
56
+ confidentiality: public
57
+ quarantine: false
58
+ schema_version: v2
@@ -0,0 +1,88 @@
1
+ # @owner src::adapters::uspto::search
2
+ # @does Search USPTO patents/applications via the Open Data Portal (ODP) `applications/search` endpoint.
3
+ # @needs src/engine/steps/fetch.ts, src/engine/steps/select.ts, src/engine/steps/map.ts, src/engine/steps/limit.ts
4
+ # @feeds src/commands/patent.ts (meta-command aggregator)
5
+ # @breaks throws PipelineError on 401/403 (missing/invalid X-API-KEY) or 5xx; ODP enforces a 6 MB response cap — narrow the query if hit
6
+ # @invariants output rows conform to PatentRecord; publication_number is canonicalized to ST.16 form `US-<doc>-<kind>`
7
+ # @side-effects reads env USPTO_ODP_API_KEY; HTTPS egress to api.uspto.gov
8
+ # @perf single request, ODP returns up to 500 records per page
9
+ # @concurrency single-call; no shared mutable state
10
+ # @test none yet (adapter ships; live verification gated on key)
11
+ # @stability stable
12
+ # @since 2026-05-18
13
+ # @verification blocked-by-key — needs USPTO_ODP_API_KEY (free tier at developer.uspto.gov)
14
+ site: uspto
15
+ name: search
16
+ description: Search USPTO patents/applications via the Open Data Portal (ODP)
17
+ domain: api.uspto.gov
18
+ type: web-api
19
+ strategy: public
20
+ lint_listing_detail: skip
21
+
22
+ args:
23
+ query:
24
+ type: str
25
+ required: true
26
+ positional: true
27
+ description: Free-text query (mapped to ODP `q` field, matches title/abstract/claims)
28
+ limit:
29
+ type: int
30
+ default: 25
31
+ description: Maximum results to return (ODP allows up to 500 per page)
32
+ offset:
33
+ type: int
34
+ default: 0
35
+ description: Result offset for pagination
36
+
37
+ pipeline:
38
+ - fetch:
39
+ url: "https://api.uspto.gov/api/v1/patent/applications/search"
40
+ method: GET
41
+ headers:
42
+ Accept: application/json
43
+ X-API-KEY: "${{ env.USPTO_ODP_API_KEY || '' }}"
44
+ params:
45
+ q: "${{ args.query }}"
46
+ limit: "${{ args.limit }}"
47
+ offset: "${{ args.offset }}"
48
+
49
+ - select: patentFileWrapperDataBag
50
+
51
+ # Field mapping references data.uspto.gov/swagger v1 patent applications schema.
52
+ # Every field below maps to a documented ODP response path — adapters must
53
+ # not synthesise values upstream did not return.
54
+ - map:
55
+ publication_number: "${{ item.applicationMetaData && item.applicationMetaData.earliestPublicationNumber ? ('US-' + item.applicationMetaData.earliestPublicationNumber) : ('US-' + (item.applicationNumberText || '')) }}"
56
+ application_number: "${{ item.applicationNumberText || '' }}"
57
+ title: "${{ item.applicationMetaData ? (item.applicationMetaData.inventionTitle || '') : '' }}"
58
+ abstract: "${{ item.applicationMetaData ? (item.applicationMetaData.abstractText || '') : '' }}"
59
+ filing_date: "${{ item.applicationMetaData ? (item.applicationMetaData.filingDate || '') : '' }}"
60
+ publication_date: "${{ item.applicationMetaData ? (item.applicationMetaData.earliestPublicationDate || '') : '' }}"
61
+ grant_date: "${{ item.applicationMetaData ? (item.applicationMetaData.grantDate || '') : '' }}"
62
+ # ODP `applicationMetaData.earliestPublicationNumber` is the compact form
63
+ # (`20240123456A1`); the trailing A1/A2/B1/B2 IS the ST.16 kind code.
64
+ kind_code: "${{ (item.applicationMetaData && item.applicationMetaData.earliestPublicationNumber) ? (item.applicationMetaData.earliestPublicationNumber.match(/[A-Z]\\d?$/) || [''])[0] : '' }}"
65
+ # ODP `inventorBag[]` and `applicantBag[]` carry per-party records.
66
+ # We serialise via JSON.stringify so the array survives the template
67
+ # engine's string projection; coerceToPatentRecords parses it back.
68
+ inventors: "${{ JSON.stringify((item.applicationMetaData && item.applicationMetaData.inventorBag) ? item.applicationMetaData.inventorBag.map(p => ({ name: p.inventorNameText || ((p.firstName || '') + ' ' + (p.lastName || '')).trim(), country: p.countryCode || undefined })) : []) }}"
69
+ assignees: "${{ JSON.stringify((item.applicationMetaData && item.applicationMetaData.applicantBag) ? item.applicationMetaData.applicantBag.map(p => ({ name: p.applicantNameText || p.organizationNameText || '', country: p.countryCode || undefined })) : []) }}"
70
+ # `cpcClassificationBag[]` is the ODP path for Cooperative Patent Classification codes.
71
+ classifications: "${{ JSON.stringify((item.applicationMetaData && item.applicationMetaData.cpcClassificationBag) ? item.applicationMetaData.cpcClassificationBag.map(c => ({ scheme: 'cpc', code: c.cpcSymbol || c })) : []) }}"
72
+ legal_status: "${{ item.applicationMetaData ? (item.applicationMetaData.applicationStatusDescriptionText || '') : '' }}"
73
+ source_adapter: uspto
74
+ source_url: "${{ 'https://ppubs.uspto.gov/dirsearch-public/patents/' + (item.applicationNumberText || '') }}"
75
+ # retrieved_at is stamped by assemblePatentRecord in the normalizer; YAML emits the empty string
76
+ retrieved_at: ""
77
+
78
+ - limit: "${{ args.limit }}"
79
+
80
+ columns: [publication_number, title, filing_date, publication_date]
81
+
82
+ # schema-v2 metadata
83
+ capabilities: ["http.fetch", "patent.search"]
84
+ minimum_capability: http.fetch
85
+ trust: public
86
+ confidentiality: public
87
+ quarantine: false
88
+ schema_version: v2
@@ -0,0 +1,43 @@
1
+ # @owner src::adapters::wipo-patentscope::info
2
+ # @does Registry placeholder for WIPO PATENTSCOPE — surfaces a structured PATENT_API_DEPRECATED envelope so `unicli patent doctor` and `unicli list` advertise the gap, without claiming false coverage.
3
+ # @needs src/engine/steps/assert.ts
4
+ # @feeds src/commands/patent.ts (meta-command discovery via `patent.*` capability)
5
+ # @breaks always throws PipelineError carrying a PATENT_API_DEPRECATED message; never silently returns rows
6
+ # @invariants no HTTPS egress; no env reads; no caller-visible state beyond the error envelope
7
+ # @side-effects none — the assertion is purely local
8
+ # @perf n/a — fails before any I/O
9
+ # @concurrency safe (pure local assertion)
10
+ # @test none yet
11
+ # @stability experimental — replace with a real adapter when WIPO ships a token-based REST/GraphQL API
12
+ # @since 2026-05-18
13
+ # @verification blocked-by-subscription — PATENTSCOPE exposes only a SOAP web service that requires a paid subscription (~CHF 600/year per third-party gem README; see https://patentscope.wipo.int/search/en/sub_user.jsf). Until WIPO ships a token-based REST/GraphQL surface, this adapter is a registry placeholder.
14
+ site: wipo-patentscope
15
+ name: info
16
+ description: WIPO PATENTSCOPE registry placeholder — no public REST API; SOAP requires subscription
17
+ domain: patentscope.wipo.int
18
+ type: web-api
19
+ strategy: public
20
+ lint_listing_detail: skip
21
+
22
+ args: {}
23
+
24
+ pipeline:
25
+ # Fail closed with a structured envelope that the agent can read and act on.
26
+ # The message names the upstream channel and the subscription URL so the
27
+ # caller has a concrete next step — no silent fallback, no fake row.
28
+ - assert:
29
+ condition: "false"
30
+ message: "PATENT_API_DEPRECATED: WIPO PATENTSCOPE exposes only a SOAP web service that requires a paid subscription. Subscribe at https://patentscope.wipo.int/search/en/sub_user.jsf, or fall back to Espacenet for WO-prefixed publications (EPO brokers PCT family lookups)."
31
+
32
+ columns: []
33
+
34
+ # schema-v2 metadata
35
+ # The patent.* capability is what makes `unicli patent doctor` discover this
36
+ # adapter so the gap is reported in the doctor table; assert.fail is the
37
+ # step the dispatcher actually invokes at runtime.
38
+ capabilities: ["assert", "patent.search", "patent.get"]
39
+ minimum_capability: assert
40
+ trust: public
41
+ confidentiality: public
42
+ quarantine: false
43
+ schema_version: v2
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @owner Xiaohongshu browser adapters.
3
+ * @does Detects login, risk-control, and rendered-feed state in XHS web pages.
4
+ * @needs Browser-backed IPage from Uni-CLI runtime.
5
+ * @feeds xiaohongshu.search and xiaohongshu.trending.
6
+ * @breaks XHS copy or route changes can require updating page-state detection.
7
+ */
8
+
9
+ import type { IPage } from "../../types.js";
10
+ import {
11
+ socialAuthError,
12
+ socialChallengeError,
13
+ } from "../../social/browser-errors.js";
14
+
15
+ interface XhsPageState {
16
+ url: string;
17
+ title: string;
18
+ text: string;
19
+ }
20
+
21
+ export async function readXhsPageState(page: IPage): Promise<XhsPageState> {
22
+ const raw = await page.evaluate(`
23
+ (() => ({
24
+ url: window.location.href,
25
+ title: document.title || '',
26
+ text: (document.body?.innerText || '').replace(/\\s+/g, ' ').slice(0, 2000)
27
+ }))()
28
+ `);
29
+ const state = raw as Partial<XhsPageState>;
30
+ return {
31
+ url: String(state.url ?? ""),
32
+ title: String(state.title ?? ""),
33
+ text: String(state.text ?? ""),
34
+ };
35
+ }
36
+
37
+ export function assertXhsReadableState(
38
+ command: string,
39
+ state: XhsPageState,
40
+ ): void {
41
+ const haystack = `${state.url}\n${state.title}\n${state.text}`;
42
+ if (
43
+ /website-login\/error|安全限制|IP存在风险|风险|风控|安全验证|验证码|人机验证|verify|captcha/i.test(
44
+ haystack,
45
+ )
46
+ ) {
47
+ throw socialChallengeError(
48
+ "xiaohongshu",
49
+ command,
50
+ `Xiaohongshu is showing a risk-control or verification page: ${state.title || state.url}`,
51
+ );
52
+ }
53
+ if (/登录后查看|登录后|请先登录|login/i.test(haystack)) {
54
+ throw socialAuthError("xiaohongshu", command);
55
+ }
56
+ }
57
+
58
+ export async function assertXhsReadable(
59
+ page: IPage,
60
+ command: string,
61
+ ): Promise<void> {
62
+ assertXhsReadableState(command, await readXhsPageState(page));
63
+ }
64
+
65
+ export async function fetchXhsFeedItems(page: IPage): Promise<unknown[]> {
66
+ const raw = await page.evaluate(`
67
+ (async () => {
68
+ const app = document.querySelector('#app')?.__vue_app__;
69
+ if (!app) throw new Error('Xiaohongshu Vue app not found');
70
+ const pinia = app.config?.globalProperties?.$pinia;
71
+ if (!pinia || !pinia._s?.has('feed')) throw new Error('Xiaohongshu feed store not found');
72
+ const store = pinia._s.get('feed');
73
+ const captured = [];
74
+ const originalFetch = window.fetch;
75
+ window.fetch = async (...args) => {
76
+ const response = await originalFetch(...args);
77
+ try {
78
+ const url = String(args[0]?.url || args[0] || '');
79
+ if (/homefeed|feed/i.test(url)) {
80
+ captured.push(await response.clone().json());
81
+ }
82
+ } catch {}
83
+ return response;
84
+ };
85
+ try {
86
+ await store.fetchFeeds();
87
+ } finally {
88
+ window.fetch = originalFetch;
89
+ }
90
+ const payload = captured.find((item) => item?.data?.items?.length) || captured[0];
91
+ return payload?.data?.items || [];
92
+ })()
93
+ `);
94
+ return Array.isArray(raw) ? raw : [];
95
+ }
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { cli, Strategy } from "../../registry.js";
9
9
  import type { IPage } from "../../types.js";
10
+ import { normalizeCommentRows } from "../../social/comments.js";
10
11
  import { buildNoteUrl } from "./note-helpers.js";
11
12
 
12
13
  function parseCommentLimit(raw: unknown, fallback = 20): number {
@@ -42,7 +43,23 @@ cli({
42
43
  description: "Include nested replies",
43
44
  },
44
45
  ],
45
- columns: ["rank", "author", "text", "likes", "time", "is_reply", "reply_to"],
46
+ columns: [
47
+ "rank",
48
+ "platform",
49
+ "content_id",
50
+ "comment_id",
51
+ "parent_id",
52
+ "depth",
53
+ "path",
54
+ "author",
55
+ "text",
56
+ "likes",
57
+ "replies",
58
+ "created",
59
+ "time",
60
+ "is_reply",
61
+ "reply_to",
62
+ ],
46
63
  func: async (page, kwargs) => {
47
64
  const p = page as IPage;
48
65
  const limit = parseCommentLimit(kwargs.limit);
@@ -100,7 +117,7 @@ cli({
100
117
  const likes = parseLikes(item.querySelector('.count'))
101
118
  const time = clean(item.querySelector('.date, .time'))
102
119
  if (!text) continue
103
- results.push({ author, text, likes, time, is_reply: false, reply_to: '' })
120
+ results.push({ author, text, likes, replies: 0, created: time, time, is_reply: false, reply_to: '' })
104
121
  if (withReplies) {
105
122
  await expandReplyThreads(p)
106
123
  p.querySelectorAll('.reply-container .comment-item-sub, .sub-comment-list .comment-item').forEach(sub => {
@@ -109,7 +126,7 @@ cli({
109
126
  const sLikes = parseLikes(sub.querySelector('.count'))
110
127
  const sTime = clean(sub.querySelector('.date, .time'))
111
128
  if (!sText) return
112
- results.push({ author: sAuthor, text: sText, likes: sLikes, time: sTime, is_reply: true, reply_to: author })
129
+ results.push({ author: sAuthor, text: sText, likes: sLikes, replies: 0, created: sTime, time: sTime, is_reply: true, reply_to: author })
113
130
  })
114
131
  }
115
132
  }
@@ -125,7 +142,7 @@ cli({
125
142
  throw new Error("Note comments require login to www.xiaohongshu.com");
126
143
  }
127
144
 
128
- interface CommentRow {
145
+ interface CommentRow extends Record<string, unknown> {
129
146
  author: string;
130
147
  text: string;
131
148
  likes: number;
@@ -144,9 +161,15 @@ cli({
144
161
  if (topCount > limit) break;
145
162
  limited.push(c);
146
163
  }
147
- return limited.map((c, i) => ({ rank: i + 1, ...c }));
164
+ return normalizeCommentRows(limited, {
165
+ platform: "xiaohongshu",
166
+ contentId: raw,
167
+ }).map((c, i) => ({ rank: i + 1, ...c }));
148
168
  }
149
169
 
150
- return all.slice(0, limit).map((c, i) => ({ rank: i + 1, ...c }));
170
+ return normalizeCommentRows(all.slice(0, limit), {
171
+ platform: "xiaohongshu",
172
+ contentId: raw,
173
+ }).map((c, i) => ({ rank: i + 1, ...c }));
151
174
  },
152
175
  });
@@ -7,16 +7,56 @@
7
7
 
8
8
  import { cli, Strategy } from "../../registry.js";
9
9
  import type { IPage } from "../../types.js";
10
- import { loadCookies, formatCookieHeader } from "../../engine/cookies.js";
10
+ import {
11
+ loadCookiesWithCDP,
12
+ formatCookieHeader,
13
+ } from "../../engine/cookies.js";
14
+ import { mkdir, writeFile } from "node:fs/promises";
15
+ import { join } from "node:path";
16
+ import { USER_AGENT } from "../../constants.js";
11
17
  import { parseNoteId, buildNoteUrl } from "./note-helpers.js";
12
18
 
13
19
  /** Build authenticated headers for Xiaohongshu downloads. */
14
- function buildCookieHeader(): string {
15
- const cookies = loadCookies("xiaohongshu");
20
+ async function buildCookieHeader(): Promise<string> {
21
+ const cookies = await loadCookiesWithCDP(
22
+ "xiaohongshu",
23
+ "www.xiaohongshu.com",
24
+ );
16
25
  if (cookies) return formatCookieHeader(cookies);
17
26
  return "";
18
27
  }
19
28
 
29
+ function extensionForMedia(type: string, url: string): string {
30
+ try {
31
+ const pathname = new URL(url).pathname;
32
+ const match = /\.[a-zA-Z0-9]{2,5}$/.exec(pathname);
33
+ if (match) return match[0].toLowerCase();
34
+ } catch {
35
+ return type === "video" ? ".mp4" : ".jpg";
36
+ }
37
+ return type === "video" ? ".mp4" : ".jpg";
38
+ }
39
+
40
+ async function downloadMedia(
41
+ url: string,
42
+ path: string,
43
+ cookieHeader: string,
44
+ ): Promise<void> {
45
+ const headers: Record<string, string> = {
46
+ "User-Agent": USER_AGENT,
47
+ Referer: "https://www.xiaohongshu.com/",
48
+ };
49
+ if (cookieHeader) headers.Cookie = cookieHeader;
50
+ const response = await fetch(url, { headers });
51
+ if (!response.ok) {
52
+ throw new Error(
53
+ `Xiaohongshu media download failed: HTTP ${response.status}`,
54
+ );
55
+ }
56
+ const bytes = Buffer.from(await response.arrayBuffer());
57
+ await writeFile(path, bytes);
58
+ }
59
+
20
60
  cli({
21
61
  site: "xiaohongshu",
22
62
  name: "download",
@@ -37,11 +77,12 @@ cli({
37
77
  description: "Output directory",
38
78
  },
39
79
  ],
40
- columns: ["index", "type", "url"],
80
+ columns: ["index", "type", "path", "url"],
41
81
  func: async (page, kwargs) => {
42
82
  const p = page as IPage;
43
83
  const rawInput = String(kwargs["note-id"]);
44
84
  const noteId = parseNoteId(rawInput);
85
+ const outputDir = String(kwargs.output ?? "./xiaohongshu-downloads");
45
86
 
46
87
  await p.goto(buildNoteUrl(rawInput));
47
88
  await p.wait(3);
@@ -158,13 +199,21 @@ cli({
158
199
  return [{ index: 0, type: "-", url: "No media found" }];
159
200
  }
160
201
 
161
- // Cookie header available for authenticated downloads when media pipeline is wired
162
- void buildCookieHeader();
202
+ await mkdir(outputDir, { recursive: true });
203
+ const cookieHeader = await buildCookieHeader();
163
204
 
164
- return data.media.map((m: { type: string; url: string }, idx: number) => ({
165
- index: idx + 1,
166
- type: m.type,
167
- url: m.url,
168
- }));
205
+ const rows = [];
206
+ for (const [idx, media] of data.media.entries()) {
207
+ const ext = extensionForMedia(media.type, media.url);
208
+ const path = join(outputDir, `${noteId}-${idx + 1}${ext}`);
209
+ await downloadMedia(media.url, path, cookieHeader);
210
+ rows.push({
211
+ index: idx + 1,
212
+ type: media.type,
213
+ path,
214
+ url: media.url,
215
+ });
216
+ }
217
+ return rows;
169
218
  },
170
219
  });