@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.
- package/AGENTS.md +28 -6
- package/README.md +8 -8
- package/README.zh-CN.md +8 -8
- package/dist/adapters/bilibili/comments.js +66 -4
- package/dist/adapters/bilibili/comments.js.map +1 -1
- package/dist/adapters/bilibili/compat.js +2 -2
- package/dist/adapters/bilibili/compat.js.map +1 -1
- package/dist/adapters/bilibili/download.js +4 -4
- package/dist/adapters/bilibili/download.js.map +1 -1
- package/dist/adapters/bilibili/wbi.d.ts.map +1 -1
- package/dist/adapters/bilibili/wbi.js +3 -3
- package/dist/adapters/bilibili/wbi.js.map +1 -1
- package/dist/adapters/cipo/_shared.d.ts +21 -0
- package/dist/adapters/cipo/_shared.d.ts.map +1 -0
- package/dist/adapters/cipo/_shared.js +67 -0
- package/dist/adapters/cipo/_shared.js.map +1 -0
- package/dist/adapters/cipo/get.d.ts +19 -0
- package/dist/adapters/cipo/get.d.ts.map +1 -0
- package/dist/adapters/cipo/get.js +140 -0
- package/dist/adapters/cipo/get.js.map +1 -0
- package/dist/adapters/cipo/legal-status.d.ts +19 -0
- package/dist/adapters/cipo/legal-status.d.ts.map +1 -0
- package/dist/adapters/cipo/legal-status.js +111 -0
- package/dist/adapters/cipo/legal-status.js.map +1 -0
- package/dist/adapters/cipo/search.d.ts +20 -0
- package/dist/adapters/cipo/search.d.ts.map +1 -0
- package/dist/adapters/cipo/search.js +148 -0
- package/dist/adapters/cipo/search.js.map +1 -0
- package/dist/adapters/cnipa/_shared.d.ts +47 -0
- package/dist/adapters/cnipa/_shared.d.ts.map +1 -0
- package/dist/adapters/cnipa/_shared.js +97 -0
- package/dist/adapters/cnipa/_shared.js.map +1 -0
- package/dist/adapters/cnipa/get.d.ts +19 -0
- package/dist/adapters/cnipa/get.d.ts.map +1 -0
- package/dist/adapters/cnipa/get.js +149 -0
- package/dist/adapters/cnipa/get.js.map +1 -0
- package/dist/adapters/cnipa/legal-status.d.ts +19 -0
- package/dist/adapters/cnipa/legal-status.d.ts.map +1 -0
- package/dist/adapters/cnipa/legal-status.js +119 -0
- package/dist/adapters/cnipa/legal-status.js.map +1 -0
- package/dist/adapters/cnipa/search.d.ts +21 -0
- package/dist/adapters/cnipa/search.d.ts.map +1 -0
- package/dist/adapters/cnipa/search.js +170 -0
- package/dist/adapters/cnipa/search.js.map +1 -0
- package/dist/adapters/espacenet/_shared.d.ts +21 -0
- package/dist/adapters/espacenet/_shared.d.ts.map +1 -0
- package/dist/adapters/espacenet/_shared.js +67 -0
- package/dist/adapters/espacenet/_shared.js.map +1 -0
- package/dist/adapters/espacenet/family.d.ts +19 -0
- package/dist/adapters/espacenet/family.d.ts.map +1 -0
- package/dist/adapters/espacenet/family.js +118 -0
- package/dist/adapters/espacenet/family.js.map +1 -0
- package/dist/adapters/espacenet/get.d.ts +19 -0
- package/dist/adapters/espacenet/get.d.ts.map +1 -0
- package/dist/adapters/espacenet/get.js +130 -0
- package/dist/adapters/espacenet/get.js.map +1 -0
- package/dist/adapters/espacenet/legal-status.d.ts +19 -0
- package/dist/adapters/espacenet/legal-status.d.ts.map +1 -0
- package/dist/adapters/espacenet/legal-status.js +110 -0
- package/dist/adapters/espacenet/legal-status.js.map +1 -0
- package/dist/adapters/espacenet/search.d.ts +20 -0
- package/dist/adapters/espacenet/search.d.ts.map +1 -0
- package/dist/adapters/espacenet/search.js +165 -0
- package/dist/adapters/espacenet/search.js.map +1 -0
- package/dist/adapters/facebook/subtitles.d.ts +9 -0
- package/dist/adapters/facebook/subtitles.d.ts.map +1 -0
- package/dist/adapters/facebook/subtitles.js +42 -0
- package/dist/adapters/facebook/subtitles.js.map +1 -0
- package/dist/adapters/fips/_shared.d.ts +21 -0
- package/dist/adapters/fips/_shared.d.ts.map +1 -0
- package/dist/adapters/fips/_shared.js +77 -0
- package/dist/adapters/fips/_shared.js.map +1 -0
- package/dist/adapters/fips/get.d.ts +19 -0
- package/dist/adapters/fips/get.d.ts.map +1 -0
- package/dist/adapters/fips/get.js +139 -0
- package/dist/adapters/fips/get.js.map +1 -0
- package/dist/adapters/fips/search.d.ts +20 -0
- package/dist/adapters/fips/search.d.ts.map +1 -0
- package/dist/adapters/fips/search.js +148 -0
- package/dist/adapters/fips/search.js.map +1 -0
- package/dist/adapters/freepatentsonline-web/_shared.d.ts +72 -0
- package/dist/adapters/freepatentsonline-web/_shared.d.ts.map +1 -0
- package/dist/adapters/freepatentsonline-web/_shared.js +216 -0
- package/dist/adapters/freepatentsonline-web/_shared.js.map +1 -0
- package/dist/adapters/freepatentsonline-web/get.d.ts +21 -0
- package/dist/adapters/freepatentsonline-web/get.d.ts.map +1 -0
- package/dist/adapters/freepatentsonline-web/get.js +127 -0
- package/dist/adapters/freepatentsonline-web/get.js.map +1 -0
- package/dist/adapters/freepatentsonline-web/search.d.ts +22 -0
- package/dist/adapters/freepatentsonline-web/search.d.ts.map +1 -0
- package/dist/adapters/freepatentsonline-web/search.js +149 -0
- package/dist/adapters/freepatentsonline-web/search.js.map +1 -0
- package/dist/adapters/google-patents-web/_shared.d.ts +110 -0
- package/dist/adapters/google-patents-web/_shared.d.ts.map +1 -0
- package/dist/adapters/google-patents-web/_shared.js +164 -0
- package/dist/adapters/google-patents-web/_shared.js.map +1 -0
- package/dist/adapters/google-patents-web/get.d.ts +36 -0
- package/dist/adapters/google-patents-web/get.d.ts.map +1 -0
- package/dist/adapters/google-patents-web/get.js +187 -0
- package/dist/adapters/google-patents-web/get.js.map +1 -0
- package/dist/adapters/google-patents-web/search.d.ts +23 -0
- package/dist/adapters/google-patents-web/search.d.ts.map +1 -0
- package/dist/adapters/google-patents-web/search.js +169 -0
- package/dist/adapters/google-patents-web/search.js.map +1 -0
- package/dist/adapters/inpi-br/_shared.d.ts +21 -0
- package/dist/adapters/inpi-br/_shared.d.ts.map +1 -0
- package/dist/adapters/inpi-br/_shared.js +67 -0
- package/dist/adapters/inpi-br/_shared.js.map +1 -0
- package/dist/adapters/inpi-br/get.d.ts +19 -0
- package/dist/adapters/inpi-br/get.d.ts.map +1 -0
- package/dist/adapters/inpi-br/get.js +142 -0
- package/dist/adapters/inpi-br/get.js.map +1 -0
- package/dist/adapters/inpi-br/search.d.ts +20 -0
- package/dist/adapters/inpi-br/search.d.ts.map +1 -0
- package/dist/adapters/inpi-br/search.js +154 -0
- package/dist/adapters/inpi-br/search.js.map +1 -0
- package/dist/adapters/instagram/subtitles.d.ts +9 -0
- package/dist/adapters/instagram/subtitles.d.ts.map +1 -0
- package/dist/adapters/instagram/subtitles.js +42 -0
- package/dist/adapters/instagram/subtitles.js.map +1 -0
- package/dist/adapters/mastodon/statuses.d.ts +40 -0
- package/dist/adapters/mastodon/statuses.d.ts.map +1 -0
- package/dist/adapters/mastodon/statuses.js +153 -0
- package/dist/adapters/mastodon/statuses.js.map +1 -0
- package/dist/adapters/reddit/comments.d.ts +9 -0
- package/dist/adapters/reddit/comments.d.ts.map +1 -0
- package/dist/adapters/reddit/comments.js +124 -0
- package/dist/adapters/reddit/comments.js.map +1 -0
- package/dist/adapters/threads/post.d.ts +32 -0
- package/dist/adapters/threads/post.d.ts.map +1 -0
- package/dist/adapters/threads/post.js +287 -0
- package/dist/adapters/threads/post.js.map +1 -0
- package/dist/adapters/tiktok/subtitles.d.ts +9 -0
- package/dist/adapters/tiktok/subtitles.d.ts.map +1 -0
- package/dist/adapters/tiktok/subtitles.js +42 -0
- package/dist/adapters/tiktok/subtitles.js.map +1 -0
- package/dist/adapters/twitter/accept.js +2 -2
- package/dist/adapters/twitter/accept.js.map +1 -1
- package/dist/adapters/twitter/browser-fallback.d.ts +26 -0
- package/dist/adapters/twitter/browser-fallback.d.ts.map +1 -0
- package/dist/adapters/twitter/browser-fallback.js +93 -0
- package/dist/adapters/twitter/browser-fallback.js.map +1 -0
- package/dist/adapters/twitter/browser-state.d.ts +11 -0
- package/dist/adapters/twitter/browser-state.d.ts.map +1 -0
- package/dist/adapters/twitter/browser-state.js +46 -0
- package/dist/adapters/twitter/browser-state.js.map +1 -0
- package/dist/adapters/twitter/client.d.ts.map +1 -1
- package/dist/adapters/twitter/client.js +36 -13
- package/dist/adapters/twitter/client.js.map +1 -1
- package/dist/adapters/twitter/reply-dm.js +2 -2
- package/dist/adapters/twitter/reply-dm.js.map +1 -1
- package/dist/adapters/twitter/reply.js +1 -0
- package/dist/adapters/twitter/reply.js.map +1 -1
- package/dist/adapters/twitter/search.js +11 -18
- package/dist/adapters/twitter/search.js.map +1 -1
- package/dist/adapters/twitter/thread.d.ts +14 -0
- package/dist/adapters/twitter/thread.d.ts.map +1 -1
- package/dist/adapters/twitter/thread.js +28 -2
- package/dist/adapters/twitter/thread.js.map +1 -1
- package/dist/adapters/twitter/trending.js +13 -59
- package/dist/adapters/twitter/trending.js.map +1 -1
- package/dist/adapters/xiaohongshu/browser-state.d.ts +19 -0
- package/dist/adapters/xiaohongshu/browser-state.d.ts.map +1 -0
- package/dist/adapters/xiaohongshu/browser-state.js +67 -0
- package/dist/adapters/xiaohongshu/browser-state.js.map +1 -0
- package/dist/adapters/xiaohongshu/comments.js +28 -5
- package/dist/adapters/xiaohongshu/comments.js.map +1 -1
- package/dist/adapters/xiaohongshu/download.js +49 -11
- package/dist/adapters/xiaohongshu/download.js.map +1 -1
- package/dist/adapters/xiaohongshu/search.d.ts.map +1 -1
- package/dist/adapters/xiaohongshu/search.js +11 -5
- package/dist/adapters/xiaohongshu/search.js.map +1 -1
- package/dist/adapters/xiaohongshu/trending.d.ts +9 -0
- package/dist/adapters/xiaohongshu/trending.d.ts.map +1 -0
- package/dist/adapters/xiaohongshu/trending.js +94 -0
- package/dist/adapters/xiaohongshu/trending.js.map +1 -0
- package/dist/adapters/youtube/comments.d.ts +80 -0
- package/dist/adapters/youtube/comments.d.ts.map +1 -1
- package/dist/adapters/youtube/comments.js +108 -12
- package/dist/adapters/youtube/comments.js.map +1 -1
- package/dist/adapters/youtube/subtitles.d.ts +9 -0
- package/dist/adapters/youtube/subtitles.d.ts.map +1 -0
- package/dist/adapters/youtube/subtitles.js +42 -0
- package/dist/adapters/youtube/subtitles.js.map +1 -0
- package/dist/adapters/yt-dlp/subtitles.d.ts +9 -0
- package/dist/adapters/yt-dlp/subtitles.d.ts.map +1 -0
- package/dist/adapters/yt-dlp/subtitles.js +41 -0
- package/dist/adapters/yt-dlp/subtitles.js.map +1 -0
- package/dist/adapters/zhihu/answer-detail.d.ts +39 -0
- package/dist/adapters/zhihu/answer-detail.d.ts.map +1 -0
- package/dist/adapters/zhihu/answer-detail.js +204 -0
- package/dist/adapters/zhihu/answer-detail.js.map +1 -0
- package/dist/adapters/zhihu/comment.d.ts +9 -0
- package/dist/adapters/zhihu/comment.d.ts.map +1 -0
- package/dist/adapters/zhihu/comment.js +149 -0
- package/dist/adapters/zhihu/comment.js.map +1 -0
- package/dist/adapters/zhihu/recommend.d.ts +36 -0
- package/dist/adapters/zhihu/recommend.d.ts.map +1 -0
- package/dist/adapters/zhihu/recommend.js +151 -0
- package/dist/adapters/zhihu/recommend.js.map +1 -0
- package/dist/browser/bridge.d.ts.map +1 -1
- package/dist/browser/bridge.js +14 -3
- package/dist/browser/bridge.js.map +1 -1
- package/dist/browser/daemon-client.d.ts +6 -0
- package/dist/browser/daemon-client.d.ts.map +1 -1
- package/dist/browser/daemon-client.js +75 -15
- package/dist/browser/daemon-client.js.map +1 -1
- package/dist/browser/daemon.js +39 -15
- package/dist/browser/daemon.js.map +1 -1
- package/dist/browser/protocol.d.ts +1 -0
- package/dist/browser/protocol.d.ts.map +1 -1
- package/dist/browser/protocol.js +1 -0
- package/dist/browser/protocol.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/approvals.d.ts.map +1 -1
- package/dist/commands/approvals.js +1 -37
- package/dist/commands/approvals.js.map +1 -1
- package/dist/commands/browser/index.d.ts.map +1 -1
- package/dist/commands/browser/index.js +7 -2
- package/dist/commands/browser/index.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +7 -3
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/dispatch.d.ts.map +1 -1
- package/dist/commands/dispatch.js +27 -3
- package/dist/commands/dispatch.js.map +1 -1
- package/dist/commands/patent-doctor.d.ts +48 -0
- package/dist/commands/patent-doctor.d.ts.map +1 -0
- package/dist/commands/patent-doctor.js +109 -0
- package/dist/commands/patent-doctor.js.map +1 -0
- package/dist/commands/patent.d.ts +78 -0
- package/dist/commands/patent.d.ts.map +1 -0
- package/dist/commands/patent.js +919 -0
- package/dist/commands/patent.js.map +1 -0
- package/dist/commands/social.d.ts +19 -0
- package/dist/commands/social.d.ts.map +1 -0
- package/dist/commands/social.js +236 -0
- package/dist/commands/social.js.map +1 -0
- package/dist/core/registry.d.ts +1 -1
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/registry.js +11 -2
- package/dist/core/registry.js.map +1 -1
- package/dist/discovery/loader.d.ts.map +1 -1
- package/dist/discovery/loader.js +4 -0
- package/dist/discovery/loader.js.map +1 -1
- package/dist/engine/approval-presenter.d.ts +10 -0
- package/dist/engine/approval-presenter.d.ts.map +1 -0
- package/dist/engine/approval-presenter.js +45 -0
- package/dist/engine/approval-presenter.js.map +1 -0
- package/dist/engine/approval-store.d.ts +4 -0
- package/dist/engine/approval-store.d.ts.map +1 -1
- package/dist/engine/approval-store.js +85 -11
- package/dist/engine/approval-store.js.map +1 -1
- package/dist/engine/auth/oauth2-cc.d.ts +67 -0
- package/dist/engine/auth/oauth2-cc.d.ts.map +1 -0
- package/dist/engine/auth/oauth2-cc.js +120 -0
- package/dist/engine/auth/oauth2-cc.js.map +1 -0
- package/dist/engine/cookies.d.ts +10 -0
- package/dist/engine/cookies.d.ts.map +1 -1
- package/dist/engine/cookies.js +64 -0
- package/dist/engine/cookies.js.map +1 -1
- package/dist/engine/download.d.ts +5 -0
- package/dist/engine/download.d.ts.map +1 -1
- package/dist/engine/download.js +11 -4
- package/dist/engine/download.js.map +1 -1
- package/dist/engine/executor.d.ts +1 -0
- package/dist/engine/executor.d.ts.map +1 -1
- package/dist/engine/executor.js +25 -0
- package/dist/engine/executor.js.map +1 -1
- package/dist/engine/framework.d.ts +5 -5
- package/dist/engine/framework.js +5 -5
- package/dist/engine/harden.d.ts +1 -1
- package/dist/engine/harden.js +1 -1
- package/dist/engine/kernel/stages.d.ts.map +1 -1
- package/dist/engine/kernel/stages.js +2 -1
- package/dist/engine/kernel/stages.js.map +1 -1
- package/dist/engine/normalizer/patent-envelope.d.ts +61 -0
- package/dist/engine/normalizer/patent-envelope.d.ts.map +1 -0
- package/dist/engine/normalizer/patent-envelope.js +132 -0
- package/dist/engine/normalizer/patent-envelope.js.map +1 -0
- package/dist/engine/research.d.ts +5 -7
- package/dist/engine/research.d.ts.map +1 -1
- package/dist/engine/research.js +6 -9
- package/dist/engine/research.js.map +1 -1
- package/dist/engine/steps/browser-helpers.d.ts +2 -2
- package/dist/engine/steps/browser-helpers.d.ts.map +1 -1
- package/dist/engine/steps/browser-helpers.js +39 -16
- package/dist/engine/steps/browser-helpers.js.map +1 -1
- package/dist/engine/steps/download.d.ts +1 -0
- package/dist/engine/steps/download.d.ts.map +1 -1
- package/dist/engine/steps/download.js +3 -1
- package/dist/engine/steps/download.js.map +1 -1
- package/dist/engine/steps/index.d.ts +2 -0
- package/dist/engine/steps/index.d.ts.map +1 -1
- package/dist/engine/steps/index.js +2 -0
- package/dist/engine/steps/index.js.map +1 -1
- package/dist/engine/steps/oauth2-token.d.ts +41 -0
- package/dist/engine/steps/oauth2-token.d.ts.map +1 -0
- package/dist/engine/steps/oauth2-token.js +115 -0
- package/dist/engine/steps/oauth2-token.js.map +1 -0
- package/dist/engine/steps/select-xml.d.ts +34 -0
- package/dist/engine/steps/select-xml.d.ts.map +1 -0
- package/dist/engine/steps/select-xml.js +222 -0
- package/dist/engine/steps/select-xml.js.map +1 -0
- package/dist/engine/template.d.ts.map +1 -1
- package/dist/engine/template.js +7 -0
- package/dist/engine/template.js.map +1 -1
- package/dist/engine/transport/mcp-browser.d.ts +128 -0
- package/dist/engine/transport/mcp-browser.d.ts.map +1 -0
- package/dist/engine/transport/mcp-browser.js +120 -0
- package/dist/engine/transport/mcp-browser.js.map +1 -0
- package/dist/fast-path/handlers/approvals.d.ts +11 -0
- package/dist/fast-path/handlers/approvals.d.ts.map +1 -0
- package/dist/fast-path/handlers/approvals.js +136 -0
- package/dist/fast-path/handlers/approvals.js.map +1 -0
- package/dist/fast-path/manifest.d.ts +1 -0
- package/dist/fast-path/manifest.d.ts.map +1 -1
- package/dist/fast-path/manifest.js.map +1 -1
- package/dist/fast-path.d.ts.map +1 -1
- package/dist/fast-path.js +3 -0
- package/dist/fast-path.js.map +1 -1
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest-compact.txt +3 -3
- package/dist/manifest-search.json +1 -1
- package/dist/manifest.json +2239 -176
- package/dist/output/auth-guidance.d.ts +14 -0
- package/dist/output/auth-guidance.d.ts.map +1 -0
- package/dist/output/auth-guidance.js +50 -0
- package/dist/output/auth-guidance.js.map +1 -0
- package/dist/output/error-map.d.ts +1 -1
- package/dist/output/error-map.d.ts.map +1 -1
- package/dist/output/error-map.js +28 -4
- package/dist/output/error-map.js.map +1 -1
- package/dist/output/next-actions.d.ts.map +1 -1
- package/dist/output/next-actions.js +19 -3
- package/dist/output/next-actions.js.map +1 -1
- package/dist/registry.d.ts +18 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +5 -0
- package/dist/registry.js.map +1 -1
- package/dist/social/browser-errors.d.ts +13 -0
- package/dist/social/browser-errors.d.ts.map +1 -0
- package/dist/social/browser-errors.js +36 -0
- package/dist/social/browser-errors.js.map +1 -0
- package/dist/social/capabilities.d.ts +29 -0
- package/dist/social/capabilities.d.ts.map +1 -0
- package/dist/social/capabilities.js +448 -0
- package/dist/social/capabilities.js.map +1 -0
- package/dist/social/comments.d.ts +26 -0
- package/dist/social/comments.d.ts.map +1 -0
- package/dist/social/comments.js +97 -0
- package/dist/social/comments.js.map +1 -0
- package/dist/social/video-text.d.ts +27 -0
- package/dist/social/video-text.d.ts.map +1 -0
- package/dist/social/video-text.js +140 -0
- package/dist/social/video-text.js.map +1 -0
- package/dist/types/patent.d.ts +160 -0
- package/dist/types/patent.d.ts.map +1 -0
- package/dist/types/patent.js +16 -0
- package/dist/types/patent.js.map +1 -0
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +9 -4
- package/server.json +3 -3
- package/skills/unicli/SKILL.md +1 -1
- package/skills/unicli-claude-code/SKILL.md +1 -1
- package/skills/unicli-hermes/SKILL.md +1 -1
- package/src/adapters/bilibili/comments-tree.test.ts +41 -0
- package/src/adapters/bilibili/comments.ts +78 -4
- package/src/adapters/bilibili/compat.ts +5 -2
- package/src/adapters/bilibili/download.ts +7 -4
- package/src/adapters/bilibili/wbi.ts +6 -3
- package/src/adapters/brave/search.yaml +53 -0
- package/src/adapters/cipo/_shared.ts +98 -0
- package/src/adapters/cipo/get.ts +188 -0
- package/src/adapters/cipo/legal-status.ts +148 -0
- package/src/adapters/cipo/search.ts +195 -0
- package/src/adapters/cnipa/_shared.ts +138 -0
- package/src/adapters/cnipa/get.ts +199 -0
- package/src/adapters/cnipa/legal-status.ts +162 -0
- package/src/adapters/cnipa/search.ts +229 -0
- package/src/adapters/dpma/get.yaml +67 -0
- package/src/adapters/dpma/search.yaml +77 -0
- package/src/adapters/duckduckgo/search.yaml +54 -0
- package/src/adapters/duckduckgo/suggest.yaml +52 -0
- package/src/adapters/epo/family.yaml +69 -0
- package/src/adapters/epo/get.yaml +74 -0
- package/src/adapters/epo/legal-status.yaml +63 -0
- package/src/adapters/epo/search.yaml +84 -0
- package/src/adapters/espacenet/_shared.ts +98 -0
- package/src/adapters/espacenet/family.ts +161 -0
- package/src/adapters/espacenet/get.ts +185 -0
- package/src/adapters/espacenet/legal-status.ts +151 -0
- package/src/adapters/espacenet/search.ts +229 -0
- package/src/adapters/facebook/subtitles.ts +44 -0
- package/src/adapters/fips/_shared.ts +109 -0
- package/src/adapters/fips/get.ts +186 -0
- package/src/adapters/fips/search.ts +195 -0
- package/src/adapters/freepatentsonline-web/_shared.ts +273 -0
- package/src/adapters/freepatentsonline-web/get.ts +144 -0
- package/src/adapters/freepatentsonline-web/search.ts +170 -0
- package/src/adapters/google-patents-bq/prior-art.yaml +80 -0
- package/src/adapters/google-patents-bq/search.yaml +97 -0
- package/src/adapters/google-patents-web/_shared.ts +242 -0
- package/src/adapters/google-patents-web/get.ts +224 -0
- package/src/adapters/google-patents-web/search.ts +196 -0
- package/src/adapters/inpi-br/_shared.ts +98 -0
- package/src/adapters/inpi-br/get.ts +193 -0
- package/src/adapters/inpi-br/search.ts +206 -0
- package/src/adapters/inpi-fr/get.yaml +62 -0
- package/src/adapters/inpi-fr/search.yaml +74 -0
- package/src/adapters/instagram/subtitles.ts +44 -0
- package/src/adapters/ipaustralia/get.yaml +67 -0
- package/src/adapters/ipaustralia/search.yaml +74 -0
- package/src/adapters/jpo/get.yaml +63 -0
- package/src/adapters/jpo/search.yaml +76 -0
- package/src/adapters/kipris/get.yaml +69 -0
- package/src/adapters/kipris/legal-status.yaml +58 -0
- package/src/adapters/kipris/search.yaml +79 -0
- package/src/adapters/lens/get.yaml +64 -0
- package/src/adapters/lens/search.yaml +82 -0
- package/src/adapters/mastodon/statuses.test.ts +82 -0
- package/src/adapters/mastodon/statuses.ts +208 -0
- package/src/adapters/patsnap/get.yaml +65 -0
- package/src/adapters/patsnap/search.yaml +77 -0
- package/src/adapters/pqai/prior-art.yaml +59 -0
- package/src/adapters/pqai/search.yaml +60 -0
- package/src/adapters/reddit/comments-tree.test.ts +79 -0
- package/src/adapters/reddit/comments.ts +159 -0
- package/src/adapters/threads/post.test.ts +64 -0
- package/src/adapters/threads/post.ts +366 -0
- package/src/adapters/threads/user.yaml +73 -0
- package/src/adapters/tiktok/subtitles.ts +44 -0
- package/src/adapters/twitter/accept.ts +5 -2
- package/src/adapters/twitter/browser-fallback.ts +138 -0
- package/src/adapters/twitter/browser-state.ts +74 -0
- package/src/adapters/twitter/client.ts +51 -21
- package/src/adapters/twitter/reply-dm.ts +5 -2
- package/src/adapters/twitter/reply.ts +1 -0
- package/src/adapters/twitter/search.ts +12 -38
- package/src/adapters/twitter/thread.test.ts +43 -0
- package/src/adapters/twitter/thread.ts +44 -2
- package/src/adapters/twitter/trending.ts +14 -95
- package/src/adapters/ukipo/info.yaml +43 -0
- package/src/adapters/uspto/get.yaml +67 -0
- package/src/adapters/uspto/legal-status.yaml +58 -0
- package/src/adapters/uspto/search.yaml +88 -0
- package/src/adapters/wipo-patentscope/info.yaml +43 -0
- package/src/adapters/xiaohongshu/browser-state.ts +95 -0
- package/src/adapters/xiaohongshu/comments.ts +29 -6
- package/src/adapters/xiaohongshu/download.ts +60 -11
- package/src/adapters/xiaohongshu/search.ts +18 -6
- package/src/adapters/xiaohongshu/trending.ts +112 -0
- package/src/adapters/yahoo/search.yaml +52 -0
- package/src/adapters/youtube/comments-microformat.test.ts +35 -0
- package/src/adapters/youtube/comments-tree.test.ts +74 -0
- package/src/adapters/youtube/comments.ts +166 -12
- package/src/adapters/youtube/subtitles.ts +44 -0
- package/src/adapters/yt-dlp/subtitles.ts +43 -0
- package/src/adapters/zhihu/answer-detail.test.ts +83 -0
- package/src/adapters/zhihu/answer-detail.ts +275 -0
- package/src/adapters/zhihu/comment-tree.test.ts +57 -0
- package/src/adapters/zhihu/comment.ts +186 -0
- package/src/adapters/zhihu/recommend.test.ts +65 -0
- 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 {
|
|
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 =
|
|
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
|
-
|
|
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 {
|
|
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 =
|
|
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 {
|
|
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 =
|
|
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 {
|
|
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 =
|
|
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 =
|
|
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
|
+
});
|