fix: correct token extraction for Claude non-streaming responses (#131)
- Add response logging for non-streaming requests (5_res_provider.json, 7_res_client.json) - Fix extractUsageFromResponse() to check Claude format before OpenAI format - Prevents format misidentification that caused tokens to show as 0 - Claude uses input_tokens/output_tokens vs OpenAI's prompt_tokens/completion_tokens Fixes dashboard Details tab showing 0 tokens for Claude requests
This commit is contained in:
@@ -194,18 +194,8 @@ function translateNonStreamingResponse(responseBody, targetFormat, sourceFormat)
|
|||||||
function extractUsageFromResponse(responseBody, provider) {
|
function extractUsageFromResponse(responseBody, provider) {
|
||||||
if (!responseBody || typeof responseBody !== 'object') return null;
|
if (!responseBody || typeof responseBody !== 'object') return null;
|
||||||
|
|
||||||
// OpenAI format
|
// Claude format - check first to avoid conflict with OpenAI check
|
||||||
if (responseBody.usage && typeof responseBody.usage === 'object') {
|
if (responseBody.usage && typeof responseBody.usage === 'object' && responseBody.usage.input_tokens !== undefined) {
|
||||||
return {
|
|
||||||
prompt_tokens: responseBody.usage.prompt_tokens || 0,
|
|
||||||
completion_tokens: responseBody.usage.completion_tokens || 0,
|
|
||||||
cached_tokens: responseBody.usage.prompt_tokens_details?.cached_tokens,
|
|
||||||
reasoning_tokens: responseBody.usage.completion_tokens_details?.reasoning_tokens
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Claude format
|
|
||||||
if (responseBody.usage && typeof responseBody.usage === 'object' && (responseBody.usage.input_tokens !== undefined || responseBody.usage.output_tokens !== undefined)) {
|
|
||||||
return {
|
return {
|
||||||
prompt_tokens: responseBody.usage.input_tokens || 0,
|
prompt_tokens: responseBody.usage.input_tokens || 0,
|
||||||
completion_tokens: responseBody.usage.output_tokens || 0,
|
completion_tokens: responseBody.usage.output_tokens || 0,
|
||||||
@@ -214,6 +204,16 @@ function extractUsageFromResponse(responseBody, provider) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpenAI format
|
||||||
|
if (responseBody.usage && typeof responseBody.usage === 'object' && responseBody.usage.prompt_tokens !== undefined) {
|
||||||
|
return {
|
||||||
|
prompt_tokens: responseBody.usage.prompt_tokens || 0,
|
||||||
|
completion_tokens: responseBody.usage.completion_tokens || 0,
|
||||||
|
cached_tokens: responseBody.usage.prompt_tokens_details?.cached_tokens,
|
||||||
|
reasoning_tokens: responseBody.usage.completion_tokens_details?.reasoning_tokens
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Gemini format
|
// Gemini format
|
||||||
if (responseBody.usageMetadata && typeof responseBody.usageMetadata === 'object') {
|
if (responseBody.usageMetadata && typeof responseBody.usageMetadata === 'object') {
|
||||||
return {
|
return {
|
||||||
@@ -723,6 +723,14 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log provider response (raw response from provider)
|
||||||
|
reqLogger.logProviderResponse(
|
||||||
|
providerResponse.status,
|
||||||
|
providerResponse.statusText,
|
||||||
|
providerResponse.headers,
|
||||||
|
responseBody
|
||||||
|
);
|
||||||
|
|
||||||
// Notify success - caller can clear error status if needed
|
// Notify success - caller can clear error status if needed
|
||||||
if (onRequestSuccess) {
|
if (onRequestSuccess) {
|
||||||
await onRequestSuccess();
|
await onRequestSuccess();
|
||||||
@@ -758,6 +766,9 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
|
|||||||
translatedResponse.usage = filterUsageForFormat(buffered, sourceFormat);
|
translatedResponse.usage = filterUsageForFormat(buffered, sourceFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log converted response (final response to client)
|
||||||
|
reqLogger.logConvertedResponse(translatedResponse);
|
||||||
|
|
||||||
const totalLatency = Date.now() - requestStartTime;
|
const totalLatency = Date.now() - requestStartTime;
|
||||||
const requestDetail = {
|
const requestDetail = {
|
||||||
provider: provider || "unknown",
|
provider: provider || "unknown",
|
||||||
|
|||||||
Reference in New Issue
Block a user