File size: 2,803 Bytes
cd8bd0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { AI_PROVIDERS } from "@/shared/constants/providers";
import { getUnifiedModelsResponse } from "@/app/api/v1/models/catalog";
import { INTERNAL_PROXY_ERROR, getCatalogDiagnosticsHeaders } from "@/lib/modelMetadataRegistry";
import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error";

/**
 * GET /api/models/catalog
 * Returns all models grouped by provider, with metadata (type, custom flag)
 */
export async function GET(request: Request) {
  const diagnosticHeaders = getCatalogDiagnosticsHeaders({ request });
  try {
    const response = await getUnifiedModelsResponse(request, {});
    const body = await response.json();

    if (!response.ok) {
      return Response.json(body, {
        status: response.status,
        headers: {
          ...diagnosticHeaders,
        },
      });
    }

    const catalog: Record<string, any> = {};
    for (const model of body.data || []) {
      const providerId =
        typeof model.owned_by === "string" && model.owned_by.length > 0
          ? model.owned_by
          : "unknown";
      const bucket = catalog[providerId] || {
        provider: AI_PROVIDERS[providerId]?.name || providerId,
        active: providerId !== "unknown",
        models: [],
      };

      bucket.models.push({
        id: model.id,
        name: model.name || model.root || model.id,
        type: model.type || "chat",
        custom: model.custom === true,
        ...(model.free === true ? { free: true } : {}),
        ...(model.capabilities ? { capabilities: model.capabilities } : {}),
        ...(typeof model.context_length === "number"
          ? { context_length: model.context_length }
          : {}),
        ...(typeof model.max_output_tokens === "number"
          ? { max_output_tokens: model.max_output_tokens }
          : {}),
        ...(Array.isArray(model.input_modalities)
          ? { input_modalities: model.input_modalities }
          : {}),
        ...(Array.isArray(model.output_modalities)
          ? { output_modalities: model.output_modalities }
          : {}),
        ...(Array.isArray(model.supported_endpoints)
          ? { supported_endpoints: model.supported_endpoints }
          : {}),
      });

      catalog[providerId] = bucket;
    }

    return Response.json(
      { catalog, catalogVersion: response.headers.get("X-Model-Catalog-Version") },
      {
        headers: {
          ...diagnosticHeaders,
        },
      }
    );
  } catch (error) {
    return Response.json(
      {
        error: {
          message: sanitizeErrorMessage(error instanceof Error ? error.message : String(error)),
          type: "server_error",
          code: INTERNAL_PROXY_ERROR,
        },
      },
      {
        status: 500,
        headers: {
          ...diagnosticHeaders,
        },
      }
    );
  }
}