87 lines · 3.1 KB · TypeScript
RawDownload
import type { SDKResultMessage } from "@anthropic-ai/claude-agent-sdk";import type { ProviderRuntimeTurnStatus, TurnTokenUsage } from "@t3tools/contracts"; function finiteNonNegativeInteger(value: unknown): number | undefined {  return typeof value === "number" && Number.isFinite(value) && value >= 0    ? Math.round(value)    : undefined;} export function normalizeClaudeTurnTokenUsage(  result: { readonly subtype: SDKResultMessage["subtype"]; readonly usage?: unknown } | undefined,  hasSubagents: boolean,  terminalStatus: ProviderRuntimeTurnStatus,): TurnTokenUsage {  const usage = result?.usage as Record<string, unknown> | undefined;  if (!usage) {    return {      usageStatus: "unavailable",      usageScope: "main_agent",      hasSubagents,    };  }   const uncachedInputTokens = finiteNonNegativeInteger(usage.input_tokens);  const cachedInputTokens = finiteNonNegativeInteger(usage.cache_read_input_tokens);  const cacheCreationTokens = finiteNonNegativeInteger(usage.cache_creation_input_tokens);  const rawOutputTokens = finiteNonNegativeInteger(usage.output_tokens);  const outputDetails = usage.output_tokens_details as Record<string, unknown> | undefined;  const thinkingTokens = finiteNonNegativeInteger(outputDetails?.thinking_tokens);  const cachedInputContribution = usage.cache_read_input_tokens == null ? 0 : cachedInputTokens;  const cacheCreationContribution =    usage.cache_creation_input_tokens == null ? 0 : cacheCreationTokens;  const inputTokens =    uncachedInputTokens !== undefined &&    cachedInputContribution !== undefined &&    cacheCreationContribution !== undefined      ? uncachedInputTokens + cachedInputContribution + cacheCreationContribution      : undefined;  const hasKnownUsage =    uncachedInputTokens !== undefined ||    cachedInputTokens !== undefined ||    cacheCreationTokens !== undefined ||    rawOutputTokens !== undefined;  const hasPositiveUsage =    (uncachedInputTokens ?? 0) +      (cachedInputTokens ?? 0) +      (cacheCreationTokens ?? 0) +      (rawOutputTokens ?? 0) >    0;   if (!hasKnownUsage || (result?.subtype !== "success" && !hasPositiveUsage)) {    return {      usageStatus: "unavailable",      usageScope: "main_agent",      hasSubagents,    };  }   const commonUsage = {    usageScope: "main_agent",    ...(cachedInputTokens !== undefined ? { cachedInputTokens } : {}),    ...(cacheCreationTokens !== undefined ? { cacheCreationTokens } : {}),    ...(thinkingTokens !== undefined && rawOutputTokens !== undefined      ? { reasoningTokens: Math.min(rawOutputTokens, thinkingTokens) }      : {}),    hasSubagents,  } as const;  if (    terminalStatus === "completed" &&    result?.subtype === "success" &&    inputTokens !== undefined &&    rawOutputTokens !== undefined  ) {    return {      ...commonUsage,      usageStatus: "complete",      inputTokens,      outputTokens: rawOutputTokens,    };  }  return {    ...commonUsage,    usageStatus: "partial",    ...(inputTokens !== undefined ? { inputTokens } : {}),    ...(rawOutputTokens !== undefined ? { outputTokens: rawOutputTokens } : {}),  };}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t