@apo-ai/sdk 0.8.0 → 0.9.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 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)`, `assert(label, predicate)`.
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-CKB3SUDO.js";
6
- import "../../chunk-HLRXQAZ5.js";
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[];
@@ -797,6 +890,19 @@ type ToolCallOptions = {
797
890
  output?: ValueMatcher<unknown>;
798
891
  status?: "ok" | "error";
799
892
  };
893
+ /** Scope for duration budgets: the whole run, or one Task Turn (1-based). */
894
+ type DurationBudgetOptions = {
895
+ turn?: number;
896
+ };
897
+ /**
898
+ * Scope for token budgets. Tokens are the agent's: usage inside `task.turn`
899
+ * spans, summed over every turn or only `turn`. `kind` defaults to `"total"`
900
+ * (input + output).
901
+ */
902
+ type TokenBudgetOptions = {
903
+ turn?: number;
904
+ kind?: TokenKind;
905
+ };
800
906
  /**
801
907
  * LLM judge model config for `t.judge(...)` calls in checks.ts. Threaded
802
908
  * through `runTask({ judge })` from the caller — the runner has no opinion
@@ -850,8 +956,15 @@ interface TestContext {
850
956
  messageIncludes(token: string | RegExp): void;
851
957
  /** Asserts the run took at most `n` turns — anti-flail. */
852
958
  maxTurns(n: number): void;
853
- /** Asserts the run took at most `n` milliseconds — anti-flail. */
854
- maxDurationMs(n: number): void;
959
+ /**
960
+ * Asserts the run took at most `n` milliseconds — anti-flail. With
961
+ * `{ turn }`, bounds that one Task Turn instead.
962
+ */
963
+ maxDurationMs(n: number, opts?: DurationBudgetOptions): void;
964
+ /** Asserts the agent spent at most `n` tokens (whole run, or `{ turn }`). */
965
+ maxTokens(n: number, opts?: TokenBudgetOptions): void;
966
+ /** Asserts the agent spent at least `n` tokens (whole run, or `{ turn }`). */
967
+ minTokens(n: number, opts?: TokenBudgetOptions): void;
855
968
  /** Escape hatch for a named predicate over the complete normalized run. */
856
969
  assert(label: string, predicate: (flow: TraceView) => boolean): void;
857
970
  /** Grades any value (a deliverable, parsed JSON, anything) with a matcher. */
@@ -867,10 +980,22 @@ interface TestContext {
867
980
  * merging field-by-field onto the config threaded in via ``runTask({ judge })``
868
981
  * — set ``{ model }`` to escalate a finicky criterion to a stronger model
869
982
  * without switching the whole run. Absent fields inherit from the base config.
983
+ *
984
+ * ``opts.secondJudgeValue`` grades a smaller view with the second judge
985
+ * only, when the full value exceeds its context limit: the primary judge
986
+ * still sees all of ``value``, so other criteria that need the complete
987
+ * deliverable are unaffected.
870
988
  */
871
989
  judge(values: unknown | unknown[], instruction: string, opts?: {
872
990
  label?: string;
873
991
  judge?: Partial<JudgeConfig>;
992
+ /**
993
+ * What the second judge reads instead of ``values`` — e.g. the
994
+ * tracked-changes section of a redline when the whole marked-up
995
+ * document is too large for the second judge's context. Absent,
996
+ * the second judge sees exactly what the primary judge sees.
997
+ */
998
+ secondJudgeValue?: unknown | unknown[];
874
999
  }): Promise<void>;
875
1000
  /**
876
1001
  * Agentic judge: a tool-using LLM session that investigates the run's own
@@ -900,7 +1025,7 @@ interface TestContext {
900
1025
  * adding a method to the interface without registering it here is a type
901
1026
  * error, and vice versa. See ``tests/test-context-methods.test.ts``.
902
1027
  */
903
- declare const TEST_METHOD_NAMES: readonly ["calledTool", "notCalledTool", "toolOrder", "usedNoTools", "maxToolCalls", "noFailedActions", "loadedSkill", "calledSubagent", "messageIncludes", "maxTurns", "maxDurationMs", "assert", "check", "judge", "agent"];
1028
+ declare const TEST_METHOD_NAMES: readonly ["calledTool", "notCalledTool", "toolOrder", "usedNoTools", "maxToolCalls", "noFailedActions", "loadedSkill", "calledSubagent", "messageIncludes", "maxTurns", "maxDurationMs", "maxTokens", "minTokens", "assert", "check", "judge", "agent"];
904
1029
 
905
1030
  type TaskDefinition<TAdapterName extends string = string, TDeliverable extends string = string> = {
906
1031
  id: string;
@@ -1456,6 +1581,8 @@ interface RejudgeOutcome {
1456
1581
  /** Full check results from the primary (first) sample. */
1457
1582
  checks: EvaluationItemResult[];
1458
1583
  pass: boolean;
1584
+ /** Every failing check got no answer from the judge — see {@link TaskEvaluationResult.noVerdict}. */
1585
+ noVerdict?: true;
1459
1586
  /** Only meaningful with samples > 1; ordered like the primary sample. */
1460
1587
  stability: RejudgeCheckStability[];
1461
1588
  /** False when the trace projection was unreadable — trajectory assertions were unsupported. */
@@ -1487,6 +1614,8 @@ type AgentTaskRunSummary = {
1487
1614
  taskDir: string;
1488
1615
  taskId: string;
1489
1616
  pass: boolean;
1617
+ /** Every failing check got no answer from the judge — see `TaskEvaluationResult.noVerdict`. */
1618
+ noVerdict?: true;
1490
1619
  checks: EvaluationItemResult[];
1491
1620
  /** Adapter that ran the task. Forwarded to the backend when recording locally. */
1492
1621
  adapterName?: string;
@@ -1741,4 +1870,4 @@ declare function canonicalManifestJson(manifest: TaskRevisionManifestV1): string
1741
1870
  /** SHA-256 (lowercase hex) of the canonical manifest JSON's UTF-8 bytes. */
1742
1871
  declare function contentSha256(manifest: TaskRevisionManifestV1): string;
1743
1872
 
1744
- 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 };
1873
+ 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 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 TokenBudgetOptions, 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 };