import { z } from "zod"; import { withUser, parseBody, json, ApiError } from "@/lib/api"; import { listConnections, upsertConnection, deleteConnection, validateConnection } from "@/lib/providers/keys"; import { syncProvider } from "@/lib/ai/registry"; import { getDecryptedKey } from "@/lib/providers/keys"; import { isProviderId } from "@/lib/ai/core/types"; import { LIMITS } from "@/lib/rate-limit"; export const dynamic = "force-dynamic"; export const GET = withUser(async ({ user }) => json({ connections: await listConnections(user.id) })); const putSchema = z.object({ provider: z.string(), apiKey: z.string().min(8).max(512) }); /** PUT /api/providers — add or replace a key (validated against the provider, then encrypted). */ export const PUT = withUser( async ({ req, user, ip }) => { const body = await parseBody(req, putSchema, 8_000); if (!isProviderId(body.provider)) throw new ApiError(400, "Unknown provider"); const result = await upsertConnection(user.id, body.provider, body.apiKey, { validate: true, ip }); // Refresh this provider's model list with the new key (best-effort, non-blocking for the UI). if (result.ok) { const key = await getDecryptedKey(user.id, body.provider); if (key) void syncProvider(body.provider, key, "user").catch(() => {}); } const connections = await listConnections(user.id); return json({ ...result, connections }); }, { limit: { ...LIMITS.keySave, key: "provider-save" } }, ); export const POST = withUser( async ({ req, user }) => { const body = await parseBody(req, z.object({ action: z.literal("validate"), provider: z.string() })); if (!isProviderId(body.provider)) throw new ApiError(400, "Unknown provider"); const res = await validateConnection(user.id, body.provider); if (res.ok) { const key = await getDecryptedKey(user.id, body.provider); if (key) void syncProvider(body.provider, key, "user").catch(() => {}); } return json({ ok: res.ok, error: res.error, modelsAvailable: res.modelsAvailable, latencyMs: res.latencyMs, connections: await listConnections(user.id) }); }, { limit: { ...LIMITS.keyValidate, key: "provider-validate" } }, ); export const DELETE = withUser(async ({ req, user, ip }) => { const provider = new URL(req.url).searchParams.get("provider"); if (!provider || !isProviderId(provider)) throw new ApiError(400, "Unknown provider"); await deleteConnection(user.id, provider, ip); return json({ connections: await listConnections(user.id) }); });