@inflexa-ai/harness 0.46.0 → 0.47.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 +1 -1
- package/dist/agents/conversation-agent.d.ts +3 -8
- package/dist/agents/conversation-agent.js +24 -4
- package/dist/agents/report-session-agent.d.ts +11 -14
- package/dist/agents/report-session-agent.js +30 -17
- 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/chat-turn-workflow.js +5 -6
- 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 +2 -5
- package/dist/index.js +3 -6
- package/dist/input-scan/enrich.d.ts +5 -10
- package/dist/input-scan/enrich.js +12 -8
- package/dist/lib/hooks.d.ts +9 -0
- package/dist/lib/hooks.js +6 -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/run-loop.d.ts +5 -0
- package/dist/loop/run-loop.js +30 -2
- package/dist/loop/sub-agent.js +5 -6
- package/dist/loop/tool-name-repair.d.ts +11 -0
- package/dist/loop/tool-name-repair.js +23 -0
- package/dist/loop/turn-credentials.d.ts +5 -0
- package/dist/loop/turn-credentials.js +17 -0
- package/dist/loop/types.d.ts +14 -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 +26 -57
- 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/providers/request-headers.js +12 -3
- 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 +20 -9
- package/dist/runtime/assemble.js +47 -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 +0 -1
- package/dist/state/index.js +0 -1
- 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 +0 -2
- package/dist/state/step-executions.js +1 -4
- package/dist/tasks/data-profile.d.ts +40 -2
- package/dist/tasks/data-profile.js +89 -87
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +6 -1
- 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-session/index.d.ts +0 -1
- package/dist/tools/report-session/index.js +0 -1
- package/dist/tools/report-session/script-tools.d.ts +30 -0
- package/dist/tools/report-session/script-tools.js +177 -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/codemode-worker.d.ts +5 -0
- package/dist/tools/script/codemode-worker.js +5 -0
- package/dist/tools/script/file-tools.d.ts +100 -0
- package/dist/tools/script/file-tools.js +377 -0
- package/dist/tools/script/metrics.d.ts +21 -0
- package/dist/tools/script/metrics.js +38 -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 +326 -0
- package/dist/tools/script/scratch.d.ts +81 -0
- package/dist/tools/script/scratch.js +142 -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 +48 -4
- package/dist/tools/workspace/mutator.js +43 -12
- 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/package.json +6 -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
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
* The realization holds three layers. Layer one is identity: membership through `snapshotEntry`, and a
|
|
6
6
|
* streamed hash compare with `computeSha256File`. A hash mismatch fails before any parse. Layer two is
|
|
7
7
|
* the host fast path: an in-process parse of a CSV, a TSV, a JSON, or a parquet file at or under the cap.
|
|
8
|
-
* Layer three is the fall-through: an over-cap file or a host parse fault
|
|
9
|
-
* doubt the read falls through, thus
|
|
10
|
-
* no tabular format refuses
|
|
8
|
+
* Layer three is the fall-through: an over-cap file or a host parse fault fails as `extraction-unavailable`.
|
|
9
|
+
* On any doubt the read falls through, thus the host parser never gives a partial or guessed answer. An
|
|
10
|
+
* extension that names no tabular format refuses the same way.
|
|
11
11
|
*
|
|
12
12
|
* A read of the bytes is the expensive part, thus an optional `ArtifactReadCache` outlives one resolver. It
|
|
13
|
-
* holds the streamed hash and the
|
|
14
|
-
* share one cache
|
|
13
|
+
* holds the streamed hash and the parsed rows against a stat signature. Two tool calls of one analysis
|
|
14
|
+
* share one cache.
|
|
15
15
|
*
|
|
16
16
|
* The realization calls the shared assert functions in `assert-rules.ts`, and it mirrors the locator walk
|
|
17
17
|
* and the reason choices of `fixture-resolver.ts`. Thus one semantics exists, and the fixture stays the
|
|
@@ -22,7 +22,6 @@ import { readFile, stat } from "node:fs/promises";
|
|
|
22
22
|
import { extname } from "node:path";
|
|
23
23
|
import { parquetReadObjects } from "hyparquet";
|
|
24
24
|
import { z } from "zod";
|
|
25
|
-
import { isWorkflowCancellation } from "../runtime/dbos.js";
|
|
26
25
|
import { allWithConcurrency } from "../lib/async-utils.js";
|
|
27
26
|
import { computeSha256File } from "../lib/fs-helpers.js";
|
|
28
27
|
import { parseJsonAs } from "../lib/parse-json.js";
|
|
@@ -92,6 +91,10 @@ export function createArtifactReadStore() {
|
|
|
92
91
|
},
|
|
93
92
|
};
|
|
94
93
|
}
|
|
94
|
+
/** The cells of a fall-through. No reader outside the host exists, thus the reference fails as `extraction-unavailable`. */
|
|
95
|
+
function fallThroughCells(path, hostDetail) {
|
|
96
|
+
return { kind: "unavailable", detail: `the host read of the file at ${path} stopped because ${hostDetail}, and no other reader exists` };
|
|
97
|
+
}
|
|
95
98
|
/** Build an `Err` that carries the unresolved reference. The `detail` key is present only when there is a detail to carry. */
|
|
96
99
|
function fail(reference, reason, detail) {
|
|
97
100
|
const failure = detail !== undefined ? { reference, reason, detail } : { reference, reason };
|
|
@@ -104,10 +107,9 @@ function describeReference(reference) {
|
|
|
104
107
|
/**
|
|
105
108
|
* Map a file extension to the format that the host arm reads. An unknown extension gives back `undefined`.
|
|
106
109
|
*
|
|
107
|
-
* This is the one format decision of the report path.
|
|
108
|
-
* sandbox arm never repeats the mapping and the two arms hold no second table between them.
|
|
110
|
+
* This is the one format decision of the report path.
|
|
109
111
|
*/
|
|
110
|
-
function detectFormat(path) {
|
|
112
|
+
export function detectFormat(path) {
|
|
111
113
|
switch (extname(path).toLowerCase()) {
|
|
112
114
|
case ".csv":
|
|
113
115
|
return "csv";
|
|
@@ -130,8 +132,7 @@ function detectFormat(path) {
|
|
|
130
132
|
* where the caller detects the loss.
|
|
131
133
|
*
|
|
132
134
|
* A non-finite number is not a cell either. A parquet float column holds a `NaN` or an `Infinity`, thus the
|
|
133
|
-
* coercion drops it and the row omits the key.
|
|
134
|
-
* drops the same value to `None`, thus the host arm and the sandbox arm read the same bytes the same way.
|
|
135
|
+
* coercion drops it and the row omits the key.
|
|
135
136
|
*/
|
|
136
137
|
export function coerceCell(value) {
|
|
137
138
|
if (value === null || value === undefined) {
|
|
@@ -339,10 +340,7 @@ async function parseParquet(bytes) {
|
|
|
339
340
|
}
|
|
340
341
|
/**
|
|
341
342
|
* Read the cells of one artifact through the host fast path. An over-cap file and a parse fault each give
|
|
342
|
-
* back a fall-through
|
|
343
|
-
*
|
|
344
|
-
* An extension that names no tabular format stops here. The arm reads a file by a decided format, and no
|
|
345
|
-
* format is decided, thus the arm has nothing to obey and the read is unavailable.
|
|
343
|
+
* back a fall-through. An extension that names no tabular format stops here.
|
|
346
344
|
*/
|
|
347
345
|
async function hostReadCells(cap, path, identity) {
|
|
348
346
|
const format = detectFormat(path);
|
|
@@ -350,26 +348,33 @@ async function hostReadCells(cap, path, identity) {
|
|
|
350
348
|
return { kind: "unsupported-format", detail: `the file at ${path} has no supported tabular format, thus no reader is decided for it` };
|
|
351
349
|
}
|
|
352
350
|
if (identity.size > cap) {
|
|
353
|
-
return { kind: "fall-through",
|
|
351
|
+
return { kind: "fall-through", detail: `the file size of ${identity.size} bytes is over the ${cap}-byte cap` };
|
|
354
352
|
}
|
|
355
353
|
let bytes;
|
|
356
354
|
try {
|
|
357
355
|
bytes = await readFile(identity.absolute);
|
|
358
356
|
}
|
|
359
357
|
catch {
|
|
360
|
-
return { kind: "fall-through",
|
|
361
|
-
}
|
|
362
|
-
if (format === "parquet") {
|
|
363
|
-
const rows = await parseParquet(bytes);
|
|
364
|
-
return rows === undefined ? { kind: "fall-through", format, detail: "the parquet read did not succeed" } : { kind: "rows", rows };
|
|
358
|
+
return { kind: "fall-through", detail: "the file could not be read" };
|
|
365
359
|
}
|
|
360
|
+
const rows = await parseTable(format, bytes);
|
|
361
|
+
return rows === undefined ? { kind: "fall-through", detail: PARSE_FAULT_DETAIL[format] } : { kind: "rows", rows };
|
|
362
|
+
}
|
|
363
|
+
/** The detail of a parse fault, for each format. */
|
|
364
|
+
const PARSE_FAULT_DETAIL = {
|
|
365
|
+
csv: "the delimited parse did not succeed",
|
|
366
|
+
tsv: "the delimited parse did not succeed",
|
|
367
|
+
json: "the JSON parse did not succeed",
|
|
368
|
+
parquet: "the parquet read did not succeed",
|
|
369
|
+
};
|
|
370
|
+
/** Parse the bytes of one table in a decided format. A parse fault gives back `undefined`. */
|
|
371
|
+
export async function parseTable(format, bytes) {
|
|
372
|
+
if (format === "parquet")
|
|
373
|
+
return parseParquet(bytes);
|
|
366
374
|
const text = bytes.toString("utf8");
|
|
367
|
-
if (format === "json")
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
}
|
|
371
|
-
const rows = parseDelimited(text, format === "tsv" ? "\t" : ",");
|
|
372
|
-
return rows === undefined ? { kind: "fall-through", format, detail: "the delimited parse did not succeed" } : { kind: "rows", rows };
|
|
375
|
+
if (format === "json")
|
|
376
|
+
return parseJsonTable(text);
|
|
377
|
+
return parseDelimited(text, format === "tsv" ? "\t" : ",");
|
|
373
378
|
}
|
|
374
379
|
/**
|
|
375
380
|
* Compute the identity of one artifact: membership, containment, and the on-disk hash.
|
|
@@ -417,58 +422,6 @@ async function computeIdentity(workspaceRoot, analysisId, path, snapshot, readCa
|
|
|
417
422
|
readCache?.set(resolved.absolute, { signature, hash: onDiskHash });
|
|
418
423
|
return { kind: "ready", onDiskHash, fileType: entry.fileType, absolute: resolved.absolute, size, signature };
|
|
419
424
|
}
|
|
420
|
-
/**
|
|
421
|
-
* Resolve each fall-through artifact through the extraction arm. One call covers the whole batch. An
|
|
422
|
-
* absent arm gives back `unavailable`, and the detail names the absent arm. An arm that gives no answer
|
|
423
|
-
* for a path gives back `unreadable`.
|
|
424
|
-
*/
|
|
425
|
-
async function extractFallThrough(arm, requests) {
|
|
426
|
-
const out = new Map();
|
|
427
|
-
if (requests.length === 0) {
|
|
428
|
-
return out;
|
|
429
|
-
}
|
|
430
|
-
if (arm === undefined) {
|
|
431
|
-
for (const request of requests) {
|
|
432
|
-
out.set(request.path, {
|
|
433
|
-
kind: "unavailable",
|
|
434
|
-
detail: `the extraction arm is not wired, and the file at ${request.path} needs it because ${request.hostDetail}`,
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
return out;
|
|
438
|
-
}
|
|
439
|
-
let answered;
|
|
440
|
-
try {
|
|
441
|
-
answered = await arm.extract(requests.map((request) => ({ path: request.path, hash: request.hash, format: request.format })));
|
|
442
|
-
}
|
|
443
|
-
catch (cause) {
|
|
444
|
-
// The arm speaks the throw protocol for a genuine infrastructure fault. This boundary turns the
|
|
445
|
-
// throw into a value, thus each reference on the batch reads a failure as data. A cancel of the
|
|
446
|
-
// workflow is not a fault of the read, thus it leaves to DBOS with no change.
|
|
447
|
-
if (isWorkflowCancellation(cause))
|
|
448
|
-
throw cause;
|
|
449
|
-
for (const request of requests) {
|
|
450
|
-
out.set(request.path, { kind: "unreadable", detail: `the extraction arm did not read the file at ${request.path}` });
|
|
451
|
-
}
|
|
452
|
-
return out;
|
|
453
|
-
}
|
|
454
|
-
if (answered.isErr()) {
|
|
455
|
-
for (const request of requests) {
|
|
456
|
-
out.set(request.path, {
|
|
457
|
-
kind: "unavailable",
|
|
458
|
-
detail: `the host refused the sandbox (${answered.error.reason}), thus the file at ${request.path} was not read`,
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
return out;
|
|
462
|
-
}
|
|
463
|
-
const answers = answered.value;
|
|
464
|
-
for (const request of requests) {
|
|
465
|
-
const answer = answers.get(request.path);
|
|
466
|
-
out.set(request.path, answer === undefined
|
|
467
|
-
? { kind: "unreadable", detail: `the extraction arm did not read the file at ${request.path}` }
|
|
468
|
-
: { kind: "rows", rows: answer.rows });
|
|
469
|
-
}
|
|
470
|
-
return out;
|
|
471
|
-
}
|
|
472
425
|
/**
|
|
473
426
|
* Give back the rows that an earlier pass read for these exact bytes, or `undefined` when nothing shared
|
|
474
427
|
* them. The signature compare is the whole guard: a file that changed on disk holds a different signature,
|
|
@@ -479,8 +432,8 @@ function sharedRows(readCache, identity) {
|
|
|
479
432
|
return held !== undefined && held.signature === identity.signature && held.rows !== undefined ? held.rows : undefined;
|
|
480
433
|
}
|
|
481
434
|
/**
|
|
482
|
-
* Share the rows of one clean read, thus the next pass over the same bytes
|
|
483
|
-
*
|
|
435
|
+
* Share the rows of one clean read, thus the next pass over the same bytes parses nothing again. A failed
|
|
436
|
+
* read is transient, thus only rows enter the cache.
|
|
484
437
|
*/
|
|
485
438
|
function shareRows(readCache, identity, rows) {
|
|
486
439
|
readCache?.set(identity.absolute, { signature: identity.signature, hash: identity.onDiskHash, rows });
|
|
@@ -500,7 +453,7 @@ function accessesOf(reference) {
|
|
|
500
453
|
}
|
|
501
454
|
}
|
|
502
455
|
/**
|
|
503
|
-
* Make the production resolver over the workspace root
|
|
456
|
+
* Make the production resolver over the workspace root.
|
|
504
457
|
*
|
|
505
458
|
* The resolver holds a per-pass cache. `prepare` groups the references by artifact, reads each file one
|
|
506
459
|
* time, and fills the cache. `resolve` then answers from the cache. A `resolve` with no prior `prepare`
|
|
@@ -508,7 +461,7 @@ function accessesOf(reference) {
|
|
|
508
461
|
* artifact on both paths, and never one read for each reference.
|
|
509
462
|
*/
|
|
510
463
|
export function createProductionResolver(deps) {
|
|
511
|
-
const { workspaceRoot, analysisId,
|
|
464
|
+
const { workspaceRoot, analysisId, readCache } = deps;
|
|
512
465
|
const cap = deps.cap ?? DEFAULT_CAP_BYTES;
|
|
513
466
|
// The per-pass caches. `prepare` clears and refills them, thus a later pass reads the artifacts again.
|
|
514
467
|
const idCache = new Map();
|
|
@@ -528,8 +481,8 @@ export function createProductionResolver(deps) {
|
|
|
528
481
|
}
|
|
529
482
|
/**
|
|
530
483
|
* Give back the cells of one path, from the cache after a prepare, or by a fresh read. A fresh read
|
|
531
|
-
* runs the host fast path
|
|
532
|
-
*
|
|
484
|
+
* runs the host fast path. The outcome enters the cache, thus a second reference at one path reads
|
|
485
|
+
* nothing again.
|
|
533
486
|
*/
|
|
534
487
|
async function getCells(path, identity) {
|
|
535
488
|
const cached = cellsCache.get(path);
|
|
@@ -549,18 +502,9 @@ export function createProductionResolver(deps) {
|
|
|
549
502
|
cellsCache.set(path, parsed);
|
|
550
503
|
return parsed;
|
|
551
504
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
return unavailable;
|
|
556
|
-
}
|
|
557
|
-
const resolved = await extractFallThrough(extractionArm, [{ path, hash: identity.onDiskHash, format: read.format, hostDetail: read.detail }]);
|
|
558
|
-
const cells = resolved.get(path) ?? { kind: "unreadable", detail: `the extraction arm did not read the file at ${path}` };
|
|
559
|
-
if (cells.kind === "rows") {
|
|
560
|
-
shareRows(readCache, identity, cells.rows);
|
|
561
|
-
}
|
|
562
|
-
cellsCache.set(path, cells);
|
|
563
|
-
return cells;
|
|
505
|
+
const unavailable = read.kind === "unsupported-format" ? { kind: "unavailable", detail: read.detail } : fallThroughCells(path, read.detail);
|
|
506
|
+
cellsCache.set(path, unavailable);
|
|
507
|
+
return unavailable;
|
|
564
508
|
}
|
|
565
509
|
/**
|
|
566
510
|
* The identity gate that a cell-reading reference passes before a read of cells.
|
|
@@ -788,7 +732,7 @@ export function createProductionResolver(deps) {
|
|
|
788
732
|
}
|
|
789
733
|
}
|
|
790
734
|
// An earlier pass over these exact bytes already paid for the rows. Take them, thus the second pass
|
|
791
|
-
// of one analysis parses nothing again
|
|
735
|
+
// of one analysis parses nothing again.
|
|
792
736
|
const pending = [];
|
|
793
737
|
for (const target of cellTargets) {
|
|
794
738
|
const shared = sharedRows(readCache, target.identity);
|
|
@@ -800,10 +744,6 @@ export function createProductionResolver(deps) {
|
|
|
800
744
|
}
|
|
801
745
|
}
|
|
802
746
|
const reads = await allWithConcurrency(pending.map((target) => async () => ({ target, read: await hostReadCells(cap, target.path, target.identity) })), PREPARE_CONCURRENCY);
|
|
803
|
-
// Split the clean reads from the fall-throughs, then resolve every fall-through in one arm call. An
|
|
804
|
-
// unsupported format reaches no arm, because no reader is decided for it.
|
|
805
|
-
const fallThrough = [];
|
|
806
|
-
const identityByPath = new Map();
|
|
807
747
|
for (const { target, read } of reads) {
|
|
808
748
|
if (read.kind === "rows") {
|
|
809
749
|
cellsCache.set(target.path, { kind: "rows", rows: read.rows });
|
|
@@ -813,16 +753,7 @@ export function createProductionResolver(deps) {
|
|
|
813
753
|
cellsCache.set(target.path, { kind: "unavailable", detail: read.detail });
|
|
814
754
|
}
|
|
815
755
|
else {
|
|
816
|
-
|
|
817
|
-
fallThrough.push({ path: target.path, hash: target.identity.onDiskHash, format: read.format, hostDetail: read.detail });
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
const resolved = await extractFallThrough(extractionArm, fallThrough);
|
|
821
|
-
for (const [path, cells] of resolved) {
|
|
822
|
-
cellsCache.set(path, cells);
|
|
823
|
-
const identity = identityByPath.get(path);
|
|
824
|
-
if (cells.kind === "rows" && identity !== undefined) {
|
|
825
|
-
shareRows(readCache, identity, cells.rows);
|
|
756
|
+
cellsCache.set(target.path, fallThroughCells(target.path, read.detail));
|
|
826
757
|
}
|
|
827
758
|
}
|
|
828
759
|
}
|
|
@@ -46,6 +46,15 @@ export declare function rendererApi(api: Echarts.CustomSeriesRenderItemAPI): Ren
|
|
|
46
46
|
* behind.
|
|
47
47
|
*/
|
|
48
48
|
export declare function renderChartSvg(echarts: ChartRuntime, option: EchartOption, size: ChartExportSize): Result<string, string>;
|
|
49
|
+
/**
|
|
50
|
+
* The count of coordinates that one option draws, summed over its series.
|
|
51
|
+
*
|
|
52
|
+
* The count bounds the export. A cloud of many thousands of points gives an SVG of many megabytes, two times,
|
|
53
|
+
* thus the page builds the SVG of such a chart on a click, with the points as one raster layer. An empty slot draws nothing, thus it counts nothing. A radar
|
|
54
|
+
* polygon draws one coordinate for each indicator, and a violin outline draws two vertices for each grid
|
|
55
|
+
* point, thus each counts every coordinate that it draws.
|
|
56
|
+
*/
|
|
57
|
+
export declare function plottedPoints(option: EchartOption): number;
|
|
49
58
|
/**
|
|
50
59
|
* The two SVG files of one chart, or `undefined` for a chart past the export bound.
|
|
51
60
|
*
|
|
@@ -138,7 +138,7 @@ function finishedSvg(svg, size) {
|
|
|
138
138
|
* polygon draws one coordinate for each indicator, and a violin outline draws two vertices for each grid
|
|
139
139
|
* point, thus each counts every coordinate that it draws.
|
|
140
140
|
*/
|
|
141
|
-
function plottedPoints(option) {
|
|
141
|
+
export function plottedPoints(option) {
|
|
142
142
|
const series = option.series;
|
|
143
143
|
if (!Array.isArray(series))
|
|
144
144
|
return 0;
|
|
@@ -19,6 +19,7 @@ import { type ConversationAgentDeps } from "../agents/conversation-agent.js";
|
|
|
19
19
|
import { type ApprovePlanInput, type ApprovePlanRefusal, type PlanApproval } from "../app/approve-plan.js";
|
|
20
20
|
import { type ChatTurns } from "../app/chat-turn-workflow.js";
|
|
21
21
|
import { type WorkSurface } from "../app/work.js";
|
|
22
|
+
import { type RunCanceler } from "../execution/run-canceler.js";
|
|
22
23
|
import { type ReportSessionRuntime } from "../app/report-session-runtime.js";
|
|
23
24
|
import type { UsageRecorder } from "../billing/usage-recorder.js";
|
|
24
25
|
import type { ResourcePolicy } from "../config/resource-limits.js";
|
|
@@ -27,6 +28,7 @@ import { type ChromeConfig } from "../lib/chrome.js";
|
|
|
27
28
|
import { type AcquireEyes } from "../lib/eyes.js";
|
|
28
29
|
import type { ThreadType } from "../memory/thread-store.js";
|
|
29
30
|
import { type ExecuteAnalysisDeps, type ExecuteAnalysisInput, type ExecuteAnalysisResult } from "../workflows/execute-analysis.js";
|
|
31
|
+
import type { SandboxClient } from "../sandbox/client.js";
|
|
30
32
|
import { type SandboxStepDeps, type SandboxStepInput, type SandboxStepResult } from "../workflows/sandbox-step.js";
|
|
31
33
|
import { type DataProfileDeps, type DataProfileWorkflowInput } from "../tasks/data-profile.js";
|
|
32
34
|
import { type CitationResolverConfig } from "../citations/resolve.js";
|
|
@@ -56,12 +58,19 @@ export type SandboxStepCallable = (input: SandboxStepInput) => Promise<SandboxSt
|
|
|
56
58
|
* the same memory that the conversation agent writes.
|
|
57
59
|
*/
|
|
58
60
|
export type CoreWorkflowDeps = {
|
|
59
|
-
readonly sandboxStep: Omit<SandboxStepDeps, "usageRecorder" | "citationResolver" | "toolOutputStore" | "runAuthorizer">;
|
|
60
|
-
readonly buildExecuteAnalysis: (sandboxStep: SandboxStepCallable) => Omit<ExecuteAnalysisDeps, "usageRecorder" | "
|
|
61
|
-
/** API keys for the bio/chem tools of the
|
|
61
|
+
readonly sandboxStep: Omit<SandboxStepDeps, "usageRecorder" | "citationResolver" | "toolOutputStore" | "runAuthorizer" | "leases">;
|
|
62
|
+
readonly buildExecuteAnalysis: (sandboxStep: SandboxStepCallable) => Omit<ExecuteAnalysisDeps, "usageRecorder" | "synthesisLookups" | "toolOutputStore" | "workingMemory" | "workspaceFs"> & {
|
|
63
|
+
/** API keys for the bio/chem tools of the lookups of the synthesis. */
|
|
62
64
|
readonly bioKeys: BioToolKeys;
|
|
63
65
|
};
|
|
64
|
-
readonly dataProfile: Omit<DataProfileDeps, "usageRecorder" | "toolOutputStore">;
|
|
66
|
+
readonly dataProfile: Omit<DataProfileDeps, "usageRecorder" | "toolOutputStore" | "leases">;
|
|
67
|
+
};
|
|
68
|
+
/** The sandboxes of the runtime. The assembly builds the one sandbox module over the client. */
|
|
69
|
+
export type CoreSandboxDeps = {
|
|
70
|
+
/** The backend client that the embedder made. Only the sandbox module calls it. */
|
|
71
|
+
readonly client: SandboxClient;
|
|
72
|
+
/** How long a lease can go unused before it loses its machine. Absent: 15 minutes. */
|
|
73
|
+
readonly idlePeriodMs?: number;
|
|
65
74
|
};
|
|
66
75
|
/** The registered, callable workflow handles. */
|
|
67
76
|
export type RegisteredWorkflows = {
|
|
@@ -86,7 +95,7 @@ export type RegisteredWorkflows = {
|
|
|
86
95
|
* chrome config. A caller that bound the eyes here would give the conversation
|
|
87
96
|
* agent a seam that the report agent never sees.
|
|
88
97
|
*/
|
|
89
|
-
export type ConversationAssemblyDeps = Omit<ConversationAgentDeps, "executeAnalysisWorkflow" | "
|
|
98
|
+
export type ConversationAssemblyDeps = Omit<ConversationAgentDeps, "executeAnalysisWorkflow" | "usageRecorder" | "citationResolver" | "anchorReportSession" | "eyes" | "toolOutputStore" | "registerSubAgent">;
|
|
90
99
|
/**
|
|
91
100
|
* What binds one reference resolver: the analysis whose pinned artifacts it reads, and the identity and the
|
|
92
101
|
* auth of the tool call that reads them. A resolver serves one analysis, thus the report tools build one for
|
|
@@ -105,9 +114,9 @@ export type MakeReportReferenceResolver = (scope: ReportResolverScope) => Promis
|
|
|
105
114
|
export type CoreRuntimeDeps = {
|
|
106
115
|
readonly conversation: ConversationAssemblyDeps;
|
|
107
116
|
readonly workflows: CoreWorkflowDeps;
|
|
117
|
+
readonly sandbox: CoreSandboxDeps;
|
|
108
118
|
/**
|
|
109
|
-
* Host resource policy — per-step ceilings and
|
|
110
|
-
* point for planner/routing guidance and workflow-input budget snapshots.
|
|
119
|
+
* Host resource policy — the per-step ceilings and the budget of the sandbox lease grant.
|
|
111
120
|
*/
|
|
112
121
|
readonly resourcePolicy?: ResourcePolicy;
|
|
113
122
|
/**
|
|
@@ -121,7 +130,7 @@ export type CoreRuntimeDeps = {
|
|
|
121
130
|
readonly citationResolverConfig?: CitationResolverConfig;
|
|
122
131
|
/**
|
|
123
132
|
* The byte cap on the in-process host read of a report reference. A file over the
|
|
124
|
-
* cap falls through
|
|
133
|
+
* cap falls through, and its reference fails as `extraction-unavailable`. Absent, the resolver uses its 16 MiB
|
|
125
134
|
* default. The embedder tunes it here, thus a host changes it with no harness change.
|
|
126
135
|
*/
|
|
127
136
|
readonly reportHostReadCapBytes?: number;
|
|
@@ -129,7 +138,7 @@ export type CoreRuntimeDeps = {
|
|
|
129
138
|
* The report reference resolver of an embedder. A managed host reads its pinned
|
|
130
139
|
* artifacts from its own store, thus it binds a realization of the seam here and the
|
|
131
140
|
* report tools resolve through it. Absent, the harness wires the production resolver
|
|
132
|
-
* over the workspace tree
|
|
141
|
+
* over the workspace tree, which is the whole OSS path. A bound
|
|
133
142
|
* factory replaces that wiring, thus `reportHostReadCapBytes` then governs nothing.
|
|
134
143
|
*/
|
|
135
144
|
readonly makeReportReferenceResolver?: MakeReportReferenceResolver;
|
|
@@ -263,6 +272,8 @@ export type CoreRuntime = {
|
|
|
263
272
|
* ends one work in each state, and `resume` and `hold` reach the waits of one work. Only a client resumes paused work.
|
|
264
273
|
*/
|
|
265
274
|
readonly work: WorkSurface;
|
|
275
|
+
/** The run canceler of `work`. It also ends the sandbox leases of the canceled workflows at once. */
|
|
276
|
+
readonly runCanceler: RunCanceler;
|
|
266
277
|
/**
|
|
267
278
|
* Approve a stored plan by its id and start its run with no model call. It runs over the deps that
|
|
268
279
|
* reach the `execute_analysis` tool of the conversation agent, thus the approval and the tool launch
|
package/dist/runtime/assemble.js
CHANGED
|
@@ -28,9 +28,11 @@ import { workPause } from "../workflows/pause.js";
|
|
|
28
28
|
import { hasBrowserUrl } from "../lib/chrome.js";
|
|
29
29
|
import { createStaticEyes } from "../lib/eyes.js";
|
|
30
30
|
import { registerExecuteAnalysis } from "../workflows/execute-analysis.js";
|
|
31
|
+
import { createSandboxLeases } from "../sandbox/leases.js";
|
|
32
|
+
import { createNoopLogger } from "../lib/console-logger.js";
|
|
33
|
+
import { dbosClientFor } from "../execution/dbos-workflow-purger.js";
|
|
31
34
|
import { registerSandboxStep } from "../workflows/sandbox-step.js";
|
|
32
35
|
import { registerDataProfileWorkflow, stopDataProfile } from "../tasks/data-profile.js";
|
|
33
|
-
import { createExtractionArm, runExtraction } from "../tasks/extract-values.js";
|
|
34
36
|
import { createCitationResolver } from "../citations/resolve.js";
|
|
35
37
|
import { createThreadStore } from "../memory/thread-store.js";
|
|
36
38
|
import { createWorkingMemory } from "../memory/working-memory.js";
|
|
@@ -38,7 +40,7 @@ import { createArtifactReadStore, createProductionResolver } from "../report-mod
|
|
|
38
40
|
import { createReportVersionStore } from "../state/report-versions.js";
|
|
39
41
|
import { createToolOutputStore } from "../state/tool-outputs.js";
|
|
40
42
|
import { createAskGateway } from "../tools/approval/gateway.js";
|
|
41
|
-
import {
|
|
43
|
+
import { createSynthesisLookupTools } from "../tools/research/synthesis-lookups.js";
|
|
42
44
|
const _assertDomainError = true;
|
|
43
45
|
/**
|
|
44
46
|
* Wrap a type→agent registry as the resolution surface. Held apart from
|
|
@@ -83,7 +85,7 @@ export function resolveCompositionEyes(seam, chrome) {
|
|
|
83
85
|
return undefined;
|
|
84
86
|
}
|
|
85
87
|
export function assembleCoreRuntime(deps) {
|
|
86
|
-
const { conversation, workflows: wf
|
|
88
|
+
const { conversation, workflows: wf } = deps;
|
|
87
89
|
const usageRecorder = deps.usageRecorder ?? createNoopUsageRecorder();
|
|
88
90
|
const citationResolver = createCitationResolver({
|
|
89
91
|
...deps.citationResolverConfig,
|
|
@@ -102,8 +104,21 @@ export function assembleCoreRuntime(deps) {
|
|
|
102
104
|
logger: conversation.logger,
|
|
103
105
|
}).afterFailure;
|
|
104
106
|
const registerPausingSubAgent = (name, body) => registerSubAgent(name, body, subAgentPauses);
|
|
107
|
+
// One sandbox module for each runtime: one budget, one lease workflow, and one reconciler.
|
|
108
|
+
const leases = createSandboxLeases({
|
|
109
|
+
pool: conversation.pool,
|
|
110
|
+
client: deps.sandbox.client,
|
|
111
|
+
resourcePolicy: deps.resourcePolicy,
|
|
112
|
+
resolveWorkspaceRoot: conversation.resolveWorkspaceRoot,
|
|
113
|
+
runAuthorizer: conversation.runAuthorizer,
|
|
114
|
+
idlePeriodMs: deps.sandbox.idlePeriodMs,
|
|
115
|
+
pauseRetryDelaysMs,
|
|
116
|
+
logger: conversation.logger,
|
|
117
|
+
dbosClient: () => dbosClientFor(conversation.pool, conversation.logger ?? createNoopLogger()),
|
|
118
|
+
});
|
|
105
119
|
const sandboxStep = registerSandboxStep({
|
|
106
120
|
...wf.sandboxStep,
|
|
121
|
+
leases,
|
|
107
122
|
citationResolver,
|
|
108
123
|
usageRecorder,
|
|
109
124
|
toolOutputStore,
|
|
@@ -111,24 +126,18 @@ export function assembleCoreRuntime(deps) {
|
|
|
111
126
|
runAuthorizer: conversation.runAuthorizer,
|
|
112
127
|
});
|
|
113
128
|
const { bioKeys: synthesisBioKeys, ...executeAnalysisDeps } = wf.buildExecuteAnalysis(sandboxStep);
|
|
114
|
-
const
|
|
115
|
-
provider: executeAnalysisDeps.provider,
|
|
116
|
-
model: executeAnalysisDeps.synthesisModel,
|
|
117
|
-
bioKeys: synthesisBioKeys,
|
|
118
|
-
citationResolver,
|
|
119
|
-
usageRecorder,
|
|
120
|
-
toolOutputStore,
|
|
121
|
-
logger: executeAnalysisDeps.logger,
|
|
122
|
-
}, registerPausingSubAgent);
|
|
129
|
+
const synthesisLookups = createSynthesisLookupTools({ bioKeys: synthesisBioKeys, citationResolver, logger: executeAnalysisDeps.logger });
|
|
123
130
|
const executeAnalysis = registerExecuteAnalysis({
|
|
124
131
|
...executeAnalysisDeps,
|
|
125
|
-
|
|
132
|
+
synthesisLookups,
|
|
133
|
+
scriptRuntime: conversation.scriptRuntime,
|
|
134
|
+
workspaceFs: conversation.workspaceFs,
|
|
126
135
|
usageRecorder,
|
|
127
136
|
toolOutputStore,
|
|
128
137
|
workingMemory: createWorkingMemory(conversation.pool),
|
|
129
138
|
pauseRetryDelaysMs,
|
|
130
139
|
});
|
|
131
|
-
const dataProfile = registerDataProfileWorkflow({ ...wf.dataProfile, usageRecorder, toolOutputStore, pauseRetryDelaysMs });
|
|
140
|
+
const dataProfile = registerDataProfileWorkflow({ ...wf.dataProfile, leases, usageRecorder, toolOutputStore, pauseRetryDelaysMs });
|
|
132
141
|
// The session runtime binds the per-session state to the thread behind the
|
|
133
142
|
// tool boundary, thus one instance serves every report thread. It comes before
|
|
134
143
|
// the conversation agent, because `start_report_session` takes its anchor
|
|
@@ -147,7 +156,6 @@ export function assembleCoreRuntime(deps) {
|
|
|
147
156
|
...conversation,
|
|
148
157
|
executeAnalysisWorkflow: executeAnalysis,
|
|
149
158
|
anchorReportSession: reportSession.ensureSessionState.bind(reportSession),
|
|
150
|
-
resourcePolicy,
|
|
151
159
|
usageRecorder,
|
|
152
160
|
toolOutputStore,
|
|
153
161
|
citationResolver,
|
|
@@ -164,21 +172,16 @@ export function assembleCoreRuntime(deps) {
|
|
|
164
172
|
const reportThreads = createThreadStore(conversation.pool);
|
|
165
173
|
// The read cache of the production report path, one for each recent analysis. A preview
|
|
166
174
|
// and the record that follows it are two tool calls over one draft, thus they meet the
|
|
167
|
-
// same artifacts. The store carries the streamed hash and the
|
|
168
|
-
//
|
|
169
|
-
// call never outlives the call, and one unchanged file costs one hash and one container.
|
|
175
|
+
// same artifacts. The store carries the streamed hash and the parsed rows between them,
|
|
176
|
+
// thus one unchanged file costs one hash and one parse.
|
|
170
177
|
const reportArtifactReads = createArtifactReadStore();
|
|
171
178
|
// The reference resolver of the report path, and its production wiring. A resolver reads
|
|
172
179
|
// the pinned artifacts of one analysis, thus the factory binds one analysis and one caller
|
|
173
|
-
// for each tool call. The
|
|
174
|
-
// rail of the profile for an over-cap file or a host parse fault. The pass runs inside the
|
|
175
|
-
// step of the tool call. The cap gates the host read, and the resolver defaults it to 16 MiB.
|
|
180
|
+
// for each tool call. The cap gates the host read, and the resolver defaults it to 16 MiB.
|
|
176
181
|
const makeProductionReportResolver = async (scope) => {
|
|
177
|
-
const arm = createExtractionArm((requests) => runExtraction({ sandboxClient: wf.dataProfile.sandboxClient, logger: wf.dataProfile.logger }, scope, requests));
|
|
178
182
|
return createProductionResolver({
|
|
179
183
|
workspaceRoot: await conversation.resolveWorkspaceRoot(scope.analysisId),
|
|
180
184
|
analysisId: scope.analysisId,
|
|
181
|
-
extractionArm: arm,
|
|
182
185
|
readCache: reportArtifactReads.forAnalysis(scope.analysisId),
|
|
183
186
|
cap: deps.reportHostReadCapBytes,
|
|
184
187
|
});
|
|
@@ -192,13 +195,9 @@ export function assembleCoreRuntime(deps) {
|
|
|
192
195
|
gateway: reportSession.gateway,
|
|
193
196
|
resolveWorkspaceRoot: conversation.resolveWorkspaceRoot,
|
|
194
197
|
store: reportVersionStore,
|
|
198
|
+
derivations: reportSession.derivations,
|
|
195
199
|
threads: reportThreads,
|
|
196
200
|
chrome: conversation.chrome,
|
|
197
|
-
// The derivation tool draws the rail of the value tier: the same sandbox client. Thus a
|
|
198
|
-
// session derivation and an extraction run on one substrate, and neither one mints a run
|
|
199
|
-
// of the analysis.
|
|
200
|
-
derivations: reportSession.derivations,
|
|
201
|
-
sandboxClient: wf.dataProfile.sandboxClient,
|
|
202
201
|
makeResolver: makeReportResolver,
|
|
203
202
|
eyes,
|
|
204
203
|
resolvePageAsset: deps.resolveReportPageAsset,
|
|
@@ -207,6 +206,7 @@ export function assembleCoreRuntime(deps) {
|
|
|
207
206
|
provenance: deps.provenance,
|
|
208
207
|
logger: conversation.logger,
|
|
209
208
|
toolOutputStore,
|
|
209
|
+
scriptRuntime: conversation.scriptRuntime,
|
|
210
210
|
});
|
|
211
211
|
// The single registration point for every typed agent. A future thread type's
|
|
212
212
|
// agent plugs in here at assembly with no embedder change. `conversation` is
|
|
@@ -232,8 +232,18 @@ export function assembleCoreRuntime(deps) {
|
|
|
232
232
|
credentialFor: deps.credentialFor,
|
|
233
233
|
pauseRetryDelaysMs,
|
|
234
234
|
});
|
|
235
|
+
const runCanceler = createRunCanceler({
|
|
236
|
+
pool: conversation.pool,
|
|
237
|
+
runCharge: executeAnalysisDeps.runCharge,
|
|
238
|
+
runAuthorizer: conversation.runAuthorizer,
|
|
239
|
+
// The end of a canceled run goes where the run engine emits the rest of the run.
|
|
240
|
+
provenance: executeAnalysisDeps.provenance,
|
|
241
|
+
logger: conversation.logger,
|
|
242
|
+
releaseLeasesOf: (workflowIds) => leases.releaseOwnedBy(workflowIds),
|
|
243
|
+
});
|
|
235
244
|
return {
|
|
236
245
|
agents: agentResolver,
|
|
246
|
+
runCanceler,
|
|
237
247
|
askGateway,
|
|
238
248
|
chatTurns,
|
|
239
249
|
work: createWork({
|
|
@@ -241,15 +251,15 @@ export function assembleCoreRuntime(deps) {
|
|
|
241
251
|
runAuthorizer: conversation.runAuthorizer,
|
|
242
252
|
logger: conversation.logger,
|
|
243
253
|
stopTurn: (turnId) => chatTurns.stop(turnId),
|
|
244
|
-
runCanceler
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
254
|
+
runCanceler,
|
|
255
|
+
stopProfile: async (analysisId, workflowId) => {
|
|
256
|
+
await stopDataProfile({ pool: conversation.pool, logger: conversation.logger, notifyDataProfileSettled: wf.dataProfile.notifyDataProfileSettled }, analysisId, workflowId);
|
|
257
|
+
// A canceled body runs no teardown, thus the lease of the profile ends here and not at its owner check.
|
|
258
|
+
await leases.releaseOwnedBy([workflowId]).catch((failure) => {
|
|
259
|
+
const logger = conversation.logger ?? createNoopLogger();
|
|
260
|
+
logger.error("the sandbox lease of a stopped profile did not end", { analysisId, ...logger.errorFields(failure) });
|
|
261
|
+
});
|
|
262
|
+
},
|
|
253
263
|
}),
|
|
254
264
|
reportSession: { ensureSessionState: reportSession.ensureSessionState.bind(reportSession) },
|
|
255
265
|
workflows: {
|
|
@@ -263,7 +273,6 @@ export function assembleCoreRuntime(deps) {
|
|
|
263
273
|
executeAnalysisWorkflow: executeAnalysis,
|
|
264
274
|
runAuthorizer: conversation.runAuthorizer,
|
|
265
275
|
runLauncher: conversation.runLauncher,
|
|
266
|
-
resourcePolicy,
|
|
267
276
|
extendAnalysisFarm: conversation.extendAnalysisFarm,
|
|
268
277
|
logger: conversation.logger,
|
|
269
278
|
provenance: deps.provenance,
|