diff --git a/open-sse/handlers/responseSanitizer.ts b/open-sse/handlers/responseSanitizer.ts index 780bb8afe8..76500b1840 100644 --- a/open-sse/handlers/responseSanitizer.ts +++ b/open-sse/handlers/responseSanitizer.ts @@ -231,6 +231,17 @@ function sanitizeUsage(usage: unknown): unknown { if (!usageRecord) return usage; const sanitized: JsonRecord = {}; + + // Cross-map Claude-style → OpenAI-style field names. + // Some providers return input_tokens/output_tokens instead of prompt_tokens/completion_tokens. + // Without this mapping, the whitelist filter below strips them, resulting in NaN/0 tokens (#617). + if (usageRecord.input_tokens !== undefined && usageRecord.prompt_tokens === undefined) { + usageRecord.prompt_tokens = usageRecord.input_tokens; + } + if (usageRecord.output_tokens !== undefined && usageRecord.completion_tokens === undefined) { + usageRecord.completion_tokens = usageRecord.output_tokens; + } + for (const key of ALLOWED_USAGE_FIELDS) { if (usageRecord[key] !== undefined) { sanitized[key] = usageRecord[key]; diff --git a/package-lock.json b/package-lock.json index 228bbd53fb..79a11f948f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19810,9 +19810,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "dev": true, "license": "ISC", "bin": {