Files
bifrost/ui/lib/store/apis/governanceApi.ts
Beyhan Oğur 880f412e2c first commit
2026-04-26 21:52:23 +03:00

858 lines
28 KiB
TypeScript

import {
Budget,
CreateCustomerRequest,
CreateModelConfigRequest,
CreatePricingOverrideRequest,
UpdatePricingOverrideRequest,
CreateTeamRequest,
CreateVirtualKeyRequest,
Customer,
DebugStatsResponse,
GetBudgetsResponse,
GetCustomersParams,
GetCustomersResponse,
GetModelConfigsParams,
GetModelConfigsResponse,
GetPricingOverridesResponse,
GetProviderGovernanceResponse,
GetRateLimitsResponse,
GetTeamsParams,
GetTeamsResponse,
GetUsageStatsResponse,
GetVirtualKeysParams,
GetVirtualKeysResponse,
HealthCheckResponse,
ModelConfig,
ProviderGovernance,
PricingOverride,
RateLimit,
ResetUsageRequest,
Team,
UpdateBudgetRequest,
UpdateCustomerRequest,
UpdateModelConfigRequest,
UpdateProviderGovernanceRequest,
UpdateRateLimitRequest,
UpdateTeamRequest,
UpdateVirtualKeyRequest,
VirtualKey,
} from "@/lib/types/governance";
import { baseApi } from "./baseApi";
type PricingOverrideQueryArgs = {
scopeKind?: string;
virtualKeyID?: string;
providerID?: string;
providerKeyID?: string;
limit?: number;
offset?: number;
search?: string;
};
export const governanceApi = baseApi.injectEndpoints({
endpoints: (builder) => ({
// Virtual Keys
getVirtualKeys: builder.query<GetVirtualKeysResponse, GetVirtualKeysParams | void>({
query: (params) => ({
url: "/governance/virtual-keys",
params: {
...(params?.limit && { limit: params.limit }),
...(params?.offset !== undefined && { offset: params.offset }),
...(params?.search && { search: params.search }),
...(params?.customer_id && { customer_id: params.customer_id }),
...(params?.team_id && { team_id: params.team_id }),
...(params?.exclude_access_profile_managed_virtual === true && {
exclude_access_profile_managed_virtual: "true",
}),
...(params?.sort_by && { sort_by: params.sort_by }),
...(params?.order && { order: params.order }),
...(params?.export && { export: "true" }),
},
}),
providesTags: ["VirtualKeys"],
}),
getVirtualKey: builder.query<{ virtual_key: VirtualKey }, string>({
query: (vkId) => `/governance/virtual-keys/${vkId}`,
providesTags: (result, error, vkId) => [{ type: "VirtualKeys", id: vkId }],
}),
createVirtualKey: builder.mutation<{ message: string; virtual_key: VirtualKey }, CreateVirtualKeyRequest>({
query: (data) => ({
url: "/governance/virtual-keys",
method: "POST",
body: data,
}),
invalidatesTags: ["VirtualKeys"],
}),
updateVirtualKey: builder.mutation<{ message: string; virtual_key: VirtualKey }, { vkId: string; data: UpdateVirtualKeyRequest }>({
query: ({ vkId, data }) => ({
url: `/governance/virtual-keys/${vkId}`,
method: "PUT",
body: data,
}),
invalidatesTags: ["VirtualKeys"],
}),
deleteVirtualKey: builder.mutation<{ message: string }, string>({
query: (vkId) => ({
url: `/governance/virtual-keys/${vkId}`,
method: "DELETE",
}),
invalidatesTags: ["VirtualKeys"],
}),
// Teams
getTeams: builder.query<GetTeamsResponse, GetTeamsParams | void>({
query: (params) => ({
url: "/governance/teams",
params: {
...(params?.limit && { limit: params.limit }),
...(params?.offset !== undefined && { offset: params.offset }),
...(params?.search && { search: params.search }),
...(params?.customer_id && { customer_id: params.customer_id }),
},
}),
providesTags: ["Teams"],
}),
getTeam: builder.query<{ team: Team }, string>({
query: (teamId) => `/governance/teams/${teamId}`,
providesTags: (result, error, teamId) => [{ type: "Teams", id: teamId }],
}),
createTeam: builder.mutation<{ message: string; team: Team }, CreateTeamRequest>({
query: (data) => ({
url: "/governance/teams",
method: "POST",
body: data,
}),
async onQueryStarted(arg, { dispatch, getState, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getTeams" || entry?.status !== "fulfilled") continue;
const search = entry.originalArgs?.search as string | undefined;
if (search && !data.team.name.toLowerCase().includes(search.toLowerCase())) continue;
dispatch(
governanceApi.util.updateQueryData("getTeams", entry.originalArgs, (draft) => {
if (!draft.teams) draft.teams = [];
draft.teams.unshift(data.team);
draft.count = (draft.count || 0) + 1;
draft.total_count = (draft.total_count || 0) + 1;
}),
);
}
} catch {
// Mutation failed
}
},
}),
updateTeam: builder.mutation<{ message: string; team: Team }, { teamId: string; data: UpdateTeamRequest }>({
query: ({ teamId, data }) => ({
url: `/governance/teams/${teamId}`,
method: "PUT",
body: data,
}),
async onQueryStarted({ teamId }, { dispatch, getState, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getTeams" || entry?.status !== "fulfilled") continue;
dispatch(
governanceApi.util.updateQueryData("getTeams", entry.originalArgs, (draft) => {
if (!draft.teams) return;
const index = draft.teams.findIndex((t) => t.id === teamId);
if (index !== -1) {
draft.teams[index] = data.team;
}
}),
);
}
dispatch(
governanceApi.util.updateQueryData("getTeam", teamId, (draft) => {
draft.team = data.team;
}),
);
} catch {
// Mutation failed
}
},
}),
deleteTeam: builder.mutation<{ message: string }, string>({
query: (teamId) => ({
url: `/governance/teams/${teamId}`,
method: "DELETE",
}),
async onQueryStarted(teamId, { dispatch, getState, queryFulfilled }) {
try {
await queryFulfilled;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getTeams" || entry?.status !== "fulfilled") continue;
dispatch(
governanceApi.util.updateQueryData("getTeams", entry.originalArgs, (draft) => {
if (!draft.teams) return;
const before = draft.teams.length;
draft.teams = draft.teams.filter((t) => t.id !== teamId);
if (draft.teams.length < before) {
draft.count = Math.max(0, (draft.count || 0) - 1);
draft.total_count = Math.max(0, (draft.total_count || 0) - 1);
}
}),
);
}
} catch {
// Mutation failed
}
},
}),
// Customers
getCustomers: builder.query<GetCustomersResponse, GetCustomersParams | void>({
query: (params) => ({
url: "/governance/customers",
params: {
...(params?.limit && { limit: params.limit }),
...(params?.offset !== undefined && { offset: params.offset }),
...(params?.search && { search: params.search }),
},
}),
providesTags: ["Customers"],
}),
getCustomer: builder.query<{ customer: Customer }, string>({
query: (customerId) => `/governance/customers/${customerId}`,
providesTags: (result, error, customerId) => [{ type: "Customers", id: customerId }],
}),
createCustomer: builder.mutation<{ message: string; customer: Customer }, CreateCustomerRequest>({
query: (data) => ({
url: "/governance/customers",
method: "POST",
body: data,
}),
async onQueryStarted(arg, { dispatch, getState, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getCustomers" || entry?.status !== "fulfilled") continue;
const search = entry.originalArgs?.search as string | undefined;
if (search && !data.customer.name.toLowerCase().includes(search.toLowerCase())) continue;
dispatch(
governanceApi.util.updateQueryData("getCustomers", entry.originalArgs, (draft) => {
if (!draft.customers) draft.customers = [];
draft.customers.unshift(data.customer);
draft.count = (draft.count || 0) + 1;
draft.total_count = (draft.total_count || 0) + 1;
}),
);
}
} catch {
// Mutation failed
}
},
}),
updateCustomer: builder.mutation<{ message: string; customer: Customer }, { customerId: string; data: UpdateCustomerRequest }>({
query: ({ customerId, data }) => ({
url: `/governance/customers/${customerId}`,
method: "PUT",
body: data,
}),
async onQueryStarted({ customerId }, { dispatch, getState, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getCustomers" || entry?.status !== "fulfilled") continue;
dispatch(
governanceApi.util.updateQueryData("getCustomers", entry.originalArgs, (draft) => {
if (!draft.customers) return;
const index = draft.customers.findIndex((c) => c.id === customerId);
if (index !== -1) {
draft.customers[index] = data.customer;
}
}),
);
}
dispatch(
governanceApi.util.updateQueryData("getCustomer", customerId, (draft) => {
draft.customer = data.customer;
}),
);
} catch {
// Mutation failed
}
},
}),
deleteCustomer: builder.mutation<{ message: string }, string>({
query: (customerId) => ({
url: `/governance/customers/${customerId}`,
method: "DELETE",
}),
async onQueryStarted(customerId, { dispatch, getState, queryFulfilled }) {
try {
await queryFulfilled;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getCustomers" || entry?.status !== "fulfilled") continue;
dispatch(
governanceApi.util.updateQueryData("getCustomers", entry.originalArgs, (draft) => {
if (!draft.customers) return;
const before = draft.customers.length;
draft.customers = draft.customers.filter((c) => c.id !== customerId);
if (draft.customers.length < before) {
draft.count = Math.max(0, (draft.count || 0) - 1);
draft.total_count = Math.max(0, (draft.total_count || 0) - 1);
}
}),
);
}
} catch {
// Mutation failed
}
},
}),
// Budgets
getBudgets: builder.query<GetBudgetsResponse, void>({
query: () => "/governance/budgets",
providesTags: ["Budgets"],
}),
getBudget: builder.query<{ budget: Budget }, string>({
query: (budgetId) => `/governance/budgets/${budgetId}`,
providesTags: (result, error, budgetId) => [{ type: "Budgets", id: budgetId }],
}),
updateBudget: builder.mutation<{ message: string; budget: Budget }, { budgetId: string; data: UpdateBudgetRequest }>({
query: ({ budgetId, data }) => ({
url: `/governance/budgets/${budgetId}`,
method: "PUT",
body: data,
}),
async onQueryStarted({ budgetId }, { dispatch, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
dispatch(
governanceApi.util.updateQueryData("getBudgets", undefined, (draft) => {
if (!draft.budgets) return;
const index = draft.budgets.findIndex((b) => b.id === budgetId);
if (index !== -1) {
draft.budgets[index] = data.budget;
}
}),
);
dispatch(
governanceApi.util.updateQueryData("getBudget", budgetId, (draft) => {
draft.budget = data.budget;
}),
);
} catch {
// Mutation failed
}
},
}),
deleteBudget: builder.mutation<{ message: string }, string>({
query: (budgetId) => ({
url: `/governance/budgets/${budgetId}`,
method: "DELETE",
}),
async onQueryStarted(budgetId, { dispatch, queryFulfilled }) {
try {
await queryFulfilled;
dispatch(
governanceApi.util.updateQueryData("getBudgets", undefined, (draft) => {
if (!draft.budgets) return;
draft.budgets = draft.budgets.filter((b) => b.id !== budgetId);
draft.count = Math.max(0, (draft.count || 0) - 1);
}),
);
} catch {
// Mutation failed
}
},
}),
// Rate Limits
getRateLimits: builder.query<GetRateLimitsResponse, void>({
query: () => "/governance/rate-limits",
providesTags: ["RateLimits"],
}),
getRateLimit: builder.query<{ rate_limit: RateLimit }, string>({
query: (rateLimitId) => `/governance/rate-limits/${rateLimitId}`,
providesTags: (result, error, rateLimitId) => [{ type: "RateLimits", id: rateLimitId }],
}),
updateRateLimit: builder.mutation<{ message: string; rate_limit: RateLimit }, { rateLimitId: string; data: UpdateRateLimitRequest }>({
query: ({ rateLimitId, data }) => ({
url: `/governance/rate-limits/${rateLimitId}`,
method: "PUT",
body: data,
}),
async onQueryStarted({ rateLimitId }, { dispatch, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
dispatch(
governanceApi.util.updateQueryData("getRateLimits", undefined, (draft) => {
if (!draft.rate_limits) return;
const index = draft.rate_limits.findIndex((r) => r.id === rateLimitId);
if (index !== -1) {
draft.rate_limits[index] = data.rate_limit;
}
}),
);
dispatch(
governanceApi.util.updateQueryData("getRateLimit", rateLimitId, (draft) => {
draft.rate_limit = data.rate_limit;
}),
);
} catch {
// Mutation failed
}
},
}),
deleteRateLimit: builder.mutation<{ message: string }, string>({
query: (rateLimitId) => ({
url: `/governance/rate-limits/${rateLimitId}`,
method: "DELETE",
}),
async onQueryStarted(rateLimitId, { dispatch, queryFulfilled }) {
try {
await queryFulfilled;
dispatch(
governanceApi.util.updateQueryData("getRateLimits", undefined, (draft) => {
if (!draft.rate_limits) return;
draft.rate_limits = draft.rate_limits.filter((r) => r.id !== rateLimitId);
draft.count = Math.max(0, (draft.count || 0) - 1);
}),
);
} catch {
// Mutation failed
}
},
}),
// Usage Stats
getUsageStats: builder.query<GetUsageStatsResponse, { virtualKeyId?: string }>({
query: ({ virtualKeyId } = {}) => ({
url: "/governance/usage-stats",
params: virtualKeyId ? { virtual_key_id: virtualKeyId } : {},
}),
providesTags: ["UsageStats"],
}),
resetUsage: builder.mutation<{ message: string }, ResetUsageRequest>({
query: (data) => ({
url: "/governance/usage-reset",
method: "POST",
body: data,
}),
invalidatesTags: ["UsageStats"],
}),
// Debug endpoints
getGovernanceDebugStats: builder.query<DebugStatsResponse, void>({
query: () => "/governance/debug/stats",
providesTags: ["DebugStats"],
}),
getGovernanceHealth: builder.query<HealthCheckResponse, void>({
query: () => "/governance/debug/health",
providesTags: ["HealthCheck"],
}),
// Model Configs
getModelConfigs: builder.query<GetModelConfigsResponse, GetModelConfigsParams | void>({
query: (params) => ({
url: "/governance/model-configs",
params: {
...(params?.limit && { limit: params.limit }),
...(params?.offset !== undefined && { offset: params.offset }),
...(params?.search && { search: params.search }),
},
}),
providesTags: ["ModelConfigs"],
}),
getModelConfig: builder.query<{ model_config: ModelConfig }, string>({
query: (id) => `/governance/model-configs/${id}`,
providesTags: (result, error, id) => [{ type: "ModelConfigs", id }],
}),
createModelConfig: builder.mutation<{ message: string; model_config: ModelConfig }, CreateModelConfigRequest>({
query: (data) => ({
url: "/governance/model-configs",
method: "POST",
body: data,
}),
async onQueryStarted(arg, { dispatch, getState, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getModelConfigs" || entry?.status !== "fulfilled") continue;
const search = entry.originalArgs?.search as string | undefined;
if (search && !data.model_config.model_name.toLowerCase().includes(search.toLowerCase())) continue;
dispatch(
governanceApi.util.updateQueryData("getModelConfigs", entry.originalArgs, (draft) => {
if (!draft.model_configs) draft.model_configs = [];
draft.model_configs.unshift(data.model_config);
draft.count = (draft.count || 0) + 1;
draft.total_count = (draft.total_count || 0) + 1;
}),
);
}
} catch {
// Mutation failed, do nothing - error handling bubbled up
}
},
}),
updateModelConfig: builder.mutation<{ message: string; model_config: ModelConfig }, { id: string; data: UpdateModelConfigRequest }>({
query: ({ id, data }) => ({
url: `/governance/model-configs/${id}`,
method: "PUT",
body: data,
}),
async onQueryStarted({ id }, { dispatch, getState, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getModelConfigs" || entry?.status !== "fulfilled") continue;
dispatch(
governanceApi.util.updateQueryData("getModelConfigs", entry.originalArgs, (draft) => {
if (!draft.model_configs) return;
const index = draft.model_configs.findIndex((mc) => mc.id === id);
if (index !== -1) {
draft.model_configs[index] = data.model_config;
}
}),
);
}
dispatch(
governanceApi.util.updateQueryData("getModelConfig", id, (draft) => {
draft.model_config = data.model_config;
}),
);
} catch {
// Mutation failed
}
},
}),
deleteModelConfig: builder.mutation<{ message: string }, string>({
query: (id) => ({
url: `/governance/model-configs/${id}`,
method: "DELETE",
}),
async onQueryStarted(id, { dispatch, getState, queryFulfilled }) {
try {
await queryFulfilled;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getModelConfigs" || entry?.status !== "fulfilled") continue;
dispatch(
governanceApi.util.updateQueryData("getModelConfigs", entry.originalArgs, (draft) => {
if (!draft.model_configs) return;
const before = draft.model_configs.length;
draft.model_configs = draft.model_configs.filter((mc) => mc.id !== id);
if (draft.model_configs.length < before) {
draft.count = Math.max(0, (draft.count || 0) - 1);
draft.total_count = Math.max(0, (draft.total_count || 0) - 1);
}
}),
);
}
} catch {
// Mutation failed
}
},
}),
getPricingOverrides: builder.query<GetPricingOverridesResponse, PricingOverrideQueryArgs | void>({
query: (params) => ({
url: "/governance/pricing-overrides",
params: {
scope_kind: params?.scopeKind,
virtual_key_id: params?.virtualKeyID,
provider_id: params?.providerID,
provider_key_id: params?.providerKeyID,
...(params?.limit !== undefined && { limit: params.limit }),
...(params?.offset !== undefined && { offset: params.offset }),
...(params?.search && { search: params.search }),
},
}),
providesTags: ["PricingOverrides"],
}),
createPricingOverride: builder.mutation<{ message: string; pricing_override: PricingOverride }, CreatePricingOverrideRequest>({
query: (data) => ({
url: "/governance/pricing-overrides",
method: "POST",
body: data,
}),
async onQueryStarted(_arg, { dispatch, getState, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
const created = data.pricing_override;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getPricingOverrides" || entry?.status !== "fulfilled") continue;
const args: PricingOverrideQueryArgs = entry.originalArgs ?? {};
const matchesQuery =
(!args.scopeKind || args.scopeKind === created.scope_kind) &&
(!args.virtualKeyID || args.virtualKeyID === created.virtual_key_id) &&
(!args.providerID || args.providerID === created.provider_id) &&
(!args.providerKeyID || args.providerKeyID === created.provider_key_id) &&
(!args.search || created.name?.toLowerCase().includes(args.search.toLowerCase()));
if (!matchesQuery) continue;
dispatch(
governanceApi.util.updateQueryData("getPricingOverrides", entry.originalArgs, (draft) => {
if (!draft.pricing_overrides) draft.pricing_overrides = [];
if (!args.offset || args.offset === 0) {
draft.pricing_overrides.unshift(created);
draft.count = (draft.count || 0) + 1;
draft.total_count = (draft.total_count || 0) + 1;
} else {
draft.total_count = (draft.total_count || 0) + 1;
}
}),
);
}
} catch {
// Mutation failed
}
},
}),
updatePricingOverride: builder.mutation<
{ message: string; pricing_override: PricingOverride },
{ id: string; data: UpdatePricingOverrideRequest }
>({
query: ({ id, data }) => ({
url: `/governance/pricing-overrides/${id}`,
method: "PUT",
body: data,
}),
async onQueryStarted({ id }, { dispatch, getState, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
const updated = data.pricing_override;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getPricingOverrides" || entry?.status !== "fulfilled") continue;
const args: PricingOverrideQueryArgs = entry.originalArgs ?? {};
const matchesQuery =
(!args.scopeKind || args.scopeKind === updated.scope_kind) &&
(!args.virtualKeyID || args.virtualKeyID === updated.virtual_key_id) &&
(!args.providerID || args.providerID === updated.provider_id) &&
(!args.providerKeyID || args.providerKeyID === updated.provider_key_id);
dispatch(
governanceApi.util.updateQueryData("getPricingOverrides", entry.originalArgs, (draft) => {
if (!draft.pricing_overrides) return;
const index = draft.pricing_overrides.findIndex((o) => o.id === id);
if (index === -1) return;
if (matchesQuery) {
draft.pricing_overrides[index] = updated;
} else {
// Override no longer belongs in this filtered list
draft.pricing_overrides.splice(index, 1);
draft.count = Math.max(0, (draft.count || 0) - 1);
draft.total_count = Math.max(0, (draft.total_count || 0) - 1);
}
}),
);
}
} catch {
// Mutation failed
}
},
}),
deletePricingOverride: builder.mutation<{ message: string }, string>({
query: (id) => ({
url: `/governance/pricing-overrides/${id}`,
method: "DELETE",
}),
async onQueryStarted(id, { dispatch, getState, queryFulfilled }) {
try {
await queryFulfilled;
const queries = (getState() as any).api.queries;
for (const entry of Object.values(queries) as any[]) {
if (entry?.endpointName !== "getPricingOverrides" || entry?.status !== "fulfilled") continue;
dispatch(
governanceApi.util.updateQueryData("getPricingOverrides", entry.originalArgs, (draft) => {
if (!draft.pricing_overrides) return;
const before = draft.pricing_overrides.length;
draft.pricing_overrides = draft.pricing_overrides.filter((o) => o.id !== id);
const removed = before - draft.pricing_overrides.length;
if (removed > 0) {
draft.count = Math.max(0, (draft.count || 0) - removed);
draft.total_count = Math.max(0, (draft.total_count || 0) - removed);
}
}),
);
}
} catch {
// Mutation failed
}
},
}),
// Provider Governance
getProviderGovernance: builder.query<GetProviderGovernanceResponse, { fromMemory?: boolean } | void>({
query: (params) => ({
url: "/governance/providers",
params: { from_memory: params?.fromMemory ?? false },
}),
providesTags: ["ProviderGovernance"],
}),
updateProviderGovernance: builder.mutation<
{ message: string; provider: ProviderGovernance },
{ provider: string; data: UpdateProviderGovernanceRequest }
>({
query: ({ provider, data }) => ({
url: `/governance/providers/${encodeURIComponent(provider)}`,
method: "PUT",
body: data,
}),
async onQueryStarted({ provider }, { dispatch, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
const variants = [undefined, { fromMemory: true }] as const;
for (const variant of variants) {
dispatch(
governanceApi.util.updateQueryData("getProviderGovernance", variant, (draft) => {
if (!draft.providers) draft.providers = [];
const index = draft.providers.findIndex((p) => p.provider === provider);
if (index !== -1) {
draft.providers[index] = data.provider;
} else {
// New provider governance - add to list
draft.providers.push(data.provider);
draft.count = (draft.count || 0) + 1;
}
}),
);
}
} catch {
// Mutation failed
}
},
}),
deleteProviderGovernance: builder.mutation<{ message: string }, string>({
query: (provider) => ({
url: `/governance/providers/${encodeURIComponent(provider)}`,
method: "DELETE",
}),
async onQueryStarted(provider, { dispatch, queryFulfilled }) {
try {
await queryFulfilled;
const variants = [undefined, { fromMemory: true }] as const;
for (const variant of variants) {
dispatch(
governanceApi.util.updateQueryData("getProviderGovernance", variant, (draft) => {
if (!draft.providers) return;
draft.providers = draft.providers.filter((p) => p.provider !== provider);
draft.count = Math.max(0, (draft.count || 0) - 1);
}),
);
}
} catch {
// Mutation failed
}
},
}),
}),
});
export const {
// Virtual Keys
useGetVirtualKeysQuery,
useGetVirtualKeyQuery,
useCreateVirtualKeyMutation,
useUpdateVirtualKeyMutation,
useDeleteVirtualKeyMutation,
// Teams
useGetTeamsQuery,
useGetTeamQuery,
useCreateTeamMutation,
useUpdateTeamMutation,
useDeleteTeamMutation,
// Customers
useGetCustomersQuery,
useGetCustomerQuery,
useCreateCustomerMutation,
useUpdateCustomerMutation,
useDeleteCustomerMutation,
// Budgets
useGetBudgetsQuery,
useGetBudgetQuery,
useUpdateBudgetMutation,
useDeleteBudgetMutation,
// Rate Limits
useGetRateLimitsQuery,
useGetRateLimitQuery,
useUpdateRateLimitMutation,
useDeleteRateLimitMutation,
// Usage Stats
useGetUsageStatsQuery,
useResetUsageMutation,
// Debug
useGetGovernanceDebugStatsQuery,
useGetGovernanceHealthQuery,
// Model Configs
useGetModelConfigsQuery,
useGetModelConfigQuery,
useCreateModelConfigMutation,
useUpdateModelConfigMutation,
useDeleteModelConfigMutation,
useGetPricingOverridesQuery,
useCreatePricingOverrideMutation,
useUpdatePricingOverrideMutation,
useDeletePricingOverrideMutation,
// Provider Governance
useGetProviderGovernanceQuery,
useUpdateProviderGovernanceMutation,
useDeleteProviderGovernanceMutation,
// Lazy queries
useLazyGetVirtualKeysQuery,
useLazyGetVirtualKeyQuery,
useLazyGetTeamsQuery,
useLazyGetTeamQuery,
useLazyGetCustomersQuery,
useLazyGetCustomerQuery,
useLazyGetBudgetsQuery,
useLazyGetBudgetQuery,
useLazyGetRateLimitsQuery,
useLazyGetRateLimitQuery,
useLazyGetUsageStatsQuery,
useLazyGetGovernanceDebugStatsQuery,
useLazyGetGovernanceHealthQuery,
useLazyGetModelConfigsQuery,
useLazyGetProviderGovernanceQuery,
} = governanceApi;