@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
|
@@ -1,34 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The reasoning depth of a
|
|
2
|
+
* The reasoning depth of a call.
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The effort resolves in order: `ChatRequest.reasoning` (set only through
|
|
5
|
+
* `RunAgentOptions.reasoning`), the provider configuration's `reasoning`, then
|
|
6
|
+
* {@link DEFAULT_REASONING}. Anthropic discards its message cache when the
|
|
7
|
+
* top-level effort changes between calls.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* The harness wrote `providerOptions.anthropic.effort` before. A value on that
|
|
12
|
-
* key turns the per-model table of the Anthropic package off, thus the raw name
|
|
13
|
-
* reached the wire. A model that accepts `high` but not `xhigh` answered 400.
|
|
14
|
-
* The neutral field has no such hazard, because the package resolves the name
|
|
15
|
-
* for the model that it is bound to.
|
|
16
|
-
*
|
|
17
|
-
* ## Where the policy belongs
|
|
18
|
-
*
|
|
19
|
-
* The policy rides on the run, not on the provider, for the same reason that the
|
|
20
|
-
* cache policy does. A one-shot LLM call elsewhere in the harness has its own
|
|
21
|
-
* depth needs, and it must not inherit the depth of an agent loop.
|
|
9
|
+
* Do not set `providerOptions.anthropic.effort` directly. It bypasses the
|
|
10
|
+
* per-model table, and a model that rejects the raw name answers 400.
|
|
22
11
|
*/
|
|
23
12
|
/**
|
|
24
|
-
* The
|
|
13
|
+
* The last source of the effort: the deepest rung of the neutral ladder.
|
|
25
14
|
*
|
|
26
15
|
* Each agent of the harness drives tools over many iterations. A shallow turn
|
|
27
16
|
* there wastes more calls than a deeper turn costs in tokens. The Anthropic
|
|
28
17
|
* package sends `xhigh` to a model that accepts it, and `max` to a model that
|
|
29
18
|
* does not. The OpenAI-compatible package sends the name as it is.
|
|
30
19
|
*
|
|
31
|
-
* A host that wants a cheaper
|
|
32
|
-
* no reasoning support
|
|
20
|
+
* A host that wants a cheaper role sets a lower name on that role's provider
|
|
21
|
+
* configuration. With no reasoning support, a host sets `"provider-default"`.
|
|
33
22
|
*/
|
|
34
23
|
export const DEFAULT_REASONING = "xhigh";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* vendor-neutral interfaces. Every call carries an `AgentSession`; billing
|
|
6
6
|
* attribution is resolved lazily at the provider wire boundary.
|
|
7
7
|
*/
|
|
8
|
-
import type { FinishReason, LanguageModel, ModelMessage, ToolSet } from "ai";
|
|
8
|
+
import type { FinishReason, LanguageModel, ModelMessage, SystemModelMessage, ToolSet } from "ai";
|
|
9
9
|
import type { LanguageModelV4CallOptions } from "@ai-sdk/provider";
|
|
10
10
|
import type { ProviderOptions } from "@ai-sdk/provider-utils";
|
|
11
11
|
import type { ResultAsync } from "neverthrow";
|
|
@@ -32,19 +32,30 @@ export interface ProviderCapabilities {
|
|
|
32
32
|
*/
|
|
33
33
|
readonly imageUserMessages?: boolean;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* The request carries no free-form provider options. That would let a caller
|
|
37
|
+
* set a vendor key that bypasses the provider's per-model table.
|
|
38
|
+
*/
|
|
35
39
|
export interface ChatRequest {
|
|
36
|
-
|
|
40
|
+
/**
|
|
41
|
+
* The system prompt: a plain string, or a system message that carries the
|
|
42
|
+
* cache marker at its end (`withSystemPromptBreakpoint`).
|
|
43
|
+
*/
|
|
44
|
+
readonly system: string | SystemModelMessage;
|
|
37
45
|
readonly messages: readonly ModelMessage[];
|
|
38
46
|
readonly tools: ToolSet;
|
|
39
47
|
/**
|
|
40
48
|
* A forced choice (`required`, or one named tool) is absent on purpose: some
|
|
41
49
|
* Claude models reject it with a 400, and the model is chosen at run time.
|
|
50
|
+
*
|
|
51
|
+
* CAUTION: `@ai-sdk/anthropic` strips the tools when this is `"none"`, and
|
|
52
|
+
* Anthropic drops its cache on any `tool_choice` change — taking a signed
|
|
53
|
+
* thinking block with it. Use a tool mask instead of sending `"none"`.
|
|
42
54
|
*/
|
|
43
55
|
readonly toolChoice?: "auto" | "none";
|
|
44
|
-
readonly providerOptions?: ProviderOptions;
|
|
45
56
|
/**
|
|
46
|
-
* How deep the model reasons
|
|
47
|
-
*
|
|
57
|
+
* How deep the model reasons. Absent, the effort falls back to the provider
|
|
58
|
+
* configuration's `reasoning`, then `DEFAULT_REASONING`.
|
|
48
59
|
*/
|
|
49
60
|
readonly reasoning?: ReasoningPolicy;
|
|
50
61
|
}
|
|
@@ -139,6 +150,11 @@ export interface ChatResponse {
|
|
|
139
150
|
* diagnostics, never as an invariant.
|
|
140
151
|
*/
|
|
141
152
|
readonly servedModelId?: string;
|
|
153
|
+
/**
|
|
154
|
+
* The AI SDK's `LanguageModel.provider` id, for example `anthropic.messages`.
|
|
155
|
+
* Absent for a bare model-id string, which names no provider.
|
|
156
|
+
*/
|
|
157
|
+
readonly provider?: string;
|
|
142
158
|
}
|
|
143
159
|
export type ChatStreamEvent = {
|
|
144
160
|
readonly type: "text-delta";
|
|
@@ -398,15 +398,15 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
|
|
|
398
398
|
x: z.ZodOptional<z.ZodObject<{
|
|
399
399
|
title: z.ZodOptional<z.ZodString>;
|
|
400
400
|
scale: z.ZodOptional<z.ZodEnum<{
|
|
401
|
-
linear: "linear";
|
|
402
401
|
log: "log";
|
|
402
|
+
linear: "linear";
|
|
403
403
|
}>>;
|
|
404
404
|
}, z.core.$strict>>;
|
|
405
405
|
y: z.ZodOptional<z.ZodObject<{
|
|
406
406
|
title: z.ZodOptional<z.ZodString>;
|
|
407
407
|
scale: z.ZodOptional<z.ZodEnum<{
|
|
408
|
-
linear: "linear";
|
|
409
408
|
log: "log";
|
|
409
|
+
linear: "linear";
|
|
410
410
|
}>>;
|
|
411
411
|
}, z.core.$strict>>;
|
|
412
412
|
}, z.core.$strict>>;
|
|
@@ -49,12 +49,13 @@ export type SandboxStepCallable = (input: SandboxStepInput) => Promise<SandboxSt
|
|
|
49
49
|
* here would let an embedder wire a recorder the workflows use and the
|
|
50
50
|
* conversation agent does not — a half-wired ledger that reads as a complete
|
|
51
51
|
* one. The protection has to hold on both sides of the assembly, not just the
|
|
52
|
-
* conversation side.
|
|
52
|
+
* conversation side. Each bag omits `toolOutputStore` for the same reason: each
|
|
53
|
+
* loop must keep its texts in the one store that each read tool reads.
|
|
53
54
|
*/
|
|
54
55
|
export interface CoreWorkflowDeps {
|
|
55
|
-
readonly sandboxStep: Omit<SandboxStepDeps, "usageRecorder" | "citationResolver">;
|
|
56
|
-
readonly buildExecuteAnalysis: (sandboxStep: SandboxStepCallable) => Omit<ExecuteAnalysisDeps, "usageRecorder" | "citationResolver">;
|
|
57
|
-
readonly dataProfile: Omit<DataProfileDeps, "usageRecorder">;
|
|
56
|
+
readonly sandboxStep: Omit<SandboxStepDeps, "usageRecorder" | "citationResolver" | "toolOutputStore">;
|
|
57
|
+
readonly buildExecuteAnalysis: (sandboxStep: SandboxStepCallable) => Omit<ExecuteAnalysisDeps, "usageRecorder" | "citationResolver" | "toolOutputStore">;
|
|
58
|
+
readonly dataProfile: Omit<DataProfileDeps, "usageRecorder" | "toolOutputStore">;
|
|
58
59
|
}
|
|
59
60
|
/** The registered, callable workflow handles. */
|
|
60
61
|
export interface RegisteredWorkflows {
|
|
@@ -66,21 +67,22 @@ export interface RegisteredWorkflows {
|
|
|
66
67
|
}
|
|
67
68
|
/**
|
|
68
69
|
* Conversation-agent deps minus the workflow callable, the resource policy, the
|
|
69
|
-
* usage recorder, the report-session anchor, and the
|
|
70
|
+
* usage recorder, the report-session anchor, the eyes, and the tool output store.
|
|
70
71
|
* `assembleCoreRuntime` supplies each of those itself. Thus a caller cannot wire
|
|
71
|
-
* one of these
|
|
72
|
+
* one of these six values:
|
|
72
73
|
*
|
|
73
74
|
* - a stale callable
|
|
74
75
|
* - a policy that diverges from the one the workflows see
|
|
75
76
|
* - a recorder that only half the agent tree reports to
|
|
76
77
|
* - an anchor over a different session runtime
|
|
77
78
|
* - a seam that only half the agent tree looks through
|
|
79
|
+
* - a store that only half the agent tree keeps its texts in
|
|
78
80
|
*
|
|
79
81
|
* The assembly resolves the eyes one time, from `CoreRuntimeDeps.eyes` and the
|
|
80
82
|
* chrome config. A caller that bound the eyes here would give the conversation
|
|
81
83
|
* agent a seam that the report agent never sees.
|
|
82
84
|
*/
|
|
83
|
-
export type ConversationAssemblyDeps = Omit<ConversationAgentDeps, "executeAnalysisWorkflow" | "resourcePolicy" | "usageRecorder" | "citationResolver" | "anchorReportSession" | "eyes">;
|
|
85
|
+
export type ConversationAssemblyDeps = Omit<ConversationAgentDeps, "executeAnalysisWorkflow" | "resourcePolicy" | "usageRecorder" | "citationResolver" | "anchorReportSession" | "eyes" | "toolOutputStore">;
|
|
84
86
|
/**
|
|
85
87
|
* What binds one reference resolver: the analysis whose pinned artifacts it reads, and the auth of the tool
|
|
86
88
|
* call that reads them. A resolver serves one analysis, thus the report tools build one for each call.
|
package/dist/runtime/assemble.js
CHANGED
|
@@ -30,6 +30,7 @@ import { createCitationResolver } from "../citations/resolve.js";
|
|
|
30
30
|
import { createThreadStore } from "../memory/thread-store.js";
|
|
31
31
|
import { createArtifactReadStore, createProductionResolver } from "../report-model/production-resolver.js";
|
|
32
32
|
import { createReportVersionStore } from "../state/report-versions.js";
|
|
33
|
+
import { createToolOutputStore } from "../state/tool-outputs.js";
|
|
33
34
|
const _assertDomainError = true;
|
|
34
35
|
/**
|
|
35
36
|
* Wrap a type→agent registry as the resolution surface. Held apart from
|
|
@@ -83,9 +84,10 @@ export function assembleCoreRuntime(deps) {
|
|
|
83
84
|
? {}
|
|
84
85
|
: { semanticScholarApiKey: conversation.bioKeys.semanticScholar }),
|
|
85
86
|
});
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
const
|
|
87
|
+
const toolOutputStore = createToolOutputStore(conversation.pool);
|
|
88
|
+
const sandboxStep = registerSandboxStep({ ...wf.sandboxStep, citationResolver, usageRecorder, toolOutputStore });
|
|
89
|
+
const executeAnalysis = registerExecuteAnalysis({ ...wf.buildExecuteAnalysis(sandboxStep), citationResolver, usageRecorder, toolOutputStore });
|
|
90
|
+
const dataProfile = registerDataProfileWorkflow({ ...wf.dataProfile, usageRecorder, toolOutputStore });
|
|
89
91
|
// The extraction workflow shares the profile's sandbox and authorization rails, thus it draws the same
|
|
90
92
|
// three seams from the profile deps. The report resolver factory binds the extraction arm over this
|
|
91
93
|
// callable, thus a fall-through report reference reads its file out of process on the profile rails.
|
|
@@ -120,6 +122,7 @@ export function assembleCoreRuntime(deps) {
|
|
|
120
122
|
anchorReportSession: reportSession.ensureSessionState,
|
|
121
123
|
resourcePolicy,
|
|
122
124
|
usageRecorder,
|
|
125
|
+
toolOutputStore,
|
|
123
126
|
citationResolver,
|
|
124
127
|
...(eyes ? { eyes } : {}),
|
|
125
128
|
// The start tool passes it to the spawn, which emits the creation of a
|
|
@@ -176,6 +179,7 @@ export function assembleCoreRuntime(deps) {
|
|
|
176
179
|
...(deps.resolveReportPageUrl ? { resolvePageUrl: deps.resolveReportPageUrl } : {}),
|
|
177
180
|
...(deps.provenance ? { provenance: deps.provenance } : {}),
|
|
178
181
|
...(conversation.logger ? { logger: conversation.logger } : {}),
|
|
182
|
+
toolOutputStore,
|
|
179
183
|
});
|
|
180
184
|
// The single registration point for every typed agent. A future thread type's
|
|
181
185
|
// agent plugs in here at assembly with no embedder change. `conversation` is
|
|
@@ -49,8 +49,8 @@ export interface CreateSandboxClientConfig {
|
|
|
49
49
|
/**
|
|
50
50
|
* Per-stream retention budget sent with every exec, so the sandbox drops
|
|
51
51
|
* output past it instead of shipping it. Defaults to `EXEC_STREAM_BYTE_CAP`,
|
|
52
|
-
* the
|
|
53
|
-
* host will keep buys nothing.
|
|
52
|
+
* the maximum of a kept tool output and the same value the host truncates to
|
|
53
|
+
* on receipt — sending more than the host will keep buys nothing.
|
|
54
54
|
*/
|
|
55
55
|
execStreamByteCap?: number;
|
|
56
56
|
/** Cluster resource ceilings; every sandbox request is clamped to these. */
|
|
@@ -26,7 +26,7 @@ export interface SubmitExecDeps {
|
|
|
26
26
|
}) => Promise<T>;
|
|
27
27
|
/**
|
|
28
28
|
* Per-stream retention budget to send when the body does not carry one.
|
|
29
|
-
* Defaults to `EXEC_STREAM_BYTE_CAP
|
|
29
|
+
* Defaults to `EXEC_STREAM_BYTE_CAP`, the maximum of a kept tool output.
|
|
30
30
|
*/
|
|
31
31
|
execStreamByteCap?: number;
|
|
32
32
|
}
|
|
@@ -8,9 +8,9 @@ import { z } from "zod";
|
|
|
8
8
|
/** Artifact type inferred from the step subdirectory. */
|
|
9
9
|
export declare const ArtifactTypeSchema: z.ZodEnum<{
|
|
10
10
|
output: "output";
|
|
11
|
-
log: "log";
|
|
12
|
-
figure: "figure";
|
|
13
11
|
script: "script";
|
|
12
|
+
figure: "figure";
|
|
13
|
+
log: "log";
|
|
14
14
|
notebook: "notebook";
|
|
15
15
|
}>;
|
|
16
16
|
export type ArtifactType = z.infer<typeof ArtifactTypeSchema>;
|
|
@@ -22,9 +22,9 @@ export declare const ArtifactManifestEntrySchema: z.ZodObject<{
|
|
|
22
22
|
size: z.ZodNumber;
|
|
23
23
|
type: z.ZodEnum<{
|
|
24
24
|
output: "output";
|
|
25
|
-
log: "log";
|
|
26
|
-
figure: "figure";
|
|
27
25
|
script: "script";
|
|
26
|
+
figure: "figure";
|
|
27
|
+
log: "log";
|
|
28
28
|
notebook: "notebook";
|
|
29
29
|
}>;
|
|
30
30
|
hash: z.ZodOptional<z.ZodString>;
|
package/dist/state/init.js
CHANGED
|
@@ -242,8 +242,8 @@ CREATE INDEX IF NOT EXISTS idx_cortex_regulatory_chunks_metadata
|
|
|
242
242
|
-- the JSON operators retractLastTurn uses work the same on either type.
|
|
243
243
|
--
|
|
244
244
|
-- reported_usage holds a whole turn's TokenUsageRollup — what providers reported
|
|
245
|
-
-- for the turn this row completed —
|
|
246
|
-
--
|
|
245
|
+
-- for the turn this row completed — on the LAST assistant row of an older turn
|
|
246
|
+
-- only. cortex_thread_turns holds the figures of each later turn.
|
|
247
247
|
-- It is NOT the tokens column beside it, and the two must never be read for
|
|
248
248
|
-- each other: tokens is an offline js-tiktoken estimate stamped on EVERY row so
|
|
249
249
|
-- the read path can window by budget without a provider round trip, and it exists
|
|
@@ -283,8 +283,8 @@ CREATE TABLE IF NOT EXISTS messages (
|
|
|
283
283
|
role TEXT,
|
|
284
284
|
content_jsonb JSONB,
|
|
285
285
|
message_envelope JSON,
|
|
286
|
-
-- Versioned AI SDK UIMessage projection
|
|
287
|
-
--
|
|
286
|
+
-- Versioned AI SDK UIMessage projection of one written group, on the first
|
|
287
|
+
-- row of that group. Model-history reads never select it.
|
|
288
288
|
display_envelope JSONB,
|
|
289
289
|
tokens INTEGER NOT NULL,
|
|
290
290
|
reported_usage JSONB,
|
|
@@ -294,6 +294,24 @@ CREATE TABLE IF NOT EXISTS messages (
|
|
|
294
294
|
PRIMARY KEY (thread_id, seq)
|
|
295
295
|
);
|
|
296
296
|
|
|
297
|
+
-- The state of one chat turn, and no message: a close never changes a row of
|
|
298
|
+
-- messages. messages.reported_usage and messages.turn_duration_ms hold the
|
|
299
|
+
-- figures of the older turns, which have no record here.
|
|
300
|
+
CREATE TABLE IF NOT EXISTS cortex_thread_turns (
|
|
301
|
+
thread_id TEXT NOT NULL,
|
|
302
|
+
-- The seq of the user row that opens the turn.
|
|
303
|
+
start_seq BIGINT NOT NULL,
|
|
304
|
+
status TEXT NOT NULL CHECK (status IN ('open', 'done', 'aborted', 'failed')),
|
|
305
|
+
-- A short text from the class of the error, never its message, because each later turn sends the note.
|
|
306
|
+
reason TEXT,
|
|
307
|
+
-- Absent when no provider reported a quantity, the same as messages.reported_usage.
|
|
308
|
+
reported_usage JSONB,
|
|
309
|
+
turn_duration_ms BIGINT,
|
|
310
|
+
opened_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
311
|
+
closed_at TIMESTAMPTZ,
|
|
312
|
+
PRIMARY KEY (thread_id, start_seq)
|
|
313
|
+
);
|
|
314
|
+
|
|
297
315
|
-- Conversation thread metadata — the harness ThreadStore module's table,
|
|
298
316
|
-- one row per conversation thread. Holds the analysis-scope, title, and
|
|
299
317
|
-- soft-delete tombstone the harness messages table deliberately lacks.
|
|
@@ -413,6 +431,23 @@ CREATE TABLE IF NOT EXISTS cortex_ask_grants (
|
|
|
413
431
|
created_at TEXT NOT NULL,
|
|
414
432
|
PRIMARY KEY (analysis_id, user_id, grant_key)
|
|
415
433
|
);
|
|
434
|
+
|
|
435
|
+
-- The kept text of each cut tool result. thread_id is null for a text of a run, thus purgeThread removes
|
|
436
|
+
-- only the texts of chat turns, and purgeAnalysis removes each row by analysis_id.
|
|
437
|
+
CREATE TABLE IF NOT EXISTS cortex_tool_outputs (
|
|
438
|
+
analysis_id TEXT NOT NULL,
|
|
439
|
+
ref TEXT NOT NULL,
|
|
440
|
+
tool_name TEXT NOT NULL,
|
|
441
|
+
tool_call_id TEXT NOT NULL,
|
|
442
|
+
thread_id TEXT,
|
|
443
|
+
content TEXT NOT NULL,
|
|
444
|
+
total_length INTEGER NOT NULL,
|
|
445
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
446
|
+
PRIMARY KEY (analysis_id, ref)
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
CREATE INDEX IF NOT EXISTS cortex_tool_outputs_thread_idx
|
|
450
|
+
ON cortex_tool_outputs (thread_id) WHERE thread_id IS NOT NULL;
|
|
416
451
|
`;
|
|
417
452
|
/**
|
|
418
453
|
* Initialize Cortex state tables. Safe to call on every startup and across
|
|
@@ -78,6 +78,8 @@ const ANALYSIS_KEYED_DELETES = [
|
|
|
78
78
|
{ op: "purgeAnalysis.workingMemory", sql: "DELETE FROM cortex_working_memory WHERE analysis_id = $1" },
|
|
79
79
|
{ op: "purgeAnalysis.asks", sql: "DELETE FROM cortex_asks WHERE analysis_id = $1" },
|
|
80
80
|
{ op: "purgeAnalysis.askGrants", sql: "DELETE FROM cortex_ask_grants WHERE analysis_id = $1" },
|
|
81
|
+
// By its own analysis id, not through the thread rows: a kept text of a run names no thread.
|
|
82
|
+
{ op: "purgeAnalysis.toolOutputs", sql: "DELETE FROM cortex_tool_outputs WHERE analysis_id = $1" },
|
|
81
83
|
{ op: "purgeAnalysis.plans", sql: "DELETE FROM cortex_plans WHERE analysis_id = $1" },
|
|
82
84
|
{ op: "purgeAnalysis.reportVersions", sql: "DELETE FROM cortex_report_versions WHERE analysis_id = $1" },
|
|
83
85
|
{ op: "purgeAnalysis.reportSessionState", sql: "DELETE FROM cortex_report_session_state WHERE analysis_id = $1" },
|
|
@@ -133,6 +135,8 @@ export function createAnalysisPurge({ pool, workflows, logger: injected }) {
|
|
|
133
135
|
// thread is still the analysis's, and a purge takes it too.
|
|
134
136
|
deleteRows(client, "purgeAnalysis.messages", `DELETE FROM messages
|
|
135
137
|
WHERE thread_id IN (SELECT thread_id FROM cortex_analysis_threads WHERE analysis_id = $1)`, analysisId)
|
|
138
|
+
.andThen((messages) => deleteRows(client, "purgeAnalysis.turnRecords", `DELETE FROM cortex_thread_turns
|
|
139
|
+
WHERE thread_id IN (SELECT thread_id FROM cortex_analysis_threads WHERE analysis_id = $1)`, analysisId).map(() => messages))
|
|
136
140
|
.andThen((messages) => deleteRows(client, "purgeAnalysis.threads", "DELETE FROM cortex_analysis_threads WHERE analysis_id = $1", analysisId).map((threads) => ({
|
|
137
141
|
threads,
|
|
138
142
|
messages,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** The Postgres realization of the tool output store of the loop, over `cortex_tool_outputs`. */
|
|
2
|
+
import type { Pool } from "pg";
|
|
3
|
+
import type { ToolOutputStore } from "../loop/tool-output.js";
|
|
4
|
+
export declare function createToolOutputStore(pool: Pool): ToolOutputStore;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** The Postgres realization of the tool output store of the loop, over `cortex_tool_outputs`. */
|
|
2
|
+
import { tryMutation, tryQuery } from "../lib/db-result.js";
|
|
3
|
+
function toKeptToolOutput(row) {
|
|
4
|
+
return {
|
|
5
|
+
analysisId: row.analysis_id,
|
|
6
|
+
ref: row.ref,
|
|
7
|
+
toolName: row.tool_name,
|
|
8
|
+
toolCallId: row.tool_call_id,
|
|
9
|
+
...(row.thread_id === null ? {} : { threadId: row.thread_id }),
|
|
10
|
+
content: row.content,
|
|
11
|
+
totalLength: row.total_length,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function createToolOutputStore(pool) {
|
|
15
|
+
return {
|
|
16
|
+
put: (output) => tryMutation("toolOutputs.put", () => pool.query(
|
|
17
|
+
// The update sets no `created_at`, thus the row keeps the time of its first put.
|
|
18
|
+
`INSERT INTO cortex_tool_outputs (analysis_id, ref, tool_name, tool_call_id, thread_id, content, total_length)
|
|
19
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
20
|
+
ON CONFLICT (analysis_id, ref) DO UPDATE SET
|
|
21
|
+
tool_name = EXCLUDED.tool_name,
|
|
22
|
+
tool_call_id = EXCLUDED.tool_call_id,
|
|
23
|
+
thread_id = EXCLUDED.thread_id,
|
|
24
|
+
content = EXCLUDED.content,
|
|
25
|
+
total_length = EXCLUDED.total_length`, [output.analysisId, output.ref, output.toolName, output.toolCallId, output.threadId ?? null, output.content, output.totalLength])).map(() => undefined),
|
|
26
|
+
get: (analysisId, ref) => tryQuery("toolOutputs.get", () => pool.query(`SELECT analysis_id, ref, tool_name, tool_call_id, thread_id, content, total_length
|
|
27
|
+
FROM cortex_tool_outputs
|
|
28
|
+
WHERE analysis_id = $1 AND ref = $2`, [analysisId, ref])).map(({ rows }) => (rows[0] === undefined ? null : toKeptToolOutput(rows[0]))),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -26,6 +26,7 @@ import type { RunAuthorization, RunAuthorizer } from "../execution/run-authorize
|
|
|
26
26
|
import type { StagedInput } from "../execution/staged-input.js";
|
|
27
27
|
import type { SandboxAgentDeps } from "../agents/sandbox/shared.js";
|
|
28
28
|
import type { BioToolKeys } from "../tools/bio/keys.js";
|
|
29
|
+
import type { ToolOutputStore } from "../loop/tool-output.js";
|
|
29
30
|
import type { DbError } from "../lib/db-result.js";
|
|
30
31
|
import { type GateRefusal } from "../lib/hooks.js";
|
|
31
32
|
import type { Logger } from "../lib/logger.js";
|
|
@@ -63,6 +64,8 @@ export interface DataProfileDeps extends EnvironmentStorePaths {
|
|
|
63
64
|
readonly skillsDir: string;
|
|
64
65
|
/** LLM usage-accounting seam for the profiler agent loop; omitted falls back to the no-op recorder. */
|
|
65
66
|
readonly usageRecorder?: UsageRecorder;
|
|
67
|
+
/** The store of the profiler loop and of its read tool. */
|
|
68
|
+
readonly toolOutputStore?: ToolOutputStore;
|
|
66
69
|
/**
|
|
67
70
|
* The farm-extension seam of the embedder. Bound, it rides into the
|
|
68
71
|
* profiler agent deps, and the substrate attaches `link_packages`. Thus
|
|
@@ -271,6 +271,7 @@ export function profilerSandboxAgentDeps(deps, step) {
|
|
|
271
271
|
...(deps.imagePackagesFile ? { imagePackagesFile: deps.imagePackagesFile } : {}),
|
|
272
272
|
...(deps.refStorePath ? { refStorePath: deps.refStorePath } : {}),
|
|
273
273
|
...(deps.extendAnalysisFarm ? { extendAnalysisFarm: deps.extendAnalysisFarm } : {}),
|
|
274
|
+
...(deps.toolOutputStore ? { toolOutputStore: deps.toolOutputStore } : {}),
|
|
274
275
|
bioKeys: deps.bioKeys,
|
|
275
276
|
step,
|
|
276
277
|
};
|
|
@@ -548,6 +549,7 @@ export async function runDataProfileBody(input, deps) {
|
|
|
548
549
|
runStep: durableStep,
|
|
549
550
|
resolved: () => accepted !== null,
|
|
550
551
|
usageRecorder: deps.usageRecorder,
|
|
552
|
+
toolOutputStore: deps.toolOutputStore,
|
|
551
553
|
isFatalLoopError: (err) => err instanceof DBOSErrors.DBOSWorkflowCancelledError,
|
|
552
554
|
}, {
|
|
553
555
|
tools: [submitProfileTool],
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { Pool } from "pg";
|
|
2
2
|
import { type AgentSession } from "../auth/types.js";
|
|
3
|
+
import type { UsageRecorder } from "../billing/usage-recorder.js";
|
|
3
4
|
import type { ResourcePolicy, ResourceSpec } from "../config/resource-limits.js";
|
|
4
5
|
import type { Logger } from "../lib/logger.js";
|
|
6
|
+
import { type AgentRunUsage } from "../loop/metrics.js";
|
|
5
7
|
import { type ChatProvider } from "../providers/types.js";
|
|
6
8
|
import type { CheckedPackage } from "./sandbox/list-available-packages.js";
|
|
7
9
|
export declare const AD_HOC_ROUTER_AGENT_ID = "adhoc-router";
|
|
@@ -48,6 +50,8 @@ export interface AdHocRouterDeps {
|
|
|
48
50
|
* the entries reach the link pass as the model wrote them.
|
|
49
51
|
*/
|
|
50
52
|
readonly resolvePackages?: (names: readonly string[]) => Promise<readonly CheckedPackage[] | null>;
|
|
53
|
+
/** Falls back to the no-op recorder when omitted. */
|
|
54
|
+
readonly usageRecorder?: UsageRecorder;
|
|
51
55
|
}
|
|
52
56
|
export declare function defaultAdHocResources(policy?: ResourcePolicy): ResourceSpec;
|
|
53
57
|
export declare function validAdHocResources(value: unknown, policy?: ResourcePolicy): ResourceSpec | null;
|
|
@@ -56,4 +60,8 @@ export declare function routeAdHocRequest(deps: AdHocRouterDeps, input: {
|
|
|
56
60
|
request: string;
|
|
57
61
|
session: AgentSession;
|
|
58
62
|
signal: AbortSignal;
|
|
63
|
+
/** The router call folds its usage into this, so the turn total includes it. */
|
|
64
|
+
readonly turnUsage?: AgentRunUsage;
|
|
65
|
+
/** Carried into the record key of the router usage entry. */
|
|
66
|
+
readonly invocationId?: string;
|
|
59
67
|
}): Promise<AdHocRoute>;
|
|
@@ -3,8 +3,11 @@ import { z } from "zod";
|
|
|
3
3
|
import { PLANNABLE_AGENT_CATALOG } from "../agents/sandbox-catalog.js";
|
|
4
4
|
import { forSubAgent } from "../auth/types.js";
|
|
5
5
|
import { DATA_PROFILE_ORIENTATION_MAX_CHARS, buildDataProfileOrientation } from "../app/data-profile-orientation.js";
|
|
6
|
+
import { createNoopUsageRecorder } from "../billing/noop-usage-recorder.js";
|
|
6
7
|
import { createNoopLogger } from "../lib/console-logger.js";
|
|
7
8
|
import { unwrapOrThrow } from "../lib/result.js";
|
|
9
|
+
import { countChatTokens } from "../loop/metrics.js";
|
|
10
|
+
import { accountForChatCall } from "../loop/run-agent.js";
|
|
8
11
|
import { packagesSection, resourceEstimationSection } from "../prompts/planner.js";
|
|
9
12
|
import { effectiveDeadlineMs } from "../providers/types.js";
|
|
10
13
|
import { formatQuery, parseQuery } from "../sandbox/package-identity.js";
|
|
@@ -12,6 +15,8 @@ import { loadDataProfileStatus } from "../state/index.js";
|
|
|
12
15
|
export const AD_HOC_ROUTER_AGENT_ID = "adhoc-router";
|
|
13
16
|
export const AD_HOC_ROUTER_TIMEOUT_MS = 10_000;
|
|
14
17
|
export const AD_HOC_FALLBACK_AGENT_ID = "scientific-executor";
|
|
18
|
+
/** Must differ from a loop step name such as `llm-0`, since both share the usage-record key space. */
|
|
19
|
+
const AD_HOC_ROUTE_CALL_NAME = "adhoc-route";
|
|
15
20
|
const resourcesSchema = z.object({
|
|
16
21
|
cpu: z.number().positive(),
|
|
17
22
|
memoryGb: z.number().positive(),
|
|
@@ -152,6 +157,7 @@ function routeTool() {
|
|
|
152
157
|
}
|
|
153
158
|
export async function routeAdHocRequest(deps, input) {
|
|
154
159
|
const logger = (deps.logger ?? createNoopLogger()).named("adhoc-router").with({ analysisId: input.analysisId, model: deps.model });
|
|
160
|
+
const routerSession = forSubAgent(input.session, AD_HOC_ROUTER_AGENT_ID);
|
|
155
161
|
const catalog = PLANNABLE_AGENT_CATALOG.map((agent) => `- ${agent.id}: capabilities [${agent.capabilities.join(", ")}]; suitable for [${agent.suitableFor.join(", ")}]`).join("\n");
|
|
156
162
|
const orientation = await profileOrientation(deps.pool, input.analysisId, logger);
|
|
157
163
|
const controller = new AbortController();
|
|
@@ -160,7 +166,8 @@ export async function routeAdHocRequest(deps, input) {
|
|
|
160
166
|
let raw;
|
|
161
167
|
let failure;
|
|
162
168
|
try {
|
|
163
|
-
const response = unwrapOrThrow(await deps.provider
|
|
169
|
+
const response = unwrapOrThrow(await deps.provider
|
|
170
|
+
.chat({
|
|
164
171
|
system: [
|
|
165
172
|
"Select exactly one specialist for a targeted one-step analysis, estimate its sandbox resources, and name the packages that the step imports.",
|
|
166
173
|
"Choose only from the supplied catalog. Do not create a plan, reject the request, or select scientific-executor.",
|
|
@@ -179,7 +186,19 @@ export async function routeAdHocRequest(deps, input) {
|
|
|
179
186
|
// No forced tool choice: some Claude models reject it with a
|
|
180
187
|
// 400. A reply without the call falls back below as `malformed`.
|
|
181
188
|
tools: routeTool(),
|
|
182
|
-
},
|
|
189
|
+
}, routerSession, signal)
|
|
190
|
+
.map(countChatTokens(AD_HOC_ROUTER_AGENT_ID)));
|
|
191
|
+
// A failed call throws at unwrapOrThrow above, so no usage is recorded.
|
|
192
|
+
accountForChatCall(response, {
|
|
193
|
+
session: routerSession,
|
|
194
|
+
agentId: AD_HOC_ROUTER_AGENT_ID,
|
|
195
|
+
callPath: routerSession.provenance.callPath,
|
|
196
|
+
stepName: AD_HOC_ROUTE_CALL_NAME,
|
|
197
|
+
...(input.invocationId === undefined ? {} : { invocationId: input.invocationId }),
|
|
198
|
+
usageRecorder: deps.usageRecorder ?? createNoopUsageRecorder(),
|
|
199
|
+
logger,
|
|
200
|
+
rollups: input.turnUsage === undefined ? [] : [input.turnUsage],
|
|
201
|
+
});
|
|
183
202
|
const call = Array.isArray(response.message.content)
|
|
184
203
|
? response.message.content.find((part) => part.type === "tool-call" && part.toolName === "submit_route")
|
|
185
204
|
: undefined;
|
|
@@ -26,7 +26,7 @@ type ShowUserOutput = {
|
|
|
26
26
|
id: string;
|
|
27
27
|
};
|
|
28
28
|
export declare const showUserTool: import("../define-tool.js").Tool<{
|
|
29
|
-
kind: "code" | "markdown" | "
|
|
29
|
+
kind: "code" | "markdown" | "echart" | "svg" | "table" | "structure";
|
|
30
30
|
title?: string | undefined;
|
|
31
31
|
spec?: Record<string, unknown> | undefined;
|
|
32
32
|
dataPath?: string | undefined;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* hoc analyses. Both modes launch the ordinary executeAnalysis workflow.
|
|
4
4
|
*/
|
|
5
5
|
import type { Pool } from "pg";
|
|
6
|
+
import type { UsageRecorder } from "../billing/usage-recorder.js";
|
|
6
7
|
import type { EnvironmentStorePaths } from "../config/environment-stores.js";
|
|
7
8
|
import type { ResourcePolicy } from "../config/resource-limits.js";
|
|
8
9
|
import type { RunAuthorizer } from "../execution/run-authorizer.js";
|
|
@@ -29,6 +30,8 @@ export interface ExecuteAnalysisToolDeps extends Pick<EnvironmentStorePaths, "fa
|
|
|
29
30
|
* run reserves anything. Without it, the link pass returns at once.
|
|
30
31
|
*/
|
|
31
32
|
readonly extendAnalysisFarm?: ExtendAnalysisFarm;
|
|
33
|
+
/** Falls back to the no-op recorder when omitted. */
|
|
34
|
+
readonly usageRecorder?: UsageRecorder;
|
|
32
35
|
}
|
|
33
36
|
export declare class PlanNotFoundError extends Error {
|
|
34
37
|
constructor(planId: string);
|
|
@@ -296,7 +296,15 @@ async function persistedAdHocPlan(deps, args) {
|
|
|
296
296
|
resourcePolicy: deps.resourcePolicy,
|
|
297
297
|
logger: deps.logger,
|
|
298
298
|
...(resolvePackages ? { resolvePackages } : {}),
|
|
299
|
-
|
|
299
|
+
...(deps.usageRecorder ? { usageRecorder: deps.usageRecorder } : {}),
|
|
300
|
+
}, {
|
|
301
|
+
analysisId: args.analysisId,
|
|
302
|
+
request: args.request,
|
|
303
|
+
session: args.ctx.session,
|
|
304
|
+
signal: args.ctx.signal,
|
|
305
|
+
...(args.ctx.turnUsage ? { turnUsage: args.ctx.turnUsage } : {}),
|
|
306
|
+
invocationId: args.ctx.invocationId,
|
|
307
|
+
});
|
|
300
308
|
const candidate = buildAdHocPlan(args.request, route);
|
|
301
309
|
unwrapOrThrow(await upsertPlan(deps.pool, { planId: args.planId, analysisId: args.analysisId, plan: candidate }));
|
|
302
310
|
const stored = unwrapOrThrow(await loadPlan(deps.pool, args.planId, { analysisId: args.analysisId }));
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `read_tool_output` — reads the kept text of a tool result that the loop cut, by a window or by a pattern.
|
|
3
|
+
* Each result stays under the cap of the loop, thus the loop never cuts a result of this tool.
|
|
4
|
+
*/
|
|
5
|
+
import { type ToolOutputStore } from "../loop/tool-output.js";
|
|
6
|
+
import { type Tool } from "./define-tool.js";
|
|
7
|
+
export declare function createReadToolOutputTool(store: ToolOutputStore): Tool;
|