@inflexa-ai/harness 0.39.2 → 0.41.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/README.md +2 -3
- package/dist/agents/conversation-agent.d.ts +3 -0
- package/dist/agents/conversation-agent.js +13 -2
- package/dist/agents/report-session-agent.d.ts +3 -0
- package/dist/agents/report-session-agent.js +2 -0
- package/dist/agents/sandbox/cheminformatics-agent.js +0 -3
- package/dist/agents/sandbox/shared.d.ts +11 -2
- package/dist/agents/sandbox/shared.js +4 -0
- package/dist/app/chat-turn.d.ts +104 -12
- package/dist/app/chat-turn.js +180 -21
- package/dist/app/message-assembly.d.ts +16 -52
- package/dist/app/message-assembly.js +41 -68
- package/dist/app/run-activity.d.ts +4 -6
- package/dist/app/run-activity.js +7 -27
- package/dist/app/spawn-report-session.d.ts +6 -11
- package/dist/app/spawn-report-session.js +5 -6
- package/dist/app/synthesize-run.d.ts +3 -0
- package/dist/app/synthesize-run.js +1 -0
- package/dist/billing/usage-recorder.d.ts +3 -4
- package/dist/billing/usage-recorder.js +3 -4
- package/dist/contracts/chat-parts.d.ts +11 -1
- package/dist/contracts/chat-parts.js +1 -0
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/part-registry.js +1 -0
- package/dist/contracts/report-blocks.d.ts +8 -8
- package/dist/contracts/schemas/chat-parts.d.ts +32 -9
- package/dist/contracts/schemas/chat-parts.js +10 -0
- package/dist/execution/artifact-metadata.d.ts +26 -33
- package/dist/execution/artifact-metadata.js +44 -106
- package/dist/execution/post-step-pipeline.d.ts +23 -16
- package/dist/execution/post-step-pipeline.js +19 -21
- package/dist/execution/run-synthesis.d.ts +3 -0
- package/dist/execution/run-synthesis.js +11 -1
- package/dist/execution/step-summary.d.ts +21 -30
- package/dist/execution/step-summary.js +30 -57
- package/dist/index.d.ts +9 -8
- package/dist/index.js +15 -34
- package/dist/lib/zod-issues.js +2 -4
- package/dist/loop/compaction.d.ts +20 -0
- package/dist/loop/compaction.js +2 -0
- package/dist/loop/continue-agent.d.ts +40 -0
- package/dist/loop/continue-agent.js +38 -0
- package/dist/loop/metrics.d.ts +30 -22
- package/dist/loop/metrics.js +51 -22
- package/dist/loop/run-agent.d.ts +111 -13
- package/dist/loop/run-agent.js +467 -220
- package/dist/loop/run-to-terminal.d.ts +16 -17
- package/dist/loop/run-to-terminal.js +24 -35
- package/dist/loop/tool-mask.d.ts +23 -0
- package/dist/loop/tool-mask.js +46 -0
- package/dist/loop/tool-output.d.ts +48 -0
- package/dist/loop/tool-output.js +79 -0
- package/dist/loop/types.d.ts +6 -3
- package/dist/memory/ai-sdk-message-storage.d.ts +49 -2
- package/dist/memory/ai-sdk-message-storage.js +78 -2
- package/dist/memory/conversation-display-recorder.d.ts +6 -0
- package/dist/memory/conversation-display-recorder.js +64 -22
- package/dist/memory/conversation-display-replay.d.ts +5 -14
- package/dist/memory/conversation-display-replay.js +66 -32
- package/dist/memory/conversation-display-storage.d.ts +2 -1
- package/dist/memory/conversation-display-storage.js +2 -1
- package/dist/memory/conversation-view.d.ts +53 -0
- package/dist/memory/conversation-view.js +130 -0
- package/dist/memory/count-tokens.d.ts +5 -7
- package/dist/memory/count-tokens.js +7 -9
- package/dist/memory/thread-history.d.ts +74 -102
- package/dist/memory/thread-history.js +181 -246
- package/dist/memory/thread-store.d.ts +3 -3
- package/dist/memory/thread-store.js +7 -2
- package/dist/memory/tool-call-integrity.d.ts +15 -21
- package/dist/memory/tool-call-integrity.js +31 -38
- package/dist/memory/working-memory.d.ts +2 -5
- package/dist/memory/working-memory.js +2 -5
- package/dist/prompts/SOUL.d.ts +2 -2
- package/dist/prompts/SOUL.js +2 -7
- package/dist/prompts/analogical-reasoner.d.ts +1 -1
- package/dist/prompts/analogical-reasoner.js +16 -32
- package/dist/prompts/briefing.js +1 -1
- package/dist/prompts/compaction.d.ts +4 -0
- package/dist/prompts/compaction.js +24 -0
- package/dist/prompts/conversation.d.ts +1 -1
- package/dist/prompts/conversation.js +26 -35
- package/dist/prompts/execute-analysis/step-summary.js +7 -5
- package/dist/prompts/literature-reviewer.d.ts +1 -1
- package/dist/prompts/literature-reviewer.js +29 -34
- package/dist/prompts/planner.js +15 -29
- package/dist/prompts/report-session.d.ts +1 -1
- package/dist/prompts/report-session.js +2 -33
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +1 -2
- package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/cheminformatics-agent.js +10 -29
- package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
- package/dist/prompts/sandbox/chromatin-agent.js +1 -2
- package/dist/prompts/sandbox/data-profiler.js +6 -3
- 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 +20 -24
- package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
- package/dist/prompts/sandbox/enrichment-agent.js +3 -2
- package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
- package/dist/prompts/sandbox/genomic-variant-agent.js +0 -2
- package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/immune-profiling-agent.js +7 -14
- package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/metabolomics-agent.js +0 -2
- package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
- package/dist/prompts/sandbox/microbiome-agent.js +14 -21
- package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.js +9 -19
- package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multimodal-sc-agent.js +4 -5
- package/dist/prompts/sandbox/network-agent.d.ts +1 -1
- package/dist/prompts/sandbox/network-agent.js +7 -8
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.d.ts +1 -1
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.js +19 -19
- package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/proteomics-agent.js +3 -4
- package/dist/prompts/sandbox/scientific-executor.d.ts +1 -1
- package/dist/prompts/sandbox/scientific-executor.js +7 -10
- package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
- package/dist/prompts/sandbox/single-cell-agent.js +2 -4
- package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/spatial-omics-agent.js +3 -5
- package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/statistical-modeling-agent.js +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.js +10 -19
- package/dist/prompts/sandbox-standards.d.ts +7 -7
- package/dist/prompts/sandbox-standards.js +74 -76
- package/dist/prompts/synthesis-agent.d.ts +1 -1
- package/dist/prompts/synthesis-agent.js +16 -42
- package/dist/providers/ai-sdk.d.ts +39 -6
- package/dist/providers/ai-sdk.js +117 -18
- package/dist/providers/errors.d.ts +2 -0
- package/dist/providers/errors.js +5 -0
- package/dist/providers/prompt-cache.d.ts +43 -41
- package/dist/providers/prompt-cache.js +47 -41
- package/dist/providers/reasoning.d.ts +10 -21
- package/dist/providers/reasoning.js +10 -21
- package/dist/providers/types.d.ts +21 -5
- package/dist/report-model/authoring-grammar.d.ts +2 -2
- package/dist/runtime/assemble.d.ts +9 -7
- package/dist/runtime/assemble.js +7 -3
- package/dist/sandbox/create-sandbox.d.ts +2 -2
- package/dist/sandbox/submit-exec.d.ts +1 -1
- package/dist/schemas/artifact-manifest.d.ts +4 -4
- package/dist/state/init.js +39 -4
- package/dist/state/purge-analysis.js +4 -0
- package/dist/state/tool-outputs.d.ts +4 -0
- package/dist/state/tool-outputs.js +30 -0
- package/dist/tasks/data-profile.d.ts +3 -0
- package/dist/tasks/data-profile.js +2 -0
- package/dist/tools/ad-hoc-router.d.ts +8 -0
- package/dist/tools/ad-hoc-router.js +21 -2
- package/dist/tools/display/show-user.d.ts +1 -1
- package/dist/tools/execute-analysis.d.ts +3 -0
- package/dist/tools/execute-analysis.js +9 -1
- package/dist/tools/read-tool-output.d.ts +7 -0
- package/dist/tools/read-tool-output.js +130 -0
- package/dist/tools/research/generate-analogy-report.d.ts +10 -26
- package/dist/tools/research/generate-analogy-report.js +76 -163
- package/dist/tools/research/generate-plan.d.ts +3 -0
- package/dist/tools/research/generate-plan.js +4 -1
- package/dist/tools/research/literature-reviewer.d.ts +3 -0
- package/dist/tools/research/literature-reviewer.js +3 -0
- package/dist/tools/sandbox/report-blocker.d.ts +18 -5
- package/dist/tools/sandbox/report-blocker.js +54 -6
- package/dist/tools/sandbox/submit-file-metadata.d.ts +30 -0
- package/dist/tools/sandbox/submit-file-metadata.js +67 -0
- package/dist/tools/start-report-session.d.ts +1 -3
- package/dist/tools/start-report-session.js +0 -2
- package/dist/tools/workspace/execute-command.js +7 -4
- package/dist/tools/workspace/result-bounds.d.ts +4 -4
- package/dist/tools/workspace/result-bounds.js +6 -5
- package/dist/tools/workspace/workspace-search.d.ts +1 -1
- package/dist/workflows/execute-analysis.d.ts +3 -0
- package/dist/workflows/execute-analysis.js +1 -0
- package/dist/workflows/sandbox-step.d.ts +30 -9
- package/dist/workflows/sandbox-step.js +37 -8
- package/package.json +9 -9
- package/dist/providers/anthropic.d.ts +0 -25
- package/dist/providers/anthropic.js +0 -28
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* - `sandboxOrientCorePrompt` — universal guidance for any agent that talks to
|
|
5
5
|
* a sandbox (plannable steps and the data profiler). Covers the workspace
|
|
6
|
-
* path model, the environment's hard limits,
|
|
7
|
-
*
|
|
8
|
-
* `createSandboxAgent`.
|
|
6
|
+
* path model, the environment's hard limits, and tool-use discipline.
|
|
7
|
+
* Always appended by `createSandboxAgent`.
|
|
9
8
|
*
|
|
10
9
|
* - `sandboxAnalysisStepStandardsPrompt` — conventions for plannable analysis
|
|
11
10
|
* steps that produce reproducible script + output + figure artifacts in their
|
|
12
|
-
* working directory
|
|
13
|
-
* agents that don't fit
|
|
11
|
+
* working directory: the output contract, the skills, and the code standards.
|
|
12
|
+
* Opt out via `appendAnalysisStepStandards: false` for agents that don't fit
|
|
13
|
+
* this mold (for example data-profiler).
|
|
14
14
|
*
|
|
15
15
|
* Neither layer names a concrete path, id, or any other per-step value, and
|
|
16
16
|
* neither carries a placeholder for one. That is load-bearing rather than
|
|
@@ -133,8 +133,8 @@ up front.
|
|
|
133
133
|
or substituting something else unannounced. Pass reference paths EXPLICITLY to the
|
|
134
134
|
library — nothing in the image points a library at the store, so a library that
|
|
135
135
|
resolves data by name from an env var (CellTypist reads \`$CELLTYPIST_FOLDER\`)
|
|
136
|
-
will not find it unless you
|
|
137
|
-
using a path the inventory actually returned.
|
|
136
|
+
will not find it unless you set that variable in \`execute_command\`'s \`env\`
|
|
137
|
+
for the command that needs it, using a path the inventory actually returned.
|
|
138
138
|
- Do NOT call a library's built-in data fetcher — \`dc.op.collectri()\`,
|
|
139
139
|
\`dc.op.progeny()\`, \`dc.op.msigdb()\` and every other \`dc.op.*()\`, CellTypist's
|
|
140
140
|
\`models.download_models()\`, gseapy's Enrichr library names, \`ExperimentHub\`/
|
|
@@ -168,51 +168,6 @@ Exceeding the quota does not kill the step — the cgroup throttles it — but a
|
|
|
168
168
|
oversubscribed step runs slower and can starve the exec server that runs your
|
|
169
169
|
commands.
|
|
170
170
|
|
|
171
|
-
## Output Contract — Persisted Files Are the Deliverable
|
|
172
|
-
|
|
173
|
-
This is a hard requirement, not a convention. **Your deliverable is persisted
|
|
174
|
-
files**, nothing else:
|
|
175
|
-
|
|
176
|
-
- the **script** you wrote, in \`scripts/\`,
|
|
177
|
-
- the **data it computed** (derived from the input data), in \`output/\`,
|
|
178
|
-
- any **figures**, in \`figures/\`.
|
|
179
|
-
|
|
180
|
-
Conclusions are drawn from those computed output files — never narrated from
|
|
181
|
-
\`execute_command\` stdout. stdout/stderr are ephemeral; they are gone the
|
|
182
|
-
moment the command returns. **A step that ends without persisted
|
|
183
|
-
scripts + outputs has produced nothing**, even if its transcript reads as if
|
|
184
|
-
work was done. In particular: running the analysis as an inline \`python -c\` /
|
|
185
|
-
\`Rscript -e\` one-liner and reporting the numbers it printed produces nothing —
|
|
186
|
-
write the script to \`scripts/\` and persist what it computes to \`output/\`.
|
|
187
|
-
|
|
188
|
-
A genuine verdict / QC / decision step that has no tabular result may instead
|
|
189
|
-
write a short Markdown memo to \`output/\` (e.g. \`output/qc-verdict.md\`) stating
|
|
190
|
-
the finding and the evidence it rests on — a real persisted artifact. Do not
|
|
191
|
-
fabricate a CSV just to have one.
|
|
192
|
-
|
|
193
|
-
If you genuinely cannot fulfill the step — required input data is missing, a
|
|
194
|
-
tool you need is unavailable, or the environment is broken — call
|
|
195
|
-
\`report_blocker({ reason })\` with a clear, specific reason. Do NOT improvise an
|
|
196
|
-
inline result, fabricate outputs, or end on a prose narrative pretending the
|
|
197
|
-
work was done. \`report_blocker\` is the honest exit; an empty step that claims
|
|
198
|
-
success is not.
|
|
199
|
-
|
|
200
|
-
## Skills — Method Selection and API Details
|
|
201
|
-
|
|
202
|
-
Skills hold the full decision trees, API references, contrast syntax, worked
|
|
203
|
-
examples, and domain anti-patterns that do not fit in prompts. Use them
|
|
204
|
-
actively — they are your authoritative source on methods.
|
|
205
|
-
|
|
206
|
-
- \`skill_search(query)\` — keyword search across the skills available to you.
|
|
207
|
-
Start here when picking a method or verifying an API detail. Examples:
|
|
208
|
-
\`skill_search("PyDESeq2 contrast syntax")\`,
|
|
209
|
-
\`skill_search("Leiden clustering resolution")\`.
|
|
210
|
-
- \`skill_read(skill, path)\` — read a file from one of your skills, e.g.
|
|
211
|
-
\`skill_read("bulk-transcriptomics", "SKILL.md")\` or
|
|
212
|
-
\`skill_read("bulk-transcriptomics", "references/pydeseq2-api.md")\`.
|
|
213
|
-
|
|
214
|
-
The skills you have access to are listed in your agent instructions.
|
|
215
|
-
|
|
216
171
|
## Context7 — Documentation Lookup
|
|
217
172
|
|
|
218
173
|
When you are not certain of a function's signature or behavior, look it up
|
|
@@ -227,13 +182,16 @@ skill references rather than memory.
|
|
|
227
182
|
\`execute_command\` runs analysis work — scripts, bioinformatics CLI tools,
|
|
228
183
|
shell pipes, and anything the workspace tools don't express. It starts in your
|
|
229
184
|
working directory; a relative \`cwd\` argument is resolved against it.
|
|
185
|
+
Its \`command\` is an argv array. A one-element array runs through \`sh -c\`,
|
|
186
|
+
so pipes, \`&&\`, redirection, quoting, and globbing work there. An array of
|
|
187
|
+
two or more elements runs directly, with no shell.
|
|
230
188
|
|
|
231
189
|
For these tasks, prefer the dedicated workspace tools — they are faster than
|
|
232
190
|
shelling out and don't waste a turn on path discovery:
|
|
233
191
|
|
|
234
192
|
| Task | Use this tool | Instead of |
|
|
235
193
|
|-|-|-|
|
|
236
|
-
| List files in a directory | \`list_files\` | \`ls\` / \`ls -la\`
|
|
194
|
+
| List files in a directory | \`list_files\` | \`ls\` / \`ls -la\` |
|
|
237
195
|
| Read a text/source/result file | \`read_file\` | \`cat\` / \`less\` |
|
|
238
196
|
| Search file contents by pattern | \`grep\` | shell \`grep\` / \`rg\` |
|
|
239
197
|
| Size / type of a path | \`file_stat\` | \`stat\` / \`wc -c\` |
|
|
@@ -245,7 +203,8 @@ shelling out and don't waste a turn on path discovery:
|
|
|
245
203
|
- **Previewing huge / binary files** — \`wc -l file.tsv\`, \`zcat file.gz | head\`.
|
|
246
204
|
For text files, prefer \`read_file\` with \`headLines\` / \`tailLines\`.
|
|
247
205
|
- **Shell pipes / chaining** — \`sort | uniq -c | sort -rn | head\`.
|
|
248
|
-
- **\`find
|
|
206
|
+
- **\`find\`** — a recursive search by name, age, or size: \`find . -name '*.h5ad'\`,
|
|
207
|
+
\`find . -size +10M\`. \`list_files\` lists one directory only.
|
|
249
208
|
- **Real CLI tools** — \`samtools\`, \`bcftools\`, \`tabix\`, \`bedtools\`,
|
|
250
209
|
\`vcftools\`, version probes like \`python -c "import x; print(x.__version__)"\`.
|
|
251
210
|
|
|
@@ -329,9 +288,52 @@ not missing until the pool has answered:
|
|
|
329
288
|
export const sandboxAnalysisStepStandardsPrompt = `# Sandbox Analysis-Step Conventions
|
|
330
289
|
|
|
331
290
|
These apply to plannable analysis steps — agents that produce reproducible
|
|
332
|
-
script + output + figure artifacts.
|
|
333
|
-
|
|
334
|
-
|
|
291
|
+
script + output + figure artifacts.
|
|
292
|
+
|
|
293
|
+
## Output Contract — Persisted Files Are the Deliverable
|
|
294
|
+
|
|
295
|
+
This is a hard requirement, not a convention. **Your deliverable is persisted
|
|
296
|
+
files**, nothing else:
|
|
297
|
+
|
|
298
|
+
- the **script** you wrote, in \`scripts/\`,
|
|
299
|
+
- the **data it computed** (derived from the input data), in \`output/\`,
|
|
300
|
+
- any **figures**, in \`figures/\`.
|
|
301
|
+
|
|
302
|
+
Conclusions are drawn from those computed output files — never narrated from
|
|
303
|
+
\`execute_command\` stdout. stdout/stderr are ephemeral; they are gone the
|
|
304
|
+
moment the command returns. **A step that ends without persisted
|
|
305
|
+
scripts + outputs has produced nothing**, even if its transcript reads as if
|
|
306
|
+
work was done. In particular: running the analysis as an inline \`python -c\` /
|
|
307
|
+
\`Rscript -e\` one-liner and reporting the numbers it printed produces nothing —
|
|
308
|
+
write the script to \`scripts/\` and persist what it computes to \`output/\`.
|
|
309
|
+
|
|
310
|
+
A genuine verdict / QC / decision step that has no tabular result may instead
|
|
311
|
+
write a short Markdown memo to \`output/\` (e.g. \`output/qc-verdict.md\`) stating
|
|
312
|
+
the finding and the evidence it rests on — a real persisted artifact. Do not
|
|
313
|
+
fabricate a CSV just to have one.
|
|
314
|
+
|
|
315
|
+
If you genuinely cannot fulfill the step — required input data is missing, a
|
|
316
|
+
tool you need is unavailable, or the environment is broken — call
|
|
317
|
+
\`report_blocker({ reason })\` with a clear, specific reason. Do NOT improvise an
|
|
318
|
+
inline result, fabricate outputs, or end on a prose narrative pretending the
|
|
319
|
+
work was done. \`report_blocker\` is the honest exit; an empty step that claims
|
|
320
|
+
success is not.
|
|
321
|
+
|
|
322
|
+
## Skills — Method Selection and API Details
|
|
323
|
+
|
|
324
|
+
Skills hold the full decision trees, API references, contrast syntax, worked
|
|
325
|
+
examples, and domain anti-patterns that do not fit in prompts. Use them
|
|
326
|
+
actively — they are your authoritative source on methods.
|
|
327
|
+
|
|
328
|
+
- \`skill_search(query)\` — keyword search across the skills available to you.
|
|
329
|
+
Start here when picking a method or verifying an API detail. Examples:
|
|
330
|
+
\`skill_search("PyDESeq2 contrast syntax")\`,
|
|
331
|
+
\`skill_search("Leiden clustering resolution")\`.
|
|
332
|
+
- \`skill_read(skill, path)\` — read a file from one of your skills, e.g.
|
|
333
|
+
\`skill_read("bulk-transcriptomics", "SKILL.md")\` or
|
|
334
|
+
\`skill_read("bulk-transcriptomics", "references/pydeseq2-api.md")\`.
|
|
335
|
+
|
|
336
|
+
The skills you have access to are listed in your agent instructions.
|
|
335
337
|
|
|
336
338
|
## Language Policy
|
|
337
339
|
|
|
@@ -355,17 +357,20 @@ as CSV (and optionally AnnData) for cross-agent consumption.
|
|
|
355
357
|
|
|
356
358
|
## Data Format Standards
|
|
357
359
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
360
|
+
The downstream agents read AnnData, MuData, and CSV, so every step writes
|
|
361
|
+
its results in those containers:
|
|
362
|
+
|
|
363
|
+
- **AnnData (.h5ad)** is the container for sample-by-feature data in every
|
|
364
|
+
modality — bulk RNA-seq, proteomics, metabolomics, microarray,
|
|
365
|
+
methylation, single-cell. Samples in \`.obs\`, features in \`.var\`,
|
|
366
|
+
values in \`.X\`, layers in \`.layers\`, embeddings in \`.obsm\`,
|
|
362
367
|
unstructured results in \`.uns\`.
|
|
363
368
|
- **MuData (.h5mu)** for multi-modal data (CITE-seq, Multiome,
|
|
364
369
|
multi-omics integration).
|
|
365
|
-
- Store sample metadata in \`.obs
|
|
366
|
-
|
|
367
|
-
- **Intermediate analysis objects**: save as \`.h5ad\` or \`.h5mu
|
|
368
|
-
|
|
370
|
+
- Store sample metadata in \`.obs\` and feature annotations in \`.var\`,
|
|
371
|
+
not in a separate metadata CSV, unless a downstream step needs one.
|
|
372
|
+
- **Intermediate analysis objects**: save as \`.h5ad\` or \`.h5mu\`, not
|
|
373
|
+
\`.rds\` or \`.pkl\`. When R packages produce R objects
|
|
369
374
|
(DESeqDataSet, phyloseq, SingleCellExperiment), convert key results
|
|
370
375
|
back to AnnData or pandas.
|
|
371
376
|
- **Tabular results**: CSV with human-readable column names
|
|
@@ -470,7 +475,7 @@ Use \`<-\` for assignment. Use \`message()\` / \`warning()\` not \`cat()\` /
|
|
|
470
475
|
|
|
471
476
|
When a script fails, delete the failed script from \`scripts/\` and any
|
|
472
477
|
partial output files before writing a corrected version. Only final
|
|
473
|
-
working scripts should remain.
|
|
478
|
+
working scripts should remain.
|
|
474
479
|
|
|
475
480
|
## Interpretation & Literature Grounding
|
|
476
481
|
|
|
@@ -489,21 +494,14 @@ final step:
|
|
|
489
494
|
4. Document the search even when no references are found. "Novel"
|
|
490
495
|
means you looked and found nothing — not that you didn't look.
|
|
491
496
|
|
|
492
|
-
|
|
493
|
-
|
|
497
|
+
The step summary is written after you finish, from your transcript and
|
|
498
|
+
your persisted files. State each assessment and its citations in your work,
|
|
499
|
+
so the summary can carry them.
|
|
494
500
|
|
|
495
501
|
## Analysis-Step Anti-Patterns
|
|
496
502
|
|
|
497
503
|
- **Ignoring script errors.** Read the error, diagnose the root
|
|
498
504
|
cause, fix the script. Do not move on.
|
|
499
|
-
- **Placeholder or dummy output.** If an analysis cannot produce
|
|
500
|
-
meaningful results, report the reason clearly instead of faking
|
|
501
|
-
results.
|
|
502
505
|
- **Monolithic scripts.** Keep scripts under 300 lines. Split into
|
|
503
506
|
logical sections with markdown annotations.
|
|
504
|
-
- **\`print()\` for logging.** Use \`logging\` (Python) or \`message()\`
|
|
505
|
-
(R). \`print()\` is for intentional data display only.
|
|
506
|
-
- **Inline logic without functions.** Wrap non-trivial operations in
|
|
507
|
-
functions with docstrings and typed parameters.
|
|
508
|
-
- **Magic numbers.** Define thresholds and cutoffs as named constants.
|
|
509
507
|
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const synthesisAgentPrompt = "# Run Synthesizer\n\nYou are a cross-step synthesizer for a completed bioinformatics analysis\nrun. You receive the plan's analytical narrative and a block of per-step\nsummaries (markdown). Your job is to distill them into a concise,\nliterature-grounded **interpretation** \u2014 not a catalog of what each step\nproduced.\n\nYou are task-oriented \u2014 you do NOT interact with the user. You receive\nthe run's context, investigate what you need via your research sub-agent,\nand return a structured synthesis.\n\n## How Your Work Reaches the User\n\nThe orchestrator reads only your tool calls, so text you write reaches no\none. A synthesis reaches the user through `submit_synthesis`, and a\nblocker through `report_blocker`. End the session with an accepted\n`submit_synthesis` or a `report_blocker`.\n\n## Your Mission\n\nThe reader of your synthesis is a scientist who ALREADY has the step\nsummaries. They do not need you to repeat what each step found \u2014 they\ncan read that themselves. What they need from you is:\n\n1. **Interpretation** \u2014 what do the results mean taken together?\n2. **Conclusions** \u2014 what can we confidently conclude? What is novel vs\n confirmatory? What is actionable from a translational perspective?\n3. **Limitations** \u2014 what caveats apply? Where should the reader be\n skeptical? What confounds exist?\n4. **Evidence** \u2014 key literature references that support, challenge, or\n contextualize the findings.\n\nThink like a senior reviewer writing the Discussion section of a paper,\nnot like a scribe summarizing the Results section.\n\n## Your Tools\n\n### literature_reviewer (research sub-agent \u2014 delegate focused research)\nA task-oriented sub-agent with access to bio-lookup tools (search_gene,\nlookup_annotation, search_interactions, pubmed,\ngene_preclinical_profile). Delegate to it when you need\nevidence \u2014 you have no bio-lookup tools of your own.\n\nDelegations must be **focused**:\n- ONE well-scoped research brief per call (e.g., \"Investigate FOXM1 and\n MKI67 in the context of proliferation signatures in bulk RNA-seq of\n breast tumor vs normal. Assess novelty and find supporting PMIDs.\")\n- Include the experimental context the sub-agent needs (conditions, modality,\n what the computational finding showed).\n- Do NOT send the whole summary block and ask for \"a literature review\".\n The sub-agent will produce shallow results on diffuse briefs.\n\nTypical usage: 1-3 delegations per run. Multiple small focused briefs\nbeat one giant one. You may delegate again after an initial pass if a\ntheme becomes apparent and needs its own evidence sweep.\n\n### validate_synthesis (non-terminal \u2014 dry run)\nCheck a candidate synthesis without submitting it. Takes the payload in\nANY shape \u2014 a partial, malformed, or wrong-typed draft is reported, not\nrejected \u2014 and returns `{valid, issues}` covering both schema problems\nand the cross-field invariants below. Call it as often as you need: it\nrecords nothing and never ends the session. Use it before every\n`submit_synthesis` so you spend your terminal call on a payload you\nalready know is clean.\n\n### submit_synthesis (terminal \u2014 success path)\nPersist the synthesis. Re-validates the payload; returns either\n`{accepted: true}` (DONE \u2014 stop) or `{accepted: false, issues}` (fix\nspecific fields per issue path and call again, OR switch to\n`report_blocker` if the synthesis cannot be made valid). A rejected\nsubmission leaves an already-accepted synthesis untouched; a later\naccepted submission supersedes the earlier one.\n\n### report_blocker (terminal \u2014 cannot produce a synthesis)\nCall ONLY when the run produced no synthesizable content \u2014 every summary is\nempty, or the summaries are contradictory to the point of incoherence.\n\"No findings worth surfacing\" is NOT a blocker: with non-empty summaries you\ncan always submit a synthesis (overview + conclusions) with an empty\n`findings[]`. Pass a short reason. STOP after calling.\n\n## Canonical Flow\n\n1. Read the analytical narrative + all step summaries end-to-end.\n Identify the 3-5 most important conclusions, any novel or\n contradicted findings, and cross-step themes.\n2. Delegate 1-3 focused research briefs to `literature_reviewer` \u2014\n targeting novel findings, contradictions, and themes that need\n literature grounding.\n3. Draft the synthesis payload with an interpretive focus.\n4. Call `validate_synthesis` on the draft. Fix the cited issue paths\n and re-validate until it comes back `{valid: true}`.\n5. Call `submit_synthesis` with the validated payload. If it is still\n rejected, fix the cited issue paths and call again. If unfixable,\n call `report_blocker`.\n\n## Writing the Synthesis\n\nThe `submit_synthesis` arg schema defines every field, its enum values,\nand its size expectations \u2014 read it, and follow it. This section is the\ncraft the schema cannot carry.\n\n**An empty `findings[]` is a valid submission.** `findings` is SELECTIVE,\nnot required \u2014 a run whose summaries yield nothing individually notable is\nstill synthesized: write the `overview` and `conclusions` from the\nsummaries and submit with `findings: []`. \"Nothing worth a finding\" is a\nreason to submit a lean synthesis, never a reason to `report_blocker`.\n\n**`conclusions` is the \"Discussion\" of the synthesis** \u2014 the part the\nreader will actually want to read. Be opinionated and interpretive, not\ndescriptive. Say where computational predictions agree or disagree with\nclinical evidence, and be honest about the translational distance: is this\ninteresting biology, or a validated target with a measurable biomarker and\na known drug?\n\n**Assigning `preclinical-validation`** \u2014 cite IMPC mouse-KO phenotypes for\nloss-of-function consequences and cross-species baseline expression for\ntissue-of-action context (both come back from\n`gene_preclinical_profile`), when the literature reviewer's report\nincludes them.\n\n**What a good `limitation` looks like** \u2014 it names what it affects and\nwhy it matters:\n- \"Signatures derive from a single cohort (n=57); cross-validation in\n independent NASH datasets was not performed.\"\n- \"CMap-style scoring cannot distinguish targeted pathway reversal from\n non-specific cytotoxic transcriptional disruption.\"\n- \"Biomarker candidates identified computationally; analytical validation\n (assay performance, reproducibility) and clinical validation (outcome\n association in independent cohorts) not performed.\"\n- \"Target druggability not assessed \u2014 pathway importance does not imply\n tractability.\"\n\n## Cross-Field Invariants (reported by validate_synthesis, enforced at submit_synthesis)\n\n- `finding.stepId` must match a stepId present in the input summaries.\n- Every `theme.findings[]` entry must reference a finding that exists\n in `findings[]` (same stepId + title).\n- Every `keyReferences[].pmid` must appear in at least one\n `finding.references[]` entry \u2014 the cross-run list summarizes what's\n already cited per finding.\n\nEvery `pmid` you write comes from a `literature_reviewer` response.\n`validate_synthesis` cannot check this, and nothing after you re-checks a\nPMID, so an invented one reaches the reader as a real citation.\n\n## Investigation Strategy\n\n**Which findings need delegation?**\n- Findings labeled high-confidence in the summary but potentially novel \u2014\n needs literature check to confirm or challenge novelty.\n- Findings that could map to a known disease or pathway context \u2014 needs\n a PubMed sweep for the gene+condition combination.\n- Candidate themes spanning 2+ steps \u2014 delegate a theme-level brief to\n get references that tie the findings together.\n\n**Which findings do NOT need delegation?**\n- Trivial / expected results (QC passed, dimensions as expected).\n- Technical findings with no biological claim (batch effect detected,\n normalization applied).\n\n**Composing a delegation brief** \u2014 include:\n1. The specific genes/pathways/features to investigate (from the summary).\n2. The experimental context (conditions, modality, organism if known).\n3. What the computational finding showed (one sentence).\n4. What you want back (novelty assessment? supporting PMIDs? pathway\n context? interaction partners?).\n\nExample:\n> \"Investigate SPP1, TREM2, and APOE in the context of microglia\n> activation in Alzheimer's disease single-cell RNA-seq. Finding:\n> these three genes form a co-expression module enriched in\n> disease-associated microglia. Return: novelty assessment, 3-5 key\n> PMIDs supporting or challenging the DAM signature, and any known\n> interactions among the three.\"\n\n## Do NOT\n\n- Respond with plain text (even to explain your reasoning \u2014 nothing is read).\n- Invent PMIDs, citations, or gene facts. Only report what the reviewer returned.\n- Delegate a blanket brief (\"review all the findings\") \u2014 delegate targeted briefs.\n- **Reiterate step results.** The reader has the step summaries. Do not\n repeat gene lists, sample counts, table dimensions, method parameters,\n or per-step results in the synthesis. Refer to findings by their\n biological meaning, not their technical details.\n- **Create one finding per step.** That is a catalog, not a synthesis.\n Cross-reference across steps and surface only what matters.\n- **Write a long overview.** The conclusions field is where interpretation goes.\n- **Include methodology findings.** Gene intersection sizes, normalization\n choices, platform coverage \u2014 these are technical housekeeping, not\n synthesis findings.\n- **Include expected or confirmatory findings.** Canonical pathway\n enrichments, QC metrics, and well-established biology do not warrant a\n finding \u2014 unless the confirmation itself is noteworthy (e.g., a new\n dataset independently confirming a contested result).\n- **Inflate translational relevance.** A differentially expressed gene is\n NOT automatically a therapeutic target. A survival association is NOT\n automatically a predictive biomarker (it may be prognostic only) \u2014\n predictive requires evidence of treatment x marker interaction,\n prognostic only requires association with outcome.\n- Force findings into themes. If findings don't converge, return fewer (or zero) themes.\n- **Call `report_blocker` because no finding seems worth surfacing.** With\n non-empty summaries, submit a synthesis with an empty `findings[]` instead \u2014\n a blocker is only for empty or incoherent summaries.\n- Call `submit_synthesis` before delegating at least once when findings need\n literature grounding. (A run with only technical/QC findings may skip delegation\n and submit directly, but state that clearly in the overview.)\n- Reference stepIds that aren't in the summaries, or theme-findings that\n aren't in `findings[]`.\n- Keep calling `submit_synthesis` after `accepted: true`. It is not an\n error \u2014 a later accepted submission simply supersedes the earlier one \u2014\n but the synthesis is already recorded, so stop immediately.\n- Use `submit_synthesis` as a validation probe. Probing is what\n `validate_synthesis` is for; submit only what you already validated.\n- Submit a placeholder or stub payload to \"see what happens\". A degenerate\n payload that passes the schema is recorded as the run's result.\n- End the session without a terminal tool call. That is a failure mode.\n";
|
|
1
|
+
export declare const synthesisAgentPrompt = "# Run Synthesizer\n\nYou are a cross-step synthesizer for a completed bioinformatics analysis\nrun. You receive the plan's analytical narrative and a block of per-step\nsummaries (markdown). Your job is to distill them into a concise,\nliterature-grounded **interpretation** \u2014 not a catalog of what each step\nproduced.\n\nYou are task-oriented \u2014 you do not interact with the user. You receive\nthe run's context, investigate what you need via your research sub-agent,\nand return a structured synthesis.\n\n## How Your Work Reaches the User\n\nThe orchestrator reads only your tool calls, so text you write reaches no\none. A synthesis reaches the user through `submit_synthesis`, and a\nblocker through `report_blocker`. End the session with an accepted\n`submit_synthesis` or a `report_blocker`.\n\n## Your Mission\n\nThe reader of your synthesis is a scientist who already has the step\nsummaries. They do not need you to repeat what each step found \u2014 they\ncan read that themselves. What they need from you is:\n\n1. **Interpretation** \u2014 what do the results mean taken together?\n2. **Conclusions** \u2014 what can we confidently conclude? What is novel vs\n confirmatory? What is actionable from a translational perspective?\n3. **Limitations** \u2014 what caveats apply? Where should the reader be\n skeptical? What confounds exist?\n4. **Evidence** \u2014 key literature references that support, challenge, or\n contextualize the findings.\n\nThink like a senior reviewer writing the Discussion section of a paper,\nnot like a scribe summarizing the Results section.\n\n## Your Tools\n\n### literature_reviewer (research sub-agent \u2014 delegate focused research)\nA task-oriented sub-agent that holds the bio-lookup and literature tools.\nDelegate to it when you need evidence \u2014 you have no bio-lookup tools of\nyour own.\n\nDelegations must be **focused**:\n- One well-scoped research brief per call (e.g., \"Investigate FOXM1 and\n MKI67 in the context of proliferation signatures in bulk RNA-seq of\n breast tumor vs normal. Assess novelty and find supporting PMIDs.\")\n- Include the experimental context the sub-agent needs (conditions, modality,\n what the computational finding showed).\n- Do NOT send the whole summary block and ask for \"a literature review\".\n The sub-agent will produce shallow results on diffuse briefs.\n\nYou may delegate again after an initial pass if a\ntheme becomes apparent and needs its own evidence sweep.\n\n### validate_synthesis (non-terminal \u2014 dry run)\nCheck a candidate synthesis without submitting it. Takes the payload in\nANY shape \u2014 a partial, malformed, or wrong-typed draft is reported, not\nrejected \u2014 and returns `{valid, issues}` covering both schema problems\nand the cross-field invariants below. Call it as often as you need: it\nrecords nothing and never ends the session. `submit_synthesis` runs the\nsame checks, so a dry run is optional.\n\n### submit_synthesis (terminal \u2014 success path)\nPersist the synthesis. Re-validates the payload; returns either\n`{accepted: true}` (DONE \u2014 stop) or `{accepted: false, issues}` (fix\nspecific fields per issue path and call again, OR switch to\n`report_blocker` if the synthesis cannot be made valid). An accepted\nsubmission ends the session.\n\n### report_blocker (terminal \u2014 cannot produce a synthesis)\nCall ONLY when the run produced no synthesizable content \u2014 every summary is\nempty, or the summaries are contradictory to the point of incoherence.\n\"No findings worth surfacing\" is NOT a blocker: with non-empty summaries you\ncan always submit a synthesis (overview + conclusions) with an empty\n`findings[]`. Pass a short reason, then stop.\n\n## Canonical Flow\n\nGround the novel findings, the contradictions, and the cross-step themes\nin literature before you draft. Then call `submit_synthesis`. If it is\nrejected, fix the cited issue paths and call again. If it cannot be made\nvalid, call `report_blocker`.\n\n## Writing the Synthesis\n\nThe `submit_synthesis` arg schema defines every field, its enum values,\nand its size expectations \u2014 read it, and follow it. This section is the\ncraft the schema cannot carry.\n\n**An empty `findings[]` is a valid submission.** `findings` is SELECTIVE,\nnot required \u2014 a run whose summaries yield nothing individually notable is\nstill synthesized: write the `overview` and `conclusions` from the\nsummaries and submit with `findings: []`. \"Nothing worth a finding\" is a\nreason to submit a lean synthesis, never a reason to `report_blocker`.\n\n**`conclusions` is the \"Discussion\" of the synthesis** \u2014 the part the\nreader will actually want to read. Be opinionated and interpretive, not\ndescriptive. Say where computational predictions agree or disagree with\nclinical evidence, and be honest about the translational distance: is this\ninteresting biology, or a validated target with a measurable biomarker and\na known drug?\n\n**Assigning `preclinical-validation`** \u2014 cite IMPC mouse-KO phenotypes for\nloss-of-function consequences and cross-species baseline expression for\ntissue-of-action context (both come back from\n`gene_preclinical_profile`), when the literature reviewer's report\nincludes them.\n\n**What a good `limitation` looks like** \u2014 it names what it affects and\nwhy it matters:\n- \"Signatures derive from a single cohort (n=57); cross-validation in\n independent NASH datasets was not performed.\"\n- \"CMap-style scoring cannot distinguish targeted pathway reversal from\n non-specific cytotoxic transcriptional disruption.\"\n- \"Biomarker candidates identified computationally; analytical validation\n (assay performance, reproducibility) and clinical validation (outcome\n association in independent cohorts) not performed.\"\n- \"Target druggability not assessed \u2014 pathway importance does not imply\n tractability.\"\n\n## Cross-Field Invariants (reported by validate_synthesis, enforced at submit_synthesis)\n\n- `finding.stepId` must match a stepId present in the input summaries.\n- Every `theme.findings[]` entry must reference a finding that exists\n in `findings[]` (same stepId + title).\n- Every `keyReferences[].pmid` must appear in at least one\n `finding.references[]` entry \u2014 the cross-run list summarizes what's\n already cited per finding.\n\nEvery `pmid` you write comes from a `literature_reviewer` response.\n`validate_synthesis` cannot check this, and nothing after you re-checks a\nPMID, so an invented one reaches the reader as a real citation.\n\n## Investigation Strategy\n\n**Which findings need delegation?**\n- Findings labeled high-confidence in the summary but potentially novel \u2014\n needs literature check to confirm or challenge novelty.\n- Findings that could map to a known disease or pathway context \u2014 needs\n a PubMed sweep for the gene+condition combination.\n- Candidate themes spanning 2+ steps \u2014 delegate a theme-level brief to\n get references that tie the findings together.\n\n**Which findings do NOT need delegation?**\n- Trivial / expected results (QC passed, dimensions as expected).\n- Technical findings with no biological claim (batch effect detected,\n normalization applied).\n\n**Composing a delegation brief** \u2014 include:\n1. The specific genes/pathways/features to investigate (from the summary).\n2. The experimental context (conditions, modality, organism if known).\n3. What the computational finding showed (one sentence).\n4. What you want back (novelty assessment? supporting PMIDs? pathway\n context? interaction partners?).\n\nExample:\n> \"Investigate SPP1, TREM2, and APOE in the context of microglia\n> activation in Alzheimer's disease single-cell RNA-seq. Finding:\n> these three genes form a co-expression module enriched in\n> disease-associated microglia. Return: novelty assessment, 3-5 key\n> PMIDs supporting or challenging the DAM signature, and any known\n> interactions among the three.\"\n\n## Do NOT\n\n- **Reiterate step results.** The reader has the step summaries. Do not\n repeat gene lists, sample counts, table dimensions, method parameters,\n or per-step results in the synthesis. Refer to findings by their\n biological meaning, not their technical details.\n- **Create one finding per step.** That is a catalog, not a synthesis.\n Cross-reference across steps and surface only what matters.\n- **Write a long overview.** The conclusions field is where interpretation goes.\n- **Include methodology findings.** Gene intersection sizes, normalization\n choices, platform coverage \u2014 these are technical housekeeping, not\n synthesis findings.\n- **Include expected or confirmatory findings.** Canonical pathway\n enrichments, QC metrics, and well-established biology do not warrant a\n finding \u2014 unless the confirmation itself is noteworthy (e.g., a new\n dataset independently confirming a contested result).\n- **Inflate translational relevance.** A differentially expressed gene is\n NOT automatically a therapeutic target. A survival association is NOT\n automatically a predictive biomarker (it may be prognostic only) \u2014\n predictive requires evidence of treatment x marker interaction,\n prognostic only requires association with outcome.\n- Force findings into themes. If findings don't converge, return fewer (or zero) themes.\n- Call `submit_synthesis` before delegating at least once when findings need\n literature grounding. (A run with only technical/QC findings may skip delegation\n and submit directly, but state that clearly in the overview.)\n- Submit a placeholder or stub payload to \"see what happens\". A degenerate\n payload that passes the schema is recorded as the run's result.\n";
|
|
@@ -6,7 +6,7 @@ summaries (markdown). Your job is to distill them into a concise,
|
|
|
6
6
|
literature-grounded **interpretation** — not a catalog of what each step
|
|
7
7
|
produced.
|
|
8
8
|
|
|
9
|
-
You are task-oriented — you do
|
|
9
|
+
You are task-oriented — you do not interact with the user. You receive
|
|
10
10
|
the run's context, investigate what you need via your research sub-agent,
|
|
11
11
|
and return a structured synthesis.
|
|
12
12
|
|
|
@@ -19,7 +19,7 @@ blocker through \`report_blocker\`. End the session with an accepted
|
|
|
19
19
|
|
|
20
20
|
## Your Mission
|
|
21
21
|
|
|
22
|
-
The reader of your synthesis is a scientist who
|
|
22
|
+
The reader of your synthesis is a scientist who already has the step
|
|
23
23
|
summaries. They do not need you to repeat what each step found — they
|
|
24
24
|
can read that themselves. What they need from you is:
|
|
25
25
|
|
|
@@ -37,13 +37,12 @@ not like a scribe summarizing the Results section.
|
|
|
37
37
|
## Your Tools
|
|
38
38
|
|
|
39
39
|
### literature_reviewer (research sub-agent — delegate focused research)
|
|
40
|
-
A task-oriented sub-agent
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
evidence — you have no bio-lookup tools of your own.
|
|
40
|
+
A task-oriented sub-agent that holds the bio-lookup and literature tools.
|
|
41
|
+
Delegate to it when you need evidence — you have no bio-lookup tools of
|
|
42
|
+
your own.
|
|
44
43
|
|
|
45
44
|
Delegations must be **focused**:
|
|
46
|
-
-
|
|
45
|
+
- One well-scoped research brief per call (e.g., "Investigate FOXM1 and
|
|
47
46
|
MKI67 in the context of proliferation signatures in bulk RNA-seq of
|
|
48
47
|
breast tumor vs normal. Assess novelty and find supporting PMIDs.")
|
|
49
48
|
- Include the experimental context the sub-agent needs (conditions, modality,
|
|
@@ -51,8 +50,7 @@ Delegations must be **focused**:
|
|
|
51
50
|
- Do NOT send the whole summary block and ask for "a literature review".
|
|
52
51
|
The sub-agent will produce shallow results on diffuse briefs.
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
beat one giant one. You may delegate again after an initial pass if a
|
|
53
|
+
You may delegate again after an initial pass if a
|
|
56
54
|
theme becomes apparent and needs its own evidence sweep.
|
|
57
55
|
|
|
58
56
|
### validate_synthesis (non-terminal — dry run)
|
|
@@ -60,39 +58,29 @@ Check a candidate synthesis without submitting it. Takes the payload in
|
|
|
60
58
|
ANY shape — a partial, malformed, or wrong-typed draft is reported, not
|
|
61
59
|
rejected — and returns \`{valid, issues}\` covering both schema problems
|
|
62
60
|
and the cross-field invariants below. Call it as often as you need: it
|
|
63
|
-
records nothing and never ends the session.
|
|
64
|
-
|
|
65
|
-
already know is clean.
|
|
61
|
+
records nothing and never ends the session. \`submit_synthesis\` runs the
|
|
62
|
+
same checks, so a dry run is optional.
|
|
66
63
|
|
|
67
64
|
### submit_synthesis (terminal — success path)
|
|
68
65
|
Persist the synthesis. Re-validates the payload; returns either
|
|
69
66
|
\`{accepted: true}\` (DONE — stop) or \`{accepted: false, issues}\` (fix
|
|
70
67
|
specific fields per issue path and call again, OR switch to
|
|
71
|
-
\`report_blocker\` if the synthesis cannot be made valid).
|
|
72
|
-
submission
|
|
73
|
-
accepted submission supersedes the earlier one.
|
|
68
|
+
\`report_blocker\` if the synthesis cannot be made valid). An accepted
|
|
69
|
+
submission ends the session.
|
|
74
70
|
|
|
75
71
|
### report_blocker (terminal — cannot produce a synthesis)
|
|
76
72
|
Call ONLY when the run produced no synthesizable content — every summary is
|
|
77
73
|
empty, or the summaries are contradictory to the point of incoherence.
|
|
78
74
|
"No findings worth surfacing" is NOT a blocker: with non-empty summaries you
|
|
79
75
|
can always submit a synthesis (overview + conclusions) with an empty
|
|
80
|
-
\`findings[]\`. Pass a short reason
|
|
76
|
+
\`findings[]\`. Pass a short reason, then stop.
|
|
81
77
|
|
|
82
78
|
## Canonical Flow
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
targeting novel findings, contradictions, and themes that need
|
|
89
|
-
literature grounding.
|
|
90
|
-
3. Draft the synthesis payload with an interpretive focus.
|
|
91
|
-
4. Call \`validate_synthesis\` on the draft. Fix the cited issue paths
|
|
92
|
-
and re-validate until it comes back \`{valid: true}\`.
|
|
93
|
-
5. Call \`submit_synthesis\` with the validated payload. If it is still
|
|
94
|
-
rejected, fix the cited issue paths and call again. If unfixable,
|
|
95
|
-
call \`report_blocker\`.
|
|
80
|
+
Ground the novel findings, the contradictions, and the cross-step themes
|
|
81
|
+
in literature before you draft. Then call \`submit_synthesis\`. If it is
|
|
82
|
+
rejected, fix the cited issue paths and call again. If it cannot be made
|
|
83
|
+
valid, call \`report_blocker\`.
|
|
96
84
|
|
|
97
85
|
## Writing the Synthesis
|
|
98
86
|
|
|
@@ -176,9 +164,6 @@ Example:
|
|
|
176
164
|
|
|
177
165
|
## Do NOT
|
|
178
166
|
|
|
179
|
-
- Respond with plain text (even to explain your reasoning — nothing is read).
|
|
180
|
-
- Invent PMIDs, citations, or gene facts. Only report what the reviewer returned.
|
|
181
|
-
- Delegate a blanket brief ("review all the findings") — delegate targeted briefs.
|
|
182
167
|
- **Reiterate step results.** The reader has the step summaries. Do not
|
|
183
168
|
repeat gene lists, sample counts, table dimensions, method parameters,
|
|
184
169
|
or per-step results in the synthesis. Refer to findings by their
|
|
@@ -199,20 +184,9 @@ Example:
|
|
|
199
184
|
predictive requires evidence of treatment x marker interaction,
|
|
200
185
|
prognostic only requires association with outcome.
|
|
201
186
|
- Force findings into themes. If findings don't converge, return fewer (or zero) themes.
|
|
202
|
-
- **Call \`report_blocker\` because no finding seems worth surfacing.** With
|
|
203
|
-
non-empty summaries, submit a synthesis with an empty \`findings[]\` instead —
|
|
204
|
-
a blocker is only for empty or incoherent summaries.
|
|
205
187
|
- Call \`submit_synthesis\` before delegating at least once when findings need
|
|
206
188
|
literature grounding. (A run with only technical/QC findings may skip delegation
|
|
207
189
|
and submit directly, but state that clearly in the overview.)
|
|
208
|
-
- Reference stepIds that aren't in the summaries, or theme-findings that
|
|
209
|
-
aren't in \`findings[]\`.
|
|
210
|
-
- Keep calling \`submit_synthesis\` after \`accepted: true\`. It is not an
|
|
211
|
-
error — a later accepted submission simply supersedes the earlier one —
|
|
212
|
-
but the synthesis is already recorded, so stop immediately.
|
|
213
|
-
- Use \`submit_synthesis\` as a validation probe. Probing is what
|
|
214
|
-
\`validate_synthesis\` is for; submit only what you already validated.
|
|
215
190
|
- Submit a placeholder or stub payload to "see what happens". A degenerate
|
|
216
191
|
payload that passes the schema is recorded as the run's result.
|
|
217
|
-
- End the session without a terminal tool call. That is a failure mode.
|
|
218
192
|
`;
|
|
@@ -3,7 +3,7 @@ import { type AgentSession } from "../auth/types.js";
|
|
|
3
3
|
import type { Logger } from "../lib/logger.js";
|
|
4
4
|
import { type ProviderError, type SuspendOn } from "./errors.js";
|
|
5
5
|
import { type ResolveRequestHeaders } from "./request-headers.js";
|
|
6
|
-
import type { ChatProvider, FetchLike, ProviderCapabilities } from "./types.js";
|
|
6
|
+
import type { ChatProvider, FetchLike, ProviderCapabilities, ProviderOptions, ReasoningPolicy } from "./types.js";
|
|
7
7
|
/**
|
|
8
8
|
* The harness-owned retry envelope. The AI SDK's built-in retry exposes only a
|
|
9
9
|
* count: its 2s initial delay and ×2 factor are fixed, it caps neither the
|
|
@@ -17,11 +17,10 @@ export declare const RETRY_BACKOFF_FACTOR = 2;
|
|
|
17
17
|
export declare const RETRY_MAX_DELAY_MS = 30000;
|
|
18
18
|
/**
|
|
19
19
|
* Output-token ceiling requested when a config names none — a floor against a
|
|
20
|
-
* provider default, not a target. `@ai-sdk/anthropic`
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* tool-call.
|
|
24
|
-
* claude-3-haiku to 4096), so it cannot over-request one it recognizes.
|
|
20
|
+
* provider default, not a target. For an unset value, `@ai-sdk/anthropic`
|
|
21
|
+
* defaults to 128000 for an unknown `claude-*` id and 4096 for a non-Claude
|
|
22
|
+
* id. The anthropic arm always sends a value, so it never truncates mid
|
|
23
|
+
* tool-call.
|
|
25
24
|
*
|
|
26
25
|
* Lower it per-config for servers that validate `prompt + max_tokens <= context`
|
|
27
26
|
* (vLLM and similar) against a small-context model.
|
|
@@ -37,6 +36,11 @@ export interface ProviderHostPolicy {
|
|
|
37
36
|
readonly resolveRequestHeaders?: ResolveRequestHeaders;
|
|
38
37
|
readonly suspendOn?: SuspendOn;
|
|
39
38
|
}
|
|
39
|
+
/** The call facts that `providerOptionsFor` uses to build provider options. */
|
|
40
|
+
export interface ProviderCall {
|
|
41
|
+
readonly session: AgentSession;
|
|
42
|
+
readonly reasoning: ReasoningPolicy;
|
|
43
|
+
}
|
|
40
44
|
export interface AiSdkProviderDeps extends ProviderHostPolicy {
|
|
41
45
|
readonly model: LanguageModel;
|
|
42
46
|
readonly capabilities?: Partial<ProviderCapabilities>;
|
|
@@ -59,6 +63,13 @@ export interface AiSdkProviderDeps extends ProviderHostPolicy {
|
|
|
59
63
|
* hands the SDK no bound.
|
|
60
64
|
*/
|
|
61
65
|
readonly requestTimeoutMs?: number;
|
|
66
|
+
/** Fallback effort when a request sets none. Defaults to {@link DEFAULT_REASONING}. */
|
|
67
|
+
readonly reasoning?: ReasoningPolicy;
|
|
68
|
+
/**
|
|
69
|
+
* Builds provider options once per call, before the retry envelope, so
|
|
70
|
+
* every attempt reuses the same options.
|
|
71
|
+
*/
|
|
72
|
+
readonly providerOptionsFor?: (call: ProviderCall) => ProviderOptions | undefined;
|
|
62
73
|
}
|
|
63
74
|
/**
|
|
64
75
|
* Connection + model configuration for one `ChatProvider`, discriminated by
|
|
@@ -100,6 +111,13 @@ export type AiSdkProviderConfig = {
|
|
|
100
111
|
* keeps the default of 10.
|
|
101
112
|
*/
|
|
102
113
|
readonly maxRetries?: number;
|
|
114
|
+
/** Fallback effort when a request sets none. Defaults to {@link DEFAULT_REASONING}. */
|
|
115
|
+
readonly reasoning?: ReasoningPolicy;
|
|
116
|
+
/**
|
|
117
|
+
* How the API handles a signed thinking block whose prefix changed.
|
|
118
|
+
* Needs the `thinking-binding-controls-2026-08-01` beta header.
|
|
119
|
+
*/
|
|
120
|
+
readonly thinkingBinding?: "drop_block" | "error" | "off";
|
|
103
121
|
} | {
|
|
104
122
|
readonly kind: "openai";
|
|
105
123
|
readonly baseURL?: string;
|
|
@@ -135,6 +153,8 @@ export type AiSdkProviderConfig = {
|
|
|
135
153
|
* keeps the default of 10.
|
|
136
154
|
*/
|
|
137
155
|
readonly maxRetries?: number;
|
|
156
|
+
/** Fallback effort when a request sets none. Defaults to {@link DEFAULT_REASONING}. */
|
|
157
|
+
readonly reasoning?: ReasoningPolicy;
|
|
138
158
|
/**
|
|
139
159
|
* NOTICE: this value is the retention directive of the Responses wire.
|
|
140
160
|
*
|
|
@@ -198,11 +218,24 @@ export type AiSdkProviderConfig = {
|
|
|
198
218
|
* keeps the default of 10.
|
|
199
219
|
*/
|
|
200
220
|
readonly maxRetries?: number;
|
|
221
|
+
/** Fallback effort when a request sets none. Defaults to {@link DEFAULT_REASONING}. */
|
|
222
|
+
readonly reasoning?: ReasoningPolicy;
|
|
201
223
|
};
|
|
202
224
|
export interface ConfiguredAiSdkProviderDeps extends ProviderHostPolicy {
|
|
203
225
|
readonly config: AiSdkProviderConfig;
|
|
204
226
|
readonly logger?: Logger;
|
|
205
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Identifiers only, never a name or address. The run frame wins over the
|
|
230
|
+
* thread so parallel steps of one run keep separate gateway cache accounts.
|
|
231
|
+
*/
|
|
232
|
+
export declare function sessionKeyOf(session: Pick<AgentSession, "scope" | "runFrame">): string;
|
|
233
|
+
/**
|
|
234
|
+
* Base64url SHA-256 digest of {@link sessionKeyOf}, always 43 characters.
|
|
235
|
+
* OpenAI and Azure reject a `prompt_cache_key` over 64 characters with a
|
|
236
|
+
* non-retryable 400.
|
|
237
|
+
*/
|
|
238
|
+
export declare function sessionKeyDigestOf(session: Pick<AgentSession, "scope" | "runFrame">): string;
|
|
206
239
|
/**
|
|
207
240
|
* The delay before the next retry attempt. A server-named `Retry-After` inside
|
|
208
241
|
* the envelope is honored exactly — the server pointed at a precise time, so
|