feat(usage): track cached tokens + correct input/output/cache cost (#2209)
Normalize every provider to one cache-inclusive convention via canonicalizeUsage() before persist, and price cached + cache_creation as subsets of prompt_tokens in calculateCostFromTokens() to stop double-counting. usageRepo now delegates cost math to a single source. Surface Cached tokens/cost across dashboard (overview, tokens, cost, details). Merge Claude message_start cache with message_delta output so cache counts survive. Compatible LLM nodes now allow multiple API-key connections (key pool). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -38,14 +38,14 @@ async function setupTestContext(nodeData) {
|
||||
};
|
||||
}
|
||||
|
||||
function makeRequest(provider) {
|
||||
function makeRequest(provider, name = "Test Connection") {
|
||||
return new Request("https://9router.local/api/providers", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
provider,
|
||||
apiKey: "test-key",
|
||||
name: "Test Connection",
|
||||
name,
|
||||
defaultModel: "test-model",
|
||||
}),
|
||||
});
|
||||
@@ -156,8 +156,8 @@ describe("compatible provider connections API", () => {
|
||||
});
|
||||
cleanup = ctx.cleanup;
|
||||
|
||||
const firstResponse = await ctx.POST(makeRequest(ctx.node.id));
|
||||
const secondResponse = await ctx.POST(makeRequest(ctx.node.id));
|
||||
const firstResponse = await ctx.POST(makeRequest(ctx.node.id, "Key A"));
|
||||
const secondResponse = await ctx.POST(makeRequest(ctx.node.id, "Key B"));
|
||||
const storedConnections = await ctx.getProviderConnections({ provider: ctx.node.id });
|
||||
|
||||
expect(firstResponse.status).toBe(201);
|
||||
|
||||
Reference in New Issue
Block a user