diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index bb0f549c5a..a486d0672d 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -1920,17 +1920,20 @@ export class Task extends EventEmitter implements TaskLike { cacheReadTokens, ) - // For tokensIn, store the base input tokens (not including cache tokens) - // This ensures context length calculation works correctly in getApiMetrics - // where it adds tokensIn + tokensOut. The cache tokens are stored separately - // in cacheWrites and cacheReads for display purposes. + // Store tokensIn based on the API protocol: + // - For Anthropic: inputTokens is base input (without cache), so use inputTokens + // - For OpenAI: inputTokens already includes cache, so use totalInputTokens + // This ensures getApiMetrics can correctly calculate context tokens by checking apiProtocol + const tokensInValue = apiProtocol === "anthropic" ? inputTokens : costResult.totalInputTokens + this.clineMessages[lastApiReqIndex].text = JSON.stringify({ ...existingData, - tokensIn: inputTokens, + tokensIn: tokensInValue, tokensOut: costResult.totalOutputTokens, cacheWrites: cacheWriteTokens, cacheReads: cacheReadTokens, cost: totalCost ?? costResult.totalCost, + apiProtocol, cancelReason, streamingFailedMessage, } satisfies ClineApiReqInfo) diff --git a/src/shared/getApiMetrics.ts b/src/shared/getApiMetrics.ts index 4f13fefc65..2a02bdba1b 100644 --- a/src/shared/getApiMetrics.ts +++ b/src/shared/getApiMetrics.ts @@ -80,12 +80,11 @@ export function getApiMetrics(messages: ClineMessage[]) { if (message.type === "say" && message.say === "api_req_started" && message.text) { try { const parsedText: ParsedApiReqStartedTextType = JSON.parse(message.text) - const { tokensIn, tokensOut } = parsedText + const { tokensIn, tokensOut, apiProtocol } = parsedText - // tokensIn contains base input tokens (without cache tokens). - // This works correctly for both Anthropic and OpenAI protocols because: - // - Cache tokens are stored separately in cacheWrites/cacheReads - // - Context length = base input + output tokens + // Context tokens = total tokens sent to the model + // For both Anthropic and OpenAI, tokensIn now stores the total input tokens + // (including cache tokens), so we just add tokensIn + tokensOut result.contextTokens = (tokensIn || 0) + (tokensOut || 0) } catch (error) { console.error("Error parsing JSON:", error)