/** * @file Tests for the automatic pricing sync: a model seen in token_usage with * no row of its own gets one from the price list, an edited row is never * overwritten, and a bad list or a failed fetch changes nothing. * @author Nguyễn Ngọc Trí Vĩ */ const { describe, it, beforeEach } = require("node:test"); const assert = require("node:assert/strict"); const path = require("path"); const os = require("os"); process.env.DASHBOARD_DB_PATH = path.join( os.tmpdir(), `pricing-sync-${Date.now()}-${process.pid}.db` ); const { db } = require("../db"); const { syncPricing, familyOf, displayName, _resetCache } = require("../lib/pricing-sync"); // The real LiteLLM entry for Opus 5.5, trimmed. const LIST = { "claude-opus-9-9": { litellm_provider: "anthropic", input_cost_per_token: 0.000004, output_cost_per_token: 0.00002, cache_read_input_token_cost: 2e-7, cache_creation_input_token_cost: 0.000005, cache_creation_input_token_cost_above_1hr: 0.000008, supports_fast_mode: true, provider_specific_entry: { fast: 2 }, }, }; function useModel(model) { db.prepare("INSERT OR IGNORE INTO sessions (id, status, started_at) VALUES (?, 'active', ?)").run( `s-${model}`, new Date().toISOString() ); db.prepare("INSERT INTO token_usage (session_id, model) VALUES (?, ?)").run(`s-${model}`, model); } const row = (p) => db.prepare("SELECT * FROM model_pricing WHERE model_pattern = ?").get(p); beforeEach(() => { _resetCache(); db.prepare("DELETE FROM token_usage").run(); db.prepare("DELETE FROM model_pricing WHERE model_pattern LIKE 'claude-opus-9%'").run(); }); describe("pricing sync", () => { it("reduces an id to its family and names it", () => { assert.equal(familyOf("claude-opus-5-5-20260101"), "claude-opus-5-5"); assert.equal(familyOf("gpt-4"), null); assert.equal(familyOf("claude-x%"), null); assert.equal(displayName("claude-opus-5-5"), "Claude Opus 5.5"); }); it("adds a row for a used model that only a broader pattern matched", async () => { db.prepare( "INSERT INTO model_pricing (model_pattern, display_name, input_per_mtok) VALUES ('claude-opus-9%', 'Broad', 5)" ).run(); useModel("claude-opus-9-9-20260101"); const added = await syncPricing(db, { fetchList: async () => LIST }); assert.deepEqual(added, ["claude-opus-9-9%"]); const r = row("claude-opus-9-9%"); assert.equal(r.display_name, "Claude Opus 9.9"); assert.deepEqual([r.input_per_mtok, r.output_per_mtok, r.cache_read_per_mtok], [4, 20, 0.2]); assert.deepEqual([r.cache_write_per_mtok, r.cache_write_1h_per_mtok], [5, 8]); assert.deepEqual([r.fast_input_per_mtok, r.fast_output_per_mtok], [8, 40]); }); it("never overwrites a row that exists, and fetches nothing when none is missing", async () => { db.prepare( "INSERT INTO model_pricing (model_pattern, display_name, input_per_mtok) VALUES ('claude-opus-9-9%', 'Mine', 1)" ).run(); useModel("claude-opus-9-9"); let fetched = false; await syncPricing(db, { fetchList: async () => { fetched = true; return LIST; }, }); assert.equal(fetched, false); assert.equal(row("claude-opus-9-9%").input_per_mtok, 1); }); it("skips absurd rates and survives a failed fetch", async () => { useModel("claude-opus-9-9"); const bad = { "claude-opus-9-9": { ...LIST["claude-opus-9-9"], input_cost_per_token: 5 } }; assert.deepEqual(await syncPricing(db, { fetchList: async () => bad }), []); _resetCache(); const failed = await syncPricing(db, { fetchList: async () => { throw new Error("offline"); }, }); assert.deepEqual(failed, []); assert.equal(row("claude-opus-9-9%"), undefined); }); });