@inflexa-ai/harness 0.48.0 → 0.48.2
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/contracts/chat-events.d.ts +40 -0
- package/dist/contracts/chat-frame.js +11 -0
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/message.d.ts +7 -1
- package/dist/contracts/schemas/chat-events.d.ts +319 -0
- package/dist/contracts/schemas/chat-events.js +29 -0
- package/dist/execution/run-synthesis.js +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -1
- package/dist/input-sanitization.d.ts +30 -2
- package/dist/input-sanitization.js +187 -2
- package/dist/loop/run-loop.js +50 -5
- package/dist/loop/tool-adapter.d.ts +8 -0
- package/dist/loop/tool-adapter.js +75 -4
- package/dist/loop/tool-detail.d.ts +5 -1
- package/dist/loop/tool-detail.js +7 -3
- package/dist/loop/tool-value.d.ts +57 -0
- package/dist/loop/tool-value.js +249 -0
- package/dist/loop/types.d.ts +9 -2
- package/dist/memory/conversation-display-storage.js +4 -1
- package/dist/memory/count-tokens.js +29 -2
- package/dist/runtime/dbos.d.ts +6 -0
- package/dist/runtime/dbos.js +14 -2
- package/dist/sandbox/sandbox-step-translate.d.ts +5 -9
- package/dist/sandbox/sandbox-step-translate.js +5 -9
- package/dist/state/artifacts.d.ts +4 -1
- package/dist/state/artifacts.js +4 -1
- package/dist/state/index.d.ts +2 -2
- package/dist/state/index.js +1 -1
- package/dist/state/plans.d.ts +27 -0
- package/dist/state/plans.js +57 -3
- package/dist/tasks/data-profile-activity.d.ts +3 -7
- package/dist/tasks/data-profile-activity.js +1 -1
- package/dist/tasks/data-profile.js +3 -6
- package/dist/tools/ad-hoc-router.js +1 -0
- package/dist/tools/bio/alphafold-prediction.js +1 -0
- package/dist/tools/bio/chembl.js +1 -0
- package/dist/tools/bio/comptox.js +1 -0
- package/dist/tools/bio/drug-gene-interactions.js +1 -0
- package/dist/tools/bio/gene-disease-evidence.js +1 -0
- package/dist/tools/bio/gene-preclinical-profile.js +1 -0
- package/dist/tools/bio/lookup-annotation.js +1 -0
- package/dist/tools/bio/opentargets.js +1 -0
- package/dist/tools/bio/pubchem.js +1 -0
- package/dist/tools/bio/pubmed.js +1 -0
- package/dist/tools/bio/search-clinical-trials.js +1 -0
- package/dist/tools/bio/search-faers.js +1 -0
- package/dist/tools/bio/search-gene.js +1 -0
- package/dist/tools/bio/search-geo-datasets.js +1 -0
- package/dist/tools/bio/search-interactions.js +1 -0
- package/dist/tools/bio/search-patents.js +1 -0
- package/dist/tools/bio/search-protein.js +1 -0
- package/dist/tools/bio/search-regulatory-approvals.js +1 -0
- package/dist/tools/bio/target-safety.js +1 -0
- package/dist/tools/capability-data.js +5 -0
- package/dist/tools/define-tool.d.ts +18 -0
- package/dist/tools/define-tool.js +2 -0
- package/dist/tools/display/show-user.js +1 -0
- package/dist/tools/execute-analysis.js +4 -0
- package/dist/tools/knowledge/check.d.ts +47 -1
- package/dist/tools/knowledge/check.js +10 -1
- package/dist/tools/knowledge/client.d.ts +1 -1
- package/dist/tools/knowledge/recommend.js +4 -3
- package/dist/tools/knowledge/situation.d.ts +39 -1
- package/dist/tools/knowledge/situation.js +80 -8
- package/dist/tools/knowledge/skeleton.d.ts +7 -0
- package/dist/tools/knowledge/skeleton.js +88 -2
- package/dist/tools/knowledge/template.js +1 -0
- package/dist/tools/memory/update-working-memory.js +5 -0
- package/dist/tools/read-tool-output.js +4 -0
- package/dist/tools/report-authoring/authoring-tools.js +8 -0
- package/dist/tools/report-session/examine-page.js +5 -0
- package/dist/tools/report-session/list-artifacts.js +5 -0
- package/dist/tools/report-session/preview-report.js +1 -0
- package/dist/tools/report-session/record-version.js +1 -0
- package/dist/tools/report-session/script-tools.js +2 -0
- package/dist/tools/research/context7-docs.js +2 -0
- package/dist/tools/research/generate-analogy-report.js +3 -0
- package/dist/tools/research/generate-plan.js +6 -0
- package/dist/tools/research/inspect-data-profile.js +5 -0
- package/dist/tools/research/inspect-run.js +5 -0
- package/dist/tools/research/resolve-citation.js +1 -0
- package/dist/tools/research/search-arxiv.js +1 -0
- package/dist/tools/research/search-github-repos.js +1 -0
- package/dist/tools/research/search-semantic-scholar.js +1 -0
- package/dist/tools/research/web-fetch.js +1 -0
- package/dist/tools/research/web-search.js +1 -0
- package/dist/tools/sandbox/lease-tools.js +2 -0
- package/dist/tools/sandbox/link-packages.js +1 -0
- package/dist/tools/sandbox/list-available-packages.js +5 -0
- package/dist/tools/sandbox/list-available-refs.js +5 -0
- package/dist/tools/sandbox/report-blocker.js +1 -0
- package/dist/tools/sandbox/skills.js +2 -0
- package/dist/tools/sandbox/submit-file-metadata.js +1 -0
- package/dist/tools/script/file-tools.js +6 -0
- package/dist/tools/script/run-script.js +20 -1
- package/dist/tools/start-report-session.js +1 -0
- package/dist/tools/tool-view.d.ts +63 -0
- package/dist/tools/tool-view.js +68 -0
- package/dist/tools/workspace/edit-file.js +5 -0
- package/dist/tools/workspace/execute-command.js +5 -2
- package/dist/tools/workspace/file-stat.js +5 -0
- package/dist/tools/workspace/grep.js +4 -0
- package/dist/tools/workspace/list-files.js +5 -0
- package/dist/tools/workspace/read-file.js +4 -0
- package/dist/tools/workspace/scan-inputs.js +5 -0
- package/dist/tools/workspace/show-file.js +1 -0
- package/dist/tools/workspace/show-plan.js +1 -0
- package/dist/tools/workspace/workspace-search.js +5 -0
- package/dist/tools/workspace/write-file.js +7 -2
- package/dist/workflows/execute-analysis.js +2 -1
- package/dist/workflows/sandbox-step.js +3 -7
- package/package.json +1 -1
- package/dist/tools/detail-resolver.d.ts +0 -40
- package/dist/tools/detail-resolver.js +0 -44
|
@@ -18,16 +18,28 @@ export const SituationFieldsSchema = z.object({
|
|
|
18
18
|
"clustering",
|
|
19
19
|
"survival",
|
|
20
20
|
"signature_scoring",
|
|
21
|
+
"dose_response",
|
|
21
22
|
])
|
|
22
23
|
.describe("What the plan needs a procedure for. `full_plan` returns QC, filtering, the model, the test, shrinkage, multiple testing, enrichment, and the report in one answer. " +
|
|
23
24
|
"Use `differential_expression` when the research question does not ask for pathways or gene sets; an enrichment step the user did not ask for is unasked scope. " +
|
|
24
25
|
"Use `enrichment` when a results table is the input and no new test is fitted, and `qc` when the question stops at the sample structure. " +
|
|
25
26
|
"Use `tf_activity` for regulator or pathway activity, `deconvolution` for cell type proportions, `coexpression` for modules, `clustering` for sample subgroups, `survival` for an outcome association, " +
|
|
26
|
-
"and `signature_scoring` for a per-sample score, or with `classifier: true` for a classifier of the samples."
|
|
27
|
-
|
|
27
|
+
"and `signature_scoring` for a per-sample score, or with `classifier: true` for a classifier of the samples. " +
|
|
28
|
+
"Use `dose_response` when the question asks at which exposure the expression leaves the control: the walk fits a curve per gene over the dose, takes the benchmark dose of each gene set, " +
|
|
29
|
+
"reads the transcriptomic point of departure from the lowest set median, and divides it by an efficacious exposure for the exposure margin. " +
|
|
30
|
+
"A `dose_response` situation carries `n_dose_levels`, `tissue`, and `exposure_axis`, because the fit, the point of departure, and the margin each stop without one of them, " +
|
|
31
|
+
"and it carries `control_placement`, `grid_complete`, `recovery_group`, and `n_compounds` when the design holds them."),
|
|
32
|
+
modality: z
|
|
33
|
+
.enum(["bulk_rna_seq", "microarray", "tempo_seq"])
|
|
34
|
+
.describe("The platform that measured the expression: `bulk_rna_seq` for a sequencing run over the whole transcriptome; `microarray` for the probe intensities of a hybridization array, the platform of the legacy toxicogenomics compendia; " +
|
|
35
|
+
"`tempo_seq` for the targeted read counts of a TempO-Seq probe panel, where the panel and not the transcriptome is the gene universe. " +
|
|
36
|
+
"An array reads no sequence, thus it has no read count and no library size: a `microarray` takes `data_state` `log_normalized`, `de_results`, or `effect_sizes_only`, and `fastq`, `counts`, or `tpm_or_fpkm` stops the plan as a contradiction. " +
|
|
37
|
+
"A probe panel is a sequencing assay and it keeps the read count, thus `tempo_seq` takes `counts`; a panel gives no transcript length, thus never `tpm_or_fpkm`."),
|
|
28
38
|
data_state: z
|
|
29
|
-
.enum(["fastq", "counts", "tpm_or_fpkm", "log_normalized"])
|
|
30
|
-
.describe("The state of the expression data in the inputs: raw reads, a raw integer count matrix, TPM/FPKM/RPKM abundances, or log-scale normalized values (log-CPM, microarray)."
|
|
39
|
+
.enum(["fastq", "counts", "tpm_or_fpkm", "log_normalized", "de_results", "effect_sizes_only"])
|
|
40
|
+
.describe("The state of the expression data in the inputs: raw reads, a raw integer count matrix, TPM/FPKM/RPKM abundances, or log-scale normalized values (log-CPM, microarray). " +
|
|
41
|
+
"`de_results` is a table of contrasts with an effect size and a p-value per gene, and `effect_sizes_only` the same table with no p-value. " +
|
|
42
|
+
"A table of contrasts holds no value of a sample and no variance inside a dose group: without the p-values no step counts calls at a false discovery rate, and either table stops a benchmark dose fit."),
|
|
31
43
|
count_source: z
|
|
32
44
|
.enum(["salmon", "kallisto", "star_featurecounts", "rsem", "unknown"])
|
|
33
45
|
.optional()
|
|
@@ -41,7 +53,9 @@ export const SituationFieldsSchema = z.object({
|
|
|
41
53
|
"`corrected_counts`: a table described as lengthScaledTPM or scaledTPM counts. " +
|
|
42
54
|
"`integer_counts`: integer counts from an aligner and a counter (STAR, featureCounts) or from a 3' protocol, with no length data. " +
|
|
43
55
|
"`unknown`: a count table from a quantifier with no statement of the correction. Omit when `data_state` is not `counts`."),
|
|
44
|
-
organism: z
|
|
56
|
+
organism: z
|
|
57
|
+
.enum(["human", "mouse", "rat", "dog", "monkey", "other"])
|
|
58
|
+
.describe("The organism of the samples. `rat`, `dog`, and `monkey` are the species of a regulatory toxicology study; use `other` only for a species this list does not name."),
|
|
45
59
|
n_groups: z
|
|
46
60
|
.number()
|
|
47
61
|
.int()
|
|
@@ -71,10 +85,10 @@ export const SituationFieldsSchema = z.object({
|
|
|
71
85
|
.describe("For a survival question, the number of samples with an observed event (event indicator 1) in the outcome column. Omit when the question is not survival or the count is not in the profile."),
|
|
72
86
|
paired: z.boolean().describe("True when each subject contributes a sample to more than one condition (paired or repeated measures)."),
|
|
73
87
|
blocking_factor: z
|
|
74
|
-
.enum(["individual", "cell_line", "litter", "site", "pair", "other"])
|
|
88
|
+
.enum(["individual", "cell_line", "litter", "site", "pair", "plate", "other"])
|
|
75
89
|
.nullable()
|
|
76
90
|
.optional()
|
|
77
|
-
.describe("The role of the blocking factor that is not the condition, never its column name: `individual` when the same subject, donor, or animal gives more than one sample; `cell_line`; `litter`; `site` for a center or a lab of a multi-site study; `pair` for matched pairs of different individuals; `other`. Omit when there is none. The column name stays in the step."),
|
|
91
|
+
.describe("The role of the blocking factor that is not the condition, never its column name: `individual` when the same subject, donor, or animal gives more than one sample; `cell_line`; `litter`; `site` for a center or a lab of a multi-site study; `pair` for matched pairs of different individuals; `plate` when the samples sit on culture or assay plates and one plate holds a set of them; `other`. Omit when there is none. The column name stays in the step."),
|
|
78
92
|
block_structure: z
|
|
79
93
|
.enum(["crossed", "nested"])
|
|
80
94
|
.optional()
|
|
@@ -126,10 +140,14 @@ export const SituationFieldsSchema = z.object({
|
|
|
126
140
|
"survival",
|
|
127
141
|
"transcript_level",
|
|
128
142
|
"annotation",
|
|
143
|
+
"reference_module_score",
|
|
144
|
+
"classifier_call",
|
|
129
145
|
]))
|
|
130
146
|
.optional()
|
|
131
147
|
.describe("Analyses the research question asks for beside the question kind, for example a regulator activity beside a differential expression. Each joins the procedure at its place. " +
|
|
132
|
-
"Add `annotation` when the rows of the count table are not gene symbols (Ensembl or Entrez identifiers) and a later step needs symbols: the identifier map is then a vetted step with its own template, and no other step rebuilds it.
|
|
148
|
+
"Add `annotation` when the rows of the count table are not gene symbols (Ensembl or Entrez identifiers) and a later step needs symbols: the identifier map is then a vetted step with its own template, and no other step rebuilds it. " +
|
|
149
|
+
"Add `reference_module_score` for a score of each sample against a reference co-expression module set, and `classifier_call` for the call of a validated classifier on each sample. " +
|
|
150
|
+
"Each of the two contrasts two levels of the group column, thus either one needs two or more groups, a time course, or a numeric predictor. Omit when none."),
|
|
133
151
|
preferred_language: z
|
|
134
152
|
.enum(["R", "python"])
|
|
135
153
|
.optional()
|
|
@@ -142,6 +160,60 @@ export const SituationFieldsSchema = z.object({
|
|
|
142
160
|
.array(z.enum(["low_depth_sample", "outlier_sample", "sample_identity_doubt", "high_duplication", "degraded_rna"]))
|
|
143
161
|
.optional()
|
|
144
162
|
.describe("The quality concerns of the profile as typed flags: a sample with a library size far below the median; a sample that does not cluster with its group; a doubt about the identity of a sample; high duplication; degraded RNA (a low RNA integrity number, a 3' coverage bias, or formalin-fixed material)."),
|
|
163
|
+
tissue: z
|
|
164
|
+
.enum(["liver", "kidney", "heart", "muscle", "brain", "adipose", "blood", "other"])
|
|
165
|
+
.optional()
|
|
166
|
+
.describe("The tissue the samples come from: `liver`, `kidney`, `heart`, `muscle` for skeletal muscle, `brain` whole or one region, `adipose`, `blood` whole or a fraction, " +
|
|
167
|
+
"or `other` for a tissue this list does not name, for example a cell line. " +
|
|
168
|
+
"A transcriptomic point of departure belongs to the tissue of its samples, and the point of departure of one tissue says nothing about another, thus one call covers one tissue and the exposure margin stops without this field. " +
|
|
169
|
+
"Read it from the sample description of the profile or from the user request. Omit it when the question is not `dose_response`, or when the samples are not from one tissue."),
|
|
170
|
+
exposure_axis: z
|
|
171
|
+
.enum(["administered_dose", "in_vitro_concentration", "systemic_exposure"])
|
|
172
|
+
.optional()
|
|
173
|
+
.describe("The axis on which the exposure values of the study lie: `administered_dose` for the dose the study gives to the animal or to the culture, for example in mg/kg; " +
|
|
174
|
+
"`in_vitro_concentration` for the concentration of the compound in the medium of a cell culture; `systemic_exposure` for a measured level in the plasma, for example a Cmax or an AUC. " +
|
|
175
|
+
"The exposure margin divides the point of departure by an efficacious exposure, and that quotient means something only when both values lie on one axis and in one unit. " +
|
|
176
|
+
"Thus the margin stops without this field, and `in_vitro_concentration` stops it too, because a concentration in a medium is no dose of an intact organism and the extrapolation from in vitro to in vivo comes first. " +
|
|
177
|
+
"Read it from the dose column of the profile or from the user request. Omit it when the question is not `dose_response`."),
|
|
178
|
+
n_dose_levels: z
|
|
179
|
+
.number()
|
|
180
|
+
.int()
|
|
181
|
+
.min(1)
|
|
182
|
+
.optional()
|
|
183
|
+
.describe("The number of dose levels of the design, the control level included. The dose levels are groups of the design, thus this count is at most `n_groups`, " +
|
|
184
|
+
"unless `continuous_predictor` is `dose` and the dose itself, not a group, is the factor of interest. " +
|
|
185
|
+
"Three levels is the floor of the walk: the model families of the average hold three or more parameters, thus below three levels no gene and no gene set has a benchmark dose and the point of departure stops. " +
|
|
186
|
+
"Read it from the dose column of the profile. Omit it when the question is not `dose_response`."),
|
|
187
|
+
n_compounds: z
|
|
188
|
+
.number()
|
|
189
|
+
.int()
|
|
190
|
+
.min(1)
|
|
191
|
+
.optional()
|
|
192
|
+
.describe("The number of compounds the study exposes the samples to. One call covers one compound: no design term names a compound as a factor, and the point of departure and the exposure margin each give one value for one compound. " +
|
|
193
|
+
"Thus 2 or more says that the plan runs the walk one time for each compound, each run over the samples of that compound and the control samples of that compound, and it pools no two compounds in one fit. " +
|
|
194
|
+
"Read it from the sample table of the profile. Omit it when the question is not `dose_response`."),
|
|
195
|
+
control_placement: z
|
|
196
|
+
.enum(["single_baseline", "per_time", "per_block", "per_time_and_block"])
|
|
197
|
+
.optional()
|
|
198
|
+
.describe("Where the control samples sit in the design, which decides the samples that form the contrast of each treated sample: `single_baseline` when one control group serves every treated group; " +
|
|
199
|
+
"`per_time` when each time point holds its own control group; `per_block` when each block, for example a plate, holds its own control group; `per_time_and_block` for both. " +
|
|
200
|
+
"With a control at each time the design takes the dose and the time as fixed factors and the control of the same time as the reference level, so that a time effect all dose levels share leaves the dose contrast. " +
|
|
201
|
+
"`per_time` and `per_time_and_block` need `n_timepoints` or `continuous_predictor: time`, and `per_block` and `per_time_and_block` need `blocking_factor`. " +
|
|
202
|
+
"Read it from the sample table of the profile. Omit it when the question is not `dose_response`."),
|
|
203
|
+
grid_complete: z
|
|
204
|
+
.boolean()
|
|
205
|
+
.optional()
|
|
206
|
+
.describe("Whether every cell of the grid of the dose levels, the times, and the blocks holds at least one sample. Set false when a cell holds none: a model that assumes every cell, " +
|
|
207
|
+
"for example a cell-means model with one coefficient per combination or a full interaction of the factors, then carries a coefficient with no data and the design matrix loses rank. " +
|
|
208
|
+
"The plan then fits the terms the design can estimate and states the estimable contrasts only. " +
|
|
209
|
+
"Read it from the sample table of the profile. Omit it when every cell holds a sample."),
|
|
210
|
+
recovery_group: z
|
|
211
|
+
.boolean()
|
|
212
|
+
.optional()
|
|
213
|
+
.describe("Set true when the study holds a group that it observes after the exposure ends, for example animals that rest after the last dose. " +
|
|
214
|
+
"Such a group carries no dose at the time of its sample, thus it lies at no point of the dose-response curve and the fit leaves it out; " +
|
|
215
|
+
"a recovery sample placed at the dose of its exposure makes the response of that dose lower than the exposure gives. " +
|
|
216
|
+
"Read it from the time column or the group labels of the sample table. Omit it when the study samples every group during the exposure."),
|
|
145
217
|
});
|
|
146
218
|
/** The situation as the client sends it: the fields as given, with the caller preference held out of the situation fields. */
|
|
147
219
|
export function toSituation(fields) {
|
|
@@ -19,6 +19,13 @@
|
|
|
19
19
|
* one enrichment step on its own track, and one report step. A group with
|
|
20
20
|
* no step in the procedure is absent from the skeleton.
|
|
21
21
|
*
|
|
22
|
+
* A step whose own template reads the output of another template gets its
|
|
23
|
+
* own group, because a fold keeps the template of the central step alone and
|
|
24
|
+
* it would drop the others. Thus the four steps of the dose-response chain
|
|
25
|
+
* (the benchmark dose of each gene, the benchmark dose of each gene set, the
|
|
26
|
+
* point of departure, and the exposure margin) are four groups of one track,
|
|
27
|
+
* in that order, and each of the other four new steps is a group of its own.
|
|
28
|
+
*
|
|
22
29
|
* The central step of a group names the method of the skeleton step, and it
|
|
23
30
|
* gives the alternatives, the template, and the environment: an alternative
|
|
24
31
|
* of a folded step (a normalization in the differential expression group)
|
|
@@ -19,6 +19,13 @@
|
|
|
19
19
|
* one enrichment step on its own track, and one report step. A group with
|
|
20
20
|
* no step in the procedure is absent from the skeleton.
|
|
21
21
|
*
|
|
22
|
+
* A step whose own template reads the output of another template gets its
|
|
23
|
+
* own group, because a fold keeps the template of the central step alone and
|
|
24
|
+
* it would drop the others. Thus the four steps of the dose-response chain
|
|
25
|
+
* (the benchmark dose of each gene, the benchmark dose of each gene set, the
|
|
26
|
+
* point of departure, and the exposure margin) are four groups of one track,
|
|
27
|
+
* in that order, and each of the other four new steps is a group of its own.
|
|
28
|
+
*
|
|
22
29
|
* The central step of a group names the method of the skeleton step, and it
|
|
23
30
|
* gives the alternatives, the template, and the environment: an alternative
|
|
24
31
|
* of a folded step (a normalization in the differential expression group)
|
|
@@ -40,6 +47,21 @@ const GROUPS = [
|
|
|
40
47
|
steps: ["filter_low_counts", "normalize", "model_design", "differential_expression", "shrink_lfc", "multiple_testing"],
|
|
41
48
|
name: "Differential expression",
|
|
42
49
|
},
|
|
50
|
+
// The dose-response chain: each step reads the table that the step before
|
|
51
|
+
// it writes, thus the four are one track in the order of the chain. The
|
|
52
|
+
// track is its own, because the chain is a branch off the test and not a
|
|
53
|
+
// part of the core walk, and it ends in a regulatory quantity.
|
|
54
|
+
{ id: "T4S1", track: "T4", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["dose_response_fit"], name: "Benchmark dose of each gene" },
|
|
55
|
+
{
|
|
56
|
+
id: "T4S2",
|
|
57
|
+
track: "T4",
|
|
58
|
+
step_type: "analysis",
|
|
59
|
+
agent: "bulk-transcriptomics-agent",
|
|
60
|
+
steps: ["benchmark_dose_sets"],
|
|
61
|
+
name: "Benchmark dose of each gene set",
|
|
62
|
+
},
|
|
63
|
+
{ id: "T4S3", track: "T4", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["point_of_departure"], name: "Point of departure" },
|
|
64
|
+
{ id: "T4S4", track: "T4", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["exposure_margin"], name: "Exposure margin" },
|
|
43
65
|
{ id: "T2S1", track: "T2", step_type: "enrichment", agent: "enrichment-agent", steps: ["enrichment"], name: "Gene set enrichment" },
|
|
44
66
|
{
|
|
45
67
|
id: "T2S2",
|
|
@@ -49,12 +71,45 @@ const GROUPS = [
|
|
|
49
71
|
steps: ["tf_activity", "pathway_activity"],
|
|
50
72
|
name: "Regulator and pathway activity",
|
|
51
73
|
},
|
|
74
|
+
// The connectivity reads the contrast of the study against a reference
|
|
75
|
+
// resource, which is the shape and the agent of this track. The resource
|
|
76
|
+
// is a compendium of contrasts and not a gene set collection, thus the
|
|
77
|
+
// step is a group of its own beside the enrichment and the activity.
|
|
78
|
+
{
|
|
79
|
+
id: "T2S3",
|
|
80
|
+
track: "T2",
|
|
81
|
+
step_type: "analysis",
|
|
82
|
+
agent: "enrichment-agent",
|
|
83
|
+
steps: ["compendium_connectivity"],
|
|
84
|
+
name: "Compendium connectivity",
|
|
85
|
+
},
|
|
52
86
|
{ id: "T1S4", track: "T1", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["variance_partition"], name: "Variance partition" },
|
|
53
87
|
{ id: "T3S1", track: "T3", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["signature_scoring"], name: "Signature scoring" },
|
|
54
88
|
{ id: "T3S2", track: "T3", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["deconvolution"], name: "Cell type deconvolution" },
|
|
55
89
|
{ id: "T3S3", track: "T3", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["coexpression"], name: "Co-expression modules" },
|
|
56
90
|
{ id: "T3S4", track: "T3", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["clustering"], name: "Sample clustering" },
|
|
57
91
|
{ id: "T3S5", track: "T3", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["survival"], name: "Outcome association" },
|
|
92
|
+
// Three computations over the value matrix and the sample table, each
|
|
93
|
+
// independent of the others and of the chain, thus each is a group of
|
|
94
|
+
// this track: a class per gene over the time points, a score per sample
|
|
95
|
+
// against a reference module set, and a call per sample.
|
|
96
|
+
{
|
|
97
|
+
id: "T3S6",
|
|
98
|
+
track: "T3",
|
|
99
|
+
step_type: "analysis",
|
|
100
|
+
agent: "bulk-transcriptomics-agent",
|
|
101
|
+
steps: ["trajectory_classification"],
|
|
102
|
+
name: "Trajectory classification",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: "T3S7",
|
|
106
|
+
track: "T3",
|
|
107
|
+
step_type: "analysis",
|
|
108
|
+
agent: "bulk-transcriptomics-agent",
|
|
109
|
+
steps: ["reference_module_score"],
|
|
110
|
+
name: "Reference module score",
|
|
111
|
+
},
|
|
112
|
+
{ id: "T3S8", track: "T3", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["classifier_call"], name: "Classifier call" },
|
|
58
113
|
{ id: "T1S5", track: "T1", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["transcript_level"], name: "Transcript-level analysis" },
|
|
59
114
|
{ id: "T1S6", track: "T1", step_type: "analysis", agent: "bulk-transcriptomics-agent", steps: ["annotation"], name: "Identifier annotation" },
|
|
60
115
|
{ id: "T1S3", track: "T1", step_type: "report", agent: "bulk-transcriptomics-agent", steps: ["report"], name: "Report" },
|
|
@@ -63,23 +118,54 @@ const GROUPS = [
|
|
|
63
118
|
* The dependencies of each group. The QC depends on the cohort assembly when
|
|
64
119
|
* one is present, a group depends on the QC, on the differential expression
|
|
65
120
|
* when its input is a results table, and the report depends on every group
|
|
66
|
-
* that is present.
|
|
121
|
+
* that is present. A step of the dose-response chain depends on the step
|
|
122
|
+
* whose table it reads: the fit reads the genes that passed the test, the
|
|
123
|
+
* gene sets read the gene table of the fit, the point of departure reads the
|
|
124
|
+
* set table and the gene table, and the margin reads the point of departure.
|
|
67
125
|
*/
|
|
68
126
|
const DEPENDS = {
|
|
69
127
|
T0S1: [],
|
|
70
128
|
T1S1: ["T0S1"],
|
|
71
129
|
T1S2: ["T1S1"],
|
|
130
|
+
T4S1: ["T1S2"],
|
|
131
|
+
T4S2: ["T4S1"],
|
|
132
|
+
T4S3: ["T4S2", "T4S1"],
|
|
133
|
+
T4S4: ["T4S3"],
|
|
72
134
|
T2S1: ["T1S2"],
|
|
73
135
|
T2S2: ["T1S2", "T1S1"],
|
|
136
|
+
T2S3: ["T1S2"],
|
|
74
137
|
T1S4: ["T1S1"],
|
|
75
138
|
T3S1: ["T1S1"],
|
|
76
139
|
T3S2: ["T1S1"],
|
|
77
140
|
T3S3: ["T1S1"],
|
|
78
141
|
T3S4: ["T1S1"],
|
|
79
142
|
T3S5: ["T3S1", "T1S1"],
|
|
143
|
+
T3S6: ["T1S1"],
|
|
144
|
+
T3S7: ["T1S1"],
|
|
145
|
+
T3S8: ["T1S1"],
|
|
80
146
|
T1S5: ["T1S1"],
|
|
81
147
|
T1S6: ["T1S1"],
|
|
82
|
-
T1S3: [
|
|
148
|
+
T1S3: [
|
|
149
|
+
"T1S2",
|
|
150
|
+
"T4S1",
|
|
151
|
+
"T4S2",
|
|
152
|
+
"T4S3",
|
|
153
|
+
"T4S4",
|
|
154
|
+
"T2S1",
|
|
155
|
+
"T2S2",
|
|
156
|
+
"T2S3",
|
|
157
|
+
"T1S4",
|
|
158
|
+
"T3S1",
|
|
159
|
+
"T3S2",
|
|
160
|
+
"T3S3",
|
|
161
|
+
"T3S4",
|
|
162
|
+
"T3S5",
|
|
163
|
+
"T3S6",
|
|
164
|
+
"T3S7",
|
|
165
|
+
"T3S8",
|
|
166
|
+
"T1S5",
|
|
167
|
+
"T1S6",
|
|
168
|
+
],
|
|
83
169
|
};
|
|
84
170
|
/** A parameter value as a setting: a scalar stays, a list becomes a list of strings, anything else its text. */
|
|
85
171
|
function settingValue(value) {
|
|
@@ -124,6 +124,7 @@ export function createKnowledgeTemplateTool(deps) {
|
|
|
124
124
|
"A change the slots do not cover: use `edit_file` on a line marked `# [adaptable: ...]` in the rendered script, and keep the edit small; the record lists each such edit. " +
|
|
125
125
|
"`match: unavailable` means the service did not answer, and `match: snapshot_mismatch` means the service moved to another release than the plan pinned; in both cases write the script yourself as you would without this tool, and state it in your summary.",
|
|
126
126
|
inputSchema: KnowledgeTemplateInputSchema,
|
|
127
|
+
view: "none",
|
|
127
128
|
describeCall: ({ template }) => template,
|
|
128
129
|
describeResult: (_input, result) => "status" in result ? (result.status === "ok" ? `${result.script_path} (${result.environment_match})` : result.status) : result.match,
|
|
129
130
|
execute: async ({ template, slots, overrides, script_name }, ctx) => {
|
|
@@ -165,6 +165,11 @@ export function createUpdateWorkingMemoryTool(workingMemory, pool, opts = DEFAUL
|
|
|
165
165
|
"user's last message, run contents (tables, gene lists, file paths), or anything you can retrieve " +
|
|
166
166
|
"again with inspect_run, read_file, or search.",
|
|
167
167
|
inputSchema,
|
|
168
|
+
view: {
|
|
169
|
+
input: (input) => input,
|
|
170
|
+
result: (_input, result) => result,
|
|
171
|
+
error: true,
|
|
172
|
+
},
|
|
168
173
|
// Four writes in one turn are four identical chips without this. The
|
|
169
174
|
// entry id rides along on revise/retire because it is the only thing
|
|
170
175
|
// separating two retirements from the same section.
|
|
@@ -122,6 +122,10 @@ export function createReadToolOutputTool(store) {
|
|
|
122
122
|
`${MAX_MATCHES} matches, each with its offset and the text around it. When a result gives \`more: true\`, ` +
|
|
123
123
|
"call again with `offset` set to its `end`.",
|
|
124
124
|
inputSchema: ReadToolOutputInputSchema,
|
|
125
|
+
view: {
|
|
126
|
+
input: (input) => input,
|
|
127
|
+
error: true,
|
|
128
|
+
},
|
|
125
129
|
// The reference alone repeats across the pages of one text, and the pattern is what tells two searches apart.
|
|
126
130
|
describeCall: ({ ref, pattern }) => (pattern === undefined ? ref : `${pattern} in ${ref}`),
|
|
127
131
|
execute: async ({ ref, offset = 0, limit, pattern }, ctx) => {
|
|
@@ -524,6 +524,7 @@ export function createReportAuthoringTools(gateway, deps = {}) {
|
|
|
524
524
|
"A reference names the path of a pinned artifact, and the session stamps the hash from the pinned evidence.",
|
|
525
525
|
inputSchema: addBlockInput,
|
|
526
526
|
outputSchema: MutationOutputSchema,
|
|
527
|
+
view: "none",
|
|
527
528
|
describeCall: (input) => {
|
|
528
529
|
const block = decodeBlockPayload(input.block);
|
|
529
530
|
const kind = readKind(block);
|
|
@@ -559,6 +560,7 @@ export function createReportAuthoringTools(gateway, deps = {}) {
|
|
|
559
560
|
"A reference names the path of a pinned artifact, and the session stamps the hash from the pinned evidence.",
|
|
560
561
|
inputSchema: changeBlockInput,
|
|
561
562
|
outputSchema: MutationOutputSchema,
|
|
563
|
+
view: "none",
|
|
562
564
|
describeCall: (input) => `change ${input.targetId}`,
|
|
563
565
|
execute: async (input, ctx) => {
|
|
564
566
|
const opening = await openMutation(ctx);
|
|
@@ -582,6 +584,7 @@ export function createReportAuthoringTools(gateway, deps = {}) {
|
|
|
582
584
|
description: "Remove one block by its id. A removed section takes its whole subtree with it, and the id is free for a later add.",
|
|
583
585
|
inputSchema: removeBlockInput,
|
|
584
586
|
outputSchema: MutationOutputSchema,
|
|
587
|
+
view: "none",
|
|
585
588
|
describeCall: (input) => `remove ${input.targetId}`,
|
|
586
589
|
execute: async (input, ctx) => {
|
|
587
590
|
const opening = await openMutation(ctx);
|
|
@@ -602,6 +605,7 @@ export function createReportAuthoringTools(gateway, deps = {}) {
|
|
|
602
605
|
"A section cannot move into its own subtree.",
|
|
603
606
|
inputSchema: moveBlockInput,
|
|
604
607
|
outputSchema: MutationOutputSchema,
|
|
608
|
+
view: "none",
|
|
605
609
|
describeCall: (input) => `move ${input.targetId}`,
|
|
606
610
|
execute: async (input, ctx) => {
|
|
607
611
|
const opening = await openMutation(ctx);
|
|
@@ -622,6 +626,7 @@ export function createReportAuthoringTools(gateway, deps = {}) {
|
|
|
622
626
|
description: "Set the title of the whole report, not the title of a section. A draft starts with no title, and a document needs one.",
|
|
623
627
|
inputSchema: setTitleInput,
|
|
624
628
|
outputSchema: MutationOutputSchema,
|
|
629
|
+
view: "none",
|
|
625
630
|
describeCall: (input) => `title the report ${input.title}`,
|
|
626
631
|
// The title sits on the document, thus no container changes its child order.
|
|
627
632
|
execute: async (input, ctx) => {
|
|
@@ -648,6 +653,7 @@ export function createReportAuthoringTools(gateway, deps = {}) {
|
|
|
648
653
|
"and read one block when the label is not enough.",
|
|
649
654
|
inputSchema: readOutlineInput,
|
|
650
655
|
outputSchema: OutlineOutputSchema,
|
|
656
|
+
view: "none",
|
|
651
657
|
// The input carries no field, thus a hook can only restate the name of the tool.
|
|
652
658
|
describeCall: "none",
|
|
653
659
|
execute: async (_input, ctx) => {
|
|
@@ -665,6 +671,7 @@ export function createReportAuthoringTools(gateway, deps = {}) {
|
|
|
665
671
|
"because the outline already names every block under it. Use it when the outline label is not enough.",
|
|
666
672
|
inputSchema: readBlockInput,
|
|
667
673
|
outputSchema: ReadBlockOutputSchema,
|
|
674
|
+
view: "none",
|
|
668
675
|
describeCall: (input) => `read ${input.targetId}`,
|
|
669
676
|
execute: async (input, ctx) => {
|
|
670
677
|
const opened = await openThread(ctx);
|
|
@@ -685,6 +692,7 @@ export function createReportAuthoringTools(gateway, deps = {}) {
|
|
|
685
692
|
"preview_report and record_report_version run the same check before they act, thus a finish directly before one of them does that check a second time. " +
|
|
686
693
|
"Use it to make sure that the draft passes the whole document schema, the id rule, and the structural tier.",
|
|
687
694
|
inputSchema: finishDraftInput,
|
|
695
|
+
view: "none",
|
|
688
696
|
// The input carries no field, thus a hook can only restate the name of the tool.
|
|
689
697
|
describeCall: "none",
|
|
690
698
|
execute: async (_input, ctx) => {
|
|
@@ -254,6 +254,11 @@ export function createExaminePageTool(deps) {
|
|
|
254
254
|
"The outcomes no-page and missed-stamp mean that no preview rendered the current page: run preview_report, then look again. " +
|
|
255
255
|
"The outcome no-browser means that this host gives no browser, and a repeat gives the same outcome.",
|
|
256
256
|
inputSchema: examinePageInput,
|
|
257
|
+
view: {
|
|
258
|
+
input: (input) => input,
|
|
259
|
+
result: (_input, result) => result,
|
|
260
|
+
error: true,
|
|
261
|
+
},
|
|
257
262
|
describeCall: (input) => {
|
|
258
263
|
const blockId = input.blockId ?? undefined;
|
|
259
264
|
return blockId === undefined ? "look at the page" : `look at ${blockId}`;
|
|
@@ -148,6 +148,11 @@ export function createListPinnedArtifactsTool(deps) {
|
|
|
148
148
|
"Read the listing to orient before you bind a block. Read the columns of one artifact to choose the column that a locator names. " +
|
|
149
149
|
"A reference names the path alone: the session stamps the hash from this evidence, thus the tool gives no hash.",
|
|
150
150
|
inputSchema: listPinnedArtifactsInput,
|
|
151
|
+
view: {
|
|
152
|
+
input: (input) => input,
|
|
153
|
+
result: (_input, result) => result,
|
|
154
|
+
error: true,
|
|
155
|
+
},
|
|
151
156
|
describeCall: (input) => input.path ?? "the pinned set",
|
|
152
157
|
// The size of the listing is what a watcher reads, and the cap makes that size differ from the
|
|
153
158
|
// pinned set. Thus a truncated listing names the total beside the count, and a whole listing names
|
|
@@ -376,6 +376,7 @@ export function createPreviewReportTool(deps) {
|
|
|
376
376
|
"The render marks the page that examine_page looks at next. " +
|
|
377
377
|
"Use it to see the report, and to confirm that each reference resolves.",
|
|
378
378
|
inputSchema: previewReportInput,
|
|
379
|
+
view: "none",
|
|
379
380
|
describeCall: "none",
|
|
380
381
|
// The page path is the one fact of a preview that a watcher wants, and it exists only in the
|
|
381
382
|
// result. Each other arm is a degraded condition whose kind already names it, thus the kind
|
|
@@ -138,6 +138,7 @@ export function createRecordVersionTool(deps) {
|
|
|
138
138
|
"A thread holds one version, thus a later record replaces it whole. Amend the draft, look at the page again, and record again. " +
|
|
139
139
|
"After the version lands, the tool removes the file of each derived table that no block of the recorded report binds.",
|
|
140
140
|
inputSchema: recordVersionInput,
|
|
141
|
+
view: "none",
|
|
141
142
|
describeCall: "none",
|
|
142
143
|
// The version id is the one durable product of the first record, thus the created arm names it. A
|
|
143
144
|
// later record writes over that same id, thus the line names the update and never reads as a
|
|
@@ -40,6 +40,7 @@ function createReadTableTool(deps) {
|
|
|
40
40
|
"A larger table does not derive; tell the user which table is absent.",
|
|
41
41
|
inputSchema: readTableInput,
|
|
42
42
|
outputSchema: ReadTableOutputSchema,
|
|
43
|
+
view: "none",
|
|
43
44
|
describeCall: ({ path }) => path,
|
|
44
45
|
describeResult: (_input, result) => `${String(result.rowCount)} rows`,
|
|
45
46
|
execute: async ({ path, columns }, ctx) => {
|
|
@@ -100,6 +101,7 @@ function createWriteDerivedTool(deps) {
|
|
|
100
101
|
"Name each pinned table that the script read in `inputs`. A name that this session already holds is refused, thus a second derivation of one table takes a new name.",
|
|
101
102
|
inputSchema: writeDerivedInput,
|
|
102
103
|
outputSchema: DerivedOutputSchema,
|
|
104
|
+
view: "none",
|
|
103
105
|
describeCall: ({ name }) => name,
|
|
104
106
|
describeResult: (_input, result) => result.path,
|
|
105
107
|
execute: async ({ name, rows, inputs }, ctx) => {
|
|
@@ -51,6 +51,7 @@ export const resolveLibraryIdTool = defineTool({
|
|
|
51
51
|
libraryName: z.string().describe("Package or library name to search for (e.g., 'scanpy', 'pysam', 'lifelines')."),
|
|
52
52
|
query: z.string().describe("What you need help with — used to rank results by relevance (e.g., 'how to run differential expression')."),
|
|
53
53
|
}),
|
|
54
|
+
view: "none",
|
|
54
55
|
describeCall: "none",
|
|
55
56
|
execute: async ({ libraryName, query }) => {
|
|
56
57
|
const result = await apiFetchValidated(`${CONTEXT7_BASE}/search?query=${encodeURIComponent(libraryName)}&topic=${encodeURIComponent(query)}`, Context7SearchResponseSchema, { maxRetries: 1 });
|
|
@@ -80,6 +81,7 @@ export const queryDocsTool = defineTool({
|
|
|
80
81
|
libraryId: z.string().describe("Context7 library ID exactly as `resolve_library_id` gave it — an owner and a library, for example '/scverse/scanpy'."),
|
|
81
82
|
query: z.string().describe("Specific question about the library (e.g., 'rank_genes_groups function parameters and usage')."),
|
|
82
83
|
}),
|
|
84
|
+
view: "none",
|
|
83
85
|
describeCall: "none",
|
|
84
86
|
execute: async ({ libraryId, query }) => {
|
|
85
87
|
// The library id is the path of the route, not a query parameter. Each
|
|
@@ -47,6 +47,7 @@ function createRecordProblemTool() {
|
|
|
47
47
|
description: "Record the extraction of phase 1: the problem summary, objects, relations, key terms, and the analogies " +
|
|
48
48
|
"that phase 2 searches. A later call replaces the record.",
|
|
49
49
|
inputSchema: RecordProblemInputSchema,
|
|
50
|
+
view: "none",
|
|
50
51
|
describeCall: "none",
|
|
51
52
|
execute: () => Promise.resolve(ok({ recorded: true })),
|
|
52
53
|
});
|
|
@@ -57,6 +58,7 @@ function createRecordAnalogyTool() {
|
|
|
57
58
|
description: "Record one analogy with its coverage and its cited solutions, when its search is done. A later call " +
|
|
58
59
|
"with the same analogyTitle replaces the record.",
|
|
59
60
|
inputSchema: AnalogySchema,
|
|
61
|
+
view: "none",
|
|
60
62
|
describeCall: ({ analogyTitle }) => analogyTitle,
|
|
61
63
|
execute: () => Promise.resolve(ok({ recorded: true })),
|
|
62
64
|
});
|
|
@@ -268,6 +270,7 @@ export function createGenerateAnalogyReportTool(deps, registerSubAgent) {
|
|
|
268
270
|
"A retry with the same or a similar problem statement meets the same " +
|
|
269
271
|
"failure, thus surface the message and ask the user to narrow the problem.",
|
|
270
272
|
inputSchema: generateAnalogyReportInputSchema,
|
|
273
|
+
view: "none",
|
|
271
274
|
describeCall: "none",
|
|
272
275
|
startsWorkflow: true,
|
|
273
276
|
execute: async (input, ctx) => ok(await research(input, ctx)),
|
|
@@ -602,6 +602,7 @@ function buildInnerTools(logger, memory) {
|
|
|
602
602
|
// structured issue reporting.
|
|
603
603
|
plan: z.union([PlannerPlanSchema, z.unknown()]).describe("Candidate plan; malformed values are reported in issues."),
|
|
604
604
|
}),
|
|
605
|
+
view: "none",
|
|
605
606
|
describeCall: "none",
|
|
606
607
|
execute: (input) => {
|
|
607
608
|
// The host owns the grounding fields: it fills them from the last answer of the run.
|
|
@@ -639,6 +640,7 @@ function buildInnerTools(logger, memory) {
|
|
|
639
640
|
question: terminalTextSchema("One short question that names each missing fact, and the step that needs it."),
|
|
640
641
|
questionContext: z.string().optional().describe("Optional context: why the plan needs the fact, and what the inputs already say about it."),
|
|
641
642
|
}),
|
|
643
|
+
view: "none",
|
|
642
644
|
describeCall: "none",
|
|
643
645
|
execute: (input) => Promise.resolve(ok({
|
|
644
646
|
kind: "clarification",
|
|
@@ -1181,6 +1183,10 @@ export function createGeneratePlanTool(deps, registerSubAgent) {
|
|
|
1181
1183
|
"when the planner is missing a fact it cannot infer; or `error` with {error} when no plan was saved (the planner reported " +
|
|
1182
1184
|
"a blocker, the save failed, the call timed out or was cancelled, or parentPlanId is not a plan of this analysis).",
|
|
1183
1185
|
inputSchema: generatePlanInputSchema,
|
|
1186
|
+
view: {
|
|
1187
|
+
input: (input) => input,
|
|
1188
|
+
error: true,
|
|
1189
|
+
},
|
|
1184
1190
|
describeCall: ({ researchQuestion }) => researchQuestion,
|
|
1185
1191
|
startsWorkflow: true,
|
|
1186
1192
|
execute: async (input, ctx) => {
|
|
@@ -136,6 +136,11 @@ export function createInspectDataProfileTool(pool) {
|
|
|
136
136
|
"against when the input set last changed before you conclude anything: if the data moved since, say the profile " +
|
|
137
137
|
"needs re-running rather than diagnosing the data itself.",
|
|
138
138
|
inputSchema: InspectDataProfileInputSchema,
|
|
139
|
+
view: {
|
|
140
|
+
input: (input) => input,
|
|
141
|
+
result: (_input, result) => result,
|
|
142
|
+
error: true,
|
|
143
|
+
},
|
|
139
144
|
// `execute` defaults both fields internally, and the hook applies the same
|
|
140
145
|
// defaults. Without them the ordinary call, which names no field at all,
|
|
141
146
|
// gives no detail. `page` acts only on the `files` scope, as in `execute`.
|
|
@@ -109,6 +109,11 @@ export function createInspectRunTool(pool, clock = systemClock) {
|
|
|
109
109
|
"For a user-directed check, waitForTerminalSeconds can wait once for 1-30 seconds; if the cutoff returns in_progress, stop polling for that turn and tell the user that the run still runs. " +
|
|
110
110
|
"Default response is lightweight — pass includeDiagnostics:true to add error/duration/retry telemetry.",
|
|
111
111
|
inputSchema,
|
|
112
|
+
view: {
|
|
113
|
+
input: (input) => input,
|
|
114
|
+
result: (_input, result) => result,
|
|
115
|
+
error: true,
|
|
116
|
+
},
|
|
112
117
|
// The two calls do different work: one inspects a named run, the other
|
|
113
118
|
// pages the list. Naming the run id is what separates repeated polls of
|
|
114
119
|
// the same run from polls of different ones.
|
|
@@ -14,6 +14,7 @@ export function createResolveCitationTool(resolver) {
|
|
|
14
14
|
"not_found, unverifiable, or inconclusive. Source failure never becomes not_found — an unreachable authority reports unavailable, and " +
|
|
15
15
|
"not_found means the authorities that answered hold no such record.",
|
|
16
16
|
inputSchema: CitationInputSchema,
|
|
17
|
+
view: "none",
|
|
17
18
|
describeCall: ({ citation }) => `verify ${citation}`,
|
|
18
19
|
execute: async (input, ctx) => ok(await resolver.resolveOne(input, { signal: ctx.signal })),
|
|
19
20
|
});
|
|
@@ -39,6 +39,7 @@ export const searchArxivTool = defineTool({
|
|
|
39
39
|
"and that filter is combined with the query using AND."),
|
|
40
40
|
limit: z.number().int().min(1).max(20).default(10).describe("Maximum results (1–20, default 10)."),
|
|
41
41
|
}),
|
|
42
|
+
view: "none",
|
|
42
43
|
describeCall: "none",
|
|
43
44
|
execute: async ({ query, categories, limit }, context) => {
|
|
44
45
|
const result = await source.search({ query, categories, limit }, context.signal);
|
|
@@ -87,6 +87,7 @@ export function createSearchGithubReposTool(deps) {
|
|
|
87
87
|
"lands here). Report either one and continue, do not retry unchanged.",
|
|
88
88
|
outputSchema: SearchGithubReposOutputSchema,
|
|
89
89
|
inputSchema: SearchGithubReposInputSchema,
|
|
90
|
+
view: "none",
|
|
90
91
|
describeCall: "none",
|
|
91
92
|
execute: async ({ query, language, limit }) => {
|
|
92
93
|
const q = language ? `${query} language:${language}` : query;
|
|
@@ -46,6 +46,7 @@ export function createSearchSemanticScholarTool(options = {}) {
|
|
|
46
46
|
'"reinforcement learning for control" or "feedback stabilisation in oscillators".'),
|
|
47
47
|
limit: z.number().int().min(1).max(20).default(10).describe("Maximum number of results to return (1–20, default 10)."),
|
|
48
48
|
}),
|
|
49
|
+
view: "none",
|
|
49
50
|
describeCall: "none",
|
|
50
51
|
execute: async ({ query, limit }, context) => {
|
|
51
52
|
const result = await source.search(query, limit, context.signal);
|
|
@@ -614,6 +614,7 @@ export function createWebFetchTool(deps = {}) {
|
|
|
614
614
|
"private, link-local, or reserved), http_error, redirect_limit, body_too_large, unextractable, and request_failed each name what " +
|
|
615
615
|
"happened. Report the status and continue, do not retry unchanged.",
|
|
616
616
|
inputSchema: WebFetchInputSchema,
|
|
617
|
+
view: "none",
|
|
617
618
|
describeCall: ({ url }) => url,
|
|
618
619
|
execute: async ({ url }, ctx) => ok(await fetchOneUrl(url, deps, ctx)),
|
|
619
620
|
});
|
|
@@ -77,6 +77,7 @@ export function createWebSearchTool(deps) {
|
|
|
77
77
|
"ABSENCE IS NORMAL: an empty results array means no page matched, and a status of http_error, retryable_status, " +
|
|
78
78
|
"schema_mismatch, or not_json names a search that did not answer. Report either one and continue, do not retry unchanged.",
|
|
79
79
|
inputSchema: WebSearchInputSchema,
|
|
80
|
+
view: "none",
|
|
80
81
|
describeCall: "none",
|
|
81
82
|
execute: async ({ query, queries, numResults, recencyFilter, domainFilter }) => {
|
|
82
83
|
const filter = parseDomainFilter(domainFilter);
|
|
@@ -24,6 +24,7 @@ export function createAcquireSandboxTool(lease) {
|
|
|
24
24
|
"size replaces your sandbox: the files of your working directory stay, and the next command runs on the new " +
|
|
25
25
|
"size. Your files and your outputs live in the workspace, not in the sandbox.",
|
|
26
26
|
inputSchema: AcquireSandboxInputSchema,
|
|
27
|
+
view: "none",
|
|
27
28
|
describeCall: ({ cpu, memoryGb }) => `Waiting for a sandbox (${cpu} CPU, ${memoryGb} GB)`,
|
|
28
29
|
execute: async ({ cpu, memoryGb, gpuCount }) => {
|
|
29
30
|
const size = gpuCount === undefined || gpuCount === 0 ? { cpu, memoryGb } : { cpu, memoryGb, gpu: { count: gpuCount } };
|
|
@@ -51,6 +52,7 @@ export function createReleaseSandboxTool(lease) {
|
|
|
51
52
|
description: "Release your sandbox when your commands are done and you work only with files or research. The files stay. " +
|
|
52
53
|
"A later `execute_command` needs `acquire_sandbox` again.",
|
|
53
54
|
inputSchema: ReleaseSandboxInputSchema,
|
|
55
|
+
view: "none",
|
|
54
56
|
describeCall: () => "Releasing the sandbox",
|
|
55
57
|
execute: async () => {
|
|
56
58
|
await lease.release();
|