heor-agent-mcp 1.14.4 → 1.15.1
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/.well-known/mcp/server-card.json +92 -0
- package/dist/formatters/reviewMarkdown.d.ts +36 -0
- package/dist/formatters/reviewMarkdown.d.ts.map +1 -0
- package/dist/formatters/reviewMarkdown.js +40 -0
- package/dist/formatters/reviewMarkdown.js.map +1 -0
- package/dist/providers/direct/allOfUs.js +31 -33
- package/dist/providers/direct/allOfUs.js.map +1 -1
- package/dist/providers/direct/chembl.js +17 -19
- package/dist/providers/direct/chembl.js.map +1 -1
- package/dist/providers/direct/citeline.d.ts.map +1 -1
- package/dist/providers/direct/citeline.js +40 -39
- package/dist/providers/direct/citeline.js.map +1 -1
- package/dist/providers/direct/clinicalTrials.d.ts.map +1 -1
- package/dist/providers/direct/clinicalTrials.js +23 -25
- package/dist/providers/direct/clinicalTrials.js.map +1 -1
- package/dist/providers/direct/cochrane.d.ts.map +1 -1
- package/dist/providers/direct/cochrane.js +36 -35
- package/dist/providers/direct/cochrane.js.map +1 -1
- package/dist/providers/direct/cortellis.d.ts.map +1 -1
- package/dist/providers/direct/cortellis.js +42 -41
- package/dist/providers/direct/cortellis.js.map +1 -1
- package/dist/providers/direct/oecd.js +47 -49
- package/dist/providers/direct/oecd.js.map +1 -1
- package/dist/providers/direct/orangeBook.js +46 -48
- package/dist/providers/direct/orangeBook.js.map +1 -1
- package/dist/providers/direct/pharmapendium.d.ts.map +1 -1
- package/dist/providers/direct/pharmapendium.js +29 -28
- package/dist/providers/direct/pharmapendium.js.map +1 -1
- package/dist/providers/direct/proxyClient.js +25 -27
- package/dist/providers/direct/proxyClient.js.map +1 -1
- package/dist/providers/direct/wiley.js +36 -38
- package/dist/providers/direct/wiley.js.map +1 -1
- package/dist/providers/direct/worldBank.d.ts.map +1 -1
- package/dist/providers/direct/worldBank.js +26 -29
- package/dist/providers/direct/worldBank.js.map +1 -1
- package/dist/review/clarificationTaxonomy.d.ts +32 -0
- package/dist/review/clarificationTaxonomy.d.ts.map +1 -0
- package/dist/review/clarificationTaxonomy.js +204 -0
- package/dist/review/clarificationTaxonomy.js.map +1 -0
- package/dist/review/dossierScan.d.ts +30 -0
- package/dist/review/dossierScan.d.ts.map +1 -0
- package/dist/review/dossierScan.js +345 -0
- package/dist/review/dossierScan.js.map +1 -0
- package/dist/server.js +37 -5
- package/dist/server.js.map +1 -1
- package/dist/tools/claimsQuery.d.ts +57 -1
- package/dist/tools/claimsQuery.d.ts.map +1 -1
- package/dist/tools/claimsQuery.js +193 -151
- package/dist/tools/claimsQuery.js.map +1 -1
- package/dist/tools/htaDossierPrep.d.ts.map +1 -1
- package/dist/tools/htaDossierPrep.js +14 -0
- package/dist/tools/htaDossierPrep.js.map +1 -1
- package/dist/tools/htaReviewSimulation.d.ts +203 -0
- package/dist/tools/htaReviewSimulation.d.ts.map +1 -0
- package/dist/tools/htaReviewSimulation.js +194 -0
- package/dist/tools/htaReviewSimulation.js.map +1 -0
- package/dist/tools/itcFeasibility.d.ts.map +1 -1
- package/dist/tools/itcFeasibility.js +16 -9
- package/dist/tools/itcFeasibility.js.map +1 -1
- package/dist/tools/livingReview.d.ts +302 -0
- package/dist/tools/livingReview.d.ts.map +1 -0
- package/dist/tools/livingReview.js +363 -0
- package/dist/tools/livingReview.js.map +1 -0
- package/dist/tools/maicWorkflow.js +6 -6
- package/dist/tools/maicWorkflow.js.map +1 -1
- package/dist/tools/queryAgent.d.ts +1 -1
- package/dist/tools/queryAgent.d.ts.map +1 -1
- package/dist/tools/queryAgent.js +33 -3
- package/dist/tools/queryAgent.js.map +1 -1
- package/dist/tools/trialEnrollmentCriteria.d.ts +25 -0
- package/dist/tools/trialEnrollmentCriteria.d.ts.map +1 -0
- package/dist/tools/trialEnrollmentCriteria.js +253 -0
- package/dist/tools/trialEnrollmentCriteria.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"serverInfo": {
|
|
3
|
+
"name": "heor-agent-mcp",
|
|
4
|
+
"version": "1.15.1",
|
|
5
|
+
"description": "AI-powered Health Economics and Outcomes Research (HEOR) MCP server. 28 tools for literature search (44 data sources incl. OHE and EuroQol), risk of bias assessment (RoB 2/ROBINS-I/AMSTAR-2 with GRADE integration), cost-effectiveness modeling (Markov/PartSA with live-formula XLSX, PSA/EVPPI/scenarios, QALY + evLYG summary metrics), budget impact analysis, abstract screening, survival curve fitting, indirect comparisons (Bucher/NMA/MAIC/STC) with I²/Cochran Q heterogeneity, ITC feasibility assessment (3-assumption framework), pharmacovigilance study classification (PASS/PAES/RMP/DUS/registry per EMA GVP rev 4), EU Joint Clinical Assessment (JCA) PICO matrix analyzer (DE/FR/IT/ES/NL + UK context), pharmacovigilance signal workflow (PRR/ROR/IC/MGPS per GVP Module IX rev 2 + GVP P.III pregnancy follow-up), MAIC pipeline orchestration, HTA dossier prep (NICE/EMA/FDA/IQWiG/HAS/EU JCA/GVD) with auto-GRADE + PV plan + NICE severity modifier + health inequalities + Global Value Dossier (13 sections, 4-market subsections US/UK/EU5/JP, gvd_evidence_pack pipe interface), structured unmet need assessment (evidence.unmet_need — 4-dimension framework: disease burden/treatment landscape/QoL/economic burden; pipes into GVD Section 4 + hta_dossier), UK EQ-5D-5L value set impact estimator, neurology & cognitive outcome scale scoring (UMSARS/UPDRS/MDS-UPDRS/ADAS-Cog/MoCA/MMSE with MCID responder classification + NNIPPS/PPMI/ADNI trajectory comparison), IRB/Ethics Committee submission classifier, examples + recipe templates."
|
|
6
|
+
},
|
|
7
|
+
"authentication": {
|
|
8
|
+
"required": false,
|
|
9
|
+
"optional": {
|
|
10
|
+
"type": "bearer",
|
|
11
|
+
"envVar": "MCP_AUTH_TOKEN",
|
|
12
|
+
"description": "Optional bearer token for production hardening"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"url": "https://github.com/neptun2000/heor-agent-mcp",
|
|
17
|
+
"source": "github"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/neptun2000/heor-agent-mcp",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"tools": [
|
|
22
|
+
{ "name": "literature.search", "description": "Search 41 data sources with PRISMA audit trail and runs=3 stability deduplication." },
|
|
23
|
+
{ "name": "literature.screen", "description": "PICO-based abstract screening with study design classification (Cochrane Handbook Ch. 4)." },
|
|
24
|
+
{ "name": "evidence.network", "description": "Build treatment comparison network, assess NMA feasibility." },
|
|
25
|
+
{ "name": "evidence.indirect", "description": "Bucher method and Frequentist NMA for indirect treatment comparisons." },
|
|
26
|
+
{ "name": "evidence.population_adjusted", "description": "MAIC/STC per NICE DSU TSD 18 (summary-level data, no IPD required)." },
|
|
27
|
+
{ "name": "evidence.survival", "description": "Fit 5 parametric distributions (Exp/Weibull/Log-logistic/Log-normal/Gompertz) to KM data with AIC/BIC (NICE DSU TSD 14)." },
|
|
28
|
+
{ "name": "models.cost_effectiveness", "description": "Markov/PartSA with PSA, OWSA, CEAC, EVPI, EVPPI, scenario analysis. Outputs text/JSON/DOCX/XLSX." },
|
|
29
|
+
{ "name": "models.budget_impact", "description": "ISPOR-compliant BIA with market share uptake, population growth, treatment displacement." },
|
|
30
|
+
{ "name": "evidence.risk_of_bias", "description": "Cochrane RoB 2 (RCTs), ROBINS-I (observational), AMSTAR-2 (systematic reviews). Auto-detects instrument from study_type. Returns GRADE Risk of Bias domain summary to pass to hta_dossier_prep." },
|
|
31
|
+
{ "name": "hta.dossier", "description": "NICE STA, EMA, FDA, IQWiG, HAS, EU JCA templates with auto-GRADE evidence quality tables. Accepts rob_results from risk_of_bias for structured RoB domain." },
|
|
32
|
+
{ "name": "utils.validate_links", "description": "HTTP validation of URLs to prevent broken citation links." },
|
|
33
|
+
{ "name": "project.create", "description": "Initialize persistent project workspace at ~/.heor-agent/projects/." },
|
|
34
|
+
{ "name": "knowledge.search", "description": "Full-text search across project raw/ and wiki/." },
|
|
35
|
+
{ "name": "knowledge.read", "description": "Read files from a project knowledge base." },
|
|
36
|
+
{ "name": "knowledge.write", "description": "Write to project wiki/ (Obsidian-compatible, YAML frontmatter + wikilinks)." },
|
|
37
|
+
{ "name": "hta.utility", "description": "EQ-5D value set reference (UK 3L/England 5L/new UK 5L 2026/DSU mapping) and NICE 5L transition impact estimator. Cites Biz, Hernández Alava, Wailoo (2026) Value in Health." },
|
|
38
|
+
{ "name": "evidence.itc", "description": "Assess ITC feasibility via the 3-assumption framework (exchangeability, homogeneity, consistency). Recommends Bucher/NMA/MAIC/STC/ML-NMR or infeasible. Cites Cope 2014, NICE DSU TSD 18, Signorovitch 2023, Cochrane Ch 10-11." },
|
|
39
|
+
{ "name": "examples", "description": "Pre-filled JSON inputs for heavy-schema tools + maic_workflow_recipe (multi-step prompt template for ChatGPT users)." },
|
|
40
|
+
{ "name": "workflow.maic", "description": "One-shot MAIC pipeline orchestrator: ITC feasibility + parallel literature_search (broad + per-trial) + screen_abstracts + risk_of_bias + evidence_network. Returns a 9-section structured report. Stops short of MAIC/Bucher itself (those need IPD)." },
|
|
41
|
+
{ "name": "pv.classify", "description": "Classify a planned study into its EMA pharmacovigilance regulatory category (PASS imposed/voluntary, PAES, RMP Annex 4, DUS, registry, pregnancy registry, spontaneous reporting, ICH E2E plan). Maps to GVP module + ENCePP study-category label (NOT a registered protocol ID — consult ENCePP Code of Conduct + EUPAS register for templates) + RMP/FDA implications + advisory warnings for edge cases (CMA SOBs, contradictory inputs). Pass result to hta_dossier for the PV Plan section." },
|
|
42
|
+
{ "name": "jca.pico_scope", "description": "Produce the canonical EU Joint Clinical Assessment (JCA) PICO matrix for a drug-indication pair across selected EU jurisdictions (DE/FR/IT/ES/NL + UK context). Returns consolidated PICO list per Reg. 2021/2282, country-specific comparator universes, outcome instrument preferences, population subgroups, and a heterogeneity warning. Pipe pico_matrix.picos into hta_dossier for a multi-PICO JCA dossier." },
|
|
43
|
+
{ "name": "pv.signal_workflow", "description": "Compute disproportionality statistics (PRR/ROR/IC/MGPS) on drug-AE case counts and decide a signal verdict per EMA GVP Module IX rev 2. Returns workflow recommendations + canonical RMP signal-section text + optional GVP P.III pregnancy follow-up. Pairs with pv.classify." },
|
|
44
|
+
{ "name": "evidence.clinical_scale", "description": "Score neurology & cognitive outcome scales: UMSARS (MSA/orphan), UPDRS + MDS-UPDRS (Parkinson's), ADAS-Cog, MoCA, MMSE (Alzheimer's/cognitive). Returns total + subscale scores, MCID-based responder classification (Krismer 2017/Horváth 2015/Andrews 2019), and trajectory vs NNIPPS/PPMI/ADNI reference cohorts. Integrates with jca_pico_scope for neurology_msa (orphan Phase 2 2028)/neurology_pd/neurology_ad indication categories." },
|
|
45
|
+
{ "name": "irb.review", "description": "Classify planned study into IRB / Ethics Committee review tier (exempt/expedited/full board) per 45 CFR 46 (US Common Rule 2018) + EU CTR 536/2014. Returns Common Rule category, EU CTR pathway, Subpart B/C/D obligations, GDPR Art. 9 / HIPAA DMP, SAE timelines, ICF tier, COI framework, and ready-to-paste cover letter." },
|
|
46
|
+
{ "name": "evidence.unmet_need", "description": "Generate a structured 4-dimension unmet need section (disease burden / treatment landscape / QoL impact / economic burden) for HTA dossiers. Consume-only: pass cited facts only. For regulatory status / approved indications / age restrictions, look up via regulatory.status_check first. Pipes unmet_need_summary into hta_dossier (NICE Section B / GVD Section 4). Design log #23." },
|
|
47
|
+
{ "name": "regulatory.status_check", "description": "Primary-source regulatory lookup: drug + region + optional indication → current FDA (OpenFDA) / EMA EPI label state with approved indications, age range, weight constraints, approval dates, source URLs, fetch timestamp. Refuses to assert 'not_approved' on database absence — returns 'unknown' instead. 24h cache + force_refresh. Closes the LLM-training-stale-on-regulatory-data failure class. Design log #25." },
|
|
48
|
+
{ "name": "trial.enrollment_criteria", "description": "Fetch enrollment/eligibility criteria for a clinical trial from ClinicalTrials.gov by NCT number. Returns structured inclusion/exclusion criteria, primary outcomes, study design, and population description. Use BEFORE building any trial-vs-real-world-population gap analysis." }
|
|
49
|
+
],
|
|
50
|
+
"keywords": [
|
|
51
|
+
"healthcare",
|
|
52
|
+
"heor",
|
|
53
|
+
"health-economics",
|
|
54
|
+
"hta",
|
|
55
|
+
"pharmaceutical",
|
|
56
|
+
"market-access",
|
|
57
|
+
"nice",
|
|
58
|
+
"cadth",
|
|
59
|
+
"icer",
|
|
60
|
+
"pbac",
|
|
61
|
+
"clinical-trials",
|
|
62
|
+
"pubmed",
|
|
63
|
+
"cost-effectiveness",
|
|
64
|
+
"markov",
|
|
65
|
+
"nma",
|
|
66
|
+
"maic",
|
|
67
|
+
"eq-5d",
|
|
68
|
+
"qaly",
|
|
69
|
+
"evlyg",
|
|
70
|
+
"utility-value-set",
|
|
71
|
+
"itc-feasibility",
|
|
72
|
+
"heterogeneity",
|
|
73
|
+
"cms-ira",
|
|
74
|
+
"pharmacovigilance",
|
|
75
|
+
"pass",
|
|
76
|
+
"encepp",
|
|
77
|
+
"gvp",
|
|
78
|
+
"rmp",
|
|
79
|
+
"jca",
|
|
80
|
+
"eu-hta-regulation",
|
|
81
|
+
"pico-scope",
|
|
82
|
+
"joint-clinical-assessment",
|
|
83
|
+
"signal-detection",
|
|
84
|
+
"prr",
|
|
85
|
+
"ror",
|
|
86
|
+
"bcpnn",
|
|
87
|
+
"mgps",
|
|
88
|
+
"ebgm",
|
|
89
|
+
"eudravigilance",
|
|
90
|
+
"evdas"
|
|
91
|
+
]
|
|
92
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown renderer for hta.review_simulation (design log #38).
|
|
3
|
+
* Self-contained render types so this module has no dependency on the tool
|
|
4
|
+
* (avoids an import cycle). The tool's ReviewQuestion is structurally a
|
|
5
|
+
* superset of RenderQuestion and passes directly.
|
|
6
|
+
*/
|
|
7
|
+
export type RenderSeverity = "critical" | "standard" | "minor";
|
|
8
|
+
export interface RenderQuestion {
|
|
9
|
+
category_label: string;
|
|
10
|
+
question: string;
|
|
11
|
+
rationale: string;
|
|
12
|
+
severity: RenderSeverity;
|
|
13
|
+
what_they_look_for: string;
|
|
14
|
+
suggested_response: string;
|
|
15
|
+
locator: string;
|
|
16
|
+
precedent?: {
|
|
17
|
+
id: string;
|
|
18
|
+
title: string;
|
|
19
|
+
url: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface RenderSummary {
|
|
23
|
+
critical: number;
|
|
24
|
+
standard: number;
|
|
25
|
+
minor: number;
|
|
26
|
+
biggest_exposure: string;
|
|
27
|
+
total: number;
|
|
28
|
+
shown: number;
|
|
29
|
+
}
|
|
30
|
+
export interface RenderMeta {
|
|
31
|
+
drug: string;
|
|
32
|
+
indication: string;
|
|
33
|
+
body_label: string;
|
|
34
|
+
}
|
|
35
|
+
export declare function renderReviewSimulation(meta: RenderMeta, questions: RenderQuestion[], summary: RenderSummary): string;
|
|
36
|
+
//# sourceMappingURL=reviewMarkdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewMarkdown.d.ts","sourceRoot":"","sources":["../../src/formatters/reviewMarkdown.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,cAAc,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACxD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAQD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,cAAc,EAAE,EAC3B,OAAO,EAAE,aAAa,GACrB,MAAM,CA0CR"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const GROUPS = [
|
|
2
|
+
["critical", "Critical", "C"],
|
|
3
|
+
["standard", "Standard", "S"],
|
|
4
|
+
["minor", "Minor", "M"],
|
|
5
|
+
];
|
|
6
|
+
export function renderReviewSimulation(meta, questions, summary) {
|
|
7
|
+
const lines = [];
|
|
8
|
+
lines.push(`## HTA Review Simulation — ${meta.drug} (${meta.indication})`);
|
|
9
|
+
lines.push("");
|
|
10
|
+
lines.push(`**Body:** ${meta.body_label} · **Anticipated questions:** ${summary.total} · ` +
|
|
11
|
+
`Critical ${summary.critical} · Standard ${summary.standard} · Minor ${summary.minor}`);
|
|
12
|
+
lines.push(`**Biggest exposure:** ${summary.biggest_exposure}`);
|
|
13
|
+
if (summary.shown < summary.total) {
|
|
14
|
+
lines.push("");
|
|
15
|
+
lines.push(`_Showing the top ${summary.shown} of ${summary.total} anticipated questions ` +
|
|
16
|
+
`(max_questions). Raise max_questions to see the rest._`);
|
|
17
|
+
}
|
|
18
|
+
lines.push("");
|
|
19
|
+
lines.push(`> ⚠️ **Anticipated** questions — a structured prior over what ${meta.body_label} is ` +
|
|
20
|
+
`likely to ask, not a record of questions historically asked.`);
|
|
21
|
+
for (const [sev, heading, prefix] of GROUPS) {
|
|
22
|
+
const qs = questions.filter((q) => q.severity === sev);
|
|
23
|
+
if (qs.length === 0)
|
|
24
|
+
continue;
|
|
25
|
+
lines.push("");
|
|
26
|
+
lines.push(`### ${heading}`);
|
|
27
|
+
qs.forEach((q, i) => {
|
|
28
|
+
lines.push("");
|
|
29
|
+
lines.push(`**${prefix}${i + 1} · ${q.category_label}.** ${q.question}`);
|
|
30
|
+
lines.push(` ↳ *Why:* ${q.rationale}`);
|
|
31
|
+
lines.push(` ↳ *What they look for:* ${q.what_they_look_for}`);
|
|
32
|
+
lines.push(` ↳ *Suggested response:* ${q.suggested_response}`);
|
|
33
|
+
if (q.precedent) {
|
|
34
|
+
lines.push(` ↳ *Related precedent:* [${q.precedent.id} — ${q.precedent.title}](${q.precedent.url})`);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return lines.join("\n").trim();
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=reviewMarkdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewMarkdown.js","sourceRoot":"","sources":["../../src/formatters/reviewMarkdown.ts"],"names":[],"mappings":"AAmCA,MAAM,MAAM,GAA4C;IACtD,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC;IAC7B,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC;IAC7B,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC;CACxB,CAAC;AAEF,MAAM,UAAU,sBAAsB,CACpC,IAAgB,EAChB,SAA2B,EAC3B,OAAsB;IAEtB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,8BAA8B,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;IAC3E,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CACR,aAAa,IAAI,CAAC,UAAU,mCAAmC,OAAO,CAAC,KAAK,OAAO;QACjF,YAAY,OAAO,CAAC,QAAQ,eAAe,OAAO,CAAC,QAAQ,YAAY,OAAO,CAAC,KAAK,EAAE,CACzF,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,yBAAyB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAChE,IAAI,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CACR,oBAAoB,OAAO,CAAC,KAAK,OAAO,OAAO,CAAC,KAAK,yBAAyB;YAC5E,wDAAwD,CAC3D,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CACR,iEAAiE,IAAI,CAAC,UAAU,MAAM;QACpF,8DAA8D,CACjE,CAAC;IAEF,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QAC5C,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC;QACvD,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAC9B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC;QAC7B,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,cAAc,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACzE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YACxC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC;YAChE,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC;YAChE,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CACR,6BAA6B,CAAC,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC,CAAC,SAAS,CAAC,GAAG,GAAG,CAC1F,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AACjC,CAAC"}
|
|
@@ -1,38 +1,36 @@
|
|
|
1
1
|
const BASE = "https://databrowser.researchallofus.org/api/v1/databrowser";
|
|
2
2
|
export async function fetchAllOfUs(query, maxResults) {
|
|
3
|
-
try
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const items = data.items ?? [];
|
|
13
|
-
return items.slice(0, maxResults).map((item) => ({
|
|
14
|
-
id: `aou_${item.conceptId}`,
|
|
15
|
-
source: "all_of_us",
|
|
16
|
-
title: `${item.conceptName} (${item.domainId})`,
|
|
17
|
-
authors: ["NIH All of Us Research Program"],
|
|
18
|
-
date: new Date().getFullYear().toString(),
|
|
19
|
-
study_type: "registry",
|
|
20
|
-
abstract: [
|
|
21
|
-
`Concept: ${item.conceptName}`,
|
|
22
|
-
`Domain: ${item.domainId}`,
|
|
23
|
-
`Vocabulary: ${item.vocabularyId} (${item.conceptCode})`,
|
|
24
|
-
`Participant count: ${item.countValue.toLocaleString()}`,
|
|
25
|
-
item.prevalence > 0
|
|
26
|
-
? `Prevalence: ${(item.prevalence * 100).toFixed(2)}%`
|
|
27
|
-
: null,
|
|
28
|
-
]
|
|
29
|
-
.filter(Boolean)
|
|
30
|
-
.join(" | "),
|
|
31
|
-
url: `https://databrowser.researchallofus.org/survey/${item.conceptId}`,
|
|
32
|
-
}));
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
return [];
|
|
3
|
+
// No try/catch — let errors propagate so the dispatcher records status:"failed".
|
|
4
|
+
const url = `${BASE}/search?query=${encodeURIComponent(query)}&limit=${maxResults}`;
|
|
5
|
+
const res = await fetch(url, {
|
|
6
|
+
headers: { Accept: "application/json" },
|
|
7
|
+
signal: AbortSignal.timeout(15_000),
|
|
8
|
+
});
|
|
9
|
+
if (!res.ok) {
|
|
10
|
+
const body = await res.text().catch(() => "");
|
|
11
|
+
throw new Error(`[AllOfUs] API ${res.status}: ${body.slice(0, 200)}`);
|
|
36
12
|
}
|
|
13
|
+
const data = (await res.json());
|
|
14
|
+
const items = data.items ?? [];
|
|
15
|
+
return items.slice(0, maxResults).map((item) => ({
|
|
16
|
+
id: `aou_${item.conceptId}`,
|
|
17
|
+
source: "all_of_us",
|
|
18
|
+
title: `${item.conceptName} (${item.domainId})`,
|
|
19
|
+
authors: ["NIH All of Us Research Program"],
|
|
20
|
+
date: new Date().getFullYear().toString(),
|
|
21
|
+
study_type: "registry",
|
|
22
|
+
abstract: [
|
|
23
|
+
`Concept: ${item.conceptName}`,
|
|
24
|
+
`Domain: ${item.domainId}`,
|
|
25
|
+
`Vocabulary: ${item.vocabularyId} (${item.conceptCode})`,
|
|
26
|
+
`Participant count: ${item.countValue.toLocaleString()}`,
|
|
27
|
+
item.prevalence > 0
|
|
28
|
+
? `Prevalence: ${(item.prevalence * 100).toFixed(2)}%`
|
|
29
|
+
: null,
|
|
30
|
+
]
|
|
31
|
+
.filter(Boolean)
|
|
32
|
+
.join(" | "),
|
|
33
|
+
url: `https://databrowser.researchallofus.org/survey/${item.conceptId}`,
|
|
34
|
+
}));
|
|
37
35
|
}
|
|
38
36
|
//# sourceMappingURL=allOfUs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"allOfUs.js","sourceRoot":"","sources":["../../../src/providers/direct/allOfUs.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAAG,4DAA4D,CAAC;AAiB1E,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAa,EACb,UAAkB;IAElB,
|
|
1
|
+
{"version":3,"file":"allOfUs.js","sourceRoot":"","sources":["../../../src/providers/direct/allOfUs.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAAG,4DAA4D,CAAC;AAiB1E,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAa,EACb,UAAkB;IAElB,iFAAiF;IACjF,MAAM,GAAG,GAAG,GAAG,IAAI,iBAAiB,kBAAkB,CAAC,KAAK,CAAC,UAAU,UAAU,EAAE,CAAC;IACpF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;QACvC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAsB,CAAC;IACrD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAE/B,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC/C,EAAE,EAAE,OAAO,IAAI,CAAC,SAAS,EAAE;QAC3B,MAAM,EAAE,WAAoB;QAC5B,KAAK,EAAE,GAAG,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,QAAQ,GAAG;QAC/C,OAAO,EAAE,CAAC,gCAAgC,CAAC;QAC3C,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;QACzC,UAAU,EAAE,UAAU;QACtB,QAAQ,EAAE;YACR,YAAY,IAAI,CAAC,WAAW,EAAE;YAC9B,WAAW,IAAI,CAAC,QAAQ,EAAE;YAC1B,eAAe,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,WAAW,GAAG;YACxD,sBAAsB,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE;YACxD,IAAI,CAAC,UAAU,GAAG,CAAC;gBACjB,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;gBACtD,CAAC,CAAC,IAAI;SACT;aACE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,KAAK,CAAC;QACd,GAAG,EAAE,kDAAkD,IAAI,CAAC,SAAS,EAAE;KACxE,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
const BASE = "https://www.ebi.ac.uk/chembl/api/data";
|
|
2
2
|
export async function fetchChembl(query, maxResults) {
|
|
3
|
-
try
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return (data.molecules ?? []).map((mol) => ({
|
|
10
|
-
id: `chembl_${mol.molecule_chembl_id}`,
|
|
11
|
-
source: "chembl",
|
|
12
|
-
title: mol.pref_name ?? mol.molecule_chembl_id,
|
|
13
|
-
authors: [],
|
|
14
|
-
date: mol.first_approval ? `${mol.first_approval}` : "",
|
|
15
|
-
study_type: "compound_data",
|
|
16
|
-
abstract: `${mol.molecule_type ?? "Molecule"} — MW: ${mol.molecule_properties?.full_mwt ?? "unknown"}`,
|
|
17
|
-
url: `https://www.ebi.ac.uk/chembl/compound_report_card/${mol.molecule_chembl_id}/`,
|
|
18
|
-
}));
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
return [];
|
|
3
|
+
// No try/catch — let errors propagate so the dispatcher records status:"failed".
|
|
4
|
+
const url = `${BASE}/molecule.json?pref_name__icontains=${encodeURIComponent(query)}&limit=${maxResults}`;
|
|
5
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(15_000) });
|
|
6
|
+
if (!res.ok) {
|
|
7
|
+
const body = await res.text().catch(() => "");
|
|
8
|
+
throw new Error(`[ChEMBL] API ${res.status}: ${body.slice(0, 200)}`);
|
|
22
9
|
}
|
|
10
|
+
const data = (await res.json());
|
|
11
|
+
return (data.molecules ?? []).map((mol) => ({
|
|
12
|
+
id: `chembl_${mol.molecule_chembl_id}`,
|
|
13
|
+
source: "chembl",
|
|
14
|
+
title: mol.pref_name ?? mol.molecule_chembl_id,
|
|
15
|
+
authors: [],
|
|
16
|
+
date: mol.first_approval ? `${mol.first_approval}` : "",
|
|
17
|
+
study_type: "compound_data",
|
|
18
|
+
abstract: `${mol.molecule_type ?? "Molecule"} — MW: ${mol.molecule_properties?.full_mwt ?? "unknown"}`,
|
|
19
|
+
url: `https://www.ebi.ac.uk/chembl/compound_report_card/${mol.molecule_chembl_id}/`,
|
|
20
|
+
}));
|
|
23
21
|
}
|
|
24
22
|
//# sourceMappingURL=chembl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chembl.js","sourceRoot":"","sources":["../../../src/providers/direct/chembl.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAAG,uCAAuC,CAAC;AAUrD,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAa,EACb,UAAkB;IAElB,
|
|
1
|
+
{"version":3,"file":"chembl.js","sourceRoot":"","sources":["../../../src/providers/direct/chembl.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAAG,uCAAuC,CAAC;AAUrD,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAa,EACb,UAAkB;IAElB,iFAAiF;IACjF,MAAM,GAAG,GAAG,GAAG,IAAI,uCAAuC,kBAAkB,CAAC,KAAK,CAAC,UAAU,UAAU,EAAE,CAAC;IAC1G,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACtE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,gBAAgB,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAoC,CAAC;IACnE,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC1C,EAAE,EAAE,UAAU,GAAG,CAAC,kBAAkB,EAAE;QACtC,MAAM,EAAE,QAAiB;QACzB,KAAK,EAAE,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,kBAAkB;QAC9C,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE;QACvD,UAAU,EAAE,eAAe;QAC3B,QAAQ,EAAE,GAAG,GAAG,CAAC,aAAa,IAAI,UAAU,UAAU,GAAG,CAAC,mBAAmB,EAAE,QAAQ,IAAI,SAAS,EAAE;QACtG,GAAG,EAAE,qDAAqD,GAAG,CAAC,kBAAkB,GAAG;KACpF,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"citeline.d.ts","sourceRoot":"","sources":["../../../src/providers/direct/citeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAsBpD,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"citeline.d.ts","sourceRoot":"","sources":["../../../src/providers/direct/citeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAsBpD,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA+C7B"}
|
|
@@ -2,50 +2,51 @@ import { fetchViaProxy, getProxyUrl } from "./proxyClient.js";
|
|
|
2
2
|
// Citeline TrialTrove API (Informa/Citeline)
|
|
3
3
|
const BASE = "https://api.citeline.com/trialtrove/v1/trials";
|
|
4
4
|
export async function fetchCiteline(query, maxResults) {
|
|
5
|
-
// Try institutional/enterprise proxy first if configured
|
|
6
5
|
if (getProxyUrl()) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
try {
|
|
7
|
+
const proxyResults = await fetchViaProxy("citeline", query, maxResults);
|
|
8
|
+
if (proxyResults.length > 0)
|
|
9
|
+
return proxyResults;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// Proxy unreachable — fall through to direct API when key is set.
|
|
13
|
+
}
|
|
10
14
|
}
|
|
11
|
-
// Fall back to direct API call if key is set
|
|
12
15
|
const apiKey = process.env.CITELINE_API_KEY;
|
|
13
16
|
if (!apiKey)
|
|
14
17
|
return [];
|
|
15
|
-
try
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const trials = data.trials ?? [];
|
|
28
|
-
return trials.slice(0, maxResults).map((t, i) => ({
|
|
29
|
-
id: `citeline_${t.trialId ?? i}`,
|
|
30
|
-
source: "citeline",
|
|
31
|
-
title: t.title ?? "Untitled trial",
|
|
32
|
-
authors: t.sponsors ?? [],
|
|
33
|
-
date: t.startDate ?? "",
|
|
34
|
-
study_type: "rct",
|
|
35
|
-
abstract: [
|
|
36
|
-
`Phase: ${t.phase ?? "N/A"}`,
|
|
37
|
-
`Status: ${t.status ?? "N/A"}`,
|
|
38
|
-
`Indication: ${t.indication ?? "N/A"}`,
|
|
39
|
-
`Therapeutic area: ${t.therapeuticArea ?? "N/A"}`,
|
|
40
|
-
t.primaryOutcome ? `Primary outcome: ${t.primaryOutcome}` : null,
|
|
41
|
-
]
|
|
42
|
-
.filter(Boolean)
|
|
43
|
-
.join(" | "),
|
|
44
|
-
url: `https://citeline.informa.com/trial/${t.trialId ?? ""}`,
|
|
45
|
-
}));
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
return [];
|
|
18
|
+
// No try/catch on direct API — let errors propagate so the dispatcher records status:"failed".
|
|
19
|
+
const url = `${BASE}?q=${encodeURIComponent(query)}&limit=${maxResults}`;
|
|
20
|
+
const res = await fetch(url, {
|
|
21
|
+
headers: {
|
|
22
|
+
Authorization: `Bearer ${apiKey}`,
|
|
23
|
+
Accept: "application/json",
|
|
24
|
+
},
|
|
25
|
+
signal: AbortSignal.timeout(15_000),
|
|
26
|
+
});
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
const body = await res.text().catch(() => "");
|
|
29
|
+
throw new Error(`[Citeline] API ${res.status}: ${body.slice(0, 200)}`);
|
|
49
30
|
}
|
|
31
|
+
const data = (await res.json());
|
|
32
|
+
const trials = data.trials ?? [];
|
|
33
|
+
return trials.slice(0, maxResults).map((t, i) => ({
|
|
34
|
+
id: `citeline_${t.trialId ?? i}`,
|
|
35
|
+
source: "citeline",
|
|
36
|
+
title: t.title ?? "Untitled trial",
|
|
37
|
+
authors: t.sponsors ?? [],
|
|
38
|
+
date: t.startDate ?? "",
|
|
39
|
+
study_type: "rct",
|
|
40
|
+
abstract: [
|
|
41
|
+
`Phase: ${t.phase ?? "N/A"}`,
|
|
42
|
+
`Status: ${t.status ?? "N/A"}`,
|
|
43
|
+
`Indication: ${t.indication ?? "N/A"}`,
|
|
44
|
+
`Therapeutic area: ${t.therapeuticArea ?? "N/A"}`,
|
|
45
|
+
t.primaryOutcome ? `Primary outcome: ${t.primaryOutcome}` : null,
|
|
46
|
+
]
|
|
47
|
+
.filter(Boolean)
|
|
48
|
+
.join(" | "),
|
|
49
|
+
url: `https://citeline.informa.com/trial/${t.trialId ?? ""}`,
|
|
50
|
+
}));
|
|
50
51
|
}
|
|
51
52
|
//# sourceMappingURL=citeline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"citeline.js","sourceRoot":"","sources":["../../../src/providers/direct/citeline.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE9D,6CAA6C;AAC7C,MAAM,IAAI,GAAG,+CAA+C,CAAC;AAkB7D,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAa,EACb,UAAkB;IAElB,
|
|
1
|
+
{"version":3,"file":"citeline.js","sourceRoot":"","sources":["../../../src/providers/direct/citeline.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE9D,6CAA6C;AAC7C,MAAM,IAAI,GAAG,+CAA+C,CAAC;AAkB7D,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAa,EACb,UAAkB;IAElB,IAAI,WAAW,EAAE,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;YACxE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,YAAY,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;QACpE,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAEvB,+FAA+F;IAC/F,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,kBAAkB,CAAC,KAAK,CAAC,UAAU,UAAU,EAAE,CAAC;IACzE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,MAAM,EAAE;YACjC,MAAM,EAAE,kBAAkB;SAC3B;QACD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAqB,CAAC;IACpD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;IAEjC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAChD,EAAE,EAAE,YAAY,CAAC,CAAC,OAAO,IAAI,CAAC,EAAE;QAChC,MAAM,EAAE,UAAmB;QAC3B,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,gBAAgB;QAClC,OAAO,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE;QACzB,IAAI,EAAE,CAAC,CAAC,SAAS,IAAI,EAAE;QACvB,UAAU,EAAE,KAAK;QACjB,QAAQ,EAAE;YACR,UAAU,CAAC,CAAC,KAAK,IAAI,KAAK,EAAE;YAC5B,WAAW,CAAC,CAAC,MAAM,IAAI,KAAK,EAAE;YAC9B,eAAe,CAAC,CAAC,UAAU,IAAI,KAAK,EAAE;YACtC,qBAAqB,CAAC,CAAC,eAAe,IAAI,KAAK,EAAE;YACjD,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,IAAI;SACjE;aACE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,KAAK,CAAC;QACd,GAAG,EAAE,sCAAsC,CAAC,CAAC,OAAO,IAAI,EAAE,EAAE;KAC7D,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clinicalTrials.d.ts","sourceRoot":"","sources":["../../../src/providers/direct/clinicalTrials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAkBpD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"clinicalTrials.d.ts","sourceRoot":"","sources":["../../../src/providers/direct/clinicalTrials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAkBpD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA6B7B"}
|
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
const BASE = "https://clinicaltrials.gov/api/v2/studies";
|
|
2
2
|
export async function fetchClinicalTrials(query, maxResults) {
|
|
3
|
-
try
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return (data.studies ?? []).map((study) => {
|
|
10
|
-
const id = study.protocolSection.identificationModule;
|
|
11
|
-
const desc = study.protocolSection.descriptionModule;
|
|
12
|
-
const contacts = study.protocolSection.contactsLocationsModule;
|
|
13
|
-
return {
|
|
14
|
-
id: `ct_${id.nctId}`,
|
|
15
|
-
source: "clinicaltrials",
|
|
16
|
-
title: id.briefTitle,
|
|
17
|
-
authors: contacts?.overallOfficials?.map((o) => o.name) ?? [],
|
|
18
|
-
date: study.protocolSection.statusModule.startDateStruct?.date ?? "",
|
|
19
|
-
study_type: study.protocolSection.designModule?.studyType?.toLowerCase() ??
|
|
20
|
-
"unknown",
|
|
21
|
-
abstract: desc?.briefSummary ?? "",
|
|
22
|
-
url: `https://clinicaltrials.gov/study/${id.nctId}`,
|
|
23
|
-
};
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
return [];
|
|
3
|
+
// No try/catch — let errors propagate so the dispatcher records status:"failed".
|
|
4
|
+
const url = `${BASE}?query.term=${encodeURIComponent(query)}&pageSize=${maxResults}&format=json`;
|
|
5
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(15_000) });
|
|
6
|
+
if (!res.ok) {
|
|
7
|
+
const body = await res.text().catch(() => "");
|
|
8
|
+
throw new Error(`[ClinicalTrials.gov] API ${res.status}: ${body.slice(0, 200)}`);
|
|
28
9
|
}
|
|
10
|
+
const data = (await res.json());
|
|
11
|
+
return (data.studies ?? []).map((study) => {
|
|
12
|
+
const id = study.protocolSection.identificationModule;
|
|
13
|
+
const desc = study.protocolSection.descriptionModule;
|
|
14
|
+
const contacts = study.protocolSection.contactsLocationsModule;
|
|
15
|
+
return {
|
|
16
|
+
id: `ct_${id.nctId}`,
|
|
17
|
+
source: "clinicaltrials",
|
|
18
|
+
title: id.briefTitle,
|
|
19
|
+
authors: contacts?.overallOfficials?.map((o) => o.name) ?? [],
|
|
20
|
+
date: study.protocolSection.statusModule.startDateStruct?.date ?? "",
|
|
21
|
+
study_type: study.protocolSection.designModule?.studyType?.toLowerCase() ??
|
|
22
|
+
"unknown",
|
|
23
|
+
abstract: desc?.briefSummary ?? "",
|
|
24
|
+
url: `https://clinicaltrials.gov/study/${id.nctId}`,
|
|
25
|
+
};
|
|
26
|
+
});
|
|
29
27
|
}
|
|
30
28
|
//# sourceMappingURL=clinicalTrials.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clinicalTrials.js","sourceRoot":"","sources":["../../../src/providers/direct/clinicalTrials.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAAG,2CAA2C,CAAC;AAgBzD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAa,EACb,UAAkB;IAElB,
|
|
1
|
+
{"version":3,"file":"clinicalTrials.js","sourceRoot":"","sources":["../../../src/providers/direct/clinicalTrials.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAAG,2CAA2C,CAAC;AAgBzD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAa,EACb,UAAkB;IAElB,iFAAiF;IACjF,MAAM,GAAG,GAAG,GAAG,IAAI,eAAe,kBAAkB,CAAC,KAAK,CAAC,aAAa,UAAU,cAAc,CAAC;IACjG,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACtE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,4BAA4B,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAChE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA2B,CAAC;IAC1D,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxC,MAAM,EAAE,GAAG,KAAK,CAAC,eAAe,CAAC,oBAAoB,CAAC;QACtD,MAAM,IAAI,GAAG,KAAK,CAAC,eAAe,CAAC,iBAAiB,CAAC;QACrD,MAAM,QAAQ,GAAG,KAAK,CAAC,eAAe,CAAC,uBAAuB,CAAC;QAC/D,OAAO;YACL,EAAE,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE;YACpB,MAAM,EAAE,gBAAyB;YACjC,KAAK,EAAE,EAAE,CAAC,UAAU;YACpB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE;YAC7D,IAAI,EAAE,KAAK,CAAC,eAAe,CAAC,YAAY,CAAC,eAAe,EAAE,IAAI,IAAI,EAAE;YACpE,UAAU,EACR,KAAK,CAAC,eAAe,CAAC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE;gBAC5D,SAAS;YACX,QAAQ,EAAE,IAAI,EAAE,YAAY,IAAI,EAAE;YAClC,GAAG,EAAE,oCAAoC,EAAE,CAAC,KAAK,EAAE;SACpD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cochrane.d.ts","sourceRoot":"","sources":["../../../src/providers/direct/cochrane.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmBpD,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"cochrane.d.ts","sourceRoot":"","sources":["../../../src/providers/direct/cochrane.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmBpD,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA2C7B"}
|
|
@@ -2,46 +2,47 @@ import { fetchViaProxy, getProxyUrl } from "./proxyClient.js";
|
|
|
2
2
|
// Wiley Online Library API — Cochrane Library is published by Wiley
|
|
3
3
|
const BASE = "https://api.wiley.com/onlinelibrary/tdm/v1/articles";
|
|
4
4
|
export async function fetchCochrane(query, maxResults) {
|
|
5
|
-
// Try institutional/enterprise proxy first if configured
|
|
6
5
|
if (getProxyUrl()) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
try {
|
|
7
|
+
const proxyResults = await fetchViaProxy("cochrane", query, maxResults);
|
|
8
|
+
if (proxyResults.length > 0)
|
|
9
|
+
return proxyResults;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// Proxy unreachable — fall through to direct API when key is set.
|
|
13
|
+
}
|
|
10
14
|
}
|
|
11
|
-
// Fall back to direct API call if key is set
|
|
12
15
|
const apiKey = process.env.COCHRANE_API_KEY;
|
|
13
16
|
if (!apiKey)
|
|
14
17
|
return [];
|
|
15
|
-
try
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const items = data.items ?? [];
|
|
28
|
-
return items.slice(0, maxResults).map((item, i) => ({
|
|
29
|
-
id: `cochrane_${item.doi ?? i}`,
|
|
30
|
-
source: "cochrane",
|
|
31
|
-
title: item.title ?? "Untitled Cochrane Review",
|
|
32
|
-
authors: item.authors ?? [],
|
|
33
|
-
date: item.publicationDate ?? "",
|
|
34
|
-
study_type: item.reviewType?.toLowerCase().includes("meta")
|
|
35
|
-
? "meta_analysis"
|
|
36
|
-
: "review",
|
|
37
|
-
abstract: item.abstract ?? "",
|
|
38
|
-
url: item.doi
|
|
39
|
-
? `https://doi.org/${item.doi}`
|
|
40
|
-
: "https://www.cochranelibrary.com/",
|
|
41
|
-
}));
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
return [];
|
|
18
|
+
// No try/catch on direct API — let errors propagate so the dispatcher records status:"failed".
|
|
19
|
+
const url = `${BASE}?q=${encodeURIComponent(query)}&rows=${maxResults}&filter=publication:cochrane`;
|
|
20
|
+
const res = await fetch(url, {
|
|
21
|
+
headers: {
|
|
22
|
+
"Wiley-TDM-Client-Token": apiKey,
|
|
23
|
+
Accept: "application/json",
|
|
24
|
+
},
|
|
25
|
+
signal: AbortSignal.timeout(15_000),
|
|
26
|
+
});
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
const body = await res.text().catch(() => "");
|
|
29
|
+
throw new Error(`[Cochrane] API ${res.status}: ${body.slice(0, 200)}`);
|
|
45
30
|
}
|
|
31
|
+
const data = (await res.json());
|
|
32
|
+
const items = data.items ?? [];
|
|
33
|
+
return items.slice(0, maxResults).map((item, i) => ({
|
|
34
|
+
id: `cochrane_${item.doi ?? i}`,
|
|
35
|
+
source: "cochrane",
|
|
36
|
+
title: item.title ?? "Untitled Cochrane Review",
|
|
37
|
+
authors: item.authors ?? [],
|
|
38
|
+
date: item.publicationDate ?? "",
|
|
39
|
+
study_type: item.reviewType?.toLowerCase().includes("meta")
|
|
40
|
+
? "meta_analysis"
|
|
41
|
+
: "review",
|
|
42
|
+
abstract: item.abstract ?? "",
|
|
43
|
+
url: item.doi
|
|
44
|
+
? `https://doi.org/${item.doi}`
|
|
45
|
+
: "https://www.cochranelibrary.com/",
|
|
46
|
+
}));
|
|
46
47
|
}
|
|
47
48
|
//# sourceMappingURL=cochrane.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cochrane.js","sourceRoot":"","sources":["../../../src/providers/direct/cochrane.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE9D,oEAAoE;AACpE,MAAM,IAAI,GAAG,qDAAqD,CAAC;AAenE,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAa,EACb,UAAkB;IAElB,
|
|
1
|
+
{"version":3,"file":"cochrane.js","sourceRoot":"","sources":["../../../src/providers/direct/cochrane.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE9D,oEAAoE;AACpE,MAAM,IAAI,GAAG,qDAAqD,CAAC;AAenE,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAa,EACb,UAAkB;IAElB,IAAI,WAAW,EAAE,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;YACxE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,YAAY,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;QACpE,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAEvB,+FAA+F;IAC/F,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,kBAAkB,CAAC,KAAK,CAAC,SAAS,UAAU,8BAA8B,CAAC;IACpG,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,OAAO,EAAE;YACP,wBAAwB,EAAE,MAAM;YAChC,MAAM,EAAE,kBAAkB;SAC3B;QACD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAqB,CAAC;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAE/B,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAClD,EAAE,EAAE,YAAY,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE;QAC/B,MAAM,EAAE,UAAmB;QAC3B,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,0BAA0B;QAC/C,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;QAC3B,IAAI,EAAE,IAAI,CAAC,eAAe,IAAI,EAAE;QAChC,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YACzD,CAAC,CAAC,eAAe;YACjB,CAAC,CAAC,QAAQ;QACZ,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;QAC7B,GAAG,EAAE,IAAI,CAAC,GAAG;YACX,CAAC,CAAC,mBAAmB,IAAI,CAAC,GAAG,EAAE;YAC/B,CAAC,CAAC,kCAAkC;KACvC,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cortellis.d.ts","sourceRoot":"","sources":["../../../src/providers/direct/cortellis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAqBpD,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"cortellis.d.ts","sourceRoot":"","sources":["../../../src/providers/direct/cortellis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAqBpD,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAiD7B"}
|