@zenalexa/unicli 0.220.1 → 0.221.0

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 (471) hide show
  1. package/AGENTS.md +28 -6
  2. package/README.md +8 -8
  3. package/README.zh-CN.md +8 -8
  4. package/dist/adapters/bilibili/comments.js +66 -4
  5. package/dist/adapters/bilibili/comments.js.map +1 -1
  6. package/dist/adapters/bilibili/compat.js +2 -2
  7. package/dist/adapters/bilibili/compat.js.map +1 -1
  8. package/dist/adapters/bilibili/download.js +4 -4
  9. package/dist/adapters/bilibili/download.js.map +1 -1
  10. package/dist/adapters/bilibili/wbi.d.ts.map +1 -1
  11. package/dist/adapters/bilibili/wbi.js +3 -3
  12. package/dist/adapters/bilibili/wbi.js.map +1 -1
  13. package/dist/adapters/cipo/_shared.d.ts +21 -0
  14. package/dist/adapters/cipo/_shared.d.ts.map +1 -0
  15. package/dist/adapters/cipo/_shared.js +67 -0
  16. package/dist/adapters/cipo/_shared.js.map +1 -0
  17. package/dist/adapters/cipo/get.d.ts +19 -0
  18. package/dist/adapters/cipo/get.d.ts.map +1 -0
  19. package/dist/adapters/cipo/get.js +140 -0
  20. package/dist/adapters/cipo/get.js.map +1 -0
  21. package/dist/adapters/cipo/legal-status.d.ts +19 -0
  22. package/dist/adapters/cipo/legal-status.d.ts.map +1 -0
  23. package/dist/adapters/cipo/legal-status.js +111 -0
  24. package/dist/adapters/cipo/legal-status.js.map +1 -0
  25. package/dist/adapters/cipo/search.d.ts +20 -0
  26. package/dist/adapters/cipo/search.d.ts.map +1 -0
  27. package/dist/adapters/cipo/search.js +148 -0
  28. package/dist/adapters/cipo/search.js.map +1 -0
  29. package/dist/adapters/cnipa/_shared.d.ts +47 -0
  30. package/dist/adapters/cnipa/_shared.d.ts.map +1 -0
  31. package/dist/adapters/cnipa/_shared.js +97 -0
  32. package/dist/adapters/cnipa/_shared.js.map +1 -0
  33. package/dist/adapters/cnipa/get.d.ts +19 -0
  34. package/dist/adapters/cnipa/get.d.ts.map +1 -0
  35. package/dist/adapters/cnipa/get.js +149 -0
  36. package/dist/adapters/cnipa/get.js.map +1 -0
  37. package/dist/adapters/cnipa/legal-status.d.ts +19 -0
  38. package/dist/adapters/cnipa/legal-status.d.ts.map +1 -0
  39. package/dist/adapters/cnipa/legal-status.js +119 -0
  40. package/dist/adapters/cnipa/legal-status.js.map +1 -0
  41. package/dist/adapters/cnipa/search.d.ts +21 -0
  42. package/dist/adapters/cnipa/search.d.ts.map +1 -0
  43. package/dist/adapters/cnipa/search.js +170 -0
  44. package/dist/adapters/cnipa/search.js.map +1 -0
  45. package/dist/adapters/espacenet/_shared.d.ts +21 -0
  46. package/dist/adapters/espacenet/_shared.d.ts.map +1 -0
  47. package/dist/adapters/espacenet/_shared.js +67 -0
  48. package/dist/adapters/espacenet/_shared.js.map +1 -0
  49. package/dist/adapters/espacenet/family.d.ts +19 -0
  50. package/dist/adapters/espacenet/family.d.ts.map +1 -0
  51. package/dist/adapters/espacenet/family.js +118 -0
  52. package/dist/adapters/espacenet/family.js.map +1 -0
  53. package/dist/adapters/espacenet/get.d.ts +19 -0
  54. package/dist/adapters/espacenet/get.d.ts.map +1 -0
  55. package/dist/adapters/espacenet/get.js +130 -0
  56. package/dist/adapters/espacenet/get.js.map +1 -0
  57. package/dist/adapters/espacenet/legal-status.d.ts +19 -0
  58. package/dist/adapters/espacenet/legal-status.d.ts.map +1 -0
  59. package/dist/adapters/espacenet/legal-status.js +110 -0
  60. package/dist/adapters/espacenet/legal-status.js.map +1 -0
  61. package/dist/adapters/espacenet/search.d.ts +20 -0
  62. package/dist/adapters/espacenet/search.d.ts.map +1 -0
  63. package/dist/adapters/espacenet/search.js +165 -0
  64. package/dist/adapters/espacenet/search.js.map +1 -0
  65. package/dist/adapters/facebook/subtitles.d.ts +9 -0
  66. package/dist/adapters/facebook/subtitles.d.ts.map +1 -0
  67. package/dist/adapters/facebook/subtitles.js +42 -0
  68. package/dist/adapters/facebook/subtitles.js.map +1 -0
  69. package/dist/adapters/fips/_shared.d.ts +21 -0
  70. package/dist/adapters/fips/_shared.d.ts.map +1 -0
  71. package/dist/adapters/fips/_shared.js +77 -0
  72. package/dist/adapters/fips/_shared.js.map +1 -0
  73. package/dist/adapters/fips/get.d.ts +19 -0
  74. package/dist/adapters/fips/get.d.ts.map +1 -0
  75. package/dist/adapters/fips/get.js +139 -0
  76. package/dist/adapters/fips/get.js.map +1 -0
  77. package/dist/adapters/fips/search.d.ts +20 -0
  78. package/dist/adapters/fips/search.d.ts.map +1 -0
  79. package/dist/adapters/fips/search.js +148 -0
  80. package/dist/adapters/fips/search.js.map +1 -0
  81. package/dist/adapters/freepatentsonline-web/_shared.d.ts +72 -0
  82. package/dist/adapters/freepatentsonline-web/_shared.d.ts.map +1 -0
  83. package/dist/adapters/freepatentsonline-web/_shared.js +216 -0
  84. package/dist/adapters/freepatentsonline-web/_shared.js.map +1 -0
  85. package/dist/adapters/freepatentsonline-web/get.d.ts +21 -0
  86. package/dist/adapters/freepatentsonline-web/get.d.ts.map +1 -0
  87. package/dist/adapters/freepatentsonline-web/get.js +127 -0
  88. package/dist/adapters/freepatentsonline-web/get.js.map +1 -0
  89. package/dist/adapters/freepatentsonline-web/search.d.ts +22 -0
  90. package/dist/adapters/freepatentsonline-web/search.d.ts.map +1 -0
  91. package/dist/adapters/freepatentsonline-web/search.js +149 -0
  92. package/dist/adapters/freepatentsonline-web/search.js.map +1 -0
  93. package/dist/adapters/google-patents-web/_shared.d.ts +110 -0
  94. package/dist/adapters/google-patents-web/_shared.d.ts.map +1 -0
  95. package/dist/adapters/google-patents-web/_shared.js +164 -0
  96. package/dist/adapters/google-patents-web/_shared.js.map +1 -0
  97. package/dist/adapters/google-patents-web/get.d.ts +36 -0
  98. package/dist/adapters/google-patents-web/get.d.ts.map +1 -0
  99. package/dist/adapters/google-patents-web/get.js +187 -0
  100. package/dist/adapters/google-patents-web/get.js.map +1 -0
  101. package/dist/adapters/google-patents-web/search.d.ts +23 -0
  102. package/dist/adapters/google-patents-web/search.d.ts.map +1 -0
  103. package/dist/adapters/google-patents-web/search.js +169 -0
  104. package/dist/adapters/google-patents-web/search.js.map +1 -0
  105. package/dist/adapters/inpi-br/_shared.d.ts +21 -0
  106. package/dist/adapters/inpi-br/_shared.d.ts.map +1 -0
  107. package/dist/adapters/inpi-br/_shared.js +67 -0
  108. package/dist/adapters/inpi-br/_shared.js.map +1 -0
  109. package/dist/adapters/inpi-br/get.d.ts +19 -0
  110. package/dist/adapters/inpi-br/get.d.ts.map +1 -0
  111. package/dist/adapters/inpi-br/get.js +142 -0
  112. package/dist/adapters/inpi-br/get.js.map +1 -0
  113. package/dist/adapters/inpi-br/search.d.ts +20 -0
  114. package/dist/adapters/inpi-br/search.d.ts.map +1 -0
  115. package/dist/adapters/inpi-br/search.js +154 -0
  116. package/dist/adapters/inpi-br/search.js.map +1 -0
  117. package/dist/adapters/instagram/subtitles.d.ts +9 -0
  118. package/dist/adapters/instagram/subtitles.d.ts.map +1 -0
  119. package/dist/adapters/instagram/subtitles.js +42 -0
  120. package/dist/adapters/instagram/subtitles.js.map +1 -0
  121. package/dist/adapters/mastodon/statuses.d.ts +40 -0
  122. package/dist/adapters/mastodon/statuses.d.ts.map +1 -0
  123. package/dist/adapters/mastodon/statuses.js +153 -0
  124. package/dist/adapters/mastodon/statuses.js.map +1 -0
  125. package/dist/adapters/reddit/comments.d.ts +9 -0
  126. package/dist/adapters/reddit/comments.d.ts.map +1 -0
  127. package/dist/adapters/reddit/comments.js +124 -0
  128. package/dist/adapters/reddit/comments.js.map +1 -0
  129. package/dist/adapters/threads/post.d.ts +32 -0
  130. package/dist/adapters/threads/post.d.ts.map +1 -0
  131. package/dist/adapters/threads/post.js +287 -0
  132. package/dist/adapters/threads/post.js.map +1 -0
  133. package/dist/adapters/tiktok/subtitles.d.ts +9 -0
  134. package/dist/adapters/tiktok/subtitles.d.ts.map +1 -0
  135. package/dist/adapters/tiktok/subtitles.js +42 -0
  136. package/dist/adapters/tiktok/subtitles.js.map +1 -0
  137. package/dist/adapters/twitter/accept.js +2 -2
  138. package/dist/adapters/twitter/accept.js.map +1 -1
  139. package/dist/adapters/twitter/browser-fallback.d.ts +26 -0
  140. package/dist/adapters/twitter/browser-fallback.d.ts.map +1 -0
  141. package/dist/adapters/twitter/browser-fallback.js +93 -0
  142. package/dist/adapters/twitter/browser-fallback.js.map +1 -0
  143. package/dist/adapters/twitter/browser-state.d.ts +11 -0
  144. package/dist/adapters/twitter/browser-state.d.ts.map +1 -0
  145. package/dist/adapters/twitter/browser-state.js +46 -0
  146. package/dist/adapters/twitter/browser-state.js.map +1 -0
  147. package/dist/adapters/twitter/client.d.ts.map +1 -1
  148. package/dist/adapters/twitter/client.js +36 -13
  149. package/dist/adapters/twitter/client.js.map +1 -1
  150. package/dist/adapters/twitter/reply-dm.js +2 -2
  151. package/dist/adapters/twitter/reply-dm.js.map +1 -1
  152. package/dist/adapters/twitter/reply.js +1 -0
  153. package/dist/adapters/twitter/reply.js.map +1 -1
  154. package/dist/adapters/twitter/search.js +11 -18
  155. package/dist/adapters/twitter/search.js.map +1 -1
  156. package/dist/adapters/twitter/thread.d.ts +14 -0
  157. package/dist/adapters/twitter/thread.d.ts.map +1 -1
  158. package/dist/adapters/twitter/thread.js +28 -2
  159. package/dist/adapters/twitter/thread.js.map +1 -1
  160. package/dist/adapters/twitter/trending.js +13 -59
  161. package/dist/adapters/twitter/trending.js.map +1 -1
  162. package/dist/adapters/xiaohongshu/browser-state.d.ts +19 -0
  163. package/dist/adapters/xiaohongshu/browser-state.d.ts.map +1 -0
  164. package/dist/adapters/xiaohongshu/browser-state.js +67 -0
  165. package/dist/adapters/xiaohongshu/browser-state.js.map +1 -0
  166. package/dist/adapters/xiaohongshu/comments.js +28 -5
  167. package/dist/adapters/xiaohongshu/comments.js.map +1 -1
  168. package/dist/adapters/xiaohongshu/download.js +49 -11
  169. package/dist/adapters/xiaohongshu/download.js.map +1 -1
  170. package/dist/adapters/xiaohongshu/search.d.ts.map +1 -1
  171. package/dist/adapters/xiaohongshu/search.js +11 -5
  172. package/dist/adapters/xiaohongshu/search.js.map +1 -1
  173. package/dist/adapters/xiaohongshu/trending.d.ts +9 -0
  174. package/dist/adapters/xiaohongshu/trending.d.ts.map +1 -0
  175. package/dist/adapters/xiaohongshu/trending.js +94 -0
  176. package/dist/adapters/xiaohongshu/trending.js.map +1 -0
  177. package/dist/adapters/youtube/comments.d.ts +80 -0
  178. package/dist/adapters/youtube/comments.d.ts.map +1 -1
  179. package/dist/adapters/youtube/comments.js +108 -12
  180. package/dist/adapters/youtube/comments.js.map +1 -1
  181. package/dist/adapters/youtube/subtitles.d.ts +9 -0
  182. package/dist/adapters/youtube/subtitles.d.ts.map +1 -0
  183. package/dist/adapters/youtube/subtitles.js +42 -0
  184. package/dist/adapters/youtube/subtitles.js.map +1 -0
  185. package/dist/adapters/yt-dlp/subtitles.d.ts +9 -0
  186. package/dist/adapters/yt-dlp/subtitles.d.ts.map +1 -0
  187. package/dist/adapters/yt-dlp/subtitles.js +41 -0
  188. package/dist/adapters/yt-dlp/subtitles.js.map +1 -0
  189. package/dist/adapters/zhihu/answer-detail.d.ts +39 -0
  190. package/dist/adapters/zhihu/answer-detail.d.ts.map +1 -0
  191. package/dist/adapters/zhihu/answer-detail.js +204 -0
  192. package/dist/adapters/zhihu/answer-detail.js.map +1 -0
  193. package/dist/adapters/zhihu/comment.d.ts +9 -0
  194. package/dist/adapters/zhihu/comment.d.ts.map +1 -0
  195. package/dist/adapters/zhihu/comment.js +149 -0
  196. package/dist/adapters/zhihu/comment.js.map +1 -0
  197. package/dist/adapters/zhihu/recommend.d.ts +36 -0
  198. package/dist/adapters/zhihu/recommend.d.ts.map +1 -0
  199. package/dist/adapters/zhihu/recommend.js +151 -0
  200. package/dist/adapters/zhihu/recommend.js.map +1 -0
  201. package/dist/browser/bridge.d.ts.map +1 -1
  202. package/dist/browser/bridge.js +14 -3
  203. package/dist/browser/bridge.js.map +1 -1
  204. package/dist/browser/daemon-client.d.ts +6 -0
  205. package/dist/browser/daemon-client.d.ts.map +1 -1
  206. package/dist/browser/daemon-client.js +75 -15
  207. package/dist/browser/daemon-client.js.map +1 -1
  208. package/dist/browser/daemon.js +39 -15
  209. package/dist/browser/daemon.js.map +1 -1
  210. package/dist/browser/protocol.d.ts +1 -0
  211. package/dist/browser/protocol.d.ts.map +1 -1
  212. package/dist/browser/protocol.js +1 -0
  213. package/dist/browser/protocol.js.map +1 -1
  214. package/dist/cli.d.ts.map +1 -1
  215. package/dist/cli.js +6 -0
  216. package/dist/cli.js.map +1 -1
  217. package/dist/commands/approvals.d.ts.map +1 -1
  218. package/dist/commands/approvals.js +1 -37
  219. package/dist/commands/approvals.js.map +1 -1
  220. package/dist/commands/browser/index.d.ts.map +1 -1
  221. package/dist/commands/browser/index.js +7 -2
  222. package/dist/commands/browser/index.js.map +1 -1
  223. package/dist/commands/daemon.d.ts.map +1 -1
  224. package/dist/commands/daemon.js +7 -3
  225. package/dist/commands/daemon.js.map +1 -1
  226. package/dist/commands/dispatch.d.ts.map +1 -1
  227. package/dist/commands/dispatch.js +27 -3
  228. package/dist/commands/dispatch.js.map +1 -1
  229. package/dist/commands/patent-doctor.d.ts +48 -0
  230. package/dist/commands/patent-doctor.d.ts.map +1 -0
  231. package/dist/commands/patent-doctor.js +109 -0
  232. package/dist/commands/patent-doctor.js.map +1 -0
  233. package/dist/commands/patent.d.ts +78 -0
  234. package/dist/commands/patent.d.ts.map +1 -0
  235. package/dist/commands/patent.js +919 -0
  236. package/dist/commands/patent.js.map +1 -0
  237. package/dist/commands/social.d.ts +19 -0
  238. package/dist/commands/social.d.ts.map +1 -0
  239. package/dist/commands/social.js +236 -0
  240. package/dist/commands/social.js.map +1 -0
  241. package/dist/core/registry.d.ts +1 -1
  242. package/dist/core/registry.d.ts.map +1 -1
  243. package/dist/core/registry.js +11 -2
  244. package/dist/core/registry.js.map +1 -1
  245. package/dist/discovery/loader.d.ts.map +1 -1
  246. package/dist/discovery/loader.js +4 -0
  247. package/dist/discovery/loader.js.map +1 -1
  248. package/dist/engine/approval-presenter.d.ts +10 -0
  249. package/dist/engine/approval-presenter.d.ts.map +1 -0
  250. package/dist/engine/approval-presenter.js +45 -0
  251. package/dist/engine/approval-presenter.js.map +1 -0
  252. package/dist/engine/approval-store.d.ts +4 -0
  253. package/dist/engine/approval-store.d.ts.map +1 -1
  254. package/dist/engine/approval-store.js +85 -11
  255. package/dist/engine/approval-store.js.map +1 -1
  256. package/dist/engine/auth/oauth2-cc.d.ts +67 -0
  257. package/dist/engine/auth/oauth2-cc.d.ts.map +1 -0
  258. package/dist/engine/auth/oauth2-cc.js +120 -0
  259. package/dist/engine/auth/oauth2-cc.js.map +1 -0
  260. package/dist/engine/cookies.d.ts +10 -0
  261. package/dist/engine/cookies.d.ts.map +1 -1
  262. package/dist/engine/cookies.js +64 -0
  263. package/dist/engine/cookies.js.map +1 -1
  264. package/dist/engine/download.d.ts +5 -0
  265. package/dist/engine/download.d.ts.map +1 -1
  266. package/dist/engine/download.js +11 -4
  267. package/dist/engine/download.js.map +1 -1
  268. package/dist/engine/executor.d.ts +1 -0
  269. package/dist/engine/executor.d.ts.map +1 -1
  270. package/dist/engine/executor.js +25 -0
  271. package/dist/engine/executor.js.map +1 -1
  272. package/dist/engine/framework.d.ts +5 -5
  273. package/dist/engine/framework.js +5 -5
  274. package/dist/engine/harden.d.ts +1 -1
  275. package/dist/engine/harden.js +1 -1
  276. package/dist/engine/kernel/stages.d.ts.map +1 -1
  277. package/dist/engine/kernel/stages.js +2 -1
  278. package/dist/engine/kernel/stages.js.map +1 -1
  279. package/dist/engine/normalizer/patent-envelope.d.ts +61 -0
  280. package/dist/engine/normalizer/patent-envelope.d.ts.map +1 -0
  281. package/dist/engine/normalizer/patent-envelope.js +132 -0
  282. package/dist/engine/normalizer/patent-envelope.js.map +1 -0
  283. package/dist/engine/research.d.ts +5 -7
  284. package/dist/engine/research.d.ts.map +1 -1
  285. package/dist/engine/research.js +6 -9
  286. package/dist/engine/research.js.map +1 -1
  287. package/dist/engine/steps/browser-helpers.d.ts +2 -2
  288. package/dist/engine/steps/browser-helpers.d.ts.map +1 -1
  289. package/dist/engine/steps/browser-helpers.js +39 -16
  290. package/dist/engine/steps/browser-helpers.js.map +1 -1
  291. package/dist/engine/steps/download.d.ts +1 -0
  292. package/dist/engine/steps/download.d.ts.map +1 -1
  293. package/dist/engine/steps/download.js +3 -1
  294. package/dist/engine/steps/download.js.map +1 -1
  295. package/dist/engine/steps/index.d.ts +2 -0
  296. package/dist/engine/steps/index.d.ts.map +1 -1
  297. package/dist/engine/steps/index.js +2 -0
  298. package/dist/engine/steps/index.js.map +1 -1
  299. package/dist/engine/steps/oauth2-token.d.ts +41 -0
  300. package/dist/engine/steps/oauth2-token.d.ts.map +1 -0
  301. package/dist/engine/steps/oauth2-token.js +115 -0
  302. package/dist/engine/steps/oauth2-token.js.map +1 -0
  303. package/dist/engine/steps/select-xml.d.ts +34 -0
  304. package/dist/engine/steps/select-xml.d.ts.map +1 -0
  305. package/dist/engine/steps/select-xml.js +222 -0
  306. package/dist/engine/steps/select-xml.js.map +1 -0
  307. package/dist/engine/template.d.ts.map +1 -1
  308. package/dist/engine/template.js +7 -0
  309. package/dist/engine/template.js.map +1 -1
  310. package/dist/engine/transport/mcp-browser.d.ts +128 -0
  311. package/dist/engine/transport/mcp-browser.d.ts.map +1 -0
  312. package/dist/engine/transport/mcp-browser.js +120 -0
  313. package/dist/engine/transport/mcp-browser.js.map +1 -0
  314. package/dist/fast-path/handlers/approvals.d.ts +11 -0
  315. package/dist/fast-path/handlers/approvals.d.ts.map +1 -0
  316. package/dist/fast-path/handlers/approvals.js +136 -0
  317. package/dist/fast-path/handlers/approvals.js.map +1 -0
  318. package/dist/fast-path/manifest.d.ts +1 -0
  319. package/dist/fast-path/manifest.d.ts.map +1 -1
  320. package/dist/fast-path/manifest.js.map +1 -1
  321. package/dist/fast-path.d.ts.map +1 -1
  322. package/dist/fast-path.js +3 -0
  323. package/dist/fast-path.js.map +1 -1
  324. package/dist/index.d.ts +23 -0
  325. package/dist/index.d.ts.map +1 -0
  326. package/dist/index.js +38 -0
  327. package/dist/index.js.map +1 -0
  328. package/dist/manifest-compact.txt +3 -3
  329. package/dist/manifest-search.json +1 -1
  330. package/dist/manifest.json +2239 -176
  331. package/dist/output/auth-guidance.d.ts +14 -0
  332. package/dist/output/auth-guidance.d.ts.map +1 -0
  333. package/dist/output/auth-guidance.js +50 -0
  334. package/dist/output/auth-guidance.js.map +1 -0
  335. package/dist/output/error-map.d.ts +1 -1
  336. package/dist/output/error-map.d.ts.map +1 -1
  337. package/dist/output/error-map.js +28 -4
  338. package/dist/output/error-map.js.map +1 -1
  339. package/dist/output/next-actions.d.ts.map +1 -1
  340. package/dist/output/next-actions.js +19 -3
  341. package/dist/output/next-actions.js.map +1 -1
  342. package/dist/registry.d.ts +18 -1
  343. package/dist/registry.d.ts.map +1 -1
  344. package/dist/registry.js +5 -0
  345. package/dist/registry.js.map +1 -1
  346. package/dist/social/browser-errors.d.ts +13 -0
  347. package/dist/social/browser-errors.d.ts.map +1 -0
  348. package/dist/social/browser-errors.js +36 -0
  349. package/dist/social/browser-errors.js.map +1 -0
  350. package/dist/social/capabilities.d.ts +29 -0
  351. package/dist/social/capabilities.d.ts.map +1 -0
  352. package/dist/social/capabilities.js +448 -0
  353. package/dist/social/capabilities.js.map +1 -0
  354. package/dist/social/comments.d.ts +26 -0
  355. package/dist/social/comments.d.ts.map +1 -0
  356. package/dist/social/comments.js +97 -0
  357. package/dist/social/comments.js.map +1 -0
  358. package/dist/social/video-text.d.ts +27 -0
  359. package/dist/social/video-text.d.ts.map +1 -0
  360. package/dist/social/video-text.js +140 -0
  361. package/dist/social/video-text.js.map +1 -0
  362. package/dist/types/patent.d.ts +160 -0
  363. package/dist/types/patent.d.ts.map +1 -0
  364. package/dist/types/patent.js +16 -0
  365. package/dist/types/patent.js.map +1 -0
  366. package/dist/types.d.ts +12 -0
  367. package/dist/types.d.ts.map +1 -1
  368. package/dist/types.js.map +1 -1
  369. package/package.json +9 -4
  370. package/server.json +3 -3
  371. package/skills/unicli/SKILL.md +1 -1
  372. package/skills/unicli-claude-code/SKILL.md +1 -1
  373. package/skills/unicli-hermes/SKILL.md +1 -1
  374. package/src/adapters/bilibili/comments-tree.test.ts +41 -0
  375. package/src/adapters/bilibili/comments.ts +78 -4
  376. package/src/adapters/bilibili/compat.ts +5 -2
  377. package/src/adapters/bilibili/download.ts +7 -4
  378. package/src/adapters/bilibili/wbi.ts +6 -3
  379. package/src/adapters/brave/search.yaml +53 -0
  380. package/src/adapters/cipo/_shared.ts +98 -0
  381. package/src/adapters/cipo/get.ts +188 -0
  382. package/src/adapters/cipo/legal-status.ts +148 -0
  383. package/src/adapters/cipo/search.ts +195 -0
  384. package/src/adapters/cnipa/_shared.ts +138 -0
  385. package/src/adapters/cnipa/get.ts +199 -0
  386. package/src/adapters/cnipa/legal-status.ts +162 -0
  387. package/src/adapters/cnipa/search.ts +229 -0
  388. package/src/adapters/dpma/get.yaml +67 -0
  389. package/src/adapters/dpma/search.yaml +77 -0
  390. package/src/adapters/duckduckgo/search.yaml +54 -0
  391. package/src/adapters/duckduckgo/suggest.yaml +52 -0
  392. package/src/adapters/epo/family.yaml +69 -0
  393. package/src/adapters/epo/get.yaml +74 -0
  394. package/src/adapters/epo/legal-status.yaml +63 -0
  395. package/src/adapters/epo/search.yaml +84 -0
  396. package/src/adapters/espacenet/_shared.ts +98 -0
  397. package/src/adapters/espacenet/family.ts +161 -0
  398. package/src/adapters/espacenet/get.ts +185 -0
  399. package/src/adapters/espacenet/legal-status.ts +151 -0
  400. package/src/adapters/espacenet/search.ts +229 -0
  401. package/src/adapters/facebook/subtitles.ts +44 -0
  402. package/src/adapters/fips/_shared.ts +109 -0
  403. package/src/adapters/fips/get.ts +186 -0
  404. package/src/adapters/fips/search.ts +195 -0
  405. package/src/adapters/freepatentsonline-web/_shared.ts +273 -0
  406. package/src/adapters/freepatentsonline-web/get.ts +144 -0
  407. package/src/adapters/freepatentsonline-web/search.ts +170 -0
  408. package/src/adapters/google-patents-bq/prior-art.yaml +80 -0
  409. package/src/adapters/google-patents-bq/search.yaml +97 -0
  410. package/src/adapters/google-patents-web/_shared.ts +242 -0
  411. package/src/adapters/google-patents-web/get.ts +224 -0
  412. package/src/adapters/google-patents-web/search.ts +196 -0
  413. package/src/adapters/inpi-br/_shared.ts +98 -0
  414. package/src/adapters/inpi-br/get.ts +193 -0
  415. package/src/adapters/inpi-br/search.ts +206 -0
  416. package/src/adapters/inpi-fr/get.yaml +62 -0
  417. package/src/adapters/inpi-fr/search.yaml +74 -0
  418. package/src/adapters/instagram/subtitles.ts +44 -0
  419. package/src/adapters/ipaustralia/get.yaml +67 -0
  420. package/src/adapters/ipaustralia/search.yaml +74 -0
  421. package/src/adapters/jpo/get.yaml +63 -0
  422. package/src/adapters/jpo/search.yaml +76 -0
  423. package/src/adapters/kipris/get.yaml +69 -0
  424. package/src/adapters/kipris/legal-status.yaml +58 -0
  425. package/src/adapters/kipris/search.yaml +79 -0
  426. package/src/adapters/lens/get.yaml +64 -0
  427. package/src/adapters/lens/search.yaml +82 -0
  428. package/src/adapters/mastodon/statuses.test.ts +82 -0
  429. package/src/adapters/mastodon/statuses.ts +208 -0
  430. package/src/adapters/patsnap/get.yaml +65 -0
  431. package/src/adapters/patsnap/search.yaml +77 -0
  432. package/src/adapters/pqai/prior-art.yaml +59 -0
  433. package/src/adapters/pqai/search.yaml +60 -0
  434. package/src/adapters/reddit/comments-tree.test.ts +79 -0
  435. package/src/adapters/reddit/comments.ts +159 -0
  436. package/src/adapters/threads/post.test.ts +64 -0
  437. package/src/adapters/threads/post.ts +366 -0
  438. package/src/adapters/threads/user.yaml +73 -0
  439. package/src/adapters/tiktok/subtitles.ts +44 -0
  440. package/src/adapters/twitter/accept.ts +5 -2
  441. package/src/adapters/twitter/browser-fallback.ts +138 -0
  442. package/src/adapters/twitter/browser-state.ts +74 -0
  443. package/src/adapters/twitter/client.ts +51 -21
  444. package/src/adapters/twitter/reply-dm.ts +5 -2
  445. package/src/adapters/twitter/reply.ts +1 -0
  446. package/src/adapters/twitter/search.ts +12 -38
  447. package/src/adapters/twitter/thread.test.ts +43 -0
  448. package/src/adapters/twitter/thread.ts +44 -2
  449. package/src/adapters/twitter/trending.ts +14 -95
  450. package/src/adapters/ukipo/info.yaml +43 -0
  451. package/src/adapters/uspto/get.yaml +67 -0
  452. package/src/adapters/uspto/legal-status.yaml +58 -0
  453. package/src/adapters/uspto/search.yaml +88 -0
  454. package/src/adapters/wipo-patentscope/info.yaml +43 -0
  455. package/src/adapters/xiaohongshu/browser-state.ts +95 -0
  456. package/src/adapters/xiaohongshu/comments.ts +29 -6
  457. package/src/adapters/xiaohongshu/download.ts +60 -11
  458. package/src/adapters/xiaohongshu/search.ts +18 -6
  459. package/src/adapters/xiaohongshu/trending.ts +112 -0
  460. package/src/adapters/yahoo/search.yaml +52 -0
  461. package/src/adapters/youtube/comments-microformat.test.ts +35 -0
  462. package/src/adapters/youtube/comments-tree.test.ts +74 -0
  463. package/src/adapters/youtube/comments.ts +166 -12
  464. package/src/adapters/youtube/subtitles.ts +44 -0
  465. package/src/adapters/yt-dlp/subtitles.ts +43 -0
  466. package/src/adapters/zhihu/answer-detail.test.ts +83 -0
  467. package/src/adapters/zhihu/answer-detail.ts +275 -0
  468. package/src/adapters/zhihu/comment-tree.test.ts +57 -0
  469. package/src/adapters/zhihu/comment.ts +186 -0
  470. package/src/adapters/zhihu/recommend.test.ts +65 -0
  471. package/src/adapters/zhihu/recommend.ts +207 -0
@@ -0,0 +1,82 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import { mapMastodonStatusRows, normalizeMastodonAccount } from "./statuses.js";
4
+
5
+ describe("mastodon statuses adapter helpers", () => {
6
+ it("normalizes account handles and instance overrides", () => {
7
+ expect(normalizeMastodonAccount("gargron@mastodon.social")).toEqual({
8
+ acct: "gargron",
9
+ instance: "mastodon.social",
10
+ });
11
+
12
+ expect(normalizeMastodonAccount("@gargron", "mastodon.social")).toEqual({
13
+ acct: "gargron",
14
+ instance: "mastodon.social",
15
+ });
16
+ });
17
+
18
+ it("maps API statuses into stable social rows", () => {
19
+ expect(
20
+ mapMastodonStatusRows(
21
+ [
22
+ {
23
+ created_at: "2026-05-14T10:00:00.000Z",
24
+ content: "<p>Hello <strong>fediverse</strong></p>",
25
+ url: "https://mastodon.social/@gargron/1",
26
+ reblogs_count: 2,
27
+ favourites_count: 3,
28
+ replies_count: 4,
29
+ account: { acct: "gargron", display_name: "Gargron" },
30
+ },
31
+ ],
32
+ 10,
33
+ ),
34
+ ).toEqual([
35
+ {
36
+ rank: 1,
37
+ author: "Gargron",
38
+ handle: "@gargron",
39
+ content: "Hello fediverse",
40
+ reblogs: 2,
41
+ favorites: 3,
42
+ replies: 4,
43
+ url: "https://mastodon.social/@gargron/1",
44
+ date: "2026-05-14T10:00:00.000Z",
45
+ },
46
+ ]);
47
+ });
48
+
49
+ it("drops empty activity rows and decodes common HTML entities", () => {
50
+ expect(
51
+ mapMastodonStatusRows(
52
+ [
53
+ {
54
+ created_at: "2026-05-14T10:00:00.000Z",
55
+ content: "",
56
+ url: "https://mastodon.social/users/Gargron/statuses/1/activity",
57
+ account: { acct: "Gargron", display_name: "Eugen Rochko" },
58
+ },
59
+ {
60
+ created_at: "2026-05-14T11:00:00.000Z",
61
+ content: "<p>Don&#39;t escape &amp; ship</p>",
62
+ url: "https://mastodon.social/@Gargron/2",
63
+ account: { acct: "Gargron", display_name: "Eugen Rochko" },
64
+ },
65
+ ],
66
+ 10,
67
+ ),
68
+ ).toEqual([
69
+ {
70
+ rank: 1,
71
+ author: "Eugen Rochko",
72
+ handle: "@Gargron",
73
+ content: "Don't escape & ship",
74
+ reblogs: 0,
75
+ favorites: 0,
76
+ replies: 0,
77
+ url: "https://mastodon.social/@Gargron/2",
78
+ date: "2026-05-14T11:00:00.000Z",
79
+ },
80
+ ]);
81
+ });
82
+ });
@@ -0,0 +1,208 @@
1
+ /**
2
+ * @owner Mastodon user status adapter.
3
+ * @does Register a public read command for recent statuses by account handle.
4
+ * @needs Mastodon-compatible public API endpoints for account lookup and statuses.
5
+ * @feeds Social research workflows and social capability coverage.
6
+ * @breaks Instance API drift, blocked public egress, or accounts hidden from public lookup.
7
+ */
8
+
9
+ import { USER_AGENT } from "../../constants.js";
10
+ import { cli, Strategy } from "../../registry.js";
11
+
12
+ interface MastodonAccount {
13
+ id?: unknown;
14
+ acct?: unknown;
15
+ display_name?: unknown;
16
+ }
17
+
18
+ interface MastodonStatus {
19
+ created_at?: unknown;
20
+ content?: unknown;
21
+ url?: unknown;
22
+ reblogs_count?: unknown;
23
+ favourites_count?: unknown;
24
+ replies_count?: unknown;
25
+ account?: MastodonAccount;
26
+ }
27
+
28
+ export interface MastodonAccountRef {
29
+ acct: string;
30
+ instance: string;
31
+ }
32
+
33
+ export interface MastodonStatusRow {
34
+ rank: number;
35
+ author: string;
36
+ handle: string;
37
+ content: string;
38
+ reblogs: number;
39
+ favorites: number;
40
+ replies: number;
41
+ url: string;
42
+ date: string;
43
+ }
44
+
45
+ function cleanString(value: unknown): string {
46
+ return typeof value === "string" ? value.trim() : "";
47
+ }
48
+
49
+ function numberValue(value: unknown): number {
50
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
51
+ }
52
+
53
+ function stripHtml(value: unknown): string {
54
+ return cleanString(value)
55
+ .replace(/<[^>]*>/g, "")
56
+ .replace(/&nbsp;/g, " ")
57
+ .replace(/&amp;/g, "&")
58
+ .replace(/&lt;/g, "<")
59
+ .replace(/&gt;/g, ">")
60
+ .replace(/&quot;/g, '"')
61
+ .replace(/&#39;/g, "'")
62
+ .replace(/\s+/g, " ")
63
+ .trim();
64
+ }
65
+
66
+ export function normalizeMastodonAccount(
67
+ input: string,
68
+ instanceOverride = "mastodon.social",
69
+ ): MastodonAccountRef {
70
+ const trimmed = input.trim().replace(/^@/, "");
71
+ if (!trimmed) throw new Error("Mastodon account cannot be empty");
72
+ const parts = trimmed.split("@").filter(Boolean);
73
+ if (parts.length > 2) {
74
+ throw new Error(`Invalid Mastodon account: ${input}`);
75
+ }
76
+ const acct = parts[0];
77
+ const instance = parts[1] ?? instanceOverride.trim();
78
+ if (!acct || !instance) {
79
+ throw new Error(`Invalid Mastodon account: ${input}`);
80
+ }
81
+ return { acct, instance };
82
+ }
83
+
84
+ export function mapMastodonStatusRows(
85
+ statuses: MastodonStatus[],
86
+ limit: number,
87
+ ): MastodonStatusRow[] {
88
+ const rows: Omit<MastodonStatusRow, "rank">[] = [];
89
+ for (const status of statuses) {
90
+ const content = stripHtml(status.content).slice(0, 500);
91
+ if (!content) continue;
92
+ const account = status.account ?? {};
93
+ const handle = cleanString(account.acct);
94
+ rows.push({
95
+ author: cleanString(account.display_name) || handle,
96
+ handle: handle ? `@${handle}` : "",
97
+ content,
98
+ reblogs: numberValue(status.reblogs_count),
99
+ favorites: numberValue(status.favourites_count),
100
+ replies: numberValue(status.replies_count),
101
+ url: cleanString(status.url),
102
+ date: cleanString(status.created_at),
103
+ });
104
+ }
105
+ return rows.slice(0, limit).map((row, index) => ({
106
+ rank: index + 1,
107
+ ...row,
108
+ }));
109
+ }
110
+
111
+ function parseLimit(value: unknown): number {
112
+ const limit = Number(value ?? 20);
113
+ if (!Number.isInteger(limit) || limit < 1 || limit > 40) {
114
+ throw new Error(
115
+ `--limit must be an integer between 1 and 40, got ${value}`,
116
+ );
117
+ }
118
+ return limit;
119
+ }
120
+
121
+ async function fetchMastodonJson(url: string): Promise<unknown> {
122
+ const response = await fetch(url, {
123
+ headers: {
124
+ Accept: "application/json",
125
+ "User-Agent": USER_AGENT,
126
+ },
127
+ });
128
+ if (!response.ok) {
129
+ const preview = (await response.text()).slice(0, 200);
130
+ throw new Error(`Mastodon HTTP ${response.status} from ${url}: ${preview}`);
131
+ }
132
+ return response.json() as Promise<unknown>;
133
+ }
134
+
135
+ function requireAccountId(account: unknown): string {
136
+ if (!account || typeof account !== "object") {
137
+ throw new Error("Mastodon account lookup returned a non-object response");
138
+ }
139
+ const id = cleanString((account as MastodonAccount).id);
140
+ if (!id) throw new Error("Mastodon account lookup did not return an id");
141
+ return id;
142
+ }
143
+
144
+ cli({
145
+ site: "mastodon",
146
+ name: "statuses",
147
+ description: "Get recent public statuses from a Mastodon account",
148
+ domain: "mastodon.social",
149
+ strategy: Strategy.PUBLIC,
150
+ args: [
151
+ {
152
+ name: "account",
153
+ required: true,
154
+ positional: true,
155
+ description: "Account handle, e.g. gargron@mastodon.social",
156
+ },
157
+ {
158
+ name: "instance",
159
+ type: "str",
160
+ default: "mastodon.social",
161
+ description: "Mastodon instance domain used when account omits one",
162
+ },
163
+ {
164
+ name: "limit",
165
+ type: "int",
166
+ default: 20,
167
+ description: "Number of statuses, 1-40",
168
+ },
169
+ ],
170
+ columns: [
171
+ "rank",
172
+ "author",
173
+ "handle",
174
+ "content",
175
+ "reblogs",
176
+ "favorites",
177
+ "replies",
178
+ "url",
179
+ "date",
180
+ ],
181
+ socialCapabilities: ["read", "user_content", "reactions"],
182
+ func: async (_page, kwargs) => {
183
+ const limit = parseLimit(kwargs.limit);
184
+ const account = normalizeMastodonAccount(
185
+ String(kwargs.account ?? ""),
186
+ String(kwargs.instance ?? "mastodon.social"),
187
+ );
188
+ const origin = `https://${account.instance}`;
189
+ const lookupUrl = new URL("/api/v1/accounts/lookup", origin);
190
+ lookupUrl.searchParams.set("acct", account.acct);
191
+ const lookup = await fetchMastodonJson(lookupUrl.toString());
192
+ const accountId = requireAccountId(lookup);
193
+ const statusesUrl = new URL(
194
+ `/api/v1/accounts/${encodeURIComponent(accountId)}/statuses`,
195
+ origin,
196
+ );
197
+ statusesUrl.searchParams.set("limit", String(limit));
198
+ statusesUrl.searchParams.set("exclude_reblogs", "false");
199
+ statusesUrl.searchParams.set("exclude_replies", "false");
200
+ const statuses = await fetchMastodonJson(statusesUrl.toString());
201
+ if (!Array.isArray(statuses)) {
202
+ throw new Error(
203
+ "Mastodon statuses endpoint returned a non-array response",
204
+ );
205
+ }
206
+ return mapMastodonStatusRows(statuses as MastodonStatus[], limit);
207
+ },
208
+ });
@@ -0,0 +1,65 @@
1
+ # PatSnap Eureka — single-record fetch.
2
+ #
3
+ # verification_status: blocked-by-subscription
4
+ #
5
+ # Maps to PatSnap's /patent/biblio/{publication_number} endpoint. The same
6
+ # OAuth2 token resolution pattern as `patsnap/search.yaml`.
7
+ site: patsnap
8
+ name: get
9
+ description: Retrieve one PatSnap patent record by publication number
10
+ domain: connect.zhihuiya.com
11
+ type: web-api
12
+ strategy: header
13
+
14
+ args:
15
+ publication_number:
16
+ type: str
17
+ required: true
18
+ positional: true
19
+
20
+ pipeline:
21
+ - oauth2-token:
22
+ token_url: https://connect.zhihuiya.com/oauth/token
23
+ client_id_env: PATSNAP_CLIENT_ID
24
+ client_secret_env: PATSNAP_CLIENT_SECRET
25
+ site: patsnap
26
+ destination: auth.bearer
27
+
28
+ - fetch:
29
+ url: "https://connect.zhihuiya.com/patent/biblio"
30
+ params:
31
+ patent_number: "${{ args.publication_number }}"
32
+ headers:
33
+ Authorization: "Bearer ${{ auth.bearer }}"
34
+
35
+ - select: data
36
+
37
+ - map:
38
+ publication_number: "${{ item.pn }}"
39
+ title: "${{ item.title }}"
40
+ abstract: "${{ item.abstract }}"
41
+ kind_code: "${{ item.kind_code || item.kindcode || '' }}"
42
+ filing_date: "${{ item.apdt || '' }}"
43
+ publication_date: "${{ item.pbdt || '' }}"
44
+ grant_date: "${{ item.grant_date || item.granted || '' }}"
45
+ priority_date: "${{ item.priority_date || item.prdate || '' }}"
46
+ application_number: "${{ item.application_number || item.an || '' }}"
47
+ family_id: "${{ item.simple_family_id || '' }}"
48
+ legal_status: "${{ item.legal_status || '' }}"
49
+ inventors: "${{ JSON.stringify((function(){ var i=item.inventor || item.inventors; if(!i) return []; if(typeof i === 'string') return i.split(/\\s*[\\|;,]\\s*/).filter(s => s).map(name => ({ name: name })); return Array.isArray(i) ? i.map(n => ({ name: typeof n === 'string' ? n : (n.name || ''), country: n.country || undefined })) : []; })()) }}"
50
+ assignees: "${{ JSON.stringify((function(){ var a=item.current_assignee || item.assignee || item.assignees; if(!a) return []; if(typeof a === 'string') return a.split(/\\s*[\\|;,]\\s*/).filter(s => s).map(name => ({ name: name })); return Array.isArray(a) ? a.map(n => ({ name: typeof n === 'string' ? n : (n.name || ''), country: n.country || undefined })) : []; })()) }}"
51
+ classifications: "${{ JSON.stringify((function(){ var out=[]; var ipc=item.ipc; if(ipc){ var arr = Array.isArray(ipc) ? ipc : String(ipc).split(/[\\|;,]/); for (var i=0;i<arr.length;i++){ var c = arr[i]; var code = typeof c === 'string' ? c.trim() : (c.code || ''); if(code) out.push({ scheme: 'ipc', code: code }); } } var cpc=item.cpc; if(cpc){ var arr2 = Array.isArray(cpc) ? cpc : String(cpc).split(/[\\|;,]/); for (var j=0;j<arr2.length;j++){ var c2 = arr2[j]; var code2 = typeof c2 === 'string' ? c2.trim() : (c2.code || ''); if(code2) out.push({ scheme: 'cpc', code: code2 }); } } return out; })()) }}"
52
+ cited_by_count: "${{ item.cited_by !== undefined ? item.cited_by : (item.citation_count !== undefined ? item.citation_count : '') }}"
53
+ cites_count: "${{ item.cites !== undefined ? item.cites : '' }}"
54
+ source_adapter: patsnap
55
+ source_url: "${{ 'https://analytics.zhihuiya.com/patent/' + (item.pn || '') }}"
56
+ retrieved_at: "${{ now }}"
57
+
58
+ columns: [publication_number, title, legal_status, source_adapter]
59
+
60
+ capabilities: ["http.fetch", "patent.get"]
61
+ minimum_capability: http.fetch
62
+ trust: public
63
+ confidentiality: public
64
+ quarantine: false
65
+ schema_version: v2
@@ -0,0 +1,77 @@
1
+ # PatSnap Eureka — OAuth2 client_credentials search.
2
+ #
3
+ # verification_status: blocked-by-subscription
4
+ #
5
+ # PatSnap is a commercial patent intelligence platform. API access requires a
6
+ # Connect / Eureka subscription with two static credentials (CLIENT_ID /
7
+ # CLIENT_SECRET) the buyer pastes into env vars. The `oauth2-token` step
8
+ # resolves the bearer once and caches it; downstream fetch reuses it.
9
+ site: patsnap
10
+ name: search
11
+ description: PatSnap Eureka patent search via OAuth2 client_credentials
12
+ domain: connect.zhihuiya.com
13
+ type: web-api
14
+ strategy: header
15
+
16
+ args:
17
+ query:
18
+ type: str
19
+ required: true
20
+ positional: true
21
+ limit:
22
+ type: int
23
+ default: 20
24
+
25
+ pipeline:
26
+ - oauth2-token:
27
+ token_url: https://connect.zhihuiya.com/oauth/token
28
+ client_id_env: PATSNAP_CLIENT_ID
29
+ client_secret_env: PATSNAP_CLIENT_SECRET
30
+ site: patsnap
31
+ destination: auth.bearer
32
+
33
+ - fetch:
34
+ url: https://connect.zhihuiya.com/search/patent/query-search-patent/v2
35
+ method: POST
36
+ headers:
37
+ Authorization: "Bearer ${{ auth.bearer }}"
38
+ Content-Type: application/json
39
+ body:
40
+ text: "${{ args.query }}"
41
+ offset: 0
42
+ limit: "${{ args.limit }}"
43
+
44
+ - select: data.results
45
+
46
+ # PatSnap Eureka response carries inventors / assignees / classifications
47
+ # under documented field names.
48
+ - map:
49
+ publication_number: "${{ item.pn || item.pbd_number }}"
50
+ title: "${{ item.title }}"
51
+ abstract: "${{ item.abstract }}"
52
+ kind_code: "${{ item.kind_code || item.kindcode || '' }}"
53
+ filing_date: "${{ item.apdt || '' }}"
54
+ publication_date: "${{ item.pbdt || '' }}"
55
+ grant_date: "${{ item.grant_date || item.granted || '' }}"
56
+ priority_date: "${{ item.priority_date || item.prdate || '' }}"
57
+ application_number: "${{ item.application_number || item.an || '' }}"
58
+ family_id: "${{ item.simple_family_id || '' }}"
59
+ inventors: "${{ JSON.stringify((function(){ var i=item.inventor || item.inventors; if(!i) return []; if(typeof i === 'string') return i.split(/\\s*[\\|;,]\\s*/).filter(s => s).map(name => ({ name: name })); return Array.isArray(i) ? i.map(n => ({ name: typeof n === 'string' ? n : (n.name || ''), country: n.country || undefined })) : []; })()) }}"
60
+ assignees: "${{ JSON.stringify((function(){ var a=item.current_assignee || item.assignee || item.assignees; if(!a) return []; if(typeof a === 'string') return a.split(/\\s*[\\|;,]\\s*/).filter(s => s).map(name => ({ name: name })); return Array.isArray(a) ? a.map(n => ({ name: typeof n === 'string' ? n : (n.name || ''), country: n.country || undefined })) : []; })()) }}"
61
+ classifications: "${{ JSON.stringify((function(){ var out=[]; var ipc=item.ipc; if(ipc){ var arr = Array.isArray(ipc) ? ipc : String(ipc).split(/[\\|;,]/); for (var i=0;i<arr.length;i++){ var c = arr[i]; var code = typeof c === 'string' ? c.trim() : (c.code || ''); if(code) out.push({ scheme: 'ipc', code: code }); } } var cpc=item.cpc; if(cpc){ var arr2 = Array.isArray(cpc) ? cpc : String(cpc).split(/[\\|;,]/); for (var j=0;j<arr2.length;j++){ var c2 = arr2[j]; var code2 = typeof c2 === 'string' ? c2.trim() : (c2.code || ''); if(code2) out.push({ scheme: 'cpc', code: code2 }); } } return out; })()) }}"
62
+ cited_by_count: "${{ item.cited_by !== undefined ? item.cited_by : (item.citation_count !== undefined ? item.citation_count : '') }}"
63
+ cites_count: "${{ item.cites !== undefined ? item.cites : '' }}"
64
+ source_adapter: patsnap
65
+ source_url: "${{ 'https://analytics.zhihuiya.com/patent/' + (item.pn || item.pbd_number || '') }}"
66
+ retrieved_at: "${{ now }}"
67
+
68
+ - limit: ${{ args.limit }}
69
+
70
+ columns: [publication_number, title, publication_date, source_adapter]
71
+
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,59 @@
1
+ # Project PQAI — semantic prior-art retrieval.
2
+ #
3
+ # verification_status: blocked-by-key
4
+ #
5
+ # PQAI publishes a permanent free tier for non-commercial use, but rate limits
6
+ # beyond ~100 queries / day require their USD 20 / month plan. The token is a
7
+ # single string passed as a `token=` query param (the only auth scheme PQAI
8
+ # offers today). Set $PQAI_API_TOKEN.
9
+ site: pqai
10
+ name: prior-art
11
+ description: Semantic prior-art retrieval via PQAI's embedding-based ranker
12
+ domain: api.projectpq.ai
13
+ type: web-api
14
+ strategy: public
15
+
16
+ args:
17
+ abstract:
18
+ type: str
19
+ required: true
20
+ description: Candidate abstract or claim text
21
+ limit:
22
+ type: int
23
+ default: 20
24
+
25
+ pipeline:
26
+ - fetch:
27
+ url: https://api.projectpq.ai/search/102
28
+ params:
29
+ q: "${{ args.abstract }}"
30
+ n: "${{ args.limit }}"
31
+ type: patent
32
+ token: "${{ env.PQAI_API_TOKEN || '' }}"
33
+
34
+ - select: results
35
+
36
+ # PQAI ships per-result `score` (semantic embedding cosine, ∈ [0, 1]).
37
+ # Forward as relevance_score so the meta-command's RRF stage can fuse it.
38
+ - map:
39
+ publication_number: "${{ item.id }}"
40
+ title: "${{ item.title }}"
41
+ abstract: "${{ item.abstract }}"
42
+ publication_date: "${{ item.publication_date || '' }}"
43
+ filing_date: "${{ item.filing_date || '' }}"
44
+ kind_code: "${{ item.kind_code || '' }}"
45
+ relevance_score: "${{ item.score !== undefined ? item.score : '' }}"
46
+ source_adapter: pqai
47
+ source_url: "https://search.projectpq.ai/patent/${{ item.id }}"
48
+ retrieved_at: "${{ now }}"
49
+
50
+ - limit: ${{ args.limit }}
51
+
52
+ columns: [publication_number, title, abstract]
53
+
54
+ capabilities: ["http.fetch", "patent.prior-art"]
55
+ minimum_capability: http.fetch
56
+ trust: public
57
+ confidentiality: public
58
+ quarantine: false
59
+ schema_version: v2
@@ -0,0 +1,60 @@
1
+ # Project PQAI — free-text keyword search.
2
+ #
3
+ # verification_status: blocked-by-key
4
+ #
5
+ # PQAI ships a `/search/102` endpoint that accepts both natural-language and
6
+ # Boolean queries. This adapter exposes it as the standard patent.search
7
+ # capability; the prior-art-specific tuning lives in pqai/prior-art.yaml.
8
+ site: pqai
9
+ name: search
10
+ description: Keyword + semantic patent search through PQAI's hybrid index
11
+ domain: api.projectpq.ai
12
+ type: web-api
13
+ strategy: public
14
+ lint_listing_detail: skip
15
+
16
+ args:
17
+ query:
18
+ type: str
19
+ required: true
20
+ positional: true
21
+ limit:
22
+ type: int
23
+ default: 20
24
+
25
+ pipeline:
26
+ - fetch:
27
+ url: https://api.projectpq.ai/search/102
28
+ params:
29
+ q: "${{ args.query }}"
30
+ n: "${{ args.limit }}"
31
+ type: patent
32
+ token: "${{ env.PQAI_API_TOKEN || '' }}"
33
+
34
+ - select: results
35
+
36
+ # PQAI returns `score` (∈ [0, 1] semantic relevance) alongside the patent
37
+ # record. Surface it as relevance_score so the downstream RRF stage can
38
+ # consult the per-engine ranking.
39
+ - map:
40
+ publication_number: "${{ item.id }}"
41
+ title: "${{ item.title }}"
42
+ abstract: "${{ item.abstract }}"
43
+ publication_date: "${{ item.publication_date || '' }}"
44
+ filing_date: "${{ item.filing_date || '' }}"
45
+ kind_code: "${{ item.kind_code || '' }}"
46
+ relevance_score: "${{ item.score !== undefined ? item.score : '' }}"
47
+ source_adapter: pqai
48
+ source_url: "https://search.projectpq.ai/patent/${{ item.id }}"
49
+ retrieved_at: "${{ now }}"
50
+
51
+ - limit: ${{ args.limit }}
52
+
53
+ columns: [publication_number, title, publication_date]
54
+
55
+ capabilities: ["http.fetch", "patent.search"]
56
+ minimum_capability: http.fetch
57
+ trust: public
58
+ confidentiality: public
59
+ quarantine: false
60
+ schema_version: v2
@@ -0,0 +1,79 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import { extractRedditCommentRows } from "./comments.js";
4
+ import { normalizeCommentRows } from "../../social/comments.js";
5
+
6
+ describe("reddit comments tree extraction", () => {
7
+ it("preserves nested reply hierarchy from Reddit JSON listings", () => {
8
+ const rawRows = extractRedditCommentRows(
9
+ [
10
+ { data: { children: [] } },
11
+ {
12
+ data: {
13
+ children: [
14
+ {
15
+ kind: "t1",
16
+ data: {
17
+ id: "root",
18
+ name: "t1_root",
19
+ parent_id: "t3_post",
20
+ author: "alice",
21
+ body: "root body",
22
+ score: 10,
23
+ created_utc: 1,
24
+ replies: {
25
+ data: {
26
+ children: [
27
+ {
28
+ kind: "t1",
29
+ data: {
30
+ id: "child",
31
+ name: "t1_child",
32
+ parent_id: "t1_root",
33
+ author: "bob",
34
+ body: "child body",
35
+ score: 3,
36
+ created_utc: 2,
37
+ replies: "",
38
+ },
39
+ },
40
+ ],
41
+ },
42
+ },
43
+ },
44
+ },
45
+ ],
46
+ },
47
+ },
48
+ ],
49
+ "r/test/comments/post/title",
50
+ );
51
+
52
+ const rows = normalizeCommentRows(rawRows, {
53
+ platform: "reddit",
54
+ contentId: "r/test/comments/post/title",
55
+ });
56
+
57
+ expect(rows).toEqual([
58
+ expect.objectContaining({
59
+ comment_id: "t1_root",
60
+ parent_id: "",
61
+ depth: 0,
62
+ path: "0001",
63
+ author: "alice",
64
+ text: "root body",
65
+ likes: 10,
66
+ replies: 1,
67
+ }),
68
+ expect.objectContaining({
69
+ comment_id: "t1_child",
70
+ parent_id: "t1_root",
71
+ depth: 1,
72
+ path: "0001.0001",
73
+ author: "bob",
74
+ text: "child body",
75
+ likes: 3,
76
+ }),
77
+ ]);
78
+ });
79
+ });