omniroute 2.7.2 → 2.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/.next/BUILD_ID +1 -1
- package/app/.next/build-manifest.json +2 -2
- package/app/.next/prerender-manifest.json +3 -3
- package/app/.next/server/app/(dashboard)/dashboard/a2a/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/agents/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/analytics/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/api-manager/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/audit-log/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/auto-combo/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/costs/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/health/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/limits/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/logs/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/mcp/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/media/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/onboarding/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/playground/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/settings/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/400/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/401/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/403/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/408/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/429/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/500/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/502/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/503/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_global-error.html +2 -2
- package/app/.next/server/app/_global-error.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/api/chat/route.js +3 -3
- package/app/.next/server/app/api/v1/audio/speech/route.js +3 -3
- package/app/.next/server/app/api/v1/audio/transcriptions/route.js +6 -6
- package/app/.next/server/app/api/v1/chat/completions/route.js +7 -7
- package/app/.next/server/app/api/v1/completions/route.js +7 -7
- package/app/.next/server/app/api/v1/embeddings/route.js +5 -5
- package/app/.next/server/app/api/v1/images/generations/route.js +7 -7
- package/app/.next/server/app/api/v1/messages/route.js +3 -3
- package/app/.next/server/app/api/v1/moderations/route.js +3 -3
- package/app/.next/server/app/api/v1/music/generations/route.js +4 -4
- package/app/.next/server/app/api/v1/providers/[provider]/chat/completions/route.js +8 -8
- package/app/.next/server/app/api/v1/providers/[provider]/embeddings/route.js +5 -5
- package/app/.next/server/app/api/v1/providers/[provider]/images/generations/route.js +8 -8
- package/app/.next/server/app/api/v1/rerank/route.js +6 -6
- package/app/.next/server/app/api/v1/responses/route.js +3 -3
- package/app/.next/server/app/api/v1/search/route.js +6 -6
- package/app/.next/server/app/api/v1/videos/generations/route.js +6 -6
- package/app/.next/server/app/api/v1beta/models/[...path]/route.js +8 -8
- package/app/.next/server/app/callback/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/docs/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/forbidden/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/forgot-password/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/landing/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/maintenance/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/privacy/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/status/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/terms/page_client-reference-manifest.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__09c944b3._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__167585da._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__7d9b23e7._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__80e3bfc3._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__84e445b2._.js +2 -2
- package/app/.next/server/chunks/[root-of-the-server]__92cb0def._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__db2f9fe0._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__dc47ee64._.js +1 -1
- package/app/.next/server/chunks/_05c48915._.js +1 -1
- package/app/.next/server/chunks/_2115d8de._.js +1 -1
- package/app/.next/server/chunks/_3ac953eb._.js +1 -1
- package/app/.next/server/chunks/_4b8fd853._.js +1 -1
- package/app/.next/server/chunks/_68683848._.js +1 -1
- package/app/.next/server/chunks/_6f1b3c3f._.js +1 -1
- package/app/.next/server/chunks/_ee9b677b._.js +1 -1
- package/app/.next/server/chunks/_ffda39da._.js +10 -10
- package/app/.next/server/chunks/src_4787afd3._.js +1 -1
- package/app/.next/server/chunks/ssr/[root-of-the-server]__9affb65e._.js +1 -1
- package/app/.next/server/chunks/ssr/[root-of-the-server]__a6942102._.js +1 -1
- package/app/.next/server/pages/500.html +2 -2
- package/app/.next/server/server-reference-manifest.js +1 -1
- package/app/.next/server/server-reference-manifest.json +1 -1
- package/app/.next/static/chunks/{f83525924aff5f68.js → 1d4f94c2f5112482.js} +1 -1
- package/app/CHANGELOG.md +13 -0
- package/app/docs/openapi.yaml +1 -1
- package/app/package-lock.json +2 -2
- package/app/package.json +1 -1
- package/app/src/domain/quotaCache.ts +40 -1
- package/app/src/sse/services/auth.ts +30 -5
- package/app/tests/unit/quota-policy-generalization.test.mjs +40 -0
- package/package.json +1 -1
- /package/app/.next/static/{_WuQZHRMiXNmIFgVwbr-Q → TaE7xCUJ3vzE5oXXL5DhE}/_buildManifest.js +0 -0
- /package/app/.next/static/{_WuQZHRMiXNmIFgVwbr-Q → TaE7xCUJ3vzE5oXXL5DhE}/_clientMiddlewareManifest.json +0 -0
- /package/app/.next/static/{_WuQZHRMiXNmIFgVwbr-Q → TaE7xCUJ3vzE5oXXL5DhE}/_ssgManifest.js +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module.exports=[287726,e=>{"use strict";e.i(245272);var t=e.i(385498),r=e.i(125852),i=e.i(548941),n=e.i(25687),l=e.i(441637),o=e.i(828059),a=e.i(16023),s=e.i(706901),c=e.i(73114);function d(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:{}}function u(e){return"string"==typeof e&&e.trim().length>0?e:null}function f(e,t=0){if("number"==typeof e&&Number.isFinite(e))return e;if("string"==typeof e&&e.trim().length>0){let r=Number(e);return Number.isFinite(r)?r:t}return t}function A(e){let t=d(e);return{id:u(t.id)||"",isActive:!0===t.isActive,rateLimitedUntil:u(t.rateLimitedUntil),testStatus:u(t.testStatus),apiKey:u(t.apiKey),accessToken:u(t.accessToken),refreshToken:u(t.refreshToken),tokenExpiresAt:u(t.tokenExpiresAt),expiresAt:u(t.expiresAt),projectId:u(t.projectId),providerSpecificData:d(t.providerSpecificData),lastUsedAt:u(t.lastUsedAt),consecutiveUseCount:f(t.consecutiveUseCount,0),priority:f(t.priority,999),lastError:u(t.lastError),lastErrorType:u(t.lastErrorType),lastErrorSource:u(t.lastErrorSource),errorCode:"string"==typeof t.errorCode||"number"==typeof t.errorCode?t.errorCode:null,backoffLevel:f(t.backoffLevel,0)}}function p(e,t){return"boolean"==typeof e?e:t}function m(e,t=90){return Math.min(100,Math.max(1,f(e,t)))}function h(e){if("string"!=typeof e)return null;let t=e.trim().toLowerCase();return t.length>0?t:null}function y(e){if(!e)return null;let t=new Date(e).getTime();return!Number.isFinite(t)||t<=Date.now()?null:t}function g(e){return e.map(e=>({raw:e,ms:y(e)})).filter(e=>null!==e.ms).sort((e,t)=>e.ms-t.ms)[0]?.raw||null}let U=Promise.resolve(),w=new Map;async function T(e,r=null,o=null){let a,u=U;U=new Promise(e=>{a=e});try{let a;await u;let U=await (0,t.getProviderConnections)({provider:e,isActive:!0}),w=(Array.isArray(U)?U:[]).map(A).filter(e=>e.id.length>0);if(o&&o.length>0&&(w=w.filter(e=>o.includes(e.id))),s.debug("AUTH",`${e} | total connections: ${w.length}, excludeId: ${r||"none"}`),0===w.length){let r=await (0,t.getProviderConnections)({provider:e}),i=(Array.isArray(r)?r:[]).map(A).filter(e=>e.id.length>0);if(s.debug("AUTH",`${e} | all connections (incl inactive): ${i.length}`),i.length>0){let t=(0,l.getEarliestRateLimitedUntil)(i);if(t)return s.warn("AUTH",`${e} | all ${i.length} accounts rate limited (${(0,l.formatRetryAfter)(t)})`),{allRateLimited:!0,retryAfter:t,retryAfterHuman:(0,l.formatRetryAfter)(t)};s.warn("AUTH",`${e} | ${i.length} accounts found but none active`),i.forEach(e=>{s.debug("AUTH",` → ${e.id?.slice(0,8)} | isActive=${e.isActive} | rateLimitedUntil=${e.rateLimitedUntil||"none"} | testStatus=${e.testStatus}`)})}return s.warn("AUTH",`No credentials for ${e}`),null}let T=w.filter(e=>!(r&&e.id===r||(0,l.isAccountUnavailable)(e.rateLimitedUntil)));if(s.debug("AUTH",`${e} | available: ${T.length}/${w.length}`),w.forEach(e=>{let t=r&&e.id===r,i=(0,l.isAccountUnavailable)(e.rateLimitedUntil);(t||i)&&s.debug("AUTH",` → ${e.id?.slice(0,8)} | ${t?"excluded":""} ${i?`rateLimited until ${e.rateLimitedUntil}`:""}`)}),0===T.length){let t=(0,l.getEarliestRateLimitedUntil)(w);if(t){let r=w.filter(e=>e.rateLimitedUntil&&new Date(e.rateLimitedUntil).getTime()>Date.now()).sort((e,t)=>new Date(e.rateLimitedUntil||0).getTime()-new Date(t.rateLimitedUntil||0).getTime())[0];return s.warn("AUTH",`${e} | all ${w.length} active accounts rate limited (${(0,l.formatRetryAfter)(t)}) | lastErrorCode=${r?.errorCode}, lastError=${r?.lastError?.slice(0,50)}`),{allRateLimited:!0,retryAfter:t,retryAfterHuman:(0,l.formatRetryAfter)(t),lastError:r?.lastError||null,lastErrorCode:r?.errorCode||null}}return s.warn("AUTH",`${e} | all ${w.length} accounts unavailable`),null}let v=T,b=[];if(v=T.filter(t=>{let r=function(e,t){let r=function(e,t){let r=d(t.limitPolicy),i=(Array.isArray(r.windows)?r.windows:[]).map(h).filter(Boolean);if("codex"===e){var n;let e,l,o,a=(n=t,l=(e=d(n.codexLimitPolicy),{use5h:p(e.use5h,!0),useWeekly:p(e.useWeekly,!0)}),o=[],l.use5h&&o.push("session"),l.useWeekly&&o.push("weekly"),o),s=i.length>0?i:a;return{enabled:p(r.enabled,s.length>0),thresholdPercent:m(r.thresholdPercent),windows:s}}return{enabled:p(r.enabled,!1),thresholdPercent:m(r.thresholdPercent),windows:i}}(e,t.providerSpecificData);if(!r.enabled||0===r.windows.length)return{blocked:!1,reasons:[],resetAt:null};let i=[],l=[];for(let e of r.windows){let o=(0,n.getQuotaWindowStatus)(t.id,e,r.thresholdPercent);o?.reachedThreshold&&(i.push(`${e} usage ${Math.round(o.usedPercentage)}%`),l.push(o.resetAt))}return{blocked:i.length>0,reasons:i,resetAt:g(l)}}(e,t);return!r.blocked||(b.push({id:t.id,reasons:r.reasons,resetAt:r.resetAt}),!1)}),b.length>0&&s.info("AUTH",`${e} | quota policy filtered ${b.length} account(s): ${b.map(e=>`${e.id.slice(0,8)}(${e.reasons.join(", ")})`).join("; ")}`),0===v.length&&T.length>0){let t=g(b.map(e=>e.resetAt)),r=y(t),i=r?new Date(r).toISOString():new Date(Date.now()+3e5).toISOString();return{allRateLimited:!0,retryAfter:i,retryAfterHuman:(0,l.formatRetryAfter)(i),lastError:`All ${e} accounts reached configured quota threshold`,lastErrorCode:429}}let S=v.filter(e=>!(0,n.isAccountQuotaExhausted)(e.id)),$=v.filter(e=>(0,n.isAccountQuotaExhausted)(e.id)),k=S.length>0?[...S,...$]:v;$.length>0&&s.debug("AUTH",`${e} | quota-aware: ${S.length} with quota, ${$.length} exhausted`);let E=await (0,i.getSettings)(),L=E.fallbackStrategy||"fill-first";if("round-robin"===L){let i=f(E.stickyRoundRobinLimit,3);if(null!==r)a=[...k].sort((e,t)=>{let r=e.backoffLevel||0,i=t.backoffLevel||0;return r!==i?r-i:e.lastUsedAt||t.lastUsedAt?e.lastUsedAt?t.lastUsedAt?new Date(e.lastUsedAt).getTime()-new Date(t.lastUsedAt).getTime():1:-1:(e.priority||999)-(t.priority||999)})[0],s.info("AUTH",`${e} round-robin: FALLBACK MODE - excluded ${r?.slice(0,8)}..., picked LRU ${a.id?.slice(0,8)}...`),await (0,t.updateProviderConnection)(a.id,{lastUsedAt:new Date().toISOString(),consecutiveUseCount:1});else{let r=[...k].sort((e,t)=>e.lastUsedAt||t.lastUsedAt?e.lastUsedAt?t.lastUsedAt?new Date(t.lastUsedAt).getTime()-new Date(e.lastUsedAt).getTime():-1:1:(e.priority||999)-(t.priority||999))[0],n=r?.consecutiveUseCount||0;r&&r.lastUsedAt&&n<i?(a=r,s.debug("AUTH",`${e} round-robin: staying with ${r.id?.slice(0,8)}... (count=${n}/${i})`),await (0,t.updateProviderConnection)(a.id,{lastUsedAt:new Date().toISOString(),consecutiveUseCount:(a.consecutiveUseCount||0)+1})):(a=[...k].sort((e,t)=>{let r=e.backoffLevel||0,i=t.backoffLevel||0;return r!==i?r-i:e.lastUsedAt||t.lastUsedAt?e.lastUsedAt?t.lastUsedAt?new Date(e.lastUsedAt).getTime()-new Date(t.lastUsedAt).getTime():1:-1:(e.priority||999)-(t.priority||999)})[0],s.debug("AUTH",`${e} round-robin: switching to LRU ${a.id?.slice(0,8)}... (current count=${n} >= limit=${i} or no lastUsedAt)`),await (0,t.updateProviderConnection)(a.id,{lastUsedAt:new Date().toISOString(),consecutiveUseCount:1}))}}else if("p2c"===L)if(k.length<=2)a=k[0];else{let e=Math.floor(Math.random()*k.length),t=Math.floor(Math.random()*(k.length-1));t>=e&&t++;let r=k[e],i=k[t],n=(r.consecutiveUseCount||0)+10*!!r.lastError,l=(i.consecutiveUseCount||0)+10*!!i.lastError;a=n<=l?r:i}else if("random"===L){let e=Math.floor(Math.random()*k.length);a=k[e]}else if("least-used"===L)a=[...k].sort((e,t)=>e.lastUsedAt||t.lastUsedAt?e.lastUsedAt?t.lastUsedAt?new Date(e.lastUsedAt).getTime()-new Date(t.lastUsedAt).getTime():1:-1:(e.priority||999)-(t.priority||999))[0];else if("cost-optimized"===L)a=[...k].sort((e,t)=>(e.priority||999)-(t.priority||999))[0];else if("strict-random"===L){let t=k.map(e=>e.id),r=(0,c.getNextFromDeckSync)(`conn:${e}`,t);a=k.find(e=>e.id===r)||k[0]}else a=k[0];return{apiKey:a.apiKey,accessToken:a.accessToken,refreshToken:a.refreshToken,expiresAt:a.tokenExpiresAt||a.expiresAt||null,projectId:a.projectId,copilotToken:"string"==typeof a.providerSpecificData.copilotToken?a.providerSpecificData.copilotToken:null,providerSpecificData:a.providerSpecificData,connectionId:a.id,testStatus:a.testStatus,lastError:a.lastError,lastErrorType:a.lastErrorType,lastErrorSource:a.lastErrorSource,errorCode:a.errorCode,rateLimitedUntil:a.rateLimitedUntil}}finally{a&&a()}}async function v(e,r,i,n=null,c=null){let d,u=w.get(e)||Promise.resolve();w.set(e,new Promise(e=>{d=e}));try{await u;let d=await (0,t.getProviderConnections)({provider:n}),f=(Array.isArray(d)?d:[]).map(A).filter(e=>e.id.length>0).find(t=>t.id===e),p=f?.backoffLevel||0;if(f?.rateLimitedUntil&&new Date(f.rateLimitedUntil).getTime()>Date.now())return s.info("AUTH",`${e.slice(0,8)} already marked unavailable (until ${f.rateLimitedUntil}), skipping duplicate mark`),{shouldFallback:!0,cooldownMs:new Date(f.rateLimitedUntil).getTime()-Date.now()};let{shouldFallback:m,cooldownMs:h,newBackoffLevel:y,reason:g}=(0,l.checkFallbackError)(r,i,p,c,n);if(!m)return{shouldFallback:!1,cooldownMs:0};let U=f?.providerSpecificData?.baseUrl;if((0,o.isLocalProvider)(U)&&404===r&&n&&c){let t=a.COOLDOWN_MS.notFoundLocal;return(0,l.lockModel)(n,e,c,"local_not_found",t),s.info("AUTH",`Local 404 for ${c} — model-only lockout ${t/1e3}s (connection stays active)`),{shouldFallback:!0,cooldownMs:t}}let w=(0,l.getUnavailableUntil)(h),T="string"==typeof i?i.slice(0,100):"Provider error";return await (0,t.updateProviderConnection)(e,{rateLimitedUntil:w,testStatus:"unavailable",lastError:T,errorCode:r,lastErrorAt:new Date().toISOString(),backoffLevel:y??p}),n&&c&&h>0&&(0,l.lockModel)(n,e,c,g||"unknown",h),n&&r&&T&&console.error(`❌ ${n} [${r}]: ${T}`),{shouldFallback:!0,cooldownMs:h}}finally{d&&d(),w.delete(e)}}async function b(e,r){(r.testStatus&&"active"!==r.testStatus||r.lastError||r.rateLimitedUntil||r.errorCode||r.lastErrorType||r.lastErrorSource)&&(await (0,t.updateProviderConnection)(e,{testStatus:"active",lastError:null,lastErrorAt:null,lastErrorType:null,lastErrorSource:null,errorCode:null,rateLimitedUntil:null,backoffLevel:0}),s.info("AUTH",`Account ${e.slice(0,8)} error cleared`))}async function S(e){e?.connectionId&&await b(e.connectionId,e)}function $(e){let t=e.headers.get("Authorization");return t?.startsWith("Bearer ")?t.slice(7):null}async function k(e){return!!e&&await (0,r.validateApiKey)(e)}e.s(["clearAccountError",()=>b,"clearRecoveredProviderState",()=>S,"extractApiKey",()=>$,"getProviderCredentials",()=>T,"isValidApiKey",()=>k,"markAccountUnavailable",()=>v])},478847,e=>{"use strict";var t=e.i(287726);e.i(245272);var r=e.i(125852),i=e.i(362225),n=e.i(719201),l=e.i(16023),o=e.i(706901);async function a(e,a){let s=(0,t.extractApiKey)(e);if(!s)return{apiKey:null,apiKeyInfo:null,rejection:null};let c=null;try{c=await (0,r.getApiKeyMetadata)(s)}catch(e){return o.error("API_POLICY","Failed to fetch API key metadata. Request blocked.",{error:e}),{apiKey:s,apiKeyInfo:null,rejection:(0,n.errorResponse)(l.HTTP_STATUS.SERVICE_UNAVAILABLE,"API key policy unavailable")}}if(!c)return{apiKey:s,apiKeyInfo:null,rejection:null};if(!1===c.isActive)return{apiKey:s,apiKeyInfo:c,rejection:(0,n.errorResponse)(l.HTTP_STATUS.FORBIDDEN,"This API key is disabled")};if(c.accessSchedule&&c.accessSchedule.enabled&&!function(e){let t,r;if(!e.enabled)return!0;let i=new Date;try{t=new Intl.DateTimeFormat("en-US",{timeZone:e.tz,hour:"2-digit",minute:"2-digit",hour12:!1}).format(i)}catch{return!0}let[n,l]=t.replace(/^24:/,"00:").split(":").map(Number),o=60*n+l;try{r=new Intl.DateTimeFormat("en-US",{timeZone:e.tz,weekday:"short"}).format(i)}catch{return!0}let a={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6}[r]??i.getDay();if(!e.days.includes(a))return!1;let[s,c]=e.from.split(":").map(Number),[d,u]=e.until.split(":").map(Number),f=60*s+c,A=60*d+u;return A<f?o>=f||o<A:o>=f&&o<A}(c.accessSchedule)){let{from:e,until:t,tz:r}=c.accessSchedule;return{apiKey:s,apiKeyInfo:c,rejection:(0,n.errorResponse)(l.HTTP_STATUS.FORBIDDEN,`Access denied outside allowed hours (${e}–${t} ${r})`)}}if(a&&c.allowedModels&&c.allowedModels.length>0&&!await (0,r.isModelAllowedForKey)(s,a))return{apiKey:s,apiKeyInfo:c,rejection:(0,n.errorResponse)(l.HTTP_STATUS.FORBIDDEN,`Model "${a}" is not allowed for this API key`)};if(c.id)try{let e=(0,i.checkBudget)(c.id);if(!e.allowed)return{apiKey:s,apiKeyInfo:c,rejection:(0,n.errorResponse)(l.HTTP_STATUS.RATE_LIMITED,e.reason||"Budget limit exceeded")}}catch(e){return o.error("API_POLICY","Budget check failed. Request blocked.",{error:e}),{apiKey:s,apiKeyInfo:c,rejection:(0,n.errorResponse)(l.HTTP_STATUS.SERVICE_UNAVAILABLE,"Budget policy unavailable")}}return{apiKey:s,apiKeyInfo:c,rejection:null}}e.s(["enforceApiKeyPolicy",()=>a])}];
|
|
1
|
+
module.exports=[287726,e=>{"use strict";e.i(245272);var t=e.i(385498),r=e.i(125852),i=e.i(548941),n=e.i(25687),l=e.i(441637),o=e.i(828059),a=e.i(16023),s=e.i(706901),c=e.i(73114);function d(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:{}}function u(e){return"string"==typeof e&&e.trim().length>0?e:null}function f(e,t=0){if("number"==typeof e&&Number.isFinite(e))return e;if("string"==typeof e&&e.trim().length>0){let r=Number(e);return Number.isFinite(r)?r:t}return t}function A(e){let t=d(e);return{id:u(t.id)||"",isActive:!0===t.isActive,rateLimitedUntil:u(t.rateLimitedUntil),testStatus:u(t.testStatus),apiKey:u(t.apiKey),accessToken:u(t.accessToken),refreshToken:u(t.refreshToken),tokenExpiresAt:u(t.tokenExpiresAt),expiresAt:u(t.expiresAt),projectId:u(t.projectId),providerSpecificData:d(t.providerSpecificData),lastUsedAt:u(t.lastUsedAt),consecutiveUseCount:f(t.consecutiveUseCount,0),priority:f(t.priority,999),lastError:u(t.lastError),lastErrorType:u(t.lastErrorType),lastErrorSource:u(t.lastErrorSource),errorCode:"string"==typeof t.errorCode||"number"==typeof t.errorCode?t.errorCode:null,backoffLevel:f(t.backoffLevel,0)}}function p(e,t){return"boolean"==typeof e?e:t}function m(e,t=90){return Math.min(100,Math.max(1,f(e,t)))}function h(e){if("string"!=typeof e)return null;let t=e.trim().toLowerCase();return t.length>0?t:null}function y(e){if("string"!=typeof e)return null;let t=e.trim().toLowerCase();return"session (5h)"===t||"5h"===t||"five_hour"===t?"session":"weekly (7d)"===t||"7d"===t||"seven_day"===t?"weekly":t}function g(e){if(!e)return null;let t=new Date(e).getTime();return!Number.isFinite(t)||t<=Date.now()?null:t}function U(e){return e.map(e=>({raw:e,ms:g(e)})).filter(e=>null!==e.ms).sort((e,t)=>e.ms-t.ms)[0]?.raw||null}let w=Promise.resolve(),T=new Map;async function v(e,r=null,o=null){let a,u=w;w=new Promise(e=>{a=e});try{let a;await u;let w=await (0,t.getProviderConnections)({provider:e,isActive:!0}),T=(Array.isArray(w)?w:[]).map(A).filter(e=>e.id.length>0);if(o&&o.length>0&&(T=T.filter(e=>o.includes(e.id))),s.debug("AUTH",`${e} | total connections: ${T.length}, excludeId: ${r||"none"}`),0===T.length){let r=await (0,t.getProviderConnections)({provider:e}),i=(Array.isArray(r)?r:[]).map(A).filter(e=>e.id.length>0);if(s.debug("AUTH",`${e} | all connections (incl inactive): ${i.length}`),i.length>0){let t=(0,l.getEarliestRateLimitedUntil)(i);if(t)return s.warn("AUTH",`${e} | all ${i.length} accounts rate limited (${(0,l.formatRetryAfter)(t)})`),{allRateLimited:!0,retryAfter:t,retryAfterHuman:(0,l.formatRetryAfter)(t)};s.warn("AUTH",`${e} | ${i.length} accounts found but none active`),i.forEach(e=>{s.debug("AUTH",` → ${e.id?.slice(0,8)} | isActive=${e.isActive} | rateLimitedUntil=${e.rateLimitedUntil||"none"} | testStatus=${e.testStatus}`)})}return s.warn("AUTH",`No credentials for ${e}`),null}let v=T.filter(e=>!(r&&e.id===r||(0,l.isAccountUnavailable)(e.rateLimitedUntil)));if(s.debug("AUTH",`${e} | available: ${v.length}/${T.length}`),T.forEach(e=>{let t=r&&e.id===r,i=(0,l.isAccountUnavailable)(e.rateLimitedUntil);(t||i)&&s.debug("AUTH",` → ${e.id?.slice(0,8)} | ${t?"excluded":""} ${i?`rateLimited until ${e.rateLimitedUntil}`:""}`)}),0===v.length){let t=(0,l.getEarliestRateLimitedUntil)(T);if(t){let r=T.filter(e=>e.rateLimitedUntil&&new Date(e.rateLimitedUntil).getTime()>Date.now()).sort((e,t)=>new Date(e.rateLimitedUntil||0).getTime()-new Date(t.rateLimitedUntil||0).getTime())[0];return s.warn("AUTH",`${e} | all ${T.length} active accounts rate limited (${(0,l.formatRetryAfter)(t)}) | lastErrorCode=${r?.errorCode}, lastError=${r?.lastError?.slice(0,50)}`),{allRateLimited:!0,retryAfter:t,retryAfterHuman:(0,l.formatRetryAfter)(t),lastError:r?.lastError||null,lastErrorCode:r?.errorCode||null}}return s.warn("AUTH",`${e} | all ${T.length} accounts unavailable`),null}let S=v,b=[];if(S=v.filter(t=>{let r=function(e,t){let r=function(e,t){let r=d(t.limitPolicy),i=(Array.isArray(r.windows)?r.windows:[]).map(h).filter(Boolean);if("codex"===e){var n,l;let e,o,a,s=(n=i,l=t,o=(e=d(l.codexLimitPolicy),{use5h:p(e.use5h,!0),useWeekly:p(e.useWeekly,!0)}),a=(a=[...n.map(y).filter(Boolean)]).filter(e=>"session"===e?o.use5h:"weekly"!==e||o.useWeekly),o.use5h&&a.push("session"),o.useWeekly&&a.push("weekly"),[...new Set(a)]);return{enabled:p(r.enabled,s.length>0),thresholdPercent:m(r.thresholdPercent),windows:s}}return{enabled:p(r.enabled,!1),thresholdPercent:m(r.thresholdPercent),windows:i}}(e,t.providerSpecificData);if(!r.enabled||0===r.windows.length)return{blocked:!1,reasons:[],resetAt:null};let i=[],l=[];for(let e of r.windows){let o=(0,n.getQuotaWindowStatus)(t.id,e,r.thresholdPercent);o?.reachedThreshold&&(i.push(`${e} usage ${Math.round(o.usedPercentage)}%`),l.push(o.resetAt))}return{blocked:i.length>0,reasons:i,resetAt:U(l)}}(e,t);return!r.blocked||(b.push({id:t.id,reasons:r.reasons,resetAt:r.resetAt}),!1)}),b.length>0&&s.info("AUTH",`${e} | quota policy filtered ${b.length} account(s): ${b.map(e=>`${e.id.slice(0,8)}(${e.reasons.join(", ")})`).join("; ")}`),0===S.length&&v.length>0){let t=U(b.map(e=>e.resetAt)),r=g(t),i=r?new Date(r).toISOString():new Date(Date.now()+3e5).toISOString();return{allRateLimited:!0,retryAfter:i,retryAfterHuman:(0,l.formatRetryAfter)(i),lastError:`All ${e} accounts reached configured quota threshold`,lastErrorCode:429}}let $=S.filter(e=>!(0,n.isAccountQuotaExhausted)(e.id)),k=S.filter(e=>(0,n.isAccountQuotaExhausted)(e.id)),E=$.length>0?[...$,...k]:S;k.length>0&&s.debug("AUTH",`${e} | quota-aware: ${$.length} with quota, ${k.length} exhausted`);let L=await (0,i.getSettings)(),D=L.fallbackStrategy||"fill-first";if("round-robin"===D){let i=f(L.stickyRoundRobinLimit,3);if(null!==r)a=[...E].sort((e,t)=>{let r=e.backoffLevel||0,i=t.backoffLevel||0;return r!==i?r-i:e.lastUsedAt||t.lastUsedAt?e.lastUsedAt?t.lastUsedAt?new Date(e.lastUsedAt).getTime()-new Date(t.lastUsedAt).getTime():1:-1:(e.priority||999)-(t.priority||999)})[0],s.info("AUTH",`${e} round-robin: FALLBACK MODE - excluded ${r?.slice(0,8)}..., picked LRU ${a.id?.slice(0,8)}...`),await (0,t.updateProviderConnection)(a.id,{lastUsedAt:new Date().toISOString(),consecutiveUseCount:1});else{let r=[...E].sort((e,t)=>e.lastUsedAt||t.lastUsedAt?e.lastUsedAt?t.lastUsedAt?new Date(t.lastUsedAt).getTime()-new Date(e.lastUsedAt).getTime():-1:1:(e.priority||999)-(t.priority||999))[0],n=r?.consecutiveUseCount||0;r&&r.lastUsedAt&&n<i?(a=r,s.debug("AUTH",`${e} round-robin: staying with ${r.id?.slice(0,8)}... (count=${n}/${i})`),await (0,t.updateProviderConnection)(a.id,{lastUsedAt:new Date().toISOString(),consecutiveUseCount:(a.consecutiveUseCount||0)+1})):(a=[...E].sort((e,t)=>{let r=e.backoffLevel||0,i=t.backoffLevel||0;return r!==i?r-i:e.lastUsedAt||t.lastUsedAt?e.lastUsedAt?t.lastUsedAt?new Date(e.lastUsedAt).getTime()-new Date(t.lastUsedAt).getTime():1:-1:(e.priority||999)-(t.priority||999)})[0],s.debug("AUTH",`${e} round-robin: switching to LRU ${a.id?.slice(0,8)}... (current count=${n} >= limit=${i} or no lastUsedAt)`),await (0,t.updateProviderConnection)(a.id,{lastUsedAt:new Date().toISOString(),consecutiveUseCount:1}))}}else if("p2c"===D)if(E.length<=2)a=E[0];else{let e=Math.floor(Math.random()*E.length),t=Math.floor(Math.random()*(E.length-1));t>=e&&t++;let r=E[e],i=E[t],n=(r.consecutiveUseCount||0)+10*!!r.lastError,l=(i.consecutiveUseCount||0)+10*!!i.lastError;a=n<=l?r:i}else if("random"===D){let e=Math.floor(Math.random()*E.length);a=E[e]}else if("least-used"===D)a=[...E].sort((e,t)=>e.lastUsedAt||t.lastUsedAt?e.lastUsedAt?t.lastUsedAt?new Date(e.lastUsedAt).getTime()-new Date(t.lastUsedAt).getTime():1:-1:(e.priority||999)-(t.priority||999))[0];else if("cost-optimized"===D)a=[...E].sort((e,t)=>(e.priority||999)-(t.priority||999))[0];else if("strict-random"===D){let t=E.map(e=>e.id),r=(0,c.getNextFromDeckSync)(`conn:${e}`,t);a=E.find(e=>e.id===r)||E[0]}else a=E[0];return{apiKey:a.apiKey,accessToken:a.accessToken,refreshToken:a.refreshToken,expiresAt:a.tokenExpiresAt||a.expiresAt||null,projectId:a.projectId,copilotToken:"string"==typeof a.providerSpecificData.copilotToken?a.providerSpecificData.copilotToken:null,providerSpecificData:a.providerSpecificData,connectionId:a.id,testStatus:a.testStatus,lastError:a.lastError,lastErrorType:a.lastErrorType,lastErrorSource:a.lastErrorSource,errorCode:a.errorCode,rateLimitedUntil:a.rateLimitedUntil}}finally{a&&a()}}async function S(e,r,i,n=null,c=null){let d,u=T.get(e)||Promise.resolve();T.set(e,new Promise(e=>{d=e}));try{await u;let d=await (0,t.getProviderConnections)({provider:n}),f=(Array.isArray(d)?d:[]).map(A).filter(e=>e.id.length>0).find(t=>t.id===e),p=f?.backoffLevel||0;if(f?.rateLimitedUntil&&new Date(f.rateLimitedUntil).getTime()>Date.now())return s.info("AUTH",`${e.slice(0,8)} already marked unavailable (until ${f.rateLimitedUntil}), skipping duplicate mark`),{shouldFallback:!0,cooldownMs:new Date(f.rateLimitedUntil).getTime()-Date.now()};let{shouldFallback:m,cooldownMs:h,newBackoffLevel:y,reason:g}=(0,l.checkFallbackError)(r,i,p,c,n);if(!m)return{shouldFallback:!1,cooldownMs:0};let U=f?.providerSpecificData?.baseUrl;if((0,o.isLocalProvider)(U)&&404===r&&n&&c){let t=a.COOLDOWN_MS.notFoundLocal;return(0,l.lockModel)(n,e,c,"local_not_found",t),s.info("AUTH",`Local 404 for ${c} — model-only lockout ${t/1e3}s (connection stays active)`),{shouldFallback:!0,cooldownMs:t}}let w=(0,l.getUnavailableUntil)(h),T="string"==typeof i?i.slice(0,100):"Provider error";return await (0,t.updateProviderConnection)(e,{rateLimitedUntil:w,testStatus:"unavailable",lastError:T,errorCode:r,lastErrorAt:new Date().toISOString(),backoffLevel:y??p}),n&&c&&h>0&&(0,l.lockModel)(n,e,c,g||"unknown",h),n&&r&&T&&console.error(`❌ ${n} [${r}]: ${T}`),{shouldFallback:!0,cooldownMs:h}}finally{d&&d(),T.delete(e)}}async function b(e,r){(r.testStatus&&"active"!==r.testStatus||r.lastError||r.rateLimitedUntil||r.errorCode||r.lastErrorType||r.lastErrorSource)&&(await (0,t.updateProviderConnection)(e,{testStatus:"active",lastError:null,lastErrorAt:null,lastErrorType:null,lastErrorSource:null,errorCode:null,rateLimitedUntil:null,backoffLevel:0}),s.info("AUTH",`Account ${e.slice(0,8)} error cleared`))}async function $(e){e?.connectionId&&await b(e.connectionId,e)}function k(e){let t=e.headers.get("Authorization");return t?.startsWith("Bearer ")?t.slice(7):null}async function E(e){return!!e&&await (0,r.validateApiKey)(e)}e.s(["clearAccountError",()=>b,"clearRecoveredProviderState",()=>$,"extractApiKey",()=>k,"getProviderCredentials",()=>v,"isValidApiKey",()=>E,"markAccountUnavailable",()=>S])},478847,e=>{"use strict";var t=e.i(287726);e.i(245272);var r=e.i(125852),i=e.i(362225),n=e.i(719201),l=e.i(16023),o=e.i(706901);async function a(e,a){let s=(0,t.extractApiKey)(e);if(!s)return{apiKey:null,apiKeyInfo:null,rejection:null};let c=null;try{c=await (0,r.getApiKeyMetadata)(s)}catch(e){return o.error("API_POLICY","Failed to fetch API key metadata. Request blocked.",{error:e}),{apiKey:s,apiKeyInfo:null,rejection:(0,n.errorResponse)(l.HTTP_STATUS.SERVICE_UNAVAILABLE,"API key policy unavailable")}}if(!c)return{apiKey:s,apiKeyInfo:null,rejection:null};if(!1===c.isActive)return{apiKey:s,apiKeyInfo:c,rejection:(0,n.errorResponse)(l.HTTP_STATUS.FORBIDDEN,"This API key is disabled")};if(c.accessSchedule&&c.accessSchedule.enabled&&!function(e){let t,r;if(!e.enabled)return!0;let i=new Date;try{t=new Intl.DateTimeFormat("en-US",{timeZone:e.tz,hour:"2-digit",minute:"2-digit",hour12:!1}).format(i)}catch{return!0}let[n,l]=t.replace(/^24:/,"00:").split(":").map(Number),o=60*n+l;try{r=new Intl.DateTimeFormat("en-US",{timeZone:e.tz,weekday:"short"}).format(i)}catch{return!0}let a={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6}[r]??i.getDay();if(!e.days.includes(a))return!1;let[s,c]=e.from.split(":").map(Number),[d,u]=e.until.split(":").map(Number),f=60*s+c,A=60*d+u;return A<f?o>=f||o<A:o>=f&&o<A}(c.accessSchedule)){let{from:e,until:t,tz:r}=c.accessSchedule;return{apiKey:s,apiKeyInfo:c,rejection:(0,n.errorResponse)(l.HTTP_STATUS.FORBIDDEN,`Access denied outside allowed hours (${e}–${t} ${r})`)}}if(a&&c.allowedModels&&c.allowedModels.length>0&&!await (0,r.isModelAllowedForKey)(s,a))return{apiKey:s,apiKeyInfo:c,rejection:(0,n.errorResponse)(l.HTTP_STATUS.FORBIDDEN,`Model "${a}" is not allowed for this API key`)};if(c.id)try{let e=(0,i.checkBudget)(c.id);if(!e.allowed)return{apiKey:s,apiKeyInfo:c,rejection:(0,n.errorResponse)(l.HTTP_STATUS.RATE_LIMITED,e.reason||"Budget limit exceeded")}}catch(e){return o.error("API_POLICY","Budget check failed. Request blocked.",{error:e}),{apiKey:s,apiKeyInfo:c,rejection:(0,n.errorResponse)(l.HTTP_STATUS.SERVICE_UNAVAILABLE,"Budget policy unavailable")}}return{apiKey:s,apiKeyInfo:c,rejection:null}}e.s(["enforceApiKeyPolicy",()=>a])}];
|
|
2
2
|
|
|
3
3
|
//# sourceMappingURL=src_4787afd3._.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module.exports=[918622,(a,b,c)=>{b.exports=a.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},677850,a=>a.a(async(b,c)=>{try{let b=await a.y("zod");a.n(b),c()}catch(a){c(a)}},!0),342602,(a,b,c)=>{"use strict";b.exports=a.r(918622)},187924,(a,b,c)=>{"use strict";b.exports=a.r(342602).vendored["react-ssr"].ReactJsxRuntime},572131,(a,b,c)=>{"use strict";b.exports=a.r(342602).vendored["react-ssr"].React},804730,a=>{a.v({name:"omniroute",version:"2.7.
|
|
1
|
+
module.exports=[918622,(a,b,c)=>{b.exports=a.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},677850,a=>a.a(async(b,c)=>{try{let b=await a.y("zod");a.n(b),c()}catch(a){c(a)}},!0),342602,(a,b,c)=>{"use strict";b.exports=a.r(918622)},187924,(a,b,c)=>{"use strict";b.exports=a.r(342602).vendored["react-ssr"].ReactJsxRuntime},572131,(a,b,c)=>{"use strict";b.exports=a.r(342602).vendored["react-ssr"].React},804730,a=>{a.v({name:"omniroute",version:"2.7.3",description:"Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",type:"module",bin:{omniroute:"bin/omniroute.mjs","omniroute-reset-password":"bin/reset-password.mjs"},files:["bin/","app/","open-sse/mcp-server/","src/shared/contracts/","scripts/postinstall.mjs","scripts/native-binary-compat.mjs","README.md","LICENSE"],workspaces:["open-sse"],engines:{node:">=18.0.0 <24.0.0"},keywords:["ai","router","proxy","openai","claude","anthropic","gemini","fallback","cursor","cline","codex","llm","auto-fallback"],license:"MIT",author:"diegosouzapw",repository:{type:"git",url:"https://github.com/diegosouzapw/OmniRoute"},homepage:"https://omniroute.online",scripts:{dev:"node scripts/run-next.mjs dev",build:"next build","build:cli":"node scripts/prepublish.mjs",start:"node scripts/run-next.mjs start",lint:"eslint .","electron:dev":'concurrently "npm run dev" "wait-on http://localhost:20128 && cd electron && npm run dev"',"electron:build":"npm run build && cd electron && npm run build","electron:build:win":"npm run build && cd electron && npm run build:win","electron:build:mac":"npm run build && cd electron && npm run build:mac","electron:build:linux":"npm run build && cd electron && npm run build:linux",test:"node --import tsx/esm --test tests/unit/*.test.mjs","test:unit":"node --import tsx/esm --test tests/unit/*.test.mjs","test:plan3":"node --import tsx/esm --test tests/unit/plan3-p0.test.mjs","test:fixes":"node --import tsx/esm --test tests/unit/fixes-p1.test.mjs","test:security":"node --import tsx/esm --test tests/unit/security-fase01.test.mjs","check:cycles":"node scripts/check-cycles.mjs","check:route-validation:t06":"node scripts/check-route-validation.mjs","check:any-budget:t11":"node scripts/check-t11-any-budget.mjs","check:docs-sync":"node scripts/check-docs-sync.mjs","typecheck:core":"tsc --pretty false -p tsconfig.typecheck-core.json","typecheck:noimplicit:core":"tsc --pretty false -p tsconfig.typecheck-noimplicit-core.json","test:integration":"node --import tsx/esm --test tests/integration/*.test.mjs","test:e2e":"node scripts/run-playwright-tests.mjs test tests/e2e/*.spec.ts","test:protocols:e2e":"node scripts/run-protocol-clients-tests.mjs","test:vitest":"vitest run open-sse/mcp-server/__tests__/*.test.ts open-sse/services/autoCombo/__tests__/*.test.ts","test:ecosystem":"node scripts/run-ecosystem-tests.mjs","test:coverage":"npx c8 --exclude=open-sse --check-coverage --lines 50 --functions 50 --branches 50 node --import tsx/esm --test tests/unit/*.test.mjs","test:all":"npm run test:unit && npm run test:vitest && npm run test:ecosystem && npm run test:e2e",check:"npm run lint && npm run test",prepublishOnly:"npm run build:cli",postinstall:"node scripts/postinstall.mjs",prepare:"husky","system-info":"node scripts/system-info.mjs"},dependencies:{"@modelcontextprotocol/sdk":"^1.27.1","@monaco-editor/react":"^4.7.0",bcryptjs:"^3.0.3","better-sqlite3":"^12.6.2",bottleneck:"^2.19.5",dompurify:"^3.3.2",express:"^5.2.1","fetch-socks":"^1.3.2","http-proxy-middleware":"^3.0.5","https-proxy-agent":"^8.0.0",jose:"^6.1.3",lowdb:"^7.0.1","monaco-editor":"^0.55.1",next:"^16.1.6","next-intl":"^4.8.3","node-machine-id":"^1.1.12",open:"^11.0.0",ora:"^9.1.0",pino:"^10.3.1","pino-pretty":"^13.1.3",react:"19.2.4","react-dom":"19.2.4",recharts:"^3.7.0",selfsigned:"^5.5.0",tsx:"^4.21.0",undici:"^7.19.2",uuid:"^13.0.0","wreq-js":"^2.0.1",zod:"^4.3.6",zustand:"^5.0.10","@swc/helpers":"0.5.19"},devDependencies:{"@playwright/test":"^1.58.2","@tailwindcss/postcss":"^4.1.18","@types/bcryptjs":"^3.0.0","@types/better-sqlite3":"^7.6.13","@types/node":"^25.2.3","@types/react":"^19.2.14","@types/react-dom":"^19.2.3",concurrently:"^9.2.1","cross-env":"^10.1.0",eslint:"^9.39.2","eslint-config-next":"16.1.6",husky:"^9.1.7","lint-staged":"^16.2.7",prettier:"^3.8.1",tailwindcss:"^4",typescript:"^5.9.3","typescript-eslint":"^8.56.0",vitest:"^4.0.18","wait-on":"^9.0.4"},"lint-staged":{"*.{js,jsx,ts,tsx,mjs}":["prettier --write","eslint --fix --no-error-on-unmatched-pattern"],"*.{json,md,yml,yaml,css}":["prettier --write"]},pnpm:{onlyBuiltDependencies:["@parcel/watcher","@swc/core","better-sqlite3","esbuild","omniroute","sharp"]}})},588788,a=>{"use strict";var b=a.i(32886),c=a.i(187924);function d({locale:a,...d}){if(!a)throw Error(void 0);return(0,c.jsx)(b.IntlProvider,{locale:a,...d})}a.s(["default",()=>d])}];
|
|
2
2
|
|
|
3
3
|
//# sourceMappingURL=%5Broot-of-the-server%5D__9affb65e._.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module.exports=[193695,(a,b,c)=>{b.exports=a.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},677850,a=>a.a(async(b,c)=>{try{let b=await a.y("zod");a.n(b),c()}catch(a){c(a)}},!0),804730,a=>{a.v({name:"omniroute",version:"2.7.
|
|
1
|
+
module.exports=[193695,(a,b,c)=>{b.exports=a.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},677850,a=>a.a(async(b,c)=>{try{let b=await a.y("zod");a.n(b),c()}catch(a){c(a)}},!0),804730,a=>{a.v({name:"omniroute",version:"2.7.3",description:"Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",type:"module",bin:{omniroute:"bin/omniroute.mjs","omniroute-reset-password":"bin/reset-password.mjs"},files:["bin/","app/","open-sse/mcp-server/","src/shared/contracts/","scripts/postinstall.mjs","scripts/native-binary-compat.mjs","README.md","LICENSE"],workspaces:["open-sse"],engines:{node:">=18.0.0 <24.0.0"},keywords:["ai","router","proxy","openai","claude","anthropic","gemini","fallback","cursor","cline","codex","llm","auto-fallback"],license:"MIT",author:"diegosouzapw",repository:{type:"git",url:"https://github.com/diegosouzapw/OmniRoute"},homepage:"https://omniroute.online",scripts:{dev:"node scripts/run-next.mjs dev",build:"next build","build:cli":"node scripts/prepublish.mjs",start:"node scripts/run-next.mjs start",lint:"eslint .","electron:dev":'concurrently "npm run dev" "wait-on http://localhost:20128 && cd electron && npm run dev"',"electron:build":"npm run build && cd electron && npm run build","electron:build:win":"npm run build && cd electron && npm run build:win","electron:build:mac":"npm run build && cd electron && npm run build:mac","electron:build:linux":"npm run build && cd electron && npm run build:linux",test:"node --import tsx/esm --test tests/unit/*.test.mjs","test:unit":"node --import tsx/esm --test tests/unit/*.test.mjs","test:plan3":"node --import tsx/esm --test tests/unit/plan3-p0.test.mjs","test:fixes":"node --import tsx/esm --test tests/unit/fixes-p1.test.mjs","test:security":"node --import tsx/esm --test tests/unit/security-fase01.test.mjs","check:cycles":"node scripts/check-cycles.mjs","check:route-validation:t06":"node scripts/check-route-validation.mjs","check:any-budget:t11":"node scripts/check-t11-any-budget.mjs","check:docs-sync":"node scripts/check-docs-sync.mjs","typecheck:core":"tsc --pretty false -p tsconfig.typecheck-core.json","typecheck:noimplicit:core":"tsc --pretty false -p tsconfig.typecheck-noimplicit-core.json","test:integration":"node --import tsx/esm --test tests/integration/*.test.mjs","test:e2e":"node scripts/run-playwright-tests.mjs test tests/e2e/*.spec.ts","test:protocols:e2e":"node scripts/run-protocol-clients-tests.mjs","test:vitest":"vitest run open-sse/mcp-server/__tests__/*.test.ts open-sse/services/autoCombo/__tests__/*.test.ts","test:ecosystem":"node scripts/run-ecosystem-tests.mjs","test:coverage":"npx c8 --exclude=open-sse --check-coverage --lines 50 --functions 50 --branches 50 node --import tsx/esm --test tests/unit/*.test.mjs","test:all":"npm run test:unit && npm run test:vitest && npm run test:ecosystem && npm run test:e2e",check:"npm run lint && npm run test",prepublishOnly:"npm run build:cli",postinstall:"node scripts/postinstall.mjs",prepare:"husky","system-info":"node scripts/system-info.mjs"},dependencies:{"@modelcontextprotocol/sdk":"^1.27.1","@monaco-editor/react":"^4.7.0",bcryptjs:"^3.0.3","better-sqlite3":"^12.6.2",bottleneck:"^2.19.5",dompurify:"^3.3.2",express:"^5.2.1","fetch-socks":"^1.3.2","http-proxy-middleware":"^3.0.5","https-proxy-agent":"^8.0.0",jose:"^6.1.3",lowdb:"^7.0.1","monaco-editor":"^0.55.1",next:"^16.1.6","next-intl":"^4.8.3","node-machine-id":"^1.1.12",open:"^11.0.0",ora:"^9.1.0",pino:"^10.3.1","pino-pretty":"^13.1.3",react:"19.2.4","react-dom":"19.2.4",recharts:"^3.7.0",selfsigned:"^5.5.0",tsx:"^4.21.0",undici:"^7.19.2",uuid:"^13.0.0","wreq-js":"^2.0.1",zod:"^4.3.6",zustand:"^5.0.10","@swc/helpers":"0.5.19"},devDependencies:{"@playwright/test":"^1.58.2","@tailwindcss/postcss":"^4.1.18","@types/bcryptjs":"^3.0.0","@types/better-sqlite3":"^7.6.13","@types/node":"^25.2.3","@types/react":"^19.2.14","@types/react-dom":"^19.2.3",concurrently:"^9.2.1","cross-env":"^10.1.0",eslint:"^9.39.2","eslint-config-next":"16.1.6",husky:"^9.1.7","lint-staged":"^16.2.7",prettier:"^3.8.1",tailwindcss:"^4",typescript:"^5.9.3","typescript-eslint":"^8.56.0",vitest:"^4.0.18","wait-on":"^9.0.4"},"lint-staged":{"*.{js,jsx,ts,tsx,mjs}":["prettier --write","eslint --fix --no-error-on-unmatched-pattern"],"*.{json,md,yml,yaml,css}":["prettier --write"]},pnpm:{onlyBuiltDependencies:["@parcel/watcher","@swc/core","better-sqlite3","esbuild","omniroute","sharp"]}})},569264,a=>{a.n(a.i(354832))},650645,a=>{a.n(a.i(827572))},923576,a=>{a.n(a.i(104858))},825210,a=>{a.n(a.i(402747))},517537,a=>{a.n(a.i(903363))},13718,a=>{a.n(a.i(685523))},118198,a=>{a.n(a.i(545518))},296736,(a,b,c)=>{"use strict";function d(a){if("function"!=typeof WeakMap)return null;var b=new WeakMap,c=new WeakMap;return(d=function(a){return a?c:b})(a)}c._=function(a,b){if(!b&&a&&a.__esModule)return a;if(null===a||"object"!=typeof a&&"function"!=typeof a)return{default:a};var c=d(b);if(c&&c.has(a))return c.get(a);var e={__proto__:null},f=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var g in a)if("default"!==g&&Object.prototype.hasOwnProperty.call(a,g)){var h=f?Object.getOwnPropertyDescriptor(a,g):null;h&&(h.get||h.set)?Object.defineProperty(e,g,h):e[g]=a[g]}return e.default=a,c&&c.set(a,e),e}},500790,(a,b,c)=>{let{createClientModuleProxy:d}=a.r(211857);a.n(d("[project]/node_modules/next/dist/client/app-dir/link.js <module evaluation>"))},784707,(a,b,c)=>{let{createClientModuleProxy:d}=a.r(211857);a.n(d("[project]/node_modules/next/dist/client/app-dir/link.js"))},297647,a=>{"use strict";a.i(500790);var b=a.i(784707);a.n(b)},395936,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={default:function(){return i},useLinkStatus:function(){return h.useLinkStatus}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(296736),g=a.r(907997),h=f._(a.r(297647));function i(a){let b=a.legacyBehavior,c="string"==typeof a.children||"number"==typeof a.children||"string"==typeof a.children?.type,d=a.children?.type?.$$typeof===Symbol.for("react.client.reference");return!b||c||d||(a.children?.type?.$$typeof===Symbol.for("react.lazy")?console.error("Using a Lazy Component as a direct child of `<Link legacyBehavior>` from a Server Component is not supported. If you need legacyBehavior, wrap your Lazy Component in a Client Component that renders the Link's `<a>` tag."):console.error("Using a Server Component as a direct child of `<Link legacyBehavior>` is not supported. If you need legacyBehavior, wrap your Server Component in a Client Component that renders the Link's `<a>` tag.")),(0,g.jsx)(h.default,{...a})}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},330878,a=>{"use strict";var b=a.i(800717),c=a.i(118845),d=a.i(40953),e=(0,b.cache)(function(a,b){return function({_cache:a=(0,c.b)(),_formatters:b=(0,c.c)(a),getMessageFallback:e=d.d,messages:f,namespace:g,onError:h=d.b,...i}){return function({messages:a,namespace:b,...c},e){return a=a["!"],b=(0,d.r)(b,"!"),(0,d.a)({...c,messages:a,namespace:b})}({...i,onError:h,cache:a,formatters:b,getMessageFallback:e,messages:{"!":f},namespace:g?`!.${g}`:"!"},0)}({...a,namespace:b})});a.s(["default",()=>e],330878)},442979,a=>{"use strict";var b=a.i(330878),c=a.i(767228),d=a.i(800717)["use".trim()];function e(...[a]){let f=function(a){var b=(0,c.default)();try{return d(b)}catch(b){throw b instanceof TypeError&&b.message.includes("Cannot read properties of null (reading 'use')")?Error(`\`${a}\` is not callable within an async component. Please refer to https://next-intl.dev/docs/environments/server-client-components#async-components`,{cause:b}):b}}("useTranslations");return(0,b.default)(f,a)}a.s(["useTranslations",()=>e],442979)}];
|
|
2
2
|
|
|
3
3
|
//# sourceMappingURL=%5Broot-of-the-server%5D__a6942102._.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
2
|
-
@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">500</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">Internal Server Error.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/e22b90cf374c3818.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[339756,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"default\"]\n3:I[837457,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"default\"]\n4:I[897367,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n7:I[897367,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"ViewportBoundary\"]\n9:I[897367,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"MetadataBoundary\"]\nb:I[168027,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"default\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"
|
|
1
|
+
<!DOCTYPE html><!--TaE7xCUJ3vzE5oXXL5DhE--><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/e22b90cf374c3818.js"/><script src="/_next/static/chunks/2ba176114bbe6b2f.js" async=""></script><script src="/_next/static/chunks/b133d1854532ff8c.js" async=""></script><script src="/_next/static/chunks/726579f2940c2a2f.js" async=""></script><script src="/_next/static/chunks/956d411224e8600a.js" async=""></script><script src="/_next/static/chunks/turbopack-cce160b74a108c3f.js" async=""></script><script src="/_next/static/chunks/d96012bcfc98706a.js" async=""></script><script src="/_next/static/chunks/16ea27c3b926bc31.js" async=""></script><meta name="next-size-adjust" content=""/><title>500: Internal Server Error.</title><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}
|
|
2
|
+
@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">500</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">Internal Server Error.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/e22b90cf374c3818.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[339756,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"default\"]\n3:I[837457,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"default\"]\n4:I[897367,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n7:I[897367,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"ViewportBoundary\"]\n9:I[897367,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"MetadataBoundary\"]\nb:I[168027,[\"/_next/static/chunks/d96012bcfc98706a.js\",\"/_next/static/chunks/16ea27c3b926bc31.js\"],\"default\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"TaE7xCUJ3vzE5oXXL5DhE\",\"c\":[\"\",\"_global-error\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]}],[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"html\",null,{\"id\":\"__next_error__\",\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"title\",null,{\"children\":\"500: Internal Server Error.\"}]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"style\":{\"lineHeight\":\"48px\"},\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}\\n@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"paddingRight\":23,\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\"},\"children\":\"500\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"28px\"},\"children\":\"Internal Server Error.\"}]}]]}]}]}]]}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/d96012bcfc98706a.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/16ea27c3b926bc31.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L7\",null,{\"children\":\"$L8\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$La\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$b\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"8:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"6:null\na:[]\n"])</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
self.__RSC_SERVER_MANIFEST="{\n \"node\": {},\n \"edge\": {},\n \"encryptionKey\": \"
|
|
1
|
+
self.__RSC_SERVER_MANIFEST="{\n \"node\": {},\n \"edge\": {},\n \"encryptionKey\": \"ibM0I8aNYJ2QdSke9mv7/Lb8RwNJNtXTsIFfUKVxVws=\"\n}"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,804730,t=>{t.v({name:"omniroute",version:"2.7.
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,804730,t=>{t.v({name:"omniroute",version:"2.7.3",description:"Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",type:"module",bin:{omniroute:"bin/omniroute.mjs","omniroute-reset-password":"bin/reset-password.mjs"},files:["bin/","app/","open-sse/mcp-server/","src/shared/contracts/","scripts/postinstall.mjs","scripts/native-binary-compat.mjs","README.md","LICENSE"],workspaces:["open-sse"],engines:{node:">=18.0.0 <24.0.0"},keywords:["ai","router","proxy","openai","claude","anthropic","gemini","fallback","cursor","cline","codex","llm","auto-fallback"],license:"MIT",author:"diegosouzapw",repository:{type:"git",url:"https://github.com/diegosouzapw/OmniRoute"},homepage:"https://omniroute.online",scripts:{dev:"node scripts/run-next.mjs dev",build:"next build","build:cli":"node scripts/prepublish.mjs",start:"node scripts/run-next.mjs start",lint:"eslint .","electron:dev":'concurrently "npm run dev" "wait-on http://localhost:20128 && cd electron && npm run dev"',"electron:build":"npm run build && cd electron && npm run build","electron:build:win":"npm run build && cd electron && npm run build:win","electron:build:mac":"npm run build && cd electron && npm run build:mac","electron:build:linux":"npm run build && cd electron && npm run build:linux",test:"node --import tsx/esm --test tests/unit/*.test.mjs","test:unit":"node --import tsx/esm --test tests/unit/*.test.mjs","test:plan3":"node --import tsx/esm --test tests/unit/plan3-p0.test.mjs","test:fixes":"node --import tsx/esm --test tests/unit/fixes-p1.test.mjs","test:security":"node --import tsx/esm --test tests/unit/security-fase01.test.mjs","check:cycles":"node scripts/check-cycles.mjs","check:route-validation:t06":"node scripts/check-route-validation.mjs","check:any-budget:t11":"node scripts/check-t11-any-budget.mjs","check:docs-sync":"node scripts/check-docs-sync.mjs","typecheck:core":"tsc --pretty false -p tsconfig.typecheck-core.json","typecheck:noimplicit:core":"tsc --pretty false -p tsconfig.typecheck-noimplicit-core.json","test:integration":"node --import tsx/esm --test tests/integration/*.test.mjs","test:e2e":"node scripts/run-playwright-tests.mjs test tests/e2e/*.spec.ts","test:protocols:e2e":"node scripts/run-protocol-clients-tests.mjs","test:vitest":"vitest run open-sse/mcp-server/__tests__/*.test.ts open-sse/services/autoCombo/__tests__/*.test.ts","test:ecosystem":"node scripts/run-ecosystem-tests.mjs","test:coverage":"npx c8 --exclude=open-sse --check-coverage --lines 50 --functions 50 --branches 50 node --import tsx/esm --test tests/unit/*.test.mjs","test:all":"npm run test:unit && npm run test:vitest && npm run test:ecosystem && npm run test:e2e",check:"npm run lint && npm run test",prepublishOnly:"npm run build:cli",postinstall:"node scripts/postinstall.mjs",prepare:"husky","system-info":"node scripts/system-info.mjs"},dependencies:{"@modelcontextprotocol/sdk":"^1.27.1","@monaco-editor/react":"^4.7.0",bcryptjs:"^3.0.3","better-sqlite3":"^12.6.2",bottleneck:"^2.19.5",dompurify:"^3.3.2",express:"^5.2.1","fetch-socks":"^1.3.2","http-proxy-middleware":"^3.0.5","https-proxy-agent":"^8.0.0",jose:"^6.1.3",lowdb:"^7.0.1","monaco-editor":"^0.55.1",next:"^16.1.6","next-intl":"^4.8.3","node-machine-id":"^1.1.12",open:"^11.0.0",ora:"^9.1.0",pino:"^10.3.1","pino-pretty":"^13.1.3",react:"19.2.4","react-dom":"19.2.4",recharts:"^3.7.0",selfsigned:"^5.5.0",tsx:"^4.21.0",undici:"^7.19.2",uuid:"^13.0.0","wreq-js":"^2.0.1",zod:"^4.3.6",zustand:"^5.0.10","@swc/helpers":"0.5.19"},devDependencies:{"@playwright/test":"^1.58.2","@tailwindcss/postcss":"^4.1.18","@types/bcryptjs":"^3.0.0","@types/better-sqlite3":"^7.6.13","@types/node":"^25.2.3","@types/react":"^19.2.14","@types/react-dom":"^19.2.3",concurrently:"^9.2.1","cross-env":"^10.1.0",eslint:"^9.39.2","eslint-config-next":"16.1.6",husky:"^9.1.7","lint-staged":"^16.2.7",prettier:"^3.8.1",tailwindcss:"^4",typescript:"^5.9.3","typescript-eslint":"^8.56.0",vitest:"^4.0.18","wait-on":"^9.0.4"},"lint-staged":{"*.{js,jsx,ts,tsx,mjs}":["prettier --write","eslint --fix --no-error-on-unmatched-pattern"],"*.{json,md,yml,yaml,css}":["prettier --write"]},pnpm:{onlyBuiltDependencies:["@parcel/watcher","@swc/core","better-sqlite3","esbuild","omniroute","sharp"]}})},175696,t=>{"use strict";var e=t.i(861745),s=t.i(843476);function n({locale:t,...n}){if(!t)throw Error(void 0);return(0,s.jsx)(e.IntlProvider,{locale:t,...n})}t.s(["default",()=>n])}]);
|
package/app/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [2.7.3] — 2026-03-18
|
|
8
|
+
|
|
9
|
+
> Sprint: Codex direct API quota fallback fix.
|
|
10
|
+
|
|
11
|
+
### 🐛 Bug Fixes
|
|
12
|
+
|
|
13
|
+
- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)
|
|
14
|
+
- `resolveQuotaWindow()` prefix matching: `"weekly"` now matches `"weekly (7d)"` cache keys
|
|
15
|
+
- `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly
|
|
16
|
+
- 4 new regression tests (766 total)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
7
20
|
## [2.7.2] — 2026-03-18
|
|
8
21
|
|
|
9
22
|
> Sprint: Light mode UI contrast fixes.
|
package/app/docs/openapi.yaml
CHANGED
package/app/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omniroute",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omniroute",
|
|
9
|
-
"version": "2.7.
|
|
9
|
+
"version": "2.7.3",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"workspaces": [
|
package/app/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omniroute",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.3",
|
|
4
4
|
"description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -101,6 +101,45 @@ function clampPercent(value: number): number {
|
|
|
101
101
|
return Math.max(0, Math.min(100, value));
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
function normalizeWindowKey(value: unknown): string {
|
|
105
|
+
if (typeof value !== "string") return "";
|
|
106
|
+
return value
|
|
107
|
+
.toLowerCase()
|
|
108
|
+
.replace(/[^a-z0-9]+/g, " ")
|
|
109
|
+
.trim();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function resolveQuotaWindow(
|
|
113
|
+
quotas: Record<string, QuotaInfo>,
|
|
114
|
+
windowName: string
|
|
115
|
+
): QuotaInfo | null {
|
|
116
|
+
const direct = quotas[windowName];
|
|
117
|
+
if (direct) return direct;
|
|
118
|
+
|
|
119
|
+
const normalizedTarget = normalizeWindowKey(windowName);
|
|
120
|
+
if (!normalizedTarget) return null;
|
|
121
|
+
|
|
122
|
+
const prefixMatches: Array<{ key: string; quota: QuotaInfo }> = [];
|
|
123
|
+
for (const [key, quota] of Object.entries(quotas)) {
|
|
124
|
+
const normalizedKey = normalizeWindowKey(key);
|
|
125
|
+
if (!normalizedKey) continue;
|
|
126
|
+
if (normalizedKey === normalizedTarget) return quota;
|
|
127
|
+
// Support canonical selection of generic windows from labeled windows,
|
|
128
|
+
// e.g. "weekly" from "weekly (7d)" or "session" from "session (5h)".
|
|
129
|
+
if (normalizedKey.startsWith(`${normalizedTarget} `)) {
|
|
130
|
+
prefixMatches.push({ key, quota });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Deterministic fallback: choose the lexicographically first matching key.
|
|
135
|
+
if (prefixMatches.length > 0) {
|
|
136
|
+
prefixMatches.sort((a, b) => a.key.localeCompare(b.key));
|
|
137
|
+
return prefixMatches[0].quota;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
|
|
104
143
|
function earliestResetAt(quotas: Record<string, QuotaInfo>): string | null {
|
|
105
144
|
let earliest: string | null = null;
|
|
106
145
|
let earliestMs = Infinity;
|
|
@@ -201,7 +240,7 @@ export function getQuotaWindowStatus(
|
|
|
201
240
|
|
|
202
241
|
const now = Date.now();
|
|
203
242
|
|
|
204
|
-
const window = entry.quotas
|
|
243
|
+
const window = resolveQuotaWindow(entry.quotas, windowName);
|
|
205
244
|
if (!window) return null;
|
|
206
245
|
|
|
207
246
|
const remainingPercentage = clampPercent(window.remainingPercentage);
|
|
@@ -132,12 +132,38 @@ function normalizeWindowName(windowName: unknown): string | null {
|
|
|
132
132
|
return normalized.length > 0 ? normalized : null;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
function
|
|
135
|
+
function uniqueWindows(windows: string[]): string[] {
|
|
136
|
+
return [...new Set(windows)];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function normalizeCodexWindowName(windowName: unknown): string | null {
|
|
140
|
+
if (typeof windowName !== "string") return null;
|
|
141
|
+
const normalized = windowName.trim().toLowerCase();
|
|
142
|
+
if (normalized === "session (5h)" || normalized === "5h" || normalized === "five_hour") {
|
|
143
|
+
return "session";
|
|
144
|
+
}
|
|
145
|
+
if (normalized === "weekly (7d)" || normalized === "7d" || normalized === "seven_day") {
|
|
146
|
+
return "weekly";
|
|
147
|
+
}
|
|
148
|
+
return normalized;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function applyCodexWindowPolicy(rawWindows: string[], providerSpecificData: JsonRecord): string[] {
|
|
136
152
|
const codexPolicy = getCodexLimitPolicy(providerSpecificData);
|
|
137
|
-
const
|
|
153
|
+
const normalizedRaw = rawWindows.map(normalizeCodexWindowName).filter(Boolean) as string[];
|
|
154
|
+
|
|
155
|
+
// Preserve explicitly configured custom windows, but enforce canonical Codex windows
|
|
156
|
+
// from toggles so weekly exhaustion is never skipped when useWeekly=true.
|
|
157
|
+
let windows = [...normalizedRaw];
|
|
158
|
+
windows = windows.filter((windowName) => {
|
|
159
|
+
if (windowName === "session") return codexPolicy.use5h;
|
|
160
|
+
if (windowName === "weekly") return codexPolicy.useWeekly;
|
|
161
|
+
return true;
|
|
162
|
+
});
|
|
138
163
|
if (codexPolicy.use5h) windows.push("session");
|
|
139
164
|
if (codexPolicy.useWeekly) windows.push("weekly");
|
|
140
|
-
|
|
165
|
+
|
|
166
|
+
return uniqueWindows(windows);
|
|
141
167
|
}
|
|
142
168
|
|
|
143
169
|
export function resolveQuotaLimitPolicy(
|
|
@@ -149,8 +175,7 @@ export function resolveQuotaLimitPolicy(
|
|
|
149
175
|
const windows = rawWindows.map(normalizeWindowName).filter(Boolean) as string[];
|
|
150
176
|
|
|
151
177
|
if (provider === "codex") {
|
|
152
|
-
const
|
|
153
|
-
const defaultWindows = windows.length > 0 ? windows : fallbackWindows;
|
|
178
|
+
const defaultWindows = applyCodexWindowPolicy(windows, providerSpecificData);
|
|
154
179
|
const enabled = toBooleanOrDefault(rawPolicy.enabled, defaultWindows.length > 0);
|
|
155
180
|
|
|
156
181
|
return {
|
|
@@ -21,6 +21,26 @@ test("resolveQuotaLimitPolicy keeps codex legacy defaults when generic policy is
|
|
|
21
21
|
assert.equal(policy.thresholdPercent, 90);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
+
test("resolveQuotaLimitPolicy enforces codex weekly window when weekly toggle is enabled", () => {
|
|
25
|
+
const policy = auth.resolveQuotaLimitPolicy("codex", {
|
|
26
|
+
codexLimitPolicy: { use5h: true, useWeekly: true },
|
|
27
|
+
limitPolicy: { enabled: true, windows: ["session"] },
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
assert.equal(policy.enabled, true);
|
|
31
|
+
assert.deepEqual(policy.windows.sort(), ["session", "weekly"]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("resolveQuotaLimitPolicy removes codex weekly window when weekly toggle is disabled", () => {
|
|
35
|
+
const policy = auth.resolveQuotaLimitPolicy("codex", {
|
|
36
|
+
codexLimitPolicy: { use5h: true, useWeekly: false },
|
|
37
|
+
limitPolicy: { enabled: true, windows: ["session", "weekly"] },
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
assert.equal(policy.enabled, true);
|
|
41
|
+
assert.deepEqual(policy.windows, ["session"]);
|
|
42
|
+
});
|
|
43
|
+
|
|
24
44
|
test("resolveQuotaLimitPolicy disables non-codex policy by default", () => {
|
|
25
45
|
const policy = auth.resolveQuotaLimitPolicy("openai", {});
|
|
26
46
|
assert.equal(policy.enabled, false);
|
|
@@ -60,6 +80,26 @@ test("evaluateQuotaLimitPolicy blocks when configured window reaches threshold",
|
|
|
60
80
|
assert.equal(result.resetAt, resetAt);
|
|
61
81
|
});
|
|
62
82
|
|
|
83
|
+
test("evaluateQuotaLimitPolicy matches canonical weekly window against labeled cache keys", () => {
|
|
84
|
+
const resetAt = new Date(Date.now() + 60_000).toISOString();
|
|
85
|
+
quotaCache.setQuotaCache("conn-policy-weekly-label", "codex", {
|
|
86
|
+
"weekly (7d)": { remainingPercentage: 0, resetAt },
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const result = auth.evaluateQuotaLimitPolicy(
|
|
90
|
+
"codex",
|
|
91
|
+
buildConnection("conn-policy-weekly-label", {
|
|
92
|
+
codexLimitPolicy: { use5h: true, useWeekly: true },
|
|
93
|
+
limitPolicy: { enabled: true, windows: ["weekly"] },
|
|
94
|
+
})
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
assert.equal(result.blocked, true);
|
|
98
|
+
assert.equal(result.reasons.length, 1);
|
|
99
|
+
assert.match(result.reasons[0], /weekly usage/i);
|
|
100
|
+
assert.equal(result.resetAt, resetAt);
|
|
101
|
+
});
|
|
102
|
+
|
|
63
103
|
test("evaluateQuotaLimitPolicy does not block when no quota data exists", () => {
|
|
64
104
|
const result = auth.evaluateQuotaLimitPolicy(
|
|
65
105
|
"openai",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omniroute",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.3",
|
|
4
4
|
"description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|