@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
@@ -7,8 +7,12 @@
7
7
 
8
8
  import { cli, Strategy } from "../../registry.js";
9
9
  import { wbiFetch } from "./wbi.js";
10
- import { loadCookies, formatCookieHeader } from "../../engine/cookies.js";
10
+ import {
11
+ loadCookiesWithCDP,
12
+ formatCookieHeader,
13
+ } from "../../engine/cookies.js";
11
14
  import { USER_AGENT } from "../../constants.js";
15
+ import { normalizeCommentRows } from "../../social/comments.js";
12
16
 
13
17
  interface ViewResponse {
14
18
  data: {
@@ -17,10 +21,14 @@ interface ViewResponse {
17
21
  }
18
22
 
19
23
  interface CommentItem {
24
+ rpid?: number;
25
+ root?: number;
26
+ parent?: number;
20
27
  member: { uname: string };
21
28
  content: { message: string };
22
29
  like: number;
23
30
  rcount: number;
31
+ ctime?: number;
24
32
  }
25
33
 
26
34
  interface CommentsResponse {
@@ -31,7 +39,7 @@ interface CommentsResponse {
31
39
 
32
40
  /** Fetch video aid from bvid using the view API (not WBI-signed). */
33
41
  async function resolveAid(bvid: string): Promise<number> {
34
- const cookies = loadCookies("bilibili");
42
+ const cookies = await loadCookiesWithCDP("bilibili", "bilibili.com");
35
43
  const headers: Record<string, string> = {
36
44
  "User-Agent": USER_AGENT,
37
45
  Accept: "application/json",
@@ -69,11 +77,32 @@ cli({
69
77
  default: 20,
70
78
  description: "Number of comments",
71
79
  },
80
+ {
81
+ name: "with-replies",
82
+ type: "bool",
83
+ default: false,
84
+ description: "Include nested replies for each root comment",
85
+ },
86
+ ],
87
+ columns: [
88
+ "platform",
89
+ "content_id",
90
+ "comment_id",
91
+ "parent_id",
92
+ "depth",
93
+ "path",
94
+ "author",
95
+ "text",
96
+ "likes",
97
+ "replies",
98
+ "created",
99
+ "user",
100
+ "content",
72
101
  ],
73
- columns: ["user", "content", "likes", "replies"],
74
102
  func: async (_page, kwargs) => {
75
103
  const bvid = String(kwargs.bvid);
76
104
  const limit = Number(kwargs.limit) || 20;
105
+ const withReplies = Boolean(kwargs["with-replies"]);
77
106
 
78
107
  const aid = await resolveAid(bvid);
79
108
 
@@ -84,11 +113,56 @@ cli({
84
113
  ps: String(limit),
85
114
  })) as CommentsResponse;
86
115
 
87
- return (json.data.replies ?? []).map((item) => ({
116
+ const roots = json.data.replies ?? [];
117
+ const rows = roots.map((item) => ({
118
+ id: item.rpid ? String(item.rpid) : "",
119
+ parent_id:
120
+ item.parent && item.parent > 0
121
+ ? String(item.parent)
122
+ : item.root && item.root > 0
123
+ ? String(item.root)
124
+ : "",
88
125
  user: item.member.uname,
126
+ author: item.member.uname,
89
127
  content: item.content.message,
128
+ text: item.content.message,
90
129
  likes: item.like,
91
130
  replies: item.rcount,
131
+ created: item.ctime ? String(item.ctime) : "",
92
132
  }));
133
+
134
+ if (withReplies) {
135
+ for (const root of roots) {
136
+ if (!root.rpid || root.rcount <= 0) continue;
137
+ const repliesJson = (await wbiFetch(
138
+ "https://api.bilibili.com/x/v2/reply/reply",
139
+ {
140
+ oid: String(aid),
141
+ type: "1",
142
+ root: String(root.rpid),
143
+ ps: "20",
144
+ pn: "1",
145
+ },
146
+ )) as CommentsResponse;
147
+ for (const reply of repliesJson.data.replies ?? []) {
148
+ rows.push({
149
+ id: reply.rpid ? String(reply.rpid) : "",
150
+ parent_id: String(root.rpid),
151
+ user: reply.member.uname,
152
+ author: reply.member.uname,
153
+ content: reply.content.message,
154
+ text: reply.content.message,
155
+ likes: reply.like,
156
+ replies: reply.rcount,
157
+ created: reply.ctime ? String(reply.ctime) : "",
158
+ });
159
+ }
160
+ }
161
+ }
162
+
163
+ return normalizeCommentRows(rows, {
164
+ platform: "bilibili",
165
+ contentId: bvid,
166
+ });
93
167
  },
94
168
  });
@@ -1,10 +1,13 @@
1
1
  import { cli, Strategy } from "../../registry.js";
2
- import { loadCookies, formatCookieHeader } from "../../engine/cookies.js";
2
+ import {
3
+ loadCookiesWithCDP,
4
+ formatCookieHeader,
5
+ } from "../../engine/cookies.js";
3
6
  import { USER_AGENT } from "../../constants.js";
4
7
  import { intArg, str } from "../_shared/browser-tools.js";
5
8
 
6
9
  async function bilibiliJson(url: string): Promise<Record<string, unknown>> {
7
- const cookies = loadCookies("bilibili");
10
+ const cookies = await loadCookiesWithCDP("bilibili", "bilibili.com");
8
11
  const headers: Record<string, string> = {
9
12
  "user-agent": USER_AGENT,
10
13
  referer: "https://www.bilibili.com",
@@ -8,7 +8,10 @@
8
8
  */
9
9
 
10
10
  import { cli, Strategy } from "../../registry.js";
11
- import { loadCookies, formatCookieHeader } from "../../engine/cookies.js";
11
+ import {
12
+ loadCookiesWithCDP,
13
+ formatCookieHeader,
14
+ } from "../../engine/cookies.js";
12
15
  import { USER_AGENT } from "../../constants.js";
13
16
 
14
17
  interface ViewResponse {
@@ -47,8 +50,8 @@ interface PlayurlResponse {
47
50
  }
48
51
 
49
52
  /** Build authenticated headers for Bilibili API calls. */
50
- function buildHeaders(): Record<string, string> {
51
- const cookies = loadCookies("bilibili");
53
+ async function buildHeaders(): Promise<Record<string, string>> {
54
+ const cookies = await loadCookiesWithCDP("bilibili", "bilibili.com");
52
55
  const headers: Record<string, string> = {
53
56
  "User-Agent": USER_AGENT,
54
57
  Accept: "application/json",
@@ -75,7 +78,7 @@ cli({
75
78
  columns: ["type", "quality", "codecs", "size", "url"],
76
79
  func: async (_page, kwargs) => {
77
80
  const bvid = String(kwargs.bvid);
78
- const headers = buildHeaders();
81
+ const headers = await buildHeaders();
79
82
 
80
83
  // Step 1: resolve cid from bvid
81
84
  const viewResp = await fetch(
@@ -6,7 +6,10 @@
6
6
  */
7
7
 
8
8
  import { createHash } from "node:crypto";
9
- import { loadCookies, formatCookieHeader } from "../../engine/cookies.js";
9
+ import {
10
+ loadCookiesWithCDP,
11
+ formatCookieHeader,
12
+ } from "../../engine/cookies.js";
10
13
  import { USER_AGENT } from "../../constants.js";
11
14
 
12
15
  const MIXIN_KEY_ENC_TAB = [
@@ -31,7 +34,7 @@ async function fetchWbiKeys(): Promise<string> {
31
34
  const now = Date.now();
32
35
  if (cachedMixinKey && now - cachedAt < CACHE_TTL) return cachedMixinKey;
33
36
 
34
- const cookies = loadCookies("bilibili");
37
+ const cookies = await loadCookiesWithCDP("bilibili", "bilibili.com");
35
38
  const headers: Record<string, string> = { "User-Agent": USER_AGENT };
36
39
  if (cookies) headers["Cookie"] = formatCookieHeader(cookies);
37
40
 
@@ -76,7 +79,7 @@ export async function wbiFetch(
76
79
  const query = await signWbi(params);
77
80
  const url = `${baseUrl}?${query}`;
78
81
 
79
- const cookies = loadCookies("bilibili");
82
+ const cookies = await loadCookiesWithCDP("bilibili", "bilibili.com");
80
83
  const headers: Record<string, string> = {
81
84
  "User-Agent": USER_AGENT,
82
85
  Accept: "application/json",
@@ -0,0 +1,53 @@
1
+ # Brave Search — keyless HTML scrape against the public web result page.
2
+ #
3
+ # verification_status: keyless-best-effort
4
+ #
5
+ # Brave operates a paid Search API at https://api.search.brave.com — that
6
+ # path needs an X-Subscription-Token header (free 2000 queries/month plan).
7
+ # This adapter takes the no-key route: hit https://search.brave.com/search
8
+ # and parse the SSR-emitted result list. Anti-bot may rate-limit aggressive
9
+ # loops; results are best-effort, not guaranteed parity with the API.
10
+ site: brave
11
+ name: search
12
+ description: Search the public web via Brave Search (no API key needed)
13
+ type: web-api
14
+ domain: search.brave.com
15
+ strategy: public
16
+ lint_listing_detail: skip
17
+
18
+ args:
19
+ query:
20
+ type: str
21
+ required: true
22
+ positional: true
23
+ description: Free-text web search query
24
+ limit:
25
+ type: int
26
+ default: 10
27
+ description: Maximum results returned (page caps around 20)
28
+
29
+ pipeline:
30
+ - fetch_text:
31
+ url: "https://search.brave.com/search?q=${{ args.query | url_encode }}&source=web"
32
+ headers:
33
+ 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"
34
+ Accept: "text/html,application/xhtml+xml"
35
+
36
+ - extract:
37
+ selector: "div.snippet[data-type='web']"
38
+ fields:
39
+ title: "div.snippet-title"
40
+ url: "a@href"
41
+ snippet: ".snippet-description"
42
+
43
+ - limit: ${{ args.limit }}
44
+
45
+ columns: [title, url, snippet]
46
+
47
+ # schema-v2 metadata
48
+ capabilities: ["http.fetch"]
49
+ minimum_capability: http.fetch
50
+ trust: public
51
+ confidentiality: public
52
+ quarantine: false
53
+ schema_version: v2
@@ -0,0 +1,98 @@
1
+ /**
2
+ * @owner src::adapters::cipo::_shared
3
+ * @does Shared helpers for the CIPO Canadian Patents Database browser adapter — emits structured envelopes for MCP-bus / not-found / schema-drift gaps.
4
+ * @needs src/engine/transport/mcp-browser.ts, src/engine/normalizer/patent-envelope.ts, src/types/patent.ts
5
+ * @feeds src/adapters/cipo/*.ts
6
+ * @breaks none — pure helpers
7
+ * @invariants every error path emits a PatentEnvelope row
8
+ * @side-effects none
9
+ * @perf n/a
10
+ * @concurrency safe
11
+ * @test covered transitively
12
+ * @stability experimental
13
+ * @since 2026-05-18
14
+ * @verification browser-only
15
+ */
16
+
17
+ import {
18
+ TransportError,
19
+ initMcpBrowserTransport,
20
+ mcpBrowserEvaluate,
21
+ mcpBrowserNavigate,
22
+ type McpBrowserResult,
23
+ } from "../../engine/transport/mcp-browser.js";
24
+ import { buildPatentEnvelope } from "../../engine/normalizer/patent-envelope.js";
25
+ import type { PatentEnvelope, PatentErrorCode } from "../../types/patent.js";
26
+
27
+ export function cipoEnvelope(
28
+ code: PatentErrorCode,
29
+ adapter_path: string,
30
+ step: string,
31
+ suggestion: string,
32
+ alternatives: string[] = [],
33
+ ): PatentEnvelope {
34
+ return buildPatentEnvelope({
35
+ code,
36
+ adapter_path,
37
+ step,
38
+ suggestion,
39
+ alternatives,
40
+ retryable: false,
41
+ });
42
+ }
43
+
44
+ export function transportErrorToCipoEnvelope(
45
+ err: TransportError,
46
+ adapter_path: string,
47
+ step: string,
48
+ ): PatentEnvelope {
49
+ if (err.code === "MCP_BUS_MISSING") {
50
+ return buildPatentEnvelope({
51
+ code: "PATENT_API_DEPRECATED",
52
+ adapter_path,
53
+ step,
54
+ suggestion:
55
+ "engine has no outbound MCP transport wired into the bus today; install an McpResolver before invoking the CIPO browser adapter, or use uspto/epo as a partial fallback",
56
+ alternatives: ["uspto", "epo", "lens"],
57
+ retryable: false,
58
+ });
59
+ }
60
+ return buildPatentEnvelope({
61
+ code: "PATENT_API_DEPRECATED",
62
+ adapter_path,
63
+ step,
64
+ suggestion: `mcp-browser transport error (${err.code}): ${err.message}`,
65
+ alternatives: ["uspto", "epo"],
66
+ retryable: false,
67
+ });
68
+ }
69
+
70
+ export async function cipoNavigateAndExtract<T>(
71
+ url: string,
72
+ expression: string,
73
+ ): Promise<McpBrowserResult<T>> {
74
+ const init = await initMcpBrowserTransport();
75
+ if (init.active_server === "none") {
76
+ const code =
77
+ init.reason === "bus-missing" ? "MCP_BUS_MISSING" : "MCP_NO_SERVER";
78
+ throw new TransportError(code, `mcp-browser unavailable (${init.reason})`);
79
+ }
80
+ const navResult = await mcpBrowserNavigate({ url });
81
+ if (!navResult.ok) {
82
+ throw new TransportError(
83
+ navResult.code ?? "MCP_NAVIGATE_FAILED",
84
+ navResult.message ?? "navigate did not succeed",
85
+ );
86
+ }
87
+ const evalResult = await mcpBrowserEvaluate<T>({
88
+ expression,
89
+ tab: navResult.tab,
90
+ });
91
+ if (!evalResult.ok) {
92
+ throw new TransportError(
93
+ evalResult.code ?? "MCP_EVALUATE_FAILED",
94
+ evalResult.message ?? "evaluate did not succeed",
95
+ );
96
+ }
97
+ return evalResult;
98
+ }
@@ -0,0 +1,188 @@
1
+ /**
2
+ * @owner src::adapters::cipo::get
3
+ * @does Browser-driven CIPO single-document retrieval — Canadian Patents Database detail page extracted into a PatentRecord.
4
+ * @needs src/engine/transport/mcp-browser.ts, src/engine/normalizer/patent-envelope.ts, src/adapters/cipo/_shared.ts, src/registry.ts
5
+ * @feeds src/commands/patent.ts (capability tag patent.get)
6
+ * @breaks PATENT_INVALID_NUMBER, PATENT_NOT_FOUND, PATENT_API_DEPRECATED (MCP_BUS_MISSING)
7
+ * @invariants output row is a canonical PatentRecord
8
+ * @side-effects controls Chrome via MCP
9
+ * @perf single navigate + evaluate
10
+ * @concurrency safe
11
+ * @test tests/unit/adapters/cipo/search.test.ts (transport-error shared path)
12
+ * @stability experimental
13
+ * @since 2026-05-18
14
+ * @verification browser-only
15
+ */
16
+
17
+ import { cli, Strategy } from "../../registry.js";
18
+ import { TransportError } from "../../engine/transport/mcp-browser.js";
19
+ import { assemblePatentRecord } from "../../engine/normalizer/patent-envelope.js";
20
+ import {
21
+ cipoEnvelope,
22
+ cipoNavigateAndExtract,
23
+ transportErrorToCipoEnvelope,
24
+ } from "./_shared.js";
25
+
26
+ const ADAPTER_PATH = "src/adapters/cipo/get.ts";
27
+
28
+ interface CipoDetail {
29
+ publication_number?: string;
30
+ application_number?: string;
31
+ title?: string;
32
+ abstract?: string;
33
+ applicant?: string;
34
+ inventor?: string;
35
+ publication_date?: string;
36
+ filing_date?: string;
37
+ grant_date?: string;
38
+ source_url?: string;
39
+ }
40
+
41
+ const DETAIL_EXTRACTOR = `(() => {
42
+ const text = (sel) => {
43
+ const node = document.querySelector(sel);
44
+ return node ? (node.textContent || '').trim() : '';
45
+ };
46
+ return {
47
+ publication_number: text('.patent-number, [data-field="patentNo"]'),
48
+ application_number: text('.application-number, [data-field="appNo"]'),
49
+ title: text('.patent-title, h1.title, [data-field="title"]'),
50
+ abstract: text('.abstract, [data-field="abstract"]'),
51
+ applicant: text('.applicant-name, [data-field="applicant"]'),
52
+ inventor: text('.inventor-name, [data-field="inventor"]'),
53
+ publication_date: text('.publication-date, [data-field="pubDate"]'),
54
+ filing_date: text('.filing-date, [data-field="filingDate"]'),
55
+ grant_date: text('.grant-date, [data-field="grantDate"]'),
56
+ source_url: location.href,
57
+ };
58
+ })()`;
59
+
60
+ function detailUrlFor(pubNo: string): string {
61
+ const stripped = pubNo.replace(/^CA[-]?/, "");
62
+ return `https://cipo.ic.gc.ca/opic-cipo/cpd/eng/patent/${encodeURIComponent(stripped)}/summary.html`;
63
+ }
64
+
65
+ export async function runCipoGet(kwargs: {
66
+ publication_number: string;
67
+ }): Promise<unknown[]> {
68
+ const pubNo = String(kwargs.publication_number ?? "").trim();
69
+ if (pubNo.length === 0) {
70
+ return [
71
+ {
72
+ envelope: cipoEnvelope(
73
+ "PATENT_INVALID_NUMBER",
74
+ ADAPTER_PATH,
75
+ "validate",
76
+ "cipo get requires a non-empty publication_number",
77
+ ),
78
+ },
79
+ ];
80
+ }
81
+ const url = detailUrlFor(pubNo);
82
+ let detail: CipoDetail;
83
+ try {
84
+ const result = await cipoNavigateAndExtract<CipoDetail>(
85
+ url,
86
+ DETAIL_EXTRACTOR,
87
+ );
88
+ if (!result.data) {
89
+ return [
90
+ {
91
+ envelope: cipoEnvelope(
92
+ "PATENT_SCHEMA_DRIFT",
93
+ ADAPTER_PATH,
94
+ "evaluate",
95
+ "cipo detail evaluate returned no data",
96
+ ),
97
+ },
98
+ ];
99
+ }
100
+ detail = result.data;
101
+ } catch (err) {
102
+ if (err instanceof TransportError) {
103
+ return [
104
+ {
105
+ envelope: transportErrorToCipoEnvelope(err, ADAPTER_PATH, "navigate"),
106
+ },
107
+ ];
108
+ }
109
+ throw err;
110
+ }
111
+ if (!detail.publication_number && !detail.title) {
112
+ return [
113
+ {
114
+ envelope: cipoEnvelope(
115
+ "PATENT_NOT_FOUND",
116
+ ADAPTER_PATH,
117
+ "evaluate",
118
+ `cipo detail page for "${pubNo}" yielded no bibliographic fields`,
119
+ ["uspto", "epo"],
120
+ ),
121
+ },
122
+ ];
123
+ }
124
+ const rawPubNo = detail.publication_number || pubNo;
125
+ const canonicalPubNo = /^CA[-]?/.test(rawPubNo) ? rawPubNo : `CA${rawPubNo}`;
126
+ try {
127
+ return [
128
+ assemblePatentRecord({
129
+ publication_number: canonicalPubNo,
130
+ application_number: detail.application_number || undefined,
131
+ title: detail.title || undefined,
132
+ abstract: detail.abstract || undefined,
133
+ assignees: detail.applicant
134
+ ? [{ name: detail.applicant, country: "CA" }]
135
+ : undefined,
136
+ inventors: detail.inventor
137
+ ? [{ name: detail.inventor, country: "CA" }]
138
+ : undefined,
139
+ publication_date: detail.publication_date || undefined,
140
+ filing_date: detail.filing_date || undefined,
141
+ grant_date: detail.grant_date || undefined,
142
+ source_adapter: "cipo",
143
+ source_url: detail.source_url || url,
144
+ } as Parameters<typeof assemblePatentRecord>[0]),
145
+ ];
146
+ } catch {
147
+ return [
148
+ {
149
+ envelope: cipoEnvelope(
150
+ "PATENT_NOT_FOUND",
151
+ ADAPTER_PATH,
152
+ "normalize",
153
+ `cipo detail page for "${pubNo}" did not yield a valid publication_number`,
154
+ ["uspto"],
155
+ ),
156
+ },
157
+ ];
158
+ }
159
+ }
160
+
161
+ cli({
162
+ site: "cipo",
163
+ name: "get",
164
+ description: "Retrieve a single Canadian patent document (CIPO, browser)",
165
+ domain: "cipo.ic.gc.ca",
166
+ strategy: Strategy.PUBLIC,
167
+ adapter_path: ADAPTER_PATH,
168
+ args: [
169
+ {
170
+ name: "publication_number",
171
+ type: "str",
172
+ required: true,
173
+ positional: true,
174
+ description: "CA publication number (with or without CA prefix)",
175
+ },
176
+ ],
177
+ columns: [
178
+ "publication_number",
179
+ "title",
180
+ "publication_date",
181
+ "grant_date",
182
+ "source_url",
183
+ ],
184
+ capabilities: ["mcp-browser.navigate", "mcp-browser.evaluate", "patent.get"],
185
+ minimum_capability: "mcp-browser.evaluate",
186
+ func: async (_page, kwargs) =>
187
+ runCipoGet(kwargs as { publication_number: string }),
188
+ });
@@ -0,0 +1,148 @@
1
+ /**
2
+ * @owner src::adapters::cipo::legal-status
3
+ * @does Browser-driven CIPO legal-status / prosecution timeline lookup; emits the most recent administrative-status field from the CPD admin tab.
4
+ * @needs src/engine/transport/mcp-browser.ts, src/adapters/cipo/_shared.ts, src/registry.ts
5
+ * @feeds src/commands/patent.ts (capability tag patent.legal-status)
6
+ * @breaks PATENT_INVALID_NUMBER, PATENT_NOT_FOUND, PATENT_API_DEPRECATED (MCP_BUS_MISSING)
7
+ * @invariants output row carries legal_status verbatim as CIPO displayed it
8
+ * @side-effects controls Chrome via MCP
9
+ * @perf single navigate + evaluate
10
+ * @concurrency safe
11
+ * @test tests/unit/adapters/cipo/search.test.ts (shared transport-error path)
12
+ * @stability experimental
13
+ * @since 2026-05-18
14
+ * @verification browser-only
15
+ */
16
+
17
+ import { cli, Strategy } from "../../registry.js";
18
+ import { TransportError } from "../../engine/transport/mcp-browser.js";
19
+ import {
20
+ cipoEnvelope,
21
+ cipoNavigateAndExtract,
22
+ transportErrorToCipoEnvelope,
23
+ } from "./_shared.js";
24
+
25
+ const ADAPTER_PATH = "src/adapters/cipo/legal-status.ts";
26
+
27
+ interface CipoLegalExtract {
28
+ publication_number?: string;
29
+ legal_status?: string;
30
+ status_date?: string;
31
+ source_url?: string;
32
+ }
33
+
34
+ const EXTRACTOR = `(() => {
35
+ const text = (sel) => {
36
+ const node = document.querySelector(sel);
37
+ return node ? (node.textContent || '').trim() : '';
38
+ };
39
+ return {
40
+ publication_number: text('.patent-number, [data-field="patentNo"]'),
41
+ legal_status: text('.admin-status, [data-field="adminStatus"]'),
42
+ status_date: text('.status-date, [data-field="statusDate"]'),
43
+ source_url: location.href,
44
+ };
45
+ })()`;
46
+
47
+ function legalUrlFor(pubNo: string): string {
48
+ const stripped = pubNo.replace(/^CA[-]?/, "");
49
+ return `https://cipo.ic.gc.ca/opic-cipo/cpd/eng/patent/${encodeURIComponent(stripped)}/admin.html`;
50
+ }
51
+
52
+ export async function runCipoLegalStatus(kwargs: {
53
+ publication_number: string;
54
+ }): Promise<unknown[]> {
55
+ const pubNo = String(kwargs.publication_number ?? "").trim();
56
+ if (pubNo.length === 0) {
57
+ return [
58
+ {
59
+ envelope: cipoEnvelope(
60
+ "PATENT_INVALID_NUMBER",
61
+ ADAPTER_PATH,
62
+ "validate",
63
+ "cipo legal-status requires a non-empty publication_number",
64
+ ),
65
+ },
66
+ ];
67
+ }
68
+ const url = legalUrlFor(pubNo);
69
+ let detail: CipoLegalExtract;
70
+ try {
71
+ const result = await cipoNavigateAndExtract<CipoLegalExtract>(
72
+ url,
73
+ EXTRACTOR,
74
+ );
75
+ if (!result.data) {
76
+ return [
77
+ {
78
+ envelope: cipoEnvelope(
79
+ "PATENT_SCHEMA_DRIFT",
80
+ ADAPTER_PATH,
81
+ "evaluate",
82
+ "cipo legal-status evaluate returned no data",
83
+ ),
84
+ },
85
+ ];
86
+ }
87
+ detail = result.data;
88
+ } catch (err) {
89
+ if (err instanceof TransportError) {
90
+ return [
91
+ {
92
+ envelope: transportErrorToCipoEnvelope(err, ADAPTER_PATH, "navigate"),
93
+ },
94
+ ];
95
+ }
96
+ throw err;
97
+ }
98
+ if (!detail.legal_status) {
99
+ return [
100
+ {
101
+ envelope: cipoEnvelope(
102
+ "PATENT_NOT_FOUND",
103
+ ADAPTER_PATH,
104
+ "evaluate",
105
+ `cipo returned no admin/legal-status for "${pubNo}"`,
106
+ ["uspto", "epo"],
107
+ ),
108
+ },
109
+ ];
110
+ }
111
+ return [
112
+ {
113
+ publication_number: detail.publication_number || pubNo,
114
+ legal_status: detail.legal_status,
115
+ status_date: detail.status_date,
116
+ source_adapter: "cipo",
117
+ source_url: detail.source_url || url,
118
+ retrieved_at: new Date().toISOString(),
119
+ },
120
+ ];
121
+ }
122
+
123
+ cli({
124
+ site: "cipo",
125
+ name: "legal-status",
126
+ description: "CIPO Canadian patent administrative-status lookup (browser)",
127
+ domain: "cipo.ic.gc.ca",
128
+ strategy: Strategy.PUBLIC,
129
+ adapter_path: ADAPTER_PATH,
130
+ args: [
131
+ {
132
+ name: "publication_number",
133
+ type: "str",
134
+ required: true,
135
+ positional: true,
136
+ description: "CA publication number",
137
+ },
138
+ ],
139
+ columns: ["publication_number", "legal_status", "status_date", "source_url"],
140
+ capabilities: [
141
+ "mcp-browser.navigate",
142
+ "mcp-browser.evaluate",
143
+ "patent.legal-status",
144
+ ],
145
+ minimum_capability: "mcp-browser.evaluate",
146
+ func: async (_page, kwargs) =>
147
+ runCipoLegalStatus(kwargs as { publication_number: string }),
148
+ });