@ai-sdk/anthropic 3.0.81 → 3.0.83

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.
@@ -5,26 +5,25 @@ import type { JSONObject, LanguageModelV3Usage } from '@ai-sdk/provider';
5
5
  *
6
6
  * - `compaction` / `message`: executor iterations, billed at executor rates.
7
7
  * - `advisor_message`: advisor sub-inference, billed at the advisor model's
8
- * rates. The `model` field carries the advisor model ID. Advisor tokens
9
- * are NOT rolled into the top-level totals because they bill at a
10
- * different rate; inspect this array for advisor cost tracking.
8
+ * rates. Advisor tokens are NOT rolled into the top-level totals because
9
+ * they bill at a different rate; inspect this array for advisor cost
10
+ * tracking.
11
+ * - `fallback_message`: a server-side fallback attempt that served the turn.
12
+ * When present, the top-level usage already reflects the served answer, so
13
+ * it is used as-is.
14
+ *
15
+ * The `model` field carries the model that produced the iteration. The API
16
+ * populates it for the per-model attribution cases (the fallback chain and
17
+ * advisor sub-inferences) and omits it otherwise.
11
18
  */
12
- export type AnthropicUsageIteration =
13
- | {
14
- type: 'compaction' | 'message';
15
- input_tokens: number;
16
- output_tokens: number;
17
- cache_creation_input_tokens?: number | null;
18
- cache_read_input_tokens?: number | null;
19
- }
20
- | {
21
- type: 'advisor_message';
22
- model: string;
23
- input_tokens: number;
24
- output_tokens: number;
25
- cache_creation_input_tokens?: number | null;
26
- cache_read_input_tokens?: number | null;
27
- };
19
+ export type AnthropicUsageIteration = {
20
+ type: 'compaction' | 'message' | 'advisor_message' | 'fallback_message';
21
+ model?: string | null;
22
+ input_tokens: number;
23
+ output_tokens: number;
24
+ cache_creation_input_tokens?: number | null;
25
+ cache_read_input_tokens?: number | null;
26
+ };
28
27
 
29
28
  export type AnthropicMessagesUsage = {
30
29
  input_tokens: number;
@@ -57,10 +56,19 @@ export function convertAnthropicMessagesUsage({
57
56
  // and output_tokens exclude compaction usage. Advisor (`advisor_message`)
58
57
  // iterations are filtered out: they bill at the advisor model's rates,
59
58
  // not the executor's, so they don't belong in the top-level totals.
59
+ //
60
+ // A turn served by a server-side fallback is the exception: the served
61
+ // answer comes from the fallback model, so the executor `message` iteration
62
+ // is the blocked primary attempt (zero output). The top-level totals already
63
+ // reflect the fallback answer, so they are used directly.
60
64
  let inputTokens: number;
61
65
  let outputTokens: number;
62
66
 
63
- if (usage.iterations && usage.iterations.length > 0) {
67
+ const servedByFallback = usage.iterations?.some(
68
+ iter => iter.type === 'fallback_message',
69
+ );
70
+
71
+ if (usage.iterations && usage.iterations.length > 0 && !servedByFallback) {
64
72
  const executorIterations = usage.iterations.filter(
65
73
  iter => iter.type === 'compaction' || iter.type === 'message',
66
74
  );