@apo-ai/sdk 0.5.0 → 0.7.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 +42 -73
- package/dist/agent-task/integrations/ai-sdk.d.ts +6 -6
- package/dist/agent-task/integrations/ai-sdk.js +1 -1
- package/dist/agent-task/integrations/anthropic.d.ts +1 -1
- package/dist/agent-task/integrations/openai.d.ts +3 -3
- package/dist/agent-task/integrations/openai.js +1 -1
- package/dist/agent-task/public.d.ts +258 -12
- package/dist/agent-task/public.js +1132 -350
- package/dist/agent-task/public.js.map +1 -1
- package/dist/{chunk-DT2LMB7O.js → chunk-6ZRW5IW6.js} +1 -1
- package/dist/chunk-6ZRW5IW6.js.map +1 -0
- package/dist/{chunk-PMYLL2H4.js → chunk-GETY34VI.js} +1 -1
- package/dist/chunk-GETY34VI.js.map +1 -0
- package/dist/{chunk-HKLBPIB4.js → chunk-QHRWPVPZ.js} +2 -1
- package/dist/chunk-QHRWPVPZ.js.map +1 -0
- package/dist/otel/index.d.ts +3 -4
- package/dist/otel/index.js +1 -1
- package/dist/{tracing-D5Yhzq8e.d.ts → tracing-DVLUqD-i.d.ts} +3 -1
- package/package.json +26 -7
- package/dist/chunk-DT2LMB7O.js.map +0 -1
- package/dist/chunk-HKLBPIB4.js.map +0 -1
- package/dist/chunk-PMYLL2H4.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
# apo SDK
|
|
2
2
|
|
|
3
|
-
TypeScript/JavaScript SDK for
|
|
4
|
-
|
|
3
|
+
TypeScript/JavaScript SDK for [apo](https://github.com/samikuikka/apo), the
|
|
4
|
+
testing and engineering system that turns expert knowledge into executable
|
|
5
|
+
capability specifications for agent harnesses. The task API runs a real harness
|
|
6
|
+
against that definition of done; the tracing API preserves the evidence a human
|
|
7
|
+
or coding agent needs to improve it. The SDK's entry points:
|
|
5
8
|
|
|
6
|
-
- **`@apo-ai/sdk`** — config + error types shared across the surface.
|
|
7
9
|
- **`@apo-ai/sdk/otel`** — OpenTelemetry-native tracing. Wrap your LLM calls and
|
|
8
10
|
agent steps so they land in apo as structured spans, then attach scores.
|
|
9
|
-
- **`@apo-ai/sdk/agent-task`** — the
|
|
10
|
-
adapters, and
|
|
11
|
-
|
|
11
|
+
- **`@apo-ai/sdk/agent-task`** — the primary capability-testing surface. Define
|
|
12
|
+
tasks, adapters, and tests; run them against the real harness and collect a
|
|
13
|
+
verdict with structured evidence.
|
|
14
|
+
- **`@apo-ai/sdk/agent-task/integrations/{ai-sdk,openai,anthropic}`** —
|
|
15
|
+
per-framework tracing wrappers re-exported for direct import.
|
|
12
16
|
|
|
13
17
|
## Installation
|
|
14
18
|
|
|
@@ -36,57 +40,23 @@ no long-lived npm token is stored in the repository.
|
|
|
36
40
|
|
|
37
41
|
## Configuration
|
|
38
42
|
|
|
39
|
-
`
|
|
40
|
-
|
|
41
|
-
| Field | Env var (server) | Env var (Next.js, browser-safe) | Required |
|
|
42
|
-
|-------------|-----------------------------|--------------------------------------|----------|
|
|
43
|
-
| `endpoint` | `APO_BACKEND_URL` | `NEXT_PUBLIC_APO_BACKEND_URL` | yes |
|
|
44
|
-
| `project` | `APO_PROJECT` | `NEXT_PUBLIC_APO_PROJECT` | yes |
|
|
45
|
-
| `publicKey` | `APO_PUBLIC_KEY` | — *(server-side only — see below)* | two-key |
|
|
46
|
-
| `secretKey` | `APO_SECRET_KEY` | — | two-key |
|
|
47
|
-
| `apiKey` | `APO_API_KEY` | — | legacy |
|
|
48
|
-
|
|
49
|
-
The Next.js (`NEXT_PUBLIC_*`) variants are read first, then the plain server
|
|
50
|
-
variants. `apiKey` is the legacy single-key format (`sk-…`); prefer the
|
|
51
|
-
two-key model (`publicKey` + `secretKey`, generated as `pk-apo-…` / `sk-apo-…`
|
|
52
|
-
in the dashboard).
|
|
53
|
-
|
|
54
|
-
there is no browser-safe variant of `APO_PUBLIC_KEY`. The public
|
|
55
|
-
identifier alone does not authorize ingestion, and exposing it in a
|
|
56
|
-
browser bundle creates a misleading direct-browser integration.
|
|
57
|
-
`NEXT_PUBLIC_APO_PUBLIC_KEY` is intentionally not read. Telemetry
|
|
58
|
-
submission always requires both halves of an API-key pair sent as HTTP
|
|
59
|
-
Basic (`base64("pk-apo-…:sk-apo-…")`); the SDK never synthesizes partial
|
|
60
|
-
Basic credentials from only one half.
|
|
43
|
+
The tracing surface (`@apo-ai/sdk/otel`) reads credentials from environment
|
|
44
|
+
variables when they are not passed explicitly:
|
|
61
45
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
## API reference — `@apo-ai/sdk`
|
|
69
|
-
|
|
70
|
-
The root entry is intentionally thin: shared types + config + errors. The
|
|
71
|
-
actual tracing surface lives at `@apo-ai/sdk/otel`.
|
|
72
|
-
|
|
73
|
-
### Types
|
|
74
|
-
|
|
75
|
-
The trace/observation parameter types used by the OTel helpers:
|
|
76
|
-
`CreateTraceParams`, `CreateSpanParams`, `EndSpanParams`, `TraceRunContext`,
|
|
77
|
-
`TraceRunOptions`, `TraceStepOptions`, `TraceEventOptions`, `IngestionEvent`,
|
|
78
|
-
`CreateScoreParams`, `ClientOptions`, `ParameterOverrides`, `ObserveOptions`,
|
|
79
|
-
`ObservationContext`.
|
|
80
|
-
|
|
81
|
-
### `readConfig(): EnvConfig`
|
|
82
|
-
|
|
83
|
-
Read endpoint/project/keys from environment variables (table above).
|
|
84
|
-
|
|
85
|
-
### Errors
|
|
46
|
+
| Purpose | Env var | Used for |
|
|
47
|
+
|--------------------------|---------------------|--------------------------------------------|
|
|
48
|
+
| OTLP traces endpoint | `APO_OTLP_ENDPOINT` | Where spans are exported |
|
|
49
|
+
| Project (diagnostic) | `APO_PROJECT` | Resource attribute only — auth owns tenancy |
|
|
50
|
+
| Two-key auth (Basic) | `APO_PUBLIC_KEY` + `APO_SECRET_KEY` | `Authorization: Basic base64(pk:sk)` |
|
|
51
|
+
| Bearer token | `APO_AUTH_TOKEN` | Short-lived task-run tokens; used only when the key pair is absent |
|
|
86
52
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
53
|
+
Telemetry submission always requires both halves of an API-key pair sent as
|
|
54
|
+
HTTP Basic (`base64("pk-apo-…:sk-apo-…")`); the SDK never synthesizes partial
|
|
55
|
+
Basic credentials from only one half. There is deliberately no
|
|
56
|
+
`NEXT_PUBLIC_*` browser variant — a public identifier alone does not
|
|
57
|
+
authorize ingestion, and exposing it in a browser bundle creates a misleading
|
|
58
|
+
direct-browser integration. Use `buildApoAuthHeaders` (exported from
|
|
59
|
+
`@apo-ai/sdk/otel`) to build the headers explicitly.
|
|
90
60
|
|
|
91
61
|
## Tracing — `@apo-ai/sdk/otel`
|
|
92
62
|
|
|
@@ -115,7 +85,7 @@ call this if your app already configures OTel itself).
|
|
|
115
85
|
```ts
|
|
116
86
|
const handle = await configureApoTelemetry({
|
|
117
87
|
takeOwnership: true,
|
|
118
|
-
endpoint: process.env.APO_OTLP_ENDPOINT ?? "http://localhost:8000/v1/
|
|
88
|
+
endpoint: process.env.APO_OTLP_ENDPOINT ?? "http://localhost:8000/api/public/otel/v1/traces",
|
|
119
89
|
// headers, resource attributes, batch/simple processor, etc.
|
|
120
90
|
});
|
|
121
91
|
|
|
@@ -199,12 +169,10 @@ import {
|
|
|
199
169
|
- **`test(id, fn)`** — register a test through the scope returned by `task()`.
|
|
200
170
|
The callback receives `t` (flat, eve-style assertions over the run's flow)
|
|
201
171
|
and the task-selected deliverables, inferred from the adapter.
|
|
202
|
-
- **`runTask(
|
|
203
|
-
`TaskRunResult` (transcript + evaluation).
|
|
172
|
+
- **`runTask(taskDir, options?)`** — execute a task and return a
|
|
173
|
+
`TaskRunResult` (transcript + evaluation). The adapter comes from the task
|
|
174
|
+
definition.
|
|
204
175
|
- **`loadTask(dir)` / `discoverAgentTaskDirs()`** — load tasks from disk.
|
|
205
|
-
- **`createAgentTaskTraceClient(config)`** — the adapter-side trace client
|
|
206
|
-
passed into runs; the auth token is supplied by the backend runner via
|
|
207
|
-
`APO_AUTH_TOKEN`.
|
|
208
176
|
|
|
209
177
|
### Testing (`*.eval.ts`)
|
|
210
178
|
|
|
@@ -277,8 +245,8 @@ anything). Matchers: `includes(substring|RegExp)`, `equals(value)` (deep),
|
|
|
277
245
|
`satisfies(predicate, label)`, `similarity(expected, threshold = 0.8)` (fuzzy,
|
|
278
246
|
normalized Levenshtein).
|
|
279
247
|
|
|
280
|
-
For apo tasks the flow is built automatically from the run's trace
|
|
281
|
-
|
|
248
|
+
For apo tasks the flow is built automatically from the run's trace
|
|
249
|
+
projection — no extra wiring.
|
|
282
250
|
|
|
283
251
|
**`t.judge(value, instruction)` — LLM-backed assertions.** Configure the judge
|
|
284
252
|
with `runTask(dir, { judge: { model, apiKey?, baseURL? } })`, or set
|
|
@@ -297,21 +265,22 @@ never revealed. The SDK appends its JSON response contract to any custom
|
|
|
297
265
|
`system` constant per task and vary only `user` to preserve the cached prompt
|
|
298
266
|
prefix across a task's criteria (issue #161).
|
|
299
267
|
|
|
300
|
-
**
|
|
301
|
-
|
|
268
|
+
**Agents not built on apo's adapter.** `fromOpenAIMessages(messages)`,
|
|
269
|
+
`fromAnthropicMessages(messages)`, and `fromAISDK(result)` convert another
|
|
270
|
+
framework's output into the neutral `Flow` format so it can be inspected with
|
|
271
|
+
`FlowView`:
|
|
302
272
|
|
|
303
273
|
```ts
|
|
304
|
-
import {
|
|
305
|
-
import { fromAISDK } from "@apo-ai/sdk/agent-task"; // or fromOpenAIMessages / fromAnthropicMessages
|
|
274
|
+
import { fromAISDK, FlowView } from "@apo-ai/sdk/agent-task";
|
|
306
275
|
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
276
|
+
const view = new FlowView(fromAISDK(myGenerateTextResult));
|
|
277
|
+
view.toolNamesInOrder; // e.g. ["read_file", "search_content"]
|
|
278
|
+
view.reply; // last assistant message text
|
|
310
279
|
```
|
|
311
280
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
281
|
+
These normalizers are **deprecated** compatibility adapters — the canonical
|
|
282
|
+
path emits standard OTel spans (see the tracing integrations above), which
|
|
283
|
+
apo projects into the same view without a Flow intermediary.
|
|
315
284
|
|
|
316
285
|
### CLI / runtime
|
|
317
286
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as AgentTaskTraceContext } from '../../tracing-
|
|
1
|
+
import { A as AgentTaskTraceContext } from '../../tracing-DVLUqD-i.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Vercel AI SDK tracing integration for apo.
|
|
@@ -6,9 +6,9 @@ import { A as AgentTaskTraceContext } from '../../tracing-D5Yhzq8e.js';
|
|
|
6
6
|
* Pass the result of {@link createApoTracer} to `generateText`'s
|
|
7
7
|
* `experimental_telemetry` option. The AI SDK already emits OpenTelemetry
|
|
8
8
|
* spans natively (e.g. `ai.toolCall`, `ai.generateText`); this tracer
|
|
9
|
-
* intercepts them and translates them into apo trace spans
|
|
10
|
-
*
|
|
11
|
-
* `t.
|
|
9
|
+
* intercepts them and translates them into apo trace spans, where they
|
|
10
|
+
* become the TOOL/GENERATION observations that `t.calledTool`,
|
|
11
|
+
* `t.noFailedActions`, and `t.messageIncludes` read.
|
|
12
12
|
*
|
|
13
13
|
* The adapter author writes zero manual span code.
|
|
14
14
|
*
|
|
@@ -109,8 +109,8 @@ interface CreateApoTracerOptions {
|
|
|
109
109
|
* - `ai.generateText` → a GENERATION span (so `t.messageIncludes(text)` works)
|
|
110
110
|
* and error status → `t.noFailedActions()` catches it
|
|
111
111
|
*
|
|
112
|
-
* Other spans (`ai.generateText.doGenerate`, etc.) are ignored —
|
|
113
|
-
*
|
|
112
|
+
* Other spans (`ai.generateText.doGenerate`, etc.) are ignored — only
|
|
113
|
+
* TOOL/AGENT/GENERATION observation types are visible to `t.*` assertions.
|
|
114
114
|
*/
|
|
115
115
|
declare function createApoTracer(options: CreateApoTracerOptions): {
|
|
116
116
|
isEnabled: true;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as AgentTaskTraceContext } from '../../tracing-
|
|
1
|
+
import { A as AgentTaskTraceContext } from '../../tracing-DVLUqD-i.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* OpenAI JS SDK tracing integration for apo.
|
|
@@ -8,8 +8,8 @@ import { A as AgentTaskTraceContext } from '../../tracing-D5Yhzq8e.js';
|
|
|
8
8
|
* any manual span code in the adapter.
|
|
9
9
|
*
|
|
10
10
|
* Uses a Proxy to intercept the `create` method, then emits GENERATION +
|
|
11
|
-
* TOOL spans through the trace context
|
|
12
|
-
*
|
|
11
|
+
* TOOL spans through the trace context, where they become the observations
|
|
12
|
+
* that `t.calledTool` reads.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* ```ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as AgentTaskTraceContext, a as AgentTaskTraceOptions } from '../tracing-
|
|
1
|
+
import { A as AgentTaskTraceContext, a as AgentTaskTraceOptions } from '../tracing-DVLUqD-i.js';
|
|
2
2
|
export { CreateApoTracerOptions, createApoTracer } from './integrations/ai-sdk.js';
|
|
3
3
|
export { CreateApoOpenAIOptions, createApoOpenAI } from './integrations/openai.js';
|
|
4
4
|
export { CreateApoAnthropicOptions, createApoAnthropic } from './integrations/anthropic.js';
|
|
@@ -323,6 +323,13 @@ type AssertionOutcome = "pass" | "fail" | "unsupported";
|
|
|
323
323
|
type JudgeMetadata = {
|
|
324
324
|
/** Model identifier, e.g. ``"google/gemini-2.5-flash-lite"``. */
|
|
325
325
|
model?: string;
|
|
326
|
+
/**
|
|
327
|
+
* Which response contract elicited this judgment (#163): reasoning-first
|
|
328
|
+
* (the default) or the legacy verdict-first (``pass`` before
|
|
329
|
+
* ``reasoning``, via ``APO_JUDGE_VERDICT_FIRST``). Group comparisons
|
|
330
|
+
* across the default flip on this field, not on time.
|
|
331
|
+
*/
|
|
332
|
+
contract?: "verdict-first" | "reasoning-first";
|
|
326
333
|
/** The messages sent to the judge LLM. */
|
|
327
334
|
prompt?: {
|
|
328
335
|
system?: string;
|
|
@@ -343,6 +350,102 @@ type JudgeMetadata = {
|
|
|
343
350
|
latency_ms?: number;
|
|
344
351
|
/** Temperature or other sampling parameters, if relevant. */
|
|
345
352
|
temperature?: number;
|
|
353
|
+
/**
|
|
354
|
+
* Agentic-judge session transcript (`t.agent`). Absent for single-shot
|
|
355
|
+
* `t.judge` calls. Records every investigation step (tool calls with
|
|
356
|
+
* truncated results), the session outcome, per-step usage, and the
|
|
357
|
+
* content-hashed evidence manifest (replay audit backbone).
|
|
358
|
+
*/
|
|
359
|
+
session?: AgentJudgeSession;
|
|
360
|
+
/**
|
|
361
|
+
* Second-grader evidence: a typed-decision model (Jev via OpenRouter's
|
|
362
|
+
* `/alpha/decisions`) graded the same deliverable + instruction alongside
|
|
363
|
+
* the primary judge. Opt-in via `APO_SECOND_JUDGE_MODEL`. The primary
|
|
364
|
+
* verdict is never changed by it — the point is agreement and confidence
|
|
365
|
+
* as extra signals per check, not a second vote.
|
|
366
|
+
*/
|
|
367
|
+
secondJudge?: SecondJudgeEvidence;
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* Evidence from the second grader. `error` is set when the decisions
|
|
371
|
+
* endpoint could not be reached — a failed second opinion must never
|
|
372
|
+
* affect the check's verdict.
|
|
373
|
+
*/
|
|
374
|
+
type SecondJudgeEvidence = {
|
|
375
|
+
/** Decision-model id that graded, e.g. `typesafe/jev-1.13`. */
|
|
376
|
+
model: string;
|
|
377
|
+
/** The typed verdict the model returned. */
|
|
378
|
+
choice?: "pass" | "fail";
|
|
379
|
+
/** P(pass) from the model's probability distribution over the choice. */
|
|
380
|
+
passProbability?: number;
|
|
381
|
+
/** The model's own confidence in its choice (0-1). */
|
|
382
|
+
confidence?: number;
|
|
383
|
+
/** Input tokens billed for the decision, when the provider reports usage. */
|
|
384
|
+
inputTokens?: number;
|
|
385
|
+
/** Cost in USD, when the provider reports it. */
|
|
386
|
+
costUsd?: number;
|
|
387
|
+
/** Wall-clock latency of the decision call in milliseconds. */
|
|
388
|
+
latencyMs?: number;
|
|
389
|
+
/** Why no verdict was recorded (transport/HTTP/parse failure). */
|
|
390
|
+
error?: string;
|
|
391
|
+
};
|
|
392
|
+
/**
|
|
393
|
+
* One investigation step of an agentic judge session. Tool results are
|
|
394
|
+
* truncated text; the sha256 + byte size are always kept so the full value
|
|
395
|
+
* stays recoverable from the evidence store (the transcript is an index,
|
|
396
|
+
* not a copy).
|
|
397
|
+
*/
|
|
398
|
+
type AgentJudgeStep = {
|
|
399
|
+
index: number;
|
|
400
|
+
tool_calls?: {
|
|
401
|
+
name: string;
|
|
402
|
+
input?: string;
|
|
403
|
+
result?: string;
|
|
404
|
+
result_sha256?: string;
|
|
405
|
+
result_bytes?: number;
|
|
406
|
+
}[];
|
|
407
|
+
/** Assistant prose, if the model produced text alongside tool calls. */
|
|
408
|
+
text?: string;
|
|
409
|
+
tokens?: {
|
|
410
|
+
input?: number;
|
|
411
|
+
output?: number;
|
|
412
|
+
cost?: number;
|
|
413
|
+
};
|
|
414
|
+
latency_ms?: number;
|
|
415
|
+
};
|
|
416
|
+
/** How an agentic judge session ended. */
|
|
417
|
+
type AgentJudgeOutcome = "verdict" | "budget_exhausted" | "error";
|
|
418
|
+
/**
|
|
419
|
+
* A fingerprint of one piece of evidence the judge consumed — the
|
|
420
|
+
* content-addressed manifest. Never truncated.
|
|
421
|
+
*/
|
|
422
|
+
type EvidenceFingerprint = {
|
|
423
|
+
step: number;
|
|
424
|
+
tool: string;
|
|
425
|
+
args_sha256?: string;
|
|
426
|
+
result_sha256: string;
|
|
427
|
+
result_bytes: number;
|
|
428
|
+
};
|
|
429
|
+
/** Transcript-shaped record of one `t.agent` session. */
|
|
430
|
+
type AgentJudgeSession = {
|
|
431
|
+
/** Tool names offered to the judge. */
|
|
432
|
+
tools?: string[];
|
|
433
|
+
/** Turn-0 context: system briefing and the rubric (user message). */
|
|
434
|
+
briefing?: {
|
|
435
|
+
system?: string;
|
|
436
|
+
rubric?: string;
|
|
437
|
+
};
|
|
438
|
+
/** Ordered investigation steps. */
|
|
439
|
+
steps?: AgentJudgeStep[];
|
|
440
|
+
outcome: AgentJudgeOutcome;
|
|
441
|
+
/** Evidence manifest — what this session consumed, hashed. Never truncated. */
|
|
442
|
+
evidence?: EvidenceFingerprint[];
|
|
443
|
+
usage?: {
|
|
444
|
+
steps?: number;
|
|
445
|
+
input_tokens?: number;
|
|
446
|
+
output_tokens?: number;
|
|
447
|
+
cache_read_tokens?: number;
|
|
448
|
+
};
|
|
346
449
|
};
|
|
347
450
|
/**
|
|
348
451
|
* A source location for a failed code check — lets the dashboard render the
|
|
@@ -386,7 +489,7 @@ type AssertionResult = {
|
|
|
386
489
|
*/
|
|
387
490
|
received?: unknown;
|
|
388
491
|
location?: CheckLocation;
|
|
389
|
-
evaluator_type?: "llm" | "code";
|
|
492
|
+
evaluator_type?: "llm" | "code" | "agent";
|
|
390
493
|
judge?: JudgeMetadata;
|
|
391
494
|
};
|
|
392
495
|
/**
|
|
@@ -416,7 +519,7 @@ type EvaluationItemResult = {
|
|
|
416
519
|
* - ``"regex"`` — pattern matching
|
|
417
520
|
* Older persisted results may still use ``"llm"`` at this level.
|
|
418
521
|
*/
|
|
419
|
-
evaluator_type?: "llm" | "code" | "regex";
|
|
522
|
+
evaluator_type?: "llm" | "code" | "agent" | "regex";
|
|
420
523
|
/**
|
|
421
524
|
* If this check was judged by an LLM, details about the judge call
|
|
422
525
|
* (model, prompt, response, tokens, cost, latency). Populated by the
|
|
@@ -443,10 +546,10 @@ type EvaluationItemResult = {
|
|
|
443
546
|
*/
|
|
444
547
|
assertions?: AssertionResult[];
|
|
445
548
|
/**
|
|
446
|
-
* the snapshot source the checks ran against.
|
|
447
|
-
* ``"legacy-flow"``
|
|
448
|
-
*
|
|
449
|
-
*
|
|
549
|
+
* the snapshot source the checks ran against. ``"local"`` marks locally
|
|
550
|
+
* recorded snapshots; ``"legacy-flow"`` survives only on results recorded
|
|
551
|
+
* by the removed Flow-path loader. Absent on projection-first results
|
|
552
|
+
* (the default).
|
|
450
553
|
*/
|
|
451
554
|
source?: "canonical" | "local" | "legacy-flow";
|
|
452
555
|
/**
|
|
@@ -557,6 +660,101 @@ type JudgePromptBuilder = (ctx: JudgeContext) => {
|
|
|
557
660
|
user?: string;
|
|
558
661
|
};
|
|
559
662
|
|
|
663
|
+
/** One prior attempt of this task, as frozen at evaluation start. */
|
|
664
|
+
type FrozenRunSummary = {
|
|
665
|
+
id: string;
|
|
666
|
+
status: string;
|
|
667
|
+
passed: boolean | null;
|
|
668
|
+
started_at?: string;
|
|
669
|
+
primary_model?: string | null;
|
|
670
|
+
passed_checks?: number | null;
|
|
671
|
+
failed_checks?: number | null;
|
|
672
|
+
corrected_tests?: unknown[];
|
|
673
|
+
/** True when this entry IS the run under judgment. */
|
|
674
|
+
is_run_under_judgment?: boolean;
|
|
675
|
+
};
|
|
676
|
+
/** A prior run's full check report (merged view, like the run detail page). */
|
|
677
|
+
type HistoryRunDetail = {
|
|
678
|
+
id: string;
|
|
679
|
+
status: string;
|
|
680
|
+
checks: {
|
|
681
|
+
id: string;
|
|
682
|
+
pass: boolean;
|
|
683
|
+
evaluator: string;
|
|
684
|
+
reasoning?: string;
|
|
685
|
+
assertions?: {
|
|
686
|
+
pass: boolean;
|
|
687
|
+
expected?: string;
|
|
688
|
+
received?: string;
|
|
689
|
+
}[];
|
|
690
|
+
}[];
|
|
691
|
+
/** Human corrections recorded against this run; "none" when empty. */
|
|
692
|
+
human_corrections: unknown[] | "none";
|
|
693
|
+
};
|
|
694
|
+
/** The frozen evidence plane handed to every `t.agent` session. */
|
|
695
|
+
type AgentHistoryPlane = {
|
|
696
|
+
/** Prior attempts of this task, frozen at evaluation start. */
|
|
697
|
+
runs: FrozenRunSummary[];
|
|
698
|
+
/**
|
|
699
|
+
* Fetch one prior run's merged check report. The run-under-judgment id
|
|
700
|
+
* returns an honest "you are deciding this run" answer instead of data
|
|
701
|
+
* whose checks are still being evaluated.
|
|
702
|
+
*/
|
|
703
|
+
getRun(runId: string): Promise<HistoryRunDetail | {
|
|
704
|
+
error: string;
|
|
705
|
+
}>;
|
|
706
|
+
/** The backend's id for the run under judgment, when known. */
|
|
707
|
+
selfRunId?: string;
|
|
708
|
+
};
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* The agentic judge — `t.agent`. A tool-using LLM session that investigates
|
|
712
|
+
* the run's own evidence (deliverables, trace) before verdicting, powered by
|
|
713
|
+
* a lazy-loaded Vercel AI SDK engine. The judge semantics live here at the
|
|
714
|
+
* call site; the loop itself is engine-level: forced tool choice plus a
|
|
715
|
+
* done-tool verdict means the only exits are a verdict or the budget — every
|
|
716
|
+
* other ending is recorded as a failure with an explanation.
|
|
717
|
+
*
|
|
718
|
+
* Sessions are stateless per check: no memory crosses sessions (upstream
|
|
719
|
+
* ablations showed remembered judgments cascade errors). Everything the
|
|
720
|
+
* session consumed is recorded as a content-hashed manifest
|
|
721
|
+
* ({@link EvidenceFingerprint}) — the transcript is an index, not a copy.
|
|
722
|
+
*/
|
|
723
|
+
|
|
724
|
+
/** Hard ceilings for one agentic session. Every field overrides a default. */
|
|
725
|
+
type AgentBudget = {
|
|
726
|
+
/** Max LLM turns (steps). Default 12. */
|
|
727
|
+
maxTurns?: number;
|
|
728
|
+
/** Max total tool executions. Default 24. */
|
|
729
|
+
maxToolCalls?: number;
|
|
730
|
+
/** Wall-clock ceiling. Default 300_000 ms. */
|
|
731
|
+
timeoutMs?: number;
|
|
732
|
+
/** Max cumulative bytes served by read/search tools. Default 2 MiB. */
|
|
733
|
+
maxReadBytes?: number;
|
|
734
|
+
};
|
|
735
|
+
/** Options for `t.agent(instruction, opts)`. */
|
|
736
|
+
type AgentJudgeOptions = {
|
|
737
|
+
/** Pre-staged values rendered into turn 0, like `t.judge` values. */
|
|
738
|
+
exhibits?: unknown | unknown[];
|
|
739
|
+
/** Judge config override for this call only (merges field-by-field). */
|
|
740
|
+
judge?: Partial<JudgeConfig>;
|
|
741
|
+
/** Tool families; deliverables are always on. `trace: false` drops get_trace. */
|
|
742
|
+
tools?: {
|
|
743
|
+
trace?: boolean;
|
|
744
|
+
};
|
|
745
|
+
budget?: AgentBudget;
|
|
746
|
+
label?: string;
|
|
747
|
+
};
|
|
748
|
+
/** The local evidence plane a session can investigate. */
|
|
749
|
+
type AgentEvidence = {
|
|
750
|
+
/** The run's deliverables, by name. */
|
|
751
|
+
deliverables: Record<string, unknown>;
|
|
752
|
+
/** The frozen trace projection; absent = no trace evidence plane. */
|
|
753
|
+
view?: TraceView;
|
|
754
|
+
/** This task's prior runs; absent = history plane unavailable. */
|
|
755
|
+
history?: AgentHistoryPlane;
|
|
756
|
+
};
|
|
757
|
+
|
|
560
758
|
/**
|
|
561
759
|
* The assertion surface — `t`. Flat and eve-style: reads the trace (via
|
|
562
760
|
* {@link TraceView}) for behavioural checks and grades explicit values via
|
|
@@ -652,6 +850,21 @@ interface TestContext {
|
|
|
652
850
|
label?: string;
|
|
653
851
|
judge?: Partial<JudgeConfig>;
|
|
654
852
|
}): Promise<void>;
|
|
853
|
+
/**
|
|
854
|
+
* Agentic judge: a tool-using LLM session that investigates the run's own
|
|
855
|
+
* evidence (deliverables via `read_deliverable`/`search_deliverable`, the
|
|
856
|
+
* trace via `get_trace`) before verdicting with `finish_verdict`. Async —
|
|
857
|
+
* the check function must `await` it. Records a single assertion tagged
|
|
858
|
+
* ``evaluator_type: "agent"`` with the full session transcript attached.
|
|
859
|
+
*
|
|
860
|
+
* Unlike `t.judge`, the author states a rubric and the judge gathers its
|
|
861
|
+
* own evidence; `opts.exhibits` optionally pre-stages values into turn 0.
|
|
862
|
+
* The session is budgeted (defaults: 12 turns / 24 tool calls / 300 s /
|
|
863
|
+
* 2 MiB read) and fail-closed: a session that ends without a verdict is a
|
|
864
|
+
* recorded failure, never a silent pass. Costs more and runs minutes, not
|
|
865
|
+
* seconds — reserve it for rubrics that need investigation.
|
|
866
|
+
*/
|
|
867
|
+
agent(instruction: string, opts?: AgentJudgeOptions): Promise<void>;
|
|
655
868
|
}
|
|
656
869
|
/**
|
|
657
870
|
* Canonical names of every assertion method on {@link TestContext}.
|
|
@@ -665,7 +878,7 @@ interface TestContext {
|
|
|
665
878
|
* adding a method to the interface without registering it here is a type
|
|
666
879
|
* error, and vice versa. See ``tests/test-context-methods.test.ts``.
|
|
667
880
|
*/
|
|
668
|
-
declare const TEST_METHOD_NAMES: readonly ["calledTool", "notCalledTool", "toolOrder", "usedNoTools", "maxToolCalls", "noFailedActions", "loadedSkill", "calledSubagent", "messageIncludes", "maxTurns", "maxDurationMs", "assert", "check", "judge"];
|
|
881
|
+
declare const TEST_METHOD_NAMES: readonly ["calledTool", "notCalledTool", "toolOrder", "usedNoTools", "maxToolCalls", "noFailedActions", "loadedSkill", "calledSubagent", "messageIncludes", "maxTurns", "maxDurationMs", "assert", "check", "judge", "agent"];
|
|
669
882
|
|
|
670
883
|
type TaskDefinition<TAdapterName extends string = string, TDeliverable extends string = string> = {
|
|
671
884
|
id: string;
|
|
@@ -927,6 +1140,40 @@ interface PreparedTaskResult {
|
|
|
927
1140
|
*/
|
|
928
1141
|
declare function persistFileArtifacts(deliverables: Record<string, unknown>, config: ArtifactUploadConfig): Promise<PreparedTaskResult>;
|
|
929
1142
|
|
|
1143
|
+
/**
|
|
1144
|
+
* Check submission compaction (issue #175).
|
|
1145
|
+
*
|
|
1146
|
+
* The backend's ``check_report_storage.normalize_check_report`` truncates
|
|
1147
|
+
* every ``received`` over 4 KiB and every judge prompt/response segment over
|
|
1148
|
+
* 16 KiB into a marker before storing anything — the full value never
|
|
1149
|
+
* survives server-side. This module applies the same limits at the producer,
|
|
1150
|
+
* so a task judging N criteria against one large document sends N tiny
|
|
1151
|
+
* markers instead of N copies of the document (a 43 MB result body becomes
|
|
1152
|
+
* single-digit MB). Local rendering keeps the uncompacted values.
|
|
1153
|
+
*
|
|
1154
|
+
* The markers are byte-compatible with the backend's (same field names,
|
|
1155
|
+
* preview length, and hash subject), so server-side normalization passes
|
|
1156
|
+
* them through unchanged and old servers store them as-is.
|
|
1157
|
+
*/
|
|
1158
|
+
|
|
1159
|
+
/** Mirrors backend RECEIVED_VALUE_LIMIT (check_report_storage.py). */
|
|
1160
|
+
declare const RECEIVED_VALUE_LIMIT: number;
|
|
1161
|
+
/** Mirrors backend JUDGE_SEGMENT_LIMIT. */
|
|
1162
|
+
declare const JUDGE_SEGMENT_LIMIT: number;
|
|
1163
|
+
interface CheckCompaction {
|
|
1164
|
+
/** Copy of ``checks`` with oversized fields replaced by markers. */
|
|
1165
|
+
checks: EvaluationItemResult[];
|
|
1166
|
+
/** How many ``received`` values were replaced. */
|
|
1167
|
+
truncatedValues: number;
|
|
1168
|
+
/** How many judge prompt/response segments were replaced. */
|
|
1169
|
+
truncatedSegments: number;
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Return a submission-safe copy of ``checks``. Touched paths are copied;
|
|
1173
|
+
* untouched values are shared. Input is never mutated.
|
|
1174
|
+
*/
|
|
1175
|
+
declare function compactChecksForSubmission(checks: readonly EvaluationItemResult[]): CheckCompaction;
|
|
1176
|
+
|
|
930
1177
|
/**
|
|
931
1178
|
* Flow — the canonical, source-agnostic recording of "what happened" during
|
|
932
1179
|
* an agent run. This is the single substrate the testing framework reads.
|
|
@@ -1018,8 +1265,7 @@ declare class FlowView {
|
|
|
1018
1265
|
* not the primary testing architecture. The canonical path is now the Trace
|
|
1019
1266
|
* Projection snapshot (`TraceProjectionSnapshot` → `TraceView` →
|
|
1020
1267
|
* `runTraceChecks`). These normalizers remain available during the
|
|
1021
|
-
* deprecation period
|
|
1022
|
-
* projection contract. New integrations should emit standard OTel spans
|
|
1268
|
+
* deprecation period. New integrations should emit standard OTel spans
|
|
1023
1269
|
* instead of producing a Flow.
|
|
1024
1270
|
*/
|
|
1025
1271
|
|
|
@@ -1241,7 +1487,7 @@ type DeliverableValidationResult = {
|
|
|
1241
1487
|
*
|
|
1242
1488
|
* The processor is global, but run isolation is maintained via
|
|
1243
1489
|
* {@link AsyncLocalStorage}: {@link getActiveApoRun} returns the current
|
|
1244
|
-
* run's trace context, so each span is routed to the correct run's
|
|
1490
|
+
* run's trace context, so each span is routed to the correct run's trace.
|
|
1245
1491
|
*
|
|
1246
1492
|
* **Design: eager creation, deferred completion.** The apo span is created
|
|
1247
1493
|
* at `onStart` (when initial attributes like tool name and model are
|
|
@@ -1465,4 +1711,4 @@ declare function canonicalManifestJson(manifest: TaskRevisionManifestV1): string
|
|
|
1465
1711
|
/** SHA-256 (lowercase hex) of the canonical manifest JSON's UTF-8 bytes. */
|
|
1466
1712
|
declare function contentSha256(manifest: TaskRevisionManifestV1): string;
|
|
1467
1713
|
|
|
1468
|
-
export { type AISDKResult, type AdapterDefinition, type AdapterRuntimeState, type AdapterSession, type AgentTaskCliOptions, type AgentTaskRunConfiguration, AgentTaskRunError, type AgentTaskRunSummary, type AgentTaskRuntime, AgentTaskTraceContext, AgentTaskTraceOptions, type AgentTurnResult, type AnthropicMessage, type ApoRunContext, ApoSpanProcessor, type ArtifactUploadConfig, type CheckContext, type CheckGroup, type CleanupContext, type CollectDeliverablesContext, type CollectedDeliverables, type DeliverableDefinition, type DeliverableSummary, type DeliverableValidationResult, type DescribeRegistration, type FileArtifact, type FileArtifactOptions, type FileEntry, type Flow, type FlowEvent, FlowView, type InitializeContext, type JudgeConfig, type JudgeContext, type JudgePromptBuilder, type JudgeScope, type LoadedTask, type ManifestFile, type ManifestFileInput, type Matcher, type ModeClass, type NameMatcher, type OpenAIMessage, type PreparedTaskResult, 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 ToolCallOptions, type ToolCallStatus, type TurnContext, type TurnFn, type TurnRecord, type TypedAdapterDefinition, type ValueMatcher, buildManifest, canonicalManifestJson, contentSha256, defineAdapter, defineTask, describe, discoverAgentTaskDirs, equals, fileArtifact, filePaths, fromAISDK, fromAnthropicMessages, fromOpenAIMessages, getActiveApoRun, getTaskTurn, includes, isFileArtifact, loadTask, loadTaskRuntime, matchValue, matches, normalizeManifestPath, parseAgentTaskCliArgs, persistFileArtifacts, registerApoTracing, rejudgeTaskRun, resetApoTracing, resetFlowChecks, resetTaskRegistry, resetTaskTurn, resolveTurn, runAgentTaskCli, runTask, runTaskDir, satisfies, sha256Hex, similarity, task, defineCheck as test, turn, withApoRun, withApoRunSync };
|
|
1714
|
+
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 EvidenceFingerprint, 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 LoadedTask, type ManifestFile, type ManifestFileInput, type Matcher, type ModeClass, type NameMatcher, type OpenAIMessage, 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 ToolCallOptions, type ToolCallStatus, type TurnContext, type TurnFn, type TurnRecord, type TypedAdapterDefinition, type ValueMatcher, buildManifest, canonicalManifestJson, compactChecksForSubmission, contentSha256, defineAdapter, defineTask, describe, discoverAgentTaskDirs, equals, fileArtifact, filePaths, fromAISDK, fromAnthropicMessages, fromOpenAIMessages, getActiveApoRun, getTaskTurn, includes, isFileArtifact, loadTask, loadTaskRuntime, matchValue, matches, normalizeManifestPath, parseAgentTaskCliArgs, persistFileArtifacts, registerApoTracing, rejudgeTaskRun, resetApoTracing, resetFlowChecks, resetTaskRegistry, resetTaskTurn, resolveTurn, runAgentTaskCli, runTask, runTaskDir, satisfies, sha256Hex, similarity, task, defineCheck as test, turn, withApoRun, withApoRunSync };
|