@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
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The fixed extraction script and its wire protocol.
|
|
3
|
-
*
|
|
4
|
-
* The extraction arm runs this one Python script in the sandbox. The script reads one JSON input: a list
|
|
5
|
-
* of path, format, and hash triples. For each triple the script hashes the file bytes with a streamed
|
|
6
|
-
* sha256 before any read. If the on-disk hash does not match the pinned hash, the script refuses the file
|
|
7
|
-
* as a typed error. If the hash matches, the script reads the file from the read-only analysis mount, and
|
|
8
|
-
* it parses the file by the carried format. A parquet file uses pyarrow. The script emits one JSON map:
|
|
9
|
-
* each path to its rows, or to a typed error. The script decides nothing else. It applies no filter and no
|
|
10
|
-
* projection.
|
|
11
|
-
*
|
|
12
|
-
* The host decides the format one time, and the request carries it. Thus the script derives no reader from
|
|
13
|
-
* an extension, and it refuses a request that names no format. The JSON arm obeys the strict host shape, an
|
|
14
|
-
* array of flat objects, thus a shape that the host refuses is a refusal here too and it never comes back
|
|
15
|
-
* as a table that pandas inferred.
|
|
16
|
-
*
|
|
17
|
-
* The harness holds the script as a string constant, thus the package ships no separate asset file. The
|
|
18
|
-
* script reaches the container as the argument of `python3 -c`. The input reaches the container as one
|
|
19
|
-
* environment variable.
|
|
20
|
-
*/
|
|
21
|
-
import { z } from "zod";
|
|
22
|
-
/**
|
|
23
|
-
* The environment variable that carries the script input. The workflow body sets it to the JSON list of
|
|
24
|
-
* path, format, and hash triples. The script reads it back one time.
|
|
25
|
-
*/
|
|
26
|
-
export const EXTRACTION_INPUT_ENV = "CORTEX_EXTRACTION_REQUESTS";
|
|
27
|
-
/**
|
|
28
|
-
* One artifact row, as plain cells. A text-backed format holds a numeric column as a string, thus a cell
|
|
29
|
-
* is a string or a number.
|
|
30
|
-
*/
|
|
31
|
-
const ExtractionRowSchema = z.record(z.string(), z.union([z.string(), z.number()]));
|
|
32
|
-
/**
|
|
33
|
-
* The outcome for one path. A clean read gives the rows. A per-file read fault gives a typed error, and
|
|
34
|
-
* the script still emits the map. The arm keeps the rows and drops the error, thus a failed path reads as
|
|
35
|
-
* an unread artifact downstream.
|
|
36
|
-
*/
|
|
37
|
-
const ExtractOutcomeSchema = z.union([
|
|
38
|
-
z.object({ rows: z.array(ExtractionRowSchema) }),
|
|
39
|
-
z.object({ error: z.object({ type: z.string(), message: z.string() }) }),
|
|
40
|
-
]);
|
|
41
|
-
/** The script output: each requested path to its outcome. */
|
|
42
|
-
export const ExtractValuesResultSchema = z.record(z.string(), ExtractOutcomeSchema);
|
|
43
|
-
/**
|
|
44
|
-
* The one extraction script. The workflow body runs it as the argument of `python3 -c`. The script reads
|
|
45
|
-
* the request list from `CORTEX_EXTRACTION_REQUESTS`, and it emits the value map to stdout.
|
|
46
|
-
*
|
|
47
|
-
* The Python comments obey the same Simplified Technical English rule as the harness comments.
|
|
48
|
-
*/
|
|
49
|
-
export const EXTRACTION_SCRIPT = `import hashlib
|
|
50
|
-
import json
|
|
51
|
-
import math
|
|
52
|
-
import os
|
|
53
|
-
import sys
|
|
54
|
-
|
|
55
|
-
import pandas as pd
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def sha256_of(path):
|
|
59
|
-
# The host pins the exact bytes with a streamed sha256, in the "sha256:<hex>" form. Mirror that form
|
|
60
|
-
# here, and stream the file in blocks, thus a large file never loads fully into memory.
|
|
61
|
-
digest = hashlib.sha256()
|
|
62
|
-
with open(path, "rb") as handle:
|
|
63
|
-
for block in iter(lambda: handle.read(1024 * 1024), b""):
|
|
64
|
-
digest.update(block)
|
|
65
|
-
return "sha256:" + digest.hexdigest()
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def coerce_cell(value):
|
|
69
|
-
# A null cell becomes None, thus the record drops the key.
|
|
70
|
-
if value is None:
|
|
71
|
-
return None
|
|
72
|
-
# A numpy scalar becomes a plain Python scalar.
|
|
73
|
-
if hasattr(value, "item"):
|
|
74
|
-
try:
|
|
75
|
-
value = value.item()
|
|
76
|
-
except (ValueError, TypeError):
|
|
77
|
-
return str(value)
|
|
78
|
-
if isinstance(value, bool):
|
|
79
|
-
return "true" if value else "false"
|
|
80
|
-
if isinstance(value, float):
|
|
81
|
-
if math.isnan(value) or math.isinf(value):
|
|
82
|
-
return None
|
|
83
|
-
return value
|
|
84
|
-
if isinstance(value, int):
|
|
85
|
-
return value
|
|
86
|
-
if isinstance(value, str):
|
|
87
|
-
return value
|
|
88
|
-
return str(value)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def read_frame(path, fmt):
|
|
92
|
-
# pyarrow reads the parquet columnar format.
|
|
93
|
-
if fmt == "parquet":
|
|
94
|
-
return pd.read_parquet(path, engine="pyarrow")
|
|
95
|
-
if fmt == "tsv":
|
|
96
|
-
# keep_default_na=False keeps a literal cell such as "NA" or an empty string as its text, and the
|
|
97
|
-
# host parser keeps it too. A default read turns each into NaN, and the row builder drops the key.
|
|
98
|
-
return pd.read_csv(path, sep="\\t", dtype=str, keep_default_na=False)
|
|
99
|
-
if fmt == "csv":
|
|
100
|
-
# keep_default_na=False keeps a literal cell such as "NA" or an empty string as its text, thus a
|
|
101
|
-
# text cell survives and the row keeps the key.
|
|
102
|
-
return pd.read_csv(path, dtype=str, keep_default_na=False)
|
|
103
|
-
# The host decides the format for both arms. A request with no decided format is a protocol fault, thus
|
|
104
|
-
# the file refuses here and no reader guesses at it.
|
|
105
|
-
raise ValueError("the request names no supported format: " + str(fmt))
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def json_rows(path):
|
|
109
|
-
# The host reads a JSON table as an array of flat objects, and it refuses any other shape. Obey the
|
|
110
|
-
# same shape here. An inference pass would turn a shape that the host refuses into a different table.
|
|
111
|
-
with open(path, "rb") as handle:
|
|
112
|
-
value = json.load(handle)
|
|
113
|
-
if not isinstance(value, list):
|
|
114
|
-
raise ValueError("the JSON top-level value is not an array")
|
|
115
|
-
rows = []
|
|
116
|
-
for item in value:
|
|
117
|
-
if not isinstance(item, dict):
|
|
118
|
-
raise ValueError("a JSON array item is not an object")
|
|
119
|
-
row = {}
|
|
120
|
-
for key, cell in item.items():
|
|
121
|
-
if isinstance(cell, (dict, list)):
|
|
122
|
-
raise ValueError("a JSON cell holds a nested value")
|
|
123
|
-
coerced = coerce_cell(cell)
|
|
124
|
-
if coerced is not None:
|
|
125
|
-
row[str(key)] = coerced
|
|
126
|
-
rows.append(row)
|
|
127
|
-
return rows
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def rows_of(frame):
|
|
131
|
-
# A null cell becomes None before the record build, thus a missing cell drops.
|
|
132
|
-
clean = frame.astype(object).where(pd.notnull(frame), None)
|
|
133
|
-
records = clean.to_dict(orient="records")
|
|
134
|
-
rows = []
|
|
135
|
-
for record in records:
|
|
136
|
-
row = {}
|
|
137
|
-
for key, value in record.items():
|
|
138
|
-
cell = coerce_cell(value)
|
|
139
|
-
if cell is not None:
|
|
140
|
-
row[str(key)] = cell
|
|
141
|
-
rows.append(row)
|
|
142
|
-
return rows
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def rows_for(path, fmt):
|
|
146
|
-
# The JSON arm reads the strict host shape itself. Each other format reads through pandas.
|
|
147
|
-
if fmt == "json":
|
|
148
|
-
return json_rows(path)
|
|
149
|
-
return rows_of(read_frame(path, fmt))
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def main():
|
|
153
|
-
raw = os.environ.get("${EXTRACTION_INPUT_ENV}", "[]")
|
|
154
|
-
requests = json.loads(raw)
|
|
155
|
-
out = {}
|
|
156
|
-
for request in requests:
|
|
157
|
-
path = request["path"]
|
|
158
|
-
fmt = request.get("format")
|
|
159
|
-
expected = request["hash"]
|
|
160
|
-
try:
|
|
161
|
-
# Hash the file before any read. A file that drifted from the pin never reaches the reader, thus
|
|
162
|
-
# the extraction never gives back drifted bytes for the gate to match against.
|
|
163
|
-
actual = sha256_of(path)
|
|
164
|
-
if actual != expected:
|
|
165
|
-
out[path] = {
|
|
166
|
-
"error": {
|
|
167
|
-
"type": "hash-mismatch",
|
|
168
|
-
"message": f"the pinned hash {expected} does not match the on-disk hash {actual}",
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
continue
|
|
172
|
-
out[path] = {"rows": rows_for(path, fmt)}
|
|
173
|
-
except Exception as exc:
|
|
174
|
-
# A per-file read fault lands as a typed error, and the map still holds each other path.
|
|
175
|
-
out[path] = {"error": {"type": "read-fault", "message": str(exc)}}
|
|
176
|
-
json.dump(out, sys.stdout)
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
main()
|
|
180
|
-
`;
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The extraction pass on the profile rails, and the `ExtractionArm` realization over it.
|
|
3
|
-
*
|
|
4
|
-
* The report resolver falls through to this arm for an over-cap file or a host parse fault. The arm runs one
|
|
5
|
-
* fixed extraction script in an ephemeral sandbox, and it gives back the rows that the script read. No agent
|
|
6
|
-
* loop runs anywhere in this path. A file whose extension names no tabular format never arrives here,
|
|
7
|
-
* because the host decides the format and it refuses the file before the fall-through.
|
|
8
|
-
*
|
|
9
|
-
* The pass runs inside the step of the tool call that resolves the report (`sandbox/step-sandbox.ts`), under
|
|
10
|
-
* the auth of that call, and it mints no mandate. One call can run more than one pass, thus the exec of each
|
|
11
|
-
* pass takes the key of the step and a hash of its requests. The container is ephemeral, and it goes away
|
|
12
|
-
* with the work, thus no standing machine exists.
|
|
13
|
-
*/
|
|
14
|
-
import type { Result } from "neverthrow";
|
|
15
|
-
import type { AuthContext, Identity } from "../auth/types.js";
|
|
16
|
-
import type { Logger } from "../lib/logger.js";
|
|
17
|
-
import type { ExtractionArm, ExtractionArtifact, ExtractionRequest } from "../report-model/production-resolver.js";
|
|
18
|
-
import type { SandboxClient } from "../sandbox/client.js";
|
|
19
|
-
import type { SuspendingRefusal } from "../sandbox/sandbox-error.js";
|
|
20
|
-
import type { ExecRequest, ExecResult } from "../sandbox/types.js";
|
|
21
|
-
import { type ExtractValuesResult } from "./extract-values-script.js";
|
|
22
|
-
/** The construction deps of the pass. It shares the sandbox rail of the profile. */
|
|
23
|
-
export type ExtractionDeps = {
|
|
24
|
-
readonly sandboxClient: SandboxClient;
|
|
25
|
-
/** Operational logging seam. An absent logger falls back to a no-op. */
|
|
26
|
-
readonly logger?: Logger;
|
|
27
|
-
};
|
|
28
|
-
/** The caller of one pass: the analysis that it reads, and the identity and the auth of the tool call. */
|
|
29
|
-
export type ExtractionCaller = {
|
|
30
|
-
readonly analysisId: string;
|
|
31
|
-
readonly identity: Identity;
|
|
32
|
-
readonly auth: AuthContext;
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* Build the sandbox exec for one extraction pass. The command runs the fixed script through `python3 -c`.
|
|
36
|
-
* The working directory is the analysis mount, thus a relative request path reads the correct file. The
|
|
37
|
-
* request list rides in one environment variable.
|
|
38
|
-
*
|
|
39
|
-
* Each request carries its pinned hash. Thus the script can hash the file first and refuse a file that
|
|
40
|
-
* drifted from the pin, before the read gives back drifted bytes.
|
|
41
|
-
*
|
|
42
|
-
* Each request also carries the format that the host decided. The script obeys that format, thus this arm
|
|
43
|
-
* derives no reader from an extension and the two arms can never read one file two ways.
|
|
44
|
-
*
|
|
45
|
-
* The function is pure, thus a test asserts the command shape without a sandbox.
|
|
46
|
-
*/
|
|
47
|
-
export declare function buildExtractionExec(analysisId: string, requests: readonly ExtractionRequest[]): ExecRequest;
|
|
48
|
-
/**
|
|
49
|
-
* Parse the script output from the exec result. A synthetic failure, a timeout, and a non-zero exit each
|
|
50
|
-
* throw, because each means the script did not emit its map. A stdout that is not the map shape throws too.
|
|
51
|
-
*
|
|
52
|
-
* The function is pure, thus a test asserts the parse without a sandbox. The arm turns the throw into a
|
|
53
|
-
* rejected promise.
|
|
54
|
-
*/
|
|
55
|
-
export declare function parseExtractionOutput(result: ExecResult): ExtractValuesResult;
|
|
56
|
-
/**
|
|
57
|
-
* Run one extraction pass: make the container, run the script on every request, and remove the container.
|
|
58
|
-
*
|
|
59
|
-
* A suspending refusal of the spawn is the `err`, and the caller reports it. Each other fault throws.
|
|
60
|
-
*/
|
|
61
|
-
export declare function runExtraction(deps: ExtractionDeps, caller: ExtractionCaller, requests: readonly ExtractionRequest[]): Promise<Result<ExtractValuesResult, SuspendingRefusal>>;
|
|
62
|
-
/** Runs one extraction pass for the bound analysis, and gives the raw value map back, or the refusal of its sandbox. */
|
|
63
|
-
export type ExtractionRunner = (requests: readonly ExtractionRequest[]) => Promise<Result<ExtractValuesResult, SuspendingRefusal>>;
|
|
64
|
-
/**
|
|
65
|
-
* Turn the raw script output into the arm result. A path with rows enters the map. A path with an error
|
|
66
|
-
* drops out, thus the reference at that path reads as an unread artifact, which the seam contract expects.
|
|
67
|
-
*
|
|
68
|
-
* The function is pure, thus a test asserts the mapping without a sandbox.
|
|
69
|
-
*/
|
|
70
|
-
export declare function extractionArtifactsFromResult(result: ExtractValuesResult): Map<string, ExtractionArtifact>;
|
|
71
|
-
/**
|
|
72
|
-
* Make the extraction arm over a runner. One `extract` call makes one run with every request in it, and it
|
|
73
|
-
* gives the value map. A run fault rejects the promise, and the resolver turns the rejection into a failed
|
|
74
|
-
* reference. A refusal of the sandbox with the suspend flag is the `err`, and the resolver reports its reason on each
|
|
75
|
-
* reference.
|
|
76
|
-
*/
|
|
77
|
-
export declare function createExtractionArm(run: ExtractionRunner): ExtractionArm;
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The extraction pass on the profile rails, and the `ExtractionArm` realization over it.
|
|
3
|
-
*
|
|
4
|
-
* The report resolver falls through to this arm for an over-cap file or a host parse fault. The arm runs one
|
|
5
|
-
* fixed extraction script in an ephemeral sandbox, and it gives back the rows that the script read. No agent
|
|
6
|
-
* loop runs anywhere in this path. A file whose extension names no tabular format never arrives here,
|
|
7
|
-
* because the host decides the format and it refuses the file before the fall-through.
|
|
8
|
-
*
|
|
9
|
-
* The pass runs inside the step of the tool call that resolves the report (`sandbox/step-sandbox.ts`), under
|
|
10
|
-
* the auth of that call, and it mints no mandate. One call can run more than one pass, thus the exec of each
|
|
11
|
-
* pass takes the key of the step and a hash of its requests. The container is ephemeral, and it goes away
|
|
12
|
-
* with the work, thus no standing machine exists.
|
|
13
|
-
*/
|
|
14
|
-
import { createHash } from "node:crypto";
|
|
15
|
-
import { createNoopLogger } from "../lib/console-logger.js";
|
|
16
|
-
import { safeParseJsonAs } from "../lib/parse-json.js";
|
|
17
|
-
import { passSpawnSession, withStepSandbox } from "../sandbox/step-sandbox.js";
|
|
18
|
-
import { EXTRACTION_INPUT_ENV, EXTRACTION_SCRIPT, ExtractValuesResultSchema } from "./extract-values-script.js";
|
|
19
|
-
/** The synthetic run id and step id of the extraction pass. Both are constants shared by every analysis. */
|
|
20
|
-
const EXTRACT_VALUES_RUN_LITERAL = "extract-values";
|
|
21
|
-
const EXTRACT_VALUES_STEP_LITERAL = "extract";
|
|
22
|
-
/** The provenance agent id. No agent loop runs, thus this names the extraction pass, not a model agent. */
|
|
23
|
-
const EXTRACT_VALUES_AGENT_ID = "value-extractor";
|
|
24
|
-
/** The exec budget for one extraction pass. It matches the profile budget. */
|
|
25
|
-
const EXTRACTION_DEADLINE_MS = 300_000;
|
|
26
|
-
/**
|
|
27
|
-
* The container size for one extraction pass. The fall-through reads a file that is over the host cap, thus
|
|
28
|
-
* the container needs headroom to load the file into pandas. The size is fixed, because the seam request
|
|
29
|
-
* carries no file size. A later change can size it from the batch.
|
|
30
|
-
*/
|
|
31
|
-
const EXTRACTION_RESOURCES = { cpu: 2, memoryGb: 8 };
|
|
32
|
-
/**
|
|
33
|
-
* Build the sandbox exec for one extraction pass. The command runs the fixed script through `python3 -c`.
|
|
34
|
-
* The working directory is the analysis mount, thus a relative request path reads the correct file. The
|
|
35
|
-
* request list rides in one environment variable.
|
|
36
|
-
*
|
|
37
|
-
* Each request carries its pinned hash. Thus the script can hash the file first and refuse a file that
|
|
38
|
-
* drifted from the pin, before the read gives back drifted bytes.
|
|
39
|
-
*
|
|
40
|
-
* Each request also carries the format that the host decided. The script obeys that format, thus this arm
|
|
41
|
-
* derives no reader from an extension and the two arms can never read one file two ways.
|
|
42
|
-
*
|
|
43
|
-
* The function is pure, thus a test asserts the command shape without a sandbox.
|
|
44
|
-
*/
|
|
45
|
-
export function buildExtractionExec(analysisId, requests) {
|
|
46
|
-
return {
|
|
47
|
-
command: ["python3", "-c", EXTRACTION_SCRIPT],
|
|
48
|
-
cwd: `/${analysisId}`,
|
|
49
|
-
env: { [EXTRACTION_INPUT_ENV]: JSON.stringify(scriptRequests(requests)) },
|
|
50
|
-
timeoutSeconds: Math.floor(EXTRACTION_DEADLINE_MS / 1000),
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function scriptRequests(requests) {
|
|
54
|
-
return requests.map((request) => ({ path: request.path, format: request.format, hash: request.hash }));
|
|
55
|
-
}
|
|
56
|
-
/** The key of one pass inside its step: the same requests give the same exec, and other requests a new one. */
|
|
57
|
-
function requestKey(requests) {
|
|
58
|
-
return createHash("sha256")
|
|
59
|
-
.update(JSON.stringify(scriptRequests(requests)), "utf8")
|
|
60
|
-
.digest("hex")
|
|
61
|
-
.slice(0, 16);
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Parse the script output from the exec result. A synthetic failure, a timeout, and a non-zero exit each
|
|
65
|
-
* throw, because each means the script did not emit its map. A stdout that is not the map shape throws too.
|
|
66
|
-
*
|
|
67
|
-
* The function is pure, thus a test asserts the parse without a sandbox. The arm turns the throw into a
|
|
68
|
-
* rejected promise.
|
|
69
|
-
*/
|
|
70
|
-
export function parseExtractionOutput(result) {
|
|
71
|
-
if (result.syntheticFailure !== undefined) {
|
|
72
|
-
throw new Error(`the extraction sandbox failed: ${result.syntheticFailure.reason}`);
|
|
73
|
-
}
|
|
74
|
-
if (result.timedOut) {
|
|
75
|
-
throw new Error("the extraction sandbox reached the deadline");
|
|
76
|
-
}
|
|
77
|
-
if (result.exitCode !== 0) {
|
|
78
|
-
throw new Error(`the extraction script exited with code ${String(result.exitCode)}`);
|
|
79
|
-
}
|
|
80
|
-
let parsed;
|
|
81
|
-
try {
|
|
82
|
-
parsed = safeParseJsonAs(result.stdout, ExtractValuesResultSchema);
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
throw new Error("the extraction script did not emit valid JSON");
|
|
86
|
-
}
|
|
87
|
-
if (!parsed.success)
|
|
88
|
-
throw parsed.error;
|
|
89
|
-
return parsed.data;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Run one extraction pass: make the container, run the script on every request, and remove the container.
|
|
93
|
-
*
|
|
94
|
-
* A suspending refusal of the spawn is the `err`, and the caller reports it. Each other fault throws.
|
|
95
|
-
*/
|
|
96
|
-
export async function runExtraction(deps, caller, requests) {
|
|
97
|
-
const logger = (deps.logger ?? createNoopLogger()).named("extract-values").with({ analysisId: caller.analysisId });
|
|
98
|
-
try {
|
|
99
|
-
const ran = await withStepSandbox(deps.sandboxClient, {
|
|
100
|
-
session: passSpawnSession(caller, {
|
|
101
|
-
analysisId: caller.analysisId,
|
|
102
|
-
runId: EXTRACT_VALUES_RUN_LITERAL,
|
|
103
|
-
stepId: EXTRACT_VALUES_STEP_LITERAL,
|
|
104
|
-
agentId: EXTRACT_VALUES_AGENT_ID,
|
|
105
|
-
}),
|
|
106
|
-
// The pass only reads, thus the container mounts the analysis tree read-only.
|
|
107
|
-
spec: { resources: EXTRACTION_RESOURCES, readOnly: true },
|
|
108
|
-
execKey: requestKey(requests),
|
|
109
|
-
}, logger, async (exec) => parseExtractionOutput(await exec(buildExtractionExec(caller.analysisId, requests), EXTRACTION_DEADLINE_MS)));
|
|
110
|
-
if (ran.isErr())
|
|
111
|
-
logger.warn("the host refused the sandbox of the extraction", { reason: ran.error.reason });
|
|
112
|
-
return ran;
|
|
113
|
-
}
|
|
114
|
-
catch (cause) {
|
|
115
|
-
logger.error("extraction failed", logger.errorFields(cause));
|
|
116
|
-
throw cause;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Turn the raw script output into the arm result. A path with rows enters the map. A path with an error
|
|
121
|
-
* drops out, thus the reference at that path reads as an unread artifact, which the seam contract expects.
|
|
122
|
-
*
|
|
123
|
-
* The function is pure, thus a test asserts the mapping without a sandbox.
|
|
124
|
-
*/
|
|
125
|
-
export function extractionArtifactsFromResult(result) {
|
|
126
|
-
const out = new Map();
|
|
127
|
-
for (const [path, outcome] of Object.entries(result)) {
|
|
128
|
-
if ("rows" in outcome) {
|
|
129
|
-
out.set(path, { rows: outcome.rows });
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
return out;
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Make the extraction arm over a runner. One `extract` call makes one run with every request in it, and it
|
|
136
|
-
* gives the value map. A run fault rejects the promise, and the resolver turns the rejection into a failed
|
|
137
|
-
* reference. A refusal of the sandbox with the suspend flag is the `err`, and the resolver reports its reason on each
|
|
138
|
-
* reference.
|
|
139
|
-
*/
|
|
140
|
-
export function createExtractionArm(run) {
|
|
141
|
-
return {
|
|
142
|
-
async extract(requests) {
|
|
143
|
-
return (await run(requests)).map(extractionArtifactsFromResult);
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
}
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The derivation tool of a report session.
|
|
3
|
-
*
|
|
4
|
-
* A run writes statistical tables, and not plot-ready ones. This tool reshapes the pinned evidence into one
|
|
5
|
-
* table that a block can bind: a join, a pivot, or an aggregate. The agent writes the script, and the record
|
|
6
|
-
* chains the derived table back to the evidence that made it.
|
|
7
|
-
*
|
|
8
|
-
* A session derivation is not an analysis run. It mints no run id, no mandate, and no artifact, and it writes
|
|
9
|
-
* under the session directory alone. The rails are the rails of the value tier (`tasks/extract-values.ts`):
|
|
10
|
-
* one ephemeral container inside the step of the call (`sandbox/step-sandbox.ts`), which goes away with the
|
|
11
|
-
* work. The container stays until the record lands, thus a rerun of the step before the record adopts the
|
|
12
|
-
* container and the exec record of the first attempt, and the script does not run again. A rerun after the
|
|
13
|
-
* record finds the record of its call, and it gives that table back.
|
|
14
|
-
*
|
|
15
|
-
* The container mounts the analysis tree read-only, and one write mount covers the `derived/` directory of
|
|
16
|
-
* the session alone. The script writes its table into that mount directly, thus a large table makes no
|
|
17
|
-
* roundtrip and no write of the script can reach the workspace tree. The working directory of the exec is
|
|
18
|
-
* that same mount, and the standard output carries the logs of the script alone.
|
|
19
|
-
*
|
|
20
|
-
* The host then reads the file that the container wrote. A path inside the mount is still untrusted bytes: a
|
|
21
|
-
* script can leave a symbolic link in place of its output. Thus the host classifies the file against the
|
|
22
|
-
* workspace root before it hashes one byte, and an escape refuses as typed data.
|
|
23
|
-
*
|
|
24
|
-
* Each declared input must sit in the served membership, and its hash comes from there. The declaration is
|
|
25
|
-
* what the record pins, thus a derived cell traces to a pinned artifact and to the script that read it.
|
|
26
|
-
*
|
|
27
|
-
* The tool refuses an output name that the membership already holds. A record is immutable, and a second
|
|
28
|
-
* derivation of one table takes a new name.
|
|
29
|
-
*
|
|
30
|
-
* A composition with no sandbox client cannot derive at all. The tool reports that condition one time, up
|
|
31
|
-
* front, the same discipline as the eyes. A per-attempt failure would instead read as a transient fault, and
|
|
32
|
-
* it would invite a repeat of a call that can never pass.
|
|
33
|
-
*/
|
|
34
|
-
import { z } from "zod";
|
|
35
|
-
import { type Logger } from "../../lib/logger.js";
|
|
36
|
-
import type { SandboxClient } from "../../sandbox/client.js";
|
|
37
|
-
import type { ExecRequest, ExecResult } from "../../sandbox/types.js";
|
|
38
|
-
import type { DerivationSource, ReportSessionStateStore } from "../../state/report-session-state.js";
|
|
39
|
-
import { type ResolveWorkspaceRoot } from "../../workspace/paths.js";
|
|
40
|
-
import { type Tool } from "../define-tool.js";
|
|
41
|
-
import { type ReportSessionStateGateway, type SessionRefusal } from "../report-authoring/authoring-tools.js";
|
|
42
|
-
import { type ProvenanceSeam } from "../../provenance/seam.js";
|
|
43
|
-
/** The input of one derivation: the script, the declared pinned inputs, and the name of the output file. */
|
|
44
|
-
declare const deriveTableInput: z.ZodObject<{
|
|
45
|
-
script: z.ZodString;
|
|
46
|
-
inputs: z.ZodArray<z.ZodString>;
|
|
47
|
-
output: z.ZodString;
|
|
48
|
-
}, z.core.$strip>;
|
|
49
|
-
export type DeriveTableInput = z.infer<typeof deriveTableInput>;
|
|
50
|
-
/**
|
|
51
|
-
* The typed outcome of the derivation tool. Each arm is ok-channel data, thus the tool never throws for one
|
|
52
|
-
* of them.
|
|
53
|
-
*
|
|
54
|
-
* `derived` carries the workspace-relative path of the derived table, its content hash, the hash of the
|
|
55
|
-
* script, the sources that the record pins, and the header columns of the output. Each other arm names a
|
|
56
|
-
* condition that the agent repairs: a call that is out of bounds, an input that the membership does not
|
|
57
|
-
* hold, a name that a record already holds, a script that failed in the container, and a green script that
|
|
58
|
-
* left no file at the output name.
|
|
59
|
-
*/
|
|
60
|
-
export type DeriveTableResult = {
|
|
61
|
-
outcome: "refused";
|
|
62
|
-
refusal: SessionRefusal;
|
|
63
|
-
} | {
|
|
64
|
-
outcome: "unavailable";
|
|
65
|
-
detail: string;
|
|
66
|
-
} | {
|
|
67
|
-
outcome: "script-too-large";
|
|
68
|
-
bytes: number;
|
|
69
|
-
cap: number;
|
|
70
|
-
detail: string;
|
|
71
|
-
} | {
|
|
72
|
-
outcome: "too-many-inputs";
|
|
73
|
-
count: number;
|
|
74
|
-
cap: number;
|
|
75
|
-
detail: string;
|
|
76
|
-
} | {
|
|
77
|
-
outcome: "unsafe-name";
|
|
78
|
-
detail: string;
|
|
79
|
-
} | {
|
|
80
|
-
outcome: "absent-input";
|
|
81
|
-
path: string;
|
|
82
|
-
detail: string;
|
|
83
|
-
} | {
|
|
84
|
-
outcome: "repeated-name";
|
|
85
|
-
outputPath: string;
|
|
86
|
-
detail: string;
|
|
87
|
-
} | {
|
|
88
|
-
outcome: "exec-failed";
|
|
89
|
-
detail: string;
|
|
90
|
-
} | {
|
|
91
|
-
outcome: "suspended";
|
|
92
|
-
reason: string;
|
|
93
|
-
detail: string;
|
|
94
|
-
} | {
|
|
95
|
-
outcome: "no-output";
|
|
96
|
-
detail: string;
|
|
97
|
-
} | {
|
|
98
|
-
outcome: "derived";
|
|
99
|
-
path: string;
|
|
100
|
-
hash: string;
|
|
101
|
-
scriptHash: string;
|
|
102
|
-
sources: DerivationSource[];
|
|
103
|
-
columns?: string[];
|
|
104
|
-
};
|
|
105
|
-
/**
|
|
106
|
-
* The construction deps of the derivation tool.
|
|
107
|
-
*
|
|
108
|
-
* `derivations` is the append side of the durable session state, thus the record lands beside the document
|
|
109
|
-
* and the pin. `sandboxClient` is the rail of the exec, and a composition that binds none leaves the session
|
|
110
|
-
* with no derivation at all. `resolveWorkspaceRoot` maps the analysis of the call onto its workspace root,
|
|
111
|
-
* thus one singleton tool serves every analysis.
|
|
112
|
-
*/
|
|
113
|
-
export type DeriveTableToolDeps = {
|
|
114
|
-
readonly gateway: ReportSessionStateGateway;
|
|
115
|
-
readonly resolveWorkspaceRoot: ResolveWorkspaceRoot;
|
|
116
|
-
readonly derivations: Pick<ReportSessionStateStore, "appendDerivation">;
|
|
117
|
-
readonly sandboxClient?: SandboxClient;
|
|
118
|
-
/** The provenance seam; an unbound session emit emits nothing and the derivation runs the same. */
|
|
119
|
-
readonly provenance?: ProvenanceSeam;
|
|
120
|
-
readonly logger?: Logger;
|
|
121
|
-
};
|
|
122
|
-
/** The environment variable that carries the declared inputs into the container. */
|
|
123
|
-
export declare const DERIVE_INPUT_ENV = "DERIVE_INPUTS";
|
|
124
|
-
/** The environment variable that carries the container path of the output file into the container. */
|
|
125
|
-
export declare const DERIVE_OUTPUT_ENV = "DERIVE_OUTPUT";
|
|
126
|
-
/** One declared input, as the container reads it: the mounted path of the file, and its pinned hash. */
|
|
127
|
-
export type DerivationInputMount = {
|
|
128
|
-
readonly path: string;
|
|
129
|
-
readonly hash: string;
|
|
130
|
-
};
|
|
131
|
-
/**
|
|
132
|
-
* Build the sandbox exec of one derivation. The command clears the output path, and then it runs the script
|
|
133
|
-
* of the agent through `python3 -c`.
|
|
134
|
-
*
|
|
135
|
-
* The working directory is the write mount, thus the script writes its table beside where it stands. Each
|
|
136
|
-
* declared input rides as its mounted path, thus the script opens the file wherever it works from. The
|
|
137
|
-
* output path rides too, thus the script names no directory of its own.
|
|
138
|
-
*
|
|
139
|
-
* The function is pure, thus a test asserts the command shape without a sandbox.
|
|
140
|
-
*/
|
|
141
|
-
export declare function buildDerivationExec(args: {
|
|
142
|
-
readonly script: string;
|
|
143
|
-
readonly workingDir: string;
|
|
144
|
-
readonly inputs: readonly DerivationInputMount[];
|
|
145
|
-
readonly output: string;
|
|
146
|
-
}): ExecRequest;
|
|
147
|
-
/**
|
|
148
|
-
* Give the failure of an exec result, or `undefined` when the script ran to a clean exit.
|
|
149
|
-
*
|
|
150
|
-
* A synthetic failure, a timeout, and a non-zero exit each mean that no table came back. The detail of a
|
|
151
|
-
* non-zero exit carries the tail of the standard error, thus the agent repairs the script from what the
|
|
152
|
-
* container reported.
|
|
153
|
-
*
|
|
154
|
-
* The function is pure, thus a test asserts the mapping without a sandbox.
|
|
155
|
-
*/
|
|
156
|
-
export declare function describeExecFailure(result: ExecResult): string | undefined;
|
|
157
|
-
/**
|
|
158
|
-
* Make the derivation tool over the session-state gateway, the derivation ledger, and the sandbox rails.
|
|
159
|
-
*
|
|
160
|
-
* The tool reads the thread id from the scope of the call, and it loads the membership through the gateway.
|
|
161
|
-
* Thus one factory serves every thread, and the tool holds no per-session value.
|
|
162
|
-
*/
|
|
163
|
-
export declare function createDeriveTableTool(deps: DeriveTableToolDeps): Tool<DeriveTableInput, DeriveTableResult>;
|
|
164
|
-
export {};
|