SPB Git forge

spb/polyllm

Public
15commits 1branches 0releases
2.2 MBsize
maindefault branch
13 days agolast push
TypeScript 97.4% SQL 1% JavaScript 0.9% CSS 0.6%
2.5 KB · 52 lines typescript
Raw Blame History
1import { z } from "zod";2import { withUser, parseBody, json, ApiError } from "@/lib/api";3import { listConnections, upsertConnection, deleteConnection, validateConnection } from "@/lib/providers/keys";4import { syncProvider } from "@/lib/ai/registry";5import { getDecryptedKey } from "@/lib/providers/keys";6import { isProviderId } from "@/lib/ai/core/types";7import { LIMITS } from "@/lib/rate-limit";89export const dynamic = "force-dynamic";1011export const GET = withUser(async ({ user }) => json({ connections: await listConnections(user.id) }));1213const putSchema = z.object({ provider: z.string(), apiKey: z.string().min(8).max(512) });1415/** PUT /api/providers — add or replace a key (validated against the provider, then encrypted). */16export const PUT = withUser(17  async ({ req, user, ip }) => {18    const body = await parseBody(req, putSchema, 8_000);19    if (!isProviderId(body.provider)) throw new ApiError(400, "Unknown provider");20    const result = await upsertConnection(user.id, body.provider, body.apiKey, { validate: true, ip });21    // Refresh this provider's model list with the new key (best-effort, non-blocking for the UI).22    if (result.ok) {23      const key = await getDecryptedKey(user.id, body.provider);24      if (key) void syncProvider(body.provider, key, "user").catch(() => {});25    }26    const connections = await listConnections(user.id);27    return json({ ...result, connections });28  },29  { limit: { ...LIMITS.keySave, key: "provider-save" } },30);3132export const POST = withUser(33  async ({ req, user }) => {34    const body = await parseBody(req, z.object({ action: z.literal("validate"), provider: z.string() }));35    if (!isProviderId(body.provider)) throw new ApiError(400, "Unknown provider");36    const res = await validateConnection(user.id, body.provider);37    if (res.ok) {38      const key = await getDecryptedKey(user.id, body.provider);39      if (key) void syncProvider(body.provider, key, "user").catch(() => {});40    }41    return json({ ok: res.ok, error: res.error, modelsAvailable: res.modelsAvailable, latencyMs: res.latencyMs, connections: await listConnections(user.id) });42  },43  { limit: { ...LIMITS.keyValidate, key: "provider-validate" } },44);4546export const DELETE = withUser(async ({ req, user, ip }) => {47  const provider = new URL(req.url).searchParams.get("provider");48  if (!provider || !isProviderId(provider)) throw new ApiError(400, "Unknown provider");49  await deleteConnection(user.id, provider, ip);50  return json({ connections: await listConnections(user.id) });51});52