mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
fix(usage): parse numeric-string quota reset timestamps as Unix sec/ms (#4493)
Rebuilt onto release/v3.8.33 (squash-base-stale). Integrated into release/v3.8.33.
This commit is contained in:
committed by
GitHub
parent
4279751abd
commit
cd45943015
@@ -75,6 +75,7 @@ _In development — bullets added per PR; finalized at release._
|
||||
- **fix(command-code): pass `reasoning` / `thinking` fields through to upstream params** — Command Code requests carrying `reasoning`/`thinking` controls had those fields dropped before the upstream call, so reasoning-effort and extended-thinking settings were silently ignored; they are now forwarded to the upstream params. ([#4473](https://github.com/diegosouzapw/OmniRoute/pull/4473) — thanks @adivekar-utexas)
|
||||
- **fix(usage): keep Kiro overage-enabled accounts routable after base quota hits zero** — a Kiro account with overage enabled was excluded from routing once its base quota reached zero, even though overage billing should keep it serving; such accounts now stay routable past base-quota exhaustion. ([#4469](https://github.com/diegosouzapw/OmniRoute/issues/4469) — thanks @heaven321357 / @CleanDev-Fix)
|
||||
- **fix(providers): model-aware `supportsRedactedThinking` for mixed-format providers** — the redacted-thinking capability was resolved per provider rather than per model, so a mixed-format provider (some models support redacted thinking, others don't) got the wrong answer for some models; the check is now model-aware. ([#4479](https://github.com/diegosouzapw/OmniRoute/pull/4479) — thanks @TF0rd)
|
||||
- **fix(usage): parse numeric-string quota reset timestamps as Unix seconds/ms** — when a provider returned the quota reset timestamp as a numeric string (e.g. `"1700000000"`), `parseResetTime` passed it straight to `new Date(str)`, which returned `Invalid Date` and dropped the reset entirely (UI showed no reset). Numeric strings are now detected and treated as Unix timestamps with the same `< 1e12` seconds-vs-ms heuristic already applied to numeric values; ISO/parseable strings are untouched. Applied symmetrically in `codexUsageQuotas.parseResetTime`. (Inspired by upstream [decolua/9router#768](https://github.com/decolua/9router/pull/768) — thanks @DEYLNN)
|
||||
|
||||
### 🔒 Security
|
||||
|
||||
|
||||
@@ -41,14 +41,20 @@ function toNumber(value: unknown, fallback = 0): number {
|
||||
function parseResetTime(resetValue: unknown): string | null {
|
||||
if (!resetValue) return null;
|
||||
try {
|
||||
const date =
|
||||
resetValue instanceof Date
|
||||
? resetValue
|
||||
: typeof resetValue === "number"
|
||||
? new Date(resetValue < 1e12 ? resetValue * 1000 : resetValue)
|
||||
: typeof resetValue === "string"
|
||||
? new Date(resetValue)
|
||||
: null;
|
||||
let date: Date | null = null;
|
||||
if (resetValue instanceof Date) {
|
||||
date = resetValue;
|
||||
} else if (typeof resetValue === "number") {
|
||||
date = new Date(resetValue < 1e12 ? resetValue * 1000 : resetValue);
|
||||
} else if (typeof resetValue === "string") {
|
||||
// Numeric strings are Unix timestamps too (seconds or milliseconds).
|
||||
if (/^\d+$/.test(resetValue)) {
|
||||
const ts = Number(resetValue);
|
||||
date = new Date(ts < 1e12 ? ts * 1000 : ts);
|
||||
} else {
|
||||
date = new Date(resetValue);
|
||||
}
|
||||
}
|
||||
if (!date || date.getTime() <= 0) return null;
|
||||
return date.toISOString();
|
||||
} catch {
|
||||
|
||||
@@ -1625,7 +1625,14 @@ function parseResetTime(resetValue: unknown): string | null {
|
||||
} else if (typeof resetValue === "number") {
|
||||
date = new Date(resetValue < 1e12 ? resetValue * 1000 : resetValue);
|
||||
} else if (typeof resetValue === "string") {
|
||||
date = new Date(resetValue);
|
||||
// Numeric strings are Unix timestamps too (seconds or milliseconds).
|
||||
// `new Date("1700000000")` otherwise returns Invalid Date.
|
||||
if (/^\d+$/.test(resetValue)) {
|
||||
const ts = Number(resetValue);
|
||||
date = new Date(ts < 1e12 ? ts * 1000 : ts);
|
||||
} else {
|
||||
date = new Date(resetValue);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,21 @@ describe("parseResetTime", () => {
|
||||
it("returns null for invalid date strings", () => {
|
||||
assert.equal(__testing.parseResetTime("not-a-date"), null);
|
||||
});
|
||||
|
||||
// Inspired-by upstream decolua/9router#768 — provider APIs sometimes return
|
||||
// the reset timestamp as a numeric string. Without explicit detection,
|
||||
// `new Date("1700000000")` returns Invalid Date and the value is lost.
|
||||
it("parses a numeric string in seconds (value < 1e12)", () => {
|
||||
const sec = "1700000000";
|
||||
const out = __testing.parseResetTime(sec);
|
||||
assert.equal(out, new Date(Number(sec) * 1000).toISOString());
|
||||
});
|
||||
|
||||
it("parses a numeric string already in milliseconds (value >= 1e12)", () => {
|
||||
const ms = "1700000000000";
|
||||
const out = __testing.parseResetTime(ms);
|
||||
assert.equal(out, new Date(Number(ms)).toISOString());
|
||||
});
|
||||
});
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
Reference in New Issue
Block a user