@inflexa-ai/harness 0.1.1 → 0.2.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 +12 -11
- package/dist/agents/conversation-agent.js +30 -33
- package/dist/agents/report-builder.js +2 -1
- package/dist/agents/sandbox/bulk-transcriptomics-agent.js +1 -1
- package/dist/agents/sandbox/cheminformatics-agent.js +1 -19
- package/dist/agents/sandbox/chromatin-agent.js +1 -10
- package/dist/agents/sandbox/dna-methylation-agent.js +1 -10
- package/dist/agents/sandbox/drug-repurposing-agent.js +4 -14
- package/dist/agents/sandbox/enrichment-agent.js +1 -10
- package/dist/agents/sandbox/ephemeral-executor.js +1 -10
- package/dist/agents/sandbox/genomic-variant-agent.js +1 -3
- package/dist/agents/sandbox/immune-profiling-agent.js +1 -13
- package/dist/agents/sandbox/metabolomics-agent.js +1 -1
- package/dist/agents/sandbox/microbiome-agent.js +1 -1
- package/dist/agents/sandbox/multi-omics-integration-agent.js +1 -12
- package/dist/agents/sandbox/multimodal-sc-agent.js +1 -1
- package/dist/agents/sandbox/network-agent.js +1 -10
- package/dist/agents/sandbox/pkpd-clinical-response-agent.js +2 -8
- package/dist/agents/sandbox/proteomics-agent.js +1 -1
- package/dist/agents/sandbox/scientific-executor.js +1 -10
- package/dist/agents/sandbox/shared.d.ts +17 -6
- package/dist/agents/sandbox/shared.js +49 -38
- package/dist/agents/sandbox/single-cell-agent.js +1 -1
- package/dist/agents/sandbox/spatial-omics-agent.js +1 -1
- package/dist/agents/sandbox/statistical-modeling-agent.js +1 -1
- package/dist/agents/sandbox/translational-safety-agent.js +3 -9
- package/dist/agents/sandbox/types.d.ts +1 -1
- package/dist/agents/system-prompt.d.ts +37 -11
- package/dist/agents/system-prompt.js +35 -12
- package/dist/app/data-profile-orientation.d.ts +34 -0
- package/dist/app/data-profile-orientation.js +117 -0
- package/dist/contracts/schemas/chat-parts.d.ts +9 -9
- package/dist/execution/artifact-metadata.js +2 -1
- package/dist/execution/ephemeral-runner.d.ts +13 -0
- package/dist/execution/ephemeral-runner.js +23 -1
- package/dist/execution/run-synthesis.js +20 -19
- package/dist/execution/step-summary.js +2 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +19 -5
- package/dist/loop/__fixtures__/scripted-provider.d.ts +2 -2
- package/dist/loop/__fixtures__/scripted-provider.js +2 -1
- package/dist/loop/metrics.d.ts +33 -1
- package/dist/loop/metrics.js +56 -2
- package/dist/loop/run-agent.d.ts +13 -1
- package/dist/loop/run-agent.js +19 -4
- package/dist/memory/card-builders.d.ts +8 -1
- package/dist/memory/card-builders.js +20 -3
- package/dist/memory/reconstruct-cards.js +4 -3
- package/dist/memory/thread-history.d.ts +27 -2
- package/dist/memory/thread-history.js +45 -5
- package/dist/memory/working-memory.d.ts +93 -10
- package/dist/memory/working-memory.js +220 -84
- package/dist/prompts/SOUL.d.ts +22 -9
- package/dist/prompts/SOUL.js +56 -37
- package/dist/prompts/analogical-reasoner.d.ts +1 -1
- package/dist/prompts/analogical-reasoner.js +2 -2
- package/dist/prompts/briefing.d.ts +100 -0
- package/dist/prompts/briefing.js +166 -0
- package/dist/prompts/conversation.d.ts +1 -1
- package/dist/prompts/conversation.js +94 -440
- package/dist/prompts/literature-reviewer.d.ts +1 -1
- package/dist/prompts/literature-reviewer.js +10 -10
- package/dist/prompts/planner.js +28 -59
- package/dist/prompts/report-builder.d.ts +1 -1
- package/dist/prompts/report-builder.js +71 -24
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +2 -7
- package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/cheminformatics-agent.js +11 -15
- package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
- package/dist/prompts/sandbox/chromatin-agent.js +3 -7
- package/dist/prompts/sandbox/data-profiler.d.ts +1 -1
- package/dist/prompts/sandbox/data-profiler.js +13 -8
- package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
- package/dist/prompts/sandbox/dna-methylation-agent.js +2 -7
- package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
- package/dist/prompts/sandbox/drug-repurposing-agent.js +15 -16
- package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
- package/dist/prompts/sandbox/enrichment-agent.js +2 -9
- package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
- package/dist/prompts/sandbox/genomic-variant-agent.js +2 -6
- package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/immune-profiling-agent.js +3 -8
- package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/metabolomics-agent.js +1 -7
- package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
- package/dist/prompts/sandbox/microbiome-agent.js +2 -7
- package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.js +2 -8
- package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multimodal-sc-agent.js +2 -7
- package/dist/prompts/sandbox/network-agent.d.ts +1 -1
- package/dist/prompts/sandbox/network-agent.js +2 -7
- package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/proteomics-agent.js +2 -9
- package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
- package/dist/prompts/sandbox/single-cell-agent.js +2 -9
- package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/spatial-omics-agent.js +3 -6
- package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/statistical-modeling-agent.js +2 -7
- package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.js +13 -14
- package/dist/prompts/sandbox-standards.d.ts +22 -14
- package/dist/prompts/sandbox-standards.js +91 -71
- package/dist/prompts/synthesis-agent.d.ts +1 -1
- package/dist/prompts/synthesis-agent.js +33 -131
- package/dist/provenance/collector.js +1 -1
- package/dist/providers/ai-sdk.js +31 -4
- package/dist/providers/prompt-cache.d.ts +74 -0
- package/dist/providers/prompt-cache.js +77 -0
- package/dist/providers/types.d.ts +33 -0
- package/dist/reference-data/catalog.d.ts +131 -0
- package/dist/reference-data/catalog.js +348 -0
- package/dist/reference-data/receipt.d.ts +41 -0
- package/dist/reference-data/receipt.js +40 -0
- package/dist/schemas/data-profile-schemas.js +5 -3
- package/dist/schemas/plan-schemas.d.ts +21 -21
- package/dist/schemas/plan-schemas.js +9 -3
- package/dist/schemas/run-synthesis.d.ts +8 -4
- package/dist/schemas/run-synthesis.js +92 -56
- package/dist/schemas/validate-plan.js +1 -1
- package/dist/schemas/workflow-state.d.ts +7 -1
- package/dist/schemas/workflow-state.js +33 -19
- package/dist/state/artifacts.d.ts +13 -0
- package/dist/state/artifacts.js +27 -0
- package/dist/state/data-profile.d.ts +64 -5
- package/dist/state/index.d.ts +3 -3
- package/dist/state/index.js +1 -1
- package/dist/tasks/data-profile.d.ts +20 -2
- package/dist/tasks/data-profile.js +71 -22
- package/dist/tools/bio/chembl.d.ts +38 -0
- package/dist/tools/bio/chembl.js +138 -0
- package/dist/tools/bio/comptox.d.ts +50 -0
- package/dist/tools/bio/comptox.js +149 -0
- package/dist/tools/bio/get-impc-ko-profile.js +9 -6
- package/dist/tools/bio/index.d.ts +5 -17
- package/dist/tools/bio/index.js +5 -17
- package/dist/tools/bio/keys.d.ts +14 -9
- package/dist/tools/bio/keys.js +16 -16
- package/dist/tools/bio/opentargets.d.ts +38 -0
- package/dist/tools/bio/opentargets.js +89 -0
- package/dist/tools/bio/pubchem.d.ts +29 -0
- package/dist/tools/bio/pubchem.js +92 -0
- package/dist/tools/bio/pubmed.d.ts +51 -0
- package/dist/tools/bio/pubmed.js +100 -0
- package/dist/tools/bio/search-bgee-expression.js +12 -6
- package/dist/tools/bio/search-clinical-trials.js +16 -5
- package/dist/tools/bio/search-faers.js +8 -4
- package/dist/tools/bio/search-geo-datasets.js +20 -6
- package/dist/tools/bio/search-gwas-catalog.d.ts +1 -1
- package/dist/tools/bio/search-pharmgkb.js +10 -4
- package/dist/tools/display/index.d.ts +1 -0
- package/dist/tools/display/index.js +1 -0
- package/dist/tools/display/normalize-echart-spec.d.ts +61 -0
- package/dist/tools/display/normalize-echart-spec.js +211 -0
- package/dist/tools/display/show-user.d.ts +6 -1
- package/dist/tools/display/show-user.js +25 -12
- package/dist/tools/execute-plan.js +5 -2
- package/dist/tools/iterate-report.d.ts +168 -118
- package/dist/tools/iterate-report.js +334 -96
- package/dist/tools/lib/chembl-client.d.ts +12 -0
- package/dist/tools/lib/chembl-client.js +127 -0
- package/dist/tools/lib/ctx-ops.d.ts +224 -0
- package/dist/tools/lib/ctx-ops.js +450 -0
- package/dist/tools/lib/iuphar-client.js +10 -1
- package/dist/tools/lib/openfda-client.js +11 -3
- package/dist/tools/lib/pathway-client.js +10 -4
- package/dist/tools/lib/pubchem-ops.d.ts +74 -0
- package/dist/tools/lib/pubchem-ops.js +224 -0
- package/dist/tools/memory/update-working-memory.d.ts +45 -7
- package/dist/tools/memory/update-working-memory.js +111 -41
- package/dist/tools/report/index.d.ts +3 -2
- package/dist/tools/report/index.js +3 -2
- package/dist/tools/research/generate-analogy-report.js +25 -12
- package/dist/tools/research/generate-plan.d.ts +12 -5
- package/dist/tools/research/generate-plan.js +168 -37
- package/dist/tools/research/index.d.ts +1 -0
- package/dist/tools/research/index.js +1 -0
- package/dist/tools/research/inspect-data-profile.d.ts +85 -0
- package/dist/tools/research/inspect-data-profile.js +161 -0
- package/dist/tools/research/literature-reviewer.js +3 -4
- package/dist/tools/sandbox/list-available-packages.d.ts +79 -5
- package/dist/tools/sandbox/list-available-packages.js +152 -10
- package/dist/tools/sandbox/list-available-refs.d.ts +141 -5
- package/dist/tools/sandbox/list-available-refs.js +647 -134
- package/dist/tools/sandbox/report-blocker.d.ts +39 -9
- package/dist/tools/sandbox/report-blocker.js +43 -20
- package/dist/tools/workspace/read-file.js +4 -5
- package/dist/tools/workspace/run-exec.d.ts +4 -4
- package/dist/tools/workspace/run-exec.js +4 -4
- package/dist/tools/workspace/show-file.js +10 -6
- package/dist/tools/workspace/show-plan.js +12 -6
- package/dist/tools/workspace/workspace-search.d.ts +1 -1
- package/dist/tools/workspace/workspace-search.js +11 -5
- package/dist/workflows/execute-analysis.d.ts +43 -4
- package/dist/workflows/execute-analysis.js +107 -6
- package/dist/workflows/target-assessment/lib/citation-validator.js +2 -2
- package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.js +2 -1
- package/dist/workspace/paths.d.ts +2 -2
- package/dist/workspace/paths.js +2 -2
- package/package.json +33 -33
- package/dist/execution/filesystem-artifact-registry.d.ts +0 -57
- package/dist/execution/filesystem-artifact-registry.js +0 -92
- package/dist/lib/identifiers.d.ts +0 -8
- package/dist/lib/identifiers.js +0 -10
- package/dist/lib/mime-detect.d.ts +0 -17
- package/dist/lib/mime-detect.js +0 -29
- package/dist/lib/streamed-download.d.ts +0 -28
- package/dist/lib/streamed-download.js +0 -111
- package/dist/lib/trace-context.d.ts +0 -11
- package/dist/lib/trace-context.js +0 -49
- package/dist/providers/llm-capabilities.d.ts +0 -33
- package/dist/providers/llm-capabilities.js +0 -58
- package/dist/schemas/render-step-prompt.d.ts +0 -32
- package/dist/schemas/render-step-prompt.js +0 -76
- package/dist/tools/bio/find-approval-precedent.d.ts +0 -32
- package/dist/tools/bio/find-approval-precedent.js +0 -72
- package/dist/tools/bio/get-article-details.d.ts +0 -11
- package/dist/tools/bio/get-article-details.js +0 -20
- package/dist/tools/bio/get-article-full-text.d.ts +0 -19
- package/dist/tools/bio/get-article-full-text.js +0 -32
- package/dist/tools/bio/get-bioactivity.d.ts +0 -11
- package/dist/tools/bio/get-bioactivity.js +0 -23
- package/dist/tools/bio/get-drug-info.d.ts +0 -9
- package/dist/tools/bio/get-drug-info.js +0 -22
- package/dist/tools/bio/get-mechanism.d.ts +0 -8
- package/dist/tools/bio/get-mechanism.js +0 -18
- package/dist/tools/bio/get-pubchem-assays.d.ts +0 -22
- package/dist/tools/bio/get-pubchem-assays.js +0 -107
- package/dist/tools/bio/get-pubchem-cross-refs.d.ts +0 -15
- package/dist/tools/bio/get-pubchem-cross-refs.js +0 -68
- package/dist/tools/bio/get-target-safety.d.ts +0 -18
- package/dist/tools/bio/get-target-safety.js +0 -26
- package/dist/tools/bio/search-compounds.d.ts +0 -22
- package/dist/tools/bio/search-compounds.js +0 -160
- package/dist/tools/bio/search-ctx-chemical.d.ts +0 -50
- package/dist/tools/bio/search-ctx-chemical.js +0 -130
- package/dist/tools/bio/search-ctx-exposure.d.ts +0 -55
- package/dist/tools/bio/search-ctx-exposure.js +0 -176
- package/dist/tools/bio/search-ctx-hazard.d.ts +0 -111
- package/dist/tools/bio/search-ctx-hazard.js +0 -178
- package/dist/tools/bio/search-opentargets.d.ts +0 -11
- package/dist/tools/bio/search-opentargets.js +0 -25
- package/dist/tools/bio/search-pubchem-compound.d.ts +0 -26
- package/dist/tools/bio/search-pubchem-compound.js +0 -110
- package/dist/tools/bio/search-pubmed.d.ts +0 -17
- package/dist/tools/bio/search-pubmed.js +0 -31
- package/dist/tools/bio/search-targets.d.ts +0 -9
- package/dist/tools/bio/search-targets.js +0 -20
- package/dist/tools/bio/search-toxcast.d.ts +0 -36
- package/dist/tools/bio/search-toxcast.js +0 -141
- package/dist/workflows/register-workflows.d.ts +0 -51
- package/dist/workflows/register-workflows.js +0 -48
- package/dist/workflows/resume-execute-analysis.d.ts +0 -70
- package/dist/workflows/resume-execute-analysis.js +0 -80
- package/dist/workflows/target-assessment/correction-loop.d.ts +0 -45
- package/dist/workflows/target-assessment/correction-loop.js +0 -62
- package/dist/workflows/target-assessment/steps/phase0-resolve.d.ts +0 -71
- package/dist/workflows/target-assessment/steps/phase0-resolve.js +0 -21
- package/dist/workflows/target-assessment/steps/phase1-aggregate.d.ts +0 -1018
- package/dist/workflows/target-assessment/steps/phase1-aggregate.js +0 -25
- package/dist/workspace/mount-strategy.d.ts +0 -50
- package/dist/workspace/mount-strategy.js +0 -67
- package/dist/workspace/provenance-collector.d.ts +0 -34
- package/dist/workspace/provenance-collector.js +0 -16
- package/dist/workspace/workspace-paths.d.ts +0 -26
- package/dist/workspace/workspace-paths.js +0 -31
|
@@ -1,7 +1,81 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* listAvailablePackages —
|
|
2
|
+
* listAvailablePackages — query the R/Python/CLI/Node packages available in the
|
|
3
|
+
* sandbox.
|
|
4
|
+
*
|
|
5
|
+
* The data source is `/mnt/libs/current/packages.txt`, assembled by the
|
|
6
|
+
* library-store build (see the lib-store-build spec). Its shape is fixed by the
|
|
7
|
+
* producers (`scripts/lib-store-common.sh`, `images/sandbox-python/inflexa-libs-refresh`):
|
|
8
|
+
* two `#` advisory lines, then one `## <Section>` heading per language track
|
|
9
|
+
* followed by that track's packages as a single comma-separated line.
|
|
10
|
+
*
|
|
11
|
+
* # Available packages in the sandbox environment.
|
|
12
|
+
* # Do NOT attempt to install packages — ...
|
|
13
|
+
*
|
|
14
|
+
* ## R (CRAN)
|
|
15
|
+
* Seurat, dplyr, ggplot2, ...
|
|
16
|
+
*
|
|
17
|
+
* ## Python (pip)
|
|
18
|
+
* anndata, scanpy, ...
|
|
19
|
+
*
|
|
20
|
+
* The file carries **names only — there are no version strings in it**, so this
|
|
21
|
+
* tool reports presence and language track and cannot report a version.
|
|
3
22
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
23
|
+
/** One language track of the store, in `packages.txt` section order. */
|
|
24
|
+
export interface Section {
|
|
25
|
+
/** The section heading verbatim, e.g. `R (CRAN)`, `Python (pip)`. */
|
|
26
|
+
readonly title: string;
|
|
27
|
+
readonly packages: readonly string[];
|
|
28
|
+
}
|
|
29
|
+
/** One `names` lookup: present + canonical spelling + track, or absent. */
|
|
30
|
+
export type CheckedPackage = {
|
|
31
|
+
readonly requested: string;
|
|
32
|
+
readonly present: true;
|
|
33
|
+
readonly name: string;
|
|
34
|
+
readonly section: string;
|
|
35
|
+
} | {
|
|
36
|
+
readonly requested: string;
|
|
37
|
+
readonly present: false;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Three shapes, one per call path: the store is unmounted; a `names` presence
|
|
41
|
+
* check; a (possibly filtered) listing bounded by `limit`, whose `total` and
|
|
42
|
+
* `hasMore` make truncation explicit.
|
|
43
|
+
*/
|
|
44
|
+
export type PackagesResult = {
|
|
45
|
+
readonly available: false;
|
|
46
|
+
readonly content: string;
|
|
47
|
+
} | {
|
|
48
|
+
readonly available: true;
|
|
49
|
+
readonly checked: readonly CheckedPackage[];
|
|
50
|
+
} | {
|
|
51
|
+
readonly available: true;
|
|
52
|
+
readonly total: number;
|
|
53
|
+
readonly returned: number;
|
|
54
|
+
readonly hasMore: boolean;
|
|
55
|
+
readonly content: string;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Parse `packages.txt` into its sections. `#` lines are the advisory header,
|
|
59
|
+
* `## X` opens a section, and every other non-empty line contributes
|
|
60
|
+
* comma-separated package names to the open section. Unknown section headings
|
|
61
|
+
* are preserved as-is — a downstream image may add its own track.
|
|
62
|
+
*/
|
|
63
|
+
export declare function parsePackagesFile(content: string): Section[];
|
|
64
|
+
/** The tool's input, as parsed from `inputSchema`. */
|
|
65
|
+
export interface PackagesQuery {
|
|
66
|
+
readonly names?: readonly string[];
|
|
67
|
+
readonly query?: string;
|
|
68
|
+
readonly language?: "r" | "python" | "cli" | "node";
|
|
69
|
+
readonly limit?: number;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Answer a packages query against a parsed catalog. Pure — the tool's `execute`
|
|
73
|
+
* is only the file read plus this call.
|
|
74
|
+
*/
|
|
75
|
+
export declare function queryPackages(sections: readonly Section[], { names, query, language, limit }: PackagesQuery): PackagesResult;
|
|
76
|
+
export declare const listAvailablePackagesTool: import("../define-tool.js").Tool<{
|
|
77
|
+
names?: string[] | undefined;
|
|
78
|
+
query?: string | undefined;
|
|
79
|
+
language?: "r" | "python" | "cli" | "node" | undefined;
|
|
80
|
+
limit?: number | undefined;
|
|
81
|
+
}, PackagesResult>;
|
|
@@ -1,27 +1,169 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* listAvailablePackages —
|
|
2
|
+
* listAvailablePackages — query the R/Python/CLI/Node packages available in the
|
|
3
|
+
* sandbox.
|
|
4
|
+
*
|
|
5
|
+
* The data source is `/mnt/libs/current/packages.txt`, assembled by the
|
|
6
|
+
* library-store build (see the lib-store-build spec). Its shape is fixed by the
|
|
7
|
+
* producers (`scripts/lib-store-common.sh`, `images/sandbox-python/inflexa-libs-refresh`):
|
|
8
|
+
* two `#` advisory lines, then one `## <Section>` heading per language track
|
|
9
|
+
* followed by that track's packages as a single comma-separated line.
|
|
10
|
+
*
|
|
11
|
+
* # Available packages in the sandbox environment.
|
|
12
|
+
* # Do NOT attempt to install packages — ...
|
|
13
|
+
*
|
|
14
|
+
* ## R (CRAN)
|
|
15
|
+
* Seurat, dplyr, ggplot2, ...
|
|
16
|
+
*
|
|
17
|
+
* ## Python (pip)
|
|
18
|
+
* anndata, scanpy, ...
|
|
19
|
+
*
|
|
20
|
+
* The file carries **names only — there are no version strings in it**, so this
|
|
21
|
+
* tool reports presence and language track and cannot report a version.
|
|
3
22
|
*/
|
|
4
23
|
import { readFile } from "node:fs/promises";
|
|
5
24
|
import { ok } from "neverthrow";
|
|
6
25
|
import { z } from "zod";
|
|
7
26
|
import { defineTool } from "../define-tool.js";
|
|
8
27
|
const PACKAGES_FILE = "/mnt/libs/current/packages.txt";
|
|
28
|
+
/** Default number of packages a filtered/unfiltered listing returns. */
|
|
29
|
+
const DEFAULT_LIMIT = 100;
|
|
30
|
+
const UNAVAILABLE_NOTE = "Package list not available. The library store may not be mounted. Assume standard bioinformatics packages (numpy, pandas, scanpy, DESeq2, etc.) are available, but do not attempt to install anything.";
|
|
31
|
+
/** The `language` filter values, mapped onto the concrete section headings. */
|
|
32
|
+
const LANGUAGE_MATCHERS = {
|
|
33
|
+
// The R triple: `R (CRAN)`, `R (Bioconductor)`, `R (GitHub)`.
|
|
34
|
+
r: (t) => /^r\b/i.test(t),
|
|
35
|
+
python: (t) => /^python\b/i.test(t),
|
|
36
|
+
// `System tools (CLI)` — the conda-installed bioinformatics executables.
|
|
37
|
+
cli: (t) => /system tools|\bcli\b/i.test(t),
|
|
38
|
+
node: (t) => /^node\b/i.test(t),
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Parse `packages.txt` into its sections. `#` lines are the advisory header,
|
|
42
|
+
* `## X` opens a section, and every other non-empty line contributes
|
|
43
|
+
* comma-separated package names to the open section. Unknown section headings
|
|
44
|
+
* are preserved as-is — a downstream image may add its own track.
|
|
45
|
+
*/
|
|
46
|
+
export function parsePackagesFile(content) {
|
|
47
|
+
const sections = [];
|
|
48
|
+
for (const line of content.split("\n")) {
|
|
49
|
+
const trimmed = line.trim();
|
|
50
|
+
if (!trimmed)
|
|
51
|
+
continue;
|
|
52
|
+
if (trimmed.startsWith("##")) {
|
|
53
|
+
sections.push({ title: trimmed.slice(2).trim(), packages: [] });
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (trimmed.startsWith("#"))
|
|
57
|
+
continue;
|
|
58
|
+
const open = sections.at(-1);
|
|
59
|
+
if (!open)
|
|
60
|
+
continue;
|
|
61
|
+
for (const name of trimmed.split(",")) {
|
|
62
|
+
const pkg = name.trim();
|
|
63
|
+
if (pkg)
|
|
64
|
+
open.packages.push(pkg);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return sections;
|
|
68
|
+
}
|
|
69
|
+
/** Render sections to the agent-facing listing, bounded at `limit` packages. */
|
|
70
|
+
function renderListing(sections, limit) {
|
|
71
|
+
const lines = [];
|
|
72
|
+
let returned = 0;
|
|
73
|
+
for (const section of sections) {
|
|
74
|
+
if (section.packages.length === 0)
|
|
75
|
+
continue;
|
|
76
|
+
const room = limit - returned;
|
|
77
|
+
if (room <= 0) {
|
|
78
|
+
lines.push(`\n## ${section.title}`, ` ${section.packages.length} package(s) — not shown (limit reached).`);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const shown = section.packages.slice(0, room);
|
|
82
|
+
returned += shown.length;
|
|
83
|
+
lines.push(`\n## ${section.title}`, ` ${shown.join(", ")}`);
|
|
84
|
+
const hidden = section.packages.length - shown.length;
|
|
85
|
+
if (hidden > 0)
|
|
86
|
+
lines.push(` … and ${hidden} more in this section (raise \`limit\` or narrow with \`query\`).`);
|
|
87
|
+
}
|
|
88
|
+
return { content: lines.join("\n").trim(), returned };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Answer a packages query against a parsed catalog. Pure — the tool's `execute`
|
|
92
|
+
* is only the file read plus this call.
|
|
93
|
+
*/
|
|
94
|
+
export function queryPackages(sections, { names, query, language, limit }) {
|
|
95
|
+
// Presence check — the cheap, targeted path. Answers "is X available, and in
|
|
96
|
+
// which track" without returning the catalog.
|
|
97
|
+
if (names && names.length > 0) {
|
|
98
|
+
const index = new Map();
|
|
99
|
+
for (const section of sections) {
|
|
100
|
+
for (const pkg of section.packages) {
|
|
101
|
+
// First writer wins: `packages.txt` sections are ordered, so a name
|
|
102
|
+
// colliding across tracks resolves to the earliest one.
|
|
103
|
+
if (!index.has(pkg.toLowerCase()))
|
|
104
|
+
index.set(pkg.toLowerCase(), { name: pkg, section: section.title });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const checked = names.map((requested) => {
|
|
108
|
+
const hit = index.get(requested.trim().toLowerCase());
|
|
109
|
+
// `name` echoes the catalog's canonical spelling — R package names are
|
|
110
|
+
// case-sensitive at `library()`, so the exact one is what the caller needs.
|
|
111
|
+
return hit ? { requested, present: true, name: hit.name, section: hit.section } : { requested, present: false };
|
|
112
|
+
});
|
|
113
|
+
return { available: true, checked };
|
|
114
|
+
}
|
|
115
|
+
const matchesLanguage = language ? LANGUAGE_MATCHERS[language] : () => true;
|
|
116
|
+
const needle = query?.trim().toLowerCase();
|
|
117
|
+
const filtered = sections
|
|
118
|
+
.filter((s) => matchesLanguage(s.title))
|
|
119
|
+
.map((s) => ({
|
|
120
|
+
title: s.title,
|
|
121
|
+
packages: needle ? s.packages.filter((p) => p.toLowerCase().includes(needle)) : s.packages,
|
|
122
|
+
}))
|
|
123
|
+
.filter((s) => s.packages.length > 0);
|
|
124
|
+
const total = filtered.reduce((n, s) => n + s.packages.length, 0);
|
|
125
|
+
if (total === 0) {
|
|
126
|
+
const scope = [language ? `language: ${language}` : null, query ? `query: "${query}"` : null].filter(Boolean).join(", ");
|
|
127
|
+
return {
|
|
128
|
+
available: true,
|
|
129
|
+
total: 0,
|
|
130
|
+
returned: 0,
|
|
131
|
+
hasMore: false,
|
|
132
|
+
content: `No packages match this filter${scope ? ` (${scope})` : ""}. Nothing can be installed at runtime.`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const { content, returned } = renderListing(filtered, limit ?? DEFAULT_LIMIT);
|
|
136
|
+
return { available: true, total, returned, hasMore: returned < total, content };
|
|
137
|
+
}
|
|
9
138
|
export const listAvailablePackagesTool = defineTool({
|
|
10
139
|
id: "list_available_packages",
|
|
11
|
-
description: "
|
|
12
|
-
|
|
13
|
-
|
|
140
|
+
description: "Query the R, Python, CLI, and Node packages installed in the sandbox. No packages can be installed at runtime — only what this tool reports is importable. " +
|
|
141
|
+
"Results are ALWAYS bounded; prefer a targeted query over a full listing. " +
|
|
142
|
+
'`names`: check specific packages (e.g. ["Seurat", "scanpy"]) — returns present/absent plus the language track for each, case-insensitively; this is the cheapest call and the right one for \'is X available?\'. ' +
|
|
143
|
+
"`query`: case-insensitive substring filter over package names. " +
|
|
144
|
+
"`language`: restrict to one track (r | python | cli | node). " +
|
|
145
|
+
"`limit`: max packages listed (default 100); the response always carries the true `total` and a `hasMore` flag, so truncation is never silent. " +
|
|
146
|
+
'The package list carries NO version numbers — this tool cannot report a package\'s version. Check a version at runtime instead (e.g. `python -c "import scanpy; print(scanpy.__version__)"`).',
|
|
147
|
+
inputSchema: z.object({
|
|
148
|
+
names: z
|
|
149
|
+
.array(z.string())
|
|
150
|
+
.max(100)
|
|
151
|
+
.optional()
|
|
152
|
+
.describe("Check these exact package names for presence (case-insensitive). Returns one entry per name: present/absent + the language track it lives in."),
|
|
153
|
+
query: z.string().optional().describe("Case-insensitive substring filter over package names."),
|
|
154
|
+
language: z.enum(["r", "python", "cli", "node"]).optional().describe("Restrict results to one language track."),
|
|
155
|
+
limit: z.number().int().min(1).max(2000).optional().describe(`Max packages to list (default ${DEFAULT_LIMIT}). Ignored when \`names\` is given.`),
|
|
156
|
+
}),
|
|
157
|
+
execute: async (input) => {
|
|
14
158
|
// A missing library-store mount is an expected environment state — model
|
|
15
159
|
// it as an `available: false` data variant with a helpful fallback note.
|
|
160
|
+
let raw;
|
|
16
161
|
try {
|
|
17
|
-
|
|
18
|
-
return ok({ available: true, content });
|
|
162
|
+
raw = await readFile(PACKAGES_FILE, "utf-8");
|
|
19
163
|
}
|
|
20
164
|
catch {
|
|
21
|
-
return ok({
|
|
22
|
-
available: false,
|
|
23
|
-
content: "Package list not available. The library store may not be mounted. Assume standard bioinformatics packages (numpy, pandas, scanpy, DESeq2, etc.) are available, but do not attempt to install anything.",
|
|
24
|
-
});
|
|
165
|
+
return ok({ available: false, content: UNAVAILABLE_NOTE });
|
|
25
166
|
}
|
|
167
|
+
return ok(queryPackages(parsePackagesFile(raw), input));
|
|
26
168
|
},
|
|
27
169
|
});
|
|
@@ -1,7 +1,143 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Reference-store discovery — two coordinated surfaces over the read-only
|
|
3
|
+
* store at /mnt/refs:
|
|
4
|
+
*
|
|
5
|
+
* - `createListAvailableRefsTool` — the wired sandbox tool. A bounded, no-follow
|
|
6
|
+
* inventory of what is ACTUALLY mounted (managed installs, user-added files),
|
|
7
|
+
* scanned live inside the sandbox. Narrow with `path`/`category`, filter with
|
|
8
|
+
* `query`, cap with `limit`; every response carries `returned`/`total`/
|
|
9
|
+
* `hasMore` and the `categories` present, so a listing is never an unbounded
|
|
10
|
+
* dump. Symlinks are never followed; nothing can be downloaded at runtime.
|
|
11
|
+
* - `queryRefs` — a pure query over a parsed `/mnt/refs/registry.json` manifest
|
|
12
|
+
* (`files.by_category`), filtering on fields the registry carries: `local_path`,
|
|
13
|
+
* `category`, `subtype`, `organism`, `tax_id`, `dataset`, `rows`.
|
|
3
14
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
15
|
+
import type { SandboxClient } from "../../sandbox/client.js";
|
|
16
|
+
import type { SandboxRef } from "../../sandbox/types.js";
|
|
17
|
+
export interface ListAvailableRefsDeps {
|
|
18
|
+
readonly sandboxClient: SandboxClient;
|
|
19
|
+
readonly sandbox: SandboxRef;
|
|
20
|
+
readonly workflowId: string;
|
|
21
|
+
readonly stepId: string;
|
|
22
|
+
readonly nextFunctionId: () => string;
|
|
23
|
+
readonly deadlineMs: () => number;
|
|
24
|
+
readonly markExecActive?: (execId: string) => Promise<void>;
|
|
25
|
+
/** Filesystem root used by the scanner; production callers omit this. */
|
|
26
|
+
readonly scanRoot?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ReferenceInventoryMetadata {
|
|
29
|
+
readonly datasetId?: string;
|
|
30
|
+
readonly version?: string;
|
|
31
|
+
readonly title?: string;
|
|
32
|
+
readonly description?: string;
|
|
33
|
+
readonly sourceUrl?: string;
|
|
34
|
+
readonly license?: string;
|
|
35
|
+
readonly category?: string;
|
|
36
|
+
readonly subtype?: string;
|
|
37
|
+
readonly organism?: string;
|
|
38
|
+
readonly rows?: number;
|
|
39
|
+
readonly endpoint?: string;
|
|
40
|
+
}
|
|
41
|
+
interface ReferenceInventoryEntryBase {
|
|
42
|
+
readonly path: string;
|
|
43
|
+
readonly metadata?: ReferenceInventoryMetadata;
|
|
44
|
+
}
|
|
45
|
+
/** A bounded, no-follow observation from the live reference mount. */
|
|
46
|
+
export type ReferenceInventoryEntry = (ReferenceInventoryEntryBase & {
|
|
47
|
+
readonly kind: "file";
|
|
48
|
+
readonly bytes: number;
|
|
49
|
+
}) | (ReferenceInventoryEntryBase & {
|
|
50
|
+
readonly kind: "symlink";
|
|
51
|
+
readonly bytes: 0;
|
|
52
|
+
}) | (ReferenceInventoryEntryBase & {
|
|
53
|
+
readonly kind: "directory";
|
|
54
|
+
readonly bytes: number;
|
|
55
|
+
readonly fileCount: number;
|
|
56
|
+
readonly fileTypes: readonly string[];
|
|
57
|
+
readonly truncated: boolean;
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* Structured result returned for every expected reference-store state. Bounding
|
|
61
|
+
* is explicit: `returned`/`total`/`hasMore` describe how much of the match set
|
|
62
|
+
* this response carries, and `categories` is the drill-in index.
|
|
63
|
+
*/
|
|
64
|
+
export interface ReferenceInventoryResult {
|
|
65
|
+
readonly available: boolean;
|
|
66
|
+
readonly state: RawScan["state"] | "out_of_scope";
|
|
67
|
+
readonly path: string;
|
|
68
|
+
readonly entries: readonly ReferenceInventoryEntry[];
|
|
69
|
+
readonly scannedEntries: number;
|
|
70
|
+
readonly returned: number;
|
|
71
|
+
readonly total: number;
|
|
72
|
+
readonly truncated: boolean;
|
|
73
|
+
readonly hasMore: boolean;
|
|
74
|
+
readonly categories: readonly string[];
|
|
75
|
+
readonly content: string;
|
|
76
|
+
}
|
|
77
|
+
interface RawScan {
|
|
78
|
+
readonly state: "unavailable" | "empty" | "populated" | "not_found" | "not_a_directory" | "symlink";
|
|
79
|
+
readonly entries: ReferenceInventoryEntry[];
|
|
80
|
+
readonly scannedEntries: number;
|
|
81
|
+
readonly truncated: boolean;
|
|
82
|
+
readonly receipts?: unknown[];
|
|
83
|
+
readonly legacyEntries?: unknown[];
|
|
84
|
+
}
|
|
85
|
+
/** Create replay-safe reference discovery bound to the active sandbox. */
|
|
86
|
+
export declare function createListAvailableRefsTool(deps: ListAvailableRefsDeps): import("../define-tool.js").Tool<{
|
|
87
|
+
path?: string | undefined;
|
|
88
|
+
category?: string | undefined;
|
|
89
|
+
query?: string | undefined;
|
|
90
|
+
limit?: number | undefined;
|
|
91
|
+
}, ReferenceInventoryResult>;
|
|
92
|
+
export interface RegistryEntry {
|
|
93
|
+
local_path: string;
|
|
94
|
+
sha256: string;
|
|
95
|
+
bytes: number;
|
|
96
|
+
rows: number | null;
|
|
97
|
+
category: string | null;
|
|
98
|
+
subtype: string | null;
|
|
99
|
+
organism: string | null;
|
|
100
|
+
tax_id: string | null;
|
|
101
|
+
dataset: string | null;
|
|
102
|
+
endpoint: string | null;
|
|
103
|
+
}
|
|
104
|
+
export interface Registry {
|
|
105
|
+
registry_version: string;
|
|
106
|
+
build_id: string;
|
|
107
|
+
generated_at: string;
|
|
108
|
+
files: {
|
|
109
|
+
by_category: Record<string, RegistryEntry[]>;
|
|
110
|
+
};
|
|
111
|
+
summary: {
|
|
112
|
+
total_output_files: number;
|
|
113
|
+
categories: string[];
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Either the store is unmounted, or a bounded listing: `categories` always names
|
|
118
|
+
* the full valid set (the drill-in index), and `total`/`hasMore` make truncation
|
|
119
|
+
* explicit.
|
|
120
|
+
*/
|
|
121
|
+
export type RefsResult = {
|
|
122
|
+
readonly available: false;
|
|
123
|
+
readonly content: string;
|
|
124
|
+
} | {
|
|
125
|
+
readonly available: true;
|
|
126
|
+
readonly total: number;
|
|
127
|
+
readonly returned: number;
|
|
128
|
+
readonly hasMore: boolean;
|
|
129
|
+
readonly categories: readonly string[];
|
|
130
|
+
readonly content: string;
|
|
131
|
+
};
|
|
132
|
+
/** The tool's input, as parsed from `inputSchema`. */
|
|
133
|
+
export interface RefsQuery {
|
|
134
|
+
readonly category?: string;
|
|
135
|
+
readonly query?: string;
|
|
136
|
+
readonly limit?: number;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Answer a refs query against a parsed registry. Pure — the tool's `execute` is
|
|
140
|
+
* only the file read plus this call.
|
|
141
|
+
*/
|
|
142
|
+
export declare function queryRefs(registry: Registry, { category, query, limit }: RefsQuery): RefsResult;
|
|
143
|
+
export {};
|