@inflexa-ai/harness 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/conversation-agent.d.ts +9 -15
- package/dist/agents/conversation-agent.js +32 -31
- 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/index.js +0 -3
- 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.d.ts +2 -2
- package/dist/agents/sandbox/shared.js +8 -14
- 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/config/resource-limits.d.ts +0 -7
- package/dist/config/resource-limits.js +0 -1
- package/dist/contracts/target-dossier.d.ts +10 -10
- package/dist/execution/dbos-run-launcher.js +1 -26
- package/dist/execution/report-runner.js +1 -1
- package/dist/execution/run-authorizer.d.ts +1 -1
- package/dist/execution/run-authorizer.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-launcher.d.ts +2 -18
- package/dist/execution/run-launcher.js +2 -4
- package/dist/execution/run-synthesis.js +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.js +23 -6
- 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 +51 -5
- package/dist/loop/run-to-terminal.d.ts +0 -2
- package/dist/loop/run-to-terminal.js +8 -1
- 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/reconstruct-cards.d.ts +1 -1
- package/dist/memory/reconstruct-cards.js +7 -5
- package/dist/memory/thread-history.js +72 -8
- package/dist/prompts/conversation.d.ts +1 -1
- package/dist/prompts/conversation.js +41 -15
- package/dist/prompts/literature-reviewer.d.ts +1 -1
- package/dist/prompts/literature-reviewer.js +16 -14
- package/dist/prompts/planner.d.ts +3 -0
- package/dist/prompts/planner.js +16 -21
- 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/sandbox-standards.d.ts +4 -4
- package/dist/prompts/sandbox-standards.js +5 -5
- 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/assemble.d.ts +5 -10
- package/dist/runtime/assemble.js +0 -4
- package/dist/runtime/boot.d.ts +2 -2
- package/dist/runtime/boot.js +1 -1
- package/dist/runtime/dbos.d.ts +4 -5
- package/dist/runtime/dbos.js +6 -7
- package/dist/runtime/pools.d.ts +15 -1
- package/dist/runtime/pools.js +15 -1
- package/dist/sandbox/mount-plan.d.ts +1 -1
- package/dist/sandbox/sandbox-error.d.ts +1 -1
- package/dist/sandbox/sandbox-error.js +1 -1
- package/dist/sandbox/sandbox-step-translate.d.ts +15 -2
- package/dist/sandbox/sandbox-step-translate.js +17 -2
- package/dist/sandbox/types.d.ts +1 -1
- package/dist/schemas/validate-plan.d.ts +1 -1
- 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 +6 -6
- package/dist/state/index.js +4 -4
- package/dist/state/init.js +37 -2
- package/dist/state/plans.js +1 -1
- package/dist/state/runs.d.ts +49 -0
- package/dist/state/runs.js +150 -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/__fixtures__/tool-context.js +1 -0
- package/dist/tools/ad-hoc-router.d.ts +31 -0
- package/dist/tools/ad-hoc-router.js +132 -0
- package/dist/tools/analysis-invocation.d.ts +4 -0
- package/dist/tools/analysis-invocation.js +17 -0
- 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/define-tool.d.ts +6 -2
- package/dist/tools/define-tool.js +1 -1
- package/dist/tools/execute-analysis.d.ts +44 -0
- package/dist/tools/execute-analysis.js +252 -0
- package/dist/tools/iterate-report.js +7 -6
- 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 +116 -70
- 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 +68 -5
- package/dist/workflows/execute-analysis.js +76 -7
- 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/agents/sandbox/ephemeral-executor.d.ts +0 -9
- package/dist/agents/sandbox/ephemeral-executor.js +0 -20
- package/dist/execution/ephemeral-runner.d.ts +0 -98
- package/dist/execution/ephemeral-runner.js +0 -189
- package/dist/prompts/sandbox/ephemeral-executor.d.ts +0 -1
- package/dist/prompts/sandbox/ephemeral-executor.js +0 -66
- 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
- package/dist/tools/execute-plan.d.ts +0 -64
- package/dist/tools/execute-plan.js +0 -211
- package/dist/tools/run-ephemeral.d.ts +0 -33
- package/dist/tools/run-ephemeral.js +0 -65
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ephemeral Executor — read-only sandbox agent for quick computations.
|
|
3
|
-
* Cannot create files; step conventions don't apply.
|
|
4
|
-
*/
|
|
5
|
-
import { ephemeralExecutorPrompt } from "../../prompts/sandbox/ephemeral-executor.js";
|
|
6
|
-
import { BASE_SANDBOX_TOOLS, createSandboxAgent } from "./shared.js";
|
|
7
|
-
export const meta = {
|
|
8
|
-
id: "ephemeral-executor",
|
|
9
|
-
capabilities: ["data inspection", "quick statistics", "data transformation", "table preview"],
|
|
10
|
-
suitableFor: ["bulk-rna-seq", "single-cell", "proteomics", "metabolomics", "genomics", "transcriptomics", "general-omics"],
|
|
11
|
-
skills: ["shared/omics-general"],
|
|
12
|
-
tools: [...BASE_SANDBOX_TOOLS, "pubmed", "searchGene", "searchPathway", "lookupGoTerm", "searchInteractions"],
|
|
13
|
-
plannable: false,
|
|
14
|
-
};
|
|
15
|
-
export function createEphemeralExecutorAgent(deps) {
|
|
16
|
-
return createSandboxAgent(deps, meta, ephemeralExecutorPrompt, {
|
|
17
|
-
appendAnalysisStepStandards: false,
|
|
18
|
-
readOnly: true,
|
|
19
|
-
});
|
|
20
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ephemeral runner — read-only sandbox execution for ad-hoc data
|
|
3
|
-
* exploration, run as a turn-scoped DBOS workflow.
|
|
4
|
-
*
|
|
5
|
-
* The `run_ephemeral` conversation tool authorizes the run at the async
|
|
6
|
-
* edge, starts this workflow, and awaits its result inline within the chat
|
|
7
|
-
* turn. The workflow is "bare": it has no run-event stream, so `emit` is a
|
|
8
|
-
* no-op and live sandbox progress events are dropped. It is never recovered
|
|
9
|
-
* — chat disconnect cancels it (`DBOS.cancelWorkflow`), and a boot-time sweep
|
|
10
|
-
* cancels any `ephemeral:`-prefixed PENDING workflow a dead pod left behind.
|
|
11
|
-
*
|
|
12
|
-
* Lifecycle: create sandbox → build the ephemeral-executor with synthetic
|
|
13
|
-
* step coords (`runId = stepId = "ephemeral"`, the literal the host-managed
|
|
14
|
-
* billing rules key on) → drive `runAgent` over the executor with `durableStep` →
|
|
15
|
-
* final text + step count → teardown the sandbox in `finally` on every
|
|
16
|
-
* terminal path.
|
|
17
|
-
*
|
|
18
|
-
* Read-only is enforced, not aspirational: the executor agent is built with
|
|
19
|
-
* `readOnly: true` (no `write_file`/`edit_file` tools) and its sandbox is
|
|
20
|
-
* provisioned with no read-write mount — only the read-only analysis tree.
|
|
21
|
-
* Container-local `/tmp` stays writable (torn down with the sandbox); nothing
|
|
22
|
-
* persists. The prompt's "you physically cannot write files" is now true.
|
|
23
|
-
*/
|
|
24
|
-
import type { Pool } from "pg";
|
|
25
|
-
import type { RunSession } from "../auth/types.js";
|
|
26
|
-
import type { EnvironmentStorePaths } from "../config/environment-stores.js";
|
|
27
|
-
import type { ResourcePolicy } from "../config/resource-limits.js";
|
|
28
|
-
import type { ChatProvider, EmbeddingProvider } from "../providers/types.js";
|
|
29
|
-
import type { SandboxClient } from "../sandbox/client.js";
|
|
30
|
-
import type { BioToolKeys } from "../tools/bio/keys.js";
|
|
31
|
-
import type { WorkspaceFilesystem } from "../workspace/filesystem.js";
|
|
32
|
-
import type { ResolveWorkspaceRoot } from "../workspace/paths.js";
|
|
33
|
-
import type { Logger } from "../lib/logger.js";
|
|
34
|
-
/** Sub-agent identity — appended to `callPath`, set as `agentId`. */
|
|
35
|
-
export declare const EPHEMERAL_AGENT_ID = "ephemeral-executor";
|
|
36
|
-
/** Workflow-id prefix — the boot-time never-recover sweep matches on it. */
|
|
37
|
-
export declare const EPHEMERAL_WORKFLOW_PREFIX: "ephemeral:";
|
|
38
|
-
/** The body's construction-time deps — closed over at registration. */
|
|
39
|
-
export interface EphemeralDeps extends EnvironmentStorePaths {
|
|
40
|
-
/** Operational logging seam; omitted falls back to no-op. */
|
|
41
|
-
readonly logger?: Logger;
|
|
42
|
-
readonly provider: ChatProvider;
|
|
43
|
-
readonly pool: Pool;
|
|
44
|
-
readonly sandboxClient: SandboxClient;
|
|
45
|
-
readonly workspaceFs: WorkspaceFilesystem;
|
|
46
|
-
/** Embedding provider for the executor's in-sandbox `workspace_search`. */
|
|
47
|
-
readonly embedding: EmbeddingProvider;
|
|
48
|
-
/** Workspace-root resolution seam (see workspace/paths.ts). */
|
|
49
|
-
readonly resolveWorkspaceRoot: ResolveWorkspaceRoot;
|
|
50
|
-
/** Model id — provenance / metric label; the provider owns the wire model. */
|
|
51
|
-
readonly model: string;
|
|
52
|
-
/** API keys for the bio/chem tools the ephemeral executor may use. */
|
|
53
|
-
readonly bioKeys: BioToolKeys;
|
|
54
|
-
/** Host resource policy — its `ephemeral` spec overrides the default sandbox size. */
|
|
55
|
-
readonly resourcePolicy?: ResourcePolicy;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Workflow input. JSON-serialisable — the authorized `RunSession` carries the
|
|
59
|
-
* run credential; the body reads it and never re-authorizes.
|
|
60
|
-
*/
|
|
61
|
-
export interface EphemeralWorkflowInput {
|
|
62
|
-
readonly runSession: RunSession;
|
|
63
|
-
readonly prompt: string;
|
|
64
|
-
/** Optional cap on the inner agent's tool-call budget. */
|
|
65
|
-
readonly maxIterations?: number;
|
|
66
|
-
/** Optional deadline override for sandbox-server execs (unix ms). */
|
|
67
|
-
readonly deadlineMs?: number;
|
|
68
|
-
}
|
|
69
|
-
export interface EphemeralResult {
|
|
70
|
-
readonly text: string;
|
|
71
|
-
readonly durationMs: number;
|
|
72
|
-
readonly stepsUsed: number;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Register the ephemeral workflow with DBOS. Returns the registered callable
|
|
76
|
-
* so the `run_ephemeral` tool can dispatch via `DBOS.startWorkflow`.
|
|
77
|
-
*/
|
|
78
|
-
export declare function registerEphemeralWorkflow(deps: EphemeralDeps): (input: EphemeralWorkflowInput) => Promise<EphemeralResult>;
|
|
79
|
-
/**
|
|
80
|
-
* The executor's seed: its workspace frame, then the caller's ask.
|
|
81
|
-
*
|
|
82
|
-
* An ephemeral run is not scheduled by `executeAnalysis`, so no step briefing is
|
|
83
|
-
* composed for it — and the sandbox system prompt names no paths (it is static
|
|
84
|
-
* per agent type, so the provider's prompt cache can reuse it). The analysis
|
|
85
|
-
* root would otherwise reach the agent nowhere: `run_ephemeral`'s `prompt` is
|
|
86
|
-
* free text authored by the conversation agent.
|
|
87
|
-
*
|
|
88
|
-
* The frame differs from a step's, so this does not reuse `renderWorkspace`:
|
|
89
|
-
* there is no writable directory to name. The read-only tree IS the cwd.
|
|
90
|
-
*/
|
|
91
|
-
export declare function ephemeralSeed(analysisId: string, prompt: string): string;
|
|
92
|
-
/**
|
|
93
|
-
* Run the ephemeral-executor agent against a fresh read-only sandbox.
|
|
94
|
-
* Throws on sandbox start failure; otherwise returns the agent's final
|
|
95
|
-
* text plus timing. Sandbox teardown fires on every terminal path —
|
|
96
|
-
* success, error, cancel.
|
|
97
|
-
*/
|
|
98
|
-
export declare function runEphemeralBody(input: EphemeralWorkflowInput, deps: EphemeralDeps): Promise<EphemeralResult>;
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ephemeral runner — read-only sandbox execution for ad-hoc data
|
|
3
|
-
* exploration, run as a turn-scoped DBOS workflow.
|
|
4
|
-
*
|
|
5
|
-
* The `run_ephemeral` conversation tool authorizes the run at the async
|
|
6
|
-
* edge, starts this workflow, and awaits its result inline within the chat
|
|
7
|
-
* turn. The workflow is "bare": it has no run-event stream, so `emit` is a
|
|
8
|
-
* no-op and live sandbox progress events are dropped. It is never recovered
|
|
9
|
-
* — chat disconnect cancels it (`DBOS.cancelWorkflow`), and a boot-time sweep
|
|
10
|
-
* cancels any `ephemeral:`-prefixed PENDING workflow a dead pod left behind.
|
|
11
|
-
*
|
|
12
|
-
* Lifecycle: create sandbox → build the ephemeral-executor with synthetic
|
|
13
|
-
* step coords (`runId = stepId = "ephemeral"`, the literal the host-managed
|
|
14
|
-
* billing rules key on) → drive `runAgent` over the executor with `durableStep` →
|
|
15
|
-
* final text + step count → teardown the sandbox in `finally` on every
|
|
16
|
-
* terminal path.
|
|
17
|
-
*
|
|
18
|
-
* Read-only is enforced, not aspirational: the executor agent is built with
|
|
19
|
-
* `readOnly: true` (no `write_file`/`edit_file` tools) and its sandbox is
|
|
20
|
-
* provisioned with no read-write mount — only the read-only analysis tree.
|
|
21
|
-
* Container-local `/tmp` stays writable (torn down with the sandbox); nothing
|
|
22
|
-
* persists. The prompt's "you physically cannot write files" is now true.
|
|
23
|
-
*/
|
|
24
|
-
import { DBOS, Error as DBOSErrors } from "@dbos-inc/dbos-sdk";
|
|
25
|
-
import { forSubAgent } from "../auth/types.js";
|
|
26
|
-
import { finalText, runAgent } from "../loop/run-agent.js";
|
|
27
|
-
import { durableStep } from "../loop/run-step.js";
|
|
28
|
-
import { generateExecutionId } from "../sandbox/execution-id.js";
|
|
29
|
-
import { mintSandboxIdentity } from "../sandbox/identity.js";
|
|
30
|
-
import { createEphemeralExecutorAgent } from "../agents/sandbox/ephemeral-executor.js";
|
|
31
|
-
import { createNoopLogger } from "../lib/console-logger.js";
|
|
32
|
-
/** Sub-agent identity — appended to `callPath`, set as `agentId`. */
|
|
33
|
-
export const EPHEMERAL_AGENT_ID = "ephemeral-executor";
|
|
34
|
-
/**
|
|
35
|
-
* Synthetic run/step literal stamped into the agent's step coords.
|
|
36
|
-
* Host-managed billing rules key on this literal to recognize chat-turn
|
|
37
|
-
* ephemeral runs (no `cortex_runs` row, no DBOS stream).
|
|
38
|
-
*/
|
|
39
|
-
const EPHEMERAL_RUN_LITERAL = "ephemeral";
|
|
40
|
-
/** Workflow-id prefix — the boot-time never-recover sweep matches on it. */
|
|
41
|
-
export const EPHEMERAL_WORKFLOW_PREFIX = "ephemeral:";
|
|
42
|
-
/** Default budget — chat-turn-scoped, no recovery, no checkpointing. */
|
|
43
|
-
const DEFAULT_DEADLINE_MS = 120_000;
|
|
44
|
-
/** Ephemeral runs have no planner estimate, so the sandbox box is chosen here
|
|
45
|
-
* explicitly — the policy's `ephemeral` spec when supplied, otherwise this
|
|
46
|
-
* mid-range default; either way clamped to cluster limits at create time. */
|
|
47
|
-
const EPHEMERAL_SANDBOX_RESOURCES = { cpu: 4, memoryGb: 8 };
|
|
48
|
-
/**
|
|
49
|
-
* Register the ephemeral workflow with DBOS. Returns the registered callable
|
|
50
|
-
* so the `run_ephemeral` tool can dispatch via `DBOS.startWorkflow`.
|
|
51
|
-
*/
|
|
52
|
-
export function registerEphemeralWorkflow(deps) {
|
|
53
|
-
return DBOS.registerWorkflow((input) => runEphemeralBody(input, deps), { name: "ephemeral" });
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* The executor's seed: its workspace frame, then the caller's ask.
|
|
57
|
-
*
|
|
58
|
-
* An ephemeral run is not scheduled by `executeAnalysis`, so no step briefing is
|
|
59
|
-
* composed for it — and the sandbox system prompt names no paths (it is static
|
|
60
|
-
* per agent type, so the provider's prompt cache can reuse it). The analysis
|
|
61
|
-
* root would otherwise reach the agent nowhere: `run_ephemeral`'s `prompt` is
|
|
62
|
-
* free text authored by the conversation agent.
|
|
63
|
-
*
|
|
64
|
-
* The frame differs from a step's, so this does not reuse `renderWorkspace`:
|
|
65
|
-
* there is no writable directory to name. The read-only tree IS the cwd.
|
|
66
|
-
*/
|
|
67
|
-
export function ephemeralSeed(analysisId, prompt) {
|
|
68
|
-
const root = `/${analysisId}`;
|
|
69
|
-
return [
|
|
70
|
-
"## Workspace",
|
|
71
|
-
`- Analysis root (read-only): \`${root}\` — inputs at \`${root}/data/inputs/\`, prior runs at \`${root}/runs/\`.`,
|
|
72
|
-
`- The analysis root is also your cwd, and what relative paths resolve against. The sandbox is read-only: there is nowhere to write, so return every result inline.`,
|
|
73
|
-
"",
|
|
74
|
-
prompt,
|
|
75
|
-
].join("\n");
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Run the ephemeral-executor agent against a fresh read-only sandbox.
|
|
79
|
-
* Throws on sandbox start failure; otherwise returns the agent's final
|
|
80
|
-
* text plus timing. Sandbox teardown fires on every terminal path —
|
|
81
|
-
* success, error, cancel.
|
|
82
|
-
*/
|
|
83
|
-
export async function runEphemeralBody(input, deps) {
|
|
84
|
-
const { runSession } = input;
|
|
85
|
-
if (runSession.scope.kind !== "analysis") {
|
|
86
|
-
throw new Error(`runEphemeralBody requires an analysis-scoped session — got ${runSession.scope.kind}`);
|
|
87
|
-
}
|
|
88
|
-
const analysisId = runSession.scope.analysisId;
|
|
89
|
-
// Bound after the scope guard: `analysisId` comes off the session's scope,
|
|
90
|
-
// not the workflow input.
|
|
91
|
-
const logger = (deps.logger ?? createNoopLogger()).named("ephemeral").with({ analysisId });
|
|
92
|
-
const startedAt = performance.now();
|
|
93
|
-
const executionId = generateExecutionId(EPHEMERAL_AGENT_ID);
|
|
94
|
-
const workflowId = DBOS.workflowID ?? `${EPHEMERAL_WORKFLOW_PREFIX}${executionId}`;
|
|
95
|
-
const childSession = forSubAgent(runSession, EPHEMERAL_AGENT_ID);
|
|
96
|
-
// Resolver throw = loud workflow failure, per the workspace-root-resolution contract.
|
|
97
|
-
const workspaceRoot = deps.resolveWorkspaceRoot(analysisId);
|
|
98
|
-
logger.info("starting sandbox", { executionId });
|
|
99
|
-
const sandbox = await deps.sandboxClient.createSandbox({
|
|
100
|
-
runId: EPHEMERAL_RUN_LITERAL,
|
|
101
|
-
stepId: EPHEMERAL_RUN_LITERAL,
|
|
102
|
-
analysisId,
|
|
103
|
-
execId: null,
|
|
104
|
-
childWorkflowId: workflowId,
|
|
105
|
-
resources: deps.resourcePolicy?.ephemeral ?? EPHEMERAL_SANDBOX_RESOURCES,
|
|
106
|
-
// No read-write step mount — only the read-only analysis tree.
|
|
107
|
-
readOnly: true,
|
|
108
|
-
}, mintSandboxIdentity(EPHEMERAL_RUN_LITERAL));
|
|
109
|
-
try {
|
|
110
|
-
// The fallback reads the CHECKPOINTED clock, not `Date.now()`: `awaitExec`
|
|
111
|
-
// gates on this absolute deadline, and its recovery-pull is a durable step,
|
|
112
|
-
// so a wall-clock deadline that grew on replay would shift which loop
|
|
113
|
-
// iteration crosses the deadline and desynchronise the recorded function-ID
|
|
114
|
-
// sequence (see the harness-durable-runtime spec; sandbox-step.ts does the
|
|
115
|
-
// same). `input.deadlineMs`, when present, is already replay-stable.
|
|
116
|
-
const deadlineAbs = input.deadlineMs ?? (await DBOS.now()) + DEFAULT_DEADLINE_MS;
|
|
117
|
-
const nextFunctionId = makeNextFunctionId();
|
|
118
|
-
const sandboxAgentDeps = {
|
|
119
|
-
provider: deps.provider,
|
|
120
|
-
pool: deps.pool,
|
|
121
|
-
sandboxClient: deps.sandboxClient,
|
|
122
|
-
workspaceFs: deps.workspaceFs,
|
|
123
|
-
embedding: deps.embedding,
|
|
124
|
-
model: deps.model,
|
|
125
|
-
bioKeys: deps.bioKeys,
|
|
126
|
-
...(deps.packagesFile ? { packagesFile: deps.packagesFile } : {}),
|
|
127
|
-
...(deps.refStorePath ? { refStorePath: deps.refStorePath } : {}),
|
|
128
|
-
step: {
|
|
129
|
-
sandbox,
|
|
130
|
-
workspaceRoot,
|
|
131
|
-
analysisId,
|
|
132
|
-
runId: EPHEMERAL_RUN_LITERAL,
|
|
133
|
-
stepId: EPHEMERAL_RUN_LITERAL,
|
|
134
|
-
workflowId,
|
|
135
|
-
// Enforced read-only: the executor agent gets no write_file/edit_file
|
|
136
|
-
// tools and the sandbox has no read-write mount. This prefix is not a
|
|
137
|
-
// writable location — it only resolves `execute_command`'s default cwd
|
|
138
|
-
// to the read-only analysis-tree root (`/{analysisId}`), where reads land.
|
|
139
|
-
allowedWritePrefix: workspaceRoot,
|
|
140
|
-
nextFunctionId,
|
|
141
|
-
deadlineMs: () => deadlineAbs,
|
|
142
|
-
},
|
|
143
|
-
};
|
|
144
|
-
const agentDef = createEphemeralExecutorAgent(sandboxAgentDeps);
|
|
145
|
-
const agent = input.maxIterations !== undefined ? { ...agentDef, maxIterations: input.maxIterations } : agentDef;
|
|
146
|
-
const signal = new AbortController().signal;
|
|
147
|
-
const { messages: finalMessages } = await runAgent(agent, [{ role: "user", content: ephemeralSeed(analysisId, input.prompt) }], childSession, {
|
|
148
|
-
provider: deps.provider,
|
|
149
|
-
signal,
|
|
150
|
-
emit: () => { },
|
|
151
|
-
runStep: durableStep,
|
|
152
|
-
isFatalLoopError: (err) => err instanceof DBOSErrors.DBOSWorkflowCancelledError,
|
|
153
|
-
});
|
|
154
|
-
const text = finalText(finalMessages);
|
|
155
|
-
const stepsUsed = countAssistantTurns(finalMessages);
|
|
156
|
-
const durationMs = Math.round(performance.now() - startedAt);
|
|
157
|
-
logger.info("completed", { executionId, stepsUsed, durationMs });
|
|
158
|
-
return { text, stepsUsed, durationMs };
|
|
159
|
-
}
|
|
160
|
-
catch (err) {
|
|
161
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
162
|
-
logger.error("failed", { executionId, err: message });
|
|
163
|
-
throw err;
|
|
164
|
-
}
|
|
165
|
-
finally {
|
|
166
|
-
try {
|
|
167
|
-
await deps.sandboxClient.teardown(sandbox);
|
|
168
|
-
}
|
|
169
|
-
catch (teardownErr) {
|
|
170
|
-
// Teardown is idempotent — "already gone" is success. A failure here
|
|
171
|
-
// is best-effort logged so the chat turn doesn't fail on cleanup.
|
|
172
|
-
logger.warn("teardown failed (non-fatal)", { executionId, ...logger.errorFields(teardownErr) });
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
/** Per-call function-id minter — replay-deterministic. */
|
|
177
|
-
function makeNextFunctionId() {
|
|
178
|
-
let n = 0;
|
|
179
|
-
return () => `fn-${(n++).toString(36)}`;
|
|
180
|
-
}
|
|
181
|
-
/** The agent's final assistant turn is the `stepsUsed` proxy — every loop
|
|
182
|
-
* iteration produces one assistant message. */
|
|
183
|
-
function countAssistantTurns(messages) {
|
|
184
|
-
let n = 0;
|
|
185
|
-
for (const m of messages)
|
|
186
|
-
if (m.role === "assistant")
|
|
187
|
-
n++;
|
|
188
|
-
return n;
|
|
189
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const ephemeralExecutorPrompt = "# Ephemeral Executor\n\nYou are a read-only compute agent. You execute scripts on the user's data\nand return the results. You **cannot create or save files** \u2014 your sandbox\nis fully read-only.\n\n## What You Do\n\n1. Read data files to understand their structure\n2. Write and execute R or Python scripts via `execute_command`\n3. Return the script output (tables, statistics, plot data) in your response\n\n## Constraints\n\n- **Read-only**: You physically cannot write files. Do not attempt to save\n output to disk. All results must be returned in your text response.\n- **Inline output**: Print results to stdout. For plots, use base64 encoding\n and print the encoded string so the caller can display it.\n- **Structured responses**: When returning tabular data, format as markdown\n tables or JSON arrays. When returning statistics, use clear labeled output.\n\n## Script Execution Pattern\n\nFor Python:\n```\nexecute_command python3 -c \"\nimport pandas as pd\ndf = pd.read_csv('/{resourceId}/data/inputs/{fileId}/data.csv')\nprint(df.describe().to_markdown())\n\"\n```\n\nFor R:\n```\nexecute_command Rscript -e \"\ndf <- read.csv('/{resourceId}/data/inputs/{fileId}/data.csv')\nsummary(df)\n\"\n```\n\nFor plots (base64):\n```\nexecute_command python3 -c \"\nimport matplotlib\nmatplotlib.use('Agg')\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport base64, io\n\ndf = pd.read_csv('...')\nfig, ax = plt.subplots()\ndf.plot(ax=ax)\nbuf = io.BytesIO()\nfig.savefig(buf, format='png')\nprint(base64.b64encode(buf.getvalue()).decode())\n\"\n```\n\n## Do NOT\n\n- Attempt to write files \u2014 it will fail silently or error\n- Install packages at runtime\n- Return raw binary data without base64 encoding\n- Guess data structure without inspecting the file first\n- Run long-running computations (you have a short timeout)\n";
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
export const ephemeralExecutorPrompt = `# Ephemeral Executor
|
|
2
|
-
|
|
3
|
-
You are a read-only compute agent. You execute scripts on the user's data
|
|
4
|
-
and return the results. You **cannot create or save files** — your sandbox
|
|
5
|
-
is fully read-only.
|
|
6
|
-
|
|
7
|
-
## What You Do
|
|
8
|
-
|
|
9
|
-
1. Read data files to understand their structure
|
|
10
|
-
2. Write and execute R or Python scripts via \`execute_command\`
|
|
11
|
-
3. Return the script output (tables, statistics, plot data) in your response
|
|
12
|
-
|
|
13
|
-
## Constraints
|
|
14
|
-
|
|
15
|
-
- **Read-only**: You physically cannot write files. Do not attempt to save
|
|
16
|
-
output to disk. All results must be returned in your text response.
|
|
17
|
-
- **Inline output**: Print results to stdout. For plots, use base64 encoding
|
|
18
|
-
and print the encoded string so the caller can display it.
|
|
19
|
-
- **Structured responses**: When returning tabular data, format as markdown
|
|
20
|
-
tables or JSON arrays. When returning statistics, use clear labeled output.
|
|
21
|
-
|
|
22
|
-
## Script Execution Pattern
|
|
23
|
-
|
|
24
|
-
For Python:
|
|
25
|
-
\`\`\`
|
|
26
|
-
execute_command python3 -c "
|
|
27
|
-
import pandas as pd
|
|
28
|
-
df = pd.read_csv('/{resourceId}/data/inputs/{fileId}/data.csv')
|
|
29
|
-
print(df.describe().to_markdown())
|
|
30
|
-
"
|
|
31
|
-
\`\`\`
|
|
32
|
-
|
|
33
|
-
For R:
|
|
34
|
-
\`\`\`
|
|
35
|
-
execute_command Rscript -e "
|
|
36
|
-
df <- read.csv('/{resourceId}/data/inputs/{fileId}/data.csv')
|
|
37
|
-
summary(df)
|
|
38
|
-
"
|
|
39
|
-
\`\`\`
|
|
40
|
-
|
|
41
|
-
For plots (base64):
|
|
42
|
-
\`\`\`
|
|
43
|
-
execute_command python3 -c "
|
|
44
|
-
import matplotlib
|
|
45
|
-
matplotlib.use('Agg')
|
|
46
|
-
import matplotlib.pyplot as plt
|
|
47
|
-
import pandas as pd
|
|
48
|
-
import base64, io
|
|
49
|
-
|
|
50
|
-
df = pd.read_csv('...')
|
|
51
|
-
fig, ax = plt.subplots()
|
|
52
|
-
df.plot(ax=ax)
|
|
53
|
-
buf = io.BytesIO()
|
|
54
|
-
fig.savefig(buf, format='png')
|
|
55
|
-
print(base64.b64encode(buf.getvalue()).decode())
|
|
56
|
-
"
|
|
57
|
-
\`\`\`
|
|
58
|
-
|
|
59
|
-
## Do NOT
|
|
60
|
-
|
|
61
|
-
- Attempt to write files — it will fail silently or error
|
|
62
|
-
- Install packages at runtime
|
|
63
|
-
- Return raw binary data without base64 encoding
|
|
64
|
-
- Guess data structure without inspecting the file first
|
|
65
|
-
- Run long-running computations (you have a short timeout)
|
|
66
|
-
`;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* checkSafetyPanel — look up identifiers against the curated
|
|
3
|
-
* secondary-pharmacology safety target panel.
|
|
4
|
-
*/
|
|
5
|
-
export declare const checkSafetyPanelTool: import("../define-tool.js").Tool<{
|
|
6
|
-
identifiers: string[];
|
|
7
|
-
identifier_type: "auto" | "gene_symbol" | "uniprot" | "chembl_id";
|
|
8
|
-
filter_organ?: "hematologic" | "metabolic" | "immune" | "hepatic" | "cns" | "renal" | "respiratory" | "cardiac" | "gi" | undefined;
|
|
9
|
-
}, {
|
|
10
|
-
matches: {
|
|
11
|
-
input: string;
|
|
12
|
-
matched_entry: {
|
|
13
|
-
chembl_id: string;
|
|
14
|
-
gene_symbol: string;
|
|
15
|
-
uniprot: string;
|
|
16
|
-
name: string;
|
|
17
|
-
organ_system: "hematologic" | "metabolic" | "immune" | "hepatic" | "cns" | "renal" | "respiratory" | "cardiac" | "gi";
|
|
18
|
-
clinical_consequence: string;
|
|
19
|
-
severity: "high" | "medium" | "low";
|
|
20
|
-
references: string[];
|
|
21
|
-
ensembl_gene_id?: string | undefined;
|
|
22
|
-
} | null;
|
|
23
|
-
}[];
|
|
24
|
-
summary: {
|
|
25
|
-
total_input: number;
|
|
26
|
-
matched: number;
|
|
27
|
-
by_severity: {
|
|
28
|
-
high: number;
|
|
29
|
-
medium: number;
|
|
30
|
-
low: number;
|
|
31
|
-
};
|
|
32
|
-
by_organ: Record<string, number>;
|
|
33
|
-
};
|
|
34
|
-
panel_version: string;
|
|
35
|
-
}>;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* checkSafetyPanel — look up identifiers against the curated
|
|
3
|
-
* secondary-pharmacology safety target panel.
|
|
4
|
-
*/
|
|
5
|
-
import { ok } from "neverthrow";
|
|
6
|
-
import { z } from "zod";
|
|
7
|
-
import { CHEMBL_RE, ORGAN_SYSTEMS, SafetyPanelFileSchema, UNIPROT_RE } from "../../data/safety-panel-schema.js";
|
|
8
|
-
import panelData from "../../data/safety-panel.json" with { type: "json" };
|
|
9
|
-
import { defineTool } from "../define-tool.js";
|
|
10
|
-
const PANEL = SafetyPanelFileSchema.parse(panelData);
|
|
11
|
-
const BY_CHEMBL = new Map(PANEL.targets.map((t) => [t.chembl_id, t]));
|
|
12
|
-
const BY_GENE = new Map(PANEL.targets.map((t) => [t.gene_symbol, t]));
|
|
13
|
-
const BY_UNIPROT = new Map(PANEL.targets.map((t) => [t.uniprot, t]));
|
|
14
|
-
function detectType(id) {
|
|
15
|
-
if (CHEMBL_RE.test(id))
|
|
16
|
-
return "chembl_id";
|
|
17
|
-
if (UNIPROT_RE.test(id))
|
|
18
|
-
return "uniprot";
|
|
19
|
-
return "gene_symbol";
|
|
20
|
-
}
|
|
21
|
-
function lookup(id, type) {
|
|
22
|
-
switch (type) {
|
|
23
|
-
case "chembl_id":
|
|
24
|
-
return BY_CHEMBL.get(id) ?? null;
|
|
25
|
-
case "gene_symbol":
|
|
26
|
-
return BY_GENE.get(id.toUpperCase()) ?? null;
|
|
27
|
-
case "uniprot":
|
|
28
|
-
return BY_UNIPROT.get(id) ?? null;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
export const checkSafetyPanelTool = defineTool({
|
|
32
|
-
id: "check_safety_panel",
|
|
33
|
-
description: "Look up identifiers (ChEMBL ID, gene symbol, or UniProt accession) against the curated " +
|
|
34
|
-
"secondary-pharmacology safety target panel. Returns organ system, severity, and clinical " +
|
|
35
|
-
"consequence for each matched target. Use as a fast first-pass off-target liability check; " +
|
|
36
|
-
"for comprehensive assessment also call get-target-safety and search-toxcast.",
|
|
37
|
-
inputSchema: z.object({
|
|
38
|
-
identifiers: z.array(z.string().min(1)).min(0).max(200).describe("0-200 identifiers (ChEMBL IDs, gene symbols, or UniProt accessions)."),
|
|
39
|
-
identifier_type: z
|
|
40
|
-
.enum(["chembl_id", "gene_symbol", "uniprot", "auto"])
|
|
41
|
-
.default("auto")
|
|
42
|
-
.describe("Identifier interpretation. 'auto' detects per-input."),
|
|
43
|
-
filter_organ: z.enum(ORGAN_SYSTEMS).optional().describe("Restrict matches to this organ system."),
|
|
44
|
-
}),
|
|
45
|
-
execute: async ({ identifiers, identifier_type = "auto", filter_organ }) => {
|
|
46
|
-
const matches = identifiers.map((input) => {
|
|
47
|
-
const type = identifier_type === "auto" ? detectType(input) : identifier_type;
|
|
48
|
-
let entry = lookup(input, type);
|
|
49
|
-
if (entry && filter_organ && entry.organ_system !== filter_organ) {
|
|
50
|
-
entry = null;
|
|
51
|
-
}
|
|
52
|
-
return { input, matched_entry: entry };
|
|
53
|
-
});
|
|
54
|
-
const bySeverity = { high: 0, medium: 0, low: 0 };
|
|
55
|
-
const byOrgan = {};
|
|
56
|
-
let matched = 0;
|
|
57
|
-
for (const m of matches) {
|
|
58
|
-
if (!m.matched_entry)
|
|
59
|
-
continue;
|
|
60
|
-
matched++;
|
|
61
|
-
bySeverity[m.matched_entry.severity]++;
|
|
62
|
-
const o = m.matched_entry.organ_system;
|
|
63
|
-
byOrgan[o] = (byOrgan[o] ?? 0) + 1;
|
|
64
|
-
}
|
|
65
|
-
return ok({
|
|
66
|
-
matches,
|
|
67
|
-
summary: {
|
|
68
|
-
total_input: identifiers.length,
|
|
69
|
-
matched,
|
|
70
|
-
by_severity: bySeverity,
|
|
71
|
-
by_organ: byOrgan,
|
|
72
|
-
},
|
|
73
|
-
panel_version: PANEL.panel_version,
|
|
74
|
-
});
|
|
75
|
-
},
|
|
76
|
-
});
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* getImpcKoProfile tool — mouse knockout phenotype profile via IMPC Solr.
|
|
3
|
-
*/
|
|
4
|
-
import { buildViabilityCalls, derivedViability, parsePhenotypeResponse } from "../lib/impc-client.js";
|
|
5
|
-
export type { PhenotypeProfile, ViabilityCall, ViabilityCategory } from "../lib/impc-client.js";
|
|
6
|
-
export { buildViabilityCalls, derivedViability, parsePhenotypeResponse };
|
|
7
|
-
export declare const getImpcKoProfileTool: import("../define-tool.js").Tool<{
|
|
8
|
-
geneSymbol: string;
|
|
9
|
-
}, import("../lib/impc-client.js").KoPhenotypeProfile>;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* getImpcKoProfile tool — mouse knockout phenotype profile via IMPC Solr.
|
|
3
|
-
*/
|
|
4
|
-
import { ok } from "neverthrow";
|
|
5
|
-
import { z } from "zod";
|
|
6
|
-
import { defineTool } from "../define-tool.js";
|
|
7
|
-
import { buildViabilityCalls, derivedViability, getKoPhenotypeProfile, parsePhenotypeResponse } from "../lib/impc-client.js";
|
|
8
|
-
export { buildViabilityCalls, derivedViability, parsePhenotypeResponse };
|
|
9
|
-
export const getImpcKoProfileTool = defineTool({
|
|
10
|
-
id: "get_impc_ko_profile",
|
|
11
|
-
description: "Get the mouse-knockout phenotype profile for a gene from IMPC — the in-vivo loss-of-function evidence for target tractability and essentiality " +
|
|
12
|
-
"('what happens to PAX5 knockout mice?', 'is loss of CASP8 lethal?'). " +
|
|
13
|
-
"Takes a human gene symbol and maps it to the mouse ortholog itself. Returns a top-line pre-weaning viability call (lethal_pre_weaning | subviable | viable | null) with its " +
|
|
14
|
-
"per-zygosity breakdown, the significant MP phenotype terms ordered by best p-value, the affected organ systems ranked by phenotype count, and a sex-dimorphism flag. " +
|
|
15
|
-
"An all-empty profile (null mouseMarkerSymbol, null viability, no phenotype terms) means the gene has not been IMPC-phenotyped — common and valid. Do NOT retry on empty output.",
|
|
16
|
-
inputSchema: z.object({
|
|
17
|
-
geneSymbol: z
|
|
18
|
-
.string()
|
|
19
|
-
.min(1)
|
|
20
|
-
.describe("HUMAN gene symbol, e.g. 'BRCA1' — one gene per call. The mouse ortholog is resolved internally; do not pass a mouse symbol or an MGI ID."),
|
|
21
|
-
}),
|
|
22
|
-
execute: async ({ geneSymbol }) => ok(await getKoPhenotypeProfile(geneSymbol)),
|
|
23
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lookupGoTerm — look up Gene Ontology terms via the QuickGO API (EBI).
|
|
3
|
-
*
|
|
4
|
-
* Supports direct ID lookup, keyword search, and gene annotation retrieval.
|
|
5
|
-
* Multiple modes can be combined in a single call.
|
|
6
|
-
*/
|
|
7
|
-
interface GoTerm {
|
|
8
|
-
id: string;
|
|
9
|
-
name: string;
|
|
10
|
-
definition?: string;
|
|
11
|
-
aspect?: string;
|
|
12
|
-
}
|
|
13
|
-
interface GoAnnotation {
|
|
14
|
-
geneProductId: string;
|
|
15
|
-
goId: string;
|
|
16
|
-
goName: string;
|
|
17
|
-
aspect?: string;
|
|
18
|
-
evidenceCode?: string;
|
|
19
|
-
qualifier?: string;
|
|
20
|
-
}
|
|
21
|
-
export declare const lookupGoTermTool: import("../define-tool.js").Tool<{
|
|
22
|
-
limit: number;
|
|
23
|
-
goId?: string | undefined;
|
|
24
|
-
query?: string | undefined;
|
|
25
|
-
geneProductId?: string | undefined;
|
|
26
|
-
taxonId?: number | undefined;
|
|
27
|
-
}, {
|
|
28
|
-
terms: GoTerm[] | undefined;
|
|
29
|
-
annotations: GoAnnotation[] | undefined;
|
|
30
|
-
}>;
|
|
31
|
-
export {};
|