"use strict";exports.id=4334,exports.ids=[4334],exports.modules={34334:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{K5:()=>r,Py:()=>s,S3:()=>o,ab:()=>m,kO:()=>q,recordUsage:()=>n});var e=c(76760),f=c.n(e),g=c(73024),h=c.n(g),i=c(49120);let a=null,u=!1;try{a=(await Promise.resolve().then(c.t.bind(c,87550,23))).default,u=!0}catch(a){console.warn("[usageLimiter] better-sqlite3 not available:",a.message),console.warn("[usageLimiter] API key usage limiting will be disabled.")}let v=f().join(i.DATA_DIR,"usage-limits.db");function j(){if(global._usageLimiterStmts&&!global._usageLimiterStmts.insertReset&&(global._usageLimiterStmts=null),global._usageLimiterStmts)return global._usageLimiterStmts;let b=function(){if(global._usageLimiterDb)return global._usageLimiterDb;if(!u)return null;h().existsSync(i.DATA_DIR)||h().mkdirSync(i.DATA_DIR,{recursive:!0});try{let b=new a(v);return b.pragma("journal_mode = WAL"),b.pragma("synchronous = NORMAL"),b.exec(`
      CREATE TABLE IF NOT EXISTS usage_entries (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        api_key TEXT NOT NULL,
        input_tokens INTEGER NOT NULL DEFAULT 0,
        cost REAL NOT NULL DEFAULT 0,
        ts INTEGER NOT NULL
      );
      CREATE INDEX IF NOT EXISTS idx_usage_key_ts ON usage_entries(api_key, ts);

      CREATE TABLE IF NOT EXISTS reset_history (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        api_key TEXT NOT NULL,
        window_ms INTEGER,
        window_label TEXT NOT NULL,
        reset_at INTEGER NOT NULL,
        tokens_cleared INTEGER NOT NULL DEFAULT 0,
        cost_cleared REAL NOT NULL DEFAULT 0
      );
      CREATE INDEX IF NOT EXISTS idx_reset_history_key ON reset_history(api_key, reset_at);
    `),global._usageLimiterDb=b,b}catch(a){return console.error("[usageLimiter] Failed to open database:",a.message),null}}();if(!b)return null;try{b.exec(`
      CREATE TABLE IF NOT EXISTS reset_history (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        api_key TEXT NOT NULL,
        window_ms INTEGER,
        window_label TEXT NOT NULL,
        reset_at INTEGER NOT NULL,
        tokens_cleared INTEGER NOT NULL DEFAULT 0,
        cost_cleared REAL NOT NULL DEFAULT 0
      );
      CREATE INDEX IF NOT EXISTS idx_reset_history_key ON reset_history(api_key, reset_at);
    `)}catch{}return global._usageLimiterStmts={insert:b.prepare("INSERT INTO usage_entries (api_key, input_tokens, cost, ts) VALUES (?, ?, ?, ?)"),sumByKey:b.prepare(`
      SELECT
        SUM(CASE WHEN ts >= ? THEN input_tokens ELSE 0 END) AS inputTokens5h,
        SUM(input_tokens) AS inputTokens24h,
        SUM(CASE WHEN ts >= ? THEN cost ELSE 0 END) AS cost5h,
        SUM(cost) AS cost24h
      FROM usage_entries
      WHERE api_key = ? AND ts >= ?
    `),sumAllKeys:b.prepare(`
      SELECT
        api_key,
        SUM(CASE WHEN ts >= ? THEN input_tokens ELSE 0 END) AS inputTokens5h,
        SUM(input_tokens) AS inputTokens24h,
        SUM(CASE WHEN ts >= ? THEN cost ELSE 0 END) AS cost5h,
        SUM(cost) AS cost24h
      FROM usage_entries
      WHERE ts >= ?
      GROUP BY api_key
    `),sumByKeyWindow:b.prepare(`
      SELECT
        SUM(input_tokens) AS inputTokens,
        SUM(cost) AS cost
      FROM usage_entries
      WHERE api_key = ? AND ts >= ?
    `),prune:b.prepare("DELETE FROM usage_entries WHERE ts < ?"),insertReset:b.prepare("INSERT INTO reset_history (api_key, window_ms, window_label, reset_at, tokens_cleared, cost_cleared) VALUES (?, ?, ?, ?, ?, ?)"),getResetHistory:b.prepare("SELECT id, window_ms, window_label, reset_at, tokens_cleared, cost_cleared FROM reset_history WHERE api_key = ? ORDER BY reset_at DESC LIMIT 30"),sumForWindow:b.prepare("SELECT SUM(input_tokens) AS tokens, SUM(cost) AS cost FROM usage_entries WHERE api_key = ? AND ts >= ?"),sumAllForKey:b.prepare("SELECT SUM(input_tokens) AS tokens, SUM(cost) AS cost FROM usage_entries WHERE api_key = ?"),deleteByWindow:b.prepare("DELETE FROM usage_entries WHERE api_key = ? AND ts >= ?"),deleteAllForKey:b.prepare("DELETE FROM usage_entries WHERE api_key = ?")},global._usageLimiterStmts}global._usageLimiterDb||(global._usageLimiterDb=null),global._usageLimiterStmts||(global._usageLimiterStmts=null),global._usageLimiterTotals||(global._usageLimiterTotals={});let w=global._usageLimiterTotals;global._usageLimiterLimits||(global._usageLimiterLimits={data:{},ts:0});let x=global._usageLimiterLimits;async function k(){if(!(Date.now()-x.ts<5e3))try{let{getApiKeys:a}=await Promise.all([c.e(7502),c.e(9718)]).then(c.bind(c,89718)),b=await a(),d={};for(let a of b)a.limits&&(d[a.key]=a.limits);x.data=d,x.ts=Date.now()}catch(a){console.error("[usageLimiter] Failed to refresh limits cache:",a.message)}}function l(a,b){if(!u)return{inputTokens:0,cost:0};let c=Date.now();try{let d=j();if(!d)return{inputTokens:0,cost:0};let e=d.sumByKeyWindow.get(a,c-b);return{inputTokens:e?.inputTokens||0,cost:e?.cost||0}}catch(a){return console.error("[usageLimiter] getWindowUsage failed:",a.message),{inputTokens:0,cost:0}}}async function m(a){if(!a)return{allowed:!0};global._usageLimiterTimer||function(){if(!global._usageLimiterTimer){if(!u)return console.warn("[usageLimiter] Background recalc disabled: better-sqlite3 not available");t(),global._usageLimiterTimer=setInterval(t,6e4),global._usageLimiterTimer.unref&&global._usageLimiterTimer.unref()}}(),await k();let b=x.data[a];if(!b)return{allowed:!0};w[a]||function(a){if(!u){w[a]={inputTokens5h:0,inputTokens24h:0,cost5h:0,cost24h:0,windows:[]};return}let b=Date.now(),c=b-18e6;try{let d=j();if(!d){w[a]={inputTokens5h:0,inputTokens24h:0,cost5h:0,cost24h:0,windows:[]};return}let e=d.sumByKey.get(c,c,a,b-864e5);w[a]={inputTokens5h:e?.inputTokens5h||0,inputTokens24h:e?.inputTokens24h||0,cost5h:e?.cost5h||0,cost24h:e?.cost24h||0,windows:[]}}catch(b){console.error("[usageLimiter] recalcKey failed:",b.message),w[a]={inputTokens5h:0,inputTokens24h:0,cost5h:0,cost24h:0,windows:[]}}}(a);let d=w[a]||{inputTokens5h:0,inputTokens24h:0,cost5h:0,cost24h:0,windows:[]},e=[];if(b.inputTokens5h&&e.push({field:"inputTokens5h",limit:b.inputTokens5h,label:"5h input token",fmt:a=>a.toLocaleString()+" tokens",type:"legacy"}),b.inputTokens24h&&e.push({field:"inputTokens24h",limit:b.inputTokens24h,label:"24h input token",fmt:a=>a.toLocaleString()+" tokens",type:"legacy"}),b.cost5h&&e.push({field:"cost5h",limit:b.cost5h,label:"5h cost",fmt:a=>"$"+a.toFixed(4),type:"legacy"}),b.cost24h&&e.push({field:"cost24h",limit:b.cost24h,label:"24h cost",fmt:a=>"$"+a.toFixed(4),type:"legacy"}),b.windows&&Array.isArray(b.windows))for(let c of b.windows){if(!c.durationMs||!c.inputTokens&&!c.cost)continue;let b=l(a,c.durationMs);c.inputTokens&&e.push({field:`window_${c.durationMs}_tokens`,limit:c.inputTokens,label:`${p(c.durationMs)} input token`,fmt:a=>a.toLocaleString()+" tokens",type:"window",durationMs:c.durationMs,current:b.inputTokens}),c.cost&&e.push({field:`window_${c.durationMs}_cost`,limit:c.cost,label:`${p(c.durationMs)} cost`,fmt:a=>"$"+a.toFixed(4),type:"window",durationMs:c.durationMs,current:b.cost})}for(let b of e){let e="window"===b.type?b.current:d[b.field];if(e>=b.limit){let f=a.slice(0,8)+"...";try{let{getApiKeys:b}=await Promise.all([c.e(7502),c.e(9718)]).then(c.bind(c,89718)),d=(await b()).find(b=>b.key===a);d&&(f=d.name)}catch{}return{allowed:!1,reason:`API key "${f}" exceeded ${b.label} limit (${b.fmt(e)} / ${b.fmt(b.limit)})`,limitType:b.field,usage:{...d}}}}return{allowed:!0,usage:{...d}}}function n(a,b,c){if(!a||"string"!=typeof a||!u)return;let d=Date.now();try{let e=j();if(!e)return;e.insert.run(a,b||0,c||0,d)}catch(a){console.error("[usageLimiter] INSERT failed:",a.message);return}w[a]||(w[a]={inputTokens5h:0,inputTokens24h:0,cost5h:0,cost24h:0,windows:[]});let e=w[a],f=b||0,g=c||0;e.inputTokens5h+=f,e.inputTokens24h+=f,e.cost5h+=g,e.cost24h+=g}async function o(a){let b=Date.now(),c=b-18e6,d={inputTokens5h:0,inputTokens24h:0,cost5h:0,cost24h:0};try{if(!u)return{usage:d,limits:{},windowUsage:{}};let e=j();if(!e)return{usage:d,limits:{},windowUsage:{}};let f=e.sumByKey.get(c,c,a,b-864e5);d={inputTokens5h:f?.inputTokens5h||0,inputTokens24h:f?.inputTokens24h||0,cost5h:f?.cost5h||0,cost24h:f?.cost24h||0}}catch(a){console.error("[usageLimiter] getUsageSummary failed:",a.message)}await k();let e=x.data[a]||{},f={};if(e.windows&&Array.isArray(e.windows))for(let b of e.windows){if(!b.durationMs)continue;let c=l(a,b.durationMs);f[`tokens_${b.durationMs}`]=c.inputTokens,f[`cost_${b.durationMs}`]=c.cost}return{usage:d,limits:e,windowUsage:f}}function p(a){let b=Math.floor(a/6e4),c=Math.floor(a/36e5),d=Math.floor(a/864e5);return d>0?`${d}d`:c>0?`${c}h`:`${b}m`}function q(a,b,c){if(!u)return{tokensCleared:0,costCleared:0};let d=j();if(!d)return{tokensCleared:0,costCleared:0};let e=Date.now(),f=0,g=0;try{if(b){let c=e-b,h=d.sumForWindow.get(a,c);f=h?.tokens||0,g=h?.cost||0,d.deleteByWindow.run(a,c)}else{let b=d.sumAllForKey.get(a);f=b?.tokens||0,g=b?.cost||0,d.deleteAllForKey.run(a)}d.insertReset.run(a,b||null,c||"All time",e,Math.round(f),g),delete w[a]}catch(a){console.error("[usageLimiter] resetKeyUsage failed:",a.message)}return{tokensCleared:Math.round(f),costCleared:g}}function r(a){if(!u)return[];let b=j();if(!b)return[];try{return b.getResetHistory.all(a)}catch(a){return console.error("[usageLimiter] getResetHistory failed:",a.message),[]}}function s(a){if(!a||"object"!=typeof a)return{valid:!1,error:"Window must be an object"};if(!a.durationMs||"number"!=typeof a.durationMs||a.durationMs<6e4)return{valid:!1,error:"durationMs must be at least 1 minute"};if(a.durationMs>2592e6)return{valid:!1,error:"durationMs cannot exceed 2592000000ms (30 days)"};let b=a.inputTokens&&"number"==typeof a.inputTokens&&a.inputTokens>0,c=a.cost&&"number"==typeof a.cost&&a.cost>0;return b||c?{valid:!0}:{valid:!1,error:"Window must have either inputTokens or cost limit"}}function t(){if(u)try{let a=j();if(!a)return;let b=Date.now(),c=b-18e6;a.prune.run(b-2592e6);let d=a.sumAllKeys.all(c,c,b-864e5),e={};for(let a of d)e[a.api_key]={inputTokens5h:a.inputTokens5h||0,inputTokens24h:a.inputTokens24h||0,cost5h:a.cost5h||0,cost24h:a.cost24h||0};for(let a of Object.keys(w))e[a]||delete w[a];for(let[a,b]of Object.entries(e))w[a]?w[a]={...b,windows:w[a].windows||[]}:w[a]={...b,windows:[]}}catch(a){console.error("[usageLimiter] Background recalc failed:",a.message)}}global._usageLimiterTimer||(global._usageLimiterTimer=null),d()}catch(a){d(a)}},1)}};