@inflexa-ai/harness 0.39.2 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/dist/agents/conversation-agent.d.ts +3 -0
- package/dist/agents/conversation-agent.js +13 -2
- package/dist/agents/report-session-agent.d.ts +3 -0
- package/dist/agents/report-session-agent.js +2 -0
- package/dist/agents/sandbox/cheminformatics-agent.js +0 -3
- package/dist/agents/sandbox/shared.d.ts +11 -2
- package/dist/agents/sandbox/shared.js +4 -0
- package/dist/app/chat-turn.d.ts +75 -12
- package/dist/app/chat-turn.js +149 -21
- package/dist/app/message-assembly.d.ts +16 -52
- package/dist/app/message-assembly.js +41 -68
- package/dist/app/run-activity.d.ts +4 -6
- package/dist/app/run-activity.js +7 -27
- package/dist/app/spawn-report-session.d.ts +6 -11
- package/dist/app/spawn-report-session.js +5 -6
- package/dist/app/synthesize-run.d.ts +3 -0
- package/dist/app/synthesize-run.js +1 -0
- package/dist/billing/usage-recorder.d.ts +3 -4
- package/dist/billing/usage-recorder.js +3 -4
- package/dist/contracts/chat-parts.d.ts +11 -1
- package/dist/contracts/chat-parts.js +1 -0
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/part-registry.js +1 -0
- package/dist/contracts/report-blocks.d.ts +8 -8
- package/dist/contracts/schemas/chat-parts.d.ts +32 -9
- package/dist/contracts/schemas/chat-parts.js +10 -0
- package/dist/execution/artifact-metadata.d.ts +26 -33
- package/dist/execution/artifact-metadata.js +44 -106
- package/dist/execution/post-step-pipeline.d.ts +23 -16
- package/dist/execution/post-step-pipeline.js +19 -21
- package/dist/execution/run-synthesis.d.ts +3 -0
- package/dist/execution/run-synthesis.js +11 -1
- package/dist/execution/step-summary.d.ts +21 -30
- package/dist/execution/step-summary.js +30 -57
- package/dist/index.d.ts +9 -8
- package/dist/index.js +15 -34
- package/dist/lib/zod-issues.js +2 -4
- package/dist/loop/compaction.d.ts +20 -0
- package/dist/loop/compaction.js +2 -0
- package/dist/loop/continue-agent.d.ts +40 -0
- package/dist/loop/continue-agent.js +38 -0
- package/dist/loop/metrics.d.ts +30 -22
- package/dist/loop/metrics.js +51 -22
- package/dist/loop/run-agent.d.ts +111 -13
- package/dist/loop/run-agent.js +467 -220
- package/dist/loop/run-to-terminal.d.ts +16 -17
- package/dist/loop/run-to-terminal.js +24 -35
- package/dist/loop/tool-mask.d.ts +23 -0
- package/dist/loop/tool-mask.js +46 -0
- package/dist/loop/tool-output.d.ts +48 -0
- package/dist/loop/tool-output.js +79 -0
- package/dist/loop/types.d.ts +6 -3
- package/dist/memory/ai-sdk-message-storage.d.ts +49 -2
- package/dist/memory/ai-sdk-message-storage.js +78 -2
- package/dist/memory/conversation-display-recorder.d.ts +6 -0
- package/dist/memory/conversation-display-recorder.js +64 -22
- package/dist/memory/conversation-display-replay.d.ts +5 -14
- package/dist/memory/conversation-display-replay.js +66 -32
- package/dist/memory/conversation-display-storage.d.ts +2 -1
- package/dist/memory/conversation-display-storage.js +2 -1
- package/dist/memory/conversation-view.d.ts +53 -0
- package/dist/memory/conversation-view.js +130 -0
- package/dist/memory/count-tokens.d.ts +5 -7
- package/dist/memory/count-tokens.js +7 -9
- package/dist/memory/thread-history.d.ts +74 -102
- package/dist/memory/thread-history.js +181 -246
- package/dist/memory/thread-store.d.ts +3 -3
- package/dist/memory/thread-store.js +7 -2
- package/dist/memory/tool-call-integrity.d.ts +15 -21
- package/dist/memory/tool-call-integrity.js +31 -38
- package/dist/memory/working-memory.d.ts +2 -5
- package/dist/memory/working-memory.js +2 -5
- package/dist/prompts/SOUL.d.ts +2 -2
- package/dist/prompts/SOUL.js +2 -7
- package/dist/prompts/analogical-reasoner.d.ts +1 -1
- package/dist/prompts/analogical-reasoner.js +16 -32
- package/dist/prompts/briefing.js +1 -1
- package/dist/prompts/compaction.d.ts +4 -0
- package/dist/prompts/compaction.js +24 -0
- package/dist/prompts/conversation.d.ts +1 -1
- package/dist/prompts/conversation.js +26 -35
- package/dist/prompts/execute-analysis/step-summary.js +7 -5
- package/dist/prompts/literature-reviewer.d.ts +1 -1
- package/dist/prompts/literature-reviewer.js +29 -34
- package/dist/prompts/planner.js +15 -29
- package/dist/prompts/report-session.d.ts +1 -1
- package/dist/prompts/report-session.js +2 -33
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +1 -2
- package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/cheminformatics-agent.js +10 -29
- package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
- package/dist/prompts/sandbox/chromatin-agent.js +1 -2
- package/dist/prompts/sandbox/data-profiler.js +6 -3
- package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
- package/dist/prompts/sandbox/dna-methylation-agent.js +2 -7
- package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
- package/dist/prompts/sandbox/drug-repurposing-agent.js +20 -24
- package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
- package/dist/prompts/sandbox/enrichment-agent.js +3 -2
- package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
- package/dist/prompts/sandbox/genomic-variant-agent.js +0 -2
- package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/immune-profiling-agent.js +7 -14
- package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/metabolomics-agent.js +0 -2
- package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
- package/dist/prompts/sandbox/microbiome-agent.js +14 -21
- package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.js +9 -19
- package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multimodal-sc-agent.js +4 -5
- package/dist/prompts/sandbox/network-agent.d.ts +1 -1
- package/dist/prompts/sandbox/network-agent.js +7 -8
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.d.ts +1 -1
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.js +19 -19
- package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/proteomics-agent.js +3 -4
- package/dist/prompts/sandbox/scientific-executor.d.ts +1 -1
- package/dist/prompts/sandbox/scientific-executor.js +7 -10
- package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
- package/dist/prompts/sandbox/single-cell-agent.js +2 -4
- package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/spatial-omics-agent.js +3 -5
- package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/statistical-modeling-agent.js +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.js +10 -19
- package/dist/prompts/sandbox-standards.d.ts +7 -7
- package/dist/prompts/sandbox-standards.js +74 -76
- package/dist/prompts/synthesis-agent.d.ts +1 -1
- package/dist/prompts/synthesis-agent.js +16 -42
- package/dist/providers/ai-sdk.d.ts +39 -6
- package/dist/providers/ai-sdk.js +117 -18
- package/dist/providers/errors.d.ts +2 -0
- package/dist/providers/errors.js +5 -0
- package/dist/providers/prompt-cache.d.ts +43 -41
- package/dist/providers/prompt-cache.js +47 -41
- package/dist/providers/reasoning.d.ts +10 -21
- package/dist/providers/reasoning.js +10 -21
- package/dist/providers/types.d.ts +21 -5
- package/dist/report-model/authoring-grammar.d.ts +2 -2
- package/dist/runtime/assemble.d.ts +9 -7
- package/dist/runtime/assemble.js +7 -3
- package/dist/sandbox/create-sandbox.d.ts +2 -2
- package/dist/sandbox/submit-exec.d.ts +1 -1
- package/dist/schemas/artifact-manifest.d.ts +4 -4
- package/dist/state/init.js +39 -4
- package/dist/state/purge-analysis.js +4 -0
- package/dist/state/tool-outputs.d.ts +4 -0
- package/dist/state/tool-outputs.js +30 -0
- package/dist/tasks/data-profile.d.ts +3 -0
- package/dist/tasks/data-profile.js +2 -0
- package/dist/tools/ad-hoc-router.d.ts +8 -0
- package/dist/tools/ad-hoc-router.js +21 -2
- package/dist/tools/display/show-user.d.ts +1 -1
- package/dist/tools/execute-analysis.d.ts +3 -0
- package/dist/tools/execute-analysis.js +9 -1
- package/dist/tools/read-tool-output.d.ts +7 -0
- package/dist/tools/read-tool-output.js +130 -0
- package/dist/tools/research/generate-analogy-report.d.ts +10 -26
- package/dist/tools/research/generate-analogy-report.js +76 -163
- package/dist/tools/research/generate-plan.d.ts +3 -0
- package/dist/tools/research/generate-plan.js +4 -1
- package/dist/tools/research/literature-reviewer.d.ts +3 -0
- package/dist/tools/research/literature-reviewer.js +3 -0
- package/dist/tools/sandbox/report-blocker.d.ts +18 -5
- package/dist/tools/sandbox/report-blocker.js +54 -6
- package/dist/tools/sandbox/submit-file-metadata.d.ts +30 -0
- package/dist/tools/sandbox/submit-file-metadata.js +67 -0
- package/dist/tools/start-report-session.d.ts +1 -3
- package/dist/tools/start-report-session.js +0 -2
- package/dist/tools/workspace/execute-command.js +7 -4
- package/dist/tools/workspace/result-bounds.d.ts +4 -4
- package/dist/tools/workspace/result-bounds.js +6 -5
- package/dist/tools/workspace/workspace-search.d.ts +1 -1
- package/dist/workflows/execute-analysis.d.ts +3 -0
- package/dist/workflows/execute-analysis.js +1 -0
- package/dist/workflows/sandbox-step.d.ts +30 -9
- package/dist/workflows/sandbox-step.js +37 -8
- package/package.json +9 -9
- package/dist/providers/anthropic.d.ts +0 -25
- package/dist/providers/anthropic.js +0 -28
|
@@ -6,18 +6,24 @@
|
|
|
6
6
|
* `report_blocker` is the alternative to improvising an inline result the
|
|
7
7
|
* harness would launder into a green run.
|
|
8
8
|
*
|
|
9
|
-
* This module is the canonical home of the tool.
|
|
10
|
-
* sandbox step agent, the planner (`tools/research/generate-plan.ts`)
|
|
11
|
-
* run synthesizer (`execution/run-synthesis.ts`)
|
|
9
|
+
* This module is the canonical home of the tool. Four loops offer it — the
|
|
10
|
+
* sandbox step agent, the planner (`tools/research/generate-plan.ts`), the
|
|
11
|
+
* run synthesizer (`execution/run-synthesis.ts`) and the analogical reasoner
|
|
12
|
+
* (`tools/research/generate-analogy-report.ts`) — and all four share one id,
|
|
12
13
|
* one input schema and one terminal contract via `createReportBlockerToolFor`.
|
|
13
14
|
* What differs per loop is only what a blocker *means* there, so each call site
|
|
14
15
|
* injects its own `blockedWhen` prose and its own capture closure. The tool
|
|
15
|
-
* records the reason and tells the agent to stop; the driving body reads
|
|
16
|
-
*
|
|
16
|
+
* records the reason and tells the agent to stop; the driving body reads the
|
|
17
|
+
* outcome after the loop and decides the terminal status. The sandbox step body
|
|
18
|
+
* runs in durable steps, so it reads the blocker back from the transcript
|
|
19
|
+
* (`recordedBlocker`) on replay, not only from its cell.
|
|
17
20
|
*/
|
|
18
21
|
import { ok } from "neverthrow";
|
|
19
22
|
import { z } from "zod";
|
|
23
|
+
import { repairToolInput } from "../../lib/zod-issues.js";
|
|
24
|
+
import { toolOutcomeForOutputType } from "../../loop/tool-outcome.js";
|
|
20
25
|
import { defineTool } from "../define-tool.js";
|
|
26
|
+
export const REPORT_BLOCKER_TOOL_ID = "report_blocker";
|
|
21
27
|
export function createBlockerHolder() {
|
|
22
28
|
return { outcome: null };
|
|
23
29
|
}
|
|
@@ -30,7 +36,7 @@ const ReportBlockerInputSchema = z.object({ reason: z.string().min(1) });
|
|
|
30
36
|
*/
|
|
31
37
|
export function createReportBlockerToolFor(deps) {
|
|
32
38
|
return defineTool({
|
|
33
|
-
id:
|
|
39
|
+
id: REPORT_BLOCKER_TOOL_ID,
|
|
34
40
|
description: `Terminal. ${deps.blockedWhen} Pass a clear reason. Stop immediately after calling — take no further actions.`,
|
|
35
41
|
inputSchema: ReportBlockerInputSchema,
|
|
36
42
|
describeCall: "none",
|
|
@@ -43,6 +49,48 @@ export function createReportBlockerToolFor(deps) {
|
|
|
43
49
|
},
|
|
44
50
|
});
|
|
45
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* The blocker that a run recorded, read from its transcript: the reason of the
|
|
54
|
+
* first `report_blocker` call, in call order, whose result is ok.
|
|
55
|
+
*
|
|
56
|
+
* A replay returns each tool step's cached result without re-running
|
|
57
|
+
* `execute`, so the in-memory cell is empty on replay; the transcript is not.
|
|
58
|
+
*/
|
|
59
|
+
export function recordedBlocker(messages) {
|
|
60
|
+
const recorded = new Set();
|
|
61
|
+
for (const message of messages) {
|
|
62
|
+
if (message.role !== "tool")
|
|
63
|
+
continue;
|
|
64
|
+
for (const part of message.content) {
|
|
65
|
+
if (part.type === "tool-result" && part.toolName === REPORT_BLOCKER_TOOL_ID && toolOutcomeForOutputType(part.output.type) === "ok") {
|
|
66
|
+
recorded.add(part.toolCallId);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
for (const message of messages) {
|
|
71
|
+
if (message.role !== "assistant" || typeof message.content === "string")
|
|
72
|
+
continue;
|
|
73
|
+
for (const part of message.content) {
|
|
74
|
+
if (part.type !== "tool-call" || part.toolName !== REPORT_BLOCKER_TOOL_ID || !recorded.has(part.toolCallId))
|
|
75
|
+
continue;
|
|
76
|
+
const reason = blockerReason(part.input);
|
|
77
|
+
if (reason !== undefined)
|
|
78
|
+
return { kind: "blocker", reason };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
/** The reason of a `report_blocker` input, validated as the dispatch validates it. */
|
|
84
|
+
function blockerReason(input) {
|
|
85
|
+
const parsed = ReportBlockerInputSchema.safeParse(input);
|
|
86
|
+
if (parsed.success)
|
|
87
|
+
return parsed.data.reason;
|
|
88
|
+
const repaired = repairToolInput(input, parsed.error);
|
|
89
|
+
if (repaired === undefined)
|
|
90
|
+
return undefined;
|
|
91
|
+
const reparsed = ReportBlockerInputSchema.safeParse(repaired);
|
|
92
|
+
return reparsed.success ? reparsed.data.reason : undefined;
|
|
93
|
+
}
|
|
46
94
|
/**
|
|
47
95
|
* The sandbox step agent's `report_blocker`, bound to the step body's holder.
|
|
48
96
|
* A blocker here ends the step with no deliverables and a blocked reason.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `submit_file_metadata` — the output tool of the file-metadata continuation of
|
|
3
|
+
* a sandbox step (see the harness-sandbox-agents spec).
|
|
4
|
+
*
|
|
5
|
+
* Each step agent declares this tool from its first request; a mask refuses it
|
|
6
|
+
* until the file-metadata continuation, because the tool set sits in the
|
|
7
|
+
* prefix that the prompt cache and a signed thinking block bind to.
|
|
8
|
+
*
|
|
9
|
+
* The tool matches each description to its file BY PATH, never by array
|
|
10
|
+
* index, so a dropped, reordered, or extra entry can never attach a
|
|
11
|
+
* description to the wrong file.
|
|
12
|
+
*/
|
|
13
|
+
import { type SubmittedFileDescription } from "../../schemas/file-metadata.js";
|
|
14
|
+
import { type Tool } from "../define-tool.js";
|
|
15
|
+
export declare const SUBMIT_FILE_METADATA_TOOL_ID = "submit_file_metadata";
|
|
16
|
+
/**
|
|
17
|
+
* The per-step cell of the file-metadata continuation. The step body makes it
|
|
18
|
+
* beside the blocker cell, and the agent factory binds the output tool to it.
|
|
19
|
+
*/
|
|
20
|
+
export interface FileMetadataCell {
|
|
21
|
+
/** The paths that the continuation describes, or `null` before the first `expect`. */
|
|
22
|
+
readonly knownPaths: ReadonlySet<string> | null;
|
|
23
|
+
/** The accepted description of each described path, keyed by the path. The tool writes only a known path. */
|
|
24
|
+
readonly descriptions: Map<string, SubmittedFileDescription>;
|
|
25
|
+
/** Arm the cell for one continuation: set the known paths, and drop each accepted description. */
|
|
26
|
+
expect(paths: readonly string[]): void;
|
|
27
|
+
}
|
|
28
|
+
export declare function createFileMetadataCell(): FileMetadataCell;
|
|
29
|
+
/** Build the `submit_file_metadata` tool bound to the cell of one step. */
|
|
30
|
+
export declare function createSubmitFileMetadataTool(cell: FileMetadataCell): Tool;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `submit_file_metadata` — the output tool of the file-metadata continuation of
|
|
3
|
+
* a sandbox step (see the harness-sandbox-agents spec).
|
|
4
|
+
*
|
|
5
|
+
* Each step agent declares this tool from its first request; a mask refuses it
|
|
6
|
+
* until the file-metadata continuation, because the tool set sits in the
|
|
7
|
+
* prefix that the prompt cache and a signed thinking block bind to.
|
|
8
|
+
*
|
|
9
|
+
* The tool matches each description to its file BY PATH, never by array
|
|
10
|
+
* index, so a dropped, reordered, or extra entry can never attach a
|
|
11
|
+
* description to the wrong file.
|
|
12
|
+
*/
|
|
13
|
+
import { err, ok } from "neverthrow";
|
|
14
|
+
import { SubmitFileMetadataInputSchema } from "../../schemas/file-metadata.js";
|
|
15
|
+
import { defineTool } from "../define-tool.js";
|
|
16
|
+
export const SUBMIT_FILE_METADATA_TOOL_ID = "submit_file_metadata";
|
|
17
|
+
export function createFileMetadataCell() {
|
|
18
|
+
let knownPaths = null;
|
|
19
|
+
const descriptions = new Map();
|
|
20
|
+
return {
|
|
21
|
+
get knownPaths() {
|
|
22
|
+
return knownPaths;
|
|
23
|
+
},
|
|
24
|
+
descriptions,
|
|
25
|
+
expect(paths) {
|
|
26
|
+
knownPaths = new Set(paths);
|
|
27
|
+
descriptions.clear();
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** Build the `submit_file_metadata` tool bound to the cell of one step. */
|
|
32
|
+
export function createSubmitFileMetadataTool(cell) {
|
|
33
|
+
return defineTool({
|
|
34
|
+
id: SUBMIT_FILE_METADATA_TOOL_ID,
|
|
35
|
+
description: "Submit the metadata of the output files of this step. The harness asks " +
|
|
36
|
+
"for this tool after the task, with the list of the files. It does not " +
|
|
37
|
+
"run during the task. Each entry's `path` MUST exactly match one of the " +
|
|
38
|
+
"listed files. Returns {accepted, unknownPaths, remaining}: " +
|
|
39
|
+
"accepted=true means every file now has metadata — STOP. Otherwise drop " +
|
|
40
|
+
"the unknownPaths and describe the remaining files.",
|
|
41
|
+
inputSchema: SubmitFileMetadataInputSchema,
|
|
42
|
+
describeCall: "none",
|
|
43
|
+
execute: async (input) => {
|
|
44
|
+
const knownPaths = cell.knownPaths;
|
|
45
|
+
if (knownPaths === null) {
|
|
46
|
+
return err({
|
|
47
|
+
error: "No list of files is known yet. The harness asks for the file metadata after the task, with the list of the files.",
|
|
48
|
+
retryable: false,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const unknownPaths = [];
|
|
52
|
+
for (const entry of input.files) {
|
|
53
|
+
if (!knownPaths.has(entry.path)) {
|
|
54
|
+
unknownPaths.push(entry.path);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
cell.descriptions.set(entry.path, entry);
|
|
58
|
+
}
|
|
59
|
+
const remaining = [...knownPaths].filter((path) => !cell.descriptions.has(path));
|
|
60
|
+
return ok({
|
|
61
|
+
accepted: unknownPaths.length === 0 && remaining.length === 0,
|
|
62
|
+
unknownPaths,
|
|
63
|
+
remaining,
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -45,7 +45,7 @@ export type StartReportSessionInput = z.infer<typeof startReportSessionInput>;
|
|
|
45
45
|
* never throws for a degraded condition.
|
|
46
46
|
*
|
|
47
47
|
* `started` and `existing-session` name a report thread. `refused` names a call
|
|
48
|
-
* whose scope carries no conversation thread. The
|
|
48
|
+
* whose scope carries no conversation thread. The three refusals of the spawn
|
|
49
49
|
* keep their own names, thus the agent reads one reason from the spawn and from
|
|
50
50
|
* the tool alike. `failed` is a store fault, and it carries a short line.
|
|
51
51
|
*/
|
|
@@ -68,8 +68,6 @@ export type StartReportSessionResult = {
|
|
|
68
68
|
} | {
|
|
69
69
|
outcome: "parent_not_a_conversation";
|
|
70
70
|
threadType: ThreadType;
|
|
71
|
-
} | {
|
|
72
|
-
outcome: "empty_parent_transcript";
|
|
73
71
|
} | {
|
|
74
72
|
outcome: "failed";
|
|
75
73
|
detail: string;
|
|
@@ -79,8 +79,6 @@ function toOutcome(fault) {
|
|
|
79
79
|
return { outcome: "parent_not_found" };
|
|
80
80
|
case "parent_not_a_conversation":
|
|
81
81
|
return { outcome: "parent_not_a_conversation", threadType: fault.threadType };
|
|
82
|
-
case "empty_parent_transcript":
|
|
83
|
-
return { outcome: "empty_parent_transcript" };
|
|
84
82
|
case "query_failed":
|
|
85
83
|
case "mutation_failed":
|
|
86
84
|
case "connection_failed":
|
|
@@ -24,7 +24,7 @@ import { ok } from "neverthrow";
|
|
|
24
24
|
import { z } from "zod";
|
|
25
25
|
import { defineTool } from "../define-tool.js";
|
|
26
26
|
import { feedExecFrame } from "../../provenance/exec-frame.js";
|
|
27
|
-
import { boundExecResult } from "./result-bounds.js";
|
|
27
|
+
import { EXEC_STREAM_BYTE_CAP, boundExecResult } from "./result-bounds.js";
|
|
28
28
|
import { runSandboxExec } from "./run-exec.js";
|
|
29
29
|
import { createNoopLogger } from "../../lib/console-logger.js";
|
|
30
30
|
const ExecuteCommandInputSchema = z.object({
|
|
@@ -32,7 +32,8 @@ const ExecuteCommandInputSchema = z.object({
|
|
|
32
32
|
.array(z.string().min(1))
|
|
33
33
|
.min(1)
|
|
34
34
|
.describe("argv array — e.g. ['python', 'scripts/run.py'] or ['head', '-n', '50', 'data/inputs/x.csv']. " +
|
|
35
|
-
"
|
|
35
|
+
"A one-element array runs through `sh -c`, so pipes, `&&`, quoting, and globbing work; " +
|
|
36
|
+
"an array of two or more elements runs directly, with no shell, and nothing is expanded."),
|
|
36
37
|
cwd: z
|
|
37
38
|
.string()
|
|
38
39
|
.optional()
|
|
@@ -57,8 +58,10 @@ export function createExecuteCommandTool(deps) {
|
|
|
57
58
|
executionMode: "workflow",
|
|
58
59
|
description: "Run a command in the sandbox and return its stdout/stderr/exit code. " +
|
|
59
60
|
"Use for scripts, CLI tools, shell pipes, and anything the workspace " +
|
|
60
|
-
|
|
61
|
-
"
|
|
61
|
+
`tools don't express. stdout and stderr are each capped at ${EXEC_STREAM_BYTE_CAP / (1024 * 1024)} MiB; the end ` +
|
|
62
|
+
"of a longer stream is dropped, and the result carries its truncation flag. A long result comes back as an " +
|
|
63
|
+
"excerpt of its start and its end, with a reference to read the rest when the harness keeps it. " +
|
|
64
|
+
"Failures are returned as data, " +
|
|
62
65
|
"not thrown. stdout/stderr are EPHEMERAL and are NOT a deliverable — use " +
|
|
63
66
|
"this to confirm a command ran, not to produce results. Do NOT compute " +
|
|
64
67
|
"analysis results via 'python -c' / inline one-liners and read them from " +
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* shape is uniform across the surface and the cap can be tuned in one
|
|
6
6
|
* place.
|
|
7
7
|
*
|
|
8
|
-
* The cap
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* The cap bounds the memory of the host and the size of a kept tool output. It
|
|
9
|
+
* does not keep the context of the model small: the loop cuts a long result into
|
|
10
|
+
* an excerpt, and it keeps the text for `read_tool_output`.
|
|
11
11
|
*
|
|
12
12
|
* The same value is sent to the sandbox as a retention budget, so the bytes are
|
|
13
13
|
* dropped at the producer and never cross the wire. Capping here as well is not
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* and this is the boundary that keeps it out of the process either way.
|
|
16
16
|
*/
|
|
17
17
|
import type { ExecResult } from "../../sandbox/types.js";
|
|
18
|
-
/** Per-stream cap
|
|
18
|
+
/** Per-stream cap: the maximum of a kept tool output, thus the host gets each stream that the store can keep. */
|
|
19
19
|
export declare const EXEC_STREAM_BYTE_CAP: number;
|
|
20
20
|
export interface BoundedStream {
|
|
21
21
|
readonly content: string;
|
|
@@ -5,17 +5,18 @@
|
|
|
5
5
|
* shape is uniform across the surface and the cap can be tuned in one
|
|
6
6
|
* place.
|
|
7
7
|
*
|
|
8
|
-
* The cap
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* The cap bounds the memory of the host and the size of a kept tool output. It
|
|
9
|
+
* does not keep the context of the model small: the loop cuts a long result into
|
|
10
|
+
* an excerpt, and it keeps the text for `read_tool_output`.
|
|
11
11
|
*
|
|
12
12
|
* The same value is sent to the sandbox as a retention budget, so the bytes are
|
|
13
13
|
* dropped at the producer and never cross the wire. Capping here as well is not
|
|
14
14
|
* redundant: a sandbox image that pre-dates the budget returns the whole stream,
|
|
15
15
|
* and this is the boundary that keeps it out of the process either way.
|
|
16
16
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
import { TOOL_OUTPUT_KEEP_MAX } from "../../loop/tool-output.js";
|
|
18
|
+
/** Per-stream cap: the maximum of a kept tool output, thus the host gets each stream that the store can keep. */
|
|
19
|
+
export const EXEC_STREAM_BYTE_CAP = TOOL_OUTPUT_KEEP_MAX;
|
|
19
20
|
/**
|
|
20
21
|
* Decode `buf` as UTF-8, dropping a trailing partial sequence rather than
|
|
21
22
|
* letting it decode to U+FFFD. Only the last few bytes can be partial, so the
|
|
@@ -23,7 +23,7 @@ export declare function fileTargetOf(id: string, metadata: unknown): string | un
|
|
|
23
23
|
export declare function createWorkspaceSearchTool(pool: Pool, embedding: EmbeddingProvider): import("../define-tool.js").Tool<{
|
|
24
24
|
query: string;
|
|
25
25
|
limit: number;
|
|
26
|
-
type?: "output" | "input" | "
|
|
26
|
+
type?: "output" | "input" | "summary" | "synthesis" | "input-group" | "input-dimension" | "input-kind" | undefined;
|
|
27
27
|
}, {
|
|
28
28
|
results: {
|
|
29
29
|
metadata: unknown;
|
|
@@ -80,6 +80,7 @@ import type { AnalysisStep } from "../schemas/workflow-state.js";
|
|
|
80
80
|
import type { ChatProvider, EmbeddingProvider } from "../providers/types.js";
|
|
81
81
|
import type { BioToolKeys } from "../tools/bio/keys.js";
|
|
82
82
|
import type { ProvenanceSeam } from "../provenance/seam.js";
|
|
83
|
+
import type { ToolOutputStore } from "../loop/tool-output.js";
|
|
83
84
|
import type { RunCharge } from "../billing/run-charge.js";
|
|
84
85
|
import { type ResolveWorkspaceRoot } from "../workspace/paths.js";
|
|
85
86
|
import { type PlanStep } from "./execute-analysis-scheduler.js";
|
|
@@ -245,6 +246,8 @@ export interface ExecuteAnalysisDeps {
|
|
|
245
246
|
* recorder.
|
|
246
247
|
*/
|
|
247
248
|
readonly usageRecorder?: UsageRecorder;
|
|
249
|
+
/** The store of the loops of the run synthesis and of their read tools. */
|
|
250
|
+
readonly toolOutputStore?: ToolOutputStore;
|
|
248
251
|
/**
|
|
249
252
|
* The provenance seam of the composition. The body reads its run emit member,
|
|
250
253
|
* and it reads no other member.
|
|
@@ -354,6 +354,7 @@ export function synthesizeFindings(args) {
|
|
|
354
354
|
bioKeys: deps.bioKeys,
|
|
355
355
|
citationResolver: deps.citationResolver,
|
|
356
356
|
usageRecorder: deps.usageRecorder,
|
|
357
|
+
...(deps.toolOutputStore ? { toolOutputStore: deps.toolOutputStore } : {}),
|
|
357
358
|
}, {
|
|
358
359
|
analysisId,
|
|
359
360
|
runId,
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
* 2. `createSandbox` — provision the sandbox; persist its handle.
|
|
10
10
|
* 3. `runAgent` — the harness agent loop. Every LLM and tool
|
|
11
11
|
* call inside is its own durableStep.
|
|
12
|
-
* 4. `generateFileMetadata`—
|
|
13
|
-
* 5. `generateStepSummary` —
|
|
12
|
+
* 4. `generateFileMetadata`— the file-metadata continuation of the step agent.
|
|
13
|
+
* 5. `generateStepSummary` — the summary continuation of the step agent,
|
|
14
|
+
* producing `output/summary.md`.
|
|
14
15
|
* 6. `reconcile + register`— write artifact manifest entries to cortex_artifacts.
|
|
15
16
|
* 7. `syncArtifacts` — register provenance + upload missing file_ids
|
|
16
17
|
* via the managed root (scoped to this run+step).
|
|
@@ -32,6 +33,7 @@ import type { Logger } from "../lib/logger.js";
|
|
|
32
33
|
import type { UsageRecorder } from "../billing/usage-recorder.js";
|
|
33
34
|
import type { CitationResolver } from "../citations/types.js";
|
|
34
35
|
import type { AgentDefinition, LoopMessage } from "../loop/types.js";
|
|
36
|
+
import { type ToolOutputStore } from "../loop/tool-output.js";
|
|
35
37
|
import type { AgentChat, EmbeddingProvider } from "../providers/types.js";
|
|
36
38
|
import { type RunSession, type SpawnSession } from "../auth/types.js";
|
|
37
39
|
import type { FileMetadataEntry } from "../execution/artifact-metadata.js";
|
|
@@ -41,10 +43,12 @@ import type { SandboxClient } from "../sandbox/client.js";
|
|
|
41
43
|
import type { WorkspaceFilesystem } from "../workspace/filesystem.js";
|
|
42
44
|
import type { ResolveWorkspaceRoot } from "../workspace/paths.js";
|
|
43
45
|
import type { ArtifactRegistry } from "../execution/artifact-registry.js";
|
|
46
|
+
import { type StepFileMetadata } from "../execution/post-step-pipeline.js";
|
|
44
47
|
import type { ResourceSpec } from "../config/resource-limits.js";
|
|
45
48
|
import type { SandboxRef } from "../sandbox/types.js";
|
|
46
49
|
import { ProvenanceCollector } from "../provenance/collector.js";
|
|
47
50
|
import { type BlockerHolder } from "../tools/sandbox/report-blocker.js";
|
|
51
|
+
import { type FileMetadataCell } from "../tools/sandbox/submit-file-metadata.js";
|
|
48
52
|
/**
|
|
49
53
|
* Input the parent hands the child. Must be JSON-serialisable — DBOS
|
|
50
54
|
* persists this as the workflow's input row.
|
|
@@ -200,13 +204,19 @@ export interface SandboxAgentBuildContext {
|
|
|
200
204
|
*/
|
|
201
205
|
readonly lineageCollector: ProvenanceCollector;
|
|
202
206
|
/**
|
|
203
|
-
* Per-run blocker cell
|
|
204
|
-
*
|
|
205
|
-
* bound to this holder.
|
|
207
|
+
* Per-run blocker cell that `report_blocker` writes. The body prefers the
|
|
208
|
+
* blocker read from the transcript and falls back to this cell.
|
|
206
209
|
*/
|
|
207
210
|
readonly blockerHolder: BlockerHolder;
|
|
211
|
+
/**
|
|
212
|
+
* Cell for the file-metadata continuation. `submit_file_metadata` is
|
|
213
|
+
* declared up front for prefix stability but masked until then.
|
|
214
|
+
*/
|
|
215
|
+
readonly fileMetadata: FileMetadataCell;
|
|
208
216
|
/** Shared host-side citation resolver for allowlisted sandbox agents. */
|
|
209
217
|
readonly citationResolver: CitationResolver;
|
|
218
|
+
/** Give it to `SandboxAgentDeps.toolOutputStore`: each loop of the step keeps its texts in it. */
|
|
219
|
+
readonly toolOutputStore?: ToolOutputStore;
|
|
210
220
|
}
|
|
211
221
|
/**
|
|
212
222
|
* Inversion of control: the parent supplies the live agent, the parent's
|
|
@@ -226,12 +236,14 @@ export interface SandboxStepDeps {
|
|
|
226
236
|
readonly logger?: Logger;
|
|
227
237
|
/**
|
|
228
238
|
* LLM usage-accounting seam. Covers this step's agent loop and the
|
|
229
|
-
* post-step
|
|
239
|
+
* post-step continuations alike; omitted falls back to the no-op recorder.
|
|
230
240
|
*/
|
|
231
241
|
readonly usageRecorder?: UsageRecorder;
|
|
242
|
+
/** The store of the task, of the two post-step continuations, and of the read tool of the step agent. */
|
|
243
|
+
readonly toolOutputStore?: ToolOutputStore;
|
|
232
244
|
/** Shared resolver threaded from `assembleCoreRuntime`. */
|
|
233
245
|
readonly citationResolver: CitationResolver;
|
|
234
|
-
/** Non-streaming chat — drives the agent loop + the post-step
|
|
246
|
+
/** Non-streaming chat — drives the agent loop + the post-step continuations. */
|
|
235
247
|
readonly provider: AgentChat;
|
|
236
248
|
/** Write-side embedder for the post-step vector index. */
|
|
237
249
|
readonly embedding: EmbeddingProvider;
|
|
@@ -242,11 +254,14 @@ export interface SandboxStepDeps {
|
|
|
242
254
|
* cloud-free build, external provenance ledger in the managed build).
|
|
243
255
|
*/
|
|
244
256
|
readonly artifactRegistry: ArtifactRegistry;
|
|
245
|
-
/**
|
|
257
|
+
/**
|
|
258
|
+
* No longer read by the step body; kept because `src/index.ts` exports
|
|
259
|
+
* this type and an embedder builds it as an object literal.
|
|
260
|
+
*/
|
|
246
261
|
readonly workspaceFs: WorkspaceFilesystem;
|
|
247
262
|
/** Workspace-root resolution seam (see workspace/paths.ts). */
|
|
248
263
|
readonly resolveWorkspaceRoot: ResolveWorkspaceRoot;
|
|
249
|
-
/**
|
|
264
|
+
/** No longer read by the step body, kept for the same reason as `workspaceFs`. */
|
|
250
265
|
readonly model: string;
|
|
251
266
|
/**
|
|
252
267
|
* Build the agent definition for this step. The parent resolves the
|
|
@@ -272,6 +287,10 @@ export interface PostStepContext {
|
|
|
272
287
|
readonly input: SandboxStepInput;
|
|
273
288
|
readonly session: RunSession;
|
|
274
289
|
readonly transcript: readonly LoopMessage[];
|
|
290
|
+
/** The step agent of the task: the continuations send its system prompt and its declared tools. */
|
|
291
|
+
readonly agent: AgentDefinition;
|
|
292
|
+
/** The cell that the `submit_file_metadata` tool of `agent` records into. */
|
|
293
|
+
readonly fileMetadata: FileMetadataCell;
|
|
275
294
|
/** Absolute path to the step's writable artifact directory. */
|
|
276
295
|
readonly writePrefix: string;
|
|
277
296
|
/** Sandbox handle id — informational only, used in log lines. */
|
|
@@ -279,6 +298,8 @@ export interface PostStepContext {
|
|
|
279
298
|
/** Same step-scoped collector the agent loop fed each exec frame into. */
|
|
280
299
|
readonly lineageCollector: ProvenanceCollector;
|
|
281
300
|
}
|
|
301
|
+
/** Normalizes a pre-`messages` checkpoint (a bare entries array) for replay. */
|
|
302
|
+
export declare function readStepFileMetadata(checkpoint: StepFileMetadata | readonly FileMetadataEntry[]): StepFileMetadata;
|
|
282
303
|
/**
|
|
283
304
|
* Build the step's lineage collector from its durable input. The agent loop
|
|
284
305
|
* feeds each exec's provenance frame into it; post-step registration reads the
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
* 2. `createSandbox` — provision the sandbox; persist its handle.
|
|
10
10
|
* 3. `runAgent` — the harness agent loop. Every LLM and tool
|
|
11
11
|
* call inside is its own durableStep.
|
|
12
|
-
* 4. `generateFileMetadata`—
|
|
13
|
-
* 5. `generateStepSummary` —
|
|
12
|
+
* 4. `generateFileMetadata`— the file-metadata continuation of the step agent.
|
|
13
|
+
* 5. `generateStepSummary` — the summary continuation of the step agent,
|
|
14
|
+
* producing `output/summary.md`.
|
|
14
15
|
* 6. `reconcile + register`— write artifact manifest entries to cortex_artifacts.
|
|
15
16
|
* 7. `syncArtifacts` — register provenance + upload missing file_ids
|
|
16
17
|
* via the managed root (scoped to this run+step).
|
|
@@ -34,6 +35,8 @@ import { deliverNotice } from "../lib/hooks.js";
|
|
|
34
35
|
import { unwrapOrThrow } from "../lib/result.js";
|
|
35
36
|
import { runAgent } from "../loop/run-agent.js";
|
|
36
37
|
import { durableStep } from "../loop/run-step.js";
|
|
38
|
+
import { maskExcept } from "../loop/tool-mask.js";
|
|
39
|
+
import { READ_TOOL_OUTPUT_TOOL_ID } from "../loop/tool-output.js";
|
|
37
40
|
import { lastExecOutcome } from "../sandbox/exec-outcome.js";
|
|
38
41
|
import { activityForTool, applyTreeDelta, isChatDataPart, sandboxTreeDelta, stepPartId } from "../sandbox/sandbox-step-translate.js";
|
|
39
42
|
import { createDetailResolver } from "../tools/detail-resolver.js";
|
|
@@ -43,7 +46,8 @@ import { collectStepOutputs, describeStepRegistrationFailure, generateStepFileMe
|
|
|
43
46
|
import { mintSandboxIdentity } from "../sandbox/identity.js";
|
|
44
47
|
import { keepSuspendingRefusal } from "../sandbox/sandbox-error.js";
|
|
45
48
|
import { ProvenanceCollector } from "../provenance/collector.js";
|
|
46
|
-
import { createBlockerHolder } from "../tools/sandbox/report-blocker.js";
|
|
49
|
+
import { createBlockerHolder, recordedBlocker } from "../tools/sandbox/report-blocker.js";
|
|
50
|
+
import { createFileMetadataCell, SUBMIT_FILE_METADATA_TOOL_ID } from "../tools/sandbox/submit-file-metadata.js";
|
|
47
51
|
import { cancelSelf, suspensionOfFailure, suspensionOfRefusal, suspensionOfSpawnRefusal } from "./suspension.js";
|
|
48
52
|
/**
|
|
49
53
|
* Fallback when the plan step omits `timeout`. Plans that need 3-hour runs
|
|
@@ -69,6 +73,15 @@ function nextFunctionIdFactory() {
|
|
|
69
73
|
let n = 0;
|
|
70
74
|
return () => `fn-${(n++).toString(36)}`;
|
|
71
75
|
}
|
|
76
|
+
const NO_STEP_FILE_METADATA = { entries: [], messages: [] };
|
|
77
|
+
/** Normalizes a pre-`messages` checkpoint (a bare entries array) for replay. */
|
|
78
|
+
export function readStepFileMetadata(checkpoint) {
|
|
79
|
+
return isBareEntries(checkpoint) ? { entries: checkpoint, messages: [] } : checkpoint;
|
|
80
|
+
}
|
|
81
|
+
/** `Array.isArray` as a guard that also narrows a readonly array. */
|
|
82
|
+
function isBareEntries(checkpoint) {
|
|
83
|
+
return Array.isArray(checkpoint);
|
|
84
|
+
}
|
|
72
85
|
/**
|
|
73
86
|
* Map an internal step failure to a user-safe string. Internal detail (file
|
|
74
87
|
* paths, content hashes, managed-root rejection reasons, stack traces) stays in the pod
|
|
@@ -210,6 +223,7 @@ export async function runSandboxStepBody(input, deps) {
|
|
|
210
223
|
// for up to N × `timeoutSeconds`.
|
|
211
224
|
const stepDeadlineMs = (await DBOS.now()) + (input.timeoutSeconds ?? DEFAULT_STEP_TIMEOUT_SECONDS) * 1000;
|
|
212
225
|
const blockerHolder = createBlockerHolder();
|
|
226
|
+
const fileMetadata = createFileMetadataCell();
|
|
213
227
|
const agent = deps.buildAgent({
|
|
214
228
|
input,
|
|
215
229
|
session,
|
|
@@ -220,8 +234,13 @@ export async function runSandboxStepBody(input, deps) {
|
|
|
220
234
|
deadlineMs: () => stepDeadlineMs,
|
|
221
235
|
lineageCollector,
|
|
222
236
|
blockerHolder,
|
|
237
|
+
fileMetadata,
|
|
223
238
|
citationResolver: deps.citationResolver,
|
|
239
|
+
...(deps.toolOutputStore ? { toolOutputStore: deps.toolOutputStore } : {}),
|
|
224
240
|
});
|
|
241
|
+
if (deps.toolOutputStore !== undefined && !agent.tools.some((tool) => tool.id === READ_TOOL_OUTPUT_TOOL_ID)) {
|
|
242
|
+
logger.warn("the step agent declares no read_tool_output, thus its loops keep no text of a cut tool result");
|
|
243
|
+
}
|
|
225
244
|
// Built over THIS agent's tools, not a shared table: a sandbox agent's roster
|
|
226
245
|
// differs per agent type, and each tool describes its own calls.
|
|
227
246
|
const resolveDetail = createDetailResolver(agent.tools, logger);
|
|
@@ -361,10 +380,14 @@ export async function runSandboxStepBody(input, deps) {
|
|
|
361
380
|
emit,
|
|
362
381
|
runStep: durableStep,
|
|
363
382
|
usageRecorder: deps.usageRecorder,
|
|
383
|
+
toolOutputStore: deps.toolOutputStore,
|
|
364
384
|
formatStepName: {
|
|
365
385
|
llm: (iteration) => `llm:${iteration}`,
|
|
366
386
|
tool: (toolName, toolUseId) => `tool:${toolName}:${toolUseId}`,
|
|
367
387
|
},
|
|
388
|
+
// The agent declares the output tool of the file-metadata
|
|
389
|
+
// continuation from its first request, and the task must not use it.
|
|
390
|
+
toolMask: maskExcept(agent.tools, [SUBMIT_FILE_METADATA_TOOL_ID]),
|
|
368
391
|
isFatalLoopError: (err) => err instanceof DBOSErrors.DBOSWorkflowCancelledError,
|
|
369
392
|
});
|
|
370
393
|
transcript = agentResult.messages;
|
|
@@ -421,7 +444,10 @@ export async function runSandboxStepBody(input, deps) {
|
|
|
421
444
|
// status would attest an empty step. A blocker outcome keeps its own
|
|
422
445
|
// reason. A capped-out step WITH artifacts stays on the completed path,
|
|
423
446
|
// because partial output is real output.
|
|
424
|
-
|
|
447
|
+
//
|
|
448
|
+
// A replay does not rerun `execute`, so the cell is empty then; the
|
|
449
|
+
// transcript is the durable record and takes precedence over the cell.
|
|
450
|
+
const blockerOutcome = recordedBlocker(transcript) ?? blockerHolder.outcome;
|
|
425
451
|
const cappedOutEmpty = hitMaxSteps && manifest.length === 0;
|
|
426
452
|
if (blockerOutcome || cappedOutEmpty) {
|
|
427
453
|
const blockedReason = blockerOutcome?.reason ?? CAPPED_OUT_EMPTY_REASON;
|
|
@@ -466,6 +492,8 @@ export async function runSandboxStepBody(input, deps) {
|
|
|
466
492
|
input,
|
|
467
493
|
session,
|
|
468
494
|
transcript,
|
|
495
|
+
agent,
|
|
496
|
+
fileMetadata,
|
|
469
497
|
writePrefix,
|
|
470
498
|
sandboxId: sandbox.sandboxId,
|
|
471
499
|
lineageCollector,
|
|
@@ -475,12 +503,13 @@ export async function runSandboxStepBody(input, deps) {
|
|
|
475
503
|
// outputs are checkpointed (see the harness-durable-runtime spec): the conditional terminal emits they
|
|
476
504
|
// gate (`data-step-summary`, file-tree) stay replay-stable and the billed
|
|
477
505
|
// LLM calls are not re-issued on recovery. The remaining stages (walk /
|
|
478
|
-
// reconcile / sync / index) stay inline — a separate follow-up.
|
|
479
|
-
|
|
506
|
+
// reconcile / sync / index) stay inline — a separate follow-up. The
|
|
507
|
+
// checkpoint keeps the exchange's messages so a replay's prefix matches.
|
|
508
|
+
const { entries: metadataEntries, messages: metadataMessages } = readStepFileMetadata(await safeRunValue(logger, () => DBOS.runStep(() => generateStepFileMetadata(deps, postCtx, manifest), {
|
|
480
509
|
name: "post-step.generate-file-metadata",
|
|
481
|
-
}), "post-step.metadata",
|
|
510
|
+
}), "post-step.metadata", NO_STEP_FILE_METADATA));
|
|
482
511
|
await emitActivity("generating-summary", "Summarizing step results");
|
|
483
|
-
const summary = await safeRunValue(logger, () => DBOS.runStep(() => generateStepSummaryAndWrite(deps, postCtx, manifest), {
|
|
512
|
+
const summary = await safeRunValue(logger, () => DBOS.runStep(() => generateStepSummaryAndWrite(deps, postCtx, manifest, metadataMessages), {
|
|
484
513
|
name: "post-step.generate-step-summary",
|
|
485
514
|
}), "post-step.summary", undefined);
|
|
486
515
|
// Lineage attestation (registration) is fail-fast (see the artifact-manifest spec): unlike
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inflexa-ai/harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"description": "Host-agnostic bioinformatics agent harness — hand-rolled agent loop, DBOS-durable workflows, sandboxed compute.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
"typecheck": "tsc --noEmit"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@ai-sdk/anthropic": "^4.0.
|
|
51
|
-
"@ai-sdk/openai": "^4.0.
|
|
52
|
-
"@ai-sdk/openai-compatible": "^3.0.
|
|
53
|
-
"@ai-sdk/otel": "^1.0.
|
|
54
|
-
"@ai-sdk/provider": "^4.0.
|
|
55
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
50
|
+
"@ai-sdk/anthropic": "^4.0.62",
|
|
51
|
+
"@ai-sdk/openai": "^4.0.74",
|
|
52
|
+
"@ai-sdk/openai-compatible": "^3.0.55",
|
|
53
|
+
"@ai-sdk/otel": "^1.0.113",
|
|
54
|
+
"@ai-sdk/provider": "^4.0.18",
|
|
55
|
+
"@ai-sdk/provider-utils": "5.0.47",
|
|
56
56
|
"@anthropic-ai/sdk": "^0.116.0",
|
|
57
57
|
"@dbos-inc/dbos-sdk": "^4.23.6",
|
|
58
58
|
"@fontsource-variable/space-grotesk": "5.1.1",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"@opentelemetry/sdk-trace-node": "^2.9.0",
|
|
70
70
|
"@opentelemetry/semantic-conventions": "^1.43.0",
|
|
71
71
|
"ag-grid-community": "36.1.0",
|
|
72
|
-
"ai": "^7.0.
|
|
72
|
+
"ai": "^7.0.113",
|
|
73
73
|
"cheerio": "^1.2.0",
|
|
74
74
|
"dockerode": "^4.0.12",
|
|
75
75
|
"echarts": "6.1.0",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"uuid": "^11.1.1"
|
|
96
96
|
},
|
|
97
97
|
"devDependencies": {
|
|
98
|
-
"@ai-sdk/amazon-bedrock": "^5.0.
|
|
98
|
+
"@ai-sdk/amazon-bedrock": "^5.0.93",
|
|
99
99
|
"@eslint/js": "^10.0.1",
|
|
100
100
|
"@types/bun": "latest",
|
|
101
101
|
"@types/dockerode": "^3.3.47",
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compatibility entry point for Anthropic-backed chat.
|
|
3
|
-
*
|
|
4
|
-
* The production provider path is AI SDK-backed; this wrapper preserves the
|
|
5
|
-
* old factory name for embedders while returning the new `ChatProvider` seam.
|
|
6
|
-
*/
|
|
7
|
-
import type { Logger } from "../lib/logger.js";
|
|
8
|
-
import { type ProviderHostPolicy } from "./ai-sdk.js";
|
|
9
|
-
import type { ChatProvider, FetchLike } from "./types.js";
|
|
10
|
-
export interface AnthropicProviderDeps extends ProviderHostPolicy {
|
|
11
|
-
readonly baseURL?: string;
|
|
12
|
-
readonly token: string;
|
|
13
|
-
readonly model: string;
|
|
14
|
-
readonly fetch?: FetchLike;
|
|
15
|
-
readonly logger?: Logger;
|
|
16
|
-
/** Output-token ceiling per request. Defaults to `DEFAULT_MAX_OUTPUT_TOKENS`. */
|
|
17
|
-
readonly maxOutputTokens?: number;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Convenience over the `anthropic` arm of the public `AiSdkProviderConfig`
|
|
21
|
-
* union: it takes the Anthropic connection fields directly (`token` as the api
|
|
22
|
-
* key) and delegates to `createConfiguredAiSdkProvider`. The same construction
|
|
23
|
-
* contract holds — the `model` is bound into the returned provider.
|
|
24
|
-
*/
|
|
25
|
-
export declare function createAnthropicProvider(deps: AnthropicProviderDeps): ChatProvider;
|