@inflexa-ai/harness 0.1.1 → 0.3.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 +48 -0
- package/dist/agents/conversation-agent.d.ts +15 -11
- package/dist/agents/conversation-agent.js +31 -34
- package/dist/agents/report-builder.js +2 -1
- package/dist/agents/sandbox/bulk-transcriptomics-agent.js +1 -1
- package/dist/agents/sandbox/cheminformatics-agent.js +1 -19
- package/dist/agents/sandbox/chromatin-agent.js +1 -10
- package/dist/agents/sandbox/dna-methylation-agent.js +1 -10
- package/dist/agents/sandbox/drug-repurposing-agent.js +4 -14
- package/dist/agents/sandbox/enrichment-agent.js +1 -10
- package/dist/agents/sandbox/ephemeral-executor.js +1 -10
- package/dist/agents/sandbox/genomic-variant-agent.js +1 -3
- package/dist/agents/sandbox/immune-profiling-agent.js +1 -13
- package/dist/agents/sandbox/metabolomics-agent.js +1 -1
- package/dist/agents/sandbox/microbiome-agent.js +1 -1
- package/dist/agents/sandbox/multi-omics-integration-agent.js +1 -12
- package/dist/agents/sandbox/multimodal-sc-agent.js +1 -1
- package/dist/agents/sandbox/network-agent.js +1 -10
- package/dist/agents/sandbox/pkpd-clinical-response-agent.js +2 -8
- package/dist/agents/sandbox/proteomics-agent.js +1 -1
- package/dist/agents/sandbox/scientific-executor.js +1 -10
- package/dist/agents/sandbox/shared.d.ts +20 -6
- package/dist/agents/sandbox/shared.js +50 -39
- package/dist/agents/sandbox/single-cell-agent.js +1 -1
- package/dist/agents/sandbox/spatial-omics-agent.js +1 -1
- package/dist/agents/sandbox/statistical-modeling-agent.js +1 -1
- package/dist/agents/sandbox/translational-safety-agent.js +3 -9
- package/dist/agents/sandbox/types.d.ts +1 -1
- package/dist/agents/system-prompt.d.ts +37 -11
- package/dist/agents/system-prompt.js +35 -12
- package/dist/app/chat-turn.d.ts +3 -0
- package/dist/app/chat-turn.js +3 -1
- package/dist/app/data-profile-orientation.d.ts +34 -0
- package/dist/app/data-profile-orientation.js +117 -0
- package/dist/app/synthesize-run.d.ts +3 -0
- package/dist/app/synthesize-run.js +3 -1
- package/dist/contracts/schemas/chat-parts.d.ts +9 -9
- package/dist/execution/artifact-metadata.d.ts +3 -0
- package/dist/execution/artifact-metadata.js +10 -3
- package/dist/execution/artifact-registration.d.ts +2 -1
- package/dist/execution/artifact-registration.js +8 -2
- package/dist/execution/ephemeral-runner.d.ts +16 -0
- package/dist/execution/ephemeral-runner.js +31 -5
- package/dist/execution/post-step-pipeline.d.ts +3 -0
- package/dist/execution/post-step-pipeline.js +24 -4
- package/dist/execution/reconcile-manifest.d.ts +7 -0
- package/dist/execution/reconcile-manifest.js +19 -5
- package/dist/execution/report-runner.d.ts +3 -0
- package/dist/execution/report-runner.js +4 -4
- package/dist/execution/run-synthesis.js +20 -19
- package/dist/execution/step-summary.d.ts +3 -0
- package/dist/execution/step-summary.js +6 -3
- package/dist/index.d.ts +9 -2
- package/dist/index.js +24 -5
- package/dist/lib/chrome.d.ts +4 -1
- package/dist/lib/chrome.js +10 -7
- package/dist/lib/console-logger.d.ts +19 -0
- package/dist/lib/console-logger.js +62 -0
- package/dist/lib/logger.d.ts +88 -0
- package/dist/lib/logger.js +37 -0
- package/dist/lib/otel.d.ts +2 -1
- package/dist/lib/otel.js +8 -3
- package/dist/loop/__fixtures__/scripted-provider.d.ts +2 -2
- package/dist/loop/__fixtures__/scripted-provider.js +2 -1
- package/dist/loop/metrics.d.ts +33 -1
- package/dist/loop/metrics.js +56 -2
- package/dist/loop/run-agent.d.ts +13 -1
- package/dist/loop/run-agent.js +19 -4
- package/dist/memory/card-builders.d.ts +8 -1
- package/dist/memory/card-builders.js +20 -3
- package/dist/memory/reconstruct-cards.js +4 -3
- package/dist/memory/thread-history.d.ts +27 -2
- package/dist/memory/thread-history.js +45 -5
- package/dist/memory/working-memory.d.ts +93 -10
- package/dist/memory/working-memory.js +220 -84
- package/dist/prompts/SOUL.d.ts +22 -9
- package/dist/prompts/SOUL.js +56 -37
- package/dist/prompts/analogical-reasoner.d.ts +1 -1
- package/dist/prompts/analogical-reasoner.js +2 -2
- package/dist/prompts/briefing.d.ts +100 -0
- package/dist/prompts/briefing.js +166 -0
- package/dist/prompts/conversation.d.ts +1 -1
- package/dist/prompts/conversation.js +94 -440
- package/dist/prompts/literature-reviewer.d.ts +1 -1
- package/dist/prompts/literature-reviewer.js +10 -10
- package/dist/prompts/planner.js +28 -59
- package/dist/prompts/report-builder.d.ts +1 -1
- package/dist/prompts/report-builder.js +71 -24
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +2 -7
- package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/cheminformatics-agent.js +11 -15
- package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
- package/dist/prompts/sandbox/chromatin-agent.js +3 -7
- package/dist/prompts/sandbox/data-profiler.d.ts +1 -1
- package/dist/prompts/sandbox/data-profiler.js +13 -8
- package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
- package/dist/prompts/sandbox/dna-methylation-agent.js +2 -7
- package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
- package/dist/prompts/sandbox/drug-repurposing-agent.js +15 -16
- package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
- package/dist/prompts/sandbox/enrichment-agent.js +2 -9
- package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
- package/dist/prompts/sandbox/genomic-variant-agent.js +2 -6
- package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/immune-profiling-agent.js +3 -8
- package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/metabolomics-agent.js +1 -7
- package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
- package/dist/prompts/sandbox/microbiome-agent.js +2 -7
- package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.js +2 -8
- package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multimodal-sc-agent.js +2 -7
- package/dist/prompts/sandbox/network-agent.d.ts +1 -1
- package/dist/prompts/sandbox/network-agent.js +2 -7
- package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/proteomics-agent.js +2 -9
- package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
- package/dist/prompts/sandbox/single-cell-agent.js +2 -9
- package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/spatial-omics-agent.js +3 -6
- package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/statistical-modeling-agent.js +2 -7
- package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.js +13 -14
- package/dist/prompts/sandbox-standards.d.ts +22 -14
- package/dist/prompts/sandbox-standards.js +91 -71
- package/dist/prompts/synthesis-agent.d.ts +1 -1
- package/dist/prompts/synthesis-agent.js +33 -131
- package/dist/provenance/collector.js +1 -1
- package/dist/providers/ai-sdk.js +31 -4
- package/dist/providers/prompt-cache.d.ts +74 -0
- package/dist/providers/prompt-cache.js +77 -0
- package/dist/providers/types.d.ts +33 -0
- package/dist/reference-data/catalog.d.ts +131 -0
- package/dist/reference-data/catalog.js +348 -0
- package/dist/reference-data/receipt.d.ts +41 -0
- package/dist/reference-data/receipt.js +40 -0
- package/dist/runtime/boot.d.ts +2 -2
- package/dist/runtime/boot.js +1 -1
- package/dist/runtime/connection-budget.d.ts +2 -2
- package/dist/runtime/connection-budget.js +5 -3
- package/dist/runtime/dbos.d.ts +7 -7
- package/dist/runtime/dbos.js +14 -11
- package/dist/runtime/shutdown.d.ts +2 -2
- package/dist/runtime/shutdown.js +4 -3
- package/dist/sandbox/create-sandbox.d.ts +2 -2
- package/dist/sandbox/docker-client.d.ts +2 -2
- package/dist/sandbox/docker-client.js +4 -1
- package/dist/sandbox/k8s-client.d.ts +3 -0
- package/dist/sandbox/k8s-client.js +5 -4
- package/dist/sandbox/notification-sweep.d.ts +3 -3
- package/dist/sandbox/notification-sweep.js +4 -2
- package/dist/sandbox/reaper.d.ts +3 -3
- package/dist/sandbox/reaper.js +7 -4
- package/dist/sandbox/watchdog.d.ts +3 -3
- package/dist/sandbox/watchdog.js +8 -2
- package/dist/schemas/data-profile-schemas.js +5 -3
- package/dist/schemas/plan-schemas.d.ts +21 -21
- package/dist/schemas/plan-schemas.js +9 -3
- package/dist/schemas/run-synthesis.d.ts +8 -4
- package/dist/schemas/run-synthesis.js +92 -56
- package/dist/schemas/validate-plan.js +1 -1
- package/dist/schemas/workflow-state.d.ts +7 -1
- package/dist/schemas/workflow-state.js +33 -19
- package/dist/state/artifacts.d.ts +13 -0
- package/dist/state/artifacts.js +27 -0
- package/dist/state/data-profile.d.ts +64 -5
- package/dist/state/index.d.ts +3 -3
- package/dist/state/index.js +1 -1
- package/dist/state/init.d.ts +2 -1
- package/dist/state/init.js +5 -6
- package/dist/tasks/data-profile.d.ts +25 -2
- package/dist/tasks/data-profile.js +95 -39
- package/dist/tools/bio/chembl.d.ts +38 -0
- package/dist/tools/bio/chembl.js +138 -0
- package/dist/tools/bio/comptox.d.ts +50 -0
- package/dist/tools/bio/comptox.js +149 -0
- package/dist/tools/bio/get-impc-ko-profile.js +9 -6
- package/dist/tools/bio/index.d.ts +5 -17
- package/dist/tools/bio/index.js +5 -17
- package/dist/tools/bio/keys.d.ts +14 -9
- package/dist/tools/bio/keys.js +16 -16
- package/dist/tools/bio/opentargets.d.ts +38 -0
- package/dist/tools/bio/opentargets.js +89 -0
- package/dist/tools/bio/pubchem.d.ts +29 -0
- package/dist/tools/bio/pubchem.js +92 -0
- package/dist/tools/bio/pubmed.d.ts +51 -0
- package/dist/tools/bio/pubmed.js +100 -0
- package/dist/tools/bio/search-bgee-expression.js +12 -6
- package/dist/tools/bio/search-clinical-trials.js +16 -5
- package/dist/tools/bio/search-dgidb.d.ts +11 -1
- package/dist/tools/bio/search-dgidb.js +92 -78
- package/dist/tools/bio/search-faers.js +8 -4
- package/dist/tools/bio/search-geo-datasets.js +20 -6
- package/dist/tools/bio/search-gwas-catalog.d.ts +1 -1
- package/dist/tools/bio/search-pharmgkb.js +10 -4
- package/dist/tools/display/index.d.ts +1 -0
- package/dist/tools/display/index.js +1 -0
- package/dist/tools/display/normalize-echart-spec.d.ts +61 -0
- package/dist/tools/display/normalize-echart-spec.js +211 -0
- package/dist/tools/display/show-user.d.ts +6 -1
- package/dist/tools/display/show-user.js +25 -12
- package/dist/tools/execute-plan.js +5 -2
- package/dist/tools/iterate-report.d.ts +171 -118
- package/dist/tools/iterate-report.js +336 -96
- package/dist/tools/lib/chembl-client.d.ts +12 -0
- package/dist/tools/lib/chembl-client.js +127 -0
- package/dist/tools/lib/ctx-ops.d.ts +224 -0
- package/dist/tools/lib/ctx-ops.js +450 -0
- package/dist/tools/lib/iuphar-client.js +10 -1
- package/dist/tools/lib/openfda-client.js +11 -3
- package/dist/tools/lib/pathway-client.js +10 -4
- package/dist/tools/lib/pubchem-ops.d.ts +74 -0
- package/dist/tools/lib/pubchem-ops.js +224 -0
- package/dist/tools/memory/update-working-memory.d.ts +45 -7
- package/dist/tools/memory/update-working-memory.js +111 -41
- package/dist/tools/report/index.d.ts +3 -2
- package/dist/tools/report/index.js +3 -2
- package/dist/tools/research/generate-analogy-report.js +25 -12
- package/dist/tools/research/generate-plan.d.ts +12 -5
- package/dist/tools/research/generate-plan.js +168 -37
- package/dist/tools/research/index.d.ts +1 -0
- package/dist/tools/research/index.js +1 -0
- package/dist/tools/research/inspect-data-profile.d.ts +85 -0
- package/dist/tools/research/inspect-data-profile.js +161 -0
- package/dist/tools/research/literature-reviewer.d.ts +3 -0
- package/dist/tools/research/literature-reviewer.js +5 -6
- package/dist/tools/sandbox/list-available-packages.d.ts +79 -5
- package/dist/tools/sandbox/list-available-packages.js +152 -10
- package/dist/tools/sandbox/list-available-refs.d.ts +141 -5
- package/dist/tools/sandbox/list-available-refs.js +647 -134
- package/dist/tools/sandbox/report-blocker.d.ts +39 -9
- package/dist/tools/sandbox/report-blocker.js +43 -20
- package/dist/tools/workspace/execute-command.d.ts +3 -0
- package/dist/tools/workspace/execute-command.js +3 -1
- package/dist/tools/workspace/read-file.js +4 -5
- package/dist/tools/workspace/run-exec.d.ts +4 -4
- package/dist/tools/workspace/run-exec.js +4 -4
- package/dist/tools/workspace/show-file.js +10 -6
- package/dist/tools/workspace/show-plan.js +12 -6
- package/dist/tools/workspace/workspace-search.d.ts +1 -1
- package/dist/tools/workspace/workspace-search.js +11 -5
- package/dist/workflows/execute-analysis.d.ts +46 -4
- package/dist/workflows/execute-analysis.js +118 -13
- package/dist/workflows/execute-target-assessment.d.ts +3 -0
- package/dist/workflows/execute-target-assessment.js +19 -15
- package/dist/workflows/sandbox-step.d.ts +9 -0
- package/dist/workflows/sandbox-step.js +39 -17
- package/dist/workflows/target-assessment/lib/citation-validator.js +2 -2
- package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.js +2 -1
- package/dist/workflows/target-assessment/lib/llm-step.d.ts +3 -0
- package/dist/workflows/target-assessment/lib/llm-step.js +3 -1
- package/dist/workflows/target-assessment/lib/structured-llm.d.ts +3 -0
- package/dist/workflows/target-assessment/lib/structured-llm.js +1 -0
- package/dist/workflows/target-assessment/phase5-persist.d.ts +3 -0
- package/dist/workflows/target-assessment/phase5-persist.js +8 -3
- package/dist/workflows/target-assessment/progress.d.ts +2 -1
- package/dist/workflows/target-assessment/progress.js +4 -3
- package/dist/workspace/filesystem.js +163 -74
- package/dist/workspace/paths.d.ts +2 -2
- package/dist/workspace/paths.js +2 -2
- package/package.json +95 -96
- package/dist/execution/filesystem-artifact-registry.d.ts +0 -57
- package/dist/execution/filesystem-artifact-registry.js +0 -92
- package/dist/lib/identifiers.d.ts +0 -8
- package/dist/lib/identifiers.js +0 -10
- package/dist/lib/mime-detect.d.ts +0 -17
- package/dist/lib/mime-detect.js +0 -29
- package/dist/lib/streamed-download.d.ts +0 -28
- package/dist/lib/streamed-download.js +0 -111
- package/dist/lib/trace-context.d.ts +0 -11
- package/dist/lib/trace-context.js +0 -49
- package/dist/providers/llm-capabilities.d.ts +0 -33
- package/dist/providers/llm-capabilities.js +0 -58
- package/dist/schemas/render-step-prompt.d.ts +0 -32
- package/dist/schemas/render-step-prompt.js +0 -76
- package/dist/tools/bio/find-approval-precedent.d.ts +0 -32
- package/dist/tools/bio/find-approval-precedent.js +0 -72
- package/dist/tools/bio/get-article-details.d.ts +0 -11
- package/dist/tools/bio/get-article-details.js +0 -20
- package/dist/tools/bio/get-article-full-text.d.ts +0 -19
- package/dist/tools/bio/get-article-full-text.js +0 -32
- package/dist/tools/bio/get-bioactivity.d.ts +0 -11
- package/dist/tools/bio/get-bioactivity.js +0 -23
- package/dist/tools/bio/get-drug-info.d.ts +0 -9
- package/dist/tools/bio/get-drug-info.js +0 -22
- package/dist/tools/bio/get-mechanism.d.ts +0 -8
- package/dist/tools/bio/get-mechanism.js +0 -18
- package/dist/tools/bio/get-pubchem-assays.d.ts +0 -22
- package/dist/tools/bio/get-pubchem-assays.js +0 -107
- package/dist/tools/bio/get-pubchem-cross-refs.d.ts +0 -15
- package/dist/tools/bio/get-pubchem-cross-refs.js +0 -68
- package/dist/tools/bio/get-target-safety.d.ts +0 -18
- package/dist/tools/bio/get-target-safety.js +0 -26
- package/dist/tools/bio/search-compounds.d.ts +0 -22
- package/dist/tools/bio/search-compounds.js +0 -160
- package/dist/tools/bio/search-ctx-chemical.d.ts +0 -50
- package/dist/tools/bio/search-ctx-chemical.js +0 -130
- package/dist/tools/bio/search-ctx-exposure.d.ts +0 -55
- package/dist/tools/bio/search-ctx-exposure.js +0 -176
- package/dist/tools/bio/search-ctx-hazard.d.ts +0 -111
- package/dist/tools/bio/search-ctx-hazard.js +0 -178
- package/dist/tools/bio/search-opentargets.d.ts +0 -11
- package/dist/tools/bio/search-opentargets.js +0 -25
- package/dist/tools/bio/search-pubchem-compound.d.ts +0 -26
- package/dist/tools/bio/search-pubchem-compound.js +0 -110
- package/dist/tools/bio/search-pubmed.d.ts +0 -17
- package/dist/tools/bio/search-pubmed.js +0 -31
- package/dist/tools/bio/search-targets.d.ts +0 -9
- package/dist/tools/bio/search-targets.js +0 -20
- package/dist/tools/bio/search-toxcast.d.ts +0 -36
- package/dist/tools/bio/search-toxcast.js +0 -141
- package/dist/workflows/register-workflows.d.ts +0 -51
- package/dist/workflows/register-workflows.js +0 -48
- package/dist/workflows/resume-execute-analysis.d.ts +0 -70
- package/dist/workflows/resume-execute-analysis.js +0 -80
- package/dist/workflows/target-assessment/correction-loop.d.ts +0 -45
- package/dist/workflows/target-assessment/correction-loop.js +0 -62
- package/dist/workflows/target-assessment/steps/phase0-resolve.d.ts +0 -71
- package/dist/workflows/target-assessment/steps/phase0-resolve.js +0 -21
- package/dist/workflows/target-assessment/steps/phase1-aggregate.d.ts +0 -1018
- package/dist/workflows/target-assessment/steps/phase1-aggregate.js +0 -25
- package/dist/workspace/mount-strategy.d.ts +0 -50
- package/dist/workspace/mount-strategy.js +0 -67
- package/dist/workspace/provenance-collector.d.ts +0 -34
- package/dist/workspace/provenance-collector.js +0 -16
- package/dist/workspace/workspace-paths.d.ts +0 -26
- package/dist/workspace/workspace-paths.js +0 -31
|
@@ -156,6 +156,7 @@ export declare const DagStatePartSchema: z.ZodObject<{
|
|
|
156
156
|
}, z.core.$strict>;
|
|
157
157
|
export declare const StepPhaseSchema: z.ZodEnum<{
|
|
158
158
|
failed: "failed";
|
|
159
|
+
warning: "warning";
|
|
159
160
|
"sandbox-init": "sandbox-init";
|
|
160
161
|
executing: "executing";
|
|
161
162
|
"generating-metadata": "generating-metadata";
|
|
@@ -164,7 +165,6 @@ export declare const StepPhaseSchema: z.ZodEnum<{
|
|
|
164
165
|
persisting: "persisting";
|
|
165
166
|
complete: "complete";
|
|
166
167
|
retrying: "retrying";
|
|
167
|
-
warning: "warning";
|
|
168
168
|
}>;
|
|
169
169
|
export declare const StepActivityPartSchema: z.ZodObject<{
|
|
170
170
|
type: z.ZodLiteral<"data-step-activity">;
|
|
@@ -173,6 +173,7 @@ export declare const StepActivityPartSchema: z.ZodObject<{
|
|
|
173
173
|
stepId: z.ZodString;
|
|
174
174
|
phase: z.ZodEnum<{
|
|
175
175
|
failed: "failed";
|
|
176
|
+
warning: "warning";
|
|
176
177
|
"sandbox-init": "sandbox-init";
|
|
177
178
|
executing: "executing";
|
|
178
179
|
"generating-metadata": "generating-metadata";
|
|
@@ -181,7 +182,6 @@ export declare const StepActivityPartSchema: z.ZodObject<{
|
|
|
181
182
|
persisting: "persisting";
|
|
182
183
|
complete: "complete";
|
|
183
184
|
retrying: "retrying";
|
|
184
|
-
warning: "warning";
|
|
185
185
|
}>;
|
|
186
186
|
activity: z.ZodString;
|
|
187
187
|
}, z.core.$strip>;
|
|
@@ -212,11 +212,11 @@ export declare const StepOutputFileSchema: z.ZodObject<{
|
|
|
212
212
|
size: z.ZodNumber;
|
|
213
213
|
fileType: z.ZodEnum<{
|
|
214
214
|
output: "output";
|
|
215
|
+
summary: "summary";
|
|
215
216
|
script: "script";
|
|
216
217
|
figure: "figure";
|
|
217
218
|
log: "log";
|
|
218
219
|
notebook: "notebook";
|
|
219
|
-
summary: "summary";
|
|
220
220
|
}>;
|
|
221
221
|
description: z.ZodString;
|
|
222
222
|
}, z.core.$strip>;
|
|
@@ -231,11 +231,11 @@ export declare const StepOutputPartSchema: z.ZodObject<{
|
|
|
231
231
|
size: z.ZodNumber;
|
|
232
232
|
fileType: z.ZodEnum<{
|
|
233
233
|
output: "output";
|
|
234
|
+
summary: "summary";
|
|
234
235
|
script: "script";
|
|
235
236
|
figure: "figure";
|
|
236
237
|
log: "log";
|
|
237
238
|
notebook: "notebook";
|
|
238
|
-
summary: "summary";
|
|
239
239
|
}>;
|
|
240
240
|
description: z.ZodString;
|
|
241
241
|
}, z.core.$strip>>;
|
|
@@ -298,11 +298,11 @@ export declare const SynthesizedFindingSchema: z.ZodObject<{
|
|
|
298
298
|
low: "low";
|
|
299
299
|
}>;
|
|
300
300
|
noveltyStatus: z.ZodEnum<{
|
|
301
|
-
expected: "expected";
|
|
302
301
|
novel: "novel";
|
|
303
302
|
confirmed: "confirmed";
|
|
304
303
|
partially_confirmed: "partially_confirmed";
|
|
305
304
|
contradicted: "contradicted";
|
|
305
|
+
expected: "expected";
|
|
306
306
|
}>;
|
|
307
307
|
literatureInterpretation: z.ZodString;
|
|
308
308
|
}, z.core.$strip>;
|
|
@@ -330,11 +330,11 @@ export declare const RunSynthesisPartSchema: z.ZodObject<{
|
|
|
330
330
|
low: "low";
|
|
331
331
|
}>;
|
|
332
332
|
noveltyStatus: z.ZodEnum<{
|
|
333
|
-
expected: "expected";
|
|
334
333
|
novel: "novel";
|
|
335
334
|
confirmed: "confirmed";
|
|
336
335
|
partially_confirmed: "partially_confirmed";
|
|
337
336
|
contradicted: "contradicted";
|
|
337
|
+
expected: "expected";
|
|
338
338
|
}>;
|
|
339
339
|
literatureInterpretation: z.ZodString;
|
|
340
340
|
}, z.core.$strip>>;
|
|
@@ -512,6 +512,7 @@ export declare const CortexChatPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
512
512
|
stepId: z.ZodString;
|
|
513
513
|
phase: z.ZodEnum<{
|
|
514
514
|
failed: "failed";
|
|
515
|
+
warning: "warning";
|
|
515
516
|
"sandbox-init": "sandbox-init";
|
|
516
517
|
executing: "executing";
|
|
517
518
|
"generating-metadata": "generating-metadata";
|
|
@@ -520,7 +521,6 @@ export declare const CortexChatPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
520
521
|
persisting: "persisting";
|
|
521
522
|
complete: "complete";
|
|
522
523
|
retrying: "retrying";
|
|
523
|
-
warning: "warning";
|
|
524
524
|
}>;
|
|
525
525
|
activity: z.ZodString;
|
|
526
526
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -547,11 +547,11 @@ export declare const CortexChatPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
547
547
|
size: z.ZodNumber;
|
|
548
548
|
fileType: z.ZodEnum<{
|
|
549
549
|
output: "output";
|
|
550
|
+
summary: "summary";
|
|
550
551
|
script: "script";
|
|
551
552
|
figure: "figure";
|
|
552
553
|
log: "log";
|
|
553
554
|
notebook: "notebook";
|
|
554
|
-
summary: "summary";
|
|
555
555
|
}>;
|
|
556
556
|
description: z.ZodString;
|
|
557
557
|
}, z.core.$strip>>;
|
|
@@ -589,11 +589,11 @@ export declare const CortexChatPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
589
589
|
low: "low";
|
|
590
590
|
}>;
|
|
591
591
|
noveltyStatus: z.ZodEnum<{
|
|
592
|
-
expected: "expected";
|
|
593
592
|
novel: "novel";
|
|
594
593
|
confirmed: "confirmed";
|
|
595
594
|
partially_confirmed: "partially_confirmed";
|
|
596
595
|
contradicted: "contradicted";
|
|
596
|
+
expected: "expected";
|
|
597
597
|
}>;
|
|
598
598
|
literatureInterpretation: z.ZodString;
|
|
599
599
|
}, z.core.$strip>>;
|
|
@@ -24,6 +24,7 @@ import type { AgentSession } from "../auth/types.js";
|
|
|
24
24
|
import type { LoopMessage } from "../loop/types.js";
|
|
25
25
|
import type { AgentChat } from "../providers/types.js";
|
|
26
26
|
import type { WorkspaceFilesystem } from "../workspace/filesystem.js";
|
|
27
|
+
import type { Logger } from "../lib/logger.js";
|
|
27
28
|
export interface ArtifactForMetadata {
|
|
28
29
|
/** Path used to update `cortex_artifacts` after metadata generation. */
|
|
29
30
|
readonly dbPath: string;
|
|
@@ -33,6 +34,8 @@ export interface ArtifactForMetadata {
|
|
|
33
34
|
readonly sizeBytes?: number;
|
|
34
35
|
}
|
|
35
36
|
export interface GenerateFileMetadataOptions {
|
|
37
|
+
/** Operational logging seam; omitted falls back to no-op. */
|
|
38
|
+
readonly logger?: Logger;
|
|
36
39
|
readonly provider: AgentChat;
|
|
37
40
|
readonly session: AgentSession;
|
|
38
41
|
readonly artifacts: readonly ArtifactForMetadata[];
|
|
@@ -26,8 +26,10 @@ import { runAgent } from "../loop/run-agent.js";
|
|
|
26
26
|
import { passthroughStep } from "../loop/run-step.js";
|
|
27
27
|
import { defineTool } from "../tools/define-tool.js";
|
|
28
28
|
import { createReadFileTool } from "../tools/workspace/read-file.js";
|
|
29
|
+
import { composeSystemPrompt } from "../agents/system-prompt.js";
|
|
29
30
|
import { inferArtifactType } from "../schemas/artifact-manifest.js";
|
|
30
31
|
import { SubmitFileMetadataInputSchema } from "../schemas/file-metadata.js";
|
|
32
|
+
import { createNoopLogger } from "../lib/console-logger.js";
|
|
31
33
|
/** Sub-agent identity for the describer loop — provenance only. */
|
|
32
34
|
const DESCRIBER_AGENT_ID = "file-metadata-describer";
|
|
33
35
|
/**
|
|
@@ -155,6 +157,7 @@ function fallbackEntry(artifact, extra) {
|
|
|
155
157
|
* result always carries exactly one entry per input artifact.
|
|
156
158
|
*/
|
|
157
159
|
export async function generateFileMetadata(opts) {
|
|
160
|
+
const logger = (opts.logger ?? createNoopLogger()).named("artifact-metadata").with({ resourceId: opts.resourceId });
|
|
158
161
|
if (opts.artifacts.length === 0) {
|
|
159
162
|
return { indexed: 0, entries: [] };
|
|
160
163
|
}
|
|
@@ -166,7 +169,7 @@ export async function generateFileMetadata(opts) {
|
|
|
166
169
|
}
|
|
167
170
|
const describer = {
|
|
168
171
|
id: DESCRIBER_AGENT_ID,
|
|
169
|
-
systemPrompt: SYSTEM_PROMPT,
|
|
172
|
+
systemPrompt: composeSystemPrompt(SYSTEM_PROMPT),
|
|
170
173
|
model: opts.modelId,
|
|
171
174
|
tools,
|
|
172
175
|
maxIterations: opts.maxIterations ?? DEFAULT_MAX_ITERATIONS,
|
|
@@ -182,7 +185,7 @@ export async function generateFileMetadata(opts) {
|
|
|
182
185
|
});
|
|
183
186
|
}
|
|
184
187
|
catch (err) {
|
|
185
|
-
|
|
188
|
+
logger.warn("describer loop failed; using fallbacks", logger.errorFields(err));
|
|
186
189
|
}
|
|
187
190
|
const entries = [];
|
|
188
191
|
const fallbackPaths = [];
|
|
@@ -197,7 +200,11 @@ export async function generateFileMetadata(opts) {
|
|
|
197
200
|
}
|
|
198
201
|
}
|
|
199
202
|
if (fallbackPaths.length > 0) {
|
|
200
|
-
|
|
203
|
+
logger.warn("file(s) used a deterministic fallback description", {
|
|
204
|
+
fallbackCount: fallbackPaths.length,
|
|
205
|
+
artifactCount: opts.artifacts.length,
|
|
206
|
+
fallbackPaths,
|
|
207
|
+
});
|
|
201
208
|
}
|
|
202
209
|
return { indexed: holder.size, entries };
|
|
203
210
|
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import type { Pool, PoolClient } from "pg";
|
|
13
13
|
import type { AgentSession } from "../auth/types.js";
|
|
14
|
+
import type { Logger } from "../lib/logger.js";
|
|
14
15
|
import type { ArtifactRegistry, ArtifactRegistrationInput } from "./artifact-registry.js";
|
|
15
16
|
export type { ArtifactRegistrationInput };
|
|
16
17
|
export interface ArtifactRegistrationResult {
|
|
@@ -33,4 +34,4 @@ export interface ArtifactRegistrationResult {
|
|
|
33
34
|
* delegates external provenance registration to the injected `ArtifactRegistry`
|
|
34
35
|
* and applies any returned external ids back onto the local rows.
|
|
35
36
|
*/
|
|
36
|
-
export declare function registerStepArtifacts(db: Pool | PoolClient, registry: ArtifactRegistry, input: ArtifactRegistrationInput, session: AgentSession): Promise<ArtifactRegistrationResult>;
|
|
37
|
+
export declare function registerStepArtifacts(db: Pool | PoolClient, registry: ArtifactRegistry, input: ArtifactRegistrationInput, session: AgentSession, logger?: Logger): Promise<ArtifactRegistrationResult>;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* (an external provenance ledger, or a filesystem index) is a composition-root
|
|
10
10
|
* decision — this module never names one.
|
|
11
11
|
*/
|
|
12
|
+
import { createNoopLogger } from "../lib/console-logger.js";
|
|
12
13
|
import { upsertArtifacts, updateArtifactId } from "../state/index.js";
|
|
13
14
|
// ── Registration ─────────────────────────────────────────────────────
|
|
14
15
|
/**
|
|
@@ -18,8 +19,13 @@ import { upsertArtifacts, updateArtifactId } from "../state/index.js";
|
|
|
18
19
|
* delegates external provenance registration to the injected `ArtifactRegistry`
|
|
19
20
|
* and applies any returned external ids back onto the local rows.
|
|
20
21
|
*/
|
|
21
|
-
export async function registerStepArtifacts(db, registry, input, session
|
|
22
|
+
export async function registerStepArtifacts(db, registry, input, session,
|
|
23
|
+
// A parameter rather than a field on `ArtifactRegistrationInput`: that type is
|
|
24
|
+
// the seam's payload, handed verbatim to `registry.register`, and an
|
|
25
|
+
// embedder's registry has no business receiving the host's logger.
|
|
26
|
+
logger = createNoopLogger()) {
|
|
22
27
|
const { resourceId, runId, stepId, artifacts } = input;
|
|
28
|
+
const log = logger.named("artifact-registration").with({ runId, stepId });
|
|
23
29
|
if (artifacts.length === 0) {
|
|
24
30
|
return { localCount: 0, externalRegistered: 0, externalFailed: 0, failureDetails: [] };
|
|
25
31
|
}
|
|
@@ -27,7 +33,7 @@ export async function registerStepArtifacts(db, registry, input, session) {
|
|
|
27
33
|
const emptyHash = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
|
28
34
|
const localEntries = artifacts.map((a) => {
|
|
29
35
|
if (a.size === 0 || a.hash === emptyHash) {
|
|
30
|
-
|
|
36
|
+
log.warn("empty artifact", { path: `${dbPathPrefix}${a.path}`, hash: a.hash?.slice(0, 16), size: a.size });
|
|
31
37
|
}
|
|
32
38
|
return {
|
|
33
39
|
resourceId,
|
|
@@ -29,12 +29,15 @@ import type { SandboxClient } from "../sandbox/client.js";
|
|
|
29
29
|
import type { BioToolKeys } from "../tools/bio/keys.js";
|
|
30
30
|
import type { WorkspaceFilesystem } from "../workspace/filesystem.js";
|
|
31
31
|
import type { ResolveWorkspaceRoot } from "../workspace/paths.js";
|
|
32
|
+
import type { Logger } from "../lib/logger.js";
|
|
32
33
|
/** Sub-agent identity — appended to `callPath`, set as `agentId`. */
|
|
33
34
|
export declare const EPHEMERAL_AGENT_ID = "ephemeral-executor";
|
|
34
35
|
/** Workflow-id prefix — the boot-time never-recover sweep matches on it. */
|
|
35
36
|
export declare const EPHEMERAL_WORKFLOW_PREFIX: "ephemeral:";
|
|
36
37
|
/** The body's construction-time deps — closed over at registration. */
|
|
37
38
|
export interface EphemeralDeps {
|
|
39
|
+
/** Operational logging seam; omitted falls back to no-op. */
|
|
40
|
+
readonly logger?: Logger;
|
|
38
41
|
readonly provider: ChatProvider;
|
|
39
42
|
readonly pool: Pool;
|
|
40
43
|
readonly sandboxClient: SandboxClient;
|
|
@@ -72,6 +75,19 @@ export interface EphemeralResult {
|
|
|
72
75
|
* so the `run_ephemeral` tool can dispatch via `DBOS.startWorkflow`.
|
|
73
76
|
*/
|
|
74
77
|
export declare function registerEphemeralWorkflow(deps: EphemeralDeps): (input: EphemeralWorkflowInput) => Promise<EphemeralResult>;
|
|
78
|
+
/**
|
|
79
|
+
* The executor's seed: its workspace frame, then the caller's ask.
|
|
80
|
+
*
|
|
81
|
+
* An ephemeral run is not scheduled by `executeAnalysis`, so no step briefing is
|
|
82
|
+
* composed for it — and the sandbox system prompt names no paths (it is static
|
|
83
|
+
* per agent type, so the provider's prompt cache can reuse it). The analysis
|
|
84
|
+
* root would otherwise reach the agent nowhere: `run_ephemeral`'s `prompt` is
|
|
85
|
+
* free text authored by the conversation agent.
|
|
86
|
+
*
|
|
87
|
+
* The frame differs from a step's, so this does not reuse `renderWorkspace`:
|
|
88
|
+
* there is no writable directory to name. The read-only tree IS the cwd.
|
|
89
|
+
*/
|
|
90
|
+
export declare function ephemeralSeed(analysisId: string, prompt: string): string;
|
|
75
91
|
/**
|
|
76
92
|
* Run the ephemeral-executor agent against a fresh read-only sandbox.
|
|
77
93
|
* Throws on sandbox start failure; otherwise returns the agent's final
|
|
@@ -28,6 +28,7 @@ import { durableStep } from "../loop/run-step.js";
|
|
|
28
28
|
import { generateExecutionId } from "../sandbox/execution-id.js";
|
|
29
29
|
import { mintSandboxIdentity } from "../sandbox/identity.js";
|
|
30
30
|
import { createEphemeralExecutorAgent } from "../agents/sandbox/ephemeral-executor.js";
|
|
31
|
+
import { createNoopLogger } from "../lib/console-logger.js";
|
|
31
32
|
/** Sub-agent identity — appended to `callPath`, set as `agentId`. */
|
|
32
33
|
export const EPHEMERAL_AGENT_ID = "ephemeral-executor";
|
|
33
34
|
/**
|
|
@@ -51,6 +52,28 @@ const EPHEMERAL_SANDBOX_RESOURCES = { cpu: 4, memoryGb: 8 };
|
|
|
51
52
|
export function registerEphemeralWorkflow(deps) {
|
|
52
53
|
return DBOS.registerWorkflow((input) => runEphemeralBody(input, deps), { name: "ephemeral" });
|
|
53
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* The executor's seed: its workspace frame, then the caller's ask.
|
|
57
|
+
*
|
|
58
|
+
* An ephemeral run is not scheduled by `executeAnalysis`, so no step briefing is
|
|
59
|
+
* composed for it — and the sandbox system prompt names no paths (it is static
|
|
60
|
+
* per agent type, so the provider's prompt cache can reuse it). The analysis
|
|
61
|
+
* root would otherwise reach the agent nowhere: `run_ephemeral`'s `prompt` is
|
|
62
|
+
* free text authored by the conversation agent.
|
|
63
|
+
*
|
|
64
|
+
* The frame differs from a step's, so this does not reuse `renderWorkspace`:
|
|
65
|
+
* there is no writable directory to name. The read-only tree IS the cwd.
|
|
66
|
+
*/
|
|
67
|
+
export function ephemeralSeed(analysisId, prompt) {
|
|
68
|
+
const root = `/${analysisId}`;
|
|
69
|
+
return [
|
|
70
|
+
"## Workspace",
|
|
71
|
+
`- Analysis root (read-only): \`${root}\` — inputs at \`${root}/data/inputs/\`, prior runs at \`${root}/runs/\`.`,
|
|
72
|
+
`- The analysis root is also your cwd, and what relative paths resolve against. The sandbox is read-only: there is nowhere to write, so return every result inline.`,
|
|
73
|
+
"",
|
|
74
|
+
prompt,
|
|
75
|
+
].join("\n");
|
|
76
|
+
}
|
|
54
77
|
/**
|
|
55
78
|
* Run the ephemeral-executor agent against a fresh read-only sandbox.
|
|
56
79
|
* Throws on sandbox start failure; otherwise returns the agent's final
|
|
@@ -63,13 +86,16 @@ export async function runEphemeralBody(input, deps) {
|
|
|
63
86
|
throw new Error(`runEphemeralBody requires an analysis-scoped session — got ${runSession.scope.kind}`);
|
|
64
87
|
}
|
|
65
88
|
const analysisId = runSession.scope.analysisId;
|
|
89
|
+
// Bound after the scope guard: `analysisId` comes off the session's scope,
|
|
90
|
+
// not the workflow input.
|
|
91
|
+
const logger = (deps.logger ?? createNoopLogger()).named("ephemeral").with({ analysisId });
|
|
66
92
|
const startedAt = performance.now();
|
|
67
93
|
const executionId = generateExecutionId(EPHEMERAL_AGENT_ID);
|
|
68
94
|
const workflowId = DBOS.workflowID ?? `${EPHEMERAL_WORKFLOW_PREFIX}${executionId}`;
|
|
69
95
|
const childSession = forSubAgent(runSession, EPHEMERAL_AGENT_ID);
|
|
70
96
|
// Resolver throw = loud workflow failure, per the workspace-root-resolution contract.
|
|
71
97
|
const workspaceRoot = deps.resolveWorkspaceRoot(analysisId);
|
|
72
|
-
|
|
98
|
+
logger.info("starting sandbox", { executionId });
|
|
73
99
|
const sandbox = await deps.sandboxClient.createSandbox({
|
|
74
100
|
runId: EPHEMERAL_RUN_LITERAL,
|
|
75
101
|
stepId: EPHEMERAL_RUN_LITERAL,
|
|
@@ -116,7 +142,7 @@ export async function runEphemeralBody(input, deps) {
|
|
|
116
142
|
const agentDef = createEphemeralExecutorAgent(sandboxAgentDeps);
|
|
117
143
|
const agent = input.maxIterations !== undefined ? { ...agentDef, maxIterations: input.maxIterations } : agentDef;
|
|
118
144
|
const signal = new AbortController().signal;
|
|
119
|
-
const { messages: finalMessages } = await runAgent(agent, [{ role: "user", content: input.prompt }], childSession, {
|
|
145
|
+
const { messages: finalMessages } = await runAgent(agent, [{ role: "user", content: ephemeralSeed(analysisId, input.prompt) }], childSession, {
|
|
120
146
|
provider: deps.provider,
|
|
121
147
|
signal,
|
|
122
148
|
emit: () => { },
|
|
@@ -126,12 +152,12 @@ export async function runEphemeralBody(input, deps) {
|
|
|
126
152
|
const text = finalText(finalMessages);
|
|
127
153
|
const stepsUsed = countAssistantTurns(finalMessages);
|
|
128
154
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
129
|
-
|
|
155
|
+
logger.info("completed", { executionId, stepsUsed, durationMs });
|
|
130
156
|
return { text, stepsUsed, durationMs };
|
|
131
157
|
}
|
|
132
158
|
catch (err) {
|
|
133
159
|
const message = err instanceof Error ? err.message : String(err);
|
|
134
|
-
|
|
160
|
+
logger.error("failed", { executionId, err: message });
|
|
135
161
|
throw err;
|
|
136
162
|
}
|
|
137
163
|
finally {
|
|
@@ -141,7 +167,7 @@ export async function runEphemeralBody(input, deps) {
|
|
|
141
167
|
catch (teardownErr) {
|
|
142
168
|
// Teardown is idempotent — "already gone" is success. A failure here
|
|
143
169
|
// is best-effort logged so the chat turn doesn't fail on cleanup.
|
|
144
|
-
|
|
170
|
+
logger.warn("teardown failed (non-fatal)", { executionId, ...logger.errorFields(teardownErr) });
|
|
145
171
|
}
|
|
146
172
|
}
|
|
147
173
|
}
|
|
@@ -16,6 +16,7 @@ import type { WorkspaceFilesystem } from "../workspace/filesystem.js";
|
|
|
16
16
|
import type { ResolveWorkspaceRoot } from "../workspace/paths.js";
|
|
17
17
|
import type { ArtifactManifestEntry } from "../schemas/artifact-manifest.js";
|
|
18
18
|
import type { StepSummary } from "../schemas/step-summary.js";
|
|
19
|
+
import type { Logger } from "../lib/logger.js";
|
|
19
20
|
import type { ArtifactRegistry } from "./artifact-registry.js";
|
|
20
21
|
import { type FileMetadataEntry } from "./artifact-metadata.js";
|
|
21
22
|
import type { PostStepArtifacts, PostStepContext, StepOutputs } from "../workflows/sandbox-step.js";
|
|
@@ -25,6 +26,8 @@ import type { PostStepArtifacts, PostStepContext, StepOutputs } from "../workflo
|
|
|
25
26
|
*/
|
|
26
27
|
export interface PostStepPipelineDeps {
|
|
27
28
|
readonly pool: Pool;
|
|
29
|
+
/** Operational logging seam; omitted falls back to no-op. */
|
|
30
|
+
readonly logger?: Logger;
|
|
28
31
|
/** Non-streaming chat — the metadata + summary sub-agent loops. */
|
|
29
32
|
readonly provider: AgentChat;
|
|
30
33
|
/** Write-side embedder for the vector index. */
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
import { unwrapOrThrow } from "../lib/result.js";
|
|
15
|
+
import { createNoopLogger } from "../lib/console-logger.js";
|
|
15
16
|
import { writeFileWithinRoot } from "../lib/fs-helpers.js";
|
|
16
17
|
import { registerStepArtifacts } from "./artifact-registration.js";
|
|
17
18
|
import { reconcileManifestWithDisk } from "./reconcile-manifest.js";
|
|
@@ -79,7 +80,12 @@ export async function generateStepSummaryAndWrite(deps, postCtx, manifest) {
|
|
|
79
80
|
await writeFileWithinRoot(writePrefix, join(writePrefix, "output", "summary.md"), summary.markdown);
|
|
80
81
|
}
|
|
81
82
|
catch (err) {
|
|
82
|
-
|
|
83
|
+
const logger = (deps.logger ?? createNoopLogger()).named("post-step").named("summary");
|
|
84
|
+
logger.warn("writeFile output/summary.md failed", {
|
|
85
|
+
runId: input.runId,
|
|
86
|
+
stepId: input.stepId,
|
|
87
|
+
...logger.errorFields(err),
|
|
88
|
+
});
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
return summary;
|
|
@@ -102,6 +108,7 @@ export async function reconcileAndRegisterStepArtifacts(deps, postCtx, manifest)
|
|
|
102
108
|
agentId: input.agentId,
|
|
103
109
|
manifest: [...manifest],
|
|
104
110
|
collector: lineageCollector,
|
|
111
|
+
...(deps.logger ? { logger: deps.logger } : {}),
|
|
105
112
|
});
|
|
106
113
|
if (reconciled.manifest.length === 0)
|
|
107
114
|
return reconciled.manifest;
|
|
@@ -111,7 +118,7 @@ export async function reconcileAndRegisterStepArtifacts(deps, postCtx, manifest)
|
|
|
111
118
|
stepId: input.stepId,
|
|
112
119
|
artifacts: reconciled.manifest,
|
|
113
120
|
collector: lineageCollector,
|
|
114
|
-
}, session);
|
|
121
|
+
}, session, deps.logger);
|
|
115
122
|
if (reg.externalFailed > 0) {
|
|
116
123
|
const wholeActivityFailed = reg.externalRegistered === 0;
|
|
117
124
|
const detail = reg.failureDetails.map((f) => `${f.path}: ${f.error}`).join("\n ");
|
|
@@ -119,7 +126,19 @@ export async function reconcileAndRegisterStepArtifacts(deps, postCtx, manifest)
|
|
|
119
126
|
`${reg.externalFailed} row(s) rejected, ${reg.externalRegistered}/${reg.localCount} local artifact(s) registered` +
|
|
120
127
|
(wholeActivityFailed ? " (WHOLE ACTIVITY ROLLED BACK — outputs orphaned)" : "") +
|
|
121
128
|
(detail ? `\n ${detail}` : "");
|
|
122
|
-
|
|
129
|
+
// Logged as fields as well as thrown: the throw reaches `failStep` as one
|
|
130
|
+
// opaque string, so the per-path rejections are only queryable from here.
|
|
131
|
+
// This is what distinguishes a registry rejection from the attestation
|
|
132
|
+
// throws in `reconcileManifestWithDisk` when a step dies.
|
|
133
|
+
(deps.logger ?? createNoopLogger()).named("post-step").named("reconcile").error("external registration failed", {
|
|
134
|
+
runId: input.runId,
|
|
135
|
+
stepId: input.stepId,
|
|
136
|
+
externalFailed: reg.externalFailed,
|
|
137
|
+
externalRegistered: reg.externalRegistered,
|
|
138
|
+
localCount: reg.localCount,
|
|
139
|
+
wholeActivityFailed,
|
|
140
|
+
failures: reg.failureDetails,
|
|
141
|
+
});
|
|
123
142
|
throw new Error(msg);
|
|
124
143
|
}
|
|
125
144
|
return reconciled.manifest;
|
|
@@ -176,7 +195,8 @@ export async function vectorIndexStepOutputs(deps, postCtx, artifacts) {
|
|
|
176
195
|
}
|
|
177
196
|
}
|
|
178
197
|
catch (err) {
|
|
179
|
-
|
|
198
|
+
const logger = (deps.logger ?? createNoopLogger()).named("post-step").named("vector-index");
|
|
199
|
+
logger.warn("indexing failed", { runId: input.runId, stepId: input.stepId, ...logger.errorFields(err) });
|
|
180
200
|
}
|
|
181
201
|
}
|
|
182
202
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ArtifactManifestEntry } from "../schemas/artifact-manifest.js";
|
|
2
2
|
import type { ProvenanceCollector } from "../provenance/collector.js";
|
|
3
|
+
import type { Logger } from "../lib/logger.js";
|
|
3
4
|
export interface ReconcileManifestInput {
|
|
4
5
|
/** Absolute host root of the analysis's workspace tree. */
|
|
5
6
|
workspaceRoot: string;
|
|
@@ -15,6 +16,12 @@ export interface ReconcileManifestInput {
|
|
|
15
16
|
manifest: ArtifactManifestEntry[];
|
|
16
17
|
/** Collector backing the manifest; mutated to reflect drops/rehashes. */
|
|
17
18
|
collector: ProvenanceCollector;
|
|
19
|
+
/**
|
|
20
|
+
* Operational logging seam; omitted falls back to no-op. Attestation is
|
|
21
|
+
* fail-fast, so what this records — which entry was dropped, which input
|
|
22
|
+
* could not be hashed — is the account of why a step died.
|
|
23
|
+
*/
|
|
24
|
+
logger?: Logger;
|
|
18
25
|
}
|
|
19
26
|
export interface ReconcileManifestResult {
|
|
20
27
|
/** Reconciled manifest — phantoms removed, every entry rehashed from disk. */
|
|
@@ -21,10 +21,12 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { stat } from "node:fs/promises";
|
|
23
23
|
import path from "node:path";
|
|
24
|
+
import { createNoopLogger } from "../lib/console-logger.js";
|
|
24
25
|
import { computeSha256File, hasValidContentHash } from "../lib/fs-helpers.js";
|
|
25
26
|
import { artifactReconcileDropped } from "../lib/metrics.js";
|
|
26
27
|
export async function reconcileManifestWithDisk(input) {
|
|
27
28
|
const { workspaceRoot, resourceId, runId, stepId, agentId, manifest, collector } = input;
|
|
29
|
+
const logger = (input.logger ?? createNoopLogger()).named("reconcile-manifest").with({ runId, stepId, agentId });
|
|
28
30
|
const stepRoot = path.join(workspaceRoot, "runs", runId, stepId);
|
|
29
31
|
const reconciled = [];
|
|
30
32
|
let droppedCount = 0;
|
|
@@ -36,7 +38,7 @@ export async function reconcileManifestWithDisk(input) {
|
|
|
36
38
|
// ENOENT and silently drop a real artifact, or — worse — succeed
|
|
37
39
|
// against a host file the step never produced.
|
|
38
40
|
if (!absPath.startsWith(stepRoot + path.sep) && absPath !== stepRoot) {
|
|
39
|
-
|
|
41
|
+
logger.warn("skipping out-of-bounds entry", { path: entry.path });
|
|
40
42
|
continue;
|
|
41
43
|
}
|
|
42
44
|
let info;
|
|
@@ -45,7 +47,7 @@ export async function reconcileManifestWithDisk(input) {
|
|
|
45
47
|
}
|
|
46
48
|
catch (err) {
|
|
47
49
|
if (err.code === "ENOENT") {
|
|
48
|
-
|
|
50
|
+
logger.debug("dropping phantom entry", { path: entry.path });
|
|
49
51
|
collector.removeRecord(entry.path);
|
|
50
52
|
droppedCount++;
|
|
51
53
|
artifactReconcileDropped.add(1, { agent_id: agentId, step_id: stepId });
|
|
@@ -58,7 +60,7 @@ export async function reconcileManifestWithDisk(input) {
|
|
|
58
60
|
// uses `createReadStream`, which throws `EISDIR` on directories and would
|
|
59
61
|
// fail the whole step's reconciliation.
|
|
60
62
|
if (!info.isFile()) {
|
|
61
|
-
|
|
63
|
+
logger.debug("dropping non-file entry", { path: entry.path });
|
|
62
64
|
collector.removeRecord(entry.path);
|
|
63
65
|
droppedCount++;
|
|
64
66
|
artifactReconcileDropped.add(1, { agent_id: agentId, step_id: stepId });
|
|
@@ -72,7 +74,7 @@ export async function reconcileManifestWithDisk(input) {
|
|
|
72
74
|
const hash = await computeSha256File(absPath);
|
|
73
75
|
reconciled.push({ ...entry, hash, size: info.size });
|
|
74
76
|
}
|
|
75
|
-
await fillInputHashesFromDisk(collector, workspaceRoot, resourceId, runId, stepId);
|
|
77
|
+
await fillInputHashesFromDisk(collector, workspaceRoot, resourceId, runId, stepId, logger);
|
|
76
78
|
return { manifest: reconciled, droppedCount };
|
|
77
79
|
}
|
|
78
80
|
/**
|
|
@@ -88,22 +90,31 @@ export async function reconcileManifestWithDisk(input) {
|
|
|
88
90
|
* Lineage attestation is fail-fast: an input we cannot hash (gone, or resolving
|
|
89
91
|
* outside the analysis tree) throws rather than registering a hashless edge.
|
|
90
92
|
*/
|
|
91
|
-
async function fillInputHashesFromDisk(collector, workspaceRoot, resourceId, runId, stepId) {
|
|
93
|
+
async function fillInputHashesFromDisk(collector, workspaceRoot, resourceId, runId, stepId, logger) {
|
|
92
94
|
const resourceRoot = path.resolve(workspaceRoot);
|
|
93
95
|
for (const ref of collector.getTrackedInputs()) {
|
|
94
96
|
if (ref.source === "artifacts")
|
|
95
97
|
continue;
|
|
96
98
|
if (hasValidContentHash(ref.hash))
|
|
97
99
|
continue;
|
|
100
|
+
// Each throw below is logged before it is raised. The thrown message reaches
|
|
101
|
+
// `failStep` as one opaque string and everything downstream of that is
|
|
102
|
+
// scrubbed, so naming the site and the offending ref HERE is what makes a
|
|
103
|
+
// fail-fast attestation distinguishable from a registry rejection after the
|
|
104
|
+
// fact — the read's `source` in particular says whether the step declared
|
|
105
|
+
// this input at all.
|
|
106
|
+
const attestation = { path: ref.path, source: ref.source, refRunId: ref.runId, refStepId: ref.stepId };
|
|
98
107
|
// `ref.path` is the absolute container path `/{resourceId}/...`; strip the
|
|
99
108
|
// mount segment and map the tail onto the host workspace root. `path.join`
|
|
100
109
|
// normalizes any `..`, and the bound confines the read to the analysis tree.
|
|
101
110
|
const containerPrefix = `/${resourceId}`;
|
|
102
111
|
if (ref.path !== containerPrefix && !ref.path.startsWith(containerPrefix + "/")) {
|
|
112
|
+
logger.error("input read resolves outside the analysis tree", { ...attestation, throwSite: "container-prefix-bound" });
|
|
103
113
|
throw new Error(`[reconcile-manifest] input read resolves outside the analysis tree: path=${ref.path} stepId=${stepId} runId=${runId}`);
|
|
104
114
|
}
|
|
105
115
|
const hostPath = path.join(resourceRoot, ref.path.slice(containerPrefix.length + 1));
|
|
106
116
|
if (hostPath !== resourceRoot && !hostPath.startsWith(resourceRoot + path.sep)) {
|
|
117
|
+
logger.error("input read resolves outside the analysis tree", { ...attestation, hostPath, throwSite: "workspace-root-bound" });
|
|
107
118
|
throw new Error(`[reconcile-manifest] input read resolves outside the analysis tree: path=${ref.path} stepId=${stepId} runId=${runId}`);
|
|
108
119
|
}
|
|
109
120
|
let info;
|
|
@@ -112,10 +123,12 @@ async function fillInputHashesFromDisk(collector, workspaceRoot, resourceId, run
|
|
|
112
123
|
}
|
|
113
124
|
catch (err) {
|
|
114
125
|
if (err.code === "ENOENT") {
|
|
126
|
+
logger.error("cannot attest input — not present at reconcile", { ...attestation, hostPath, throwSite: "input-enoent" });
|
|
115
127
|
throw new Error(`[reconcile-manifest] cannot attest input ${ref.path}: not present at reconcile (stepId=${stepId} runId=${runId})`, {
|
|
116
128
|
cause: err,
|
|
117
129
|
});
|
|
118
130
|
}
|
|
131
|
+
logger.error("cannot attest input — stat failed", { ...attestation, hostPath, throwSite: "input-stat", ...logger.errorFields(err) });
|
|
119
132
|
throw err;
|
|
120
133
|
}
|
|
121
134
|
if (!info.isFile()) {
|
|
@@ -124,6 +137,7 @@ async function fillInputHashesFromDisk(collector, workspaceRoot, resourceId, run
|
|
|
124
137
|
// it from lineage rather than failing the step — mirrors the output-side
|
|
125
138
|
// non-file drop above. A genuinely missing FILE (ENOENT) still fails fast
|
|
126
139
|
// as drift; a directory is not drift.
|
|
140
|
+
logger.debug("dropping non-file input from lineage", attestation);
|
|
127
141
|
collector.dropInput(ref);
|
|
128
142
|
continue;
|
|
129
143
|
}
|
|
@@ -37,7 +37,10 @@ import type { EmitFn } from "../loop/types.js";
|
|
|
37
37
|
import type { ChatProvider } from "../providers/types.js";
|
|
38
38
|
import type { PreviewPublisher } from "../tools/report/preview-publisher.js";
|
|
39
39
|
import type { ChromeConfig } from "../lib/chrome.js";
|
|
40
|
+
import type { Logger } from "../lib/logger.js";
|
|
40
41
|
export interface ReportRunnerDeps {
|
|
42
|
+
/** Operational logging seam; omitted falls back to no-op. */
|
|
43
|
+
readonly logger?: Logger;
|
|
41
44
|
readonly provider: ChatProvider;
|
|
42
45
|
readonly pool: Pool;
|
|
43
46
|
/** Model id — provenance / metric label; provider owns the wire model. */
|
|
@@ -41,10 +41,12 @@ import { withPreviewLock } from "../tools/lib/preview-lock.js";
|
|
|
41
41
|
import { createBuildReportTool, createSubmitReportTool, createMintPreviewUrlTool, createPreviewSnapshotTool, createVersionFsTools, } from "../tools/report/index.js";
|
|
42
42
|
import { createReportBuilderAgent, REPORT_BUILDER_AGENT_ID } from "../agents/report-builder.js";
|
|
43
43
|
import { createSkillTools } from "../tools/sandbox/skills.js";
|
|
44
|
+
import { createNoopLogger } from "../lib/console-logger.js";
|
|
44
45
|
/** Skill pack the report-builder prompt directs the model to read (design-system reference). */
|
|
45
46
|
const REPORT_BUILDER_SKILLS = ["report-html"];
|
|
46
47
|
const REPORT_AGENT_MAX_STEPS = 75;
|
|
47
48
|
export async function runReportIteration(deps, opts) {
|
|
49
|
+
const logger = (deps.logger ?? createNoopLogger()).named("report-runner").with({ previewId: opts.previewId });
|
|
48
50
|
const startTime = performance.now();
|
|
49
51
|
return withPreviewLock(opts.previewId, async () => {
|
|
50
52
|
// ── Resolve version directories ───────────────────────────────
|
|
@@ -169,9 +171,7 @@ export async function runReportIteration(deps, opts) {
|
|
|
169
171
|
}
|
|
170
172
|
}
|
|
171
173
|
if (!outcome || agentError || phantomSuccess) {
|
|
172
|
-
|
|
173
|
-
`submitted=${outcome?.ok === true} phantom=${phantomSuccess} ` +
|
|
174
|
-
`agentError=${agentError ?? "null"}`);
|
|
174
|
+
logger.warn("report.agent.finish", { version: newVersion, submitted: outcome?.ok === true, phantom: phantomSuccess, agentError });
|
|
175
175
|
const { reason, errorKind } = classifyFailure({
|
|
176
176
|
phantomSuccess,
|
|
177
177
|
agentError,
|
|
@@ -182,7 +182,7 @@ export async function runReportIteration(deps, opts) {
|
|
|
182
182
|
await rm(versionDirAbs, { recursive: true, force: true });
|
|
183
183
|
}
|
|
184
184
|
catch (err) {
|
|
185
|
-
|
|
185
|
+
logger.error("rollback failed", { versionDirAbs, ...logger.errorFields(err) });
|
|
186
186
|
}
|
|
187
187
|
return failure(opts.previewId, newVersion, reason, errorKind, startTime);
|
|
188
188
|
}
|