mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
fix: honor observed provider quota resets
Detect same-resetAt quota resets when provider usage drops back to the reset floor, and prefer that observed snapshot over stale recorded weekly events for provider USD windows and API-key USD quotas.\n\nTests: npx eslint changed files\nTests: npm run typecheck:core\nTests: DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/lib/quota-reset-events.test.ts tests/unit/provider-window-costs.test.ts tests/unit/api-key-usage-limits.test.ts\nTests: npm run build\nTests: docker build --target runner-base --build-arg OMNIROUTE_BUILD_MEMORY_MB=4096 -t omniroute:quota-reset-window-20260702002300 .
This commit is contained in:
@@ -22,7 +22,11 @@ interface ProviderWindowCostPayload {
|
|||||||
windowStartAt: string;
|
windowStartAt: string;
|
||||||
windowResetAt: string | null;
|
windowResetAt: string | null;
|
||||||
windowSource: "provider_weekly_reset" | "fallback_rolling_7d";
|
windowSource: "provider_weekly_reset" | "fallback_rolling_7d";
|
||||||
windowStartSource: "recorded_reset_event" | "inferred_from_reset_at" | "fallback_rolling_7d";
|
windowStartSource:
|
||||||
|
| "recorded_reset_event"
|
||||||
|
| "observed_snapshot_reset"
|
||||||
|
| "inferred_from_reset_at"
|
||||||
|
| "fallback_rolling_7d";
|
||||||
quotaName: string | null;
|
quotaName: string | null;
|
||||||
quotaUsedPercent: number | null;
|
quotaUsedPercent: number | null;
|
||||||
quotaRemainingPercent: number | null;
|
quotaRemainingPercent: number | null;
|
||||||
@@ -207,9 +211,11 @@ export default function ProviderUsdCostModal({
|
|||||||
<span>
|
<span>
|
||||||
{payload.windowStartSource === "recorded_reset_event"
|
{payload.windowStartSource === "recorded_reset_event"
|
||||||
? `From recorded ${payload.quotaName || "weekly quota"} reset`
|
? `From recorded ${payload.quotaName || "weekly quota"} reset`
|
||||||
: payload.windowSource === "provider_weekly_reset"
|
: payload.windowStartSource === "observed_snapshot_reset"
|
||||||
? `From ${payload.quotaName || "weekly quota"} reset`
|
? `From observed ${payload.quotaName || "weekly quota"} reset`
|
||||||
: "Fallback rolling 7d"}
|
: payload.windowSource === "provider_weekly_reset"
|
||||||
|
? `From ${payload.quotaName || "weekly quota"} reset`
|
||||||
|
: "Fallback rolling 7d"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-3 flex flex-col gap-2">
|
<div className="mt-3 flex flex-col gap-2">
|
||||||
|
|||||||
@@ -36,6 +36,17 @@ interface QuotaSnapshotObservationRow {
|
|||||||
remainingPercentage: number | null;
|
remainingPercentage: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface QuotaSnapshotWindowRow {
|
||||||
|
nextResetAt: string | null;
|
||||||
|
remainingPercentage: number | null;
|
||||||
|
createdAt: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProviderQuotaWindowStart {
|
||||||
|
windowStartIso: string;
|
||||||
|
source: "recorded_reset_event" | "observed_snapshot_reset";
|
||||||
|
}
|
||||||
|
|
||||||
function toNumberOrNull(value: unknown): number | null {
|
function toNumberOrNull(value: unknown): number | null {
|
||||||
if (typeof value === "number" && Number.isFinite(value)) return value;
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
||||||
if (typeof value === "string" && value.trim()) {
|
if (typeof value === "string" && value.trim()) {
|
||||||
@@ -55,6 +66,17 @@ function usedPercent(remainingPercentage: number | null): number | null {
|
|||||||
return remaining === null ? null : Math.max(0, Math.min(100, 100 - remaining));
|
return remaining === null ? null : Math.max(0, Math.min(100, 100 - remaining));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isResetDrop(
|
||||||
|
previousUsedPercentage: number | null,
|
||||||
|
currentUsedPercentage: number
|
||||||
|
): boolean {
|
||||||
|
if (previousUsedPercentage === null) return false;
|
||||||
|
const droppedToResetFloor =
|
||||||
|
currentUsedPercentage <= 1 && previousUsedPercentage > currentUsedPercentage;
|
||||||
|
const significantDrop = previousUsedPercentage - currentUsedPercentage >= 5;
|
||||||
|
return droppedToResetFloor || significantDrop;
|
||||||
|
}
|
||||||
|
|
||||||
function parseResetIso(value: string | null): string | null {
|
function parseResetIso(value: string | null): string | null {
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
const parsed = Date.parse(value);
|
const parsed = Date.parse(value);
|
||||||
@@ -127,12 +149,22 @@ export function recordProviderQuotaResetEventIfChanged(input: ResetEventInput):
|
|||||||
const previousResetMs = Date.parse(previousResetIso);
|
const previousResetMs = Date.parse(previousResetIso);
|
||||||
const currentResetMs = Date.parse(currentResetIso);
|
const currentResetMs = Date.parse(currentResetIso);
|
||||||
if (!Number.isFinite(previousResetMs) || !Number.isFinite(currentResetMs)) return;
|
if (!Number.isFinite(previousResetMs) || !Number.isFinite(currentResetMs)) return;
|
||||||
if (currentResetMs <= previousResetMs) return;
|
|
||||||
if (resetDay(previousResetIso) === resetDay(currentResetIso)) return;
|
|
||||||
|
|
||||||
const previousRemaining = clampPercent(toNumberOrNull(previous?.remainingPercentage));
|
const previousRemaining = clampPercent(toNumberOrNull(previous?.remainingPercentage));
|
||||||
const currentRemaining = clampPercent(toNumberOrNull(input.currentRemainingPercentage));
|
const currentRemaining = clampPercent(toNumberOrNull(input.currentRemainingPercentage));
|
||||||
const observedAt = parseResetIso(input.observedAt ?? null) ?? new Date().toISOString();
|
const observedAt = parseResetIso(input.observedAt ?? null) ?? new Date().toISOString();
|
||||||
|
const previousUsed = usedPercent(previousRemaining);
|
||||||
|
const currentUsed = usedPercent(currentRemaining);
|
||||||
|
const resetMovedForward =
|
||||||
|
currentResetMs > previousResetMs && resetDay(previousResetIso) !== resetDay(currentResetIso);
|
||||||
|
const resetObservedWithinSameResetAt =
|
||||||
|
resetDay(previousResetIso) === resetDay(currentResetIso) &&
|
||||||
|
currentUsed !== null &&
|
||||||
|
isResetDrop(previousUsed, currentUsed);
|
||||||
|
|
||||||
|
if (!resetMovedForward && !resetObservedWithinSameResetAt) return;
|
||||||
|
|
||||||
|
const windowStartedAt = resetMovedForward ? previousResetIso : observedAt;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const db = getDbInstance() as unknown as DbLike;
|
const db = getDbInstance() as unknown as DbLike;
|
||||||
@@ -148,13 +180,13 @@ export function recordProviderQuotaResetEventIfChanged(input: ResetEventInput):
|
|||||||
input.provider,
|
input.provider,
|
||||||
input.connectionId,
|
input.connectionId,
|
||||||
input.windowKey,
|
input.windowKey,
|
||||||
previousResetIso,
|
windowStartedAt,
|
||||||
currentResetIso,
|
currentResetIso,
|
||||||
observedAt,
|
observedAt,
|
||||||
previousRemaining,
|
previousRemaining,
|
||||||
currentRemaining,
|
currentRemaining,
|
||||||
usedPercent(previousRemaining),
|
previousUsed,
|
||||||
usedPercent(currentRemaining),
|
currentUsed,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
@@ -163,7 +195,7 @@ export function recordProviderQuotaResetEventIfChanged(input: ResetEventInput):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProviderQuotaWindowStartIso(
|
function getRecordedQuotaWindowStartIso(
|
||||||
connectionId: string,
|
connectionId: string,
|
||||||
targetResetAtIso: string,
|
targetResetAtIso: string,
|
||||||
nowMs = Date.now()
|
nowMs = Date.now()
|
||||||
@@ -204,3 +236,99 @@ export function getProviderQuotaWindowStartIso(
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getObservedQuotaWindowStartIso(
|
||||||
|
connectionId: string,
|
||||||
|
targetResetAtIso: string,
|
||||||
|
nowMs = Date.now()
|
||||||
|
): { windowStartIso: string; resetDrop: boolean } | null {
|
||||||
|
if (!connectionId || !targetResetAtIso) return null;
|
||||||
|
const targetDay = resetDay(targetResetAtIso);
|
||||||
|
if (!targetDay) return null;
|
||||||
|
|
||||||
|
const db = getDbInstance() as unknown as DbLike;
|
||||||
|
const nowIso = new Date(nowMs).toISOString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const rows = db
|
||||||
|
.prepare<QuotaSnapshotWindowRow>(
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
next_reset_at as nextResetAt,
|
||||||
|
remaining_percentage as remainingPercentage,
|
||||||
|
created_at as createdAt
|
||||||
|
FROM quota_snapshots
|
||||||
|
WHERE connection_id = @connectionId
|
||||||
|
AND LOWER(window_key) LIKE '%weekly%'
|
||||||
|
AND LOWER(window_key) NOT LIKE '%sonnet%'
|
||||||
|
AND created_at <= @nowIso
|
||||||
|
ORDER BY created_at ASC, id ASC
|
||||||
|
`
|
||||||
|
)
|
||||||
|
.all({ connectionId, nowIso });
|
||||||
|
|
||||||
|
let firstObservedIso: string | null = null;
|
||||||
|
let resetDropIso: string | null = null;
|
||||||
|
let previousUsedPercentage: number | null = null;
|
||||||
|
|
||||||
|
for (const row of rows) {
|
||||||
|
const createdIso = parseResetIso(row.createdAt);
|
||||||
|
if (!createdIso || resetDay(row.nextResetAt) !== targetDay) continue;
|
||||||
|
|
||||||
|
if (!firstObservedIso) firstObservedIso = createdIso;
|
||||||
|
|
||||||
|
const currentUsedPercentage = usedPercent(clampPercent(row.remainingPercentage));
|
||||||
|
if (currentUsedPercentage !== null) {
|
||||||
|
if (isResetDrop(previousUsedPercentage, currentUsedPercentage)) {
|
||||||
|
resetDropIso = createdIso;
|
||||||
|
}
|
||||||
|
previousUsedPercentage = currentUsedPercentage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resetDropIso) return { windowStartIso: resetDropIso, resetDrop: true };
|
||||||
|
if (firstObservedIso) return { windowStartIso: firstObservedIso, resetDrop: false };
|
||||||
|
return null;
|
||||||
|
} catch (error: unknown) {
|
||||||
|
if (error instanceof Error && error.message.includes("no such table")) return null;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getProviderQuotaWindowStart(
|
||||||
|
connectionId: string,
|
||||||
|
targetResetAtIso: string,
|
||||||
|
nowMs = Date.now()
|
||||||
|
): ProviderQuotaWindowStart | null {
|
||||||
|
const recordedIso = getRecordedQuotaWindowStartIso(connectionId, targetResetAtIso, nowMs);
|
||||||
|
const observed = getObservedQuotaWindowStartIso(connectionId, targetResetAtIso, nowMs);
|
||||||
|
|
||||||
|
if (!recordedIso && !observed) return null;
|
||||||
|
if (!recordedIso && observed) {
|
||||||
|
return { windowStartIso: observed.windowStartIso, source: "observed_snapshot_reset" };
|
||||||
|
}
|
||||||
|
if (recordedIso && !observed) {
|
||||||
|
return { windowStartIso: recordedIso, source: "recorded_reset_event" };
|
||||||
|
}
|
||||||
|
|
||||||
|
const recordedMs = Date.parse(recordedIso!);
|
||||||
|
const observedMs = Date.parse(observed!.windowStartIso);
|
||||||
|
if (
|
||||||
|
observed!.resetDrop &&
|
||||||
|
Number.isFinite(recordedMs) &&
|
||||||
|
Number.isFinite(observedMs) &&
|
||||||
|
observedMs > recordedMs
|
||||||
|
) {
|
||||||
|
return { windowStartIso: observed!.windowStartIso, source: "observed_snapshot_reset" };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { windowStartIso: recordedIso!, source: "recorded_reset_event" };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getProviderQuotaWindowStartIso(
|
||||||
|
connectionId: string,
|
||||||
|
targetResetAtIso: string,
|
||||||
|
nowMs = Date.now()
|
||||||
|
): string | null {
|
||||||
|
return getProviderQuotaWindowStart(connectionId, targetResetAtIso, nowMs)?.windowStartIso ?? null;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { getCostSummary } from "@/domain/costRules";
|
|||||||
import { getApiKeys } from "@/lib/db/apiKeys";
|
import { getApiKeys } from "@/lib/db/apiKeys";
|
||||||
import { getDbInstance } from "@/lib/db/core";
|
import { getDbInstance } from "@/lib/db/core";
|
||||||
import { getAllProviderLimitsCache, getProviderLimitsCache } from "@/lib/db/providerLimits";
|
import { getAllProviderLimitsCache, getProviderLimitsCache } from "@/lib/db/providerLimits";
|
||||||
import { getProviderQuotaWindowStartIso } from "@/lib/db/quotaResetEvents";
|
import { getProviderQuotaWindowStart } from "@/lib/db/quotaResetEvents";
|
||||||
import { calculateCost } from "@/lib/usage/costCalculator";
|
import { calculateCost } from "@/lib/usage/costCalculator";
|
||||||
|
|
||||||
const WEEK_MS = 7 * 24 * 60 * 60 * 1000;
|
const WEEK_MS = 7 * 24 * 60 * 60 * 1000;
|
||||||
@@ -69,7 +69,11 @@ export interface ProviderWindowCostBreakdown {
|
|||||||
windowStartAt: string;
|
windowStartAt: string;
|
||||||
windowResetAt: string | null;
|
windowResetAt: string | null;
|
||||||
windowSource: "provider_weekly_reset" | "fallback_rolling_7d";
|
windowSource: "provider_weekly_reset" | "fallback_rolling_7d";
|
||||||
windowStartSource: "recorded_reset_event" | "inferred_from_reset_at" | "fallback_rolling_7d";
|
windowStartSource:
|
||||||
|
| "recorded_reset_event"
|
||||||
|
| "observed_snapshot_reset"
|
||||||
|
| "inferred_from_reset_at"
|
||||||
|
| "fallback_rolling_7d";
|
||||||
quotaName: string | null;
|
quotaName: string | null;
|
||||||
quotaUsedPercent: number | null;
|
quotaUsedPercent: number | null;
|
||||||
quotaRemainingPercent: number | null;
|
quotaRemainingPercent: number | null;
|
||||||
@@ -111,19 +115,19 @@ function parseResetAt(value: unknown, nowMs: number): number | null {
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRecordedWindowStartMs(
|
function getProviderWindowStart(
|
||||||
connectionId: string | null,
|
connectionId: string | null,
|
||||||
resetMs: number,
|
resetMs: number,
|
||||||
nowMs: number
|
nowMs: number
|
||||||
): number | null {
|
): { startMs: number; source: ProviderWindowCostBreakdown["windowStartSource"] } | null {
|
||||||
if (!connectionId) return null;
|
if (!connectionId) return null;
|
||||||
const resetIso = new Date(resetMs).toISOString();
|
const resetIso = new Date(resetMs).toISOString();
|
||||||
const startIso = getProviderQuotaWindowStartIso(connectionId, resetIso, nowMs);
|
const start = getProviderQuotaWindowStart(connectionId, resetIso, nowMs);
|
||||||
if (!startIso) return null;
|
if (!start) return null;
|
||||||
const startMs = Date.parse(startIso);
|
const startMs = Date.parse(start.windowStartIso);
|
||||||
if (!Number.isFinite(startMs)) return null;
|
if (!Number.isFinite(startMs)) return null;
|
||||||
if (startMs > nowMs || startMs >= resetMs) return null;
|
if (startMs > nowMs || startMs >= resetMs) return null;
|
||||||
return startMs;
|
return { startMs, source: start.source };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRemainingPercent(quota: JsonRecord): number | null {
|
function getRemainingPercent(quota: JsonRecord): number | null {
|
||||||
@@ -212,16 +216,16 @@ function selectWeeklyWindow(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
const recordedStartMs = getRecordedWindowStartMs(
|
const providerWindowStart = getProviderWindowStart(
|
||||||
selected.connectionId,
|
selected.connectionId,
|
||||||
selected.resetMs,
|
selected.resetMs,
|
||||||
nowMs
|
nowMs
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
startMs: recordedStartMs ?? selected.resetMs - WEEK_MS,
|
startMs: providerWindowStart?.startMs ?? selected.resetMs - WEEK_MS,
|
||||||
resetMs: selected.resetMs,
|
resetMs: selected.resetMs,
|
||||||
source: "provider_weekly_reset",
|
source: "provider_weekly_reset",
|
||||||
windowStartSource: recordedStartMs ? "recorded_reset_event" : "inferred_from_reset_at",
|
windowStartSource: providerWindowStart?.source ?? "inferred_from_reset_at",
|
||||||
quotaName: selected.quotaName,
|
quotaName: selected.quotaName,
|
||||||
quotaUsedPercent: selected.quotaUsedPercent,
|
quotaUsedPercent: selected.quotaUsedPercent,
|
||||||
quotaRemainingPercent: selected.quotaRemainingPercent,
|
quotaRemainingPercent: selected.quotaRemainingPercent,
|
||||||
|
|||||||
@@ -231,6 +231,27 @@ test("getApiKeyUsageLimitStatus cuts weekly USD spend at observed provider quota
|
|||||||
null,
|
null,
|
||||||
"2026-06-20T02:10:00.000Z"
|
"2026-06-20T02:10:00.000Z"
|
||||||
);
|
);
|
||||||
|
db.prepare(
|
||||||
|
`
|
||||||
|
INSERT INTO provider_quota_reset_events
|
||||||
|
(provider, connection_id, window_key, window_started_at, window_resets_at,
|
||||||
|
observed_at, previous_remaining_percentage, new_remaining_percentage,
|
||||||
|
previous_used_percentage, new_used_percentage, raw_data)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
`
|
||||||
|
).run(
|
||||||
|
"claude",
|
||||||
|
"conn-claude",
|
||||||
|
"weekly (7d)",
|
||||||
|
"2026-06-18T23:00:00.000Z",
|
||||||
|
"2026-06-25T23:00:00.000Z",
|
||||||
|
"2026-06-18T23:04:00.000Z",
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
const metadata = await apiKeysDb.getApiKeyMetadata(created.key);
|
const metadata = await apiKeysDb.getApiKeyMetadata(created.key);
|
||||||
assert.ok(metadata);
|
assert.ok(metadata);
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-quota-res
|
|||||||
process.env.DATA_DIR = TEST_DATA_DIR;
|
process.env.DATA_DIR = TEST_DATA_DIR;
|
||||||
|
|
||||||
const core = await import("../../../src/lib/db/core.ts");
|
const core = await import("../../../src/lib/db/core.ts");
|
||||||
const { recordProviderQuotaResetEventIfChanged, getProviderQuotaWindowStartIso } = await import(
|
const {
|
||||||
"../../../src/lib/db/quotaResetEvents.ts"
|
recordProviderQuotaResetEventIfChanged,
|
||||||
);
|
getProviderQuotaWindowStart,
|
||||||
|
getProviderQuotaWindowStartIso,
|
||||||
|
} = await import("../../../src/lib/db/quotaResetEvents.ts");
|
||||||
|
|
||||||
// Force migrations (incl. 108_provider_quota_reset_events) to run.
|
// Force migrations (incl. 108_provider_quota_reset_events) to run.
|
||||||
core.getDbInstance();
|
core.getDbInstance();
|
||||||
@@ -49,13 +51,132 @@ test("getWindowStart returns null for a reset day with no recorded event", () =>
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("does not record when previous and current reset fall on the same day (no transition)", () => {
|
test("observed same-resetAt quota drop overrides an older recorded weekly window", () => {
|
||||||
|
const connectionId = "conn-early-reset-snapshot";
|
||||||
|
const targetResetAt = "2026-07-02T23:00:00.000Z";
|
||||||
|
const db = core.getDbInstance();
|
||||||
|
|
||||||
|
db.prepare(
|
||||||
|
`
|
||||||
|
INSERT INTO provider_quota_reset_events
|
||||||
|
(provider, connection_id, window_key, window_started_at, window_resets_at,
|
||||||
|
observed_at, previous_remaining_percentage, new_remaining_percentage,
|
||||||
|
previous_used_percentage, new_used_percentage, raw_data)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
`
|
||||||
|
).run(
|
||||||
|
"claude",
|
||||||
|
connectionId,
|
||||||
|
"weekly (7d)",
|
||||||
|
"2026-06-25T23:00:00.000Z",
|
||||||
|
targetResetAt,
|
||||||
|
"2026-06-25T23:04:00.000Z",
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
const insertSnapshot = db.prepare(`
|
||||||
|
INSERT INTO quota_snapshots (
|
||||||
|
provider,
|
||||||
|
connection_id,
|
||||||
|
window_key,
|
||||||
|
remaining_percentage,
|
||||||
|
is_exhausted,
|
||||||
|
next_reset_at,
|
||||||
|
window_duration_ms,
|
||||||
|
raw_data,
|
||||||
|
created_at
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
`);
|
||||||
|
insertSnapshot.run(
|
||||||
|
"claude",
|
||||||
|
connectionId,
|
||||||
|
"weekly (7d)",
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
targetResetAt,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"2026-06-25T23:04:00.000Z"
|
||||||
|
);
|
||||||
|
insertSnapshot.run(
|
||||||
|
"claude",
|
||||||
|
connectionId,
|
||||||
|
"weekly (7d)",
|
||||||
|
4,
|
||||||
|
0,
|
||||||
|
targetResetAt,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"2026-07-01T00:05:00.000Z"
|
||||||
|
);
|
||||||
|
insertSnapshot.run(
|
||||||
|
"claude",
|
||||||
|
connectionId,
|
||||||
|
"weekly (7d)",
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
targetResetAt,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"2026-07-01T21:41:13.293Z"
|
||||||
|
);
|
||||||
|
|
||||||
|
const start = getProviderQuotaWindowStart(
|
||||||
|
connectionId,
|
||||||
|
targetResetAt,
|
||||||
|
Date.parse("2026-07-02T00:00:00.000Z")
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.deepEqual(start, {
|
||||||
|
windowStartIso: "2026-07-01T21:41:13.293Z",
|
||||||
|
source: "observed_snapshot_reset",
|
||||||
|
});
|
||||||
|
assert.equal(
|
||||||
|
getProviderQuotaWindowStartIso(
|
||||||
|
connectionId,
|
||||||
|
targetResetAt,
|
||||||
|
Date.parse("2026-07-02T00:00:00.000Z")
|
||||||
|
),
|
||||||
|
"2026-07-01T21:41:13.293Z"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("records same-resetAt weekly resets when usage drops back to the reset floor", () => {
|
||||||
|
const connectionId = "conn-early-reset-record";
|
||||||
|
const targetResetAt = "2026-07-02T23:00:00.000Z";
|
||||||
|
const observedAt = "2026-07-01T21:41:13.293Z";
|
||||||
|
|
||||||
|
recordProviderQuotaResetEventIfChanged({
|
||||||
|
provider: "claude",
|
||||||
|
connectionId,
|
||||||
|
windowKey: "weekly (7d)",
|
||||||
|
currentResetAt: targetResetAt,
|
||||||
|
currentRemainingPercentage: 100,
|
||||||
|
previousObservation: { resetAt: targetResetAt, remainingPercentage: 4 },
|
||||||
|
observedAt,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
getProviderQuotaWindowStartIso(
|
||||||
|
connectionId,
|
||||||
|
targetResetAt,
|
||||||
|
Date.parse("2026-07-02T00:00:00.000Z")
|
||||||
|
),
|
||||||
|
observedAt
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("does not record when previous and current reset fall on the same day without a reset drop", () => {
|
||||||
recordProviderQuotaResetEventIfChanged({
|
recordProviderQuotaResetEventIfChanged({
|
||||||
provider: PROVIDER,
|
provider: PROVIDER,
|
||||||
connectionId: "conn-sameday",
|
connectionId: "conn-sameday",
|
||||||
windowKey: "weekly",
|
windowKey: "weekly",
|
||||||
currentResetAt: "2026-03-10T23:00:00.000Z",
|
currentResetAt: "2026-03-10T23:00:00.000Z",
|
||||||
currentRemainingPercentage: 80,
|
currentRemainingPercentage: 69,
|
||||||
previousObservation: { resetAt: "2026-03-10T01:00:00.000Z", remainingPercentage: 70 },
|
previousObservation: { resetAt: "2026-03-10T01:00:00.000Z", remainingPercentage: 70 },
|
||||||
observedAt: "2026-03-10T23:30:00.000Z",
|
observedAt: "2026-03-10T23:30:00.000Z",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -267,6 +267,126 @@ test("provider window costs use the recorded reset event as the cost cutoff", as
|
|||||||
assert.equal(result.rows[0].requests, 1);
|
assert.equal(result.rows[0].requests, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("provider window costs cut at an observed same-resetAt quota reset", async () => {
|
||||||
|
await localDb.updatePricing({
|
||||||
|
claude: {
|
||||||
|
"claude-opus-4-8": { input: 1, output: 1, cached: 1, cache_creation: 1, reasoning: 1 },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const targetResetAt = "2026-07-02T23:00:00.000Z";
|
||||||
|
providerLimits.setProviderLimitsCache("claude-early-reset", {
|
||||||
|
quotas: {
|
||||||
|
"weekly (7d)": {
|
||||||
|
used: 7,
|
||||||
|
total: 100,
|
||||||
|
remainingPercentage: 93,
|
||||||
|
resetAt: targetResetAt,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plan: "default_claude_max_20x",
|
||||||
|
message: null,
|
||||||
|
fetchedAt: "2026-07-02T00:04:00.000Z",
|
||||||
|
});
|
||||||
|
|
||||||
|
const db = core.getDbInstance();
|
||||||
|
db.prepare(
|
||||||
|
`
|
||||||
|
INSERT INTO provider_quota_reset_events
|
||||||
|
(provider, connection_id, window_key, window_started_at, window_resets_at,
|
||||||
|
observed_at, previous_remaining_percentage, new_remaining_percentage,
|
||||||
|
previous_used_percentage, new_used_percentage, raw_data)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
`
|
||||||
|
).run(
|
||||||
|
"claude",
|
||||||
|
"claude-early-reset",
|
||||||
|
"weekly (7d)",
|
||||||
|
"2026-06-25T23:00:00.000Z",
|
||||||
|
targetResetAt,
|
||||||
|
"2026-06-25T23:04:00.000Z",
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
const insertSnapshot = db.prepare(`
|
||||||
|
INSERT INTO quota_snapshots (
|
||||||
|
provider,
|
||||||
|
connection_id,
|
||||||
|
window_key,
|
||||||
|
remaining_percentage,
|
||||||
|
is_exhausted,
|
||||||
|
next_reset_at,
|
||||||
|
window_duration_ms,
|
||||||
|
raw_data,
|
||||||
|
created_at
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
`);
|
||||||
|
insertSnapshot.run(
|
||||||
|
"claude",
|
||||||
|
"claude-early-reset",
|
||||||
|
"weekly (7d)",
|
||||||
|
4,
|
||||||
|
0,
|
||||||
|
targetResetAt,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"2026-07-01T00:05:00.000Z"
|
||||||
|
);
|
||||||
|
insertSnapshot.run(
|
||||||
|
"claude",
|
||||||
|
"claude-early-reset",
|
||||||
|
"weekly (7d)",
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
targetResetAt,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"2026-07-01T21:41:13.293Z"
|
||||||
|
);
|
||||||
|
insertSnapshot.run(
|
||||||
|
"claude",
|
||||||
|
"claude-early-reset",
|
||||||
|
"weekly (7d)",
|
||||||
|
93,
|
||||||
|
0,
|
||||||
|
targetResetAt,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"2026-07-02T00:04:00.000Z"
|
||||||
|
);
|
||||||
|
|
||||||
|
await usageHistory.saveRequestUsage({
|
||||||
|
provider: "claude",
|
||||||
|
model: "claude-opus-4-8",
|
||||||
|
connectionId: "claude-early-reset",
|
||||||
|
tokens: { input: 8_000_000, output: 0 },
|
||||||
|
timestamp: "2026-07-01T20:00:00.000Z",
|
||||||
|
});
|
||||||
|
await usageHistory.saveRequestUsage({
|
||||||
|
provider: "claude",
|
||||||
|
model: "claude-opus-4-8",
|
||||||
|
connectionId: "claude-early-reset",
|
||||||
|
tokens: { input: 2_000_000, output: 0 },
|
||||||
|
timestamp: "2026-07-01T22:00:00.000Z",
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await getProviderWindowCostBreakdown({
|
||||||
|
provider: "claude",
|
||||||
|
connectionId: "claude-early-reset",
|
||||||
|
now: Date.parse("2026-07-02T00:10:00.000Z"),
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(result.windowStartAt, "2026-07-01T21:41:13.293Z");
|
||||||
|
assert.equal(result.windowStartSource, "observed_snapshot_reset");
|
||||||
|
assert.equal(result.totalCostUsd, 2);
|
||||||
|
assert.equal(result.rows.length, 1);
|
||||||
|
assert.equal(result.rows[0].requests, 1);
|
||||||
|
});
|
||||||
|
|
||||||
test("provider window costs prefer recorded USD history over repricing usage tokens", async () => {
|
test("provider window costs prefer recorded USD history over repricing usage tokens", async () => {
|
||||||
await localDb.updatePricing({
|
await localDb.updatePricing({
|
||||||
claude: {
|
claude: {
|
||||||
|
|||||||
Reference in New Issue
Block a user