// cost-estimat.mjs — Heuristic cost-estimate for KB-update runs. // Pure function. Auth-mode-aware: api-key returns numeric USD, // subscription modes return null USD + kvote_warn flag. // Zero dependencies. const AVG_INPUT_TOKENS_PER_FILE = 3000; const AVG_OUTPUT_TOKENS_PER_FILE = 1500; const SONNET_INPUT_USD_PER_M = 3.0; const SONNET_OUTPUT_USD_PER_M = 15.0; const SUBSCRIPTION_MODES = new Set(['long-oauth', 'subscription-browser-only']); /** * Estimate cost (and quota-warn flag) for a run of N files at given priorities. * Filters to critical + high only (medium/low excluded per brief). * * @param {object} priorities — { critical, high, medium, low } file counts * @param {object} [opts] * @param {string} [opts.authMode] — 'api-key' | 'long-oauth' | 'subscription-browser-only' | 'unauthenticated' * @returns {{tokens_input: number, tokens_output: number, usd: number|null, kvote_warn: boolean}} */ export function estimateCost(priorities = {}, opts = {}) { const authMode = opts.authMode ?? 'api-key'; const fileCount = (priorities.critical ?? 0) + (priorities.high ?? 0); const tokens_input = fileCount * AVG_INPUT_TOKENS_PER_FILE; const tokens_output = fileCount * AVG_OUTPUT_TOKENS_PER_FILE; if (SUBSCRIPTION_MODES.has(authMode)) { return { tokens_input, tokens_output, usd: null, kvote_warn: true }; } const usd = (tokens_input / 1_000_000) * SONNET_INPUT_USD_PER_M + (tokens_output / 1_000_000) * SONNET_OUTPUT_USD_PER_M; return { tokens_input, tokens_output, usd, kvote_warn: false }; }