@inflexa-ai/harness 0.46.2 → 0.48.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 -2
- package/dist/agents/conversation-agent.d.ts +7 -6
- package/dist/agents/conversation-agent.js +26 -4
- package/dist/agents/report-session-agent.d.ts +14 -14
- package/dist/agents/report-session-agent.js +40 -26
- package/dist/agents/sandbox/shared.d.ts +18 -13
- package/dist/agents/sandbox/shared.js +42 -27
- package/dist/agents/sandbox/types.d.ts +1 -1
- package/dist/agents/sandbox-catalog.d.ts +2 -0
- package/dist/agents/sandbox-catalog.js +30 -1
- package/dist/app/synthesize-run.d.ts +10 -6
- package/dist/app/synthesize-run.js +4 -2
- package/dist/contracts/analogy-report.d.ts +46 -2
- package/dist/contracts/analogy-report.js +31 -25
- package/dist/contracts/chat-parts.d.ts +3 -14
- package/dist/contracts/report-reference.d.ts +2 -1
- package/dist/contracts/report-reference.js +2 -1
- package/dist/contracts/schemas/chat-parts.d.ts +0 -27
- package/dist/contracts/schemas/chat-parts.js +1 -3
- package/dist/execution/run-canceler.d.ts +2 -0
- package/dist/execution/run-canceler.js +9 -0
- package/dist/execution/run-synthesis.d.ts +36 -8
- package/dist/execution/run-synthesis.js +114 -32
- package/dist/index.d.ts +5 -6
- package/dist/index.js +5 -7
- package/dist/input-scan/enrich.d.ts +5 -10
- package/dist/input-scan/enrich.js +12 -8
- package/dist/lib/hooks.d.ts +1 -1
- package/dist/lib/markdown-pdf.d.ts +27 -0
- package/dist/lib/markdown-pdf.js +236 -0
- package/dist/lib/metrics.d.ts +31 -0
- package/dist/lib/metrics.js +64 -0
- package/dist/lib/pdf-text.d.ts +23 -0
- package/dist/lib/pdf-text.js +34 -0
- package/dist/lib/regulatory-corpus/fetch-fda-guidance.js +3 -5
- package/dist/lib/regulatory-corpus/fetch-ich.js +3 -5
- package/dist/loop/chat-stream.js +2 -1
- package/dist/loop/run-loop.d.ts +5 -0
- package/dist/loop/run-loop.js +30 -2
- package/dist/loop/tool-name-repair.d.ts +11 -0
- package/dist/loop/tool-name-repair.js +23 -0
- package/dist/loop/types.d.ts +19 -0
- package/dist/memory/card-builders.d.ts +1 -1
- package/dist/prompts/SOUL.d.ts +6 -6
- package/dist/prompts/SOUL.js +22 -121
- package/dist/prompts/analogical-reasoner.d.ts +1 -1
- package/dist/prompts/analogical-reasoner.js +35 -101
- package/dist/prompts/briefing.d.ts +20 -11
- package/dist/prompts/briefing.js +36 -19
- package/dist/prompts/conversation.d.ts +1 -1
- package/dist/prompts/conversation.js +103 -383
- package/dist/prompts/planner.d.ts +1 -5
- package/dist/prompts/planner.js +45 -128
- package/dist/prompts/report-session.d.ts +1 -1
- package/dist/prompts/report-session.js +29 -58
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +3 -3
- package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/cheminformatics-agent.js +12 -47
- package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
- package/dist/prompts/sandbox/chromatin-agent.js +4 -5
- package/dist/prompts/sandbox/data-profiler.js +11 -34
- package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
- package/dist/prompts/sandbox/dna-methylation-agent.js +3 -1
- package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
- package/dist/prompts/sandbox/drug-repurposing-agent.js +23 -73
- package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
- package/dist/prompts/sandbox/enrichment-agent.js +3 -1
- package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
- package/dist/prompts/sandbox/genomic-variant-agent.js +3 -4
- package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/immune-profiling-agent.js +5 -4
- package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/metabolomics-agent.js +3 -1
- package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
- package/dist/prompts/sandbox/microbiome-agent.js +3 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.js +3 -1
- package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multimodal-sc-agent.js +3 -1
- package/dist/prompts/sandbox/network-agent.d.ts +1 -1
- package/dist/prompts/sandbox/network-agent.js +3 -1
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.d.ts +1 -1
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.js +4 -7
- package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/proteomics-agent.js +3 -1
- package/dist/prompts/sandbox/scientific-executor.d.ts +1 -1
- package/dist/prompts/sandbox/scientific-executor.js +0 -12
- package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
- package/dist/prompts/sandbox/single-cell-agent.js +3 -1
- package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/spatial-omics-agent.js +3 -1
- package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/statistical-modeling-agent.js +4 -4
- package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.js +10 -29
- package/dist/prompts/sandbox-standards.d.ts +15 -18
- package/dist/prompts/sandbox-standards.js +96 -305
- package/dist/prompts/synthesis-agent.d.ts +1 -1
- package/dist/prompts/synthesis-agent.js +24 -90
- package/dist/provenance/collector.d.ts +2 -5
- package/dist/provenance/collector.js +2 -5
- package/dist/provenance/seam.d.ts +36 -1
- package/dist/provenance/workspace-reads.d.ts +36 -0
- package/dist/provenance/workspace-reads.js +33 -0
- package/dist/report-model/production-resolver.d.ts +22 -52
- package/dist/report-model/production-resolver.js +43 -112
- package/dist/report-render/chart-export.d.ts +9 -0
- package/dist/report-render/chart-export.js +1 -1
- package/dist/report-render/views/chart-view.d.ts +1 -0
- package/dist/report-render/views/chart-view.js +1 -0
- package/dist/report-render/views/lineage.d.ts +1 -0
- package/dist/report-render/views/page-view.d.ts +1 -0
- package/dist/report-render/views/page-view.js +1 -0
- package/dist/report-render/views/prose.d.ts +1 -0
- package/dist/report-render/views/prose.js +1 -0
- package/dist/report-render/views/references-view.d.ts +1 -0
- package/dist/report-render/views/values.d.ts +1 -0
- package/dist/report-render/views/values.js +1 -0
- package/dist/runtime/assemble.d.ts +32 -12
- package/dist/runtime/assemble.js +49 -38
- package/dist/sandbox/client.d.ts +5 -3
- package/dist/sandbox/create-sandbox.d.ts +7 -12
- package/dist/sandbox/create-sandbox.js +15 -37
- package/dist/sandbox/docker-client.d.ts +1 -3
- package/dist/sandbox/docker-client.js +3 -5
- package/dist/sandbox/exec-outcome.d.ts +11 -11
- package/dist/sandbox/exec-outcome.js +22 -22
- package/dist/sandbox/exec.d.ts +5 -0
- package/dist/sandbox/exec.js +9 -1
- package/dist/sandbox/identity.d.ts +4 -16
- package/dist/sandbox/identity.js +5 -21
- package/dist/sandbox/k8s-client.d.ts +0 -1
- package/dist/sandbox/k8s-client.js +8 -13
- package/dist/sandbox/lease-names.d.ts +6 -0
- package/dist/sandbox/lease-names.js +12 -0
- package/dist/sandbox/leases.d.ts +105 -0
- package/dist/sandbox/leases.js +519 -0
- package/dist/sandbox/liveness.d.ts +5 -2
- package/dist/sandbox/mount-plan.d.ts +10 -1
- package/dist/sandbox/mount-plan.js +7 -1
- package/dist/sandbox/reconciler.d.ts +58 -0
- package/dist/sandbox/reconciler.js +153 -0
- package/dist/sandbox/sandbox-step-translate.d.ts +1 -1
- package/dist/sandbox/types.d.ts +25 -18
- package/dist/sandbox/types.js +10 -4
- package/dist/schemas/plan-schemas.d.ts +0 -21
- package/dist/schemas/plan-schemas.js +2 -3
- package/dist/schemas/run-synthesis.d.ts +2 -2
- package/dist/schemas/run-synthesis.js +3 -3
- package/dist/schemas/validate-plan.d.ts +1 -14
- package/dist/schemas/validate-plan.js +5 -24
- package/dist/schemas/workflow-state.d.ts +3 -32
- package/dist/schemas/workflow-state.js +4 -13
- package/dist/state/index.d.ts +2 -3
- package/dist/state/index.js +1 -2
- package/dist/state/migrations/20261030120000_lease_the_sandboxes.d.ts +7 -0
- package/dist/state/migrations/20261030120000_lease_the_sandboxes.js +34 -0
- package/dist/state/migrations/20261030120100_drop_the_report_derivations.d.ts +5 -0
- package/dist/state/migrations/20261030120100_drop_the_report_derivations.js +9 -0
- package/dist/state/migrations/20261030120200_keep_the_report_derivations.d.ts +6 -0
- package/dist/state/migrations/20261030120200_keep_the_report_derivations.js +10 -0
- package/dist/state/migrations/index.js +6 -0
- package/dist/state/purge-analysis.d.ts +4 -2
- package/dist/state/purge-analysis.js +22 -11
- package/dist/state/sandbox-leases.d.ts +81 -0
- package/dist/state/sandbox-leases.js +247 -0
- package/dist/state/schema.d.ts +1 -13
- package/dist/state/schema.js +1 -6
- package/dist/state/step-executions.d.ts +13 -2
- package/dist/state/step-executions.js +23 -4
- package/dist/tasks/data-profile.d.ts +40 -2
- package/dist/tasks/data-profile.js +89 -87
- package/dist/tools/ad-hoc-router.d.ts +1 -6
- package/dist/tools/ad-hoc-router.js +5 -48
- package/dist/tools/bio/comptox.js +1 -1
- package/dist/tools/bio/drug-gene-interactions.js +1 -1
- package/dist/tools/bio/gene-disease-evidence.js +1 -1
- package/dist/tools/bio/keys.d.ts +1 -1
- package/dist/tools/bio/pubmed.js +31 -0
- package/dist/tools/bio/search-gene.js +17 -0
- package/dist/tools/bio/search-geo-datasets.js +13 -0
- package/dist/tools/bio/search-regulatory-approvals.js +1 -1
- package/dist/tools/define-tool.d.ts +25 -2
- package/dist/tools/define-tool.js +11 -1
- package/dist/tools/display/show-user.js +1 -1
- package/dist/tools/execute-analysis.d.ts +1 -3
- package/dist/tools/execute-analysis.js +5 -33
- package/dist/tools/report-authoring/authoring-tools.d.ts +2 -2
- package/dist/tools/report-authoring/authoring-tools.js +31 -6
- package/dist/tools/report-session/index.d.ts +0 -1
- package/dist/tools/report-session/index.js +0 -1
- package/dist/tools/report-session/script-tools.d.ts +33 -0
- package/dist/tools/report-session/script-tools.js +186 -0
- package/dist/tools/research/generate-analogy-report.d.ts +16 -9
- package/dist/tools/research/generate-analogy-report.js +111 -49
- package/dist/tools/research/generate-plan.d.ts +102 -7
- package/dist/tools/research/generate-plan.js +74 -43
- package/dist/tools/research/index.d.ts +4 -3
- package/dist/tools/research/index.js +4 -3
- package/dist/tools/research/inspect-run.d.ts +0 -1
- package/dist/tools/research/inspect-run.js +5 -10
- package/dist/tools/research/search-arxiv.js +15 -0
- package/dist/tools/research/search-github-repos.js +13 -0
- package/dist/tools/research/search-semantic-scholar.js +16 -0
- package/dist/tools/research/synthesis-lookups.d.ts +21 -0
- package/dist/tools/research/synthesis-lookups.js +29 -0
- package/dist/tools/research/web-fetch.d.ts +1 -1
- package/dist/tools/research/web-fetch.js +14 -12
- package/dist/tools/sandbox/lease-tools.d.ts +32 -0
- package/dist/tools/sandbox/lease-tools.js +60 -0
- package/dist/tools/script/archive.d.ts +34 -0
- package/dist/tools/script/archive.js +182 -0
- package/dist/tools/script/codemode-worker.d.ts +5 -0
- package/dist/tools/script/codemode-worker.js +5 -0
- package/dist/tools/script/file-tools.d.ts +106 -0
- package/dist/tools/script/file-tools.js +491 -0
- package/dist/tools/script/metrics.d.ts +30 -0
- package/dist/tools/script/metrics.js +53 -0
- package/dist/tools/script/quickjs.wasm +0 -0
- package/dist/tools/script/run-script.d.ts +76 -0
- package/dist/tools/script/run-script.js +413 -0
- package/dist/tools/script/scratch.d.ts +84 -0
- package/dist/tools/script/scratch.js +145 -0
- package/dist/tools/start-report-session.js +1 -1
- package/dist/tools/workspace/edit-file.js +2 -1
- package/dist/tools/workspace/execute-command.d.ts +9 -13
- package/dist/tools/workspace/execute-command.js +23 -19
- package/dist/tools/workspace/file-stat.js +1 -1
- package/dist/tools/workspace/grep.d.ts +5 -2
- package/dist/tools/workspace/grep.js +19 -10
- package/dist/tools/workspace/mutator.d.ts +51 -4
- package/dist/tools/workspace/mutator.js +54 -13
- package/dist/tools/workspace/read-file.d.ts +5 -2
- package/dist/tools/workspace/read-file.js +15 -11
- package/dist/tools/workspace/read-surface.d.ts +17 -0
- package/dist/tools/workspace/read-surface.js +17 -0
- package/dist/tools/workspace/result-bounds.d.ts +1 -0
- package/dist/tools/workspace/run-exec.d.ts +12 -13
- package/dist/tools/workspace/run-exec.js +13 -13
- package/dist/tools/workspace/scan-inputs.d.ts +2 -5
- package/dist/tools/workspace/scan-inputs.js +2 -3
- package/dist/tools/workspace/show-file.js +1 -1
- package/dist/tools/workspace/show-plan.js +4 -3
- package/dist/tools/workspace/write-file.js +2 -1
- package/dist/workflows/execute-analysis-scheduler.d.ts +0 -26
- package/dist/workflows/execute-analysis-scheduler.js +12 -32
- package/dist/workflows/execute-analysis.d.ts +17 -35
- package/dist/workflows/execute-analysis.js +13 -107
- package/dist/workflows/pause.js +29 -22
- package/dist/workflows/sandbox-step.d.ts +16 -31
- package/dist/workflows/sandbox-step.js +36 -71
- package/dist/workflows/test/sql-writes.d.ts +0 -1
- package/dist/workflows/test/sql-writes.js +0 -2
- package/dist/workspace/filesystem.d.ts +2 -2
- package/dist/workspace/filesystem.js +10 -5
- package/dist/workspace/paths.d.ts +19 -1
- package/dist/workspace/paths.js +22 -1
- package/dist/workspace/session-files.d.ts +35 -0
- package/dist/workspace/session-files.js +16 -0
- package/package.json +7 -3
- package/dist/prompts/literature-reviewer.d.ts +0 -1
- package/dist/prompts/literature-reviewer.js +0 -114
- package/dist/sandbox/reaper.d.ts +0 -81
- package/dist/sandbox/reaper.js +0 -161
- package/dist/sandbox/step-sandbox.d.ts +0 -47
- package/dist/sandbox/step-sandbox.js +0 -53
- package/dist/state/active-sandboxes.d.ts +0 -33
- package/dist/state/active-sandboxes.js +0 -65
- package/dist/tasks/extract-values-script.d.ts +0 -64
- package/dist/tasks/extract-values-script.js +0 -180
- package/dist/tasks/extract-values.d.ts +0 -77
- package/dist/tasks/extract-values.js +0 -146
- package/dist/tools/report-session/derive-table.d.ts +0 -164
- package/dist/tools/report-session/derive-table.js +0 -419
- package/dist/tools/research/literature-reviewer.d.ts +0 -42
- package/dist/tools/research/literature-reviewer.js +0 -107
- package/dist/workflows/metrics.d.ts +0 -23
- package/dist/workflows/metrics.js +0 -38
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ No embedder drives the agent loop. A host opens a chat turn with the `open` of `
|
|
|
50
50
|
|
|
51
51
|
A failure that a person or time can repair pauses a turn, a run, or a data profile, and the work does not fail. Examples are a billing refusal of the host, a provider outage, and a missing credential. A host lists the active work of an analysis with `CoreRuntime.work`. It stops a work in each state, and it resumes or holds paused work.
|
|
52
52
|
|
|
53
|
-
`assembleCoreRuntime` is the single composition point: it registers the durable workflows and builds the conversation agent over them. The harness declares **four capability seams** an embedder wires — `RunAuthorizer`, `ArtifactRegistry`, `RunCharge`, `UsageRecorder` — plus the **shared `RunLauncher`** (one host-neutral realization, `createDbosRunLauncher`). Local, dependency-free realizations of all four ship from the barrel; an embedder constructs them (or its own) and passes them in. The harness only ever sees the interface. Two optional hooks go into the component that uses their values: `resolveRequestHeaders` into each provider, and `resolveSandboxLabels` into the sandbox client config.
|
|
53
|
+
`assembleCoreRuntime` is the single composition point: it registers the durable workflows and builds the conversation agent over them. The harness declares **four capability seams** an embedder wires — `RunAuthorizer`, `ArtifactRegistry`, `RunCharge`, `UsageRecorder` — plus the **shared `RunLauncher`** (one host-neutral realization, `createDbosRunLauncher`). Local, dependency-free realizations of all four ship from the barrel; an embedder constructs them (or its own) and passes them in. The harness only ever sees the interface. Two optional hooks go into the component that uses their values: `resolveRequestHeaders` into each provider, and `resolveSandboxLabels` into the sandbox client config. A third, `syncSessionFile`, goes into `assembleCoreRuntime`: it receives each file that a chat thread or a report session writes outside a run.
|
|
54
54
|
|
|
55
55
|
## Logging
|
|
56
56
|
|
|
@@ -101,7 +101,7 @@ function pinoAsHarnessLogger(p: pino.Logger, names: readonly string[] = []): Log
|
|
|
101
101
|
|
|
102
102
|
A chat turn is a **durable workflow**. The harness stores the opening, each round, and the outcome of the turn, and a recovery continues a turn from its checkpoints. The harness ships no HTTP layer, thus the host owns the route. Compute-heavy work runs as durable workflows too — `executeAnalysis` starts a child workflow per plan step once its dependencies have completed, and each step drives a sandbox agent inside a container. The same `runLoop` primitive runs in each workflow, and each model call and each tool call is a durable step.
|
|
103
103
|
|
|
104
|
-
The sandbox protocol is submit-then-poll, which lets a long run survive a host restart. Each exec runs inside one durable step: the host submits the command with `POST /exec`, and then it polls `GET /exec/{execId}?since={cursor}` until the result. A recovered step submits the same exec id again, and the sandbox gives the existing record, thus the command does not run again. The sandbox initiates nothing and has no egress, and confinement keeps each other peer away from its exec port. Refer to the [`harness-sandbox-exec`](./openspec/specs/harness-sandbox-exec/) spec.
|
|
104
|
+
The sandbox protocol is submit-then-poll, which lets a long run survive a host restart. Each exec runs inside one durable step: the host submits the command with `POST /exec`, and then it polls `GET /exec/{execId}?since={cursor}` until the result. A recovered step submits the same exec id again, and the sandbox gives the existing record, thus the command does not run again. The sandbox initiates nothing and has no egress, and confinement keeps each other peer away from its exec port. Refer to the [`harness-sandbox-exec`](./openspec/specs/harness-sandbox-exec/) spec. A consumer holds a sandbox through a lease: the step agent acquires a size with `acquire_sandbox`, and a detached lease workflow owns the machine, its admission against one budget, its idle removal, and its teardown. Refer to the [`sandbox-leases`](./openspec/specs/sandbox-leases/) spec.
|
|
105
105
|
|
|
106
106
|
## Further reading
|
|
107
107
|
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
import type { Pool } from "pg";
|
|
27
27
|
import type { ExecuteAnalysisInput, ExecuteAnalysisResult } from "../workflows/execute-analysis.js";
|
|
28
28
|
import type { EnsureSessionStateResult } from "../app/report-session-runtime.js";
|
|
29
|
-
import type { ResourcePolicy } from "../config/resource-limits.js";
|
|
30
29
|
import type { ChromeConfig } from "../lib/chrome.js";
|
|
31
30
|
import type { AcquireEyes } from "../lib/eyes.js";
|
|
32
31
|
import type { ToolOutputStore } from "../loop/tool-output.js";
|
|
@@ -43,10 +42,12 @@ import type { EnvironmentStorePaths } from "../config/environment-stores.js";
|
|
|
43
42
|
import type { RunAuthorizer } from "../execution/run-authorizer.js";
|
|
44
43
|
import type { RunLauncher } from "../execution/run-launcher.js";
|
|
45
44
|
import type { ProvenanceSeam } from "../provenance/seam.js";
|
|
45
|
+
import type { SyncSessionFile } from "../workspace/session-files.js";
|
|
46
46
|
import type { Logger } from "../lib/logger.js";
|
|
47
47
|
import type { UsageRecorder } from "../billing/usage-recorder.js";
|
|
48
48
|
import type { CitationResolver } from "../citations/types.js";
|
|
49
49
|
import { type WebSearchEngine } from "../tools/research/web-search.js";
|
|
50
|
+
import type { ScriptRuntime } from "../tools/script/run-script.js";
|
|
50
51
|
/** Canonical agent id — the single source of truth. */
|
|
51
52
|
export declare const CONVERSATION_AGENT_ID: "conversation-agent";
|
|
52
53
|
/**
|
|
@@ -143,12 +144,10 @@ export type ConversationAgentDeps = EnvironmentStorePaths & {
|
|
|
143
144
|
*/
|
|
144
145
|
readonly provenance?: ProvenanceSeam;
|
|
145
146
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* `execute_analysis` snapshots the budget into the workflow input. Absent,
|
|
149
|
-
* planning guidance and scheduling keep their legacy behavior.
|
|
147
|
+
* The host copy of each file that the agent writes: a derived file or a script of `run_script`, owned by the
|
|
148
|
+
* thread, and a `write_file` or `edit_file` write, owned by the analysis. See `SyncSessionFile`.
|
|
150
149
|
*/
|
|
151
|
-
readonly
|
|
150
|
+
readonly syncSessionFile?: SyncSessionFile;
|
|
152
151
|
/**
|
|
153
152
|
* Embedder-contributed conversation-tool seam — additional tools the host
|
|
154
153
|
* supplies, appended after the built-in roster. The harness stays agnostic to
|
|
@@ -156,6 +155,8 @@ export type ConversationAgentDeps = EnvironmentStorePaths & {
|
|
|
156
155
|
* built-in tool.
|
|
157
156
|
*/
|
|
158
157
|
readonly hostTools?: readonly Tool[];
|
|
158
|
+
/** Where the VM of `run_script` comes from. A bundled host gives the embedded paths; see `ScriptRuntime`. */
|
|
159
|
+
readonly scriptRuntime?: ScriptRuntime;
|
|
159
160
|
/**
|
|
160
161
|
* The farm-extension seam of the embedder. When it is bound,
|
|
161
162
|
* `execute_analysis` links the packages of the plan into the farm of the
|
|
@@ -44,6 +44,9 @@ import { createStartReportSessionTool } from "../tools/start-report-session.js";
|
|
|
44
44
|
import { createResolveCitationTool } from "../tools/research/resolve-citation.js";
|
|
45
45
|
import { createWebFetchTool } from "../tools/research/web-fetch.js";
|
|
46
46
|
import { createWebSearchTool } from "../tools/research/web-search.js";
|
|
47
|
+
import { createScriptFileTools } from "../tools/script/file-tools.js";
|
|
48
|
+
import { createScriptScratch } from "../tools/script/scratch.js";
|
|
49
|
+
import { conversationSessionDir } from "../workspace/paths.js";
|
|
47
50
|
/** Canonical agent id — the single source of truth. */
|
|
48
51
|
export const CONVERSATION_AGENT_ID = "conversation-agent";
|
|
49
52
|
/** Runaway guard — heavy tool-driving turns need generous headroom. */
|
|
@@ -52,7 +55,7 @@ const CONVERSATION_MAX_ITERATIONS = 200;
|
|
|
52
55
|
const CONVERSATION_COMPACTION = { turnStartBudget: 150_000, budget: 200_000 };
|
|
53
56
|
/** Build the conversation `AgentDefinition` with every tool fully dep-bound. */
|
|
54
57
|
export function createConversationAgent(deps) {
|
|
55
|
-
const { provider, pool, embedding, workspaceFs, model, utilityProvider, utilityModel, executeAnalysisWorkflow, runAuthorizer, runLauncher, bioKeys, chrome,
|
|
58
|
+
const { provider, pool, embedding, workspaceFs, model, utilityProvider, utilityModel, executeAnalysisWorkflow, runAuthorizer, runLauncher, bioKeys, chrome, hostTools, refStorePath, farmLockFile, imagePackagesFile, readPoolInventory, usageRecorder, toolOutputStore, citationResolver, webSearch, } = deps;
|
|
56
59
|
const workingMemory = createWorkingMemory(pool);
|
|
57
60
|
const ncbi = createNcbiTools(bioKeys);
|
|
58
61
|
const chemDb = createChemDbTools(bioKeys, { logger: deps.logger });
|
|
@@ -63,9 +66,22 @@ export function createConversationAgent(deps) {
|
|
|
63
66
|
const mutator = createSessionWorkspaceMutator({
|
|
64
67
|
resolveWorkspaceRoot: deps.resolveWorkspaceRoot,
|
|
65
68
|
provenance: deps.provenance,
|
|
69
|
+
syncSessionFile: deps.syncSessionFile,
|
|
66
70
|
logger: deps.logger,
|
|
67
71
|
});
|
|
68
|
-
|
|
72
|
+
// The scratch directory of each conversation: the scripts of `run_script`, and the files that they derive.
|
|
73
|
+
const scriptScratch = createScriptScratch({
|
|
74
|
+
resolveWorkspaceRoot: deps.resolveWorkspaceRoot,
|
|
75
|
+
sessionDir: conversationSessionDir,
|
|
76
|
+
provenance: deps.provenance,
|
|
77
|
+
syncSessionFile: deps.syncSessionFile,
|
|
78
|
+
logger: deps.logger,
|
|
79
|
+
});
|
|
80
|
+
// The lookups and the light work on tables run in a script (`run_script`). Each tool asks no approval, and a
|
|
81
|
+
// script writes only into the scratch directory of its conversation.
|
|
82
|
+
const scriptTools = [
|
|
83
|
+
// Tables of the workspace in, derived files and chart files out.
|
|
84
|
+
...createScriptFileTools({ workspaceFs, resolveWorkspaceRoot: deps.resolveWorkspaceRoot, scratch: scriptScratch }),
|
|
69
85
|
// Identifier resolution — the ENSG most other bio tools key off, and the
|
|
70
86
|
// UniProt accession that the structure tools take.
|
|
71
87
|
searchGeneTool,
|
|
@@ -112,6 +128,8 @@ export function createConversationAgent(deps) {
|
|
|
112
128
|
targetSafetyTool,
|
|
113
129
|
// EPA CompTox (toxcast / hazard / chemical / exposure behind one dataset).
|
|
114
130
|
chemDb.comptox,
|
|
131
|
+
];
|
|
132
|
+
const tools = [
|
|
115
133
|
// What reference data this install actually holds. The conversation agent is
|
|
116
134
|
// where provisioning is decided — an embedder may give it a way to install more,
|
|
117
135
|
// and a host that does asks the user to approve the download. Deciding that
|
|
@@ -140,10 +158,11 @@ export function createConversationAgent(deps) {
|
|
|
140
158
|
createGeneratePlanTool({
|
|
141
159
|
conversation: { provider, model },
|
|
142
160
|
pool,
|
|
143
|
-
resourcePolicy,
|
|
144
161
|
usageRecorder,
|
|
145
162
|
toolOutputStore,
|
|
146
163
|
bioKeys,
|
|
164
|
+
workspace: { workspaceFs, pool, embedding, resolveWorkspaceRoot: deps.resolveWorkspaceRoot },
|
|
165
|
+
scriptRuntime: deps.scriptRuntime,
|
|
147
166
|
knowledge: deps.knowledge,
|
|
148
167
|
refStorePath,
|
|
149
168
|
farmLockFile,
|
|
@@ -156,7 +175,6 @@ export function createConversationAgent(deps) {
|
|
|
156
175
|
executeAnalysisWorkflow,
|
|
157
176
|
runAuthorizer,
|
|
158
177
|
runLauncher,
|
|
159
|
-
resourcePolicy,
|
|
160
178
|
utilityProvider,
|
|
161
179
|
utilityModel,
|
|
162
180
|
farmLockFile,
|
|
@@ -193,6 +211,7 @@ export function createConversationAgent(deps) {
|
|
|
193
211
|
usageRecorder,
|
|
194
212
|
toolOutputStore,
|
|
195
213
|
logger: deps.logger,
|
|
214
|
+
scriptRuntime: deps.scriptRuntime,
|
|
196
215
|
}, deps.registerSubAgent),
|
|
197
216
|
// Workspace semantic search + raw read/grep over the read seam.
|
|
198
217
|
createWorkspaceSearchTool(pool, embedding),
|
|
@@ -219,6 +238,9 @@ export function createConversationAgent(deps) {
|
|
|
219
238
|
systemPrompt: composeSystemPrompt(conversationPrompt, { identity: true, conversational: true }),
|
|
220
239
|
model,
|
|
221
240
|
tools,
|
|
241
|
+
scriptTools,
|
|
242
|
+
scriptRuntime: deps.scriptRuntime,
|
|
243
|
+
scriptScratch,
|
|
222
244
|
maxIterations: CONVERSATION_MAX_ITERATIONS,
|
|
223
245
|
compaction: CONVERSATION_COMPACTION,
|
|
224
246
|
};
|
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
* the workspace search, the run inspection, and the data-profile inspection. It
|
|
12
12
|
* holds no planner, no run launcher, no working-memory write, and no sandbox
|
|
13
13
|
* mutate surface. Thus no tool starts a run, and no tool changes an analysis. The
|
|
14
|
-
* roster omits those tools, and no runtime guard blocks them.
|
|
14
|
+
* roster omits those tools, and no runtime guard blocks them. No tool runs a
|
|
15
|
+
* container.
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
-
* analysis
|
|
18
|
-
*
|
|
17
|
+
* A derivation of a table runs in a script (`run_script`), and it changes no
|
|
18
|
+
* analysis: it mints no run id, it registers no artifact, and it writes under the
|
|
19
|
+
* directory of the session alone.
|
|
19
20
|
*
|
|
20
21
|
* The definition carries no per-session value. The system prompt composes through
|
|
21
22
|
* `composeSystemPrompt` with the identity part and the conversational part, the
|
|
@@ -26,11 +27,10 @@ import type { Pool } from "pg";
|
|
|
26
27
|
import type { AuthContext, Identity } from "../auth/types.js";
|
|
27
28
|
import type { ToolOutputStore } from "../loop/tool-output.js";
|
|
28
29
|
import type { AgentDefinition } from "../loop/types.js";
|
|
29
|
-
import type { SandboxClient } from "../sandbox/client.js";
|
|
30
30
|
import type { ReportSessionStateStore } from "../state/report-session-state.js";
|
|
31
31
|
import type { EmbeddingProvider, ProviderOptions } from "../providers/types.js";
|
|
32
32
|
import type { WorkspaceFilesystem } from "../workspace/filesystem.js";
|
|
33
|
-
import type
|
|
33
|
+
import { type ResolveWorkspaceRoot } from "../workspace/paths.js";
|
|
34
34
|
import type { ChromeConfig } from "../lib/chrome.js";
|
|
35
35
|
import type { AcquireEyes } from "../lib/eyes.js";
|
|
36
36
|
import type { Logger } from "../lib/logger.js";
|
|
@@ -39,7 +39,9 @@ import type { ReferenceResolver } from "../report-model/reference-resolver.js";
|
|
|
39
39
|
import type { ReportVersionStore } from "../state/report-versions.js";
|
|
40
40
|
import type { ReportSessionStateGateway } from "../tools/report-authoring/authoring-tools.js";
|
|
41
41
|
import type { ProvenanceSeam } from "../provenance/seam.js";
|
|
42
|
+
import type { SyncSessionFile } from "../workspace/session-files.js";
|
|
42
43
|
import { type MakeSessionPagePublisher, type ResolvePageAsset, type ResolvePageUrl } from "../tools/report-session/index.js";
|
|
44
|
+
import type { ScriptRuntime } from "../tools/script/run-script.js";
|
|
43
45
|
/** Canonical agent id -- distinct from the id of the old templating agent. */
|
|
44
46
|
export declare const REPORT_SESSION_AGENT_ID: "report-session";
|
|
45
47
|
/**
|
|
@@ -68,14 +70,8 @@ export type ReportSessionAgentDeps = {
|
|
|
68
70
|
readonly resolveWorkspaceRoot: ResolveWorkspaceRoot;
|
|
69
71
|
/** Append-only version store -- the record tool gates the whole document first, then records one version. */
|
|
70
72
|
readonly store: ReportVersionStore;
|
|
71
|
-
/** Derivation ledger --
|
|
73
|
+
/** Derivation ledger -- `write_derived` appends one record for each derived table. */
|
|
72
74
|
readonly derivations: Pick<ReportSessionStateStore, "appendDerivation">;
|
|
73
|
-
/**
|
|
74
|
-
* Sandbox client -- the derivation tool runs one ephemeral container for each derived table, inside the
|
|
75
|
-
* step of its call. Omitted, the tool reports that the composition gives no sandbox, and it derives
|
|
76
|
-
* nothing.
|
|
77
|
-
*/
|
|
78
|
-
readonly sandboxClient?: SandboxClient;
|
|
79
75
|
/** Thread store -- the record tool reads the anchor of the report thread, and the preview tool names it. */
|
|
80
76
|
readonly threads: Pick<ThreadStore, "getThread" | "setAutoTitle">;
|
|
81
77
|
/** Headless-Chrome config -- the eyes tool opens the rendered page. */
|
|
@@ -118,16 +114,20 @@ export type ReportSessionAgentDeps = {
|
|
|
118
114
|
readonly resolvePageUrl?: ResolvePageUrl;
|
|
119
115
|
/**
|
|
120
116
|
* The provenance seam -- the acts of the session as typed events, and the frozen document of the
|
|
121
|
-
* analysis as opaque bytes. The tools that change the draft,
|
|
117
|
+
* analysis as opaque bytes. The tools that change the draft, preview the page, and
|
|
122
118
|
* record a version each emit through the session member, thus one bound member carries the whole
|
|
123
119
|
* session. The preview asks the read member before each render, and the page then carries the
|
|
124
120
|
* document. An unbound member emits nothing, or gives absence, and every tool acts the same.
|
|
125
121
|
*/
|
|
126
122
|
readonly provenance?: ProvenanceSeam;
|
|
123
|
+
/** The host copy of each file that the session writes. See `SyncSessionFile`. */
|
|
124
|
+
readonly syncSessionFile?: SyncSessionFile;
|
|
127
125
|
/** Operational logging seam; omitted falls back to no-op. */
|
|
128
126
|
readonly logger?: Logger;
|
|
129
127
|
/** Adds `read_tool_output`. The loop of a report turn must keep its texts in the same store. */
|
|
130
128
|
readonly toolOutputStore?: ToolOutputStore;
|
|
129
|
+
/** Where the VM of `run_script` comes from. A bundled host gives the embedded paths; see `ScriptRuntime`. */
|
|
130
|
+
readonly scriptRuntime?: ScriptRuntime;
|
|
131
131
|
};
|
|
132
132
|
/** Build the report `AgentDefinition` with every tool bound to its deps. */
|
|
133
133
|
export declare function createReportSessionAgent(deps: ReportSessionAgentDeps): AgentDefinition;
|
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
* the workspace search, the run inspection, and the data-profile inspection. It
|
|
12
12
|
* holds no planner, no run launcher, no working-memory write, and no sandbox
|
|
13
13
|
* mutate surface. Thus no tool starts a run, and no tool changes an analysis. The
|
|
14
|
-
* roster omits those tools, and no runtime guard blocks them.
|
|
14
|
+
* roster omits those tools, and no runtime guard blocks them. No tool runs a
|
|
15
|
+
* container.
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
-
* analysis
|
|
18
|
-
*
|
|
17
|
+
* A derivation of a table runs in a script (`run_script`), and it changes no
|
|
18
|
+
* analysis: it mints no run id, it registers no artifact, and it writes under the
|
|
19
|
+
* directory of the session alone.
|
|
19
20
|
*
|
|
20
21
|
* The definition carries no per-session value. The system prompt composes through
|
|
21
22
|
* `composeSystemPrompt` with the identity part and the conversational part, the
|
|
@@ -23,16 +24,20 @@
|
|
|
23
24
|
* across threads, and the provider cache reuses it.
|
|
24
25
|
*/
|
|
25
26
|
import { createReadToolOutputTool } from "../tools/read-tool-output.js";
|
|
27
|
+
import { reportSessionDir } from "../workspace/paths.js";
|
|
28
|
+
import { createDocumentTools, createReadPdfTool } from "../tools/script/file-tools.js";
|
|
26
29
|
import { createReportAuthoringTools } from "../tools/report-authoring/authoring-tools.js";
|
|
27
|
-
import {
|
|
30
|
+
import { createExaminePageTool, createListPinnedArtifactsTool, createPreviewReportTool, createRecordVersionTool, } from "../tools/report-session/index.js";
|
|
28
31
|
import { createFileStatTool, createGrepTool, createListFilesTool, createReadFileTool, createWorkspaceSearchTool } from "../tools/workspace/index.js";
|
|
29
32
|
import { createInspectDataProfileTool, createInspectRunTool } from "../tools/research/index.js";
|
|
30
33
|
import { reportSessionPrompt } from "../prompts/report-session.js";
|
|
31
34
|
import { composeSystemPrompt } from "./system-prompt.js";
|
|
35
|
+
import { createReportScriptTools } from "../tools/report-session/script-tools.js";
|
|
36
|
+
import { createScriptScratch } from "../tools/script/scratch.js";
|
|
32
37
|
/** Canonical agent id -- distinct from the id of the old templating agent. */
|
|
33
38
|
export const REPORT_SESSION_AGENT_ID = "report-session";
|
|
34
39
|
/**
|
|
35
|
-
* Runaway guard. A full session — orient,
|
|
40
|
+
* Runaway guard. A full session — orient, compose each section, preview,
|
|
36
41
|
* look, record — drives more small tool calls than a conversation turn, thus it
|
|
37
42
|
* gets the headroom of the report runner (REPORT_AGENT_MAX_STEPS).
|
|
38
43
|
*/
|
|
@@ -50,7 +55,7 @@ export const REPORT_SESSION_PROVIDER_OPTIONS = {
|
|
|
50
55
|
/** Build the report `AgentDefinition` with every tool bound to its deps. */
|
|
51
56
|
export function createReportSessionAgent(deps) {
|
|
52
57
|
const { model, pool, embedding, workspaceFs, gateway, resolveWorkspaceRoot, store, threads, chrome, eyes, makeResolver, resolvePageAsset, logger } = deps;
|
|
53
|
-
const { derivations,
|
|
58
|
+
const { derivations, makeSessionPages, resolvePageUrl, provenance, syncSessionFile } = deps;
|
|
54
59
|
// The seam rides into each tool that lands an act of the session, thus the composition binds it one
|
|
55
60
|
// time and no tool reads a second source.
|
|
56
61
|
const observation = provenance ? { provenance } : {};
|
|
@@ -65,15 +70,7 @@ export function createReportSessionAgent(deps) {
|
|
|
65
70
|
createWorkspaceSearchTool(pool, embedding),
|
|
66
71
|
createInspectRunTool(pool),
|
|
67
72
|
createInspectDataProfileTool(pool),
|
|
68
|
-
// The
|
|
69
|
-
// two threads never share one draft.
|
|
70
|
-
authoring.add_block,
|
|
71
|
-
authoring.change_block,
|
|
72
|
-
authoring.remove_block,
|
|
73
|
-
authoring.move_block,
|
|
74
|
-
authoring.set_title,
|
|
75
|
-
authoring.read_outline,
|
|
76
|
-
authoring.read_block,
|
|
73
|
+
// The gate of the draft. The edits of the draft are script tools below.
|
|
77
74
|
authoring.finish_draft,
|
|
78
75
|
// The orientation source of the pinned evidence. It reads the snapshot of the
|
|
79
76
|
// thread, and it resolves the workspace root per call for the header columns.
|
|
@@ -82,16 +79,6 @@ export function createReportSessionAgent(deps) {
|
|
|
82
79
|
resolveWorkspaceRoot,
|
|
83
80
|
logger,
|
|
84
81
|
}),
|
|
85
|
-
// The derivation tool. It reshapes the pinned evidence into one table under the
|
|
86
|
-
// session directory, on the sandbox rails of the value tier.
|
|
87
|
-
createDeriveTableTool({
|
|
88
|
-
gateway,
|
|
89
|
-
resolveWorkspaceRoot,
|
|
90
|
-
derivations,
|
|
91
|
-
sandboxClient,
|
|
92
|
-
...observation,
|
|
93
|
-
logger,
|
|
94
|
-
}),
|
|
95
82
|
// The render-and-preview tool. It resolves the page root per call.
|
|
96
83
|
createPreviewReportTool({
|
|
97
84
|
gateway,
|
|
@@ -126,11 +113,38 @@ export function createReportSessionAgent(deps) {
|
|
|
126
113
|
logger,
|
|
127
114
|
}),
|
|
128
115
|
];
|
|
116
|
+
// A derivation of a table of up to the read cap runs in a script, thus it starts no container. The scripts
|
|
117
|
+
// of a session stay beside its page.
|
|
118
|
+
const scriptScratch = createScriptScratch({ resolveWorkspaceRoot, sessionDir: reportSessionDir, provenance, syncSessionFile, logger });
|
|
119
|
+
// A PDF of the report is a document that a script builds from the content of the session, not a print of the
|
|
120
|
+
// page. Its images come from the directory of the session alone, thus no unpinned file reaches it.
|
|
121
|
+
const scriptTools = [
|
|
122
|
+
// The edits of the draft. Each binds to the gateway, thus two threads never share one draft, and a script
|
|
123
|
+
// builds a section in one call. A refused edit comes back as data, thus the script reads `applied`.
|
|
124
|
+
authoring.add_block,
|
|
125
|
+
authoring.change_block,
|
|
126
|
+
authoring.remove_block,
|
|
127
|
+
authoring.move_block,
|
|
128
|
+
authoring.set_title,
|
|
129
|
+
authoring.read_outline,
|
|
130
|
+
authoring.read_block,
|
|
131
|
+
...createReportScriptTools({ gateway, workspaceFs, resolveWorkspaceRoot, derivations, provenance, syncSessionFile, logger }),
|
|
132
|
+
createReadPdfTool({ workspaceFs, resolveWorkspaceRoot }),
|
|
133
|
+
...createDocumentTools({
|
|
134
|
+
workspaceFs,
|
|
135
|
+
resolveWorkspaceRoot,
|
|
136
|
+
scratch: scriptScratch,
|
|
137
|
+
imageScope: (session) => (session.scope.threadId === undefined ? undefined : reportSessionDir(session.scope.threadId)),
|
|
138
|
+
}),
|
|
139
|
+
];
|
|
129
140
|
return {
|
|
130
141
|
id: REPORT_SESSION_AGENT_ID,
|
|
131
142
|
systemPrompt: composeSystemPrompt(reportSessionPrompt, { identity: true, conversational: true }),
|
|
132
143
|
model,
|
|
133
144
|
tools,
|
|
145
|
+
scriptTools,
|
|
146
|
+
scriptRuntime: deps.scriptRuntime,
|
|
147
|
+
scriptScratch,
|
|
134
148
|
maxIterations: REPORT_SESSION_MAX_ITERATIONS,
|
|
135
149
|
compaction: REPORT_SESSION_COMPACTION,
|
|
136
150
|
providerOptions: REPORT_SESSION_PROVIDER_OPTIONS,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* `allowedWritePrefix` through the host-side `WorkspaceMutator` —,
|
|
11
11
|
* the workspace read tools (`read_file`, `grep`) over the shared
|
|
12
12
|
* `WorkspaceFilesystem`, `inspect_data_profile` over the shared `Pool`, and the
|
|
13
|
-
* bio/literature/context7
|
|
13
|
+
* bio/literature/context7 tools its `meta.tools` allowlist names.
|
|
14
14
|
*
|
|
15
15
|
* Tool resolution is a single registry lookup — every name in `meta.tools`
|
|
16
16
|
* must map to a concrete `Tool`; unknown names throw at composition time
|
|
@@ -20,8 +20,8 @@ import type { Querier } from "../../state/db.js";
|
|
|
20
20
|
import type { ToolOutputStore } from "../../loop/tool-output.js";
|
|
21
21
|
import type { AgentDefinition } from "../../loop/types.js";
|
|
22
22
|
import type { ChatProvider, EmbeddingProvider } from "../../providers/types.js";
|
|
23
|
-
import type {
|
|
24
|
-
import type { ExtendAnalysisFarm,
|
|
23
|
+
import type { BoundLease } from "../../sandbox/leases.js";
|
|
24
|
+
import type { ExtendAnalysisFarm, ToolchainSource } from "../../sandbox/types.js";
|
|
25
25
|
import type { WorkspaceFilesystem } from "../../workspace/filesystem.js";
|
|
26
26
|
import type { ProvenanceCollector as LineageCollector } from "../../provenance/collector.js";
|
|
27
27
|
import { type BioToolKeys } from "../../tools/bio/keys.js";
|
|
@@ -31,9 +31,10 @@ import type { EnvironmentStorePaths } from "../../config/environment-stores.js";
|
|
|
31
31
|
import type { Logger } from "../../lib/logger.js";
|
|
32
32
|
import type { CitationResolver } from "../../citations/types.js";
|
|
33
33
|
import { type KnowledgeClient, type TemplateBinding } from "../../tools/knowledge/index.js";
|
|
34
|
+
import type { ScriptRuntime } from "../../tools/script/run-script.js";
|
|
34
35
|
/**
|
|
35
36
|
* Tools every sandbox agent receives — sandbox-environment introspection,
|
|
36
|
-
* library docs,
|
|
37
|
+
* library docs, and the knowledge template. Spread into each
|
|
37
38
|
* agent's `meta.tools` so planner-facing metadata and the resolved tool record
|
|
38
39
|
* stay in sync. Keep minimal — only tools every agent genuinely needs.
|
|
39
40
|
*
|
|
@@ -47,14 +48,13 @@ import { type KnowledgeClient, type TemplateBinding } from "../../tools/knowledg
|
|
|
47
48
|
export declare const BASE_SANDBOX_TOOLS: readonly SandboxToolName[];
|
|
48
49
|
/** Per-step coordinates the composition root threads through every mutate tool. */
|
|
49
50
|
export type SandboxStepCoords = {
|
|
50
|
-
|
|
51
|
+
/** The lease of the step. `acquire_sandbox` and `release_sandbox` drive it, and each command runs on it. */
|
|
52
|
+
readonly lease: BoundLease;
|
|
51
53
|
/** Absolute host root of this analysis's workspace tree (resolved at the workflow body). */
|
|
52
54
|
readonly workspaceRoot: string;
|
|
53
55
|
readonly analysisId: string;
|
|
54
56
|
/** Absolute writable artifact directory for this step (e.g. stepWritePrefix(...)). */
|
|
55
57
|
readonly allowedWritePrefix: string;
|
|
56
|
-
/** Absolute unix-ms deadline of each exec. */
|
|
57
|
-
readonly deadlineMs: () => number;
|
|
58
58
|
/**
|
|
59
59
|
* The plan settings bound to the template of this step, from the durable
|
|
60
60
|
* step input. Reaches `knowledge_template` alone. Absent when the step
|
|
@@ -68,14 +68,16 @@ export type SandboxAgentDeps = EnvironmentStorePaths & {
|
|
|
68
68
|
readonly logger?: Logger;
|
|
69
69
|
readonly provider: ChatProvider;
|
|
70
70
|
readonly pool: Querier;
|
|
71
|
-
|
|
71
|
+
/** The toolchain of the sandboxes, as the sandbox client declares it. The orient-core prompt keys on it. */
|
|
72
|
+
readonly toolchainSource: ToolchainSource;
|
|
72
73
|
readonly workspaceFs: WorkspaceFilesystem;
|
|
73
74
|
/** Embedding provider for in-sandbox semantic `workspace_search`. Omit to skip that tool. */
|
|
74
75
|
readonly embedding?: EmbeddingProvider;
|
|
75
76
|
/**
|
|
76
77
|
* Step-scoped lineage collector fed by each `execute_command`'s
|
|
77
|
-
* `ExecResult.provenance` frame
|
|
78
|
-
*
|
|
78
|
+
* `ExecResult.provenance` frame, and by the reads of `read_file`, `grep`, and
|
|
79
|
+
* `read_pdf`. Records the input/script edges post-step registration
|
|
80
|
+
* translates into provenance parents.
|
|
79
81
|
*/
|
|
80
82
|
readonly lineageCollector?: LineageCollector;
|
|
81
83
|
/** Model id provenance label — the provider owns the wire model. */
|
|
@@ -103,8 +105,9 @@ export type SandboxAgentDeps = EnvironmentStorePaths & {
|
|
|
103
105
|
readonly toolOutputStore?: ToolOutputStore;
|
|
104
106
|
/**
|
|
105
107
|
* The farm-extension seam of the embedder. When it is bound, every
|
|
106
|
-
* sandbox agent gets the `link_packages` tool in its always-on substrate
|
|
107
|
-
*
|
|
108
|
+
* sandbox agent gets the `link_packages` tool in its always-on substrate.
|
|
109
|
+
* The system prompt is the same with and without it: the descriptions of
|
|
110
|
+
* `link_packages` and `list_available_packages` carry the link rules.
|
|
108
111
|
*/
|
|
109
112
|
readonly extendAnalysisFarm?: ExtendAnalysisFarm;
|
|
110
113
|
/**
|
|
@@ -114,6 +117,8 @@ export type SandboxAgentDeps = EnvironmentStorePaths & {
|
|
|
114
117
|
* of the open-source host and never an error.
|
|
115
118
|
*/
|
|
116
119
|
readonly knowledge?: KnowledgeClient;
|
|
120
|
+
/** Where the VM of `run_script` comes from, for the lookups of the agent. */
|
|
121
|
+
readonly scriptRuntime?: ScriptRuntime;
|
|
117
122
|
};
|
|
118
123
|
/** Per-agent override for the prompt composition and tool surface. */
|
|
119
124
|
export type SandboxAgentPromptOptions = {
|
|
@@ -138,7 +143,7 @@ export type SandboxAgentPromptOptions = {
|
|
|
138
143
|
*
|
|
139
144
|
* The composed `systemPrompt` is a **pure function of the agent type** — nothing
|
|
140
145
|
* from `deps.step` reaches it, so two steps of one run, and two runs of one
|
|
141
|
-
* analysis, send a byte-identical
|
|
146
|
+
* analysis, send a byte-identical prefix that the provider's prompt
|
|
142
147
|
* cache can actually reuse. Keep it that way: a single interpolated id or path
|
|
143
148
|
* makes every step's prefix unique again, and each step pays a full cache write
|
|
144
149
|
* and reads nothing back. Per-step values belong in the step's briefing (its
|
|
@@ -10,21 +10,20 @@
|
|
|
10
10
|
* `allowedWritePrefix` through the host-side `WorkspaceMutator` —,
|
|
11
11
|
* the workspace read tools (`read_file`, `grep`) over the shared
|
|
12
12
|
* `WorkspaceFilesystem`, `inspect_data_profile` over the shared `Pool`, and the
|
|
13
|
-
* bio/literature/context7
|
|
13
|
+
* bio/literature/context7 tools its `meta.tools` allowlist names.
|
|
14
14
|
*
|
|
15
15
|
* Tool resolution is a single registry lookup — every name in `meta.tools`
|
|
16
16
|
* must map to a concrete `Tool`; unknown names throw at composition time
|
|
17
17
|
* so misconfigured agents fail at startup, not at the first LLM call.
|
|
18
18
|
*/
|
|
19
19
|
import { createEditIntentStore } from "../../state/edit-intents.js";
|
|
20
|
-
import {
|
|
20
|
+
import { createWorkspaceReadLineage } from "../../provenance/workspace-reads.js";
|
|
21
|
+
import { sandboxOrientCorePromptFor, sandboxAnalysisStepStandardsPrompt } from "../../prompts/sandbox-standards.js";
|
|
21
22
|
import { composeSystemPrompt } from "../system-prompt.js";
|
|
22
23
|
// Sandbox-environment introspection, plus the farm-extension seam face.
|
|
23
24
|
import { createLinkPackagesTool, createListAvailablePackagesTool, createListAvailableRefsTool } from "../../tools/sandbox/index.js";
|
|
24
25
|
// Context7 docs (pure leaves).
|
|
25
26
|
import { queryDocsTool, resolveLibraryIdTool } from "../../tools/research/context7-docs.js";
|
|
26
|
-
// Run-inspection (dependency-bearing).
|
|
27
|
-
import { createInspectRunTool } from "../../tools/research/inspect-run.js";
|
|
28
27
|
// Data-profile retrieval (dependency-bearing) — always-on, see `createSandboxAgent`.
|
|
29
28
|
import { createInspectDataProfileTool } from "../../tools/research/inspect-data-profile.js";
|
|
30
29
|
// Bio leaf tools.
|
|
@@ -38,15 +37,17 @@ import { createEditFileTool, createExecuteCommandTool, createWorkspaceMutator, c
|
|
|
38
37
|
// Skills (declared per agent via meta.skills).
|
|
39
38
|
import { createSkillTools } from "../../tools/sandbox/skills.js";
|
|
40
39
|
import { createReadToolOutputTool } from "../../tools/read-tool-output.js";
|
|
40
|
+
import { createAcquireSandboxTool, createReleaseSandboxTool } from "../../tools/sandbox/lease-tools.js";
|
|
41
41
|
import { createReportBlockerTool } from "../../tools/sandbox/report-blocker.js";
|
|
42
42
|
import { createSubmitFileMetadataTool } from "../../tools/sandbox/submit-file-metadata.js";
|
|
43
43
|
import { toSandboxPath } from "../../workspace/paths.js";
|
|
44
44
|
import { SANDBOX_AGENT_DEFAULT_MAX_ITERATIONS } from "./types.js";
|
|
45
45
|
import { createResolveCitationTool } from "../../tools/research/resolve-citation.js";
|
|
46
46
|
import { createKnowledgeTemplateTool } from "../../tools/knowledge/index.js";
|
|
47
|
+
import { createReadPdfTool } from "../../tools/script/file-tools.js";
|
|
47
48
|
/**
|
|
48
49
|
* Tools every sandbox agent receives — sandbox-environment introspection,
|
|
49
|
-
* library docs,
|
|
50
|
+
* library docs, and the knowledge template. Spread into each
|
|
50
51
|
* agent's `meta.tools` so planner-facing metadata and the resolved tool record
|
|
51
52
|
* stay in sync. Keep minimal — only tools every agent genuinely needs.
|
|
52
53
|
*
|
|
@@ -62,9 +63,13 @@ export const BASE_SANDBOX_TOOLS = [
|
|
|
62
63
|
"listAvailableRefs",
|
|
63
64
|
"resolveLibraryId",
|
|
64
65
|
"queryDocs",
|
|
65
|
-
"inspectRun",
|
|
66
66
|
"knowledgeTemplate",
|
|
67
67
|
];
|
|
68
|
+
/**
|
|
69
|
+
* The tools of the allowlist that stay direct: the environment of the step. Each other tool of the allowlist is a
|
|
70
|
+
* lookup of an outside source, and it runs in `run_script`.
|
|
71
|
+
*/
|
|
72
|
+
const DIRECT_ALLOWLIST_TOOLS = new Set(["list_available_packages", "list_available_refs", "scan_inputs", "knowledge_template"]);
|
|
68
73
|
/**
|
|
69
74
|
* Resolve `meta.tools` into the bio/research tools record. The workspace
|
|
70
75
|
* read/mutate tools and `inspect_data_profile` are added by `createSandboxAgent`
|
|
@@ -89,13 +94,10 @@ function resolveSandboxTools(deps, tools, mutator) {
|
|
|
89
94
|
scanInputs: createScanInputsTool({
|
|
90
95
|
workspaceFs: deps.workspaceFs,
|
|
91
96
|
analysisId: deps.step.analysisId,
|
|
92
|
-
|
|
93
|
-
sandbox: deps.step.sandbox,
|
|
94
|
-
deadlineMs: deps.step.deadlineMs,
|
|
97
|
+
lease: deps.step.lease,
|
|
95
98
|
}),
|
|
96
99
|
resolveLibraryId: resolveLibraryIdTool,
|
|
97
100
|
queryDocs: queryDocsTool,
|
|
98
|
-
inspectRun: createInspectRunTool(deps.pool),
|
|
99
101
|
pubmed: ncbi.pubmed,
|
|
100
102
|
resolve_citation: deps.citationResolver === undefined ? undefined : createResolveCitationTool(deps.citationResolver),
|
|
101
103
|
searchGene: searchGeneTool,
|
|
@@ -146,8 +148,8 @@ function resolveSandboxTools(deps, tools, mutator) {
|
|
|
146
148
|
/** Build the workspace mutate + read tools every sandbox agent receives. In
|
|
147
149
|
* `readOnly` mode the write_file/edit_file pair is omitted; execute_command
|
|
148
150
|
* and the read tools stay. */
|
|
149
|
-
function buildWorkspaceTools(deps, readOnly) {
|
|
150
|
-
const { step,
|
|
151
|
+
function buildWorkspaceTools(deps, readOnly, readLineage) {
|
|
152
|
+
const { step, workspaceFs, pool, embedding, lineageCollector } = deps;
|
|
151
153
|
// The agent's writable working directory: relative paths resolve here, and
|
|
152
154
|
// writes are confined here. `allowedWritePrefix` is its host path; the
|
|
153
155
|
// in-sandbox path (the `execute_command` default cwd, see the harness-workspace-tools spec) is the same
|
|
@@ -170,10 +172,10 @@ function buildWorkspaceTools(deps, readOnly) {
|
|
|
170
172
|
]
|
|
171
173
|
: [];
|
|
172
174
|
const tools = [
|
|
175
|
+
createAcquireSandboxTool(step.lease),
|
|
176
|
+
createReleaseSandboxTool(step.lease),
|
|
173
177
|
createExecuteCommandTool({
|
|
174
|
-
|
|
175
|
-
sandbox: step.sandbox,
|
|
176
|
-
deadlineMs: step.deadlineMs,
|
|
178
|
+
lease: step.lease,
|
|
177
179
|
defaultCwd: sandboxWorkingDir,
|
|
178
180
|
lineageCollector,
|
|
179
181
|
mountRoot: `/${step.analysisId}`,
|
|
@@ -181,10 +183,10 @@ function buildWorkspaceTools(deps, readOnly) {
|
|
|
181
183
|
mutator,
|
|
182
184
|
}),
|
|
183
185
|
...mutateTools,
|
|
184
|
-
createReadFileTool(workspaceFs, hostWorkingDir),
|
|
186
|
+
createReadFileTool(workspaceFs, hostWorkingDir, readLineage),
|
|
185
187
|
createListFilesTool(workspaceFs, hostWorkingDir),
|
|
186
188
|
createFileStatTool(workspaceFs, hostWorkingDir),
|
|
187
|
-
createGrepTool(workspaceFs, hostWorkingDir),
|
|
189
|
+
createGrepTool(workspaceFs, hostWorkingDir, readLineage),
|
|
188
190
|
...(embedding ? [createWorkspaceSearchTool(pool, embedding)] : []),
|
|
189
191
|
];
|
|
190
192
|
return { tools, mutator };
|
|
@@ -200,7 +202,7 @@ function buildWorkspaceTools(deps, readOnly) {
|
|
|
200
202
|
*
|
|
201
203
|
* The composed `systemPrompt` is a **pure function of the agent type** — nothing
|
|
202
204
|
* from `deps.step` reaches it, so two steps of one run, and two runs of one
|
|
203
|
-
* analysis, send a byte-identical
|
|
205
|
+
* analysis, send a byte-identical prefix that the provider's prompt
|
|
204
206
|
* cache can actually reuse. Keep it that way: a single interpolated id or path
|
|
205
207
|
* makes every step's prefix unique again, and each step pays a full cache write
|
|
206
208
|
* and reads nothing back. Per-step values belong in the step's briefing (its
|
|
@@ -210,20 +212,27 @@ function buildWorkspaceTools(deps, readOnly) {
|
|
|
210
212
|
export function createSandboxAgent(deps, meta, body, opts = {}) {
|
|
211
213
|
const appendStandards = opts.appendAnalysisStepStandards ?? true;
|
|
212
214
|
// The layer order is fixed by the harness-sandbox-agents spec: the agent
|
|
213
|
-
// body, the orient core keyed on the toolchain of the sandbox client,
|
|
214
|
-
//
|
|
215
|
+
// body, the orient core keyed on the toolchain of the sandbox client, then
|
|
216
|
+
// the step standards.
|
|
215
217
|
// The client is the one declaration: the environment it provisions and the
|
|
216
218
|
// text that describes it come from the same value, thus a bag cannot
|
|
217
219
|
// describe a toolchain the sandbox does not have.
|
|
218
|
-
const sandboxLayer = [
|
|
219
|
-
sandboxOrientCorePromptFor(deps.sandboxClient.toolchainSource),
|
|
220
|
-
...(deps.extendAnalysisFarm ? [sandboxPackageLinkPrompt] : []),
|
|
221
|
-
...(appendStandards ? [sandboxAnalysisStepStandardsPrompt] : []),
|
|
222
|
-
];
|
|
220
|
+
const sandboxLayer = [sandboxOrientCorePromptFor(deps.toolchainSource), ...(appendStandards ? [sandboxAnalysisStepStandardsPrompt] : [])];
|
|
223
221
|
const agentBody = [body, ...sandboxLayer].map((s) => s.trim()).join("\n\n");
|
|
224
222
|
const systemPrompt = composeSystemPrompt(agentBody);
|
|
225
223
|
const skillTools = deps.skillsDir ? Object.values(createSkillTools({ skillsDir: deps.skillsDir, skills: meta.skills })) : [];
|
|
226
|
-
|
|
224
|
+
// The working directory is the one of the read tools, thus a relative path resolves to the same file.
|
|
225
|
+
const readLineage = deps.lineageCollector
|
|
226
|
+
? createWorkspaceReadLineage({
|
|
227
|
+
collector: deps.lineageCollector,
|
|
228
|
+
workspaceRoot: deps.step.workspaceRoot,
|
|
229
|
+
analysisId: deps.step.analysisId,
|
|
230
|
+
workingDir: deps.step.allowedWritePrefix,
|
|
231
|
+
logger: deps.logger,
|
|
232
|
+
})
|
|
233
|
+
: undefined;
|
|
234
|
+
const workspace = buildWorkspaceTools(deps, opts.readOnly ?? false, readLineage);
|
|
235
|
+
const allowlisted = resolveSandboxTools(deps, meta.tools, workspace.mutator);
|
|
227
236
|
const tools = [
|
|
228
237
|
...workspace.tools,
|
|
229
238
|
...(deps.toolOutputStore ? [createReadToolOutputTool(deps.toolOutputStore)] : []),
|
|
@@ -238,7 +247,7 @@ export function createSandboxAgent(deps, meta, body, opts = {}) {
|
|
|
238
247
|
// seam (the harness-sandbox-agents spec).
|
|
239
248
|
...(deps.extendAnalysisFarm ? [createLinkPackagesTool({ extendAnalysisFarm: deps.extendAnalysisFarm, analysisId: deps.step.analysisId })] : []),
|
|
240
249
|
...skillTools,
|
|
241
|
-
...
|
|
250
|
+
...allowlisted.filter((tool) => DIRECT_ALLOWLIST_TOOLS.has(tool.id)),
|
|
242
251
|
...(deps.reportsBlocker === true ? [createReportBlockerTool()] : []),
|
|
243
252
|
...(deps.fileMetadata ? [createSubmitFileMetadataTool(deps.fileMetadata)] : []),
|
|
244
253
|
];
|
|
@@ -247,6 +256,12 @@ export function createSandboxAgent(deps, meta, body, opts = {}) {
|
|
|
247
256
|
systemPrompt,
|
|
248
257
|
model: deps.model,
|
|
249
258
|
tools,
|
|
259
|
+
// A paper of the analysis is a PDF, and each step can need it, thus each agent reads PDFs in a script.
|
|
260
|
+
scriptTools: [
|
|
261
|
+
...allowlisted.filter((tool) => !DIRECT_ALLOWLIST_TOOLS.has(tool.id)),
|
|
262
|
+
createReadPdfTool({ workspaceFs: deps.workspaceFs, resolveWorkspaceRoot: () => Promise.resolve(deps.step.workspaceRoot), lineage: readLineage }),
|
|
263
|
+
],
|
|
264
|
+
scriptRuntime: deps.scriptRuntime,
|
|
250
265
|
maxIterations: meta.defaultMaxSteps ?? SANDBOX_AGENT_DEFAULT_MAX_ITERATIONS,
|
|
251
266
|
};
|
|
252
267
|
}
|