@axlsdk/axl 0.22.3 → 0.23.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/dist/index.d.cts CHANGED
@@ -124,10 +124,23 @@ type ChatOptions = {
124
124
  responseFormat?: ResponseFormat;
125
125
  stop?: string[];
126
126
  signal?: AbortSignal;
127
+ /** @internal Runtime observer for the actual adapter transport lifecycle. */
128
+ requestLifecycle?: {
129
+ /** The request was actually dispatched, after limiter queue and retry backoff. */
130
+ onDispatch?(): void;
131
+ /** A retryable response was received; SDK retry backoff is about to begin. */
132
+ onRetry?(): void;
133
+ };
127
134
  /** How hard should the model try? Primary param for cost/quality tradeoff.
128
135
  * 'none' disables thinking/reasoning (Gemini 3.x: maps to minimal).
129
136
  * Omit to use provider defaults. */
130
137
  effort?: Effort;
138
+ /** Opt in to provider prompt caching of the stable request prefix (system
139
+ * prompt + tool definitions). Anthropic requires an explicit `cache_control`
140
+ * breakpoint; OpenAI and Gemini cache automatically, so this is a no-op
141
+ * there. Off by default: a prefix that changes every call (a system prompt
142
+ * built from `ctx.metadata`) pays the cache-write premium with no reads. */
143
+ promptCache?: boolean;
131
144
  /** Precise thinking token budget (advanced). When set alongside `effort`, overrides the
132
145
  * thinking/reasoning allocation. On Anthropic 4.6, `effort` still controls output quality
133
146
  * independently. On all other providers, `thinkingBudget` fully overrides `effort` for
@@ -187,6 +200,12 @@ type StreamChunk = {
187
200
  cost?: number;
188
201
  /** Provider-specific opaque metadata (e.g. raw Gemini parts with thought signatures). */
189
202
  providerMetadata?: Record<string, unknown>;
203
+ /**
204
+ * Per-call latency breakdown. The `done` chunk is the only channel a
205
+ * stream has back to the runtime, so every terminal `done` must carry it
206
+ * — including the usage-less fallbacks, or a $0 stream loses its timing.
207
+ */
208
+ timing?: CallTiming;
190
209
  };
191
210
  /**
192
211
  * Core provider interface. Every LLM adapter must implement this.
@@ -194,6 +213,8 @@ type StreamChunk = {
194
213
  interface Provider {
195
214
  /** Human-readable name for the provider (e.g. "openai", "anthropic") */
196
215
  readonly name?: string;
216
+ /** @internal Built-in adapters set this when `ChatOptions.requestLifecycle` reports fetch dispatch. */
217
+ readonly reportsRequestLifecycle?: true;
197
218
  /** Coarse, model-aware input metadata for UI/documentation. */
198
219
  inputCapabilities?(model: string): InputModalitySupport;
199
220
  /** Authoritative request-scoped rich-input validation. Omission means text-only. */
@@ -228,6 +249,16 @@ interface Provider {
228
249
  * JSON instruction instead (e.g. Anthropic).
229
250
  */
230
251
  nativeStructuredOutputSupport?(model: string): 'schema' | 'downgraded' | 'lossy' | 'unsupported';
252
+ /**
253
+ * Whether this adapter realizes `ChatOptions.promptCache` for this model --
254
+ * i.e. actually places a cache breakpoint on the request. The runtime only
255
+ * emits the promptCache diagnostics (cold writes with no reads; no cache
256
+ * activity at all) for adapters that declare this, because on providers
257
+ * that cache automatically the absence of cache fields is not a signal.
258
+ * Adapters that omit this method opt out; the built-in Anthropic adapter is
259
+ * the only one that declares it today.
260
+ */
261
+ realizesPromptCache?(model: string): boolean;
231
262
  /**
232
263
  * How this provider resolved the unified `effort` knob for this request.
233
264
  *
@@ -314,11 +345,10 @@ type BudgetResult<T> = {
314
345
  budgetExceeded: boolean;
315
346
  totalCost: number;
316
347
  /**
317
- * True when the block ran a model with no usable cost (unpriced / pricing-table
318
- * miss) that did measurable work. `totalCost` is then a LOWER BOUND — the unknown
319
- * component is omitted. NOTE: this is observability only; cost limits / `hard_stop`
320
- * are NOT enforced on unpriced spend (the enforcement rail never sees it). Token
321
- * budgets are the future fix for governing unpriced models.
348
+ * True when the block included work with no usable cost (for example, an
349
+ * unpriced model or an abandoned dispatched call). `totalCost` is then a LOWER
350
+ * BOUND — the unknown component is omitted. Cost limits / `hard_stop` are NOT
351
+ * enforced on unknown spend because the enforcement rail never sees it.
322
352
  */
323
353
  unpriced: boolean;
324
354
  };
@@ -429,12 +459,20 @@ type AskOptions<T = unknown> = {
429
459
  thinkingBudget?: number;
430
460
  /** Show reasoning summaries in responses. */
431
461
  includeThoughts?: boolean;
462
+ /** Override prompt caching of the stable prefix for this call. */
463
+ promptCache?: boolean;
432
464
  /** Tool choice strategy for this call. */
433
465
  toolChoice?: ToolChoice;
434
466
  /** Stop sequences for this call. */
435
467
  stop?: string[];
436
468
  /** Provider-specific options merged into API requests. Not portable across providers. */
437
469
  providerOptions?: Record<string, unknown>;
470
+ /** Graceful overall budget for this ask. The in-flight provider turn is allowed to finish. */
471
+ timeout?: string;
472
+ /** Abort an in-flight provider request that makes no streaming progress. Unset by default. */
473
+ stallTimeout?: string;
474
+ /** Per-ask hard cancellation signal. It is composed with the context signal and inherited by nested asks. */
475
+ signal?: AbortSignal;
438
476
  };
439
477
  /** Delegate options */
440
478
  type DelegateOptions<T = unknown> = {
@@ -999,7 +1037,7 @@ type AxlEventBase = {
999
1037
  * `memory_recall`): the authoritative charge for this single
1000
1038
  * provider call / tool invocation / embedder call. Summing these
1001
1039
  * across an execution gives the spend — a LOWER BOUND when any call
1002
- * used an unpriced model (its `cost` is `undefined` and contributes
1040
+ * included unknown-cost work (its `cost` is `undefined` and contributes
1003
1041
  * nothing; the owning `ask_end` sets `unpriced: true`).
1004
1042
  *
1005
1043
  * - **Per-ask rollup** (`ask_end`): the SUM of leaf costs emitted
@@ -1089,11 +1127,10 @@ type LegacyAxlEventPayloadV1 = (AxlEventBase & {
1089
1127
  /** Sum of `agent_call_end.cost` + `tool_call_end.cost` WITHIN THIS ASK,
1090
1128
  * excluding nested asks. Nested asks contribute to their own ask_end. */
1091
1129
  cost: number;
1092
- /** True when a cost-bearing leaf in this ask did measurable work but had
1093
- * no usable cost (unpriced model / pricing-table miss). When set, `cost`
1130
+ /** True when a cost-bearing leaf in this ask had no usable cost. When set, `cost`
1094
1131
  * is a LOWER BOUND — the unknown component is not included. Absent ⇒
1095
1132
  * `cost` is exact. Surfaced so dashboards don't render a misleading
1096
- * exact `$0.00` for an ask that used an unpriced model. */
1133
+ * exact `$0.00` for an ask with unknown-cost work. */
1097
1134
  unpriced?: boolean;
1098
1135
  duration: number;
1099
1136
  }) | (AxlEventBase & AskScoped & {
@@ -1111,6 +1148,10 @@ type LegacyAxlEventPayloadV1 = (AxlEventBase & {
1111
1148
  /** Authoritative turn-level cost. `undefined` for an unpriced model
1112
1149
  * (pricing-table miss) and absent on the error path (no usage). */
1113
1150
  cost?: number;
1151
+ /** Explicit lower-bound marker when a dispatched request was abandoned
1152
+ * without usage/cost (for example, a non-cooperative stalled provider).
1153
+ * The work may still be billed after this terminal event. */
1154
+ unpriced?: boolean;
1114
1155
  duration: number;
1115
1156
  tokens?: {
1116
1157
  input?: number;
@@ -1119,6 +1160,12 @@ type LegacyAxlEventPayloadV1 = (AxlEventBase & {
1119
1160
  cached?: number;
1120
1161
  cacheWrite?: number;
1121
1162
  };
1163
+ /** Per-call latency breakdown when the provider reported one. Additive
1164
+ * beside `duration`, which keeps its turn-wall-clock meaning (queue,
1165
+ * retries, gates and all). Present on the error path too when the
1166
+ * provider returned a response (any non-2xx); absent when the call
1167
+ * never reached one (network failure, abort, non-provider throw). */
1168
+ timing?: CallTiming;
1122
1169
  /** Response-side payload — response text, thinking. */
1123
1170
  data: AgentCallEndData;
1124
1171
  }) | (AxlEventBase & AskScoped & {
@@ -1442,12 +1489,12 @@ type ExecutionInfoV1 = {
1442
1489
  * here (stream-only); aggregate `tokens: { input, output, reasoning? }`
1443
1490
  * on `agent_call_end` is the persisted token representation. */
1444
1491
  events: LegacyAxlEventV1[];
1445
- /** Total spend for the execution. A LOWER BOUND when an unpriced model ran
1492
+ /** Total known spend for the execution. A LOWER BOUND when unknown-cost work ran
1446
1493
  * (those calls contribute nothing) — read {@link ExecutionInfo.unpriced} to
1447
1494
  * know whether it's exact, rather than scanning the event timeline. */
1448
1495
  totalCost: number;
1449
- /** True when any cost-bearing leaf in this execution did billable work but had
1450
- * no usable cost (unpriced model / pricing-table miss): `totalCost` is then a
1496
+ /** True when any cost-bearing leaf in this execution had no usable cost:
1497
+ * `totalCost` is then a
1451
1498
  * LOWER BOUND, not exact. `false` means every cost-bearing call was priced.
1452
1499
  * The aggregate counterpart of `ask_end.unpriced` / `BudgetResult.unpriced`,
1453
1500
  * computed via `isUnpricedLeaf`. `undefined` only on executions recorded
@@ -1548,6 +1595,13 @@ type ChatMessage = {
1548
1595
  * (the option name and shape are not yet stable); today it is purely
1549
1596
  * informational. */
1550
1597
  agent?: string;
1598
+ /** Provenance of a message the Axl runtime synthesized rather than the caller
1599
+ * authored: the rolling conversation summary and the handoff header. Like
1600
+ * `agent`, never sent on the wire. Adapters use it to avoid treating
1601
+ * runtime-injected text as the caller's stable prompt -- the Anthropic
1602
+ * adapter will not place its prompt-cache breakpoint on a system message
1603
+ * with `origin: 'runtime'`. */
1604
+ origin?: 'runtime';
1551
1605
  };
1552
1606
  type ToolCallMessage = {
1553
1607
  id: string;
@@ -1557,6 +1611,52 @@ type ToolCallMessage = {
1557
1611
  arguments: string;
1558
1612
  };
1559
1613
  };
1614
+ /**
1615
+ * Per-call latency breakdown, reported by adapters that route through
1616
+ * `fetchWithRetry`. Every figure is a non-negative integer count of
1617
+ * milliseconds derived from `Date.now()` deltas — the same clock
1618
+ * `agent_call_end.duration` uses.
1619
+ *
1620
+ * Entirely optional and additive: a custom `Provider` that omits `timing` stays
1621
+ * valid, and consumers must treat every field as possibly absent.
1622
+ *
1623
+ * The buckets separate the three things that `duration` conflates — the SDK's
1624
+ * own pacing, the provider's throttling, and the model's actual latency:
1625
+ */
1626
+ type CallTiming = {
1627
+ /**
1628
+ * Time parked in Axl's own opt-in `RateLimiter` (concurrency cap plus
1629
+ * `minIntervalMs` spacing) before the request was allowed out. `0` when the
1630
+ * provider has no `rateLimit` configured. This is self-imposed wait, not
1631
+ * provider latency.
1632
+ */
1633
+ queuedMs: number;
1634
+ /** `fetch` attempts made for this call, including the final one (≥ 1). */
1635
+ attempts: number;
1636
+ /**
1637
+ * First attempt's dispatch → final attempt's dispatch, i.e. everything spent
1638
+ * on failed attempts and their backoff sleeps. `0` for a single attempt.
1639
+ */
1640
+ retryMs: number;
1641
+ /** Final dispatch → response headers. Time to first byte. */
1642
+ ttfbMs: number;
1643
+ /**
1644
+ * Final dispatch → first `text_delta`/`thinking_delta`, excluding consumer
1645
+ * suspension after an earlier non-content chunk. Streaming only, and absent
1646
+ * on a stream that ends without any content delta. This is the model-
1647
+ * discriminating figure: headers arrive at roughly one round trip regardless
1648
+ * of model, first token does not.
1649
+ */
1650
+ firstTokenMs?: number;
1651
+ /**
1652
+ * Time attributable to the provider. For `chat()`, final dispatch → response
1653
+ * body parsed. For `stream()`, `ttfbMs` plus cumulative body-read waits,
1654
+ * floored at `firstTokenMs` when content arrives. Parsing needed to deliver
1655
+ * first content is included; consumer suspension between yielded chunks is
1656
+ * excluded, so two models stay comparable under different listener loads.
1657
+ */
1658
+ wireMs: number;
1659
+ };
1560
1660
  /** Provider response */
1561
1661
  type ProviderResponse = {
1562
1662
  content: string;
@@ -1574,6 +1674,8 @@ type ProviderResponse = {
1574
1674
  cost?: number;
1575
1675
  /** Provider-specific opaque metadata that needs to round-trip through conversation history. */
1576
1676
  providerMetadata?: Record<string, unknown>;
1677
+ /** Per-call latency breakdown. Absent on providers that don't instrument it. */
1678
+ timing?: CallTiming;
1577
1679
  };
1578
1680
 
1579
1681
  /** Base error class for all Axl errors */
@@ -1694,9 +1796,33 @@ declare class QuorumNotMet extends AxlError {
1694
1796
  declare class NoConsensus extends AxlError {
1695
1797
  constructor(reason: string);
1696
1798
  }
1799
+ /**
1800
+ * Where a timed-out ask's elapsed budget went, summed over the turns that
1801
+ * completed before the timeout fired. Present only when at least one of those
1802
+ * turns reported provider `timing` — an all-zero breakdown on an uninstrumented
1803
+ * provider would falsely blame tools and gates.
1804
+ */
1805
+ type TimeoutBreakdown = {
1806
+ /** Wall clock consumed by the operation when it timed out. */
1807
+ elapsedMs: number;
1808
+ /** Sum of `CallTiming.queuedMs` — self-imposed rate-limiter wait. */
1809
+ queuedMs: number;
1810
+ /** Sum of `CallTiming.retryMs` — failed provider attempts and their backoff. */
1811
+ retryMs: number;
1812
+ /** Sum of `CallTiming.wireMs` — provider time. */
1813
+ wireMs: number;
1814
+ /** `elapsedMs` minus the three sums: tools, gates, and runtime work. */
1815
+ otherMs: number;
1816
+ };
1697
1817
  /** Thrown when an operation exceeds its timeout */
1698
1818
  declare class TimeoutError extends AxlError {
1699
- constructor(operation: string, timeoutMs: number);
1819
+ /** Latency attribution for the timed-out operation, when measurable. */
1820
+ readonly breakdown?: TimeoutBreakdown;
1821
+ constructor(operation: string, timeoutMs: number, breakdown?: TimeoutBreakdown, agent?: string);
1822
+ }
1823
+ /** Thrown when a dispatched provider request stops making progress. */
1824
+ declare class StallTimeoutError extends TimeoutError {
1825
+ constructor(operation: string, timeoutMs: number, agent?: string);
1700
1826
  }
1701
1827
  /** Thrown when a budget limit is exceeded */
1702
1828
  declare class BudgetExceededError extends AxlError {
@@ -1753,6 +1879,9 @@ type AgentConfig = {
1753
1879
  includeThoughts?: boolean;
1754
1880
  toolChoice?: ToolChoice;
1755
1881
  stop?: string[];
1882
+ /** Opt in to prompt caching of this agent's stable prefix (system prompt +
1883
+ * tools). Only Anthropic needs it; off by default. See `docs/providers.md`. */
1884
+ promptCache?: boolean;
1756
1885
  /** Provider-specific options merged into API requests. Not portable across providers. */
1757
1886
  providerOptions?: Record<string, unknown>;
1758
1887
  /** Default rendering of a `ctx.ask` output schema into this agent's prompt.
@@ -1763,6 +1892,7 @@ type AgentConfig = {
1763
1892
  nativeStructuredOutput?: boolean;
1764
1893
  maxTurns?: number;
1765
1894
  timeout?: string;
1895
+ stallTimeout?: string;
1766
1896
  maxContext?: number;
1767
1897
  version?: string;
1768
1898
  guardrails?: GuardrailsConfig;
@@ -2183,11 +2313,14 @@ declare class AxlEventBus implements AsyncIterable<AxlEvent> {
2183
2313
  * shared API key can storm a provider's rate limit; a governor smooths that.
2184
2314
  *
2185
2315
  * ## Scope & caveats (v1)
2186
- * - **Caps request concurrency, not token throughput (TPM).** Streaming `chat()`
2187
- * releases the permit at *headers* (the adapter gets the `Response` from
2188
- * `fetchWithRetry`, then iterates the body separately), so a slow stream does
2189
- * NOT hold a permit for its whole lifetime. Non-streaming `chat()` holds the
2190
- * permit through `res.json()`. Neither bounds tokens/min.
2316
+ * - **Caps request concurrency, not token throughput (TPM).** The permit is
2317
+ * released at response *headers* on BOTH transports: `fetchWithRetry`
2318
+ * releases in its `finally` as it returns the `Response`, and every adapter
2319
+ * reads the body only afterwards — so `res.json()` and stream iteration alike
2320
+ * run outside the permit. A slow stream therefore does not hold a permit for
2321
+ * its whole lifetime. Non-streaming calls still hold it across generation in
2322
+ * practice, because a provider sends no headers until the completion is
2323
+ * finished. Neither bounds tokens/min.
2191
2324
  * - **Per provider instance.** Providers are singletons per (runtime, provider
2192
2325
  * type), so one governor governs all calls through that adapter — but NOT
2193
2326
  * embedder calls (the embedder is constructed outside the registry) and NOT
@@ -2477,6 +2610,7 @@ type OpenAICompatibleOptions = {
2477
2610
  */
2478
2611
  declare class OpenAICompatibleProvider implements Provider {
2479
2612
  readonly name: string;
2613
+ readonly reportsRequestLifecycle: true;
2480
2614
  inputCapabilities(model: string): {
2481
2615
  image?: {
2482
2616
  sources: readonly InputMediaSource['type'][];
@@ -2517,7 +2651,21 @@ declare class OpenAICompatibleProvider implements Provider {
2517
2651
  }): number | undefined;
2518
2652
  protected parseResponse(json: OpenAIChatResponse, model: string, request?: Record<string, unknown>): ProviderResponse;
2519
2653
  private roundTripMetadata;
2520
- protected parseSSEStream(body: ReadableStream<Uint8Array>, model: string, request?: Record<string, unknown>): AsyncGenerator<StreamChunk>;
2654
+ /**
2655
+ * PRIVATE, and deliberately not an extension point. It was `protected`, but
2656
+ * nothing in or out of this repo overrides it, and `protected` could not
2657
+ * carry the guarantee it appeared to: TypeScript checks an override for
2658
+ * assignability, and a function type with fewer parameters is assignable to
2659
+ * one with more — so an override that simply dropped the recorder still
2660
+ * compiled and then reported `wireMs === ttfbMs` for the whole subclass. Its
2661
+ * type is not exported from the barrel either, so a subclass author could not
2662
+ * name what they were required to accept.
2663
+ *
2664
+ * A provider with a different wire format implements `Provider` (see
2665
+ * docs/providers.md); an OpenAI-compatible one adds a `ProviderProfile`.
2666
+ * Neither needs to reach in here.
2667
+ */
2668
+ private parseSSEStream;
2521
2669
  }
2522
2670
  type OpenAIUsage = {
2523
2671
  prompt_tokens: number;
@@ -2956,6 +3104,7 @@ type StateConfig = {
2956
3104
  /** Global defaults */
2957
3105
  type DefaultsConfig = {
2958
3106
  timeout?: string;
3107
+ stallTimeout?: string;
2959
3108
  maxRetries?: number;
2960
3109
  budgetPolicy?: 'finish_and_stop' | 'hard_stop' | 'warn';
2961
3110
  };
@@ -3522,6 +3671,13 @@ declare class WorkflowContext<TInput = unknown> {
3522
3671
  private readonly workflowLifecycleState;
3523
3672
  private signal?;
3524
3673
  private summaryCache?;
3674
+ /** Consecutive provider calls with promptCache on that wrote to the cache
3675
+ * without reading from it (prefix changes per call), and consecutive calls
3676
+ * with no cache activity at all (prefix below the model's minimum, which
3677
+ * Anthropic silently ignores). Either reports once per context. */
3678
+ private promptCacheColdWrites;
3679
+ private promptCacheInactive;
3680
+ private promptCacheWarned;
3525
3681
  private workflowName?;
3526
3682
  private mcpManager?;
3527
3683
  private spanManager?;
@@ -3648,6 +3804,7 @@ declare class WorkflowContext<TInput = unknown> {
3648
3804
  private observeToolInvocation;
3649
3805
  ask<T = string>(agent: Agent, prompt: ModelInput, options?: AskOptions<T>): Promise<T>;
3650
3806
  private executeAgentCall;
3807
+ private executeAgentCallImpl;
3651
3808
  /**
3652
3809
  * Resolve the corrective feedback text for one rejected attempt, giving an optional
3653
3810
  * caller-supplied `retryFeedback` hook the chance to replace it or to stop retrying.
@@ -4646,12 +4803,62 @@ declare class AxlRuntime extends EventEmitter {
4646
4803
  */
4647
4804
  trackExecution<T>(fn: () => Promise<T>, options?: {
4648
4805
  captureTraces?: boolean;
4806
+ captureTimingSamples?: boolean;
4649
4807
  }): Promise<{
4650
4808
  result: T;
4651
4809
  cost: number;
4652
4810
  /** True when any tracked call was unpriced — `cost` is then a LOWER BOUND.
4653
4811
  * Aggregate counterpart of `ExecutionInfo.unpriced`, via `isUnpricedLeaf`. */
4654
4812
  unpriced: boolean;
4813
+ /**
4814
+ * Per-model sums of `agent_call_end.timing`, keyed by the same effective
4815
+ * model URI as `metadata.modelCallCounts`. Present only when at least one
4816
+ * tracked call reported timing, so absence means "nothing was instrumented"
4817
+ * rather than "everything took zero ms".
4818
+ *
4819
+ * `calls` counts the SUCCESSFUL timed calls only — it can be lower than the
4820
+ * same model's `modelCallCounts` entry when a provider omits `timing` or a
4821
+ * call failed. Divide a sum by `calls`, never by `modelCallCounts`.
4822
+ *
4823
+ * Failed calls are excluded even though they now report timing: a non-2xx
4824
+ * response is a measured round trip, but a rollup blending answers with
4825
+ * failures describes neither, and a fast 429 would improve a model's
4826
+ * apparent latency. The failures stay on the events themselves.
4827
+ *
4828
+ * `firstTokenMs` is streaming-only and is summed across the calls that
4829
+ * reported it; it is omitted entirely when no call did, so a non-streaming
4830
+ * model never reports a misleading `0`. Its denominator is `firstTokenCalls`,
4831
+ * NOT `calls` — the two travel together and are present or absent together,
4832
+ * so a mixed streaming/non-streaming model still yields an exact mean.
4833
+ *
4834
+ * Sums are per-call totals, so `wireMs` across concurrent calls can exceed
4835
+ * the wall clock of `fn` — that is expected under fan-out and is why
4836
+ * nothing in the core sums timing at the ask level.
4837
+ *
4838
+ * `samples` carries the raw per-call `CallTiming` blocks behind the sums, in
4839
+ * `agent_call_end` order, so a caller that needs a DISTRIBUTION (percentiles,
4840
+ * min/max) rather than a mean can compute one over real per-call values. It
4841
+ * is the same data the sums were built from — `samples.length === calls` —
4842
+ * and is deliberately not something callers should persist per item: the
4843
+ * sums are the compact form, `samples` is the working form.
4844
+ *
4845
+ * It is **opt-in** via `captureTimingSamples` and the key is absent
4846
+ * otherwise. Retaining it is O(calls) in memory for the lifetime of `fn`,
4847
+ * which no caller should pay for a figure it never reads — the sums alone
4848
+ * are O(models).
4849
+ */
4850
+ modelTiming?: Record<string, {
4851
+ calls: number;
4852
+ queuedMs: number;
4853
+ retryMs: number;
4854
+ wireMs: number;
4855
+ firstTokenMs?: number;
4856
+ /** Timed calls that reported a `firstTokenMs` — the denominator for it. */
4857
+ firstTokenCalls?: number;
4858
+ /** The per-call blocks the sums were built from, in event order.
4859
+ * `length === calls`. Present only under `captureTimingSamples`. */
4860
+ samples?: CallTiming[];
4861
+ }>;
4655
4862
  traces?: AxlEvent[];
4656
4863
  metadata: {
4657
4864
  models: string[];
@@ -4980,9 +5187,9 @@ declare function stringStreamFromEvents(source: AsyncIterable<AxlEvent>, opts?:
4980
5187
  declare const COST_BEARING_LEAF_TYPES: readonly ["agent_call_end", "tool_call_end", "memory_remember", "memory_recall", "transcription_end"];
4981
5188
  /**
4982
5189
  * True when an event reports a POSITIVE token count — i.e. it did measurable,
4983
- * billable work. This is the discriminator the unpriced-cost signal (T2.5) uses:
4984
- * a cost-bearing leaf with positive tokens but no usable cost is an unpriced
4985
- * model / pricing-table miss, whereas a failed call (no usage) or a no-usage
5190
+ * billable work. This is one discriminator the unpriced-cost signal uses:
5191
+ * a cost-bearing leaf with positive tokens but no usable cost is unknown-cost
5192
+ * work, whereas a failed call (no usage) or a no-usage
4986
5193
  * streamed `done` (zero tokens) is NOT "unpriced". Used by the core ask-cost
4987
5194
  * rollup AND the Studio aggregators, so the per-ask flag and the dashboard count
4988
5195
  * stay in lockstep.
@@ -5045,16 +5252,17 @@ declare function eventCostContribution(event: HistoricalAxlEvent): number;
5045
5252
  declare function isCostBearingLeaf(event: HistoricalAxlEvent): boolean;
5046
5253
  /**
5047
5254
  * True when the event is the "unpriced lower-bound" signal: a cost-bearing leaf
5048
- * that did measurable, billable work (POSITIVE tokens) but produced no usable
5049
- * cost (an unpriced model / pricing-table miss). This is the SINGLE source of
5050
- * truth for that discriminator — the core ask-cost rollup, the runtime's
5255
+ * that either explicitly reports unknown cost (for example, an abandoned
5256
+ * dispatched request) or did measurable, billable work (POSITIVE tokens) but
5257
+ * produced no usable cost (an unpriced model / pricing-table miss). This is the
5258
+ * SINGLE source of truth for that discriminator — the core ask-cost rollup, the runtime's
5051
5259
  * `ExecutionInfo.unpriced` / `trackExecution().unpriced` aggregation, and
5052
5260
  * Studio's `unpricedCalls` count + cost reducer ALL route through it, so they
5053
5261
  * cannot drift.
5054
5262
  *
5055
- * It is the conjunction of the three primitives:
5056
- * `isCostBearingLeaf` ∧ `!isUsableCost(cost)` ∧ `hasPositiveTokens`.
5057
- * The positive-token term is what distinguishes an unpriced model from a FAILED
5263
+ * It is the conjunction of the first two primitives and either uncertainty signal:
5264
+ * `isCostBearingLeaf` ∧ `!isUsableCost(cost)` ∧ (`unpriced === true` ∨ `hasPositiveTokens`).
5265
+ * The positive-token term is what distinguishes ordinary unpriced work from a FAILED
5058
5266
  * call (no usage) or a no-usage streamed `done` (zero tokens) — neither is
5059
5267
  * "unpriced". An `ask_end` rollup carries a numeric cost, and `tool_call_end`
5060
5268
  * carries no tokens, so both are naturally excluded.
@@ -5065,6 +5273,7 @@ declare function isCostBearingLeaf(event: HistoricalAxlEvent): boolean;
5065
5273
  declare function isUnpricedLeaf(event: {
5066
5274
  type?: string;
5067
5275
  cost?: unknown;
5276
+ unpriced?: boolean;
5068
5277
  tokens?: {
5069
5278
  input?: number;
5070
5279
  output?: number;
@@ -5354,6 +5563,16 @@ declare class ProviderError extends AxlError {
5354
5563
  * and is redaction-eligible). See `docs/security.md`.
5355
5564
  */
5356
5565
  readonly body?: string;
5566
+ /**
5567
+ * Per-call latency breakdown for the failed call, when the transport reached
5568
+ * the provider and a `Response` came back (any non-2xx, streamed or not).
5569
+ * Absent — the KEY itself, not `undefined` — when there is nothing to
5570
+ * report: a network-level failure (`status: 0`) never got a response, and a
5571
+ * custom transport may not instrument timing at all. `declare` keeps the
5572
+ * property from being defined as `undefined` under `useDefineForClassFields`,
5573
+ * so `'timing' in err` distinguishes "not measured" from "measured as zero".
5574
+ */
5575
+ readonly timing?: CallTiming;
5357
5576
  constructor(args: {
5358
5577
  provider: string;
5359
5578
  status: number;
@@ -5362,6 +5581,7 @@ declare class ProviderError extends AxlError {
5362
5581
  retryAfterMs?: number;
5363
5582
  requestId?: string;
5364
5583
  body?: string;
5584
+ timing?: CallTiming;
5365
5585
  });
5366
5586
  }
5367
5587
  /**
@@ -5430,6 +5650,7 @@ declare class OpenAIProvider extends OpenAICompatibleProvider {
5430
5650
  */
5431
5651
  declare class OpenAIResponsesProvider implements Provider {
5432
5652
  readonly name = "openai-responses";
5653
+ readonly reportsRequestLifecycle: true;
5433
5654
  inputCapabilities(model: string): {
5434
5655
  image?: {
5435
5656
  sources: readonly InputMediaSource['type'][];
@@ -5492,6 +5713,7 @@ declare class OpenAIResponsesProvider implements Provider {
5492
5713
  */
5493
5714
  declare class AnthropicProvider implements Provider {
5494
5715
  readonly name = "anthropic";
5716
+ readonly reportsRequestLifecycle: true;
5495
5717
  /** Report a clamped `effort`. Anthropic clamps to each model's supported
5496
5718
  * `output_config.effort` levels, and models that always think fall back to
5497
5719
  * adaptive `'low'` when asked to disable thinking. Only reported when the
@@ -5506,6 +5728,8 @@ declare class AnthropicProvider implements Provider {
5506
5728
  validateInput(request: ProviderInputValidationRequest): ProviderInputValidationResult;
5507
5729
  /** Anthropic ignores native `json_schema` structurally — Axl uses a system
5508
5730
  * prompt JSON instruction + client-side Zod validation (see buildRequest). */
5731
+ /** The only built-in adapter that honors `promptCache` (see buildBody). */
5732
+ realizesPromptCache(): boolean;
5509
5733
  nativeStructuredOutputSupport(): 'unsupported';
5510
5734
  private baseUrl;
5511
5735
  private apiKeySource;
@@ -5574,6 +5798,7 @@ declare class AnthropicProvider implements Provider {
5574
5798
  */
5575
5799
  declare class GeminiProvider implements Provider {
5576
5800
  readonly name = "google";
5801
+ readonly reportsRequestLifecycle: true;
5577
5802
  inputCapabilities(model: string): {
5578
5803
  image?: {
5579
5804
  sources: readonly InputMediaSource['type'][];
@@ -6270,4 +6495,4 @@ declare class NoopSpanManager implements SpanManager {
6270
6495
  */
6271
6496
  declare function createSpanManager(config?: TelemetryConfig): Promise<SpanManager>;
6272
6497
 
6273
- export { AXL_EVENT_TYPES, AXL_EVENT_TYPES_V2, AXL_TOOL_LIFECYCLE_TYPES_V2, AZURE_PROFILE, type Agent, type AgentCallEndData, type AgentCallInfo, type AgentCallParams, type AgentCallStartData, type AgentConfig, AnthropicProvider, type AnyWorkflow, type ApiKeySource, type AskOptions, type AskScoped, type AuthHeader, type AwaitHumanData, type AwaitHumanOptions, type AwaitHumanResolvedData, type AxlConfig, AxlError, type AxlEvent, type AxlEventBase, AxlEventBus, type AxlEventOf, type AxlEventType, type AxlEventV2, type AxlEventV2Of, AxlRuntime, AxlStream, BEDROCK_PROFILE, BUILTIN_PROFILES, BudgetExceededError, type BudgetOptions, type BudgetResult, CONFIG_CANDIDATES, COST_BEARING_LEAF_TYPES, type CapabilityFlags, type ChatMessage, type ChatOptions, type CheckpointEventData, type CoalescedPartialObject, type CreateContextOptions, DEEPSEEK_PROFILE, type DecisionCleanupFailedEvent, type DelegateData, type DelegateOptions, type Effort, type EffortResolution, type EmbedResult, type EmbedUsage, type Embedder, type EvalExecuteWorkflow, type EvalHistoryEntry, type EventStreamOptions, EventStreamOverflowError, type ExecuteOptions, type ExecutionInfo, type ExecutionInfoV1, type ExecutionInfoV2, type ExecutionState, GROQ_PROFILE, GeminiProvider, GeminiTranscriptionProvider, type GuardrailBlockHandler, type GuardrailData, GuardrailError, type GuardrailResult, type GuardrailsConfig, type HandoffDescriptor, type HandoffRecord, type HandoffReturnData, type HandoffStartData, type HistoricalAxlEvent, type HistoricalExecutionInfo, type HumanDecision, InMemoryVectorStore, type InputContentPart, type InputGuardrail, type InputImagePart, type InputMediaSource, type InputModalitySupport, type InputTextPart, InvalidModelInputError, InvalidTranscriptionInputError, LLAMACPP_PROFILE, LMSTUDIO_PROFILE, type LegacyAxlEventV1, type LegacyExecutionInfoV1, MAX_INLINE_MODEL_INPUT_BYTES, MAX_INLINE_TRANSCRIPTION_BYTES, MISTRAL_PROFILE, type MapOptions, MaxTurnsError, McpManager, type McpServer, type McpServerConfig, type McpToolDefinition, type McpToolResult, type MemoryConfig, type MemoryEventData, MemoryManager, MemoryStore, type ModelInput, type ModelInputDescriptor, NoConsensus, NoopSpanManager, OLLAMA_PROFILE, OPENAI_PRICING, OPENAI_PROFILE, OPENROUTER_PROFILE, type ObservationStatus, type OpenAICompatibleOptions, OpenAICompatibleProvider, OpenAIEmbedder, OpenAIProvider, OpenAIResponsesProvider, OpenAITranscriptionProvider, OpenRouterTranscriptionProvider, type OutputGuardrail, type OutputValidator, type PendingDecision, type PerModel, type PricingSource, type PricingTable, type Provider, type ProviderAdapter, type ProviderDiagnosticData, ProviderError, type ProviderInputValidationRequest, type ProviderInputValidationResult, type ProviderProfile, ProviderRegistry, type ProviderResponse, QuorumNotMet, REDACTED, REDACTION_RULES, type RaceOptions, type RateLimitConfig, RateLimiter, type ReasoningCapture, type ReasoningEmit, type ReasoningProfile, type ReasoningRoundTrip, type RecallOptions, type RecallResult, type RecordedAudioSource, RedisStore, type RememberOptions, type RememberResult, type ResolvedThinkingOptions, type Result, type RetryFeedbackHook, type RetryFeedbackInfo, type RetryFeedbackResult, type RetryPolicy, SGLANG_PROFILE, SQLiteStore, type SchemaCheckData, type SchemaDiagnosticData, type SchemaPromptOption, Session, type SessionOptions, type SpanHandle, type SpanManager, type SpawnOptions, SqliteVectorStore, type StateStore, type StreamChunk, type StringDeltaData, type StringStreamEvent, type StringStreamFilter, type TelemetryConfig, ThinkTagScanner, TimeoutError, type Tool, type ToolApprovalData, type ToolArgumentIssue, type ToolCallCancellation, type ToolCallData, type ToolCallEndData, type ToolCallFailure, type ToolCallMessage, type ToolCallOutcome, type ToolCallRejectedData, type ToolCallRejectedEvent, type ToolCallStartData, type ToolCallStartDataV2, type ToolChoice, type ToolConfig, type ToolDeniedData, type ToolEventError, ToolFailure, type ToolFailureConstructor, type ToolFailureOptions, type ToolHooks, type ToolLifecycleEventV2, type ToolModelOutput, ToolModelOutputError, type Transcript, type TranscriptionCapabilities, TranscriptionOperationError, type TranscriptionProvider, TranscriptionProviderRegistry, type TranscriptionProviderRequest, type TranscriptionProviderResult, type TranscriptionRequest, UnsupportedEventSchemaVersionError, UnsupportedModelInputError, UnsupportedTranscriptionInputError, VLLM_PROFILE, type ValidateData, type ValidateResult, ValidationError, type VectorEntry, type VectorResult, type VectorStore, type VerifyData, VerifyError, type VerifyOptions, type VerifyRetry, type VoteOptions, type Workflow, type WorkflowConfig, WorkflowContext, type WorkflowContextInit, type WorkflowEndData, type WorkflowStartData, XAI_PROFILE, agent, createSpanManager, defineConfig, estimateOpenAICost, eventCostContribution, expandGlob, extractJson, extractThinkTags, findConfig, getEventSchemaVersion, getExecutionEventSchemaVersion, hasPositiveBillableWork, hasPositiveTokens, importModule, inputText, isCostBearingLeaf, isRetryableStatus, isRootLevel, isUnpricedLeaf, isUsableCost, needsTsxLoader, normalizeStoredExecution, openaiReasoningEmit, parsePartialJson, pickDefault, pickExport, priceFromTable, reasoningEffortEmit, reasoningObjectEmit, redactEvent, redactHistoricalEvent, registerConditions, resolveApiKey, resolvePerModel, resolveRuntime, resolveThinkingOptions, stringStreamFromEvents, tool, workflow, zodToJsonSchema };
6498
+ export { AXL_EVENT_TYPES, AXL_EVENT_TYPES_V2, AXL_TOOL_LIFECYCLE_TYPES_V2, AZURE_PROFILE, type Agent, type AgentCallEndData, type AgentCallInfo, type AgentCallParams, type AgentCallStartData, type AgentConfig, AnthropicProvider, type AnyWorkflow, type ApiKeySource, type AskOptions, type AskScoped, type AuthHeader, type AwaitHumanData, type AwaitHumanOptions, type AwaitHumanResolvedData, type AxlConfig, AxlError, type AxlEvent, type AxlEventBase, AxlEventBus, type AxlEventOf, type AxlEventType, type AxlEventV2, type AxlEventV2Of, AxlRuntime, AxlStream, BEDROCK_PROFILE, BUILTIN_PROFILES, BudgetExceededError, type BudgetOptions, type BudgetResult, CONFIG_CANDIDATES, COST_BEARING_LEAF_TYPES, type CallTiming, type CapabilityFlags, type ChatMessage, type ChatOptions, type CheckpointEventData, type CoalescedPartialObject, type CreateContextOptions, DEEPSEEK_PROFILE, type DecisionCleanupFailedEvent, type DelegateData, type DelegateOptions, type Effort, type EffortResolution, type EmbedResult, type EmbedUsage, type Embedder, type EvalExecuteWorkflow, type EvalHistoryEntry, type EventStreamOptions, EventStreamOverflowError, type ExecuteOptions, type ExecutionInfo, type ExecutionInfoV1, type ExecutionInfoV2, type ExecutionState, GROQ_PROFILE, GeminiProvider, GeminiTranscriptionProvider, type GuardrailBlockHandler, type GuardrailData, GuardrailError, type GuardrailResult, type GuardrailsConfig, type HandoffDescriptor, type HandoffRecord, type HandoffReturnData, type HandoffStartData, type HistoricalAxlEvent, type HistoricalExecutionInfo, type HumanDecision, InMemoryVectorStore, type InputContentPart, type InputGuardrail, type InputImagePart, type InputMediaSource, type InputModalitySupport, type InputTextPart, InvalidModelInputError, InvalidTranscriptionInputError, LLAMACPP_PROFILE, LMSTUDIO_PROFILE, type LegacyAxlEventV1, type LegacyExecutionInfoV1, MAX_INLINE_MODEL_INPUT_BYTES, MAX_INLINE_TRANSCRIPTION_BYTES, MISTRAL_PROFILE, type MapOptions, MaxTurnsError, McpManager, type McpServer, type McpServerConfig, type McpToolDefinition, type McpToolResult, type MemoryConfig, type MemoryEventData, MemoryManager, MemoryStore, type ModelInput, type ModelInputDescriptor, NoConsensus, NoopSpanManager, OLLAMA_PROFILE, OPENAI_PRICING, OPENAI_PROFILE, OPENROUTER_PROFILE, type ObservationStatus, type OpenAICompatibleOptions, OpenAICompatibleProvider, OpenAIEmbedder, OpenAIProvider, OpenAIResponsesProvider, OpenAITranscriptionProvider, OpenRouterTranscriptionProvider, type OutputGuardrail, type OutputValidator, type PendingDecision, type PerModel, type PricingSource, type PricingTable, type Provider, type ProviderAdapter, type ProviderDiagnosticData, ProviderError, type ProviderInputValidationRequest, type ProviderInputValidationResult, type ProviderProfile, ProviderRegistry, type ProviderResponse, QuorumNotMet, REDACTED, REDACTION_RULES, type RaceOptions, type RateLimitConfig, RateLimiter, type ReasoningCapture, type ReasoningEmit, type ReasoningProfile, type ReasoningRoundTrip, type RecallOptions, type RecallResult, type RecordedAudioSource, RedisStore, type RememberOptions, type RememberResult, type ResolvedThinkingOptions, type Result, type RetryFeedbackHook, type RetryFeedbackInfo, type RetryFeedbackResult, type RetryPolicy, SGLANG_PROFILE, SQLiteStore, type SchemaCheckData, type SchemaDiagnosticData, type SchemaPromptOption, Session, type SessionOptions, type SpanHandle, type SpanManager, type SpawnOptions, SqliteVectorStore, StallTimeoutError, type StateStore, type StreamChunk, type StringDeltaData, type StringStreamEvent, type StringStreamFilter, type TelemetryConfig, ThinkTagScanner, type TimeoutBreakdown, TimeoutError, type Tool, type ToolApprovalData, type ToolArgumentIssue, type ToolCallCancellation, type ToolCallData, type ToolCallEndData, type ToolCallFailure, type ToolCallMessage, type ToolCallOutcome, type ToolCallRejectedData, type ToolCallRejectedEvent, type ToolCallStartData, type ToolCallStartDataV2, type ToolChoice, type ToolConfig, type ToolDeniedData, type ToolEventError, ToolFailure, type ToolFailureConstructor, type ToolFailureOptions, type ToolHooks, type ToolLifecycleEventV2, type ToolModelOutput, ToolModelOutputError, type Transcript, type TranscriptionCapabilities, TranscriptionOperationError, type TranscriptionProvider, TranscriptionProviderRegistry, type TranscriptionProviderRequest, type TranscriptionProviderResult, type TranscriptionRequest, UnsupportedEventSchemaVersionError, UnsupportedModelInputError, UnsupportedTranscriptionInputError, VLLM_PROFILE, type ValidateData, type ValidateResult, ValidationError, type VectorEntry, type VectorResult, type VectorStore, type VerifyData, VerifyError, type VerifyOptions, type VerifyRetry, type VoteOptions, type Workflow, type WorkflowConfig, WorkflowContext, type WorkflowContextInit, type WorkflowEndData, type WorkflowStartData, XAI_PROFILE, agent, createSpanManager, defineConfig, estimateOpenAICost, eventCostContribution, expandGlob, extractJson, extractThinkTags, findConfig, getEventSchemaVersion, getExecutionEventSchemaVersion, hasPositiveBillableWork, hasPositiveTokens, importModule, inputText, isCostBearingLeaf, isRetryableStatus, isRootLevel, isUnpricedLeaf, isUsableCost, needsTsxLoader, normalizeStoredExecution, openaiReasoningEmit, parsePartialJson, pickDefault, pickExport, priceFromTable, reasoningEffortEmit, reasoningObjectEmit, redactEvent, redactHistoricalEvent, registerConditions, resolveApiKey, resolvePerModel, resolveRuntime, resolveThinkingOptions, stringStreamFromEvents, tool, workflow, zodToJsonSchema };