omniroute 2.7.1 → 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 +2 -2
- 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/chunks/ssr/_5a9cd299._.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/{7db919b3e9b8f72c.js → 1d4f94c2f5112482.js} +1 -1
- package/app/.next/static/chunks/201cb349d9cc400f.css +1 -0
- package/app/.next/static/chunks/{4b1344f456abe7c3.js → 5609e4cc1aa751bb.js} +1 -1
- package/app/CHANGELOG.md +25 -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/shared/components/RequestLoggerV2.tsx +5 -5
- 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/chunks/85b7200badb8af05.css +0 -1
- /package/app/.next/static/{kvAWBEqvRUAvBVH0wpZhX → TaE7xCUJ3vzE5oXXL5DhE}/_buildManifest.js +0 -0
- /package/app/.next/static/{kvAWBEqvRUAvBVH0wpZhX → TaE7xCUJ3vzE5oXXL5DhE}/_clientMiddlewareManifest.json +0 -0
- /package/app/.next/static/{kvAWBEqvRUAvBVH0wpZhX → TaE7xCUJ3vzE5oXXL5DhE}/_ssgManifest.js +0 -0
package/app/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,31 @@
|
|
|
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
|
+
|
|
20
|
+
## [2.7.2] — 2026-03-18
|
|
21
|
+
|
|
22
|
+
> Sprint: Light mode UI contrast fixes.
|
|
23
|
+
|
|
24
|
+
### 🐛 Bug Fixes
|
|
25
|
+
|
|
26
|
+
- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)
|
|
27
|
+
- Error/Success/Combo filter buttons now readable in light mode
|
|
28
|
+
- Combo row badge uses stronger violet in light mode
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
7
32
|
## [2.7.1] — 2026-03-17
|
|
8
33
|
|
|
9
34
|
> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).
|
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);
|
|
@@ -258,7 +258,7 @@ export default function RequestLoggerV2() {
|
|
|
258
258
|
onClick={() => setRecording(!recording)}
|
|
259
259
|
className={`flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-medium border transition-colors ${
|
|
260
260
|
recording
|
|
261
|
-
? "bg-red-500/10 border-red-500/30 text-red-400"
|
|
261
|
+
? "bg-red-500/10 border-red-500/30 text-red-700 dark:text-red-400"
|
|
262
262
|
: "bg-bg-subtle border-border text-text-muted"
|
|
263
263
|
}`}
|
|
264
264
|
>
|
|
@@ -413,11 +413,11 @@ export default function RequestLoggerV2() {
|
|
|
413
413
|
className={`flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium border transition-all ${
|
|
414
414
|
activeFilter === f.key
|
|
415
415
|
? f.key === "error"
|
|
416
|
-
? "bg-red-500/20 text-red-400 border-red-500/40"
|
|
416
|
+
? "bg-red-500/20 text-red-700 dark:text-red-400 border-red-500/40"
|
|
417
417
|
: f.key === "ok"
|
|
418
|
-
? "bg-emerald-500/20 text-emerald-400 border-emerald-500/40"
|
|
418
|
+
? "bg-emerald-500/20 text-emerald-700 dark:text-emerald-400 border-emerald-500/40"
|
|
419
419
|
: f.key === "combo"
|
|
420
|
-
? "bg-violet-500/20 text-violet-300 border-violet-500/40"
|
|
420
|
+
? "bg-violet-500/20 text-violet-700 dark:text-violet-300 border-violet-500/40"
|
|
421
421
|
: "bg-primary text-white border-primary"
|
|
422
422
|
: "bg-bg-subtle border-border text-text-muted hover:border-text-muted"
|
|
423
423
|
}`}
|
|
@@ -635,7 +635,7 @@ export default function RequestLoggerV2() {
|
|
|
635
635
|
{visibleColumns.combo && (
|
|
636
636
|
<td className="px-3 py-2">
|
|
637
637
|
{log.comboName ? (
|
|
638
|
-
<span className="inline-block px-2 py-0.5 rounded-full text-[9px] font-bold bg-violet-500/20 text-violet-
|
|
638
|
+
<span className="inline-block px-2 py-0.5 rounded-full text-[9px] font-bold bg-violet-500/20 text-violet-800 dark:text-violet-300 border border-violet-500/40">
|
|
639
639
|
{log.comboName}
|
|
640
640
|
</span>
|
|
641
641
|
) : (
|
|
@@ -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": {
|