@inflexa-ai/harness 0.13.0 → 0.14.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/dist/agents/conversation-agent.js +23 -16
- package/dist/agents/sandbox/cheminformatics-agent.js +1 -1
- package/dist/agents/sandbox/chromatin-agent.js +1 -1
- package/dist/agents/sandbox/dna-methylation-agent.js +1 -1
- package/dist/agents/sandbox/drug-repurposing-agent.js +5 -10
- package/dist/agents/sandbox/enrichment-agent.js +1 -1
- package/dist/agents/sandbox/genomic-variant-agent.js +1 -11
- package/dist/agents/sandbox/immune-profiling-agent.js +1 -1
- package/dist/agents/sandbox/multi-omics-integration-agent.js +1 -1
- package/dist/agents/sandbox/network-agent.js +1 -1
- package/dist/agents/sandbox/pkpd-clinical-response-agent.js +3 -6
- package/dist/agents/sandbox/scientific-executor.js +1 -1
- package/dist/agents/sandbox/shared.js +7 -13
- package/dist/agents/sandbox/translational-safety-agent.js +4 -7
- package/dist/agents/sandbox/types.d.ts +5 -5
- package/dist/agents/sandbox/types.js +4 -4
- package/dist/app/chat-turn.js +4 -1
- package/dist/app/message-assembly.d.ts +5 -2
- package/dist/app/message-assembly.js +7 -2
- package/dist/app/run-activity.d.ts +13 -0
- package/dist/app/run-activity.js +51 -0
- package/dist/contracts/target-dossier.d.ts +10 -10
- package/dist/execution/report-runner.js +1 -1
- package/dist/execution/run-event-parts.d.ts +44 -0
- package/dist/execution/run-event-parts.js +0 -0
- package/dist/execution/run-event-stream.d.ts +91 -0
- package/dist/execution/run-event-stream.js +212 -0
- package/dist/execution/run-synthesis.js +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +20 -1
- package/dist/input-sanitization.d.ts +14 -4
- package/dist/input-sanitization.js +27 -4
- package/dist/lib/storage.js +4 -1
- package/dist/loop/budget-exceeded.d.ts +18 -2
- package/dist/loop/budget-exceeded.js +49 -2
- package/dist/loop/run-agent.d.ts +22 -1
- package/dist/loop/run-agent.js +91 -25
- package/dist/loop/run-to-terminal.d.ts +22 -4
- package/dist/loop/run-to-terminal.js +20 -4
- package/dist/memory/ai-sdk-message-storage.d.ts +37 -4
- package/dist/memory/ai-sdk-message-storage.js +45 -4
- package/dist/memory/content-to-cortex.js +19 -3
- package/dist/memory/message-backfill.js +1 -1
- package/dist/memory/thread-history.js +34 -8
- package/dist/prompts/conversation.d.ts +1 -1
- package/dist/prompts/conversation.js +15 -6
- package/dist/prompts/literature-reviewer.d.ts +1 -1
- package/dist/prompts/literature-reviewer.js +16 -14
- package/dist/prompts/planner.js +15 -20
- package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
- package/dist/prompts/sandbox/drug-repurposing-agent.js +31 -22
- package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.js +9 -10
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.d.ts +1 -1
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.js +8 -7
- package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.js +20 -14
- package/dist/prompts/synthesis-agent.d.ts +1 -1
- package/dist/prompts/synthesis-agent.js +7 -7
- package/dist/providers/errors.d.ts +7 -0
- package/dist/providers/errors.js +88 -3
- package/dist/runtime/pools.d.ts +15 -1
- package/dist/runtime/pools.js +15 -1
- package/dist/sandbox/sandbox-step-translate.d.ts +15 -2
- package/dist/sandbox/sandbox-step-translate.js +17 -2
- package/dist/schemas/workflow-state.d.ts +2 -2
- package/dist/schemas/workflow-state.js +2 -2
- package/dist/state/data-profile.d.ts +53 -1
- package/dist/state/data-profile.js +66 -6
- package/dist/state/index.d.ts +3 -3
- package/dist/state/index.js +2 -2
- package/dist/state/init.js +37 -2
- package/dist/state/runs.d.ts +39 -0
- package/dist/state/runs.js +103 -0
- package/dist/tasks/data-profile-activity.d.ts +87 -0
- package/dist/tasks/data-profile-activity.js +56 -0
- package/dist/tasks/data-profile.js +66 -4
- package/dist/tools/bio/chembl.d.ts +1 -1
- package/dist/tools/bio/chembl.js +51 -54
- package/dist/tools/bio/comptox.js +35 -33
- package/dist/tools/bio/drug-gene-interactions.d.ts +76 -0
- package/dist/tools/bio/drug-gene-interactions.js +175 -0
- package/dist/tools/bio/gene-disease-evidence.d.ts +61 -0
- package/dist/tools/bio/gene-disease-evidence.js +187 -0
- package/dist/tools/bio/gene-preclinical-profile.d.ts +58 -0
- package/dist/tools/bio/gene-preclinical-profile.js +125 -0
- package/dist/tools/bio/index.d.ts +23 -16
- package/dist/tools/bio/index.js +29 -22
- package/dist/tools/bio/keys.d.ts +16 -9
- package/dist/tools/bio/keys.js +22 -13
- package/dist/tools/bio/lookup-annotation.d.ts +48 -0
- package/dist/tools/bio/lookup-annotation.js +173 -0
- package/dist/tools/bio/opentargets.d.ts +7 -11
- package/dist/tools/bio/opentargets.js +24 -35
- package/dist/tools/bio/pubchem.js +6 -4
- package/dist/tools/bio/pubmed.d.ts +15 -7
- package/dist/tools/bio/pubmed.js +79 -20
- package/dist/tools/bio/search-clinical-trials.d.ts +20 -1
- package/dist/tools/bio/search-clinical-trials.js +26 -5
- package/dist/tools/bio/search-faers.js +9 -3
- package/dist/tools/bio/search-gene.d.ts +0 -1
- package/dist/tools/bio/search-gene.js +4 -5
- package/dist/tools/bio/search-geo-datasets.js +10 -4
- package/dist/tools/bio/search-interactions.d.ts +8 -4
- package/dist/tools/bio/search-interactions.js +28 -12
- package/dist/tools/bio/target-safety.d.ts +59 -0
- package/dist/tools/bio/target-safety.js +191 -0
- package/dist/tools/execute-analysis.d.ts +1 -0
- package/dist/tools/execute-analysis.js +5 -5
- package/dist/tools/lib/dgidb-client.d.ts +49 -0
- package/dist/tools/lib/dgidb-client.js +168 -0
- package/dist/tools/lib/disgenet-client.d.ts +56 -0
- package/dist/tools/lib/disgenet-client.js +59 -0
- package/dist/tools/lib/drugbank-client.d.ts +83 -0
- package/dist/tools/lib/drugbank-client.js +95 -0
- package/dist/tools/lib/ensembl-client.d.ts +4 -1
- package/dist/tools/lib/ensembl-client.js +5 -3
- package/dist/tools/lib/gwas-catalog-client.d.ts +60 -0
- package/dist/tools/lib/gwas-catalog-client.js +136 -0
- package/dist/tools/lib/pharmgkb-client.d.ts +22 -0
- package/dist/tools/lib/pharmgkb-client.js +32 -0
- package/dist/tools/lib/pubmed-client.d.ts +57 -4
- package/dist/tools/lib/pubmed-client.js +57 -3
- package/dist/tools/lib/string-client.d.ts +25 -4
- package/dist/tools/lib/string-client.js +22 -5
- package/dist/tools/research/generate-plan.d.ts +16 -9
- package/dist/tools/research/generate-plan.js +405 -85
- package/dist/tools/research/inspect-data-profile.d.ts +31 -6
- package/dist/tools/research/inspect-data-profile.js +23 -7
- package/dist/tools/research/inspect-run.d.ts +33 -15
- package/dist/tools/research/inspect-run.js +155 -66
- package/dist/tools/research/literature-reviewer.js +7 -11
- package/dist/workflows/execute-analysis.d.ts +63 -0
- package/dist/workflows/execute-analysis.js +73 -2
- package/dist/workflows/sandbox-step.js +1 -11
- package/dist/workflows/target-assessment/decisions/index.d.ts +1 -1
- package/dist/workflows/target-assessment/phase4-assemble.d.ts +1 -1
- package/dist/workflows/target-assessment/steps/phase2-aggregate.d.ts +2 -2
- package/dist/workflows/target-assessment/steps/phase3-aggregate.d.ts +1 -1
- package/package.json +1 -1
- package/dist/tools/bio/check-safety-panel.d.ts +0 -35
- package/dist/tools/bio/check-safety-panel.js +0 -76
- package/dist/tools/bio/get-impc-ko-profile.d.ts +0 -9
- package/dist/tools/bio/get-impc-ko-profile.js +0 -23
- package/dist/tools/bio/lookup-go-term.d.ts +0 -31
- package/dist/tools/bio/lookup-go-term.js +0 -116
- package/dist/tools/bio/search-bgee-expression.d.ts +0 -10
- package/dist/tools/bio/search-bgee-expression.js +0 -30
- package/dist/tools/bio/search-clinvar.d.ts +0 -13
- package/dist/tools/bio/search-clinvar.js +0 -28
- package/dist/tools/bio/search-dgidb.d.ts +0 -53
- package/dist/tools/bio/search-dgidb.js +0 -213
- package/dist/tools/bio/search-disgenet.d.ts +0 -30
- package/dist/tools/bio/search-disgenet.js +0 -84
- package/dist/tools/bio/search-drugbank.d.ts +0 -38
- package/dist/tools/bio/search-drugbank.js +0 -109
- package/dist/tools/bio/search-gwas-catalog.d.ts +0 -33
- package/dist/tools/bio/search-gwas-catalog.js +0 -172
- package/dist/tools/bio/search-pathway.d.ts +0 -12
- package/dist/tools/bio/search-pathway.js +0 -32
- package/dist/tools/bio/search-pharmgkb.d.ts +0 -17
- package/dist/tools/bio/search-pharmgkb.js +0 -52
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* searchGwasCatalog — search NHGRI-EBI GWAS Catalog for SNP-trait associations.
|
|
3
|
-
*
|
|
4
|
-
* Public REST API, no key required. Three search modes:
|
|
5
|
-
* - 'gene' — gene-trait associations (via SNP-by-gene lookup, then assocs)
|
|
6
|
-
* - 'trait' — trait-gene associations (via EFO trait search, then assocs)
|
|
7
|
-
* - 'variant' — direct rsID lookup
|
|
8
|
-
*/
|
|
9
|
-
import { ok } from "neverthrow";
|
|
10
|
-
import { z } from "zod";
|
|
11
|
-
import { defineTool } from "../define-tool.js";
|
|
12
|
-
import { apiFetchValidated, describeApiError } from "../lib/api-utils.js";
|
|
13
|
-
import { GWAS_BASE, GWAS_HEADERS } from "../lib/gwas-catalog-config.js";
|
|
14
|
-
// GWAS Catalog raw wire shapes (HAL+JSON), validated at the fetch boundary.
|
|
15
|
-
// Every field is optional because the API omits absent values; leaf strings
|
|
16
|
-
// that the API can return as an explicit `null` are `.nullable()`.
|
|
17
|
-
const RawGwasStudySchema = z.object({
|
|
18
|
-
accessionId: z.string().optional(),
|
|
19
|
-
pubmedId: z.string().optional(),
|
|
20
|
-
initialSampleSize: z.string().optional(),
|
|
21
|
-
});
|
|
22
|
-
// `_snpRsId` is not on the wire — the 'gene' search path assigns it after
|
|
23
|
-
// parsing (`a._snpRsId = snp.rsId`), so it stays a writable optional field.
|
|
24
|
-
const RawGwasAssociationSchema = z.object({
|
|
25
|
-
_snpRsId: z.string().optional(),
|
|
26
|
-
loci: z
|
|
27
|
-
.array(z.object({
|
|
28
|
-
strongestRiskAlleles: z.array(z.object({ riskAlleleName: z.string().nullable().optional() })).optional(),
|
|
29
|
-
authorReportedGenes: z.array(z.object({ geneName: z.string().nullable().optional() })).optional(),
|
|
30
|
-
}))
|
|
31
|
-
.optional(),
|
|
32
|
-
efoTraits: z.array(z.object({ trait: z.string().nullable().optional() })).optional(),
|
|
33
|
-
study: RawGwasStudySchema.optional(),
|
|
34
|
-
pvalueMantissa: z.number().optional(),
|
|
35
|
-
pvalueExponent: z.number().optional(),
|
|
36
|
-
riskFrequency: z.string().optional(),
|
|
37
|
-
orPerCopyNum: z.number().nullable().optional(),
|
|
38
|
-
betaNum: z.number().nullable().optional(),
|
|
39
|
-
range: z.string().optional(),
|
|
40
|
-
});
|
|
41
|
-
const GwasEmbeddedSchema = z.object({
|
|
42
|
-
_embedded: z.object({ associations: z.array(RawGwasAssociationSchema).optional() }).optional(),
|
|
43
|
-
page: z.object({ totalElements: z.number().optional() }).optional(),
|
|
44
|
-
});
|
|
45
|
-
const GwasTraitSearchResponseSchema = z.object({
|
|
46
|
-
_embedded: z
|
|
47
|
-
.object({
|
|
48
|
-
efoTraits: z.array(z.object({ _links: z.object({ self: z.object({ href: z.string().optional() }).optional() }).optional() })).optional(),
|
|
49
|
-
})
|
|
50
|
-
.optional(),
|
|
51
|
-
});
|
|
52
|
-
const GwasSnpSearchResponseSchema = z.object({
|
|
53
|
-
_embedded: z
|
|
54
|
-
.object({
|
|
55
|
-
singleNucleotidePolymorphisms: z
|
|
56
|
-
.array(z.object({
|
|
57
|
-
rsId: z.string().optional(),
|
|
58
|
-
_links: z.object({ associations: z.object({ href: z.string().optional() }).optional() }).optional(),
|
|
59
|
-
}))
|
|
60
|
-
.optional(),
|
|
61
|
-
})
|
|
62
|
-
.optional(),
|
|
63
|
-
});
|
|
64
|
-
function mapAssociation(a) {
|
|
65
|
-
const loci = a.loci ?? [];
|
|
66
|
-
const riskAlleles = loci.flatMap((l) => l.strongestRiskAlleles?.map((ra) => String(ra.riskAlleleName ?? "")) ?? []);
|
|
67
|
-
const genes = loci.flatMap((l) => l.authorReportedGenes?.map((g) => String(g.geneName ?? "")) ?? []);
|
|
68
|
-
const traits = (a.efoTraits ?? []).map((t) => String(t.trait ?? ""));
|
|
69
|
-
const study = a.study ?? {};
|
|
70
|
-
const pMantissa = a.pvalueMantissa ?? 0;
|
|
71
|
-
const pExponent = a.pvalueExponent ?? 0;
|
|
72
|
-
return {
|
|
73
|
-
rsId: String(a._snpRsId ?? riskAlleles[0]?.split("-")[0] ?? ""),
|
|
74
|
-
pValue: pMantissa * Math.pow(10, pExponent),
|
|
75
|
-
pValueMantissa: pMantissa,
|
|
76
|
-
pValueExponent: pExponent,
|
|
77
|
-
riskAllele: riskAlleles.join(", "),
|
|
78
|
-
riskFrequency: String(a.riskFrequency ?? ""),
|
|
79
|
-
orBeta: (a.orPerCopyNum ?? a.betaNum ?? null),
|
|
80
|
-
ci: String(a.range ?? ""),
|
|
81
|
-
trait: traits.join("; "),
|
|
82
|
-
mappedGenes: [...new Set(genes)],
|
|
83
|
-
studyAccession: String(study.accessionId ?? ""),
|
|
84
|
-
pubmedId: String(study.pubmedId ?? ""),
|
|
85
|
-
sampleSize: String(study.initialSampleSize ?? ""),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
export const searchGwasCatalogTool = defineTool({
|
|
89
|
-
id: "search_gwas_catalog",
|
|
90
|
-
description: "Search the NHGRI-EBI GWAS Catalog for genome-wide association study results. " +
|
|
91
|
-
"Returns SNP associations with traits/diseases, effect sizes, p-values, and mapped genes. " +
|
|
92
|
-
"Use to find genetic evidence linking genes to phenotypes for target validation or " +
|
|
93
|
-
"Mendelian randomization support.",
|
|
94
|
-
inputSchema: z.object({
|
|
95
|
-
query: z.string().describe("Gene symbol (e.g. PCSK9), trait keyword (e.g. cholesterol), or rsID (e.g. rs11591147)"),
|
|
96
|
-
searchType: z
|
|
97
|
-
.enum(["gene", "trait", "variant"])
|
|
98
|
-
.describe("'gene' for gene-trait associations, 'trait' for trait-gene associations, 'variant' for a specific rsID"),
|
|
99
|
-
pValueThreshold: z.number().default(5e-8).describe("P-value threshold for genome-wide significance"),
|
|
100
|
-
limit: z.number().int().min(1).max(100).default(25).describe("Max results to return"),
|
|
101
|
-
}),
|
|
102
|
-
execute: async ({ query, searchType, pValueThreshold = 5e-8, limit = 25 }) => {
|
|
103
|
-
let url;
|
|
104
|
-
if (searchType === "variant") {
|
|
105
|
-
const rsId = query.startsWith("rs") ? query : `rs${query}`;
|
|
106
|
-
url = `${GWAS_BASE}/singleNucleotidePolymorphisms/${rsId}/associations?projection=associationBySnp`;
|
|
107
|
-
}
|
|
108
|
-
else if (searchType === "gene") {
|
|
109
|
-
url = `${GWAS_BASE}/singleNucleotidePolymorphisms/search/findByGene?geneName=${encodeURIComponent(query)}&projection=snpByGene`;
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
url = `${GWAS_BASE}/efoTraits/search/findBySearchQuery?query=${encodeURIComponent(query)}`;
|
|
113
|
-
}
|
|
114
|
-
if (searchType === "trait") {
|
|
115
|
-
const traitRes = await apiFetchValidated(url, GwasTraitSearchResponseSchema, { headers: GWAS_HEADERS });
|
|
116
|
-
if (traitRes.isErr())
|
|
117
|
-
throw new Error(describeApiError(traitRes.error));
|
|
118
|
-
const traits = traitRes.value?._embedded?.efoTraits ?? [];
|
|
119
|
-
if (traits.length === 0) {
|
|
120
|
-
return ok({ totalFound: 0, associations: [] });
|
|
121
|
-
}
|
|
122
|
-
const traitUri = traits[0]?._links?.self?.href;
|
|
123
|
-
if (!traitUri) {
|
|
124
|
-
return ok({ totalFound: 0, associations: [] });
|
|
125
|
-
}
|
|
126
|
-
const traitId = traitUri.split("/").pop();
|
|
127
|
-
url = `${GWAS_BASE}/efoTraits/${traitId}/associations?size=${limit}`;
|
|
128
|
-
}
|
|
129
|
-
if (searchType === "gene") {
|
|
130
|
-
const snpRes = await apiFetchValidated(url, GwasSnpSearchResponseSchema, { headers: GWAS_HEADERS });
|
|
131
|
-
if (snpRes.isErr())
|
|
132
|
-
throw new Error(describeApiError(snpRes.error));
|
|
133
|
-
const snps = snpRes.value?._embedded?.singleNucleotidePolymorphisms ?? [];
|
|
134
|
-
const allAssocs = [];
|
|
135
|
-
for (const snp of snps.slice(0, Math.min(limit, 10))) {
|
|
136
|
-
const assocLink = snp?._links?.associations?.href;
|
|
137
|
-
if (!assocLink)
|
|
138
|
-
continue;
|
|
139
|
-
const aRes = await apiFetchValidated(assocLink, GwasEmbeddedSchema, {
|
|
140
|
-
headers: GWAS_HEADERS,
|
|
141
|
-
});
|
|
142
|
-
if (aRes.isOk()) {
|
|
143
|
-
for (const a of aRes.value?._embedded?.associations ?? []) {
|
|
144
|
-
a._snpRsId = snp.rsId;
|
|
145
|
-
allAssocs.push(a);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
if (allAssocs.length >= limit)
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
151
|
-
return ok({
|
|
152
|
-
totalFound: allAssocs.length,
|
|
153
|
-
associations: allAssocs.slice(0, limit).map(mapAssociation),
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
const res = await apiFetchValidated(url, GwasEmbeddedSchema, { headers: GWAS_HEADERS });
|
|
157
|
-
if (res.isErr())
|
|
158
|
-
throw new Error(describeApiError(res.error));
|
|
159
|
-
const rawAssocs = res.value?._embedded?.associations ?? [];
|
|
160
|
-
const totalFound = res.value?.page?.totalElements ?? rawAssocs.length;
|
|
161
|
-
const filtered = rawAssocs
|
|
162
|
-
.filter((a) => {
|
|
163
|
-
const p = (a.pvalueMantissa ?? 1) * Math.pow(10, a.pvalueExponent ?? 0);
|
|
164
|
-
return p <= pValueThreshold;
|
|
165
|
-
})
|
|
166
|
-
.slice(0, limit);
|
|
167
|
-
return ok({
|
|
168
|
-
totalFound,
|
|
169
|
-
associations: filtered.map(mapAssociation),
|
|
170
|
-
});
|
|
171
|
-
},
|
|
172
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* searchPathway — search biological pathways via KEGG and Reactome.
|
|
3
|
-
*/
|
|
4
|
-
export declare const searchPathwayTool: import("../define-tool.js").Tool<{
|
|
5
|
-
query: string;
|
|
6
|
-
source: "kegg" | "reactome" | "both";
|
|
7
|
-
organism: string;
|
|
8
|
-
includeGenes: boolean;
|
|
9
|
-
maxResults: number;
|
|
10
|
-
}, {
|
|
11
|
-
pathways: import("../lib/pathway-client.js").Pathway[];
|
|
12
|
-
}>;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* searchPathway — search biological pathways via KEGG and Reactome.
|
|
3
|
-
*/
|
|
4
|
-
import { ok } from "neverthrow";
|
|
5
|
-
import { z } from "zod";
|
|
6
|
-
import { defineTool } from "../define-tool.js";
|
|
7
|
-
import { searchPathways } from "../lib/pathway-client.js";
|
|
8
|
-
export const searchPathwayTool = defineTool({
|
|
9
|
-
id: "search_pathway",
|
|
10
|
-
description: "Search biological pathways in KEGG and/or Reactome databases. " +
|
|
11
|
-
"Returns pathway IDs, names, URLs, and optionally gene lists. " +
|
|
12
|
-
"Use source='both' to query both databases in parallel.",
|
|
13
|
-
inputSchema: z.object({
|
|
14
|
-
query: z.string().min(1).describe("Pathway search term (e.g. 'apoptosis', 'MAPK signaling')"),
|
|
15
|
-
source: z.enum(["kegg", "reactome", "both"]).default("both").describe("Which database to search"),
|
|
16
|
-
organism: z
|
|
17
|
-
.string()
|
|
18
|
-
.default("hsa")
|
|
19
|
-
.describe("KEGG organism code (e.g. 'hsa' for human, 'mmu' for mouse). " + "Automatically mapped to species name for Reactome."),
|
|
20
|
-
includeGenes: z.boolean().default(false).describe("Whether to fetch gene lists for each pathway (slower)"),
|
|
21
|
-
maxResults: z.number().int().min(1).max(50).default(10),
|
|
22
|
-
}),
|
|
23
|
-
execute: async ({ query, source, organism, includeGenes, maxResults }) => {
|
|
24
|
-
const pathways = await searchPathways(query, {
|
|
25
|
-
source,
|
|
26
|
-
organism,
|
|
27
|
-
includeGenes,
|
|
28
|
-
maxResults,
|
|
29
|
-
});
|
|
30
|
-
return ok({ pathways });
|
|
31
|
-
},
|
|
32
|
-
});
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* searchPharmgkb — search PharmGKB for pharmacogenomic clinical annotations.
|
|
3
|
-
*/
|
|
4
|
-
export declare const searchPharmgkbTool: import("../define-tool.js").Tool<{
|
|
5
|
-
query: string;
|
|
6
|
-
searchType: "drug" | "gene";
|
|
7
|
-
limit: number;
|
|
8
|
-
}, {
|
|
9
|
-
annotations: {
|
|
10
|
-
gene: string;
|
|
11
|
-
drug: string;
|
|
12
|
-
phenotype: null;
|
|
13
|
-
levelOfEvidence: string;
|
|
14
|
-
guidelineSource: null;
|
|
15
|
-
summary: null;
|
|
16
|
-
}[];
|
|
17
|
-
}>;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* searchPharmgkb — search PharmGKB for pharmacogenomic clinical annotations.
|
|
3
|
-
*/
|
|
4
|
-
import { ok } from "neverthrow";
|
|
5
|
-
import { z } from "zod";
|
|
6
|
-
import { defineTool } from "../define-tool.js";
|
|
7
|
-
import { apiFetchValidated, describeApiError } from "../lib/api-utils.js";
|
|
8
|
-
import { PHARMGKB_BASE, PHARMGKB_HEADERS } from "../lib/pharmgkb-config.js";
|
|
9
|
-
// Raw PharmGKB clinicalAnnotation wire shape, validated at the fetch boundary.
|
|
10
|
-
// Every field is optional because the API omits absent values; the mapper in
|
|
11
|
-
// `execute` folds request context (`query`) into its output, so the schema
|
|
12
|
-
// models only the raw wire and the mapping stays where it is.
|
|
13
|
-
const PharmgkbAnnotationSchema = z.object({
|
|
14
|
-
location: z.object({ genes: z.array(z.object({ symbol: z.string().optional() })).optional() }).optional(),
|
|
15
|
-
relatedChemicals: z.array(z.object({ name: z.string().optional() })).optional(),
|
|
16
|
-
levelOfEvidence: z.object({ term: z.string().optional() }).optional(),
|
|
17
|
-
});
|
|
18
|
-
const PharmgkbResponseSchema = z.object({
|
|
19
|
-
data: z.array(PharmgkbAnnotationSchema).optional(),
|
|
20
|
-
});
|
|
21
|
-
export const searchPharmgkbTool = defineTool({
|
|
22
|
-
id: "search_pharmgkb",
|
|
23
|
-
description: "Search PharmGKB clinical annotations for a gene-drug pharmacogenomic link — use it to judge whether a gene affects a drug's metabolism, efficacy, or toxicity. " +
|
|
24
|
-
"Returns annotations[]: { gene, drug, levelOfEvidence (PharmGKB 1A…4, where 1A is guideline-backed) }. The phenotype, guidelineSource and summary fields are always null " +
|
|
25
|
-
"in this tool's output — treat levelOfEvidence as the only strength signal and do not attribute CPIC/DPWG guideline text to it. " +
|
|
26
|
-
"Matching is an exact field filter, not a search: 'CYP2D6' resolves, 'cytochrome P450 2D6' does not. " +
|
|
27
|
-
"An empty annotations array is valid no-data (no curated PGx link) — do not retry.",
|
|
28
|
-
inputSchema: z.object({
|
|
29
|
-
query: z
|
|
30
|
-
.string()
|
|
31
|
-
.describe("Exact gene symbol (e.g. 'CYP2D6') when searchType='gene', or exact drug name (e.g. 'tamoxifen') when searchType='drug'. No fuzzy matching."),
|
|
32
|
-
searchType: z.enum(["gene", "drug"]).describe("'gene' filters PharmGKB on location.genes.symbol; 'drug' filters on relatedChemicals.name."),
|
|
33
|
-
limit: z.number().int().min(1).max(50).default(20).describe("Max annotations to return (default 20, max 50); applied client-side after the fetch."),
|
|
34
|
-
}),
|
|
35
|
-
execute: async ({ query, searchType, limit = 20 }) => {
|
|
36
|
-
const filter = searchType === "gene" ? `location.genes.symbol=${encodeURIComponent(query)}` : `relatedChemicals.name=${encodeURIComponent(query)}`;
|
|
37
|
-
const endpoint = `${PHARMGKB_BASE}/clinicalAnnotation?${filter}`;
|
|
38
|
-
const res = await apiFetchValidated(endpoint, PharmgkbResponseSchema, { headers: PHARMGKB_HEADERS });
|
|
39
|
-
if (res.isErr())
|
|
40
|
-
throw new Error(describeApiError(res.error));
|
|
41
|
-
const data = res.value?.data ?? [];
|
|
42
|
-
const annotations = data.slice(0, limit).map((ann) => ({
|
|
43
|
-
gene: ann.location?.genes?.map((g) => g.symbol).join(", ") ?? query,
|
|
44
|
-
drug: ann.relatedChemicals?.map((c) => c.name).join(", ") ?? "",
|
|
45
|
-
phenotype: null,
|
|
46
|
-
levelOfEvidence: ann.levelOfEvidence?.term ?? "Unknown",
|
|
47
|
-
guidelineSource: null,
|
|
48
|
-
summary: null,
|
|
49
|
-
}));
|
|
50
|
-
return ok({ annotations });
|
|
51
|
-
},
|
|
52
|
-
});
|