@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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# @owner src::adapters::epo::legal-status
|
|
2
|
+
# @does Fetch INPADOC legal-status events for a publication via EPO Open Patent Services v3.2.
|
|
3
|
+
# @needs src/engine/steps/oauth2-token.ts, src/engine/steps/fetch.ts, src/engine/steps/select-xml.ts, src/engine/steps/map.ts
|
|
4
|
+
# @feeds src/commands/patent.ts
|
|
5
|
+
# @breaks throws PipelineError on token failure, 404, 401/403, 5xx
|
|
6
|
+
# @invariants output rows are legal-status events in PatentRecord shape; legal_status holds the latest event code/description
|
|
7
|
+
# @side-effects reads EPO OAuth2 credentials; HTTPS to ops.epo.org
|
|
8
|
+
# @perf two HTTPS requests
|
|
9
|
+
# @concurrency safe
|
|
10
|
+
# @test none yet
|
|
11
|
+
# @stability stable
|
|
12
|
+
# @since 2026-05-18
|
|
13
|
+
# @verification blocked-by-key
|
|
14
|
+
site: epo
|
|
15
|
+
name: legal-status
|
|
16
|
+
description: INPADOC legal-status events for an EPO publication
|
|
17
|
+
domain: ops.epo.org
|
|
18
|
+
type: web-api
|
|
19
|
+
strategy: public
|
|
20
|
+
lint_listing_detail: skip
|
|
21
|
+
|
|
22
|
+
args:
|
|
23
|
+
publication_number:
|
|
24
|
+
type: str
|
|
25
|
+
required: true
|
|
26
|
+
positional: true
|
|
27
|
+
description: Publication number in epodoc format
|
|
28
|
+
|
|
29
|
+
pipeline:
|
|
30
|
+
- oauth2-token:
|
|
31
|
+
site: epo
|
|
32
|
+
token_url: https://ops.epo.org/3.2/auth/accesstoken
|
|
33
|
+
client_id_env: EPO_OPS_CLIENT_ID
|
|
34
|
+
client_secret_env: EPO_OPS_CLIENT_SECRET
|
|
35
|
+
|
|
36
|
+
- fetch:
|
|
37
|
+
url: "https://ops.epo.org/3.2/rest-services/legal/publication/epodoc/${{ args.publication_number | urlencode }}"
|
|
38
|
+
method: GET
|
|
39
|
+
headers:
|
|
40
|
+
Authorization: "Bearer ${{ auth.bearer || '' }}"
|
|
41
|
+
Accept: application/xml
|
|
42
|
+
|
|
43
|
+
- select-xml:
|
|
44
|
+
xpath: "//ops:legal"
|
|
45
|
+
namespaces:
|
|
46
|
+
ops: "http://ops.epo.org"
|
|
47
|
+
|
|
48
|
+
- map:
|
|
49
|
+
publication_number: "${{ args.publication_number || '' }}"
|
|
50
|
+
legal_status: "${{ (item['legal-event-code'] || '') + ' ' + (item['L007EP'] || item['L008EP'] || '') }}"
|
|
51
|
+
source_adapter: epo
|
|
52
|
+
source_url: "${{ 'https://worldwide.espacenet.com/patent/search/publication/' + (args.publication_number || '') }}"
|
|
53
|
+
retrieved_at: ""
|
|
54
|
+
|
|
55
|
+
columns: [publication_number, legal_status]
|
|
56
|
+
|
|
57
|
+
# schema-v2 metadata
|
|
58
|
+
capabilities: ["http.fetch", "patent.legal-status"]
|
|
59
|
+
minimum_capability: http.fetch
|
|
60
|
+
trust: public
|
|
61
|
+
confidentiality: public
|
|
62
|
+
quarantine: false
|
|
63
|
+
schema_version: v2
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# @owner src::adapters::epo::search
|
|
2
|
+
# @does Search EPO Open Patent Services v3.2 published-data via CQL — returns DOCDB exchange-document records (St.36 XML).
|
|
3
|
+
# @needs src/engine/steps/oauth2-token.ts, src/engine/steps/fetch.ts, src/engine/steps/select-xml.ts, src/engine/steps/map.ts, src/engine/steps/limit.ts
|
|
4
|
+
# @feeds src/commands/patent.ts
|
|
5
|
+
# @breaks throws PipelineError on token-endpoint failure, 401/403 (auth) or 5xx; EPO OPS rate-limits free tier at 4 GB/week
|
|
6
|
+
# @invariants output rows conform to PatentRecord; publication_number is canonicalized to `<CC>-<doc>-<kind>`
|
|
7
|
+
# @side-effects reads env EPO_OPS_CLIENT_ID / EPO_OPS_CLIENT_SECRET (or ~/.unicli/auth/epo.json); HTTPS to ops.epo.org
|
|
8
|
+
# @perf two HTTPS requests per call (token + data); token is cached via oauth2-cc broker
|
|
9
|
+
# @concurrency safe; token cache deduplicates concurrent token fetches
|
|
10
|
+
# @test none yet
|
|
11
|
+
# @stability stable
|
|
12
|
+
# @since 2026-05-18
|
|
13
|
+
# @verification blocked-by-key — needs EPO_OPS_CLIENT_ID / EPO_OPS_CLIENT_SECRET (free tier at developers.epo.org)
|
|
14
|
+
site: epo
|
|
15
|
+
name: search
|
|
16
|
+
description: Search EPO published patents via Open Patent Services v3.2 (CQL)
|
|
17
|
+
domain: ops.epo.org
|
|
18
|
+
type: web-api
|
|
19
|
+
strategy: public
|
|
20
|
+
lint_listing_detail: skip
|
|
21
|
+
|
|
22
|
+
args:
|
|
23
|
+
query:
|
|
24
|
+
type: str
|
|
25
|
+
required: true
|
|
26
|
+
positional: true
|
|
27
|
+
description: EPO CQL query (e.g. "ti=quantum and pa=ibm")
|
|
28
|
+
limit:
|
|
29
|
+
type: int
|
|
30
|
+
default: 25
|
|
31
|
+
description: Maximum results (OPS caps at 100 per page)
|
|
32
|
+
|
|
33
|
+
pipeline:
|
|
34
|
+
- oauth2-token:
|
|
35
|
+
site: epo
|
|
36
|
+
token_url: https://ops.epo.org/3.2/auth/accesstoken
|
|
37
|
+
client_id_env: EPO_OPS_CLIENT_ID
|
|
38
|
+
client_secret_env: EPO_OPS_CLIENT_SECRET
|
|
39
|
+
|
|
40
|
+
- fetch:
|
|
41
|
+
url: "https://ops.epo.org/3.2/rest-services/published-data/search?q=${{ args.query | urlencode }}&Range=1-${{ args.limit }}"
|
|
42
|
+
method: GET
|
|
43
|
+
headers:
|
|
44
|
+
Authorization: "Bearer ${{ auth.bearer || '' }}"
|
|
45
|
+
Accept: application/xml
|
|
46
|
+
|
|
47
|
+
- select-xml:
|
|
48
|
+
xpath: "//ops:exchange-document"
|
|
49
|
+
namespaces:
|
|
50
|
+
ops: "http://ops.epo.org"
|
|
51
|
+
exchange: "http://www.epo.org/exchange"
|
|
52
|
+
|
|
53
|
+
# Field mapping references the OPS v3.2 DOCDB schema (docs.epo.org).
|
|
54
|
+
# Every path below is a documented DOCDB element; arrays are JSON-serialised
|
|
55
|
+
# so they survive the template engine's string projection.
|
|
56
|
+
- map:
|
|
57
|
+
publication_number: "${{ ((item['bibliographic-data'] && item['bibliographic-data']['publication-reference'] && item['bibliographic-data']['publication-reference']['document-id']) ? (item['bibliographic-data']['publication-reference']['document-id'].country + '-' + item['bibliographic-data']['publication-reference']['document-id']['doc-number'] + '-' + (item['bibliographic-data']['publication-reference']['document-id'].kind || '')) : '') }}"
|
|
58
|
+
application_number: "${{ ((item['bibliographic-data'] && item['bibliographic-data']['application-reference'] && item['bibliographic-data']['application-reference']['document-id']) ? (item['bibliographic-data']['application-reference']['document-id'].country + '-' + item['bibliographic-data']['application-reference']['document-id']['doc-number'] + '-' + (item['bibliographic-data']['application-reference']['document-id'].kind || '')) : '') }}"
|
|
59
|
+
# DOCDB renders invention-title as one element per language; prefer EN.
|
|
60
|
+
title: "${{ (function(t){ if(!t) return ''; if(Array.isArray(t)){ var en=t.find(x=>x['@_lang']==='en'); return en ? (en['#text']||en) : (t[0]['#text']||t[0]); } return t['#text']||t; })(item['bibliographic-data'] ? item['bibliographic-data']['invention-title'] : null) }}"
|
|
61
|
+
abstract: "${{ (function(a){ if(!a) return ''; if(Array.isArray(a)){ var en=a.find(x=>x['@_lang']==='en'); return en ? ((en.p ? (en.p['#text']||en.p) : (en['#text']||en))) : ''; } return a.p ? (a.p['#text']||a.p) : (a['#text']||a); })(item.abstract) }}"
|
|
62
|
+
kind_code: "${{ (item['bibliographic-data'] && item['bibliographic-data']['publication-reference'] && item['bibliographic-data']['publication-reference']['document-id']) ? (item['bibliographic-data']['publication-reference']['document-id'].kind || '') : '' }}"
|
|
63
|
+
publication_date: "${{ (function(d){ if(!d) return ''; var s=String(d); return s.length===8 ? (s.slice(0,4)+'-'+s.slice(4,6)+'-'+s.slice(6,8)) : s; })((item['bibliographic-data'] && item['bibliographic-data']['publication-reference'] && item['bibliographic-data']['publication-reference']['document-id']) ? item['bibliographic-data']['publication-reference']['document-id'].date : '') }}"
|
|
64
|
+
# DOCDB `parties.inventors.inventor[]` carries `inventor-name.name`.
|
|
65
|
+
inventors: "${{ JSON.stringify((function(){ var p=item['bibliographic-data'] && item['bibliographic-data'].parties; if(!p || !p.inventors || !p.inventors.inventor) return []; var arr = Array.isArray(p.inventors.inventor) ? p.inventors.inventor : [p.inventors.inventor]; return arr.map(i => ({ name: (i['inventor-name'] && (i['inventor-name'].name || i['inventor-name']['#text'])) || '' })).filter(x => x.name); })()) }}"
|
|
66
|
+
assignees: "${{ JSON.stringify((function(){ var p=item['bibliographic-data'] && item['bibliographic-data'].parties; if(!p || !p.applicants || !p.applicants.applicant) return []; var arr = Array.isArray(p.applicants.applicant) ? p.applicants.applicant : [p.applicants.applicant]; return arr.map(i => ({ name: (i['applicant-name'] && (i['applicant-name'].name || i['applicant-name']['#text'])) || '' })).filter(x => x.name); })()) }}"
|
|
67
|
+
# `classifications-ipcr.classification-ipcr[].text` is IPC; `patent-classifications.patent-classification[]` is CPC + others.
|
|
68
|
+
classifications: "${{ JSON.stringify((function(){ var bd = item['bibliographic-data']; if(!bd) return []; var out = []; var ipcr = bd['classifications-ipcr'] && bd['classifications-ipcr']['classification-ipcr']; if(ipcr){ var arr = Array.isArray(ipcr) ? ipcr : [ipcr]; for (var i=0;i<arr.length;i++) out.push({ scheme: 'ipc', code: arr[i].text || arr[i]['#text'] || '' }); } var pc = bd['patent-classifications'] && bd['patent-classifications']['patent-classification']; if(pc){ var arr2 = Array.isArray(pc) ? pc : [pc]; for (var i=0;i<arr2.length;i++){ var c=arr2[i]; var scheme=(c['classification-scheme'] && (c['classification-scheme']['@_scheme']||'')).toLowerCase()||'cpc'; var section=(c.section||'')+(c.class||'')+(c.subclass||''); var main=(c['main-group']||'')+(c['subgroup']?'/'+c.subgroup:''); out.push({ scheme: scheme, code: (section+main) }); } } return out.filter(x => x.code); })()) }}"
|
|
69
|
+
family_id: "${{ item['@_family-id'] || '' }}"
|
|
70
|
+
source_adapter: epo
|
|
71
|
+
source_url: "${{ 'https://worldwide.espacenet.com/patent/search?q=' + (args.query || '') }}"
|
|
72
|
+
retrieved_at: ""
|
|
73
|
+
|
|
74
|
+
- limit: "${{ args.limit }}"
|
|
75
|
+
|
|
76
|
+
columns: [publication_number, title]
|
|
77
|
+
|
|
78
|
+
# schema-v2 metadata
|
|
79
|
+
capabilities: ["http.fetch", "patent.search"]
|
|
80
|
+
minimum_capability: http.fetch
|
|
81
|
+
trust: public
|
|
82
|
+
confidentiality: public
|
|
83
|
+
quarantine: false
|
|
84
|
+
schema_version: v2
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @owner src::adapters::espacenet::_shared
|
|
3
|
+
* @does Shared helpers for the Espacenet browser-driven adapter — distinct from the EPO OPS HTTP adapter (which lives at src/adapters/epo/*). Espacenet is the no-key public front end; EPO OPS is the keyed REST API.
|
|
4
|
+
* @needs src/engine/transport/mcp-browser.ts, src/engine/normalizer/patent-envelope.ts, src/types/patent.ts
|
|
5
|
+
* @feeds src/adapters/espacenet/*.ts
|
|
6
|
+
* @breaks none — pure helpers
|
|
7
|
+
* @invariants every transport gap surfaces as a PatentEnvelope row with adapter_path stamped
|
|
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 espacenetEnvelope(
|
|
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 transportErrorToEspacenetEnvelope(
|
|
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 espacenet browser adapter, or use EPO OPS (src/adapters/epo/*) which exposes a keyed API",
|
|
56
|
+
alternatives: ["epo", "uspto", "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: ["epo"],
|
|
66
|
+
retryable: false,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function espacenetNavigateAndExtract<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,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @owner src::adapters::espacenet::family
|
|
3
|
+
* @does Browser-driven Espacenet family lookup — DOCDB simple-family rows visible on the family tab of the detail page; alternative to EPO OPS keyed family broker.
|
|
4
|
+
* @needs src/engine/transport/mcp-browser.ts, src/adapters/espacenet/_shared.ts, src/registry.ts
|
|
5
|
+
* @feeds src/commands/patent.ts (capability tag patent.family)
|
|
6
|
+
* @breaks PATENT_INVALID_NUMBER, PATENT_NOT_FOUND, PATENT_API_DEPRECATED (MCP_BUS_MISSING)
|
|
7
|
+
* @invariants output rows carry publication_number + jurisdiction + relationship per PatentFamilyMember shape
|
|
8
|
+
* @side-effects controls Chrome via MCP
|
|
9
|
+
* @perf single navigate + evaluate
|
|
10
|
+
* @concurrency safe
|
|
11
|
+
* @test tests/unit/adapters/espacenet/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 {
|
|
20
|
+
espacenetEnvelope,
|
|
21
|
+
espacenetNavigateAndExtract,
|
|
22
|
+
transportErrorToEspacenetEnvelope,
|
|
23
|
+
} from "./_shared.js";
|
|
24
|
+
|
|
25
|
+
const ADAPTER_PATH = "src/adapters/espacenet/family.ts";
|
|
26
|
+
|
|
27
|
+
interface EspacenetFamilyExtract {
|
|
28
|
+
rows: Array<{
|
|
29
|
+
publication_number: string;
|
|
30
|
+
jurisdiction?: string;
|
|
31
|
+
publication_date?: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const FAMILY_EXTRACTOR = `(() => {
|
|
36
|
+
const rows = Array.from(
|
|
37
|
+
document.querySelectorAll('[data-test="family-row"], .familyRow, tr.family-member')
|
|
38
|
+
).map((el) => {
|
|
39
|
+
const text = (sel) => {
|
|
40
|
+
const node = el.querySelector(sel);
|
|
41
|
+
return node ? (node.textContent || '').trim() : '';
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
publication_number: text('[data-test="publication-number"], .publicationNumber'),
|
|
45
|
+
jurisdiction: text('[data-test="country"], .country'),
|
|
46
|
+
publication_date: text('[data-test="publication-date"], .publicationDate'),
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
return { rows };
|
|
50
|
+
})()`;
|
|
51
|
+
|
|
52
|
+
function familyUrlFor(pubNo: string): string {
|
|
53
|
+
return `https://worldwide.espacenet.com/patent/search/family/${encodeURIComponent(pubNo)}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function runEspacenetFamily(kwargs: {
|
|
57
|
+
publication_number: string;
|
|
58
|
+
}): Promise<unknown[]> {
|
|
59
|
+
const pubNo = String(kwargs.publication_number ?? "").trim();
|
|
60
|
+
if (pubNo.length === 0) {
|
|
61
|
+
return [
|
|
62
|
+
{
|
|
63
|
+
envelope: espacenetEnvelope(
|
|
64
|
+
"PATENT_INVALID_NUMBER",
|
|
65
|
+
ADAPTER_PATH,
|
|
66
|
+
"validate",
|
|
67
|
+
"espacenet family requires a non-empty publication_number",
|
|
68
|
+
),
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
const url = familyUrlFor(pubNo);
|
|
73
|
+
let extract: EspacenetFamilyExtract;
|
|
74
|
+
try {
|
|
75
|
+
const result = await espacenetNavigateAndExtract<EspacenetFamilyExtract>(
|
|
76
|
+
url,
|
|
77
|
+
FAMILY_EXTRACTOR,
|
|
78
|
+
);
|
|
79
|
+
if (!result.data) {
|
|
80
|
+
return [
|
|
81
|
+
{
|
|
82
|
+
envelope: espacenetEnvelope(
|
|
83
|
+
"PATENT_SCHEMA_DRIFT",
|
|
84
|
+
ADAPTER_PATH,
|
|
85
|
+
"evaluate",
|
|
86
|
+
"espacenet family evaluate returned no data",
|
|
87
|
+
),
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
extract = result.data;
|
|
92
|
+
} catch (err) {
|
|
93
|
+
if (err instanceof TransportError) {
|
|
94
|
+
return [
|
|
95
|
+
{
|
|
96
|
+
envelope: transportErrorToEspacenetEnvelope(
|
|
97
|
+
err,
|
|
98
|
+
ADAPTER_PATH,
|
|
99
|
+
"navigate",
|
|
100
|
+
),
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
throw err;
|
|
105
|
+
}
|
|
106
|
+
if (extract.rows.length === 0) {
|
|
107
|
+
return [
|
|
108
|
+
{
|
|
109
|
+
envelope: espacenetEnvelope(
|
|
110
|
+
"PATENT_NOT_FOUND",
|
|
111
|
+
ADAPTER_PATH,
|
|
112
|
+
"evaluate",
|
|
113
|
+
`espacenet found no family members for "${pubNo}"`,
|
|
114
|
+
["epo"],
|
|
115
|
+
),
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
return extract.rows
|
|
120
|
+
.filter((row) => row.publication_number)
|
|
121
|
+
.map((row) => ({
|
|
122
|
+
publication_number: row.publication_number,
|
|
123
|
+
jurisdiction:
|
|
124
|
+
row.jurisdiction || row.publication_number.slice(0, 2).toUpperCase(),
|
|
125
|
+
relationship: "simple_family",
|
|
126
|
+
publication_date: row.publication_date || undefined,
|
|
127
|
+
source_adapter: "espacenet",
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
cli({
|
|
132
|
+
site: "espacenet",
|
|
133
|
+
name: "family",
|
|
134
|
+
description: "Espacenet DOCDB simple-family lookup (browser)",
|
|
135
|
+
domain: "worldwide.espacenet.com",
|
|
136
|
+
strategy: Strategy.PUBLIC,
|
|
137
|
+
adapter_path: ADAPTER_PATH,
|
|
138
|
+
args: [
|
|
139
|
+
{
|
|
140
|
+
name: "publication_number",
|
|
141
|
+
type: "str",
|
|
142
|
+
required: true,
|
|
143
|
+
positional: true,
|
|
144
|
+
description: "ST.16 publication number",
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
columns: [
|
|
148
|
+
"publication_number",
|
|
149
|
+
"jurisdiction",
|
|
150
|
+
"relationship",
|
|
151
|
+
"publication_date",
|
|
152
|
+
],
|
|
153
|
+
capabilities: [
|
|
154
|
+
"mcp-browser.navigate",
|
|
155
|
+
"mcp-browser.evaluate",
|
|
156
|
+
"patent.family",
|
|
157
|
+
],
|
|
158
|
+
minimum_capability: "mcp-browser.evaluate",
|
|
159
|
+
func: async (_page, kwargs) =>
|
|
160
|
+
runEspacenetFamily(kwargs as { publication_number: string }),
|
|
161
|
+
});
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @owner src::adapters::espacenet::get
|
|
3
|
+
* @does Browser-driven retrieval of a single Espacenet publication detail page; extracts bibliographic fields and emits a PatentRecord.
|
|
4
|
+
* @needs src/engine/transport/mcp-browser.ts, src/engine/normalizer/patent-envelope.ts, src/adapters/espacenet/_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 with MCP_BUS_MISSING
|
|
7
|
+
* @invariants output is a single PatentRecord row when upstream answers; never returns a stub
|
|
8
|
+
* @side-effects controls Chrome via MCP
|
|
9
|
+
* @perf single navigate + evaluate
|
|
10
|
+
* @concurrency safe
|
|
11
|
+
* @test tests/unit/adapters/espacenet/search.test.ts (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 { assemblePatentRecord } from "../../engine/normalizer/patent-envelope.js";
|
|
20
|
+
import {
|
|
21
|
+
espacenetEnvelope,
|
|
22
|
+
espacenetNavigateAndExtract,
|
|
23
|
+
transportErrorToEspacenetEnvelope,
|
|
24
|
+
} from "./_shared.js";
|
|
25
|
+
|
|
26
|
+
const ADAPTER_PATH = "src/adapters/espacenet/get.ts";
|
|
27
|
+
|
|
28
|
+
interface EspacenetDetail {
|
|
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
|
+
source_url?: string;
|
|
38
|
+
html_marker?: 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('[data-test="publication-number"], .publicationNumber'),
|
|
48
|
+
application_number: text('[data-test="application-number"], .applicationNumber'),
|
|
49
|
+
title: text('[data-test="title"], h1.title, .invention-title'),
|
|
50
|
+
abstract: text('[data-test="abstract"], .abstract'),
|
|
51
|
+
applicant: text('[data-test="applicant"], .applicantName'),
|
|
52
|
+
inventor: text('[data-test="inventor"], .inventorName'),
|
|
53
|
+
publication_date: text('[data-test="publication-date"], .publicationDate'),
|
|
54
|
+
filing_date: text('[data-test="filing-date"], .filingDate'),
|
|
55
|
+
source_url: location.href,
|
|
56
|
+
html_marker: document.body && document.body.innerText
|
|
57
|
+
? document.body.innerText.slice(0, 200)
|
|
58
|
+
: '',
|
|
59
|
+
};
|
|
60
|
+
})()`;
|
|
61
|
+
|
|
62
|
+
function detailUrlFor(pubNo: string): string {
|
|
63
|
+
return `https://worldwide.espacenet.com/patent/search/publication/${encodeURIComponent(pubNo)}`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function runEspacenetGet(kwargs: {
|
|
67
|
+
publication_number: string;
|
|
68
|
+
}): Promise<unknown[]> {
|
|
69
|
+
const pubNo = String(kwargs.publication_number ?? "").trim();
|
|
70
|
+
if (pubNo.length === 0) {
|
|
71
|
+
return [
|
|
72
|
+
{
|
|
73
|
+
envelope: espacenetEnvelope(
|
|
74
|
+
"PATENT_INVALID_NUMBER",
|
|
75
|
+
ADAPTER_PATH,
|
|
76
|
+
"validate",
|
|
77
|
+
"espacenet get requires a non-empty publication_number",
|
|
78
|
+
),
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
const url = detailUrlFor(pubNo);
|
|
83
|
+
let detail: EspacenetDetail;
|
|
84
|
+
try {
|
|
85
|
+
const result = await espacenetNavigateAndExtract<EspacenetDetail>(
|
|
86
|
+
url,
|
|
87
|
+
DETAIL_EXTRACTOR,
|
|
88
|
+
);
|
|
89
|
+
if (!result.data) {
|
|
90
|
+
return [
|
|
91
|
+
{
|
|
92
|
+
envelope: espacenetEnvelope(
|
|
93
|
+
"PATENT_SCHEMA_DRIFT",
|
|
94
|
+
ADAPTER_PATH,
|
|
95
|
+
"evaluate",
|
|
96
|
+
"espacenet detail evaluate returned no data",
|
|
97
|
+
),
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
detail = result.data;
|
|
102
|
+
} catch (err) {
|
|
103
|
+
if (err instanceof TransportError) {
|
|
104
|
+
return [
|
|
105
|
+
{
|
|
106
|
+
envelope: transportErrorToEspacenetEnvelope(
|
|
107
|
+
err,
|
|
108
|
+
ADAPTER_PATH,
|
|
109
|
+
"navigate",
|
|
110
|
+
),
|
|
111
|
+
},
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
const fieldCount = [detail.publication_number, detail.title].filter(
|
|
117
|
+
Boolean,
|
|
118
|
+
).length;
|
|
119
|
+
if (fieldCount === 0) {
|
|
120
|
+
return [
|
|
121
|
+
{
|
|
122
|
+
envelope: espacenetEnvelope(
|
|
123
|
+
"PATENT_NOT_FOUND",
|
|
124
|
+
ADAPTER_PATH,
|
|
125
|
+
"evaluate",
|
|
126
|
+
`espacenet detail page for "${pubNo}" yielded no bibliographic fields`,
|
|
127
|
+
["epo", "uspto"],
|
|
128
|
+
),
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
}
|
|
132
|
+
const canonicalPubNo = detail.publication_number || pubNo;
|
|
133
|
+
try {
|
|
134
|
+
return [
|
|
135
|
+
assemblePatentRecord({
|
|
136
|
+
publication_number: canonicalPubNo,
|
|
137
|
+
application_number: detail.application_number || undefined,
|
|
138
|
+
title: detail.title || undefined,
|
|
139
|
+
abstract: detail.abstract || undefined,
|
|
140
|
+
assignees: detail.applicant ? [{ name: detail.applicant }] : undefined,
|
|
141
|
+
inventors: detail.inventor ? [{ name: detail.inventor }] : undefined,
|
|
142
|
+
publication_date: detail.publication_date || undefined,
|
|
143
|
+
filing_date: detail.filing_date || undefined,
|
|
144
|
+
source_adapter: "espacenet",
|
|
145
|
+
source_url: detail.source_url || url,
|
|
146
|
+
} as Parameters<typeof assemblePatentRecord>[0]),
|
|
147
|
+
];
|
|
148
|
+
} catch {
|
|
149
|
+
return [
|
|
150
|
+
{
|
|
151
|
+
envelope: espacenetEnvelope(
|
|
152
|
+
"PATENT_NOT_FOUND",
|
|
153
|
+
ADAPTER_PATH,
|
|
154
|
+
"normalize",
|
|
155
|
+
`espacenet detail page for "${pubNo}" did not yield a valid publication_number`,
|
|
156
|
+
["epo"],
|
|
157
|
+
),
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
cli({
|
|
164
|
+
site: "espacenet",
|
|
165
|
+
name: "get",
|
|
166
|
+
description:
|
|
167
|
+
"Retrieve a single Espacenet publication detail (browser, no key)",
|
|
168
|
+
domain: "worldwide.espacenet.com",
|
|
169
|
+
strategy: Strategy.PUBLIC,
|
|
170
|
+
adapter_path: ADAPTER_PATH,
|
|
171
|
+
args: [
|
|
172
|
+
{
|
|
173
|
+
name: "publication_number",
|
|
174
|
+
type: "str",
|
|
175
|
+
required: true,
|
|
176
|
+
positional: true,
|
|
177
|
+
description: "ST.16 publication number (e.g. EP4123456A1)",
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
columns: ["publication_number", "title", "publication_date", "source_url"],
|
|
181
|
+
capabilities: ["mcp-browser.navigate", "mcp-browser.evaluate", "patent.get"],
|
|
182
|
+
minimum_capability: "mcp-browser.evaluate",
|
|
183
|
+
func: async (_page, kwargs) =>
|
|
184
|
+
runEspacenetGet(kwargs as { publication_number: string }),
|
|
185
|
+
});
|