papersearch 0.0.0-stage → 0.4.2
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/.env.example +208 -0
- package/LICENSE +21 -0
- package/README.md +213 -2
- package/README.zh.md +214 -0
- package/carsi/LICENSE +21 -0
- package/carsi/NOTICE +5 -0
- package/carsi/README.md +75 -0
- package/carsi/paper_search_carsi/__init__.py +6 -0
- package/carsi/paper_search_carsi/_core/__init__.py +26 -0
- package/carsi/paper_search_carsi/_core/racing.pyx +280 -0
- package/carsi/paper_search_carsi/adapters/__init__.py +26 -0
- package/carsi/paper_search_carsi/adapters/acm/__init__.py +13 -0
- package/carsi/paper_search_carsi/adapters/acs/__init__.py +47 -0
- package/carsi/paper_search_carsi/adapters/aha_journals/__init__.py +13 -0
- package/carsi/paper_search_carsi/adapters/ams/__init__.py +19 -0
- package/carsi/paper_search_carsi/adapters/annual_reviews/__init__.py +154 -0
- package/carsi/paper_search_carsi/adapters/aps/__init__.py +127 -0
- package/carsi/paper_search_carsi/adapters/asce/__init__.py +13 -0
- package/carsi/paper_search_carsi/adapters/base.py +320 -0
- package/carsi/paper_search_carsi/adapters/bmj/__init__.py +32 -0
- package/carsi/paper_search_carsi/adapters/copernicus/__init__.py +20 -0
- package/carsi/paper_search_carsi/adapters/dovepress/__init__.py +43 -0
- package/carsi/paper_search_carsi/adapters/elsevier/__init__.py +302 -0
- package/carsi/paper_search_carsi/adapters/elsevier/journal_site.py +237 -0
- package/carsi/paper_search_carsi/adapters/elsevier/sciencedirect.py +138 -0
- package/carsi/paper_search_carsi/adapters/ieee/__init__.py +184 -0
- package/carsi/paper_search_carsi/adapters/iop/__init__.py +41 -0
- package/carsi/paper_search_carsi/adapters/jama/__init__.py +54 -0
- package/carsi/paper_search_carsi/adapters/karger/__init__.py +75 -0
- package/carsi/paper_search_carsi/adapters/lww/__init__.py +103 -0
- package/carsi/paper_search_carsi/adapters/lww/journals_lww.py +36 -0
- package/carsi/paper_search_carsi/adapters/lww/ovid.py +72 -0
- package/carsi/paper_search_carsi/adapters/mdpi/__init__.py +20 -0
- package/carsi/paper_search_carsi/adapters/nejm/__init__.py +18 -0
- package/carsi/paper_search_carsi/adapters/neurology/__init__.py +13 -0
- package/carsi/paper_search_carsi/adapters/optica/__init__.py +33 -0
- package/carsi/paper_search_carsi/adapters/oup/__init__.py +366 -0
- package/carsi/paper_search_carsi/adapters/platforms/__init__.py +5 -0
- package/carsi/paper_search_carsi/adapters/platforms/atypon/__init__.py +149 -0
- package/carsi/paper_search_carsi/adapters/platforms/silverchair/__init__.py +83 -0
- package/carsi/paper_search_carsi/adapters/plos/__init__.py +20 -0
- package/carsi/paper_search_carsi/adapters/pnas/__init__.py +13 -0
- package/carsi/paper_search_carsi/adapters/rsc/__init__.py +74 -0
- package/carsi/paper_search_carsi/adapters/sage/__init__.py +154 -0
- package/carsi/paper_search_carsi/adapters/science/__init__.py +13 -0
- package/carsi/paper_search_carsi/adapters/springer/__init__.py +62 -0
- package/carsi/paper_search_carsi/adapters/taylor_francis/__init__.py +46 -0
- package/carsi/paper_search_carsi/adapters/thieme/__init__.py +164 -0
- package/carsi/paper_search_carsi/adapters/wiley/__init__.py +145 -0
- package/carsi/paper_search_carsi/adapters/world_scientific/__init__.py +27 -0
- package/carsi/paper_search_carsi/assets/icon-32.png +0 -0
- package/carsi/paper_search_carsi/assets/icon-512.png +0 -0
- package/carsi/paper_search_carsi/assets/icon-64.png +0 -0
- package/carsi/paper_search_carsi/assets/icon.svg +43 -0
- package/carsi/paper_search_carsi/blocked_journals.py +63 -0
- package/carsi/paper_search_carsi/browser/__init__.py +1 -0
- package/carsi/paper_search_carsi/browser/backend.py +823 -0
- package/carsi/paper_search_carsi/browser/cookies.py +386 -0
- package/carsi/paper_search_carsi/browser/ego_relay.py +152 -0
- package/carsi/paper_search_carsi/browser/engine.py +927 -0
- package/carsi/paper_search_carsi/browser/login.py +336 -0
- package/carsi/paper_search_carsi/browser/preview.py +379 -0
- package/carsi/paper_search_carsi/browser/watchdog.py +193 -0
- package/carsi/paper_search_carsi/cache.py +62 -0
- package/carsi/paper_search_carsi/carsi_schools.py +109 -0
- package/carsi/paper_search_carsi/cli.py +479 -0
- package/carsi/paper_search_carsi/cold_start.py +251 -0
- package/carsi/paper_search_carsi/config.py +301 -0
- package/carsi/paper_search_carsi/data/institutional_identity_policy.json +165 -0
- package/carsi/paper_search_carsi/data/publisher_access_catalog.json +969 -0
- package/carsi/paper_search_carsi/data/publisher_browser_verification_matrix.json +625 -0
- package/carsi/paper_search_carsi/download_diagnostics.py +228 -0
- package/carsi/paper_search_carsi/engine/__init__.py +1 -0
- package/carsi/paper_search_carsi/engine/access_rules.py +345 -0
- package/carsi/paper_search_carsi/engine/batch.py +702 -0
- package/carsi/paper_search_carsi/engine/batch_access.py +483 -0
- package/carsi/paper_search_carsi/engine/batch_capture.py +1531 -0
- package/carsi/paper_search_carsi/engine/batch_common.py +427 -0
- package/carsi/paper_search_carsi/engine/batch_diagnostics.py +307 -0
- package/carsi/paper_search_carsi/engine/batch_institution.py +981 -0
- package/carsi/paper_search_carsi/engine/batch_login.py +1605 -0
- package/carsi/paper_search_carsi/engine/batch_pdf_urls.py +274 -0
- package/carsi/paper_search_carsi/engine/batch_runs.py +711 -0
- package/carsi/paper_search_carsi/engine/batch_user.py +173 -0
- package/carsi/paper_search_carsi/engine/batch_waits.py +441 -0
- package/carsi/paper_search_carsi/engine/bridge.py +666 -0
- package/carsi/paper_search_carsi/engine/pdf_guard.py +310 -0
- package/carsi/paper_search_carsi/engine/router.py +514 -0
- package/carsi/paper_search_carsi/engine/supplements.py +148 -0
- package/carsi/paper_search_carsi/entitlements.py +233 -0
- package/carsi/paper_search_carsi/extractors/__init__.py +0 -0
- package/carsi/paper_search_carsi/extractors/pdf_extractor.py +149 -0
- package/carsi/paper_search_carsi/identifiers.py +121 -0
- package/carsi/paper_search_carsi/issues.py +227 -0
- package/carsi/paper_search_carsi/log.py +84 -0
- package/carsi/paper_search_carsi/mcp_progress.py +82 -0
- package/carsi/paper_search_carsi/network.py +359 -0
- package/carsi/paper_search_carsi/orchestrator.py +130 -0
- package/carsi/paper_search_carsi/pdf_utils.py +279 -0
- package/carsi/paper_search_carsi/progress_bar.py +778 -0
- package/carsi/paper_search_carsi/progress_reporter.py +530 -0
- package/carsi/paper_search_carsi/progress_status.py +212 -0
- package/carsi/paper_search_carsi/publishers/__init__.py +10 -0
- package/carsi/paper_search_carsi/publishers/builtin/acm.json +65 -0
- package/carsi/paper_search_carsi/publishers/builtin/acs.json +73 -0
- package/carsi/paper_search_carsi/publishers/builtin/aha-journals.json +47 -0
- package/carsi/paper_search_carsi/publishers/builtin/aip.json +66 -0
- package/carsi/paper_search_carsi/publishers/builtin/ams.json +66 -0
- package/carsi/paper_search_carsi/publishers/builtin/annual-reviews.json +64 -0
- package/carsi/paper_search_carsi/publishers/builtin/aps.json +70 -0
- package/carsi/paper_search_carsi/publishers/builtin/asce.json +46 -0
- package/carsi/paper_search_carsi/publishers/builtin/bmj.json +46 -0
- package/carsi/paper_search_carsi/publishers/builtin/copernicus.json +45 -0
- package/carsi/paper_search_carsi/publishers/builtin/dovepress.json +35 -0
- package/carsi/paper_search_carsi/publishers/builtin/elsevier.json +77 -0
- package/carsi/paper_search_carsi/publishers/builtin/frontiers.json +62 -0
- package/carsi/paper_search_carsi/publishers/builtin/ieee.json +68 -0
- package/carsi/paper_search_carsi/publishers/builtin/iop.json +69 -0
- package/carsi/paper_search_carsi/publishers/builtin/jama.json +48 -0
- package/carsi/paper_search_carsi/publishers/builtin/karger.json +48 -0
- package/carsi/paper_search_carsi/publishers/builtin/lww.json +57 -0
- package/carsi/paper_search_carsi/publishers/builtin/mdpi.json +46 -0
- package/carsi/paper_search_carsi/publishers/builtin/nejm.json +46 -0
- package/carsi/paper_search_carsi/publishers/builtin/neurology.json +45 -0
- package/carsi/paper_search_carsi/publishers/builtin/optica.json +77 -0
- package/carsi/paper_search_carsi/publishers/builtin/oxfordacademic.json +64 -0
- package/carsi/paper_search_carsi/publishers/builtin/plos.json +46 -0
- package/carsi/paper_search_carsi/publishers/builtin/pnas.json +67 -0
- package/carsi/paper_search_carsi/publishers/builtin/royalsocietypublishing.json +62 -0
- package/carsi/paper_search_carsi/publishers/builtin/rsc.json +71 -0
- package/carsi/paper_search_carsi/publishers/builtin/sage.json +48 -0
- package/carsi/paper_search_carsi/publishers/builtin/science.json +68 -0
- package/carsi/paper_search_carsi/publishers/builtin/springer.json +92 -0
- package/carsi/paper_search_carsi/publishers/builtin/taylor-francis.json +52 -0
- package/carsi/paper_search_carsi/publishers/builtin/thieme.json +50 -0
- package/carsi/paper_search_carsi/publishers/builtin/wiley.json +77 -0
- package/carsi/paper_search_carsi/publishers/builtin/world-scientific.json +68 -0
- package/carsi/paper_search_carsi/publishers/extensions.py +241 -0
- package/carsi/paper_search_carsi/publishers/loader.py +93 -0
- package/carsi/paper_search_carsi/publishers/model.py +90 -0
- package/carsi/paper_search_carsi/publishers/profiles.py +127 -0
- package/carsi/paper_search_carsi/publishers/schema.json +129 -0
- package/carsi/paper_search_carsi/publishers/site.py +86 -0
- package/carsi/paper_search_carsi/rate_limit.py +51 -0
- package/carsi/paper_search_carsi/server.py +197 -0
- package/carsi/paper_search_carsi/session_broker.py +163 -0
- package/carsi/paper_search_carsi/tor.py +9 -0
- package/carsi/paper_search_carsi/user_settings.py +55 -0
- package/carsi/pyproject.toml +41 -0
- package/dist/capabilities/body-snippet-search/handler.d.ts +9 -0
- package/dist/capabilities/body-snippet-search/handler.d.ts.map +1 -0
- package/dist/capabilities/body-snippet-search/handler.js +17 -0
- package/dist/capabilities/body-snippet-search/handler.js.map +1 -0
- package/dist/capabilities/body-snippet-search/index.d.ts +7 -0
- package/dist/capabilities/body-snippet-search/index.d.ts.map +1 -0
- package/dist/capabilities/body-snippet-search/index.js +6 -0
- package/dist/capabilities/body-snippet-search/index.js.map +1 -0
- package/dist/capabilities/body-snippet-search/schemas.d.ts +36 -0
- package/dist/capabilities/body-snippet-search/schemas.d.ts.map +1 -0
- package/dist/capabilities/body-snippet-search/schemas.js +16 -0
- package/dist/capabilities/body-snippet-search/schemas.js.map +1 -0
- package/dist/capabilities/body-snippet-search/service.d.ts +4 -0
- package/dist/capabilities/body-snippet-search/service.d.ts.map +1 -0
- package/dist/capabilities/body-snippet-search/service.js +4 -0
- package/dist/capabilities/body-snippet-search/service.js.map +1 -0
- package/dist/capabilities/body-snippet-search/tools.d.ts +187 -0
- package/dist/capabilities/body-snippet-search/tools.d.ts.map +1 -0
- package/dist/capabilities/body-snippet-search/tools.js +49 -0
- package/dist/capabilities/body-snippet-search/tools.js.map +1 -0
- package/dist/capabilities/body-snippet-search/types.d.ts +14 -0
- package/dist/capabilities/body-snippet-search/types.d.ts.map +1 -0
- package/dist/capabilities/body-snippet-search/types.js +2 -0
- package/dist/capabilities/body-snippet-search/types.js.map +1 -0
- package/dist/capabilities/citation-expansion/CitationService.d.ts +47 -0
- package/dist/capabilities/citation-expansion/CitationService.d.ts.map +1 -0
- package/dist/capabilities/citation-expansion/CitationService.js +243 -0
- package/dist/capabilities/citation-expansion/CitationService.js.map +1 -0
- package/dist/capabilities/citation-expansion/handler.d.ts +36 -0
- package/dist/capabilities/citation-expansion/handler.d.ts.map +1 -0
- package/dist/capabilities/citation-expansion/handler.js +44 -0
- package/dist/capabilities/citation-expansion/handler.js.map +1 -0
- package/dist/capabilities/citation-expansion/index.d.ts +6 -0
- package/dist/capabilities/citation-expansion/index.d.ts.map +1 -0
- package/dist/capabilities/citation-expansion/index.js +5 -0
- package/dist/capabilities/citation-expansion/index.js.map +1 -0
- package/dist/capabilities/citation-expansion/schemas.d.ts +28 -0
- package/dist/capabilities/citation-expansion/schemas.d.ts.map +1 -0
- package/dist/capabilities/citation-expansion/schemas.js +13 -0
- package/dist/capabilities/citation-expansion/schemas.js.map +1 -0
- package/dist/capabilities/citation-expansion/tools.d.ts +82 -0
- package/dist/capabilities/citation-expansion/tools.d.ts.map +1 -0
- package/dist/capabilities/citation-expansion/tools.js +48 -0
- package/dist/capabilities/citation-expansion/tools.js.map +1 -0
- package/dist/capabilities/citation-expansion/types.d.ts +22 -0
- package/dist/capabilities/citation-expansion/types.d.ts.map +1 -0
- package/dist/capabilities/citation-expansion/types.js +2 -0
- package/dist/capabilities/citation-expansion/types.js.map +1 -0
- package/dist/capabilities/journal-metrics/JournalMetricsService.d.ts +3 -0
- package/dist/capabilities/journal-metrics/JournalMetricsService.d.ts.map +1 -0
- package/dist/capabilities/journal-metrics/JournalMetricsService.js +142 -0
- package/dist/capabilities/journal-metrics/JournalMetricsService.js.map +1 -0
- package/dist/capabilities/journal-metrics/handler.d.ts +12 -0
- package/dist/capabilities/journal-metrics/handler.d.ts.map +1 -0
- package/dist/capabilities/journal-metrics/handler.js +38 -0
- package/dist/capabilities/journal-metrics/handler.js.map +1 -0
- package/dist/capabilities/journal-metrics/index.d.ts +6 -0
- package/dist/capabilities/journal-metrics/index.d.ts.map +1 -0
- package/dist/capabilities/journal-metrics/index.js +5 -0
- package/dist/capabilities/journal-metrics/index.js.map +1 -0
- package/dist/capabilities/journal-metrics/schemas.d.ts +28 -0
- package/dist/capabilities/journal-metrics/schemas.d.ts.map +1 -0
- package/dist/capabilities/journal-metrics/schemas.js +13 -0
- package/dist/capabilities/journal-metrics/schemas.js.map +1 -0
- package/dist/capabilities/journal-metrics/tools.d.ts +67 -0
- package/dist/capabilities/journal-metrics/tools.d.ts.map +1 -0
- package/dist/capabilities/journal-metrics/tools.js +27 -0
- package/dist/capabilities/journal-metrics/tools.js.map +1 -0
- package/dist/capabilities/journal-metrics/types.d.ts +36 -0
- package/dist/capabilities/journal-metrics/types.d.ts.map +1 -0
- package/dist/capabilities/journal-metrics/types.js +2 -0
- package/dist/capabilities/journal-metrics/types.js.map +1 -0
- package/dist/capabilities/metadata-search/MultiSourceSearchService.d.ts +9 -0
- package/dist/capabilities/metadata-search/MultiSourceSearchService.d.ts.map +1 -0
- package/dist/capabilities/metadata-search/MultiSourceSearchService.js +81 -0
- package/dist/capabilities/metadata-search/MultiSourceSearchService.js.map +1 -0
- package/dist/capabilities/metadata-search/handler.d.ts +23 -0
- package/dist/capabilities/metadata-search/handler.d.ts.map +1 -0
- package/dist/capabilities/metadata-search/handler.js +153 -0
- package/dist/capabilities/metadata-search/handler.js.map +1 -0
- package/dist/capabilities/metadata-search/index.d.ts +6 -0
- package/dist/capabilities/metadata-search/index.d.ts.map +1 -0
- package/dist/capabilities/metadata-search/index.js +5 -0
- package/dist/capabilities/metadata-search/index.js.map +1 -0
- package/dist/capabilities/metadata-search/schemas.d.ts +83 -0
- package/dist/capabilities/metadata-search/schemas.d.ts.map +1 -0
- package/dist/capabilities/metadata-search/schemas.js +80 -0
- package/dist/capabilities/metadata-search/schemas.js.map +1 -0
- package/dist/capabilities/metadata-search/tools.d.ts +178 -0
- package/dist/capabilities/metadata-search/tools.d.ts.map +1 -0
- package/dist/capabilities/metadata-search/tools.js +75 -0
- package/dist/capabilities/metadata-search/tools.js.map +1 -0
- package/dist/capabilities/metadata-search/types.d.ts +13 -0
- package/dist/capabilities/metadata-search/types.d.ts.map +1 -0
- package/dist/capabilities/metadata-search/types.js +2 -0
- package/dist/capabilities/metadata-search/types.js.map +1 -0
- package/dist/capabilities/pdf-discovery/DownloadTier.d.ts +43 -0
- package/dist/capabilities/pdf-discovery/DownloadTier.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/DownloadTier.js +2 -0
- package/dist/capabilities/pdf-discovery/DownloadTier.js.map +1 -0
- package/dist/capabilities/pdf-discovery/OpenAccessFallbackService.d.ts +16 -0
- package/dist/capabilities/pdf-discovery/OpenAccessFallbackService.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/OpenAccessFallbackService.js +202 -0
- package/dist/capabilities/pdf-discovery/OpenAccessFallbackService.js.map +1 -0
- package/dist/capabilities/pdf-discovery/batch.d.ts +74 -0
- package/dist/capabilities/pdf-discovery/batch.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/batch.js +370 -0
- package/dist/capabilities/pdf-discovery/batch.js.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiAttempt.d.ts +7 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiAttempt.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiAttempt.js +46 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiAttempt.js.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiMcpClient.d.ts +35 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiMcpClient.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiMcpClient.js +689 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiMcpClient.js.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiProgress.d.ts +23 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiProgress.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiProgress.js +30 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiProgress.js.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiReadiness.d.ts +29 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiReadiness.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiReadiness.js +176 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiReadiness.js.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiResultNormalizer.d.ts +8 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiResultNormalizer.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiResultNormalizer.js +225 -0
- package/dist/capabilities/pdf-discovery/carsi/CarsiResultNormalizer.js.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/index.d.ts +8 -0
- package/dist/capabilities/pdf-discovery/carsi/index.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/index.js +11 -0
- package/dist/capabilities/pdf-discovery/carsi/index.js.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/types.d.ts +118 -0
- package/dist/capabilities/pdf-discovery/carsi/types.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/carsi/types.js +2 -0
- package/dist/capabilities/pdf-discovery/carsi/types.js.map +1 -0
- package/dist/capabilities/pdf-discovery/handler.d.ts +28 -0
- package/dist/capabilities/pdf-discovery/handler.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/handler.js +72 -0
- package/dist/capabilities/pdf-discovery/handler.js.map +1 -0
- package/dist/capabilities/pdf-discovery/identity.d.ts +8 -0
- package/dist/capabilities/pdf-discovery/identity.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/identity.js +24 -0
- package/dist/capabilities/pdf-discovery/identity.js.map +1 -0
- package/dist/capabilities/pdf-discovery/index.d.ts +8 -0
- package/dist/capabilities/pdf-discovery/index.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/index.js +6 -0
- package/dist/capabilities/pdf-discovery/index.js.map +1 -0
- package/dist/capabilities/pdf-discovery/oaHosts.d.ts +3 -0
- package/dist/capabilities/pdf-discovery/oaHosts.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/oaHosts.js +37 -0
- package/dist/capabilities/pdf-discovery/oaHosts.js.map +1 -0
- package/dist/capabilities/pdf-discovery/pmcCloud.d.ts +6 -0
- package/dist/capabilities/pdf-discovery/pmcCloud.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/pmcCloud.js +95 -0
- package/dist/capabilities/pdf-discovery/pmcCloud.js.map +1 -0
- package/dist/capabilities/pdf-discovery/publisherApi/elsevier.d.ts +4 -0
- package/dist/capabilities/pdf-discovery/publisherApi/elsevier.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/publisherApi/elsevier.js +122 -0
- package/dist/capabilities/pdf-discovery/publisherApi/elsevier.js.map +1 -0
- package/dist/capabilities/pdf-discovery/publisherApi/index.d.ts +31 -0
- package/dist/capabilities/pdf-discovery/publisherApi/index.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/publisherApi/index.js +20 -0
- package/dist/capabilities/pdf-discovery/publisherApi/index.js.map +1 -0
- package/dist/capabilities/pdf-discovery/publisherApi/springer.d.ts +4 -0
- package/dist/capabilities/pdf-discovery/publisherApi/springer.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/publisherApi/springer.js +114 -0
- package/dist/capabilities/pdf-discovery/publisherApi/springer.js.map +1 -0
- package/dist/capabilities/pdf-discovery/schemas.d.ts +176 -0
- package/dist/capabilities/pdf-discovery/schemas.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/schemas.js +72 -0
- package/dist/capabilities/pdf-discovery/schemas.js.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/directPdfUrl.d.ts +5 -0
- package/dist/capabilities/pdf-discovery/tiers/directPdfUrl.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/directPdfUrl.js +40 -0
- package/dist/capabilities/pdf-discovery/tiers/directPdfUrl.js.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/entitledAccess.d.ts +13 -0
- package/dist/capabilities/pdf-discovery/tiers/entitledAccess.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/entitledAccess.js +123 -0
- package/dist/capabilities/pdf-discovery/tiers/entitledAccess.js.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/primary.d.ts +3 -0
- package/dist/capabilities/pdf-discovery/tiers/primary.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/primary.js +21 -0
- package/dist/capabilities/pdf-discovery/tiers/primary.js.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/publisherApi.d.ts +12 -0
- package/dist/capabilities/pdf-discovery/tiers/publisherApi.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/publisherApi.js +109 -0
- package/dist/capabilities/pdf-discovery/tiers/publisherApi.js.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/repositories.d.ts +10 -0
- package/dist/capabilities/pdf-discovery/tiers/repositories.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/repositories.js +37 -0
- package/dist/capabilities/pdf-discovery/tiers/repositories.js.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/scihub.d.ts +3 -0
- package/dist/capabilities/pdf-discovery/tiers/scihub.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/scihub.js +21 -0
- package/dist/capabilities/pdf-discovery/tiers/scihub.js.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/unpaywall.d.ts +3 -0
- package/dist/capabilities/pdf-discovery/tiers/unpaywall.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/tiers/unpaywall.js +76 -0
- package/dist/capabilities/pdf-discovery/tiers/unpaywall.js.map +1 -0
- package/dist/capabilities/pdf-discovery/tools.d.ts +337 -0
- package/dist/capabilities/pdf-discovery/tools.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/tools.js +144 -0
- package/dist/capabilities/pdf-discovery/tools.js.map +1 -0
- package/dist/capabilities/pdf-discovery/types.d.ts +86 -0
- package/dist/capabilities/pdf-discovery/types.d.ts.map +1 -0
- package/dist/capabilities/pdf-discovery/types.js +2 -0
- package/dist/capabilities/pdf-discovery/types.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1196 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/ConfigService.d.ts +28 -0
- package/dist/config/ConfigService.d.ts.map +1 -0
- package/dist/config/ConfigService.js +204 -0
- package/dist/config/ConfigService.js.map +1 -0
- package/dist/config/ResultCaps.d.ts +4 -0
- package/dist/config/ResultCaps.d.ts.map +1 -0
- package/dist/config/ResultCaps.js +10 -0
- package/dist/config/ResultCaps.js.map +1 -0
- package/dist/config/constants.d.ts +158 -0
- package/dist/config/constants.d.ts.map +1 -0
- package/dist/config/constants.js +102 -0
- package/dist/config/constants.js.map +1 -0
- package/dist/core/capabilityProfile.d.ts +2 -0
- package/dist/core/capabilityProfile.d.ts.map +1 -0
- package/dist/core/capabilityProfile.js +2 -0
- package/dist/core/capabilityProfile.js.map +1 -0
- package/dist/core/diagnostics.d.ts +2 -0
- package/dist/core/diagnostics.d.ts.map +1 -0
- package/dist/core/diagnostics.js +2 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/handleToolCall.d.ts +13 -0
- package/dist/core/handleToolCall.d.ts.map +1 -0
- package/dist/core/handleToolCall.js +304 -0
- package/dist/core/handleToolCall.js.map +1 -0
- package/dist/core/httpPolicies.d.ts +2 -0
- package/dist/core/httpPolicies.d.ts.map +1 -0
- package/dist/core/httpPolicies.js +2 -0
- package/dist/core/httpPolicies.js.map +1 -0
- package/dist/core/liveSmoke.d.ts +2 -0
- package/dist/core/liveSmoke.d.ts.map +1 -0
- package/dist/core/liveSmoke.js +2 -0
- package/dist/core/liveSmoke.js.map +1 -0
- package/dist/core/platformFactories.d.ts +2 -0
- package/dist/core/platformFactories.d.ts.map +1 -0
- package/dist/core/platformFactories.js +2 -0
- package/dist/core/platformFactories.js.map +1 -0
- package/dist/core/platformMetadata.d.ts +2 -0
- package/dist/core/platformMetadata.d.ts.map +1 -0
- package/dist/core/platformMetadata.js +2 -0
- package/dist/core/platformMetadata.js.map +1 -0
- package/dist/core/schemas.d.ts +365 -0
- package/dist/core/schemas.d.ts.map +1 -0
- package/dist/core/schemas.js +256 -0
- package/dist/core/schemas.js.map +1 -0
- package/dist/core/searchers.d.ts +41 -0
- package/dist/core/searchers.d.ts.map +1 -0
- package/dist/core/searchers.js +24 -0
- package/dist/core/searchers.js.map +1 -0
- package/dist/core/textReports.d.ts +2 -0
- package/dist/core/textReports.d.ts.map +1 -0
- package/dist/core/textReports.js +2 -0
- package/dist/core/textReports.js.map +1 -0
- package/dist/core/tools.d.ts +7 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +489 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/infrastructure/cache/RequestCache.d.ts +26 -0
- package/dist/infrastructure/cache/RequestCache.d.ts.map +1 -0
- package/dist/infrastructure/cache/RequestCache.js +66 -0
- package/dist/infrastructure/cache/RequestCache.js.map +1 -0
- package/dist/infrastructure/http/ErrorHandler.d.ts +101 -0
- package/dist/infrastructure/http/ErrorHandler.d.ts.map +1 -0
- package/dist/infrastructure/http/ErrorHandler.js +278 -0
- package/dist/infrastructure/http/ErrorHandler.js.map +1 -0
- package/dist/infrastructure/http/HttpClient.d.ts +31 -0
- package/dist/infrastructure/http/HttpClient.d.ts.map +1 -0
- package/dist/infrastructure/http/HttpClient.js +52 -0
- package/dist/infrastructure/http/HttpClient.js.map +1 -0
- package/dist/infrastructure/pdf/PDFExtractor.d.ts +34 -0
- package/dist/infrastructure/pdf/PDFExtractor.d.ts.map +1 -0
- package/dist/infrastructure/pdf/PDFExtractor.js +130 -0
- package/dist/infrastructure/pdf/PDFExtractor.js.map +1 -0
- package/dist/infrastructure/pdf/PdfDownload.d.ts +16 -0
- package/dist/infrastructure/pdf/PdfDownload.d.ts.map +1 -0
- package/dist/infrastructure/pdf/PdfDownload.js +242 -0
- package/dist/infrastructure/pdf/PdfDownload.js.map +1 -0
- package/dist/infrastructure/pdf/PdfFirstPage.cjs +70 -0
- package/dist/infrastructure/pdf/PdfFirstPage.cjs.map +1 -0
- package/dist/infrastructure/pdf/PdfFirstPage.d.cts +16 -0
- package/dist/infrastructure/pdf/PdfFirstPage.d.cts.map +1 -0
- package/dist/infrastructure/pdf/PdfIdentity.d.ts +29 -0
- package/dist/infrastructure/pdf/PdfIdentity.d.ts.map +1 -0
- package/dist/infrastructure/pdf/PdfIdentity.js +283 -0
- package/dist/infrastructure/pdf/PdfIdentity.js.map +1 -0
- package/dist/infrastructure/rate-limit/RateLimiter.d.ts +50 -0
- package/dist/infrastructure/rate-limit/RateLimiter.d.ts.map +1 -0
- package/dist/infrastructure/rate-limit/RateLimiter.js +128 -0
- package/dist/infrastructure/rate-limit/RateLimiter.js.map +1 -0
- package/dist/infrastructure/runlog/RunLedger.d.ts +61 -0
- package/dist/infrastructure/runlog/RunLedger.d.ts.map +1 -0
- package/dist/infrastructure/runlog/RunLedger.js +284 -0
- package/dist/infrastructure/runlog/RunLedger.js.map +1 -0
- package/dist/infrastructure/runlog/failureClass.d.ts +26 -0
- package/dist/infrastructure/runlog/failureClass.d.ts.map +1 -0
- package/dist/infrastructure/runlog/failureClass.js +125 -0
- package/dist/infrastructure/runlog/failureClass.js.map +1 -0
- package/dist/infrastructure/security/SecurityUtils.d.ts +80 -0
- package/dist/infrastructure/security/SecurityUtils.d.ts.map +1 -0
- package/dist/infrastructure/security/SecurityUtils.js +357 -0
- package/dist/infrastructure/security/SecurityUtils.js.map +1 -0
- package/dist/management/capability-profile/carsiReadiness.d.ts +10 -0
- package/dist/management/capability-profile/carsiReadiness.d.ts.map +1 -0
- package/dist/management/capability-profile/carsiReadiness.js +13 -0
- package/dist/management/capability-profile/carsiReadiness.js.map +1 -0
- package/dist/management/capability-profile/index.d.ts +26 -0
- package/dist/management/capability-profile/index.d.ts.map +1 -0
- package/dist/management/capability-profile/index.js +183 -0
- package/dist/management/capability-profile/index.js.map +1 -0
- package/dist/management/carsi/host.d.ts +4 -0
- package/dist/management/carsi/host.d.ts.map +1 -0
- package/dist/management/carsi/host.js +65 -0
- package/dist/management/carsi/host.js.map +1 -0
- package/dist/management/carsi/installer.d.ts +146 -0
- package/dist/management/carsi/installer.d.ts.map +1 -0
- package/dist/management/carsi/installer.js +527 -0
- package/dist/management/carsi/installer.js.map +1 -0
- package/dist/management/carsi/runtime.d.ts +31 -0
- package/dist/management/carsi/runtime.d.ts.map +1 -0
- package/dist/management/carsi/runtime.js +67 -0
- package/dist/management/carsi/runtime.js.map +1 -0
- package/dist/management/config/index.d.ts +2 -0
- package/dist/management/config/index.d.ts.map +1 -0
- package/dist/management/config/index.js +2 -0
- package/dist/management/config/index.js.map +1 -0
- package/dist/management/diagnostics/index.d.ts +43 -0
- package/dist/management/diagnostics/index.d.ts.map +1 -0
- package/dist/management/diagnostics/index.js +610 -0
- package/dist/management/diagnostics/index.js.map +1 -0
- package/dist/management/failures/index.d.ts +47 -0
- package/dist/management/failures/index.d.ts.map +1 -0
- package/dist/management/failures/index.js +134 -0
- package/dist/management/failures/index.js.map +1 -0
- package/dist/management/reports/index.d.ts +32 -0
- package/dist/management/reports/index.d.ts.map +1 -0
- package/dist/management/reports/index.js +123 -0
- package/dist/management/reports/index.js.map +1 -0
- package/dist/management/skills/autoSync.d.ts +41 -0
- package/dist/management/skills/autoSync.d.ts.map +1 -0
- package/dist/management/skills/autoSync.js +142 -0
- package/dist/management/skills/autoSync.js.map +1 -0
- package/dist/management/skills/index.d.ts +3 -0
- package/dist/management/skills/index.d.ts.map +1 -0
- package/dist/management/skills/index.js +3 -0
- package/dist/management/skills/index.js.map +1 -0
- package/dist/management/smoke/index.d.ts +44 -0
- package/dist/management/smoke/index.d.ts.map +1 -0
- package/dist/management/smoke/index.js +254 -0
- package/dist/management/smoke/index.js.map +1 -0
- package/dist/models/Paper.d.ts +64 -0
- package/dist/models/Paper.d.ts.map +1 -0
- package/dist/models/Paper.js +70 -0
- package/dist/models/Paper.js.map +1 -0
- package/dist/platforms/ACMSearcher.d.ts +16 -0
- package/dist/platforms/ACMSearcher.d.ts.map +1 -0
- package/dist/platforms/ACMSearcher.js +125 -0
- package/dist/platforms/ACMSearcher.js.map +1 -0
- package/dist/platforms/BioRxivSearcher.d.ts +47 -0
- package/dist/platforms/BioRxivSearcher.d.ts.map +1 -0
- package/dist/platforms/BioRxivSearcher.js +215 -0
- package/dist/platforms/BioRxivSearcher.js.map +1 -0
- package/dist/platforms/CORESearcher.d.ts +17 -0
- package/dist/platforms/CORESearcher.d.ts.map +1 -0
- package/dist/platforms/CORESearcher.js +185 -0
- package/dist/platforms/CORESearcher.js.map +1 -0
- package/dist/platforms/CrossrefSearcher.d.ts +34 -0
- package/dist/platforms/CrossrefSearcher.d.ts.map +1 -0
- package/dist/platforms/CrossrefSearcher.js +339 -0
- package/dist/platforms/CrossrefSearcher.js.map +1 -0
- package/dist/platforms/DBLPSearcher.d.ts +16 -0
- package/dist/platforms/DBLPSearcher.d.ts.map +1 -0
- package/dist/platforms/DBLPSearcher.js +116 -0
- package/dist/platforms/DBLPSearcher.js.map +1 -0
- package/dist/platforms/EuropePMCSearcher.d.ts +20 -0
- package/dist/platforms/EuropePMCSearcher.d.ts.map +1 -0
- package/dist/platforms/EuropePMCSearcher.js +173 -0
- package/dist/platforms/EuropePMCSearcher.js.map +1 -0
- package/dist/platforms/GoogleScholarSearcher.d.ts +142 -0
- package/dist/platforms/GoogleScholarSearcher.d.ts.map +1 -0
- package/dist/platforms/GoogleScholarSearcher.js +648 -0
- package/dist/platforms/GoogleScholarSearcher.js.map +1 -0
- package/dist/platforms/IACRSearcher.d.ts +51 -0
- package/dist/platforms/IACRSearcher.d.ts.map +1 -0
- package/dist/platforms/IACRSearcher.js +339 -0
- package/dist/platforms/IACRSearcher.js.map +1 -0
- package/dist/platforms/IEEESearcher.d.ts +15 -0
- package/dist/platforms/IEEESearcher.d.ts.map +1 -0
- package/dist/platforms/IEEESearcher.js +123 -0
- package/dist/platforms/IEEESearcher.js.map +1 -0
- package/dist/platforms/OpenAIRESearcher.d.ts +22 -0
- package/dist/platforms/OpenAIRESearcher.d.ts.map +1 -0
- package/dist/platforms/OpenAIRESearcher.js +235 -0
- package/dist/platforms/OpenAIRESearcher.js.map +1 -0
- package/dist/platforms/OpenAlexSearcher.d.ts +14 -0
- package/dist/platforms/OpenAlexSearcher.d.ts.map +1 -0
- package/dist/platforms/OpenAlexSearcher.js +114 -0
- package/dist/platforms/OpenAlexSearcher.js.map +1 -0
- package/dist/platforms/OpenReviewSearcher.d.ts +19 -0
- package/dist/platforms/OpenReviewSearcher.d.ts.map +1 -0
- package/dist/platforms/OpenReviewSearcher.js +141 -0
- package/dist/platforms/OpenReviewSearcher.js.map +1 -0
- package/dist/platforms/PMCSearcher.d.ts +20 -0
- package/dist/platforms/PMCSearcher.d.ts.map +1 -0
- package/dist/platforms/PMCSearcher.js +177 -0
- package/dist/platforms/PMCSearcher.js.map +1 -0
- package/dist/platforms/PaperSource.d.ts +149 -0
- package/dist/platforms/PaperSource.d.ts.map +1 -0
- package/dist/platforms/PaperSource.js +125 -0
- package/dist/platforms/PaperSource.js.map +1 -0
- package/dist/platforms/PubMedSearcher.d.ts +104 -0
- package/dist/platforms/PubMedSearcher.d.ts.map +1 -0
- package/dist/platforms/PubMedSearcher.js +430 -0
- package/dist/platforms/PubMedSearcher.js.map +1 -0
- package/dist/platforms/SciHubSearcher.d.ts +66 -0
- package/dist/platforms/SciHubSearcher.d.ts.map +1 -0
- package/dist/platforms/SciHubSearcher.js +398 -0
- package/dist/platforms/SciHubSearcher.js.map +1 -0
- package/dist/platforms/ScienceDirectSearcher.d.ts +42 -0
- package/dist/platforms/ScienceDirectSearcher.d.ts.map +1 -0
- package/dist/platforms/ScienceDirectSearcher.js +334 -0
- package/dist/platforms/ScienceDirectSearcher.js.map +1 -0
- package/dist/platforms/ScopusSearcher.d.ts +43 -0
- package/dist/platforms/ScopusSearcher.d.ts.map +1 -0
- package/dist/platforms/ScopusSearcher.js +377 -0
- package/dist/platforms/ScopusSearcher.js.map +1 -0
- package/dist/platforms/SemanticScholarSearcher.d.ts +96 -0
- package/dist/platforms/SemanticScholarSearcher.d.ts.map +1 -0
- package/dist/platforms/SemanticScholarSearcher.js +419 -0
- package/dist/platforms/SemanticScholarSearcher.js.map +1 -0
- package/dist/platforms/SpringerSearcher.d.ts +54 -0
- package/dist/platforms/SpringerSearcher.d.ts.map +1 -0
- package/dist/platforms/SpringerSearcher.js +387 -0
- package/dist/platforms/SpringerSearcher.js.map +1 -0
- package/dist/platforms/USENIXSearcher.d.ts +14 -0
- package/dist/platforms/USENIXSearcher.d.ts.map +1 -0
- package/dist/platforms/USENIXSearcher.js +75 -0
- package/dist/platforms/USENIXSearcher.js.map +1 -0
- package/dist/platforms/UnpaywallSearcher.d.ts +29 -0
- package/dist/platforms/UnpaywallSearcher.d.ts.map +1 -0
- package/dist/platforms/UnpaywallSearcher.js +135 -0
- package/dist/platforms/UnpaywallSearcher.js.map +1 -0
- package/dist/platforms/WebOfScienceSearcher.d.ts +111 -0
- package/dist/platforms/WebOfScienceSearcher.d.ts.map +1 -0
- package/dist/platforms/WebOfScienceSearcher.js +500 -0
- package/dist/platforms/WebOfScienceSearcher.js.map +1 -0
- package/dist/registry/aliases.d.ts +2 -0
- package/dist/registry/aliases.d.ts.map +1 -0
- package/dist/registry/aliases.js +2 -0
- package/dist/registry/aliases.js.map +1 -0
- package/dist/registry/httpPolicies.d.ts +3 -0
- package/dist/registry/httpPolicies.d.ts.map +1 -0
- package/dist/registry/httpPolicies.js +13 -0
- package/dist/registry/httpPolicies.js.map +1 -0
- package/dist/registry/platformFactories.d.ts +8 -0
- package/dist/registry/platformFactories.d.ts.map +1 -0
- package/dist/registry/platformFactories.js +51 -0
- package/dist/registry/platformFactories.js.map +1 -0
- package/dist/registry/platformMetadata.d.ts +55 -0
- package/dist/registry/platformMetadata.d.ts.map +1 -0
- package/dist/registry/platformMetadata.js +438 -0
- package/dist/registry/platformMetadata.js.map +1 -0
- package/dist/services/CitationService.d.ts +3 -0
- package/dist/services/CitationService.d.ts.map +1 -0
- package/dist/services/CitationService.js +2 -0
- package/dist/services/CitationService.js.map +1 -0
- package/dist/services/JournalMetricsService.d.ts +3 -0
- package/dist/services/JournalMetricsService.d.ts.map +1 -0
- package/dist/services/JournalMetricsService.js +2 -0
- package/dist/services/JournalMetricsService.js.map +1 -0
- package/dist/services/MultiSourceSearchService.d.ts +3 -0
- package/dist/services/MultiSourceSearchService.d.ts.map +1 -0
- package/dist/services/MultiSourceSearchService.js +2 -0
- package/dist/services/MultiSourceSearchService.js.map +1 -0
- package/dist/services/OpenAccessFallbackService.d.ts +4 -0
- package/dist/services/OpenAccessFallbackService.d.ts.map +1 -0
- package/dist/services/OpenAccessFallbackService.js +2 -0
- package/dist/services/OpenAccessFallbackService.js.map +1 -0
- package/dist/skills/SkillInstaller.d.ts +110 -0
- package/dist/skills/SkillInstaller.d.ts.map +1 -0
- package/dist/skills/SkillInstaller.js +393 -0
- package/dist/skills/SkillInstaller.js.map +1 -0
- package/dist/utils/ErrorHandler.d.ts +3 -0
- package/dist/utils/ErrorHandler.d.ts.map +1 -0
- package/dist/utils/ErrorHandler.js +3 -0
- package/dist/utils/ErrorHandler.js.map +1 -0
- package/dist/utils/HttpClient.d.ts +2 -0
- package/dist/utils/HttpClient.d.ts.map +1 -0
- package/dist/utils/HttpClient.js +2 -0
- package/dist/utils/HttpClient.js.map +1 -0
- package/dist/utils/Logger.d.ts +6 -0
- package/dist/utils/Logger.d.ts.map +1 -0
- package/dist/utils/Logger.js +26 -0
- package/dist/utils/Logger.js.map +1 -0
- package/dist/utils/PDFExtractor.d.ts +3 -0
- package/dist/utils/PDFExtractor.d.ts.map +1 -0
- package/dist/utils/PDFExtractor.js +3 -0
- package/dist/utils/PDFExtractor.js.map +1 -0
- package/dist/utils/PdfDownload.d.ts +2 -0
- package/dist/utils/PdfDownload.d.ts.map +1 -0
- package/dist/utils/PdfDownload.js +2 -0
- package/dist/utils/PdfDownload.js.map +1 -0
- package/dist/utils/QuotaManager.d.ts +32 -0
- package/dist/utils/QuotaManager.d.ts.map +1 -0
- package/dist/utils/QuotaManager.js +95 -0
- package/dist/utils/QuotaManager.js.map +1 -0
- package/dist/utils/RateLimiter.d.ts +2 -0
- package/dist/utils/RateLimiter.d.ts.map +1 -0
- package/dist/utils/RateLimiter.js +2 -0
- package/dist/utils/RateLimiter.js.map +1 -0
- package/dist/utils/RequestCache.d.ts +3 -0
- package/dist/utils/RequestCache.d.ts.map +1 -0
- package/dist/utils/RequestCache.js +3 -0
- package/dist/utils/RequestCache.js.map +1 -0
- package/dist/utils/SecurityUtils.d.ts +3 -0
- package/dist/utils/SecurityUtils.d.ts.map +1 -0
- package/dist/utils/SecurityUtils.js +3 -0
- package/dist/utils/SecurityUtils.js.map +1 -0
- package/package.json +118 -4
- package/skills/paper-search/SKILL.md +151 -0
- package/skills/paper-search/references/browser-download.md +101 -0
- package/skills/paper-search/references/capability-routing.md +174 -0
- package/skills/paper-search/references/carsi-setup.md +69 -0
- package/skills/paper-search/references/cli-contract.md +200 -0
- package/skills/paper-search/references/management-layer.md +149 -0
- package/skills/paper-search/references/publisher-support.md +72 -0
- package/skills/paper-search/references/troubleshooting.md +15 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"""Adapter interface and registry (publisher level, optionally journal level)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import re
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Iterable
|
|
7
|
+
|
|
8
|
+
_REGISTRY: dict[str, list[type["PublisherAdapter"]]] = {}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class SupplementLink:
|
|
13
|
+
"""One supplementary file offered on the article page."""
|
|
14
|
+
|
|
15
|
+
url: str
|
|
16
|
+
label: str = ""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class PublisherAdapter:
|
|
20
|
+
"""Publisher-specific answers for the shared engine; ``None`` = no opinion.
|
|
21
|
+
|
|
22
|
+
A journal with its own quirks subclasses its publisher's adapter, sets one
|
|
23
|
+
or more of ``issns`` / ``hosts`` / ``doi_pattern`` and overrides only the
|
|
24
|
+
hooks that differ; everything else is inherited.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
#: Profile name in lower case; the registry key.
|
|
28
|
+
publisher = ""
|
|
29
|
+
#: Journal-level selection: print/electronic ISSNs (upper case, with hyphen).
|
|
30
|
+
issns: frozenset[str] = frozenset()
|
|
31
|
+
#: Journal-level selection: hosts the journal is served from (or their parent domain).
|
|
32
|
+
hosts: tuple[str, ...] = ()
|
|
33
|
+
#: Journal-level selection: regular expression on the lower-case DOI.
|
|
34
|
+
doi_pattern: str = ""
|
|
35
|
+
#: Captured PDFs must come from this article's own PDF endpoint.
|
|
36
|
+
validates_article_pdf = False
|
|
37
|
+
#: Event name used when a captured PDF is not accepted.
|
|
38
|
+
pdf_rejected_event = "publisher_pdf_rejected"
|
|
39
|
+
#: URL patterns whose PDF responses are captured natively by the browser.
|
|
40
|
+
native_pdf_patterns: tuple[str, ...] = ()
|
|
41
|
+
#: The site's own PDF addresses: once the page's citation PDF is one of them
|
|
42
|
+
#: (batch_pdf_urls ``_metadata_pdf_urls``), it comes first, is captured
|
|
43
|
+
#: natively, and every other PDF response is refused.
|
|
44
|
+
metadata_pdf_patterns: tuple[str, ...] = ()
|
|
45
|
+
#: The site's PDF paths name no article: the article page's own citation PDF
|
|
46
|
+
#: (``citation_doi`` this DOI) is the only candidate and the only PDF accepted.
|
|
47
|
+
binds_pdf_to_citation = False
|
|
48
|
+
#: PDF responses are read later (signed CDN URLs answer only once).
|
|
49
|
+
defers_pdf_response_body = False
|
|
50
|
+
#: Open PDF candidates by script navigation in the article tab.
|
|
51
|
+
async_pdf_navigation = False
|
|
52
|
+
# Only a complete PDF counts (%%EOF at the end, pages, not repaired): a viewer's
|
|
53
|
+
# first range can start with %PDF yet hold no usable pages (Taylor & Francis).
|
|
54
|
+
requires_complete_pdf = False
|
|
55
|
+
# The main PDF anchor is marked as a download: keep it out of the browser's
|
|
56
|
+
# download manager (Chromium writes a UUID file even when CDP took the body).
|
|
57
|
+
keeps_pdf_out_of_downloads = False
|
|
58
|
+
# The article's PDF endpoint redirects to a CDN copy (``is_pdf_cdn_url``); the
|
|
59
|
+
# redirect is remembered as its provenance (Oxford Academic -> Silverchair).
|
|
60
|
+
pdf_cdn_redirects = False
|
|
61
|
+
# Only the article's own PDF URLs are tried as candidates.
|
|
62
|
+
article_pdf_candidates_only = False
|
|
63
|
+
# Failures keep a full-page screenshot in the diagnostic packet.
|
|
64
|
+
diagnostic_screenshots = True
|
|
65
|
+
# A finished login that lands on the publisher's home page goes back to the
|
|
66
|
+
# article once (Oxford Academic).
|
|
67
|
+
returns_from_home_page = False
|
|
68
|
+
# A login that ends on any other page of the publisher goes back to this
|
|
69
|
+
# record's article (APS).
|
|
70
|
+
returns_to_record_article = False
|
|
71
|
+
# A captured response's own URL must be this article's PDF endpoint, not
|
|
72
|
+
# only a hop of its redirect chain.
|
|
73
|
+
binds_response_url = False
|
|
74
|
+
# A CARSI login that opened no institution entry (and reached no login
|
|
75
|
+
# page) ends as ``publisher_institution_entry_missing``.
|
|
76
|
+
requires_institution_entry = False
|
|
77
|
+
# Every PDF response that is not this article's bound PDF
|
|
78
|
+
# (``binds_pdf_to_citation``) is refused and kept from the browser.
|
|
79
|
+
discards_unbound_pdfs = False
|
|
80
|
+
# Redirect responses are passed over while capturing: the final response
|
|
81
|
+
# keeps the chain and decides whether it is the article's PDF.
|
|
82
|
+
passes_over_redirects = False
|
|
83
|
+
# Words (lower case) of the site's own IP-block page, besides the shared
|
|
84
|
+
# "IP address ... blocked" rule (ACS's contact mailbox).
|
|
85
|
+
block_page_markers: tuple[str, ...] = ()
|
|
86
|
+
|
|
87
|
+
def __init__(self, downloader: Any):
|
|
88
|
+
self.d = downloader
|
|
89
|
+
|
|
90
|
+
# --- Profile-level rules, asked by the PDF router (engine/router.py),
|
|
91
|
+
# which works on a profile: no downloader, page or journal is known there.
|
|
92
|
+
|
|
93
|
+
#: Supplementary-file URLs are matched after percent-decoding.
|
|
94
|
+
unquotes_supplement_urls = False
|
|
95
|
+
|
|
96
|
+
@classmethod
|
|
97
|
+
def profile_pdf_candidates(cls, doi: str, source_url: str) -> list[str]:
|
|
98
|
+
"""PDF URLs derived from the DOI and the source page, tried before the profile's templates."""
|
|
99
|
+
return []
|
|
100
|
+
|
|
101
|
+
@classmethod
|
|
102
|
+
def profile_pdf_candidate_url(cls, url: str) -> bool | None:
|
|
103
|
+
"""Whether ``url`` may be a PDF candidate (None = the profile's PDF URL markers decide)."""
|
|
104
|
+
return None
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def keeps_pdf_candidate(cls, profile: Any, url: str, doi: str) -> bool:
|
|
108
|
+
"""Whether the finished candidate list keeps ``url``."""
|
|
109
|
+
return True
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def names_supplement(cls, url: str) -> bool:
|
|
113
|
+
"""A supplementary file by the publisher's own file naming (``url`` lower
|
|
114
|
+
case, decoded when ``unquotes_supplement_urls``); the profile's markers follow."""
|
|
115
|
+
return False
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def belongs_to_article(cls, url: str, doi: str, source_url: str) -> bool | None:
|
|
119
|
+
"""Whether a PDF URL found on the page is this article's (None = it is)."""
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
@classmethod
|
|
123
|
+
def is_journal_level(cls) -> bool:
|
|
124
|
+
return bool(cls.issns or cls.hosts or cls.doi_pattern)
|
|
125
|
+
|
|
126
|
+
@classmethod
|
|
127
|
+
def matches_journal(cls, *, doi: str = "", host: str = "", issns: Iterable[str] = ()) -> bool:
|
|
128
|
+
if not cls.is_journal_level():
|
|
129
|
+
return False
|
|
130
|
+
host = (host or "").lower()
|
|
131
|
+
if cls.issns and cls.issns & {str(i).upper() for i in issns}:
|
|
132
|
+
return True
|
|
133
|
+
if host and any(host == h or host.endswith("." + h) for h in cls.hosts):
|
|
134
|
+
return True
|
|
135
|
+
return bool(cls.doi_pattern and doi and re.fullmatch(cls.doi_pattern, doi.lower()))
|
|
136
|
+
|
|
137
|
+
def login_url(self) -> str | None:
|
|
138
|
+
"""Start page for a stand-alone institution login."""
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
def article_url(self, doi: str) -> str | None:
|
|
142
|
+
"""This article's page when the profile's template cannot give it (APS's
|
|
143
|
+
journal codes); None: the profile's ``article_url``."""
|
|
144
|
+
return None
|
|
145
|
+
|
|
146
|
+
def login_page_url(self, page: Any) -> str | None:
|
|
147
|
+
"""A page to start the institution login from instead of the current one
|
|
148
|
+
(e.g. the publisher's main platform for a journal's own site)."""
|
|
149
|
+
return None
|
|
150
|
+
|
|
151
|
+
def ensure_login(self, page: Any, result: Any) -> bool | None:
|
|
152
|
+
"""Open the article and sign in with the publisher's own flow; True when
|
|
153
|
+
the article is accessible. None = the engine's flow."""
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
def complete_login(self, page: Any, result: Any) -> bool | None:
|
|
157
|
+
"""Finish the sign-in from the current page with the publisher's own flow.
|
|
158
|
+
None = the engine's flow."""
|
|
159
|
+
return None
|
|
160
|
+
|
|
161
|
+
def login_page_urls(self, page: Any) -> list[str]:
|
|
162
|
+
"""Pages to start the institution login from, in order; each is opened at
|
|
163
|
+
most once per article. Default: ``login_page_url``."""
|
|
164
|
+
url = self.login_page_url(page)
|
|
165
|
+
return [url] if url else []
|
|
166
|
+
|
|
167
|
+
def own_institution_entry(self, page: Any, result: Any) -> bool | None:
|
|
168
|
+
"""Open the institution login with the publisher's own flow, asked before
|
|
169
|
+
the engine's whole entry lookup (the adapter's login pages included);
|
|
170
|
+
True when the chooser is reached. None = the engine's lookup."""
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
def open_institution_entry(self, page: Any, result: Any) -> bool | None:
|
|
174
|
+
"""Open the publisher's own institution login; True when navigated."""
|
|
175
|
+
return None
|
|
176
|
+
|
|
177
|
+
def openathens_entry(self, page: Any, result: Any) -> bool | None:
|
|
178
|
+
"""Outside CARSI, asked before the generic OpenAthens control: the
|
|
179
|
+
publisher's own way to its OpenAthens sign-in from this page. True when
|
|
180
|
+
navigated, False = none here (no generic control either), None = no opinion."""
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
def click_institution_control(self, page: Any, result: Any) -> bool:
|
|
184
|
+
"""Outside CARSI, once no generic institution control matched: click the
|
|
185
|
+
publisher's own; True when clicked."""
|
|
186
|
+
return False
|
|
187
|
+
|
|
188
|
+
def fill_institution_search(self, page: Any, result: Any) -> bool:
|
|
189
|
+
"""Outside CARSI: type the configured school into the publisher's own
|
|
190
|
+
institution search and choose its entry; True when chosen."""
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
def looks_logged_out(self, page: Any, url: str, text: str) -> bool | None:
|
|
194
|
+
"""A page type of this site that the shared access rule
|
|
195
|
+
(engine/access_rules.py) cannot judge: True = shown without
|
|
196
|
+
access, False = readable, None = the shared rule decides. Asked after the
|
|
197
|
+
institution session and the reader's access, before offers and denials."""
|
|
198
|
+
return None
|
|
199
|
+
|
|
200
|
+
# Controls that open the institution login, tried before the generic ones.
|
|
201
|
+
sso_selectors: tuple[str, ...] = ()
|
|
202
|
+
|
|
203
|
+
def login_block_reason(self, page: Any, text: str) -> str | None:
|
|
204
|
+
"""A publisher-specific verdict on whether the login cannot proceed ("" = not blocked)."""
|
|
205
|
+
return None
|
|
206
|
+
|
|
207
|
+
def chooser_block_reason(self, page: Any, url: str, text: str) -> str | None:
|
|
208
|
+
"""On the publisher's own institution chooser, asked right after the
|
|
209
|
+
verification checks and before every other block rule: "" = the chooser
|
|
210
|
+
can be used, a reason = the login cannot proceed (None = no opinion)."""
|
|
211
|
+
return None
|
|
212
|
+
|
|
213
|
+
def content_error(self, page: Any) -> bool:
|
|
214
|
+
"""The publisher's own content-service error page (not a login or entitlement issue)."""
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
def is_redirect_page(self, url: str) -> bool:
|
|
218
|
+
"""A page that moves on to the article by script (wait for it to leave)."""
|
|
219
|
+
return False
|
|
220
|
+
|
|
221
|
+
def is_institution_chooser(self, url: str) -> bool:
|
|
222
|
+
"""A page of the publisher's own sign-in service, on another host of its
|
|
223
|
+
own, where the user's organisation is searched; the configured school is
|
|
224
|
+
chosen there as on a federation's chooser."""
|
|
225
|
+
return False
|
|
226
|
+
|
|
227
|
+
def institution_chooser_open(self, page: Any) -> bool:
|
|
228
|
+
"""The publisher's own federation/school chooser is on screen: there the
|
|
229
|
+
school is chosen (``choose_institution``) and nothing else is clicked."""
|
|
230
|
+
return False
|
|
231
|
+
|
|
232
|
+
def prepare_institution_choice(self, page: Any, result: Any) -> bool | None:
|
|
233
|
+
"""In the CARSI school choice, after the federation form and the school
|
|
234
|
+
assistance, before the SeamlessAccess and publisher choosers: the
|
|
235
|
+
publisher's own step on this page. False ends this pass (None = go on)."""
|
|
236
|
+
return None
|
|
237
|
+
|
|
238
|
+
def choose_institution(self, page: Any, result: Any) -> bool | None:
|
|
239
|
+
"""Choose the federation and school on the publisher's own chooser; True
|
|
240
|
+
when something was chosen. None = the engine's generic school assistance."""
|
|
241
|
+
return None
|
|
242
|
+
|
|
243
|
+
def follow_federated_login(self, page: Any, result: Any) -> bool:
|
|
244
|
+
"""On the publisher's own login page, follow its institutional (federated)
|
|
245
|
+
option instead of the personal form; True when navigated."""
|
|
246
|
+
return False
|
|
247
|
+
|
|
248
|
+
def is_other_article(self, page: Any, doi: str) -> bool:
|
|
249
|
+
"""The page is another article's page (a login returned to a stale target)."""
|
|
250
|
+
return False
|
|
251
|
+
|
|
252
|
+
def unsupported_platform(self, page: Any) -> str | None:
|
|
253
|
+
"""Name of the platform the article page landed on when the engine cannot
|
|
254
|
+
sign in or capture a PDF there; None = supported."""
|
|
255
|
+
return None
|
|
256
|
+
|
|
257
|
+
def open_pdf_entry(self, page: Any, result: Any) -> bool | None:
|
|
258
|
+
"""Click the article's own PDF control; True when clicked."""
|
|
259
|
+
return None
|
|
260
|
+
|
|
261
|
+
def is_article_pdf_url(self, url: str, doi: str = "") -> bool | None:
|
|
262
|
+
"""Whether ``url`` is this publisher's article PDF endpoint (for ``doi``)."""
|
|
263
|
+
return None
|
|
264
|
+
|
|
265
|
+
def is_pdf_cdn_url(self, url: str, doi: str) -> bool:
|
|
266
|
+
"""A CDN copy of this article's PDF, reached by redirect from its endpoint."""
|
|
267
|
+
return False
|
|
268
|
+
|
|
269
|
+
def is_article_page_url(self, url: str) -> bool | None:
|
|
270
|
+
"""Whether ``url`` is an article page of this publisher on a host outside the profile's domains."""
|
|
271
|
+
return None
|
|
272
|
+
|
|
273
|
+
def is_success_article_url(self, url: str) -> bool | None:
|
|
274
|
+
"""Whether ``url`` is an article page, for the access checks only (None =
|
|
275
|
+
the profile's success markers decide). Unlike ``is_article_page_url`` it
|
|
276
|
+
neither makes the host the publisher's nor the page a supplements page."""
|
|
277
|
+
return None
|
|
278
|
+
|
|
279
|
+
def supplements_page_url(self, doi: str) -> str | None:
|
|
280
|
+
"""The article page listing supplementary files (None = the profile's article URL)."""
|
|
281
|
+
return None
|
|
282
|
+
|
|
283
|
+
def supplements_page_urls(self, doi: str) -> list[str]:
|
|
284
|
+
"""Pages to look for supplements on, in order; the first that lists any is used."""
|
|
285
|
+
url = self.supplements_page_url(doi)
|
|
286
|
+
return [url] if url else []
|
|
287
|
+
|
|
288
|
+
def supplement_links(self, page: Any, doi: str) -> list[SupplementLink] | None:
|
|
289
|
+
"""Supplementary files listed on the article page."""
|
|
290
|
+
return None
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def register(cls: type[PublisherAdapter]) -> type[PublisherAdapter]:
|
|
294
|
+
_REGISTRY.setdefault(cls.publisher, []).append(cls)
|
|
295
|
+
return cls
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def adapter_class(publisher: str, *, doi: str = "", host: str = "",
|
|
299
|
+
issns: Iterable[str] = ()) -> type[PublisherAdapter]:
|
|
300
|
+
"""Most specific adapter: journal, then publisher, then the generic one."""
|
|
301
|
+
classes = _REGISTRY.get((publisher or "").lower(), [])
|
|
302
|
+
issns = tuple(issns)
|
|
303
|
+
for cls in classes:
|
|
304
|
+
if cls.matches_journal(doi=doi, host=host, issns=issns):
|
|
305
|
+
return cls
|
|
306
|
+
for cls in classes:
|
|
307
|
+
if not cls.is_journal_level():
|
|
308
|
+
return cls
|
|
309
|
+
return PublisherAdapter
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def adapter_class_for(profile: Any) -> type[PublisherAdapter]:
|
|
313
|
+
"""The publisher-level adapter class of a profile (no article, host or journal known)."""
|
|
314
|
+
return adapter_class(str(getattr(profile, "name", "") or ""))
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def adapter_for(downloader: Any, *, doi: str = "", host: str = "",
|
|
318
|
+
issns: Iterable[str] = ()) -> PublisherAdapter:
|
|
319
|
+
name = str(getattr(getattr(downloader, "profile", None), "name", "") or "")
|
|
320
|
+
return adapter_class(name, doi=doi, host=host, issns=issns)(downloader)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""BMJ: journals on <journal>.bmj.com (HighWire).
|
|
2
|
+
|
|
3
|
+
Without access the article page offers the article for sale ("Buy this
|
|
4
|
+
article", an offer of the shared access rule). The institution login is HighWire's "Log in via Institution", a
|
|
5
|
+
Shibboleth discovery page on the journal's own host (``/login/shibboleth``).
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
from urllib.parse import urljoin, urlparse
|
|
11
|
+
|
|
12
|
+
from ...engine.batch_common import open_page
|
|
13
|
+
from ..base import PublisherAdapter, register
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@register
|
|
17
|
+
class BMJAdapter(PublisherAdapter):
|
|
18
|
+
publisher = "bmj"
|
|
19
|
+
|
|
20
|
+
def open_institution_entry(self, page: Any, result: Any) -> bool | None:
|
|
21
|
+
"""HighWire's "Log in via Institution"; the login menu also holds
|
|
22
|
+
personal and society logins, which are never used."""
|
|
23
|
+
host = (urlparse(str(getattr(page, "url", "") or "")).hostname or "").lower()
|
|
24
|
+
if not host.endswith("bmj.com"):
|
|
25
|
+
return None
|
|
26
|
+
for control in page.locator('a[href*="/login/shibboleth"]').all():
|
|
27
|
+
target = urlparse(urljoin(str(page.url), control.get_attribute("href") or ""))
|
|
28
|
+
if target.scheme == "https" and target.hostname == host and target.path == "/login/shibboleth":
|
|
29
|
+
open_page(page, target.geturl(), timeout_ms=30_000)
|
|
30
|
+
self.d._event(result, "sso_entry_clicked", "bmj-institution-login")
|
|
31
|
+
return True
|
|
32
|
+
return False
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Copernicus Publications: open-access journals on <journal>.copernicus.org.
|
|
2
|
+
|
|
3
|
+
The PDF path is derived from the DOI
|
|
4
|
+
(``10.5194/<journal>-<volume>-<page>-<year>``).
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from ...engine.router import _append_copernicus_candidates
|
|
9
|
+
from ..base import PublisherAdapter, register
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@register
|
|
13
|
+
class CopernicusAdapter(PublisherAdapter):
|
|
14
|
+
publisher = "copernicus"
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def profile_pdf_candidates(cls, doi: str, source_url: str) -> list[str]:
|
|
18
|
+
urls: list[str] = []
|
|
19
|
+
_append_copernicus_candidates(urls, doi, source_url)
|
|
20
|
+
return urls
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Dove Medical Press: open-access journals on dovepress.com.
|
|
2
|
+
|
|
3
|
+
No sign-in: the article page links its PDF (``citation_pdf_url``,
|
|
4
|
+
``/article/download/<n>``, an address without "pdf" in it: taken as the
|
|
5
|
+
article's PDF so that it is opened when the click brings nothing in time; a
|
|
6
|
+
20 MB PDF did not arrive within the click's 5 s, 2026-11-03). Its
|
|
7
|
+
supplementary files are ``/article/supplementary_file/<n>/<name>``, where
|
|
8
|
+
``<n>`` is the number in the DOI (10.2147/JIR.S620421: 620421), often linked
|
|
9
|
+
more than once (2026-11-01).
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
from typing import Any
|
|
15
|
+
from urllib.parse import unquote, urlparse
|
|
16
|
+
|
|
17
|
+
from ..base import PublisherAdapter, SupplementLink, register
|
|
18
|
+
|
|
19
|
+
_HOSTS = frozenset({"dovepress.com", "www.dovepress.com"})
|
|
20
|
+
_NUMBER = re.compile(r"^10\.2147/[a-z]+\.s(\d+)$", re.I)
|
|
21
|
+
_SUPPLEMENT_ROWS_JS = """() => [...document.querySelectorAll('a[href*="/article/supplementary_file/"]')].map(a => ({
|
|
22
|
+
href: a.href, label: (a.innerText || '').replace(/\\s+/g, ' ').trim().slice(0, 200)}))"""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@register
|
|
26
|
+
class DovePressAdapter(PublisherAdapter):
|
|
27
|
+
publisher = "dove medical press"
|
|
28
|
+
metadata_pdf_patterns = ("https://www.dovepress.com/article/download/*",)
|
|
29
|
+
|
|
30
|
+
def supplement_links(self, page: Any, doi: str) -> list[SupplementLink] | None:
|
|
31
|
+
match = _NUMBER.match((doi or "").strip())
|
|
32
|
+
if not match:
|
|
33
|
+
return []
|
|
34
|
+
prefix = f"/article/supplementary_file/{match.group(1)}/"
|
|
35
|
+
links: list[SupplementLink] = []
|
|
36
|
+
rows = page.evaluate(_SUPPLEMENT_ROWS_JS)
|
|
37
|
+
for row in rows if isinstance(rows, list) else []:
|
|
38
|
+
target = urlparse(str(row.get("href") or "") if isinstance(row, dict) else "")
|
|
39
|
+
url = target._replace(fragment="").geturl()
|
|
40
|
+
if (target.scheme == "https" and (target.hostname or "").lower() in _HOSTS
|
|
41
|
+
and unquote(target.path).startswith(prefix) and url not in {link.url for link in links}):
|
|
42
|
+
links.append(SupplementLink(url, str(row.get("label") or "")))
|
|
43
|
+
return links
|