@inflexa-ai/harness 0.14.1 → 0.15.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 -1
- package/dist/agents/conversation-agent.d.ts +7 -0
- package/dist/agents/conversation-agent.js +5 -3
- package/dist/app/synthesize-run.d.ts +3 -0
- package/dist/app/synthesize-run.js +2 -1
- package/dist/billing/noop-usage-recorder.d.ts +7 -0
- package/dist/billing/noop-usage-recorder.js +10 -0
- package/dist/billing/usage-recorder.d.ts +63 -0
- package/dist/billing/usage-recorder.js +15 -0
- package/dist/contracts/chat-events.d.ts +44 -3
- package/dist/contracts/chat-parts.d.ts +38 -2
- package/dist/contracts/chat-parts.js +1 -1
- package/dist/contracts/data-profile.d.ts +26 -0
- package/dist/contracts/data-profile.js +26 -0
- package/dist/contracts/index.d.ts +3 -1
- package/dist/contracts/index.js +1 -0
- package/dist/contracts/message.d.ts +21 -1
- package/dist/contracts/part-registry.js +1 -0
- package/dist/contracts/schemas/chat-events.d.ts +48 -2
- package/dist/contracts/schemas/chat-events.js +8 -1
- package/dist/contracts/schemas/chat-parts.d.ts +46 -3
- package/dist/contracts/schemas/chat-parts.js +13 -0
- package/dist/contracts/schemas/index.d.ts +2 -1
- package/dist/contracts/schemas/index.js +2 -1
- package/dist/contracts/schemas/usage.d.ts +11 -0
- package/dist/contracts/schemas/usage.js +18 -0
- package/dist/contracts/usage.d.ts +51 -0
- package/dist/contracts/usage.js +41 -0
- package/dist/execution/artifact-metadata.d.ts +3 -0
- package/dist/execution/artifact-metadata.js +1 -0
- package/dist/execution/dbos-workflow-purger.d.ts +30 -0
- package/dist/execution/dbos-workflow-purger.js +193 -0
- package/dist/execution/post-step-pipeline.d.ts +3 -0
- package/dist/execution/post-step-pipeline.js +2 -0
- package/dist/execution/reconcile-manifest.js +28 -15
- package/dist/execution/report-runner.d.ts +16 -0
- package/dist/execution/report-runner.js +4 -0
- package/dist/execution/run-synthesis.d.ts +3 -0
- package/dist/execution/run-synthesis.js +2 -0
- package/dist/execution/step-summary.d.ts +3 -0
- package/dist/execution/step-summary.js +1 -0
- package/dist/execution/workflow-purger.d.ts +38 -0
- package/dist/execution/workflow-purger.js +24 -0
- package/dist/index.d.ts +25 -3
- package/dist/index.js +28 -1
- package/dist/lib/metrics.js +2 -1
- package/dist/loop/metrics.d.ts +18 -0
- package/dist/loop/metrics.js +18 -1
- package/dist/loop/run-agent.d.ts +35 -0
- package/dist/loop/run-agent.js +149 -23
- package/dist/loop/run-to-terminal.d.ts +5 -2
- package/dist/loop/run-to-terminal.js +36 -2
- package/dist/loop/tool-detail.d.ts +54 -0
- package/dist/loop/tool-detail.js +105 -0
- package/dist/loop/tool-outcome.d.ts +21 -0
- package/dist/loop/tool-outcome.js +25 -0
- package/dist/loop/types.d.ts +15 -1
- package/dist/memory/content-to-cortex.d.ts +28 -4
- package/dist/memory/content-to-cortex.js +70 -14
- package/dist/memory/thread-history.d.ts +21 -1
- package/dist/memory/thread-history.js +29 -7
- package/dist/memory/thread-store.d.ts +65 -8
- package/dist/memory/thread-store.js +81 -17
- package/dist/provenance/collector.d.ts +5 -3
- package/dist/provenance/collector.js +5 -3
- package/dist/providers/ai-sdk.d.ts +18 -0
- package/dist/providers/ai-sdk.js +129 -16
- package/dist/providers/anthropic.d.ts +2 -0
- package/dist/providers/anthropic.js +1 -0
- package/dist/providers/streaming-chat.js +5 -0
- package/dist/providers/types.d.ts +23 -0
- package/dist/providers/types.js +1 -0
- package/dist/runtime/assemble.d.ts +25 -8
- package/dist/runtime/assemble.js +7 -4
- package/dist/sandbox/sandbox-step-translate.d.ts +22 -1
- package/dist/sandbox/sandbox-step-translate.js +23 -36
- package/dist/schemas/run-synthesis.d.ts +2 -2
- package/dist/state/index.d.ts +2 -0
- package/dist/state/index.js +3 -0
- package/dist/state/init.js +28 -0
- package/dist/state/purge-analysis.d.ts +74 -0
- package/dist/state/purge-analysis.js +205 -0
- package/dist/state/vector-store.d.ts +6 -0
- package/dist/state/vector-store.js +22 -2
- package/dist/tasks/data-profile-activity.d.ts +14 -2
- package/dist/tasks/data-profile-activity.js +1 -1
- package/dist/tasks/data-profile.d.ts +3 -0
- package/dist/tasks/data-profile.js +9 -3
- package/dist/tools/bio/pubmed.js +15 -0
- package/dist/tools/bio/search-gene.js +12 -0
- package/dist/tools/define-tool.d.ts +41 -3
- package/dist/tools/define-tool.js +4 -1
- package/dist/tools/detail-resolver.d.ts +35 -0
- package/dist/tools/detail-resolver.js +39 -0
- package/dist/tools/execute-analysis.js +3 -0
- package/dist/tools/iterate-report.d.ts +3 -0
- package/dist/tools/iterate-report.js +3 -0
- package/dist/tools/memory/update-working-memory.js +8 -0
- package/dist/tools/research/generate-analogy-report.d.ts +3 -0
- package/dist/tools/research/generate-analogy-report.js +6 -0
- package/dist/tools/research/generate-plan.d.ts +3 -0
- package/dist/tools/research/generate-plan.js +6 -0
- package/dist/tools/research/inspect-run.js +4 -0
- package/dist/tools/research/literature-reviewer.d.ts +3 -0
- package/dist/tools/research/literature-reviewer.js +6 -0
- package/dist/tools/workspace/edit-file.js +2 -0
- package/dist/tools/workspace/execute-command.js +25 -0
- package/dist/tools/workspace/grep.js +3 -0
- package/dist/tools/workspace/list-files.js +2 -0
- package/dist/tools/workspace/read-file.js +7 -0
- package/dist/tools/workspace/workspace-search.js +1 -0
- package/dist/tools/workspace/write-file.js +3 -0
- package/dist/workflows/execute-analysis.d.ts +7 -0
- package/dist/workflows/execute-analysis.js +31 -2
- package/dist/workflows/execute-target-assessment.d.ts +3 -0
- package/dist/workflows/sandbox-step.d.ts +23 -0
- package/dist/workflows/sandbox-step.js +33 -2
- package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.d.ts +3 -0
- package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.js +1 -0
- package/package.json +2 -2
|
@@ -38,6 +38,8 @@ 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
40
|
import type { Logger } from "../lib/logger.js";
|
|
41
|
+
import type { UsageRecorder } from "../billing/usage-recorder.js";
|
|
42
|
+
import type { AgentRunUsage } from "../loop/metrics.js";
|
|
41
43
|
export interface ReportRunnerDeps {
|
|
42
44
|
/** Operational logging seam; omitted falls back to no-op. */
|
|
43
45
|
readonly logger?: Logger;
|
|
@@ -50,6 +52,8 @@ export interface ReportRunnerDeps {
|
|
|
50
52
|
/** Skills root; the report-builder gets read-only `report-html` skill tools. */
|
|
51
53
|
readonly skillsDir: string;
|
|
52
54
|
readonly chrome: ChromeConfig;
|
|
55
|
+
/** LLM usage-accounting seam for the report-builder loop; omitted falls back to the no-op recorder. */
|
|
56
|
+
readonly usageRecorder?: UsageRecorder;
|
|
53
57
|
}
|
|
54
58
|
export interface ReportRunnerOptions {
|
|
55
59
|
readonly resourceId: string;
|
|
@@ -75,6 +79,18 @@ export interface ReportRunnerOptions {
|
|
|
75
79
|
readonly signal: AbortSignal;
|
|
76
80
|
/** Event sink — forwarded to the agent loop. */
|
|
77
81
|
readonly emit: EmitFn;
|
|
82
|
+
/**
|
|
83
|
+
* The calling turn's usage accumulator (`ctx.turnUsage`), so the
|
|
84
|
+
* report-builder loop's tokens land in the turn total its root reports.
|
|
85
|
+
*/
|
|
86
|
+
readonly turnUsage?: AgentRunUsage;
|
|
87
|
+
/**
|
|
88
|
+
* The dispatching tool call's id (`ctx.invocationId`), which discriminates
|
|
89
|
+
* the builder loop's usage record keys from those of a sibling iteration
|
|
90
|
+
* dispatched in the same round — same frame, same call path, same
|
|
91
|
+
* loop-local step names.
|
|
92
|
+
*/
|
|
93
|
+
readonly invocationId?: string;
|
|
78
94
|
}
|
|
79
95
|
export type ReportRunnerResult = {
|
|
80
96
|
ok: true;
|
|
@@ -148,6 +148,10 @@ export async function runReportIteration(deps, opts) {
|
|
|
148
148
|
emit: opts.emit,
|
|
149
149
|
runStep: passthroughStep,
|
|
150
150
|
resolved: () => outcome !== undefined,
|
|
151
|
+
usageRecorder: deps.usageRecorder,
|
|
152
|
+
// Fold the builder's calls into the turn total the root loop reports.
|
|
153
|
+
turnUsage: opts.turnUsage,
|
|
154
|
+
invocationId: opts.invocationId,
|
|
151
155
|
}, {
|
|
152
156
|
tools: [buildReportTool, submitReportTool],
|
|
153
157
|
nudge: "You stopped without calling submit_report, so this report version " +
|
|
@@ -27,6 +27,7 @@ import { type RunSynthesis } from "../schemas/run-synthesis.js";
|
|
|
27
27
|
import type { StepSummary } from "../schemas/step-summary.js";
|
|
28
28
|
import type { ChatDataPart, EmitFn } from "../loop/types.js";
|
|
29
29
|
import type { ChatProvider } from "../providers/types.js";
|
|
30
|
+
import type { UsageRecorder } from "../billing/usage-recorder.js";
|
|
30
31
|
import type { RunSession } from "../auth/types.js";
|
|
31
32
|
import { type Tool } from "../tools/define-tool.js";
|
|
32
33
|
import type { BioToolKeys } from "../tools/bio/keys.js";
|
|
@@ -66,6 +67,8 @@ export interface GenerateRunSynthesisInput {
|
|
|
66
67
|
readonly model: string;
|
|
67
68
|
/** API keys for the bio/chem tools the embedded literature reviewer uses. */
|
|
68
69
|
readonly bioKeys: BioToolKeys;
|
|
70
|
+
/** LLM usage-accounting seam for the synthesizer + reviewer loops; omitted falls back to the no-op recorder. */
|
|
71
|
+
readonly usageRecorder?: UsageRecorder;
|
|
69
72
|
/** Step summaries from the completed run. Non-empty. */
|
|
70
73
|
readonly summaries: readonly StepSummary[];
|
|
71
74
|
/** Plan analytical narrative for context. */
|
|
@@ -349,6 +349,7 @@ export async function generateRunSynthesis(input) {
|
|
|
349
349
|
provider: input.provider,
|
|
350
350
|
model: input.model,
|
|
351
351
|
bioKeys: input.bioKeys,
|
|
352
|
+
usageRecorder: input.usageRecorder,
|
|
352
353
|
});
|
|
353
354
|
const validateTool = buildValidateTool(innerCtx);
|
|
354
355
|
const submitTool = buildSubmitTool(holder, innerCtx);
|
|
@@ -370,6 +371,7 @@ export async function generateRunSynthesis(input) {
|
|
|
370
371
|
emit,
|
|
371
372
|
runStep: passthroughStep,
|
|
372
373
|
resolved: () => holder.outcome !== null,
|
|
374
|
+
usageRecorder: input.usageRecorder,
|
|
373
375
|
};
|
|
374
376
|
await runToTerminal(agent, [{ role: "user", content: prompt }], input.session, loopDeps, {
|
|
375
377
|
tools: [submitTool, blockerTool],
|
|
@@ -30,9 +30,12 @@ import type { AgentChat } from "../providers/types.js";
|
|
|
30
30
|
import type { WorkspaceFilesystem } from "../workspace/filesystem.js";
|
|
31
31
|
import { type StepSummary } from "../schemas/step-summary.js";
|
|
32
32
|
import type { Logger } from "../lib/logger.js";
|
|
33
|
+
import type { UsageRecorder } from "../billing/usage-recorder.js";
|
|
33
34
|
export interface GenerateStepSummaryOptions {
|
|
34
35
|
/** Operational logging seam; omitted falls back to no-op. */
|
|
35
36
|
readonly logger?: Logger;
|
|
37
|
+
/** LLM usage-accounting seam for the summary loop; omitted falls back to the no-op recorder. */
|
|
38
|
+
readonly usageRecorder?: UsageRecorder;
|
|
36
39
|
readonly provider: AgentChat;
|
|
37
40
|
readonly session: AgentSession;
|
|
38
41
|
readonly modelId: string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkflowPurger — the durability-engine seam for reclaiming workflow rows.
|
|
3
|
+
*
|
|
4
|
+
* Most of what an analysis stores lives in the durability engine's own ledger —
|
|
5
|
+
* sandbox-agent step outputs, the run-event streams, workflow inputs — not in the
|
|
6
|
+
* harness's `cortex_*` tables, so removing an analysis has to reach that ledger.
|
|
7
|
+
* The engine is quarantined out of the state layer, the tools, and the loop
|
|
8
|
+
* (`RunLauncher` holds that line for the launch direction); this seam is the
|
|
9
|
+
* reclaim direction of the same quarantine. It speaks only in workflow ids, so a
|
|
10
|
+
* caller never names an engine type.
|
|
11
|
+
*
|
|
12
|
+
* Cancellation is a separate verb from deletion, and a caller uses it first:
|
|
13
|
+
* deleting the status row of a running workflow does not stop the executor
|
|
14
|
+
* running it, and that executor goes on writing rows behind the delete. A caller
|
|
15
|
+
* that cannot cancel must not proceed to a delete whose completeness it can no
|
|
16
|
+
* longer claim.
|
|
17
|
+
*
|
|
18
|
+
* Absence is a normal outcome throughout. A host may purge from a process that
|
|
19
|
+
* never launched the durable runtime, and the engine creates its schema at first
|
|
20
|
+
* launch — so a missing ledger means "nothing to purge", not a failure. Unknown
|
|
21
|
+
* ids are likewise ignored rather than rejected, which is what makes a re-run of
|
|
22
|
+
* an already-reclaimed purge succeed.
|
|
23
|
+
*/
|
|
24
|
+
import type { ResultAsync } from "neverthrow";
|
|
25
|
+
import type { DbError } from "../lib/db-result.js";
|
|
26
|
+
export interface WorkflowPurger {
|
|
27
|
+
/** Workflow ids in a given id namespace (e.g. `dataprofile:{analysisId}:`). Empty when the ledger has no schema yet. */
|
|
28
|
+
findByIdPrefix(prefix: string): ResultAsync<string[], DbError>;
|
|
29
|
+
/** Cancel the given workflows so no executor keeps writing behind a purge. Unknown ids are ignored. */
|
|
30
|
+
cancel(workflowIds: readonly string[]): ResultAsync<void, DbError>;
|
|
31
|
+
/**
|
|
32
|
+
* Delete the given workflows, and their descendants when `includeDescendants`.
|
|
33
|
+
* Resolves to how many workflows the delete targeted, counted immediately before
|
|
34
|
+
* it — a post-fact tally is not available, because the engine owns the delete and
|
|
35
|
+
* reports no count of its own.
|
|
36
|
+
*/
|
|
37
|
+
deleteWorkflows(workflowIds: readonly string[], includeDescendants?: boolean): ResultAsync<number, DbError>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkflowPurger — the durability-engine seam for reclaiming workflow rows.
|
|
3
|
+
*
|
|
4
|
+
* Most of what an analysis stores lives in the durability engine's own ledger —
|
|
5
|
+
* sandbox-agent step outputs, the run-event streams, workflow inputs — not in the
|
|
6
|
+
* harness's `cortex_*` tables, so removing an analysis has to reach that ledger.
|
|
7
|
+
* The engine is quarantined out of the state layer, the tools, and the loop
|
|
8
|
+
* (`RunLauncher` holds that line for the launch direction); this seam is the
|
|
9
|
+
* reclaim direction of the same quarantine. It speaks only in workflow ids, so a
|
|
10
|
+
* caller never names an engine type.
|
|
11
|
+
*
|
|
12
|
+
* Cancellation is a separate verb from deletion, and a caller uses it first:
|
|
13
|
+
* deleting the status row of a running workflow does not stop the executor
|
|
14
|
+
* running it, and that executor goes on writing rows behind the delete. A caller
|
|
15
|
+
* that cannot cancel must not proceed to a delete whose completeness it can no
|
|
16
|
+
* longer claim.
|
|
17
|
+
*
|
|
18
|
+
* Absence is a normal outcome throughout. A host may purge from a process that
|
|
19
|
+
* never launched the durable runtime, and the engine creates its schema at first
|
|
20
|
+
* launch — so a missing ledger means "nothing to purge", not a failure. Unknown
|
|
21
|
+
* ids are likewise ignored rather than rejected, which is what makes a re-run of
|
|
22
|
+
* an already-reclaimed purge succeed.
|
|
23
|
+
*/
|
|
24
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export { createNoopBillingResolver } from "./billing/noop-resolver.js";
|
|
|
16
16
|
export type { ResolveBilling, ResolvableSession, BillingMap, BillingHeaders, BillingFetchResult } from "./billing/resolver.js";
|
|
17
17
|
export { createNoopRunCharge } from "./billing/noop-run-charge.js";
|
|
18
18
|
export type { RunCharge } from "./billing/run-charge.js";
|
|
19
|
+
export { createNoopUsageRecorder } from "./billing/noop-usage-recorder.js";
|
|
20
|
+
export type { UsageRecorder, LlmUsageRecord } from "./billing/usage-recorder.js";
|
|
19
21
|
export { createNoopArtifactRegistry } from "./execution/noop-artifact-registry.js";
|
|
20
22
|
export type { ArtifactRegistry, ArtifactRegistrationInput, ArtifactSyncInput, ExternalRegistrationResult } from "./execution/artifact-registry.js";
|
|
21
23
|
export type { ArtifactManifestEntry } from "./schemas/artifact-manifest.js";
|
|
@@ -24,6 +26,9 @@ export { UnavailablePreviewPublisher } from "./tools/report/preview-publisher.js
|
|
|
24
26
|
export type { PreviewPublisher, PreviewMintResult } from "./tools/report/preview-publisher.js";
|
|
25
27
|
export { createDbosRunLauncher } from "./execution/dbos-run-launcher.js";
|
|
26
28
|
export type { RunLauncher, LaunchOptions } from "./execution/run-launcher.js";
|
|
29
|
+
export { createDbosWorkflowPurger } from "./execution/dbos-workflow-purger.js";
|
|
30
|
+
export type { DbosWorkflowPurgerDeps } from "./execution/dbos-workflow-purger.js";
|
|
31
|
+
export type { WorkflowPurger } from "./execution/workflow-purger.js";
|
|
27
32
|
export { defineTool, isToolError } from "./tools/define-tool.js";
|
|
28
33
|
export type { Tool, ToolDefinition, ToolContext, ToolError } from "./tools/define-tool.js";
|
|
29
34
|
export { createAskGateway } from "./tools/approval/gateway.js";
|
|
@@ -39,7 +44,7 @@ export type { AgentSession, RequestSession, RunSession, Identity, Scope, Credent
|
|
|
39
44
|
export { makeLocalAuth } from "./auth/local-auth-context.js";
|
|
40
45
|
export { createAnthropicProvider } from "./providers/anthropic.js";
|
|
41
46
|
export type { AnthropicProviderDeps } from "./providers/anthropic.js";
|
|
42
|
-
export { createConfiguredAiSdkProvider } from "./providers/ai-sdk.js";
|
|
47
|
+
export { createConfiguredAiSdkProvider, DEFAULT_MAX_OUTPUT_TOKENS } from "./providers/ai-sdk.js";
|
|
43
48
|
export type { AiSdkProviderConfig, ConfiguredAiSdkProviderDeps } from "./providers/ai-sdk.js";
|
|
44
49
|
export { createEmbeddingProvider } from "./providers/embedding.js";
|
|
45
50
|
export type { EmbeddingProviderDeps } from "./providers/embedding.js";
|
|
@@ -56,10 +61,14 @@ export { createThreadHistory } from "./memory/thread-history.js";
|
|
|
56
61
|
export type { ThreadHistory, StoredMessage, MessagePage, RetractOutcome } from "./memory/thread-history.js";
|
|
57
62
|
export { syntheticUserMessage, syntheticRecordMessage, isSyntheticUserMessage, isSyntheticRecordMessage } from "./memory/ai-sdk-message-storage.js";
|
|
58
63
|
export { contentToCortexMessages } from "./memory/content-to-cortex.js";
|
|
64
|
+
export type { ContentToCortexOptions } from "./memory/content-to-cortex.js";
|
|
59
65
|
export { createCardResolver } from "./memory/reconstruct-cards.js";
|
|
60
66
|
export type { ToolCardResolver, StoredToolCallForCard } from "./memory/reconstruct-cards.js";
|
|
61
|
-
export
|
|
62
|
-
export type {
|
|
67
|
+
export { createDetailResolver } from "./tools/detail-resolver.js";
|
|
68
|
+
export type { ToolDetailResolver } from "./tools/detail-resolver.js";
|
|
69
|
+
export type { CortexChatEvent, TextDeltaEvent, ToolStartedEvent, ToolFinishedEvent, ToolOutcome, ToolCallDetail, FinishEvent, ChatErrorEvent, } from "./contracts/chat-events.js";
|
|
70
|
+
export type { TokenUsageRollup } from "./contracts/usage.js";
|
|
71
|
+
export type { CortexChatPart, PresentationPart, PresentationContent, PlanPart, RunCardPart, FileReferencePart, FileReferenceEntry, RunStartedPart, DagStatePart, DagStepState, StepStatus, StepActivityPart, StepPhase, StepFileTreePart, FileTreeEntry, StepOutputPart, StepOutputFile, StepSummaryPart, StepUsagePart, StepBlockedPart, RunSynthesisPart, SynthesizedFinding, BiologicalTheme, SynthesisProgressPart, SynthesisPhase, RunCompletedPart, RunCompletedFinding, RunFailedPart, PreviewPart, DataPreviewFailedPart, } from "./contracts/chat-parts.js";
|
|
63
72
|
export { PART_REGISTRY, isTransient, isReconciling, isSidebarPart } from "./contracts/part-registry.js";
|
|
64
73
|
export type { CortexChatPartType, PartDescriptor, PartEmitter, PartConsumer } from "./contracts/part-registry.js";
|
|
65
74
|
export { launchDbos, shutdownDbos, sweepEphemeralWorkflows } from "./runtime/dbos.js";
|
|
@@ -71,10 +80,23 @@ export type { PoolConfig } from "./lib/storage.js";
|
|
|
71
80
|
export type { Pool } from "pg";
|
|
72
81
|
export { registerDataProfileWorkflow, triggerDataProfile, runDataProfile } from "./tasks/data-profile.js";
|
|
73
82
|
export type { DataProfileDeps, DataProfileWorkflowInput, DataProfileTriggerDeps, DataProfileTriggerParams, DataProfileTriggerResult, } from "./tasks/data-profile.js";
|
|
83
|
+
/**
|
|
84
|
+
* The synthetic run id the data-profile workflow stamps onto its own frame — the profile has no run
|
|
85
|
+
* row, so this literal is the only thing that identifies its work as the profile's.
|
|
86
|
+
*
|
|
87
|
+
* An embedder needs it to READ BACK what the harness recorded: usage accounting carries one run-id
|
|
88
|
+
* column, so a host reporting "consumption by run" sees profile calls sitting among real runs and can
|
|
89
|
+
* only separate them by comparing against this value. Exported rather than documented so that
|
|
90
|
+
* comparison is a compile-time coupling — a host holding a copy of the string would keep compiling
|
|
91
|
+
* through a rename here and quietly resume reporting the profile as an unnamed run.
|
|
92
|
+
*/
|
|
93
|
+
export { DATA_PROFILE_RUN_LITERAL } from "./contracts/data-profile.js";
|
|
74
94
|
export { initCortexState } from "./state/init.js";
|
|
75
95
|
export { upsertAnalysis } from "./state/analyses.js";
|
|
76
96
|
export { clearDataProfile, loadDataProfileStatus, tryRetryDataProfile, reconcileOrphanedDataProfile } from "./state/data-profile.js";
|
|
77
97
|
export type { DataProfileInputFile, DataProfileResult, DataProfileStatus } from "./state/data-profile.js";
|
|
98
|
+
export { createAnalysisPurge } from "./state/purge-analysis.js";
|
|
99
|
+
export type { AnalysisPurge, AnalysisPurgeDeps, AnalysisPurgeOutcome } from "./state/purge-analysis.js";
|
|
78
100
|
export type { StagedInput } from "./execution/staged-input.js";
|
|
79
101
|
export type { ResolveWorkspaceRoot } from "./workspace/paths.js";
|
|
80
102
|
export { createSandboxClient } from "./sandbox/create-sandbox.js";
|
package/dist/index.js
CHANGED
|
@@ -17,12 +17,20 @@ export { createLocalRunAuthorizer } from "./auth/local-run-authorizer.js";
|
|
|
17
17
|
export { createNoopBillingResolver } from "./billing/noop-resolver.js";
|
|
18
18
|
// Seam: run-level billing bracket.
|
|
19
19
|
export { createNoopRunCharge } from "./billing/noop-run-charge.js";
|
|
20
|
+
// Seam: per-call LLM usage accounting. `record` is fire-and-forget — the loop
|
|
21
|
+
// neither awaits nor guards it, so a realization must not throw and must not
|
|
22
|
+
// block. Wired as the optional `usageRecorder` of `assembleCoreRuntime`;
|
|
23
|
+
// unwired, every call is dropped by `createNoopUsageRecorder`.
|
|
24
|
+
export { createNoopUsageRecorder } from "./billing/noop-usage-recorder.js";
|
|
20
25
|
// Seam: artifact registration.
|
|
21
26
|
export { createNoopArtifactRegistry } from "./execution/noop-artifact-registry.js";
|
|
22
27
|
// Seam: report preview publishing.
|
|
23
28
|
export { UnavailablePreviewPublisher } from "./tools/report/preview-publisher.js";
|
|
24
29
|
// Run launching.
|
|
25
30
|
export { createDbosRunLauncher } from "./execution/dbos-run-launcher.js";
|
|
31
|
+
// Seam: workflow-ledger reclamation — cancels and deletes an analysis's rows in
|
|
32
|
+
// the durability engine's own ledger, so no caller names an engine type.
|
|
33
|
+
export { createDbosWorkflowPurger } from "./execution/dbos-workflow-purger.js";
|
|
26
34
|
// Tool primitive.
|
|
27
35
|
export { defineTool, isToolError } from "./tools/define-tool.js";
|
|
28
36
|
// Seam: tool approval (`ctx.ask`). `createAskGateway` realizes the `Ask` seam
|
|
@@ -48,7 +56,7 @@ export { createAnthropicProvider } from "./providers/anthropic.js";
|
|
|
48
56
|
// union discriminated over the `anthropic` and `openai-compatible` kinds — with
|
|
49
57
|
// `ConfiguredAiSdkProviderDeps` as its argument shape. `createAnthropicProvider`
|
|
50
58
|
// above is a convenience over this union's `anthropic` arm.
|
|
51
|
-
export { createConfiguredAiSdkProvider } from "./providers/ai-sdk.js";
|
|
59
|
+
export { createConfiguredAiSdkProvider, DEFAULT_MAX_OUTPUT_TOKENS } from "./providers/ai-sdk.js";
|
|
52
60
|
export { createEmbeddingProvider } from "./providers/embedding.js";
|
|
53
61
|
// Prompt caching. `PromptCachePolicy` is the harness's vendor-neutral cache
|
|
54
62
|
// directive; a composition root sets it per run via `RunAgentOptions.promptCache`
|
|
@@ -93,6 +101,11 @@ export { createThreadHistory } from "./memory/thread-history.js";
|
|
|
93
101
|
export { syntheticUserMessage, syntheticRecordMessage, isSyntheticUserMessage, isSyntheticRecordMessage } from "./memory/ai-sdk-message-storage.js";
|
|
94
102
|
export { contentToCortexMessages } from "./memory/content-to-cortex.js";
|
|
95
103
|
export { createCardResolver } from "./memory/reconstruct-cards.js";
|
|
104
|
+
// The call-detail resolver, the reload counterpart of the `describeCall` hook a
|
|
105
|
+
// tool declares. Built over a tool list the HOST supplies — its own composed
|
|
106
|
+
// roster, `HarnessRuntime.conversationAgent.tools` — because tools contributed
|
|
107
|
+
// through the host-tools seam are invisible to any map the harness holds.
|
|
108
|
+
export { createDetailResolver } from "./tools/detail-resolver.js";
|
|
96
109
|
export { PART_REGISTRY, isTransient, isReconciling, isSidebarPart } from "./contracts/part-registry.js";
|
|
97
110
|
// Embedder runtime surface — what a same-process host needs to run durable
|
|
98
111
|
// workflows itself: the DBOS lifecycle, per-workflow registration + triggers,
|
|
@@ -121,6 +134,17 @@ export { createPool } from "./lib/storage.js";
|
|
|
121
134
|
// via `tryRetryDataProfile` and then started with `runDataProfile` (the managed retry
|
|
122
135
|
// route's shape — embedders mirror it).
|
|
123
136
|
export { registerDataProfileWorkflow, triggerDataProfile, runDataProfile } from "./tasks/data-profile.js";
|
|
137
|
+
/**
|
|
138
|
+
* The synthetic run id the data-profile workflow stamps onto its own frame — the profile has no run
|
|
139
|
+
* row, so this literal is the only thing that identifies its work as the profile's.
|
|
140
|
+
*
|
|
141
|
+
* An embedder needs it to READ BACK what the harness recorded: usage accounting carries one run-id
|
|
142
|
+
* column, so a host reporting "consumption by run" sees profile calls sitting among real runs and can
|
|
143
|
+
* only separate them by comparing against this value. Exported rather than documented so that
|
|
144
|
+
* comparison is a compile-time coupling — a host holding a copy of the string would keep compiling
|
|
145
|
+
* through a rename here and quietly resume reporting the profile as an unnamed run.
|
|
146
|
+
*/
|
|
147
|
+
export { DATA_PROFILE_RUN_LITERAL } from "./contracts/data-profile.js";
|
|
124
148
|
// Ledger surface the embedder needs around a trigger: schema init at boot,
|
|
125
149
|
// the analysis-state seed (the trigger's CAS transitions the row this creates
|
|
126
150
|
// — without it every trigger reports "failed"), and run-state observation.
|
|
@@ -133,6 +157,9 @@ export { upsertAnalysis } from "./state/analyses.js";
|
|
|
133
157
|
// analysis's input set empties (deferring on a running workflow), so the UI
|
|
134
158
|
// stops advertising a profile that describes files the analysis no longer has.
|
|
135
159
|
export { clearDataProfile, loadDataProfileStatus, tryRetryDataProfile, reconcileOrphanedDataProfile } from "./state/data-profile.js";
|
|
160
|
+
// Analysis reclamation — `purgeAnalysis` reclaims an analysis's whole Postgres
|
|
161
|
+
// footprint from its id alone; workspace files stay the embedder's to dispose of.
|
|
162
|
+
export { createAnalysisPurge } from "./state/purge-analysis.js";
|
|
136
163
|
export { createSandboxClient } from "./sandbox/create-sandbox.js";
|
|
137
164
|
export { MachineBudgetSchema, ResourceLimitsSchema, ResourcePolicySchema, ResourceSpecSchema, parseResourcePolicy } from "./config/resource-limits.js";
|
|
138
165
|
export { createWorkspaceFilesystem } from "./workspace/filesystem.js";
|
package/dist/lib/metrics.js
CHANGED
|
@@ -14,5 +14,6 @@ export const artifactReconcileDropped = meter.createCounter("cortex.artifact.rec
|
|
|
14
14
|
export const lineageInputDropped = meter.createCounter("cortex.artifact.reconcile.input_dropped", {
|
|
15
15
|
description: "Tracked input reads dropped from lineage at reconcile because they are " +
|
|
16
16
|
"not content-attestable files of the analysis (directory reads, " +
|
|
17
|
-
"out-of-tree resolutions). Tagged by
|
|
17
|
+
"out-of-tree resolutions, paths absent at reconcile). Tagged by " +
|
|
18
|
+
"agent_id, step_id, reason.",
|
|
18
19
|
});
|
package/dist/loop/metrics.d.ts
CHANGED
|
@@ -28,20 +28,38 @@
|
|
|
28
28
|
* `MeterProvider` is registered globally at runtime (production: the OTLP
|
|
29
29
|
* exporter from `harness/lib/otel.ts`; tests: an in-memory reader).
|
|
30
30
|
*/
|
|
31
|
+
import { type TokenUsageRollup } from "../contracts/usage.js";
|
|
31
32
|
import type { ChatUsage } from "../providers/types.js";
|
|
32
33
|
/**
|
|
33
34
|
* Token usage summed over every LLM call one `runAgent` made. Each field stays
|
|
34
35
|
* `undefined` until some call actually reports it, so "the provider told us
|
|
35
36
|
* nothing" never masquerades as a measured zero.
|
|
37
|
+
*
|
|
38
|
+
* The fold is wider than the instruments: `reasoningTokens` is carried for the
|
|
39
|
+
* usage records and the finish rollups, and deliberately has no OTel counter —
|
|
40
|
+
* whether a provider counts reasoning inside `outputTokens` varies, so a
|
|
41
|
+
* cross-agent counter would sum figures that do not mean the same thing.
|
|
36
42
|
*/
|
|
37
43
|
export interface AgentRunUsage {
|
|
38
44
|
inputTokens?: number;
|
|
39
45
|
outputTokens?: number;
|
|
40
46
|
cacheCreationInputTokens?: number;
|
|
41
47
|
cacheReadInputTokens?: number;
|
|
48
|
+
reasoningTokens?: number;
|
|
42
49
|
}
|
|
43
50
|
/** Fold one call's reported usage into a run's running total. */
|
|
44
51
|
export declare function addChatUsage(total: AgentRunUsage, usage: ChatUsage | undefined): void;
|
|
52
|
+
/**
|
|
53
|
+
* Whether anything was ever folded in. An accumulator no call reported into
|
|
54
|
+
* stays empty, and the surfaces that carry a rollup must then carry none at
|
|
55
|
+
* all rather than an all-zero figure.
|
|
56
|
+
*
|
|
57
|
+
* It also accepts the wire-shaped `TokenUsageRollup`, so a surface that RECEIVES
|
|
58
|
+
* a rollup (thread history storing a turn's) decides "reported nothing" with the
|
|
59
|
+
* same predicate the loop used to decide whether to emit one. Restating the rule
|
|
60
|
+
* at either end is how the two would come to disagree.
|
|
61
|
+
*/
|
|
62
|
+
export declare function hasReportedUsage(usage: AgentRunUsage | ChatUsage | TokenUsageRollup | undefined): boolean;
|
|
45
63
|
/** Record one completed `runAgent` invocation. */
|
|
46
64
|
export declare function recordAgentRun(run: {
|
|
47
65
|
readonly agentId: string;
|
package/dist/loop/metrics.js
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
* exporter from `harness/lib/otel.ts`; tests: an in-memory reader).
|
|
30
30
|
*/
|
|
31
31
|
import { metrics } from "@opentelemetry/api";
|
|
32
|
+
import { TOKEN_USAGE_FIELDS } from "../contracts/usage.js";
|
|
32
33
|
let instruments;
|
|
33
34
|
function getInstruments() {
|
|
34
35
|
if (instruments === undefined) {
|
|
@@ -61,16 +62,32 @@ function getInstruments() {
|
|
|
61
62
|
}
|
|
62
63
|
return instruments;
|
|
63
64
|
}
|
|
65
|
+
const _assertRunUsageFields = true;
|
|
64
66
|
/** Fold one call's reported usage into a run's running total. */
|
|
65
67
|
export function addChatUsage(total, usage) {
|
|
66
68
|
if (usage === undefined)
|
|
67
69
|
return;
|
|
68
|
-
for (const key of
|
|
70
|
+
for (const key of TOKEN_USAGE_FIELDS) {
|
|
69
71
|
const value = usage[key];
|
|
70
72
|
if (value !== undefined)
|
|
71
73
|
total[key] = (total[key] ?? 0) + value;
|
|
72
74
|
}
|
|
73
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Whether anything was ever folded in. An accumulator no call reported into
|
|
78
|
+
* stays empty, and the surfaces that carry a rollup must then carry none at
|
|
79
|
+
* all rather than an all-zero figure.
|
|
80
|
+
*
|
|
81
|
+
* It also accepts the wire-shaped `TokenUsageRollup`, so a surface that RECEIVES
|
|
82
|
+
* a rollup (thread history storing a turn's) decides "reported nothing" with the
|
|
83
|
+
* same predicate the loop used to decide whether to emit one. Restating the rule
|
|
84
|
+
* at either end is how the two would come to disagree.
|
|
85
|
+
*/
|
|
86
|
+
export function hasReportedUsage(usage) {
|
|
87
|
+
if (usage === undefined)
|
|
88
|
+
return false;
|
|
89
|
+
return Object.values(usage).some((value) => value !== undefined);
|
|
90
|
+
}
|
|
74
91
|
/** Record one completed `runAgent` invocation. */
|
|
75
92
|
export function recordAgentRun(run) {
|
|
76
93
|
const { iterations, capHits, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens } = getInstruments();
|
package/dist/loop/run-agent.d.ts
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import { type FinishReason } from "ai";
|
|
2
2
|
import type { AgentSession } from "../auth/types.js";
|
|
3
|
+
import type { UsageRecorder } from "../billing/usage-recorder.js";
|
|
3
4
|
import type { Logger } from "../lib/logger.js";
|
|
4
5
|
import type { AgentChat, ChatRequest, PromptCachePolicy } from "../providers/types.js";
|
|
5
6
|
import { type AskApproval, type AskRequest } from "../tools/approval/contract.js";
|
|
7
|
+
import { type AgentRunUsage } from "./metrics.js";
|
|
6
8
|
import type { AgentDefinition, EmitFn, LoopMessage, RunStep } from "./types.js";
|
|
7
9
|
export interface AgentFinish {
|
|
8
10
|
readonly reason: FinishReason | "aborted" | "max_iterations" | "denied";
|
|
9
11
|
readonly cappedOut: boolean;
|
|
10
12
|
readonly truncationRecoveries: number;
|
|
13
|
+
/**
|
|
14
|
+
* What this loop's own LLM calls reported, the forced wrap-up included.
|
|
15
|
+
* Absent when no call reported anything — never an all-zero figure.
|
|
16
|
+
*/
|
|
17
|
+
readonly usage?: AgentRunUsage;
|
|
18
|
+
/**
|
|
19
|
+
* The whole turn's total, every descendant loop included. Present only on
|
|
20
|
+
* the loop that created the turn accumulator — the run whose options
|
|
21
|
+
* carried none, which is by construction the turn's root.
|
|
22
|
+
*/
|
|
23
|
+
readonly turnUsage?: AgentRunUsage;
|
|
11
24
|
}
|
|
12
25
|
export interface RunAgentResult {
|
|
13
26
|
readonly messages: LoopMessage[];
|
|
@@ -67,6 +80,28 @@ export interface RunAgentOptions {
|
|
|
67
80
|
* progress is emitted and then dropped. This is where it survives.
|
|
68
81
|
*/
|
|
69
82
|
readonly logger?: Logger;
|
|
83
|
+
/**
|
|
84
|
+
* Per-call LLM usage-accounting seam. Omitted falls back to the no-op
|
|
85
|
+
* recorder. Delivery is fire-and-forget by contract — the loop neither
|
|
86
|
+
* awaits `record` nor guards it, so a realization must not throw or block.
|
|
87
|
+
*/
|
|
88
|
+
readonly usageRecorder?: UsageRecorder;
|
|
89
|
+
/**
|
|
90
|
+
* The turn's usage accumulator, supplied by whatever ran this loop as part
|
|
91
|
+
* of a larger turn (a sub-agent-running tool passes `ctx.turnUsage`). A run
|
|
92
|
+
* that receives none creates its own and is therefore the turn's root: it
|
|
93
|
+
* alone reports `turnUsage` on its finish.
|
|
94
|
+
*/
|
|
95
|
+
readonly turnUsage?: AgentRunUsage;
|
|
96
|
+
/**
|
|
97
|
+
* The id of the tool call this loop runs inside, supplied by a
|
|
98
|
+
* sub-agent-running tool from its `ctx.invocationId`. It is what separates
|
|
99
|
+
* two dispatches of the *same* sub-agent in one round — they share the run
|
|
100
|
+
* frame, the call path, and every loop-local step name — in the usage
|
|
101
|
+
* record key. Absent for a loop that is not nested inside a tool dispatch
|
|
102
|
+
* (a chat turn's root, a workflow step body, a background task).
|
|
103
|
+
*/
|
|
104
|
+
readonly invocationId?: string;
|
|
70
105
|
}
|
|
71
106
|
export declare function runAgent(agent: AgentDefinition, initial: readonly LoopMessage[], session: AgentSession, opts: RunAgentOptions): Promise<RunAgentResult>;
|
|
72
107
|
export declare function finalText(messages: readonly LoopMessage[]): string;
|