heor-agent-mcp 0.1.7 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/formatters/comparisonMarkdown.d.ts +3 -0
  2. package/dist/formatters/comparisonMarkdown.d.ts.map +1 -0
  3. package/dist/formatters/comparisonMarkdown.js +68 -0
  4. package/dist/formatters/comparisonMarkdown.js.map +1 -0
  5. package/dist/formatters/networkMarkdown.d.ts +3 -0
  6. package/dist/formatters/networkMarkdown.d.ts.map +1 -0
  7. package/dist/formatters/networkMarkdown.js +74 -0
  8. package/dist/formatters/networkMarkdown.js.map +1 -0
  9. package/dist/network/bucher.d.ts +29 -0
  10. package/dist/network/bucher.d.ts.map +1 -0
  11. package/dist/network/bucher.js +125 -0
  12. package/dist/network/bucher.js.map +1 -0
  13. package/dist/network/builder.d.ts +3 -0
  14. package/dist/network/builder.d.ts.map +1 -0
  15. package/dist/network/builder.js +155 -0
  16. package/dist/network/builder.js.map +1 -0
  17. package/dist/network/extractor.d.ts +5 -0
  18. package/dist/network/extractor.d.ts.map +1 -0
  19. package/dist/network/extractor.js +149 -0
  20. package/dist/network/extractor.js.map +1 -0
  21. package/dist/network/frequentistNma.d.ts +12 -0
  22. package/dist/network/frequentistNma.d.ts.map +1 -0
  23. package/dist/network/frequentistNma.js +230 -0
  24. package/dist/network/frequentistNma.js.map +1 -0
  25. package/dist/network/index.d.ts +7 -0
  26. package/dist/network/index.d.ts.map +1 -0
  27. package/dist/network/index.js +6 -0
  28. package/dist/network/index.js.map +1 -0
  29. package/dist/network/pathfinder.d.ts +14 -0
  30. package/dist/network/pathfinder.d.ts.map +1 -0
  31. package/dist/network/pathfinder.js +93 -0
  32. package/dist/network/pathfinder.js.map +1 -0
  33. package/dist/network/types.d.ts +87 -0
  34. package/dist/network/types.d.ts.map +1 -0
  35. package/dist/network/types.js +2 -0
  36. package/dist/network/types.js.map +1 -0
  37. package/dist/providers/direct/index.d.ts.map +1 -1
  38. package/dist/providers/direct/index.js +62 -27
  39. package/dist/providers/direct/index.js.map +1 -1
  40. package/dist/providers/types.d.ts +1 -0
  41. package/dist/providers/types.d.ts.map +1 -1
  42. package/dist/server.js +10 -0
  43. package/dist/server.js.map +1 -1
  44. package/dist/tools/evidenceNetwork.d.ts +54 -0
  45. package/dist/tools/evidenceNetwork.d.ts.map +1 -0
  46. package/dist/tools/evidenceNetwork.js +81 -0
  47. package/dist/tools/evidenceNetwork.js.map +1 -0
  48. package/dist/tools/indirectComparison.d.ts +73 -0
  49. package/dist/tools/indirectComparison.d.ts.map +1 -0
  50. package/dist/tools/indirectComparison.js +191 -0
  51. package/dist/tools/indirectComparison.js.map +1 -0
  52. package/dist/tools/literatureSearch.d.ts +4 -0
  53. package/dist/tools/literatureSearch.d.ts.map +1 -1
  54. package/dist/tools/literatureSearch.js +43 -1
  55. package/dist/tools/literatureSearch.js.map +1 -1
  56. package/package.json +4 -2
@@ -0,0 +1,3 @@
1
+ import type { IndirectComparisonResult } from "../network/types.js";
2
+ export declare function comparisonToMarkdown(result: IndirectComparisonResult): string;
3
+ //# sourceMappingURL=comparisonMarkdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comparisonMarkdown.d.ts","sourceRoot":"","sources":["../../src/formatters/comparisonMarkdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAYpE,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,wBAAwB,GAC/B,MAAM,CAgFR"}
@@ -0,0 +1,68 @@
1
+ function formatNum(n, decimals = 2) {
2
+ return n.toFixed(decimals);
3
+ }
4
+ function formatP(p) {
5
+ if (p < 0.001)
6
+ return "<0.001";
7
+ if (p < 0.01)
8
+ return formatNum(p, 3);
9
+ return formatNum(p, 3);
10
+ }
11
+ export function comparisonToMarkdown(result) {
12
+ const lines = [];
13
+ lines.push("## Indirect Treatment Comparisons");
14
+ lines.push("");
15
+ const methodLabel = result.method === "bucher"
16
+ ? "Bucher Method"
17
+ : result.method === "frequentist_nma"
18
+ ? "Frequentist Network Meta-Analysis"
19
+ : "Mixed Methods";
20
+ lines.push(`**Method:** ${methodLabel}`);
21
+ lines.push(`**Comparisons:** ${result.estimates.length}`);
22
+ lines.push("");
23
+ if (result.estimates.length === 0) {
24
+ lines.push("No indirect comparisons could be computed. Check that comparisons share a common comparator and measure the same outcome.");
25
+ return lines.join("\n");
26
+ }
27
+ // Group by outcome
28
+ const outcomes = new Map();
29
+ for (const e of result.estimates) {
30
+ if (!outcomes.has(e.outcome))
31
+ outcomes.set(e.outcome, []);
32
+ outcomes.get(e.outcome).push(e);
33
+ }
34
+ for (const [outcome, estimates] of outcomes) {
35
+ lines.push(`### ${outcome}`);
36
+ lines.push("");
37
+ const measure = estimates[0].measure;
38
+ const label = measure === "MD" ? "MD" : measure;
39
+ lines.push(`| Comparison | ${label} | 95% CI | p-value | Via | Method |`);
40
+ lines.push("|------------|---------|--------|---------|-----|--------|");
41
+ for (const e of estimates) {
42
+ const est = measure === "MD"
43
+ ? formatNum(e.estimate)
44
+ : formatNum(e.estimate);
45
+ const ci = `[${formatNum(e.ci_lower)}, ${formatNum(e.ci_upper)}]`;
46
+ const p = formatP(e.p_value);
47
+ const via = e.commonComparator;
48
+ const method = e.method === "bucher" ? "Bucher" : "Freq. NMA";
49
+ lines.push(`| ${e.intervention} vs ${e.comparator} | ${est} | ${ci} | ${p} | ${via} | ${method} |`);
50
+ }
51
+ lines.push("");
52
+ }
53
+ // Warnings
54
+ if (result.warnings.length > 0) {
55
+ lines.push("### Warnings");
56
+ for (const w of result.warnings) {
57
+ lines.push(`- ⚠️ ${w}`);
58
+ }
59
+ lines.push("");
60
+ }
61
+ // Limitations
62
+ lines.push("### Limitations");
63
+ for (const l of result.limitations) {
64
+ lines.push(`- ${l}`);
65
+ }
66
+ return lines.join("\n");
67
+ }
68
+ //# sourceMappingURL=comparisonMarkdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comparisonMarkdown.js","sourceRoot":"","sources":["../../src/formatters/comparisonMarkdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { EvidenceNetwork } from "../network/types.js";
2
+ export declare function networkToMarkdown(network: EvidenceNetwork): string;
3
+ //# sourceMappingURL=networkMarkdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"networkMarkdown.d.ts","sourceRoot":"","sources":["../../src/formatters/networkMarkdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CA8FlE"}
@@ -0,0 +1,74 @@
1
+ export function networkToMarkdown(network) {
2
+ const lines = [];
3
+ lines.push("## Evidence Network Analysis");
4
+ lines.push("");
5
+ // Summary
6
+ const { feasibility } = network;
7
+ const verdict = feasibility.feasible ? "**Feasible**" : "**Not feasible**";
8
+ lines.push(`**NMA Feasibility:** ${verdict}`);
9
+ lines.push(`**Treatments:** ${feasibility.nodeCount} | **Comparisons:** ${feasibility.edgeCount} | **Connected:** ${feasibility.connected ? "Yes" : "No"}`);
10
+ lines.push("");
11
+ // Reasons
12
+ lines.push("### Assessment");
13
+ for (const reason of feasibility.reasons) {
14
+ const icon = reason.includes("not") || reason.includes("Only") || reason.includes("disconnected")
15
+ ? "⚠️"
16
+ : "✓";
17
+ lines.push(`- ${icon} ${reason}`);
18
+ }
19
+ lines.push("");
20
+ // Network graph (text)
21
+ if (network.edges.length > 0) {
22
+ lines.push("### Evidence Network");
23
+ lines.push("| Comparison | Trials | Study Types | Confidence |");
24
+ lines.push("|------------|--------|-------------|------------|");
25
+ for (const edge of network.edges) {
26
+ const sourceNode = network.nodes.find((n) => n.id === edge.source);
27
+ const targetNode = network.nodes.find((n) => n.id === edge.target);
28
+ const source = sourceNode?.label ?? edge.source;
29
+ const target = targetNode?.label ?? edge.target;
30
+ const types = [...new Set(edge.studyTypes)].join(", ");
31
+ lines.push(`| ${source} ↔ ${target} | ${edge.trials.length} | ${types} | ${edge.confidence} |`);
32
+ }
33
+ lines.push("");
34
+ }
35
+ // Nodes
36
+ if (network.nodes.length > 0) {
37
+ lines.push("### Treatments Identified");
38
+ lines.push("| Treatment | Role |");
39
+ lines.push("|-----------|------|");
40
+ for (const node of network.nodes) {
41
+ lines.push(`| ${node.label} | ${node.type} |`);
42
+ }
43
+ lines.push("");
44
+ }
45
+ // Components (if disconnected)
46
+ if (feasibility.componentCount > 1) {
47
+ lines.push("### Disconnected Components");
48
+ for (let i = 0; i < feasibility.components.length; i++) {
49
+ lines.push(`- **Component ${i + 1}:** ${feasibility.components[i].join(", ")}`);
50
+ }
51
+ lines.push("");
52
+ }
53
+ // Gaps
54
+ if (feasibility.gaps.length > 0) {
55
+ lines.push("### Evidence Gaps");
56
+ for (const gap of feasibility.gaps) {
57
+ lines.push(`- ⚠️ ${gap.description}`);
58
+ }
59
+ lines.push("");
60
+ }
61
+ // Recommendation
62
+ lines.push("### Recommendation");
63
+ if (feasibility.feasible) {
64
+ lines.push("The evidence network is connected with sufficient comparisons to support a network meta-analysis. " +
65
+ "Consider Bayesian NMA (R/Stan or WinBUGS) with assessment of heterogeneity and inconsistency.");
66
+ }
67
+ else {
68
+ lines.push("The evidence network does not currently support a valid NMA. " +
69
+ "Consider: expanding the literature search, including indirect comparators, " +
70
+ "or using pairwise meta-analysis for available direct comparisons.");
71
+ }
72
+ return lines.join("\n");
73
+ }
74
+ //# sourceMappingURL=networkMarkdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"networkMarkdown.js","sourceRoot":"","sources":["../../src/formatters/networkMarkdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { EffectMeasure, PooledEstimate, DirectComparison, IndirectEstimate } from "./types.js";
2
+ /** Standard error from 95% CI */
3
+ export declare function seFromCI(lower: number, upper: number): number;
4
+ /** Normal CDF approximation (Abramowitz & Stegun 26.2.17) */
5
+ export declare function normalCDF(x: number): number;
6
+ /** Two-tailed p-value from z-score */
7
+ export declare function pValueFromZ(z: number): number;
8
+ /** Fixed-effect inverse-variance pooling */
9
+ export declare function poolFixedEffect(studies: Array<{
10
+ value: number;
11
+ se: number;
12
+ }>): PooledEstimate;
13
+ /** Bucher indirect comparison: A vs C = A vs B - C vs B */
14
+ export declare function bucherIndirect(ab: PooledEstimate, cb: PooledEstimate): {
15
+ value: number;
16
+ se: number;
17
+ z: number;
18
+ p_value: number;
19
+ };
20
+ /**
21
+ * Compute a single indirect comparison A vs C through common comparator B.
22
+ *
23
+ * directAB: studies comparing A (intervention) vs B (comparator)
24
+ * directCB: studies comparing C (intervention) vs B (comparator)
25
+ *
26
+ * Returns the indirect estimate of A vs C.
27
+ */
28
+ export declare function computeIndirectComparison(intervention: string, comparator: string, bridge: string, directAB: DirectComparison[], directCB: DirectComparison[], outcome: string, measure: EffectMeasure): IndirectEstimate;
29
+ //# sourceMappingURL=bucher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bucher.d.ts","sourceRoot":"","sources":["../../src/network/bucher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB,iCAAiC;AACjC,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAc3C;AAED,sCAAsC;AACtC,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAiDD,4CAA4C;AAC5C,wBAAgB,eAAe,CAC7B,OAAO,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GAC5C,cAAc,CAqBhB;AAED,2DAA2D;AAC3D,wBAAgB,cAAc,CAC5B,EAAE,EAAE,cAAc,EAClB,EAAE,EAAE,cAAc,GACjB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAM3D;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,gBAAgB,EAAE,EAC5B,QAAQ,EAAE,gBAAgB,EAAE,EAC5B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,aAAa,GACrB,gBAAgB,CAoDlB"}
@@ -0,0 +1,125 @@
1
+ /** Standard error from 95% CI */
2
+ export function seFromCI(lower, upper) {
3
+ return (upper - lower) / 3.92;
4
+ }
5
+ /** Normal CDF approximation (Abramowitz & Stegun 26.2.17) */
6
+ export function normalCDF(x) {
7
+ const sign = x < 0 ? -1 : 1;
8
+ const z = Math.abs(x);
9
+ const t = 1.0 / (1.0 + 0.2316419 * z);
10
+ const d = 0.3989422804014327; // 1/sqrt(2*pi)
11
+ const p = d *
12
+ Math.exp((-z * z) / 2.0) *
13
+ (t *
14
+ (0.319381530 +
15
+ t *
16
+ (-0.356563782 +
17
+ t * (1.781477937 + t * (-1.821255978 + t * 1.330274429)))));
18
+ return sign === 1 ? 1.0 - p : p;
19
+ }
20
+ /** Two-tailed p-value from z-score */
21
+ export function pValueFromZ(z) {
22
+ return 2 * (1 - normalCDF(Math.abs(z)));
23
+ }
24
+ /** Whether the measure operates on a log scale */
25
+ function isLogScale(measure) {
26
+ return measure === "OR" || measure === "RR" || measure === "HR";
27
+ }
28
+ /** Convert to working scale (log for ratio measures) */
29
+ function toWorkingScale(estimate, se, measure) {
30
+ if (isLogScale(measure)) {
31
+ return { value: Math.log(estimate), se };
32
+ }
33
+ return { value: estimate, se };
34
+ }
35
+ /** Convert SE from CI on the original scale to working scale */
36
+ function seOnWorkingScale(estimate, ci_lower, ci_upper, measure) {
37
+ if (isLogScale(measure)) {
38
+ return (Math.log(ci_upper) - Math.log(ci_lower)) / 3.92;
39
+ }
40
+ return seFromCI(ci_lower, ci_upper);
41
+ }
42
+ /** Back-transform from working scale */
43
+ function fromWorkingScale(value, lower, upper, measure) {
44
+ if (isLogScale(measure)) {
45
+ return {
46
+ estimate: Math.exp(value),
47
+ ci_lower: Math.exp(lower),
48
+ ci_upper: Math.exp(upper),
49
+ };
50
+ }
51
+ return { estimate: value, ci_lower: lower, ci_upper: upper };
52
+ }
53
+ /** Fixed-effect inverse-variance pooling */
54
+ export function poolFixedEffect(studies) {
55
+ if (studies.length === 0) {
56
+ throw new Error("No studies to pool");
57
+ }
58
+ if (studies.length === 1) {
59
+ return { value: studies[0].value, se: studies[0].se, n_studies: 1 };
60
+ }
61
+ let sumW = 0;
62
+ let sumWY = 0;
63
+ for (const s of studies) {
64
+ const w = 1 / (s.se * s.se);
65
+ sumW += w;
66
+ sumWY += w * s.value;
67
+ }
68
+ return {
69
+ value: sumWY / sumW,
70
+ se: Math.sqrt(1 / sumW),
71
+ n_studies: studies.length,
72
+ };
73
+ }
74
+ /** Bucher indirect comparison: A vs C = A vs B - C vs B */
75
+ export function bucherIndirect(ab, cb) {
76
+ const value = ab.value - cb.value;
77
+ const se = Math.sqrt(ab.se * ab.se + cb.se * cb.se);
78
+ const z = value / se;
79
+ const p_value = pValueFromZ(z);
80
+ return { value, se, z, p_value };
81
+ }
82
+ /**
83
+ * Compute a single indirect comparison A vs C through common comparator B.
84
+ *
85
+ * directAB: studies comparing A (intervention) vs B (comparator)
86
+ * directCB: studies comparing C (intervention) vs B (comparator)
87
+ *
88
+ * Returns the indirect estimate of A vs C.
89
+ */
90
+ export function computeIndirectComparison(intervention, comparator, bridge, directAB, directCB, outcome, measure) {
91
+ // Convert to working scale and pool
92
+ const abStudies = directAB.map((d) => ({
93
+ value: toWorkingScale(d.estimate, seOnWorkingScale(d.estimate, d.ci_lower, d.ci_upper, measure), measure).value,
94
+ se: seOnWorkingScale(d.estimate, d.ci_lower, d.ci_upper, measure),
95
+ }));
96
+ const cbStudies = directCB.map((d) => ({
97
+ value: toWorkingScale(d.estimate, seOnWorkingScale(d.estimate, d.ci_lower, d.ci_upper, measure), measure).value,
98
+ se: seOnWorkingScale(d.estimate, d.ci_lower, d.ci_upper, measure),
99
+ }));
100
+ const pooledAB = poolFixedEffect(abStudies);
101
+ const pooledCB = poolFixedEffect(cbStudies);
102
+ // Bucher indirect
103
+ const indirect = bucherIndirect(pooledAB, pooledCB);
104
+ // Back-transform
105
+ const ciLowerWorking = indirect.value - 1.96 * indirect.se;
106
+ const ciUpperWorking = indirect.value + 1.96 * indirect.se;
107
+ const result = fromWorkingScale(indirect.value, ciLowerWorking, ciUpperWorking, measure);
108
+ return {
109
+ intervention,
110
+ comparator,
111
+ commonComparator: bridge,
112
+ outcome,
113
+ measure,
114
+ method: "bucher",
115
+ estimate: result.estimate,
116
+ se: indirect.se,
117
+ ci_lower: result.ci_lower,
118
+ ci_upper: result.ci_upper,
119
+ z: indirect.z,
120
+ p_value: indirect.p_value,
121
+ pooled_ab: pooledAB,
122
+ pooled_bc: pooledCB,
123
+ };
124
+ }
125
+ //# sourceMappingURL=bucher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bucher.js","sourceRoot":"","sources":["../../src/network/bucher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { EvidenceNetwork, ComparatorPair } from "./types.js";
2
+ export declare function buildEvidenceNetwork(pairs: ComparatorPair[]): EvidenceNetwork;
3
+ //# sourceMappingURL=builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/network/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,eAAe,EAGf,cAAc,EACf,MAAM,YAAY,CAAC;AAmCpB,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,eAAe,CAoJ7E"}
@@ -0,0 +1,155 @@
1
+ import { normalizeDrugName } from "./extractor.js";
2
+ // Union-Find for connected components
3
+ class UnionFind {
4
+ parent = new Map();
5
+ find(x) {
6
+ if (!this.parent.has(x))
7
+ this.parent.set(x, x);
8
+ const p = this.parent.get(x);
9
+ if (p !== x) {
10
+ const root = this.find(p);
11
+ this.parent.set(x, root);
12
+ return root;
13
+ }
14
+ return x;
15
+ }
16
+ union(a, b) {
17
+ const ra = this.find(a);
18
+ const rb = this.find(b);
19
+ if (ra !== rb)
20
+ this.parent.set(ra, rb);
21
+ }
22
+ components() {
23
+ const groups = new Map();
24
+ for (const key of this.parent.keys()) {
25
+ const root = this.find(key);
26
+ if (!groups.has(root))
27
+ groups.set(root, []);
28
+ groups.get(root).push(key);
29
+ }
30
+ return groups;
31
+ }
32
+ }
33
+ export function buildEvidenceNetwork(pairs) {
34
+ // Build nodes
35
+ const nodeMap = new Map();
36
+ const edgeMap = new Map();
37
+ for (const pair of pairs) {
38
+ const intId = normalizeDrugName(pair.intervention);
39
+ const compId = normalizeDrugName(pair.comparator);
40
+ if (!nodeMap.has(intId)) {
41
+ nodeMap.set(intId, {
42
+ id: intId,
43
+ label: pair.intervention,
44
+ type: "intervention",
45
+ });
46
+ }
47
+ if (!nodeMap.has(compId)) {
48
+ nodeMap.set(compId, {
49
+ id: compId,
50
+ label: pair.comparator,
51
+ type: "comparator",
52
+ });
53
+ }
54
+ // Edge key is sorted to avoid duplicates (A→B = B→A)
55
+ const edgeKey = [intId, compId].sort().join("↔");
56
+ if (!edgeMap.has(edgeKey)) {
57
+ edgeMap.set(edgeKey, {
58
+ source: intId,
59
+ target: compId,
60
+ trials: [],
61
+ studyTypes: [],
62
+ direct: true,
63
+ confidence: pair.confidence,
64
+ });
65
+ }
66
+ const edge = edgeMap.get(edgeKey);
67
+ if (!edge.trials.includes(pair.trialId)) {
68
+ edge.trials.push(pair.trialId);
69
+ edge.studyTypes.push(pair.studyType);
70
+ }
71
+ // Upgrade confidence if higher
72
+ if (pair.confidence === "high" ||
73
+ (pair.confidence === "medium" && edge.confidence === "low")) {
74
+ edge.confidence = pair.confidence;
75
+ }
76
+ }
77
+ const nodes = Array.from(nodeMap.values());
78
+ const edges = Array.from(edgeMap.values());
79
+ // Connectivity analysis
80
+ const uf = new UnionFind();
81
+ for (const node of nodes) {
82
+ uf.find(node.id); // register
83
+ }
84
+ for (const edge of edges) {
85
+ uf.union(edge.source, edge.target);
86
+ }
87
+ const componentMap = uf.components();
88
+ const components = Array.from(componentMap.values()).filter((c) => c.length > 0);
89
+ const connected = components.length === 1;
90
+ // Find gaps: pairs of nodes in different components
91
+ const gaps = [];
92
+ if (!connected && components.length >= 2) {
93
+ for (let i = 0; i < components.length - 1; i++) {
94
+ for (let j = i + 1; j < components.length; j++) {
95
+ const nodeA = nodeMap.get(components[i][0]);
96
+ const nodeB = nodeMap.get(components[j][0]);
97
+ if (nodeA && nodeB) {
98
+ gaps.push({
99
+ from: nodeA.label,
100
+ to: nodeB.label,
101
+ description: `No direct or indirect evidence path between "${nodeA.label}" network and "${nodeB.label}" network`,
102
+ });
103
+ }
104
+ }
105
+ }
106
+ }
107
+ const minTrialsPerEdge = edges.length > 0 ? Math.min(...edges.map((e) => e.trials.length)) : 0;
108
+ // Feasibility assessment
109
+ const reasons = [];
110
+ let feasible = true;
111
+ if (nodes.length < 3) {
112
+ reasons.push(`Only ${nodes.length} treatments identified — NMA requires at least 3`);
113
+ feasible = false;
114
+ }
115
+ else {
116
+ reasons.push(`${nodes.length} treatments identified`);
117
+ }
118
+ if (!connected) {
119
+ reasons.push(`Network is disconnected (${components.length} components) — NMA requires a connected network`);
120
+ feasible = false;
121
+ }
122
+ else {
123
+ reasons.push("Network is fully connected");
124
+ }
125
+ if (minTrialsPerEdge < 1) {
126
+ reasons.push("Some comparisons have no supporting trials");
127
+ feasible = false;
128
+ }
129
+ else if (minTrialsPerEdge < 2) {
130
+ reasons.push("Some comparisons have only 1 trial — consider heterogeneity carefully");
131
+ }
132
+ else {
133
+ reasons.push(`All comparisons supported by ≥${minTrialsPerEdge} trials`);
134
+ }
135
+ if (edges.length < 2) {
136
+ reasons.push(`Only ${edges.length} comparison(s) found — NMA adds value with ≥3 comparisons`);
137
+ feasible = false;
138
+ }
139
+ else {
140
+ reasons.push(`${edges.length} direct comparisons found`);
141
+ }
142
+ const feasibility = {
143
+ feasible,
144
+ reasons,
145
+ nodeCount: nodes.length,
146
+ edgeCount: edges.length,
147
+ connected,
148
+ componentCount: components.length,
149
+ components: components.map((c) => c.map((id) => nodeMap.get(id)?.label ?? id)),
150
+ minTrialsPerEdge,
151
+ gaps,
152
+ };
153
+ return { nodes, edges, feasibility };
154
+ }
155
+ //# sourceMappingURL=builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/network/builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { LiteratureResult } from "../providers/types.js";
2
+ import type { ComparatorPair } from "./types.js";
3
+ export declare function normalizeDrugName(name: string): string;
4
+ export declare function extractComparatorPairs(results: LiteratureResult[]): ComparatorPair[];
5
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/network/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAqGjD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKtD;AAyCD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,gBAAgB,EAAE,GAC1B,cAAc,EAAE,CAsClB"}