easyai-ai-gateway/apps/web/src/api.ts

338 lines
9.7 KiB
TypeScript

import type {
AuthResponse,
BaseModelCatalogItem,
BaseModelUpsertRequest,
CatalogProvider,
CatalogProviderUpsertRequest,
CreatedGatewayApiKey,
GatewayApiKey,
GatewayTenant,
GatewayTask,
GatewayUser,
IntegrationPlatform,
ListResponse,
PlatformModel,
PricingRule,
PricingRuleSet,
PricingRuleSetUpsertRequest,
RateLimitWindow,
UserGroup,
} from '@easyai-ai-gateway/contracts';
const API_BASE = import.meta.env.VITE_GATEWAY_API_BASE_URL ?? 'http://localhost:8088';
export interface HealthResponse {
ok: boolean;
service: string;
env: string;
identityMode?: string;
}
export async function getHealth(): Promise<HealthResponse> {
return request<HealthResponse>('/healthz', { auth: false });
}
export async function registerLocalAccount(input: {
username: string;
email?: string;
password: string;
displayName?: string;
invitationCode?: string;
}): Promise<AuthResponse> {
return request<AuthResponse>('/api/v1/auth/register', {
auth: false,
body: input,
method: 'POST',
});
}
export async function loginLocalAccount(input: { account: string; password: string }): Promise<AuthResponse> {
return request<AuthResponse>('/api/v1/auth/login', {
auth: false,
body: input,
method: 'POST',
});
}
export async function listPlatforms(token: string): Promise<ListResponse<IntegrationPlatform>> {
return request<ListResponse<IntegrationPlatform>>('/api/v1/platforms', { token });
}
export async function listModels(token: string): Promise<ListResponse<PlatformModel>> {
return request<ListResponse<PlatformModel>>('/api/v1/models', { token });
}
export async function listPublicCatalogProviders(): Promise<ListResponse<CatalogProvider>> {
return request<ListResponse<CatalogProvider>>('/api/v1/public/catalog/providers', { auth: false });
}
export async function listCatalogProviders(token: string): Promise<ListResponse<CatalogProvider>> {
return request<ListResponse<CatalogProvider>>('/api/v1/catalog/providers', { token });
}
export async function createCatalogProvider(
token: string,
input: CatalogProviderUpsertRequest,
): Promise<CatalogProvider> {
return request<CatalogProvider>('/api/v1/catalog/providers', {
body: input,
method: 'POST',
token,
});
}
export async function updateCatalogProvider(
token: string,
providerId: string,
input: CatalogProviderUpsertRequest,
): Promise<CatalogProvider> {
return request<CatalogProvider>(`/api/v1/catalog/providers/${providerId}`, {
body: input,
method: 'PATCH',
token,
});
}
export async function deleteCatalogProvider(token: string, providerId: string): Promise<void> {
await request<void>(`/api/v1/catalog/providers/${providerId}`, {
method: 'DELETE',
token,
});
}
export async function listPublicBaseModels(): Promise<ListResponse<BaseModelCatalogItem>> {
return request<ListResponse<BaseModelCatalogItem>>('/api/v1/public/catalog/base-models', { auth: false });
}
export async function listBaseModels(token: string): Promise<ListResponse<BaseModelCatalogItem>> {
return request<ListResponse<BaseModelCatalogItem>>('/api/v1/catalog/base-models', { token });
}
export async function createBaseModel(token: string, input: BaseModelUpsertRequest): Promise<BaseModelCatalogItem> {
return request<BaseModelCatalogItem>('/api/v1/catalog/base-models', {
body: input,
method: 'POST',
token,
});
}
export async function updateBaseModel(
token: string,
baseModelId: string,
input: BaseModelUpsertRequest,
): Promise<BaseModelCatalogItem> {
return request<BaseModelCatalogItem>(`/api/v1/catalog/base-models/${baseModelId}`, {
body: input,
method: 'PATCH',
token,
});
}
export async function deleteBaseModel(token: string, baseModelId: string): Promise<void> {
await request<void>(`/api/v1/catalog/base-models/${baseModelId}`, {
method: 'DELETE',
token,
});
}
export async function listPricingRules(token: string): Promise<ListResponse<PricingRule>> {
return request<ListResponse<PricingRule>>('/api/v1/pricing/rules', { token });
}
export async function listPricingRuleSets(token: string): Promise<ListResponse<PricingRuleSet>> {
return request<ListResponse<PricingRuleSet>>('/api/v1/pricing/rule-sets', { token });
}
export async function createPricingRuleSet(
token: string,
input: PricingRuleSetUpsertRequest,
): Promise<PricingRuleSet> {
return request<PricingRuleSet>('/api/v1/pricing/rule-sets', {
body: input,
method: 'POST',
token,
});
}
export async function updatePricingRuleSet(
token: string,
ruleSetId: string,
input: PricingRuleSetUpsertRequest,
): Promise<PricingRuleSet> {
return request<PricingRuleSet>(`/api/v1/pricing/rule-sets/${ruleSetId}`, {
body: input,
method: 'PATCH',
token,
});
}
export async function deletePricingRuleSet(token: string, ruleSetId: string): Promise<void> {
await request<void>(`/api/v1/pricing/rule-sets/${ruleSetId}`, {
method: 'DELETE',
token,
});
}
export async function listTenants(token: string): Promise<ListResponse<GatewayTenant>> {
return request<ListResponse<GatewayTenant>>('/api/v1/tenants', { token });
}
export async function listUsers(token: string): Promise<ListResponse<GatewayUser>> {
return request<ListResponse<GatewayUser>>('/api/v1/users', { token });
}
export async function listUserGroups(token: string): Promise<ListResponse<UserGroup>> {
return request<ListResponse<UserGroup>>('/api/v1/user-groups', { token });
}
export async function listApiKeys(token: string): Promise<ListResponse<GatewayApiKey>> {
return request<ListResponse<GatewayApiKey>>('/api/v1/api-keys', { token });
}
export async function createApiKey(
token: string,
input: { name: string; scopes?: string[] },
): Promise<CreatedGatewayApiKey> {
return request<CreatedGatewayApiKey>('/api/v1/api-keys', {
body: input,
method: 'POST',
token,
});
}
export async function createPlatform(
token: string,
input: {
provider: string;
platformKey?: string;
name: string;
baseUrl?: string;
authType?: string;
credentials?: Record<string, unknown>;
config?: Record<string, unknown>;
defaultPricingMode?: string;
defaultDiscountFactor?: number;
pricingRuleSetId?: string;
priority?: number;
},
): Promise<IntegrationPlatform> {
return request<IntegrationPlatform>('/api/v1/platforms', {
body: input,
method: 'POST',
token,
});
}
export async function createPlatformModel(
token: string,
platformId: string,
input: {
canonicalModelKey?: string;
baseModelId?: string;
modelName: string;
modelAlias?: string;
modelType: string;
displayName?: string;
retryPolicy?: Record<string, unknown>;
rateLimitPolicy?: Record<string, unknown>;
pricingRuleSetId?: string;
discountFactor?: number;
},
): Promise<PlatformModel> {
return request<PlatformModel>(`/api/v1/platforms/${platformId}/models`, {
body: input,
method: 'POST',
token,
});
}
export async function createChatTask(
token: string,
input: { model: string; messages: Array<Record<string, unknown>>; runMode?: string; simulation?: boolean },
): Promise<{ task: GatewayTask; next: Record<string, string> }> {
return request<{ task: GatewayTask; next: Record<string, string> }>('/api/v1/chat/completions', {
body: input,
method: 'POST',
token,
});
}
export async function createImageGenerationTask(
token: string,
input: { model: string; prompt: string; size?: string; quality?: string; runMode?: string; simulation?: boolean },
): Promise<{ task: GatewayTask; next: Record<string, string> }> {
return request<{ task: GatewayTask; next: Record<string, string> }>('/api/v1/images/generations', {
body: input,
method: 'POST',
token,
});
}
export async function createImageEditTask(
token: string,
input: { model: string; prompt: string; image?: string; mask?: string; runMode?: string; simulation?: boolean },
): Promise<{ task: GatewayTask; next: Record<string, string> }> {
return request<{ task: GatewayTask; next: Record<string, string> }>('/api/v1/images/edits', {
body: input,
method: 'POST',
token,
});
}
export async function estimatePricing(
token: string,
input: Record<string, unknown>,
): Promise<{ items: unknown[]; resolver: string }> {
return request<{ items: unknown[]; resolver: string }>('/api/v1/pricing/estimate', {
body: input,
method: 'POST',
token,
});
}
export async function getTask(token: string, taskId: string): Promise<GatewayTask> {
return request<GatewayTask>(`/api/v1/tasks/${taskId}`, { token });
}
export async function listRateLimitWindows(token: string): Promise<ListResponse<RateLimitWindow>> {
return request<ListResponse<RateLimitWindow>>('/api/v1/runtime/rate-limit-windows', { token });
}
async function request<T>(
path: string,
options: { token?: string; auth?: boolean; method?: string; body?: unknown } = {},
): Promise<T> {
const headers: Record<string, string> = {};
if (options.auth !== false && options.token) {
headers.Authorization = `Bearer ${options.token}`;
}
if (options.body !== undefined) {
headers['Content-Type'] = 'application/json';
}
const response = await fetch(`${API_BASE}${path}`, {
method: options.method ?? 'GET',
headers,
body: options.body === undefined ? undefined : JSON.stringify(options.body),
});
if (!response.ok) {
const body = await response.text();
throw new Error(parseErrorMessage(body) || `Request failed: ${response.status}`);
}
if (response.status === 204) {
return undefined as T;
}
return response.json() as Promise<T>;
}
function parseErrorMessage(body: string) {
if (!body) {
return '';
}
try {
const parsed = JSON.parse(body) as { error?: { message?: string } };
return parsed.error?.message ?? body;
} catch {
return body;
}
}