Add provider rate limit snapshot state

This commit is contained in:
ZacharyZhang-NY committed 2026-05-23 19:30:11 -04:00
1 parent c6be8a4ee4
commit 0388e1003b
7 files changed
+102 -34

No files matched your search

@@ -4,6 +4,7 @@ import { BrowserWindow, session } from "electron";
import type { CreateProviderResponseInput, SaveProviderCredentialInput, UpdateProviderPolicyInput } from "../../shared/commands";
import { FEATURE_FLAG_KEY, PROVIDER_AUTH_TYPE, PROVIDER_DATA_POLICY, PROVIDER_EXECUTION_MODE, PROVIDER_REQUEST_STATE, SLO_SIGNAL_KEY, type ProviderAuthType, type ProviderExecutionMode } from "../../shared/domain";
import { PROVIDER_CATALOG } from "../../shared/provider-catalog";
import { currentProviderUsageWindow } from "../../shared/provider-runtime-domain";
import { createId } from "../../shared/ids";
import { AuditService } from "./audit-service";
import { AuthBrokerService, type ProviderSecretVault } from "./auth-broker-service";
@@ -271,7 +272,7 @@ export class ProviderService {
if (executionMode === PROVIDER_EXECUTION_MODE.BACKGROUND && provider.background_enabled !== 1) {
throw new Error("Background execution is disabled for this provider policy.");
}
const window = currentMonthlyWindow();
const window = currentProviderUsageWindow();
const usage = this.db.prepare(`
select request_count
from provider_usage_windows
@@ -341,7 +342,7 @@ export class ProviderService {
}
private recordUsage(orgId: string, providerId: string, inputCharCount: number, outputCharCount: number): void {
const window = currentMonthlyWindow();
const window = currentProviderUsageWindow();
const now = new Date().toISOString();
this.db.prepare(`
insert into provider_usage_windows(
@@ -374,10 +375,3 @@ interface ProviderRow {
function hashPrompt(prompt: string): string {
return createHash("sha256").update(prompt).digest("hex");
}
function currentMonthlyWindow(): { start: string; end: string } {
const now = new Date();
const start = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
const end = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1));
return { start: start.toISOString(), end: end.toISOString() };
}
@@ -1,8 +1,13 @@
import type { DatabaseSync, StatementSync } from "node:sqlite";
import type { AppSnapshot } from "../../shared/domain";
import { PROVIDER_CATALOG } from "../../shared/provider-catalog";
import { currentProviderUsageWindow } from "../../shared/provider-runtime-domain";
type Row = Record<string, unknown>;
type ProviderUsageWindowRow = Pick<
AppSnapshot["providerRateLimits"][number],
"orgId" | "providerId" | "windowStart" | "windowEnd" | "requestCount" | "inputCharCount" | "outputCharCount"
>;
function all<T>(statement: StatementSync): T[] {
return statement.all() as T[];
@@ -45,6 +50,8 @@ export class SnapshotService {
.map((provider) => ({ ...provider, enabled: toBool(provider.enabled), backgroundEnabled: toBool(provider.backgroundEnabled) }));
const providerAuthProfiles = list<AppSnapshot["providerAuthProfiles"][number]>(this.db, "provider_auth_profiles", "created_at desc")
.map((profile) => ({ ...profile, active: toBool(profile.active) }));
const providerUsageWindows = list<ProviderUsageWindowRow>(this.db, "provider_usage_windows", "window_start desc");
const providerRateLimits = buildProviderRateLimits(providers, providerUsageWindows);
const skillBindings = list<AppSnapshot["skillBindings"][number]>(this.db, "skill_bindings", "priority asc")
.map((binding) => ({ ...binding, enabled: toBool(binding.enabled) }));
const files = list<AppSnapshot["files"][number]>(this.db, "file_objects", "created_at desc")
@@ -95,6 +102,7 @@ export class SnapshotService {
providerAuthProfiles,
providerCatalog: PROVIDER_CATALOG,
providerRequests: list(this.db, "provider_requests", "created_at desc"),
providerRateLimits,
skillDefinitions: list(this.db, "skill_definitions", "created_at asc"),
skillRevisions: list(this.db, "skill_revisions", "published_at desc"),
skillBindings,
@@ -140,3 +148,30 @@ export class SnapshotService {
return known[0] ?? null;
}
}
function buildProviderRateLimits(
providers: AppSnapshot["providers"],
providerUsageWindows: ProviderUsageWindowRow[],
): AppSnapshot["providerRateLimits"] {
const window = currentProviderUsageWindow();
return providers.map((provider) => {
const usage = providerUsageWindows.find((item) => item.providerId === provider.id && item.windowStart === window.start);
const requestCount = usage?.requestCount ?? 0;
const inputCharCount = usage?.inputCharCount ?? 0;
const outputCharCount = usage?.outputCharCount ?? 0;
const remainingRequestCount = Math.max(0, provider.monthlyRequestLimit - requestCount);
return {
orgId: provider.orgId,
providerId: provider.id,
providerKey: provider.providerKey,
windowStart: usage?.windowStart ?? window.start,
windowEnd: usage?.windowEnd ?? window.end,
monthlyRequestLimit: provider.monthlyRequestLimit,
requestCount,
inputCharCount,
outputCharCount,
remainingRequestCount,
exhausted: remainingRequestCount === 0,
};
});
}