Add provider rate limit snapshot state
This commit is contained in:
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,
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user