@apo-ai/sdk 0.8.0 → 0.9.1
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/agent-task/integrations/ai-sdk.js +2 -2
- package/dist/agent-task/public.d.ts +461 -5
- package/dist/agent-task/public.js +1511 -131
- package/dist/agent-task/public.js.map +1 -1
- package/dist/{chunk-HLRXQAZ5.js → chunk-HRYXLRXJ.js} +2 -2
- package/dist/{chunk-HLRXQAZ5.js.map → chunk-HRYXLRXJ.js.map} +1 -1
- package/dist/{chunk-CKB3SUDO.js → chunk-IK4GJX7H.js} +2 -2
- package/dist/{chunk-IPQ6IIEG.js → chunk-KLZLE3VQ.js} +2 -2
- package/dist/otel/index.js +2 -2
- package/package.json +3 -1
- /package/dist/{chunk-CKB3SUDO.js.map → chunk-IK4GJX7H.js.map} +0 -0
- /package/dist/{chunk-IPQ6IIEG.js.map → chunk-KLZLE3VQ.js.map} +0 -0
package/README.md
CHANGED
|
@@ -216,7 +216,8 @@ exposes only the deliverables selected by that task.
|
|
|
216
216
|
`calledTool(name, opts?)`, `notCalledTool(name, opts?)`, `toolOrder([...])`,
|
|
217
217
|
`usedNoTools()`, `maxToolCalls(n)`, `noFailedActions()`, `loadedSkill(skill)`,
|
|
218
218
|
`calledSubagent(agent)`, `messageIncludes(token)`, `maxTurns(n)`,
|
|
219
|
-
`maxDurationMs(n)`, `
|
|
219
|
+
`maxDurationMs(n, { turn? })`, `maxTokens(n, { turn?, kind? })`,
|
|
220
|
+
`minTokens(n, { turn?, kind? })`, `assert(label, predicate)`.
|
|
220
221
|
|
|
221
222
|
`calledTool` / `notCalledTool` take optional constraints to match a call's
|
|
222
223
|
**input**, **output**, and **status** (and `count` for an exact number). Each
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Do not edit by hand — edit the src/ originals and rebuild.
|
|
3
3
|
import {
|
|
4
4
|
createApoTracer
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
5
|
+
} from "../../chunk-IK4GJX7H.js";
|
|
6
|
+
import "../../chunk-HRYXLRXJ.js";
|
|
7
7
|
export {
|
|
8
8
|
createApoTracer
|
|
9
9
|
};
|
|
@@ -47,6 +47,19 @@ interface TraceProjectionCapabilities {
|
|
|
47
47
|
timing: EvidenceAvailability;
|
|
48
48
|
skills: EvidenceAvailability;
|
|
49
49
|
subagents: EvidenceAvailability;
|
|
50
|
+
/**
|
|
51
|
+
* Token usage on observations. Optional for snapshots written before usage
|
|
52
|
+
* was projected: absent reads as `unavailable`.
|
|
53
|
+
*/
|
|
54
|
+
usage?: EvidenceAvailability;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Token counts one observation reported. Each dimension is present only when
|
|
58
|
+
* the source reported it — unknown stays unknown, never zero.
|
|
59
|
+
*/
|
|
60
|
+
interface TraceProjectionUsage {
|
|
61
|
+
inputTokens?: number;
|
|
62
|
+
outputTokens?: number;
|
|
50
63
|
}
|
|
51
64
|
/** One chat message reconstructed from a generation observation. */
|
|
52
65
|
interface TraceProjectionMessage {
|
|
@@ -75,6 +88,8 @@ interface TraceProjectionObservation {
|
|
|
75
88
|
toolParameters?: unknown;
|
|
76
89
|
toolResult?: unknown;
|
|
77
90
|
messages?: readonly TraceProjectionMessage[];
|
|
91
|
+
/** Token usage this observation reported. Absent when none was recorded. */
|
|
92
|
+
usage?: TraceProjectionUsage;
|
|
78
93
|
metadata?: Readonly<Record<string, unknown>>;
|
|
79
94
|
}
|
|
80
95
|
/** Trace-level facts. All timing is optional; absence is honest. */
|
|
@@ -139,6 +154,34 @@ interface TraceSubagentCall {
|
|
|
139
154
|
status: ObservationStatus;
|
|
140
155
|
startedAt?: string;
|
|
141
156
|
}
|
|
157
|
+
/** One Task Turn, derived from a `task.turn` observation. */
|
|
158
|
+
interface TraceTurn {
|
|
159
|
+
/** 1-based, in invocation order. */
|
|
160
|
+
turnNumber: number;
|
|
161
|
+
spanId: string;
|
|
162
|
+
durationMs?: number;
|
|
163
|
+
status: ObservationStatus;
|
|
164
|
+
}
|
|
165
|
+
type TokenKind = "input" | "output" | "total";
|
|
166
|
+
/**
|
|
167
|
+
* Token usage summed over a scope (the whole agent execution, or one turn).
|
|
168
|
+
* When `unreported` is non-zero, `tokens` is only a lower bound.
|
|
169
|
+
*/
|
|
170
|
+
interface TraceTokenTally {
|
|
171
|
+
tokens: number;
|
|
172
|
+
/**
|
|
173
|
+
* Observations that reported a count, including a step whose count its
|
|
174
|
+
* parent call's own larger count superseded.
|
|
175
|
+
*/
|
|
176
|
+
reported: number;
|
|
177
|
+
/**
|
|
178
|
+
* LLM calls in scope whose count is unknown or untrustworthy: a GENERATION
|
|
179
|
+
* that reported no usage for the dimension, or an errored call (a provider
|
|
180
|
+
* error often drops the final usage event, so its count may be short) —
|
|
181
|
+
* except a step beneath a call whose own count is complete, which covers it.
|
|
182
|
+
*/
|
|
183
|
+
unreported: number;
|
|
184
|
+
}
|
|
142
185
|
declare class TraceView {
|
|
143
186
|
readonly snapshot: TraceProjectionSnapshot;
|
|
144
187
|
constructor(snapshot: TraceProjectionSnapshot);
|
|
@@ -174,6 +217,34 @@ declare class TraceView {
|
|
|
174
217
|
* startedAt/endedAt when present.
|
|
175
218
|
*/
|
|
176
219
|
get durationMs(): number | undefined;
|
|
220
|
+
/**
|
|
221
|
+
* Task Turns in invocation order, or `undefined` when timing evidence is
|
|
222
|
+
* not available. Each is one `task.turn` span: the adapter's whole
|
|
223
|
+
* `sendUserTurn` call for that turn.
|
|
224
|
+
*/
|
|
225
|
+
get turns(): readonly TraceTurn[] | undefined;
|
|
226
|
+
/**
|
|
227
|
+
* Tokens the agent under test spent: usage on observations inside
|
|
228
|
+
* `task.turn` spans (every turn, or only turn `turn`). Work outside the
|
|
229
|
+
* turns — the evaluation phase's judges, adapter setup — is not the
|
|
230
|
+
* agent's and is excluded. `undefined` when usage evidence is not
|
|
231
|
+
* available or the requested turn does not exist.
|
|
232
|
+
*/
|
|
233
|
+
/** How many Task Turns ran — independent of timing evidence. */
|
|
234
|
+
get turnCountFromSpans(): number;
|
|
235
|
+
tokens(kind: TokenKind, opts?: {
|
|
236
|
+
turn?: number;
|
|
237
|
+
}): TraceTokenTally | undefined;
|
|
238
|
+
/**
|
|
239
|
+
* The run's own Task Turns: `task.turn` observations with no `task.turn`
|
|
240
|
+
* ancestor (a nested run or a user span of the same name inside a turn is
|
|
241
|
+
* part of that turn, not a turn of its own). Turns run sequentially, so
|
|
242
|
+
* invocation order is turn order.
|
|
243
|
+
*/
|
|
244
|
+
private get turnSpans();
|
|
245
|
+
private _turnSpans;
|
|
246
|
+
private get childrenByParent();
|
|
247
|
+
private _children;
|
|
177
248
|
/**
|
|
178
249
|
* Observations sorted deterministically by invocation time then span ID.
|
|
179
250
|
* Memoized per TraceView instance since the snapshot is immutable.
|
|
@@ -381,7 +452,11 @@ type JudgeMetadata = {
|
|
|
381
452
|
/**
|
|
382
453
|
* Evidence from the second grader. `error` is set when the decisions
|
|
383
454
|
* endpoint could not be reached — a failed second opinion must never
|
|
384
|
-
* affect the check's verdict.
|
|
455
|
+
* affect the check's verdict. `skipped` is set when no verdict was
|
|
456
|
+
* attempted or possible because the second judge could not read the
|
|
457
|
+
* input — a different fact from a transport failure, and rendered
|
|
458
|
+
* distinctly so a run can say "N checks had no second opinion because
|
|
459
|
+
* the value was too large" without grepping error strings (issue #311).
|
|
385
460
|
*/
|
|
386
461
|
type SecondJudgeEvidence = {
|
|
387
462
|
/** Decision-model id that graded, e.g. `typesafe/jev-1.13`. */
|
|
@@ -398,8 +473,20 @@ type SecondJudgeEvidence = {
|
|
|
398
473
|
costUsd?: number;
|
|
399
474
|
/** Wall-clock latency of the decision call in milliseconds. */
|
|
400
475
|
latencyMs?: number;
|
|
476
|
+
/**
|
|
477
|
+
* Why no verdict was possible (as opposed to attempted): the input
|
|
478
|
+
* exceeded the second judge model's context limit, so the provider
|
|
479
|
+
* rejected it before judging.
|
|
480
|
+
*/
|
|
481
|
+
skipped?: string;
|
|
401
482
|
/** Why no verdict was recorded (transport/HTTP/parse failure). */
|
|
402
483
|
error?: string;
|
|
484
|
+
/**
|
|
485
|
+
* True when the second judge graded a `secondJudgeValue` projection
|
|
486
|
+
* instead of the full value the primary judge saw — the verdict
|
|
487
|
+
* corroborates the projection, not the whole deliverable.
|
|
488
|
+
*/
|
|
489
|
+
projected?: boolean;
|
|
403
490
|
};
|
|
404
491
|
/**
|
|
405
492
|
* One investigation step of an agentic judge session. Tool results are
|
|
@@ -590,6 +677,12 @@ type EvaluationItemResult = {
|
|
|
590
677
|
type TaskEvaluationResult = {
|
|
591
678
|
checks: EvaluationItemResult[];
|
|
592
679
|
pass: boolean;
|
|
680
|
+
/**
|
|
681
|
+
* Set when the run has no verdict: every failing check got no answer from
|
|
682
|
+
* the judge (`outcome: "error"`) and nothing genuinely failed. `pass` stays
|
|
683
|
+
* `false`; readers should report "no verdict" rather than FAIL (issue #323).
|
|
684
|
+
*/
|
|
685
|
+
noVerdict?: true;
|
|
593
686
|
};
|
|
594
687
|
type TaskTranscript = {
|
|
595
688
|
turns: TaskTranscriptTurn[];
|
|
@@ -729,6 +822,111 @@ type AgentHistoryPlane = {
|
|
|
729
822
|
selfRunId?: string;
|
|
730
823
|
};
|
|
731
824
|
|
|
825
|
+
/**
|
|
826
|
+
* MCP plumbing for apo's two tool planes. The judge's budgeted toolset
|
|
827
|
+
* (`createMcpToolset`) wraps user-declared MCP servers into `t.agent`
|
|
828
|
+
* sessions under the same budget ledger and evidence-manifest discipline as
|
|
829
|
+
* the built-in evidence tools. `connectMcpServers` is the raw connect core
|
|
830
|
+
* shared with adapters — the agent under test is not apo's to budget, so
|
|
831
|
+
* adapters merge the namespaced `mcp__<server>__<tool>` tools themselves.
|
|
832
|
+
*
|
|
833
|
+
* Judge config layers exactly like the judge model config
|
|
834
|
+
* (`resolveJudgeConfig`): env/file (APO_JUDGE_MCP) ← runTask({ judgeTools })
|
|
835
|
+
* ← task.judgeTools ← per-call `t.agent(..., { tools: { mcp } })` — most
|
|
836
|
+
* specific wins, arrays replace, never concat. Task-level `mcpServers`
|
|
837
|
+
* (adapter plane) is a separate declaration honored by adapters that choose
|
|
838
|
+
* to (see TaskDefinition.mcpServers).
|
|
839
|
+
*
|
|
840
|
+
* The MCP client (`@ai-sdk/mcp`) is lazy-loaded: suites that never configure
|
|
841
|
+
* MCP servers must never pay for the dependency (pinned by the
|
|
842
|
+
* lazy-isolation test in tests/judge-mcp.test.ts).
|
|
843
|
+
*/
|
|
844
|
+
|
|
845
|
+
/** Stdio transport: the judge's machine spawns the server process. */
|
|
846
|
+
type McpStdioTransport = {
|
|
847
|
+
type: "stdio";
|
|
848
|
+
command: string;
|
|
849
|
+
args?: string[];
|
|
850
|
+
/**
|
|
851
|
+
* Environment for the spawned process. Values support `${VAR}` expansion
|
|
852
|
+
* from the judge process's environment at connect time; an unset variable
|
|
853
|
+
* is a load error, never an empty string.
|
|
854
|
+
*/
|
|
855
|
+
env?: Record<string, string>;
|
|
856
|
+
};
|
|
857
|
+
/** HTTP transport: an already-running remote server (Streamable HTTP). */
|
|
858
|
+
type McpHttpTransport = {
|
|
859
|
+
type: "http";
|
|
860
|
+
url: string;
|
|
861
|
+
/** Header values support `${VAR}` expansion like stdio env values. */
|
|
862
|
+
headers?: Record<string, string>;
|
|
863
|
+
};
|
|
864
|
+
/** One user MCP server the judge may call. Mirrors the industry shape. */
|
|
865
|
+
type McpServerConfig = {
|
|
866
|
+
/** Unique server name; its tools are exposed as `mcp__<name>__<tool>`. */
|
|
867
|
+
name: string;
|
|
868
|
+
transport: McpStdioTransport | McpHttpTransport;
|
|
869
|
+
/** Allowlist of raw server tool names (applied before namespacing). */
|
|
870
|
+
tools?: string[];
|
|
871
|
+
/** Denylist applied after the allowlist. */
|
|
872
|
+
excludeTools?: string[];
|
|
873
|
+
/** Per-tool-call timeout in ms. Default 30_000. */
|
|
874
|
+
timeoutMs?: number;
|
|
875
|
+
};
|
|
876
|
+
/** Layered judge-tools config, sibling of `JudgeConfig`. */
|
|
877
|
+
type JudgeToolsConfig = {
|
|
878
|
+
mcp?: McpServerConfig[];
|
|
879
|
+
};
|
|
880
|
+
/**
|
|
881
|
+
* Expand `${VAR}` placeholders in secret-bearing string maps (stdio env,
|
|
882
|
+
* HTTP headers). Unset variables throw naming the variable — a missing
|
|
883
|
+
* credential must fail visibly at load time, never collapse to "".
|
|
884
|
+
*/
|
|
885
|
+
declare function expandSecretPlaceholders(values: Record<string, string>): Record<string, string>;
|
|
886
|
+
/**
|
|
887
|
+
* Narrow, locally-owned view of an MCP client, mirroring the engine-facade
|
|
888
|
+
* discipline in agent-session.ts: never let tsc instantiate the library's
|
|
889
|
+
* generics. The real `@ai-sdk/mcp` client is structurally compatible.
|
|
890
|
+
*/
|
|
891
|
+
type McpRawTool = {
|
|
892
|
+
description?: unknown;
|
|
893
|
+
inputSchema?: unknown;
|
|
894
|
+
execute?: unknown;
|
|
895
|
+
};
|
|
896
|
+
type McpClientLike = {
|
|
897
|
+
tools: () => Promise<Record<string, McpRawTool>>;
|
|
898
|
+
close: () => Promise<void>;
|
|
899
|
+
};
|
|
900
|
+
type McpClientFactory = (args: {
|
|
901
|
+
server: McpServerConfig;
|
|
902
|
+
timeoutMs: number;
|
|
903
|
+
}) => Promise<McpClientLike>;
|
|
904
|
+
/**
|
|
905
|
+
* Resolve path-like stdio values against a base directory (the task dir):
|
|
906
|
+
* absolute values, "./" and "../" prefixes resolve; bare names stay bare so
|
|
907
|
+
* the spawn resolves them from PATH. Applied to TaskDefinition.mcpServers
|
|
908
|
+
* by adapters AND to layered judgeTools by runTask — "./mcp/server.mjs"
|
|
909
|
+
* means the same thing on both planes, independent of the runner's cwd.
|
|
910
|
+
*/
|
|
911
|
+
declare function resolveMcpServerPaths(servers: McpServerConfig[], baseDir: string): McpServerConfig[];
|
|
912
|
+
/**
|
|
913
|
+
* Connects one client per declared server and returns the RAW namespaced
|
|
914
|
+
* tools — no budget wrapping, because the agent under test is not apo's to
|
|
915
|
+
* budget (that discipline is judge-only, in `createMcpToolset` below).
|
|
916
|
+
* Adapters that drive an AI-SDK agent loop merge `tools` into their own tool
|
|
917
|
+
* record; `byServer` maps each server name to its exposed raw tool names.
|
|
918
|
+
*
|
|
919
|
+
* Connect failures throw naming the server after closing what already
|
|
920
|
+
* connected. Duplicate server names throw before anything spawns.
|
|
921
|
+
*/
|
|
922
|
+
declare function connectMcpServers(servers: McpServerConfig[], opts?: {
|
|
923
|
+
clientFactory?: McpClientFactory;
|
|
924
|
+
}): Promise<{
|
|
925
|
+
tools: Record<string, unknown>;
|
|
926
|
+
byServer: Record<string, string[]>;
|
|
927
|
+
cleanup: () => Promise<void>;
|
|
928
|
+
}>;
|
|
929
|
+
|
|
732
930
|
/**
|
|
733
931
|
* The agentic judge — `t.agent`. A tool-using LLM session that investigates
|
|
734
932
|
* the run's own evidence (deliverables, trace) before verdicting, powered by
|
|
@@ -763,6 +961,7 @@ type AgentJudgeOptions = {
|
|
|
763
961
|
/** Tool families; deliverables are always on. `trace: false` drops get_trace. */
|
|
764
962
|
tools?: {
|
|
765
963
|
trace?: boolean;
|
|
964
|
+
mcp?: McpServerConfig[];
|
|
766
965
|
};
|
|
767
966
|
budget?: AgentBudget;
|
|
768
967
|
label?: string;
|
|
@@ -797,6 +996,19 @@ type ToolCallOptions = {
|
|
|
797
996
|
output?: ValueMatcher<unknown>;
|
|
798
997
|
status?: "ok" | "error";
|
|
799
998
|
};
|
|
999
|
+
/** Scope for duration budgets: the whole run, or one Task Turn (1-based). */
|
|
1000
|
+
type DurationBudgetOptions = {
|
|
1001
|
+
turn?: number;
|
|
1002
|
+
};
|
|
1003
|
+
/**
|
|
1004
|
+
* Scope for token budgets. Tokens are the agent's: usage inside `task.turn`
|
|
1005
|
+
* spans, summed over every turn or only `turn`. `kind` defaults to `"total"`
|
|
1006
|
+
* (input + output).
|
|
1007
|
+
*/
|
|
1008
|
+
type TokenBudgetOptions = {
|
|
1009
|
+
turn?: number;
|
|
1010
|
+
kind?: TokenKind;
|
|
1011
|
+
};
|
|
800
1012
|
/**
|
|
801
1013
|
* LLM judge model config for `t.judge(...)` calls in checks.ts. Threaded
|
|
802
1014
|
* through `runTask({ judge })` from the caller — the runner has no opinion
|
|
@@ -850,8 +1062,15 @@ interface TestContext {
|
|
|
850
1062
|
messageIncludes(token: string | RegExp): void;
|
|
851
1063
|
/** Asserts the run took at most `n` turns — anti-flail. */
|
|
852
1064
|
maxTurns(n: number): void;
|
|
853
|
-
/**
|
|
854
|
-
|
|
1065
|
+
/**
|
|
1066
|
+
* Asserts the run took at most `n` milliseconds — anti-flail. With
|
|
1067
|
+
* `{ turn }`, bounds that one Task Turn instead.
|
|
1068
|
+
*/
|
|
1069
|
+
maxDurationMs(n: number, opts?: DurationBudgetOptions): void;
|
|
1070
|
+
/** Asserts the agent spent at most `n` tokens (whole run, or `{ turn }`). */
|
|
1071
|
+
maxTokens(n: number, opts?: TokenBudgetOptions): void;
|
|
1072
|
+
/** Asserts the agent spent at least `n` tokens (whole run, or `{ turn }`). */
|
|
1073
|
+
minTokens(n: number, opts?: TokenBudgetOptions): void;
|
|
855
1074
|
/** Escape hatch for a named predicate over the complete normalized run. */
|
|
856
1075
|
assert(label: string, predicate: (flow: TraceView) => boolean): void;
|
|
857
1076
|
/** Grades any value (a deliverable, parsed JSON, anything) with a matcher. */
|
|
@@ -867,10 +1086,22 @@ interface TestContext {
|
|
|
867
1086
|
* merging field-by-field onto the config threaded in via ``runTask({ judge })``
|
|
868
1087
|
* — set ``{ model }`` to escalate a finicky criterion to a stronger model
|
|
869
1088
|
* without switching the whole run. Absent fields inherit from the base config.
|
|
1089
|
+
*
|
|
1090
|
+
* ``opts.secondJudgeValue`` grades a smaller view with the second judge
|
|
1091
|
+
* only, when the full value exceeds its context limit: the primary judge
|
|
1092
|
+
* still sees all of ``value``, so other criteria that need the complete
|
|
1093
|
+
* deliverable are unaffected.
|
|
870
1094
|
*/
|
|
871
1095
|
judge(values: unknown | unknown[], instruction: string, opts?: {
|
|
872
1096
|
label?: string;
|
|
873
1097
|
judge?: Partial<JudgeConfig>;
|
|
1098
|
+
/**
|
|
1099
|
+
* What the second judge reads instead of ``values`` — e.g. the
|
|
1100
|
+
* tracked-changes section of a redline when the whole marked-up
|
|
1101
|
+
* document is too large for the second judge's context. Absent,
|
|
1102
|
+
* the second judge sees exactly what the primary judge sees.
|
|
1103
|
+
*/
|
|
1104
|
+
secondJudgeValue?: unknown | unknown[];
|
|
874
1105
|
}): Promise<void>;
|
|
875
1106
|
/**
|
|
876
1107
|
* Agentic judge: a tool-using LLM session that investigates the run's own
|
|
@@ -900,7 +1131,7 @@ interface TestContext {
|
|
|
900
1131
|
* adding a method to the interface without registering it here is a type
|
|
901
1132
|
* error, and vice versa. See ``tests/test-context-methods.test.ts``.
|
|
902
1133
|
*/
|
|
903
|
-
declare const TEST_METHOD_NAMES: readonly ["calledTool", "notCalledTool", "toolOrder", "usedNoTools", "maxToolCalls", "noFailedActions", "loadedSkill", "calledSubagent", "messageIncludes", "maxTurns", "maxDurationMs", "assert", "check", "judge", "agent"];
|
|
1134
|
+
declare const TEST_METHOD_NAMES: readonly ["calledTool", "notCalledTool", "toolOrder", "usedNoTools", "maxToolCalls", "noFailedActions", "loadedSkill", "calledSubagent", "messageIncludes", "maxTurns", "maxDurationMs", "maxTokens", "minTokens", "assert", "check", "judge", "agent"];
|
|
904
1135
|
|
|
905
1136
|
type TaskDefinition<TAdapterName extends string = string, TDeliverable extends string = string> = {
|
|
906
1137
|
id: string;
|
|
@@ -917,6 +1148,21 @@ type TaskDefinition<TAdapterName extends string = string, TDeliverable extends s
|
|
|
917
1148
|
* `prompt` that tells the judge what it is grading.
|
|
918
1149
|
*/
|
|
919
1150
|
judge?: Partial<JudgeConfig>;
|
|
1151
|
+
/**
|
|
1152
|
+
* Task-level judge-tools layer: MCP evidence servers for `t.agent` sessions
|
|
1153
|
+
* in this task. Overrides `runTask({ judgeTools })`, is overridden per
|
|
1154
|
+
* `t.agent(..., { tools: { mcp } })` call. Arrays replace, never concat.
|
|
1155
|
+
*/
|
|
1156
|
+
judgeTools?: JudgeToolsConfig;
|
|
1157
|
+
/**
|
|
1158
|
+
* MCP servers declared for the AGENT UNDER TEST (the adapter plane — a
|
|
1159
|
+
* separate declaration from `judgeTools`). Adapters that honor it resolve
|
|
1160
|
+
* relative `command`/`args` paths against the task directory and expose
|
|
1161
|
+
* the tools as `mcp__<server>__<tool>`; trace assertions can match those
|
|
1162
|
+
* stable names. Declaring the harness's tool surface here keeps the task
|
|
1163
|
+
* portable across harnesses.
|
|
1164
|
+
*/
|
|
1165
|
+
mcpServers?: McpServerConfig[];
|
|
920
1166
|
};
|
|
921
1167
|
type TaskConfig<TDeliverable extends string = string> = Omit<TaskDefinition<string, TDeliverable>, "adapter">;
|
|
922
1168
|
type FileEntry = {
|
|
@@ -1361,6 +1607,11 @@ type RunTaskOptions = {
|
|
|
1361
1607
|
tracing?: AgentTaskTraceOptions;
|
|
1362
1608
|
/** LLM judge model config for `t.judge(...)` calls in the task checks. */
|
|
1363
1609
|
judge?: JudgeConfig;
|
|
1610
|
+
/**
|
|
1611
|
+
* Judge tool config for `t.agent(...)` sessions (MCP evidence servers).
|
|
1612
|
+
* Layered under `TaskDefinition.judgeTools` and per-call `tools.mcp`.
|
|
1613
|
+
*/
|
|
1614
|
+
judgeTools?: JudgeToolsConfig;
|
|
1364
1615
|
onTurn?: (turnNumber: number, userAction: TaskTranscriptTurn["userAction"], agentResponse: unknown) => void;
|
|
1365
1616
|
/**
|
|
1366
1617
|
* Skip the internal `loadTask(taskDir)` call and reuse an already-loaded
|
|
@@ -1456,6 +1707,8 @@ interface RejudgeOutcome {
|
|
|
1456
1707
|
/** Full check results from the primary (first) sample. */
|
|
1457
1708
|
checks: EvaluationItemResult[];
|
|
1458
1709
|
pass: boolean;
|
|
1710
|
+
/** Every failing check got no answer from the judge — see {@link TaskEvaluationResult.noVerdict}. */
|
|
1711
|
+
noVerdict?: true;
|
|
1459
1712
|
/** Only meaningful with samples > 1; ordered like the primary sample. */
|
|
1460
1713
|
stability: RejudgeCheckStability[];
|
|
1461
1714
|
/** False when the trace projection was unreadable — trajectory assertions were unsupported. */
|
|
@@ -1482,11 +1735,14 @@ declare function discoverAgentTaskDirs(rootDir: string): string[];
|
|
|
1482
1735
|
|
|
1483
1736
|
type AgentTaskRuntime = {
|
|
1484
1737
|
judge?: JudgeConfig;
|
|
1738
|
+
judgeTools?: JudgeToolsConfig;
|
|
1485
1739
|
};
|
|
1486
1740
|
type AgentTaskRunSummary = {
|
|
1487
1741
|
taskDir: string;
|
|
1488
1742
|
taskId: string;
|
|
1489
1743
|
pass: boolean;
|
|
1744
|
+
/** Every failing check got no answer from the judge — see `TaskEvaluationResult.noVerdict`. */
|
|
1745
|
+
noVerdict?: true;
|
|
1490
1746
|
checks: EvaluationItemResult[];
|
|
1491
1747
|
/** Adapter that ran the task. Forwarded to the backend when recording locally. */
|
|
1492
1748
|
adapterName?: string;
|
|
@@ -1741,4 +1997,204 @@ declare function canonicalManifestJson(manifest: TaskRevisionManifestV1): string
|
|
|
1741
1997
|
/** SHA-256 (lowercase hex) of the canonical manifest JSON's UTF-8 bytes. */
|
|
1742
1998
|
declare function contentSha256(manifest: TaskRevisionManifestV1): string;
|
|
1743
1999
|
|
|
1744
|
-
|
|
2000
|
+
/**
|
|
2001
|
+
* Normalized transcript model — the common shape every harness transcript
|
|
2002
|
+
* parser produces, and the input to the OTLP translator.
|
|
2003
|
+
*
|
|
2004
|
+
* The model is deliberately lossy-but-sufficient for trace reconstruction:
|
|
2005
|
+
* per turn it keeps the user/assistant text, thinking, tool calls with their
|
|
2006
|
+
* results, model identity, and token usage. Anything the projection cannot
|
|
2007
|
+
* use (streaming chunk boundaries, harness housekeeping) is folded away.
|
|
2008
|
+
*/
|
|
2009
|
+
type TranscriptSource = "claude-code" | "codex";
|
|
2010
|
+
type TranscriptUsage = {
|
|
2011
|
+
inputTokens?: number;
|
|
2012
|
+
outputTokens?: number;
|
|
2013
|
+
cacheReadTokens?: number;
|
|
2014
|
+
cacheWriteTokens?: number;
|
|
2015
|
+
reasoningTokens?: number;
|
|
2016
|
+
};
|
|
2017
|
+
type TranscriptToolCall = {
|
|
2018
|
+
callId: string;
|
|
2019
|
+
name: string;
|
|
2020
|
+
/** Arguments exactly as recorded — parsed object when the harness allows, raw string otherwise. */
|
|
2021
|
+
input: unknown;
|
|
2022
|
+
/** Rendered result text or the raw output payload; absent when the transcript never recorded one. */
|
|
2023
|
+
result?: unknown;
|
|
2024
|
+
/** ISO timestamp of the call, when the transcript carries one. */
|
|
2025
|
+
startedAt?: string;
|
|
2026
|
+
/** ISO timestamp of the matching result, when the transcript carries one. */
|
|
2027
|
+
endedAt?: string;
|
|
2028
|
+
};
|
|
2029
|
+
type TranscriptTurn = {
|
|
2030
|
+
/** Zero-based position of the turn within the session. */
|
|
2031
|
+
index: number;
|
|
2032
|
+
/** ISO timestamp of the user message that opened the turn. */
|
|
2033
|
+
startedAt: string;
|
|
2034
|
+
/** ISO timestamp of the last observed event in the turn, when known. */
|
|
2035
|
+
endedAt?: string;
|
|
2036
|
+
model?: string;
|
|
2037
|
+
userMessage?: string;
|
|
2038
|
+
assistantMessage?: string;
|
|
2039
|
+
/** Extended-thinking text (Claude) or reasoning summaries (Codex). */
|
|
2040
|
+
thinkingText?: string;
|
|
2041
|
+
/** Codex commentary-phase messages (progress narration, not reasoning). */
|
|
2042
|
+
commentary?: string[];
|
|
2043
|
+
toolCalls: TranscriptToolCall[];
|
|
2044
|
+
usage?: TranscriptUsage;
|
|
2045
|
+
};
|
|
2046
|
+
type ParsedTranscriptSession = {
|
|
2047
|
+
source: TranscriptSource;
|
|
2048
|
+
sessionId: string;
|
|
2049
|
+
cwd?: string;
|
|
2050
|
+
turns: TranscriptTurn[];
|
|
2051
|
+
/** Non-fatal parse issues: torn lines, unterminated turns, unmatched outputs. */
|
|
2052
|
+
warnings: string[];
|
|
2053
|
+
};
|
|
2054
|
+
|
|
2055
|
+
/**
|
|
2056
|
+
* Claude Code session-transcript parser.
|
|
2057
|
+
*
|
|
2058
|
+
* Claude Code appends one JSON object per line to
|
|
2059
|
+
* ``~/.claude/projects/<project>/<session-id>.jsonl`` for every session:
|
|
2060
|
+
*
|
|
2061
|
+
* { type: "user" | "assistant", timestamp, requestId?, sessionId?, cwd?,
|
|
2062
|
+
* toolUseResult?, message: { id?, role, model?, usage?, stop_reason?,
|
|
2063
|
+
* content: string | Array<text | thinking | tool_use | tool_result> } }
|
|
2064
|
+
*
|
|
2065
|
+
* Two grouping rules do the real work:
|
|
2066
|
+
* - Streamed assistant chunks of one API response share ``message.id``; they
|
|
2067
|
+
* are one logical message, and usage is read from the most complete chunk
|
|
2068
|
+
* (the first chunk's snapshot undercounts the request).
|
|
2069
|
+
* - A user line whose content is a ``tool_result`` block array is the harness
|
|
2070
|
+
* feeding a tool result back to the model, not a new turn.
|
|
2071
|
+
*/
|
|
2072
|
+
|
|
2073
|
+
declare function parseClaudeCodeTranscript(content: string): ParsedTranscriptSession;
|
|
2074
|
+
|
|
2075
|
+
/**
|
|
2076
|
+
* Codex CLI session-transcript parser.
|
|
2077
|
+
*
|
|
2078
|
+
* Codex writes rollout files under ``~/.codex/sessions/YYYY/MM/DD/``, one
|
|
2079
|
+
* JSON object per line:
|
|
2080
|
+
*
|
|
2081
|
+
* { type: "session_meta" | "turn_context" | "event_msg" | "response_item",
|
|
2082
|
+
* timestamp, payload }
|
|
2083
|
+
*
|
|
2084
|
+
* - ``event_msg`` payloads: ``task_started``, ``task_complete``,
|
|
2085
|
+
* ``user_message``, ``agent_message`` (phase ``final_answer`` |
|
|
2086
|
+
* ``commentary``), ``token_count`` (``info.last_token_usage``).
|
|
2087
|
+
* - ``response_item`` payloads: ``function_call`` / ``custom_tool_call`` and
|
|
2088
|
+
* their ``*_output`` counterparts (paired by ``call_id``), ``reasoning``
|
|
2089
|
+
* (summary text), ``web_search_call``.
|
|
2090
|
+
*
|
|
2091
|
+
* A turn is bracketed by ``task_started`` … ``task_complete``. A rollout that
|
|
2092
|
+
* ends mid-turn (harness killed, crash) still yields its turn — the activity
|
|
2093
|
+
* happened, the trace should show it — with a warning.
|
|
2094
|
+
*/
|
|
2095
|
+
|
|
2096
|
+
declare function parseCodexTranscript(content: string): ParsedTranscriptSession;
|
|
2097
|
+
|
|
2098
|
+
/**
|
|
2099
|
+
* Transcript → OTLP/JSON translator.
|
|
2100
|
+
*
|
|
2101
|
+
* Converts a parsed session into exactly the span vocabulary apo's receiver
|
|
2102
|
+
* already normalizes best. Two rules make replayed traces indistinguishable
|
|
2103
|
+
* from live-OTel ones in the projection:
|
|
2104
|
+
*
|
|
2105
|
+
* 1. Every span carries an explicit ``apo.observation.type`` override — the
|
|
2106
|
+
* priority-1 mapper — so typing (AGENT / GENERATION / TOOL / SPAN) never
|
|
2107
|
+
* depends on the backend's registry guessing from attributes.
|
|
2108
|
+
* 2. Attributes use apo's established GenAI keys (``gen_ai.request.model``,
|
|
2109
|
+
* ``gen_ai.usage.*`` incl. the cache/reasoning buckets the pricing path
|
|
2110
|
+
* reads, ``gen_ai.tool.*``, ``gen_ai.input/output.messages``) — not a
|
|
2111
|
+
* replay-specific dialect.
|
|
2112
|
+
*
|
|
2113
|
+
* IDs are SHA-256-derived from the session identity, so re-exporting the same
|
|
2114
|
+
* transcript is idempotent: the receiver upserts on
|
|
2115
|
+
* ``(project_id, trace_id, span_id)``.
|
|
2116
|
+
*/
|
|
2117
|
+
|
|
2118
|
+
type OtlpAttributeValue = {
|
|
2119
|
+
stringValue: string;
|
|
2120
|
+
} | {
|
|
2121
|
+
intValue: string;
|
|
2122
|
+
} | {
|
|
2123
|
+
boolValue: boolean;
|
|
2124
|
+
};
|
|
2125
|
+
type OtlpAttribute = {
|
|
2126
|
+
key: string;
|
|
2127
|
+
value: OtlpAttributeValue;
|
|
2128
|
+
};
|
|
2129
|
+
type OtlpSpan = {
|
|
2130
|
+
traceId: string;
|
|
2131
|
+
spanId: string;
|
|
2132
|
+
parentSpanId?: string;
|
|
2133
|
+
name: string;
|
|
2134
|
+
kind: number;
|
|
2135
|
+
startTimeUnixNano: string;
|
|
2136
|
+
endTimeUnixNano: string;
|
|
2137
|
+
attributes: OtlpAttribute[];
|
|
2138
|
+
status: {
|
|
2139
|
+
code: number;
|
|
2140
|
+
};
|
|
2141
|
+
};
|
|
2142
|
+
type OtlpTracesPayload = {
|
|
2143
|
+
resourceSpans: Array<{
|
|
2144
|
+
resource: {
|
|
2145
|
+
attributes: OtlpAttribute[];
|
|
2146
|
+
};
|
|
2147
|
+
scopeSpans: Array<{
|
|
2148
|
+
scope: {
|
|
2149
|
+
name: string;
|
|
2150
|
+
version: string;
|
|
2151
|
+
};
|
|
2152
|
+
spans: OtlpSpan[];
|
|
2153
|
+
}>;
|
|
2154
|
+
}>;
|
|
2155
|
+
};
|
|
2156
|
+
type TranscriptReplayOptions = {
|
|
2157
|
+
/** Trace id (32 lowercase hex). Default: deterministic from source + session id. */
|
|
2158
|
+
traceId?: string;
|
|
2159
|
+
/** Parent for the first turn's interaction span — adapter capture mode nests it under the live task.turn span. */
|
|
2160
|
+
parentSpanId?: string;
|
|
2161
|
+
/** Run list label (`apo.run.flow_name`). Default: "<source> session <id prefix>". */
|
|
2162
|
+
flowName?: string;
|
|
2163
|
+
/** Run tags (`apo.run.tags`). Default: ["transcript-replay", source]. */
|
|
2164
|
+
tags?: string[];
|
|
2165
|
+
};
|
|
2166
|
+
declare function transcriptSessionToOtlp(session: ParsedTranscriptSession, options?: TranscriptReplayOptions): OtlpTracesPayload;
|
|
2167
|
+
|
|
2168
|
+
/**
|
|
2169
|
+
* OTLP export for replayed transcripts.
|
|
2170
|
+
*
|
|
2171
|
+
* Posts an OTLP/JSON traces payload to apo's public OTLP endpoint using the
|
|
2172
|
+
* same auth the live exporters use. Auth mode decides what the trace becomes:
|
|
2173
|
+
*
|
|
2174
|
+
* - API key (CLI import): the trace lands as an unclaimed project run.
|
|
2175
|
+
* - Attempt/service token (adapter capture): the replayed spans join the live
|
|
2176
|
+
* task run's trace — the runner's root span already carries the claim.
|
|
2177
|
+
*
|
|
2178
|
+
* 5xx and network failures are retried; a 4xx is a caller bug (bad token,
|
|
2179
|
+
* malformed payload) and fails fast with the response body excerpt.
|
|
2180
|
+
*/
|
|
2181
|
+
|
|
2182
|
+
declare class TranscriptReplayError extends Error {
|
|
2183
|
+
readonly status?: number;
|
|
2184
|
+
constructor(message: string, status?: number);
|
|
2185
|
+
}
|
|
2186
|
+
type ExportOtlpTracesOptions = {
|
|
2187
|
+
/** apo base URL (e.g. http://localhost:8000); a full …/v1/traces URL is accepted verbatim. */
|
|
2188
|
+
endpoint: string;
|
|
2189
|
+
/** API key or attempt token — sent as the OTLP Authorization bearer. */
|
|
2190
|
+
token: string;
|
|
2191
|
+
/** Per-request timeout. Default 30s. */
|
|
2192
|
+
timeoutMs?: number;
|
|
2193
|
+
/** Extra attempts after the first on 5xx/network failure. Default 2. */
|
|
2194
|
+
retries?: number;
|
|
2195
|
+
};
|
|
2196
|
+
/** Normalize an apo base URL into the public OTLP traces endpoint. */
|
|
2197
|
+
declare function resolveOtlpTracesUrl(base: string): string;
|
|
2198
|
+
declare function exportOtlpTraces(payload: OtlpTracesPayload, options: ExportOtlpTracesOptions): Promise<void>;
|
|
2199
|
+
|
|
2200
|
+
export { type AISDKResult, type AdapterDefinition, type AdapterRuntimeState, type AdapterSession, type AgentBudget, type AgentEvidence, type AgentJudgeOptions, type AgentJudgeOutcome, type AgentJudgeSession, type AgentJudgeStep, type AgentTaskCliOptions, type AgentTaskRunConfiguration, AgentTaskRunError, type AgentTaskRunSummary, type AgentTaskRuntime, AgentTaskTraceContext, AgentTaskTraceOptions, type AgentTurnResult, type AnthropicMessage, type ApoRunContext, ApoSpanProcessor, type ArtifactUploadConfig, type CheckCompaction, type CheckContext, type CheckGroup, type CleanupContext, type CollectDeliverablesContext, type CollectedDeliverables, type DeliverableDefinition, type DeliverableSummary, type DeliverableValidationResult, type DescribeRegistration, type DurationBudgetOptions, type EvidenceFingerprint, type ExportOtlpTracesOptions, type FileArtifact, type FileArtifactOptions, type FileEntry, type Flow, type FlowEvent, FlowView, type InitializeContext, JUDGE_SEGMENT_LIMIT, type JudgeConfig, type JudgeContext, type JudgePromptBuilder, type JudgeScope, type JudgeToolsConfig, type LoadedTask, type ManifestFile, type ManifestFileInput, type Matcher, type McpHttpTransport, type McpServerConfig, type McpStdioTransport, type ModeClass, type NameMatcher, type OpenAIMessage, type OtlpAttribute, type OtlpAttributeValue, type OtlpSpan, type OtlpTracesPayload, type ParsedTranscriptSession, type PreparedTaskResult, RECEIVED_VALUE_LIMIT, type RegisterApoTracingOptions, type RejudgeCheckStability, type RejudgeEndpoints, RejudgeError, type RejudgeOptions, type RejudgeOutcome, type RunTaskOptions, type StartSessionContext, TEST_METHOD_NAMES, type TaskConfig, type TaskDefinition, type TaskEvaluationResult, TaskFiles, type TaskRevisionManifestV1, type TaskRunResult, type TaskScope, type TaskTranscript, type TaskTranscriptTurn, type TestContext, type TestRegistration, type TokenBudgetOptions, type ToolCallOptions, type ToolCallStatus, TranscriptReplayError, type TranscriptReplayOptions, type TranscriptSource, type TranscriptToolCall, type TranscriptTurn, type TranscriptUsage, type TurnContext, type TurnFn, type TurnRecord, type TypedAdapterDefinition, type ValueMatcher, buildManifest, canonicalManifestJson, compactChecksForSubmission, connectMcpServers, contentSha256, defineAdapter, defineTask, describe, discoverAgentTaskDirs, equals, expandSecretPlaceholders, exportOtlpTraces, fileArtifact, filePaths, fromAISDK, fromAnthropicMessages, fromOpenAIMessages, getActiveApoRun, getTaskTurn, includes, isFileArtifact, loadTask, loadTaskRuntime, matchValue, matches, normalizeManifestPath, parseAgentTaskCliArgs, parseClaudeCodeTranscript, parseCodexTranscript, persistFileArtifacts, registerApoTracing, rejudgeTaskRun, resetApoTracing, resetFlowChecks, resetTaskRegistry, resetTaskTurn, resolveMcpServerPaths, resolveOtlpTracesUrl, resolveTurn, runAgentTaskCli, runTask, runTaskDir, satisfies, sha256Hex, similarity, task, defineCheck as test, transcriptSessionToOtlp, turn, withApoRun, withApoRunSync };
|