File size: 3,339 Bytes
eeb9404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { NextRequest, NextResponse } from 'next/server';
import { ProviderId } from '@/lib/llm/providers/types';
import { getProvider } from '@/lib/llm/providers/registry';
import { logger } from '@/lib/utils';

export async function POST(request: NextRequest) {
  try {
    const { apiKey, provider } = await request.json();
    
    if (!apiKey || !provider) {
      return NextResponse.json(
        { error: 'API key and provider are required' },
        { status: 400 }
      );
    }

    const providerConfig = getProvider(provider as ProviderId);
    let isValid = false;

    switch (provider) {
      case 'openrouter':
        const openrouterResp = await fetch('https://openrouter.ai/api/v1/auth/key', {
          headers: { 'Authorization': `Bearer ${apiKey}` }
        });
        isValid = openrouterResp.ok;
        break;

      case 'openai':
      case 'openai-codex':
        const openaiResp = await fetch('https://api.openai.com/v1/models', {
          headers: { 'Authorization': `Bearer ${apiKey}` }
        });
        isValid = openaiResp.ok;
        break;

      case 'anthropic':
        const anthropicResp = await fetch('https://api.anthropic.com/v1/models', {
          headers: {
            'x-api-key': apiKey,
            'anthropic-version': '2023-06-01'
          }
        });
        isValid = anthropicResp.ok;
        break;

      case 'groq':
        const groqResp = await fetch('https://api.groq.com/openai/v1/models', {
          headers: { 'Authorization': `Bearer ${apiKey}` }
        });
        isValid = groqResp.ok;
        break;

      case 'ollama':
      case 'lmstudio':
      case 'llamacpp':
        const localResp = await fetch(`${providerConfig.baseUrl}/models`);
        isValid = localResp.ok;
        break;

      case 'gemini':
        isValid = !!apiKey && apiKey.length > 10;
        break;

      case 'zhipu':
      case 'minimax':
        isValid = !!apiKey && apiKey.length > 10;
        break;

      case 'huggingface':
        const hfResp = await fetch('https://huggingface.co/api/whoami-v2', {
          headers: { 'Authorization': `Bearer ${apiKey}` }
        });
        isValid = hfResp.ok;
        break;

      case 'github':
        const githubResp = await fetch('https://api.github.com/user', {
          headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Accept': 'application/vnd.github+json',
            'X-GitHub-Api-Version': '2022-11-28'
          }
        });
        if (githubResp.ok) {
          const userData = await githubResp.json();
          return NextResponse.json({ valid: true, username: userData.login });
        }
        isValid = false;
        break;

      default:
        // For other OpenAI-compatible providers (including custom ones)
        if (providerConfig.baseUrl) {
          const headers: Record<string, string> = {};
          if (apiKey) {
            headers['Authorization'] = `Bearer ${apiKey}`;
          }
          const defaultResp = await fetch(`${providerConfig.baseUrl}/models`, { headers });
          isValid = defaultResp.ok;
        } else {
          isValid = false;
        }
        break;
    }

    return NextResponse.json({ valid: isValid });

  } catch (error) {
    logger.error('Validation error:', error);
    return NextResponse.json({ valid: false });
  }
}