@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,209 @@
1
+ /**
2
+ * @owner src::adapters::crossref::works
3
+ * @does Registers Crossref REST work search and DOI lookup commands for publisher metadata.
4
+ * @needs api.crossref.org REST API, optional CROSSREF_MAILTO, src/registry.ts
5
+ * @feeds src/commands/scholar.ts via scholar.search and scholar.get
6
+ * @breaks Crossref response-shape drift or rate limiting surfaces as explicit adapter errors.
7
+ * @invariants DOI lookup accepts only DOI-shaped references; output maps to ScholarlyWorkRecord.
8
+ * @side-effects HTTPS egress to api.crossref.org only
9
+ * @perf O(limit) JSON mapping
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.crossref.org";
20
+
21
+ interface CrossrefPerson {
22
+ given?: unknown;
23
+ family?: unknown;
24
+ name?: unknown;
25
+ }
26
+
27
+ interface CrossrefItem {
28
+ DOI?: unknown;
29
+ title?: unknown[];
30
+ subtitle?: unknown[];
31
+ author?: CrossrefPerson[];
32
+ "container-title"?: unknown[];
33
+ issued?: { "date-parts"?: unknown[][] };
34
+ published?: { "date-parts"?: unknown[][] };
35
+ "is-referenced-by-count"?: unknown;
36
+ reference?: unknown[];
37
+ URL?: unknown;
38
+ type?: unknown;
39
+ abstract?: unknown;
40
+ }
41
+
42
+ function str(value: unknown): string {
43
+ return typeof value === "string" ? value.trim() : "";
44
+ }
45
+
46
+ function arrFirst(value: unknown): string {
47
+ return Array.isArray(value) ? str(value[0]) : str(value);
48
+ }
49
+
50
+ function num(value: unknown): number | undefined {
51
+ return typeof value === "number" && Number.isFinite(value)
52
+ ? value
53
+ : undefined;
54
+ }
55
+
56
+ function dateParts(item: CrossrefItem): unknown[] {
57
+ return (
58
+ item.issued?.["date-parts"]?.[0] ??
59
+ item.published?.["date-parts"]?.[0] ??
60
+ []
61
+ );
62
+ }
63
+
64
+ function year(item: CrossrefItem): number | undefined {
65
+ const first = dateParts(item)[0];
66
+ return typeof first === "number" && Number.isFinite(first)
67
+ ? first
68
+ : undefined;
69
+ }
70
+
71
+ function date(item: CrossrefItem): string | undefined {
72
+ const parts = dateParts(item).filter(
73
+ (part): part is number => typeof part === "number",
74
+ );
75
+ if (parts.length === 0) return undefined;
76
+ return [
77
+ String(parts[0]).padStart(4, "0"),
78
+ String(parts[1] ?? 1).padStart(2, "0"),
79
+ String(parts[2] ?? 1).padStart(2, "0"),
80
+ ].join("-");
81
+ }
82
+
83
+ function authors(value: CrossrefPerson[] | undefined): string[] | undefined {
84
+ if (!Array.isArray(value)) return undefined;
85
+ const out = value
86
+ .map(
87
+ (person) =>
88
+ str(person.name) ||
89
+ [person.given, person.family].map(str).filter(Boolean).join(" "),
90
+ )
91
+ .filter(Boolean);
92
+ return out.length > 0 ? out : undefined;
93
+ }
94
+
95
+ function bareDoi(value: unknown): string {
96
+ return str(value)
97
+ .replace(/^doi:/i, "")
98
+ .replace(/^https?:\/\/(?:dx\.)?doi\.org\//i, "");
99
+ }
100
+
101
+ export function requireCrossrefDoi(value: unknown): string {
102
+ const doi = bareDoi(value);
103
+ if (!/^10\.\S+\/\S+/.test(doi)) {
104
+ throw new Error(`crossref DOI "${String(value ?? "")}" is not recognised.`);
105
+ }
106
+ return doi;
107
+ }
108
+
109
+ function maybeMailto(params: URLSearchParams): void {
110
+ const mailto = process.env.CROSSREF_MAILTO?.trim();
111
+ if (mailto) params.set("mailto", mailto);
112
+ }
113
+
114
+ async function fetchCrossref(path: string, label: string): Promise<unknown> {
115
+ const response = await fetch(`${API}${path}`, {
116
+ headers: {
117
+ Accept: "application/json",
118
+ "User-Agent":
119
+ "unicli-crossref/1.0 (https://github.com/olo-dot-io/Uni-CLI)",
120
+ },
121
+ });
122
+ if (response.status === 404) throw new Error(`${label} returned no result.`);
123
+ if (response.status === 429) throw new Error(`${label} returned HTTP 429.`);
124
+ if (!response.ok)
125
+ throw new Error(`${label} returned HTTP ${response.status}.`);
126
+ return response.json();
127
+ }
128
+
129
+ export function mapCrossrefItem(
130
+ item: CrossrefItem,
131
+ source: string,
132
+ ): ScholarlyWorkRecord {
133
+ const doi = requireCrossrefDoi(item.DOI);
134
+ return {
135
+ id: doi,
136
+ title: arrFirst(item.title),
137
+ authors: authors(item.author),
138
+ year: year(item),
139
+ date: date(item),
140
+ venue: arrFirst(item["container-title"]) || undefined,
141
+ type: str(item.type) || undefined,
142
+ abstract: str(item.abstract).replace(/<[^>]+>/g, " ") || undefined,
143
+ doi,
144
+ cited_by_count: num(item["is-referenced-by-count"]),
145
+ references_count: Array.isArray(item.reference)
146
+ ? item.reference.length
147
+ : undefined,
148
+ source_adapter: source,
149
+ source_url: str(item.URL) || `https://doi.org/${doi}`,
150
+ retrieved_at: new Date().toISOString(),
151
+ };
152
+ }
153
+
154
+ cli({
155
+ site: "crossref",
156
+ name: "search",
157
+ description:
158
+ "Search Crossref Works by title, author, DOI, or bibliographic text",
159
+ domain: "api.crossref.org",
160
+ strategy: Strategy.PUBLIC,
161
+ args: [
162
+ { name: "query", type: "str", required: true, positional: true },
163
+ { name: "limit", type: "int", default: 20 },
164
+ ],
165
+ columns: ["id", "title", "authors", "year", "venue", "doi", "source_url"],
166
+ capabilities: ["http.fetch", "scholar.search"],
167
+ func: async (_page, kwargs) => {
168
+ const query = String(kwargs.query ?? "").trim();
169
+ if (!query) throw new Error("crossref search query cannot be empty.");
170
+ const limit = Math.min(Math.max(Number(kwargs.limit ?? 20), 1), 100);
171
+ const params = new URLSearchParams({ query, rows: String(limit) });
172
+ maybeMailto(params);
173
+ const body = (await fetchCrossref(
174
+ `/works?${params.toString()}`,
175
+ "crossref search",
176
+ )) as {
177
+ message?: { items?: CrossrefItem[] };
178
+ };
179
+ const rows = (body.message?.items ?? []).map((item) =>
180
+ mapCrossrefItem(item, "crossref"),
181
+ );
182
+ if (rows.length === 0)
183
+ throw new Error(`No Crossref works matched "${query}".`);
184
+ return rows;
185
+ },
186
+ });
187
+
188
+ cli({
189
+ site: "crossref",
190
+ name: "work",
191
+ description: "Fetch one Crossref Work by DOI",
192
+ domain: "api.crossref.org",
193
+ strategy: Strategy.PUBLIC,
194
+ args: [{ name: "doi", type: "str", required: true, positional: true }],
195
+ columns: ["id", "title", "authors", "year", "venue", "doi", "source_url"],
196
+ capabilities: ["http.fetch", "scholar.get"],
197
+ func: async (_page, kwargs) => {
198
+ const doi = requireCrossrefDoi(kwargs.doi ?? kwargs.id ?? kwargs.ref);
199
+ const params = new URLSearchParams();
200
+ maybeMailto(params);
201
+ const suffix = params.size > 0 ? `?${params.toString()}` : "";
202
+ const body = (await fetchCrossref(
203
+ `/works/${encodeURIComponent(doi)}${suffix}`,
204
+ `crossref work ${doi}`,
205
+ )) as { message?: CrossrefItem };
206
+ if (!body.message) throw new Error(`Crossref returned no work for ${doi}.`);
207
+ return [mapCrossrefItem(body.message, "crossref")];
208
+ },
209
+ });
@@ -0,0 +1,136 @@
1
+ /**
2
+ * @owner src::adapters::cvf::papers
3
+ * @does Registers CVF OpenAccess conference paper search for CVPR/ICCV/ECCV-style proceedings pages.
4
+ * @needs openaccess.thecvf.com static proceedings HTML, src/registry.ts
5
+ * @feeds src/commands/scholar.ts via scholar.search, scholar.pdf, and scholar.venue
6
+ * @breaks CVF markup drift surfaces as empty/parse errors rather than non-CVF fallbacks.
7
+ * @invariants Venue/year map to explicit CVF event pages; PDF URLs are absolutized against openaccess.thecvf.com.
8
+ * @side-effects HTTPS egress to openaccess.thecvf.com only
9
+ * @perf O(N) over one proceedings HTML page
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 ORIGIN = "https://openaccess.thecvf.com";
20
+
21
+ function decode(value: string): string {
22
+ return value
23
+ .replace(/&amp;/g, "&")
24
+ .replace(/&lt;/g, "<")
25
+ .replace(/&gt;/g, ">")
26
+ .replace(/&quot;/g, '"')
27
+ .replace(/&#39;/g, "'")
28
+ .replace(/\s+/g, " ")
29
+ .trim();
30
+ }
31
+
32
+ function absolute(path: string): string {
33
+ return /^https?:\/\//i.test(path)
34
+ ? path
35
+ : `${ORIGIN}${path.startsWith("/") ? "" : "/"}${path}`;
36
+ }
37
+
38
+ function eventId(venue: unknown, year: unknown): string {
39
+ const v = String(venue ?? "CVPR")
40
+ .trim()
41
+ .toUpperCase();
42
+ const y = String(year ?? "").trim();
43
+ if (!/^(CVPR|ICCV|ECCV|WACV)$/.test(v))
44
+ throw new Error(`unsupported CVF venue: ${v}`);
45
+ if (!/^\d{4}$/.test(y)) throw new Error(`cvf year "${y}" is not valid.`);
46
+ return `${v}${y}`;
47
+ }
48
+
49
+ export function parseCvfRows(
50
+ html: string,
51
+ event = "CVPR2024",
52
+ ): ScholarlyWorkRecord[] {
53
+ const out: ScholarlyWorkRecord[] = [];
54
+ const re =
55
+ /<dt class="ptitle">[\s\S]*?<a href="([^"]+)">([\s\S]*?)<\/a><\/dt>([\s\S]*?)(?=<dt class="ptitle">|$)/g;
56
+ let match: RegExpExecArray | null;
57
+ while ((match = re.exec(html)) !== null) {
58
+ const sourceUrl = absolute(match[1]);
59
+ const title = decode(match[2].replace(/<[^>]+>/g, " "));
60
+ const block = match[3];
61
+ const pdf = block.match(/<a href="([^"]+\.pdf)">pdf<\/a>/i)?.[1] ?? "";
62
+ const authorText = block
63
+ .replace(/\[[\s\S]*?\]/g, " ")
64
+ .replace(/<form[\s\S]*?<\/form>/g, " ")
65
+ .replace(/<[^>]+>/g, " ");
66
+ const authors = decode(authorText)
67
+ .split(",")
68
+ .map((author) => author.trim())
69
+ .filter(Boolean);
70
+ out.push({
71
+ id:
72
+ sourceUrl
73
+ .split("/")
74
+ .pop()
75
+ ?.replace(/\.html$/, "") ?? title,
76
+ title,
77
+ authors: authors.length > 0 ? authors : undefined,
78
+ year: Number(event.slice(-4)),
79
+ venue: event.replace(/\d{4}$/, ""),
80
+ pdf_url: pdf ? absolute(pdf) : undefined,
81
+ source_adapter: "cvf",
82
+ source_url: sourceUrl,
83
+ retrieved_at: new Date().toISOString(),
84
+ });
85
+ }
86
+ return out;
87
+ }
88
+
89
+ cli({
90
+ site: "cvf",
91
+ name: "search",
92
+ description: "Search CVF OpenAccess proceedings (CVPR/ICCV/ECCV/WACV)",
93
+ domain: "openaccess.thecvf.com",
94
+ strategy: Strategy.PUBLIC,
95
+ args: [
96
+ { name: "query", type: "str", required: true, positional: true },
97
+ { name: "venue", type: "str", default: "CVPR" },
98
+ { name: "year", type: "str", default: "2024" },
99
+ { name: "limit", type: "int", default: 20 },
100
+ ],
101
+ columns: ["id", "title", "authors", "year", "venue", "pdf_url", "source_url"],
102
+ capabilities: [
103
+ "http.fetch",
104
+ "scholar.search",
105
+ "scholar.venue",
106
+ "scholar.pdf",
107
+ ],
108
+ func: async (_page, kwargs) => {
109
+ const query = String(kwargs.query ?? "")
110
+ .trim()
111
+ .toLowerCase();
112
+ if (!query) throw new Error("cvf search query cannot be empty.");
113
+ const event = eventId(kwargs.venue, kwargs.year);
114
+ const response = await fetch(`${ORIGIN}/${event}?day=all`, {
115
+ headers: {
116
+ Accept: "*/*",
117
+ "User-Agent": "unicli-cvf/1.0 (https://github.com/olo-dot-io/Uni-CLI)",
118
+ },
119
+ });
120
+ if (response.status === 404)
121
+ throw new Error(`CVF ${event} returned no proceedings page.`);
122
+ if (!response.ok)
123
+ throw new Error(`CVF ${event} returned HTTP ${response.status}.`);
124
+ const limit = Math.min(Math.max(Number(kwargs.limit ?? 20), 1), 200);
125
+ const rows = parseCvfRows(await response.text(), event)
126
+ .filter((row) =>
127
+ `${row.title} ${row.authors?.join(" ") ?? ""}`
128
+ .toLowerCase()
129
+ .includes(query),
130
+ )
131
+ .slice(0, limit);
132
+ if (rows.length === 0)
133
+ throw new Error(`No CVF ${event} papers matched "${query}".`);
134
+ return rows;
135
+ },
136
+ });
@@ -332,6 +332,7 @@ cli({
332
332
  "doi",
333
333
  "url",
334
334
  ],
335
+ capabilities: ["http.fetch", "scholar.search"],
335
336
  func: async (_page, kwargs) => {
336
337
  const query = requireDblpQuery(kwargs.query);
337
338
  const limit = requireDblpLimit(kwargs.limit, 20, 100);
@@ -375,6 +376,7 @@ cli({
375
376
  "open_access_url",
376
377
  "dblp_url",
377
378
  ],
379
+ capabilities: ["http.fetch", "scholar.get", "scholar.pdf"],
378
380
  func: async (_page, kwargs) => {
379
381
  const key = requireRecordKey(kwargs.key);
380
382
  const xml = await fetchDblpXml(
@@ -406,6 +408,7 @@ cli({
406
408
  { name: "limit", type: "int", default: 20, description: "Max venues" },
407
409
  ],
408
410
  columns: ["rank", "acronym", "venue", "type", "url"],
411
+ capabilities: ["http.fetch", "scholar.venue"],
409
412
  func: async (_page, kwargs) => {
410
413
  const query = requireDblpQuery(kwargs.query);
411
414
  const limit = requireDblpLimit(kwargs.limit, 20, 100);
@@ -455,6 +458,7 @@ cli({
455
458
  "pid",
456
459
  "url",
457
460
  ],
461
+ capabilities: ["http.fetch", "scholar.author", "scholar.search"],
458
462
  func: async (_page, kwargs) => {
459
463
  const limit = requireDblpLimit(kwargs.limit, 20, 200);
460
464
  let pid = kwargs.pid ? requirePid(kwargs.pid) : "";
@@ -0,0 +1,67 @@
1
+ # @owner src::adapters::dpma::get
2
+ # @does Fetch a German patent record by publication number via DPMAconnectPlus REST.
3
+ # @needs src/engine/steps/fetch.ts, src/engine/steps/select-xml.ts, src/engine/steps/map.ts
4
+ # @feeds src/commands/patent.ts
5
+ # @breaks throws PipelineError on 401/403, 404, 5xx
6
+ # @invariants output row conforms to PatentRecord
7
+ # @side-effects reads env DPMA_AUTHORIZATION; HTTPS egress to dpmaconnect.dpma.de
8
+ # @perf single request
9
+ # @concurrency safe
10
+ # @test none yet
11
+ # @stability stable
12
+ # @since 2026-05-18
13
+ # @verification blocked-by-subscription
14
+ site: dpma
15
+ name: get
16
+ description: Fetch a German patent record by publication number (subscription)
17
+ domain: dpmaconnect.dpma.de
18
+ type: web-api
19
+ strategy: public
20
+ lint_listing_detail: skip
21
+
22
+ args:
23
+ publication_number:
24
+ type: str
25
+ required: true
26
+ positional: true
27
+ description: German publication number (e.g. DE102023012345)
28
+
29
+ pipeline:
30
+ - fetch:
31
+ url: "https://dpmaconnect.dpma.de/dpmaconnectplus/rest/document/${{ args.publication_number | urlencode }}"
32
+ method: GET
33
+ headers:
34
+ Accept: application/xml
35
+ Authorization: "${{ env.DPMA_AUTHORIZATION || '' }}"
36
+
37
+ - select-xml:
38
+ xpath: "//record"
39
+ unwrap_single: true
40
+
41
+ - map:
42
+ publication_number: "${{ 'DE-' + (item.publicationNumber || args.publication_number || '') + '-' + (item.kindCode || '') }}"
43
+ application_number: "${{ item.applicationNumber || '' }}"
44
+ title: "${{ item.title || item.titleDe || item.titleEn || '' }}"
45
+ abstract: "${{ item.abstract || item.abstractDe || item.abstractEn || '' }}"
46
+ kind_code: "${{ item.kindCode || '' }}"
47
+ filing_date: "${{ item.filingDate || '' }}"
48
+ publication_date: "${{ item.publicationDate || '' }}"
49
+ grant_date: "${{ item.grantDate || '' }}"
50
+ priority_date: "${{ item.priorityDate || '' }}"
51
+ legal_status: "${{ item.legalStatus || item.status || '' }}"
52
+ inventors: "${{ JSON.stringify((function(){ var i=item.inventor || item.inventors; if(!i) return []; var arr = Array.isArray(i) ? i : [i]; return arr.map(n => ({ name: typeof n === 'string' ? n : (n.name || n.fullName || ''), country: 'DE' })).filter(x => x.name); })()) }}"
53
+ assignees: "${{ JSON.stringify((function(){ var a=item.applicant || item.applicants; if(!a) return []; var arr = Array.isArray(a) ? a : [a]; return arr.map(n => ({ name: typeof n === 'string' ? n : (n.name || n.fullName || ''), country: 'DE' })).filter(x => x.name); })()) }}"
54
+ classifications: "${{ JSON.stringify((function(){ var c=item.ipc || item.classifications; if(!c) return []; var arr = Array.isArray(c) ? c : [c]; return arr.map(x => ({ scheme: 'ipc', code: typeof x === 'string' ? x : (x.code || '') })).filter(x => x.code); })()) }}"
55
+ source_adapter: dpma
56
+ source_url: "${{ 'https://register.dpma.de/DPMAregister/pat/register?AKZ=' + (item.applicationNumber || '') }}"
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,77 @@
1
+ # @owner src::adapters::dpma::search
2
+ # @does Search German patents via the DPMAconnectPlus REST API (XML / OAI-PMH-style envelope).
3
+ # @needs src/engine/steps/fetch.ts, src/engine/steps/select-xml.ts, src/engine/steps/map.ts, src/engine/steps/limit.ts
4
+ # @feeds src/commands/patent.ts
5
+ # @breaks throws PipelineError on 401/403 (missing DPMA_AUTHORIZATION precomputed `Basic <base64>` header), 4xx, 5xx
6
+ # @invariants output rows conform to PatentRecord; publication_number is `DE-<doc>-<kind>`
7
+ # @side-effects reads env DPMA_AUTHORIZATION (precomputed `Basic <base64(user:pass)>`); HTTPS egress to dpmaconnect.dpma.de
8
+ # @perf single request
9
+ # @concurrency safe
10
+ # @test none yet
11
+ # @stability stable
12
+ # @since 2026-05-18
13
+ # @verification blocked-by-subscription — DPMAconnectPlus requires a paid connection contract (~200 EUR setup). Adapter ships so contracted users can run it; precompute `DPMA_AUTHORIZATION="Basic $(printf '%s:%s' "$USER" "$PASS" | base64)"` before invocation.
14
+ site: dpma
15
+ name: search
16
+ description: Search German patents via DPMAconnectPlus REST (subscription)
17
+ domain: dpmaconnect.dpma.de
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: DPMA query (free-text, mapped to title/abstract)
28
+ limit:
29
+ type: int
30
+ default: 25
31
+ description: Maximum results
32
+
33
+ pipeline:
34
+ - fetch:
35
+ url: "https://dpmaconnect.dpma.de/dpmaconnectplus/rest/search/published"
36
+ method: GET
37
+ headers:
38
+ Accept: application/xml
39
+ Authorization: "${{ env.DPMA_AUTHORIZATION || '' }}"
40
+ params:
41
+ query: "${{ args.query }}"
42
+ maximumRecords: "${{ args.limit }}"
43
+ startRecord: "1"
44
+
45
+ - select-xml:
46
+ xpath: "//record"
47
+
48
+ # DPMAconnectPlus XML mirrors INPI / EPO field naming; preserve German
49
+ # script in title / abstract.
50
+ - map:
51
+ publication_number: "${{ 'DE-' + (item.publicationNumber || '') + '-' + (item.kindCode || '') }}"
52
+ application_number: "${{ item.applicationNumber || '' }}"
53
+ title: "${{ item.title || item.titleDe || item.titleEn || '' }}"
54
+ abstract: "${{ item.abstract || item.abstractDe || item.abstractEn || '' }}"
55
+ kind_code: "${{ item.kindCode || '' }}"
56
+ filing_date: "${{ item.filingDate || '' }}"
57
+ publication_date: "${{ item.publicationDate || '' }}"
58
+ grant_date: "${{ item.grantDate || '' }}"
59
+ priority_date: "${{ item.priorityDate || '' }}"
60
+ inventors: "${{ JSON.stringify((function(){ var i=item.inventor || item.inventors; if(!i) return []; var arr = Array.isArray(i) ? i : [i]; return arr.map(n => ({ name: typeof n === 'string' ? n : (n.name || n.fullName || ''), country: 'DE' })).filter(x => x.name); })()) }}"
61
+ assignees: "${{ JSON.stringify((function(){ var a=item.applicant || item.applicants; if(!a) return []; var arr = Array.isArray(a) ? a : [a]; return arr.map(n => ({ name: typeof n === 'string' ? n : (n.name || n.fullName || ''), country: 'DE' })).filter(x => x.name); })()) }}"
62
+ classifications: "${{ JSON.stringify((function(){ var c=item.ipc || item.classifications; if(!c) return []; var arr = Array.isArray(c) ? c : [c]; return arr.map(x => ({ scheme: 'ipc', code: typeof x === 'string' ? x : (x.code || '') })).filter(x => x.code); })()) }}"
63
+ source_adapter: dpma
64
+ source_url: "${{ 'https://register.dpma.de/DPMAregister/pat/register?AKZ=' + (item.applicationNumber || '') }}"
65
+ retrieved_at: ""
66
+
67
+ - limit: "${{ args.limit }}"
68
+
69
+ columns: [publication_number, title, filing_date, publication_date]
70
+
71
+ # schema-v2 metadata
72
+ capabilities: ["http.fetch", "patent.search"]
73
+ minimum_capability: http.fetch
74
+ trust: public
75
+ confidentiality: public
76
+ quarantine: false
77
+ schema_version: v2
@@ -0,0 +1,54 @@
1
+ # DuckDuckGo Search — keyless HTML lite endpoint.
2
+ #
3
+ # verification_status: keyless-best-effort
4
+ #
5
+ # DuckDuckGo runs an Instant-Answer JSON API at api.duckduckgo.com that
6
+ # returns disambiguation pages and zero web results, plus a lite HTML
7
+ # search at https://html.duckduckgo.com/html that returns SSR result rows
8
+ # without JS. We use the lite HTML path so a fresh user gets web results
9
+ # with no token of any kind. DDG rate-limits aggressive scraping; the
10
+ # adapter is for human-scale interactive use.
11
+ site: duckduckgo
12
+ name: search
13
+ description: Search the public web via DuckDuckGo (no API key needed)
14
+ type: web-api
15
+ domain: html.duckduckgo.com
16
+ strategy: public
17
+ lint_listing_detail: skip
18
+
19
+ args:
20
+ query:
21
+ type: str
22
+ required: true
23
+ positional: true
24
+ description: Free-text web search query
25
+ limit:
26
+ type: int
27
+ default: 10
28
+ description: Maximum results returned (DDG lite caps at ~30 per page)
29
+
30
+ pipeline:
31
+ - fetch_text:
32
+ url: "https://html.duckduckgo.com/html/?q=${{ args.query | url_encode }}"
33
+ headers:
34
+ User-Agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
35
+ Accept: "text/html,application/xhtml+xml"
36
+
37
+ - extract:
38
+ selector: "div.result"
39
+ fields:
40
+ title: "h2.result__title a"
41
+ url: "h2.result__title a@href"
42
+ snippet: "a.result__snippet"
43
+
44
+ - limit: ${{ args.limit }}
45
+
46
+ columns: [title, url, snippet]
47
+
48
+ # schema-v2 metadata
49
+ capabilities: ["http.fetch"]
50
+ minimum_capability: http.fetch
51
+ trust: public
52
+ confidentiality: public
53
+ quarantine: false
54
+ schema_version: v2
@@ -0,0 +1,52 @@
1
+ # DuckDuckGo Autocomplete — keyless JSON endpoint.
2
+ #
3
+ # verification_status: keyless-best-effort
4
+ #
5
+ # The autocomplete endpoint at https://duckduckgo.com/ac is the JSON used
6
+ # by the DDG search box. No auth, no rate-limit gate at low volumes, and
7
+ # returns a flat list of suggested completions for a prefix.
8
+ site: duckduckgo
9
+ name: suggest
10
+ description: Get query autocompletion suggestions from DuckDuckGo
11
+ type: web-api
12
+ domain: duckduckgo.com
13
+ strategy: public
14
+ lint_listing_detail: skip
15
+
16
+ args:
17
+ query:
18
+ type: str
19
+ required: true
20
+ positional: true
21
+ description: Partial query prefix to autocomplete
22
+ limit:
23
+ type: int
24
+ default: 10
25
+ description: Maximum suggestions returned
26
+
27
+ pipeline:
28
+ - fetch:
29
+ url: "https://duckduckgo.com/ac/"
30
+ params:
31
+ q: "${{ args.query }}"
32
+ type: list
33
+ headers:
34
+ User-Agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
35
+ Accept: "application/json"
36
+
37
+ - select: "1"
38
+
39
+ - map:
40
+ phrase: "${{ item }}"
41
+
42
+ - limit: ${{ args.limit }}
43
+
44
+ columns: [phrase]
45
+
46
+ # schema-v2 metadata
47
+ capabilities: ["http.fetch"]
48
+ minimum_capability: http.fetch
49
+ trust: public
50
+ confidentiality: public
51
+ quarantine: false
52
+ schema_version: v2