Files

59 lines
2.6 KiB
JavaScript

// Gemini per-1M-token pricing in USD. Used by the relay to compute
// per-call API costs as audit-log entries are written. Operator can
// update this table by editing the file and redeploying when Google
// changes published rates — preferable to a config field because
// (a) prices are stable for months at a time, (b) hardcoding keeps
// the audit log self-contained without a config-snapshot copy at
// write time.
//
// Rates as of mid-2026. ALWAYS verify against the current Google AI
// Studio pricing page before relying on these for billing-grade
// margin math — Google has been known to adjust prices ~quarterly.
export const GEMINI_PRICING = {
// The five supported models, verified against Google's official
// docs (ai.google.dev/gemini-api/docs/models) on 2026-05-12.
// Retired model IDs (gemini-3-pro-preview shut down 2026-03-09,
// gemini-2.0-flash deprecated) intentionally omitted — they should
// never appear in cost calc here for current calls.
// Pro tier — best for analysis.
"gemini-3.1-pro-preview": { input: 5.0, output: 25.0, thinking: 25.0 },
"gemini-2.5-pro": { input: 1.25, output: 10.0, thinking: 10.0 },
// Flash tier — best speed/cost for transcription + cheap analysis.
"gemini-3-flash-preview": { input: 0.3, output: 2.5, thinking: 2.5 },
"gemini-2.5-flash": { input: 0.3, output: 2.5, thinking: 2.5 },
"gemini-3.1-flash-lite": { input: 0.1, output: 0.4, thinking: 0.4 },
// Fallback used when an unknown model id appears (e.g. operator
// typed a custom model name in setBackendRouting). Conservative —
// priced like Flash so cost estimates skew low rather than 0.
default: { input: 0.3, output: 2.5, thinking: 2.5 },
};
// Compute cost for a Gemini API call given its model + usageMetadata
// (the shape @google/genai returns: promptTokenCount,
// candidatesTokenCount, thoughtsTokenCount). Returns:
// { input_tokens, output_tokens, thinking_tokens, cost_usd }
export function calcGeminiCost(model, usage) {
const rates = GEMINI_PRICING[model] || GEMINI_PRICING.default;
const inputTokens = usage?.promptTokenCount || 0;
const outputTokens = usage?.candidatesTokenCount || 0;
const thinkingTokens = usage?.thoughtsTokenCount || 0;
const costUSD =
(inputTokens / 1_000_000) * rates.input +
(outputTokens / 1_000_000) * rates.output +
(thinkingTokens / 1_000_000) * (rates.thinking ?? rates.output);
return {
input_tokens: inputTokens,
output_tokens: outputTokens,
thinking_tokens: thinkingTokens,
cost_usd: costUSD,
};
}
export function listKnownModels() {
return Object.keys(GEMINI_PRICING).filter((k) => k !== "default");
}