-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathroute.ts
More file actions
132 lines (116 loc) · 4.85 KB
/
route.ts
File metadata and controls
132 lines (116 loc) · 4.85 KB
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { createOpenAI } from '@ai-sdk/openai';
import { createAnthropic } from '@ai-sdk/anthropic';
import { createGoogleGenerativeAI } from '@ai-sdk/google';
import { convertToModelMessages, stepCountIs, streamText, UIMessage } from 'ai';
import { NextRequest } from 'next/server';
import { getModelConfig, getProviderFromModelId, DEFAULT_MODELS, getBestDefaultModel } from '@/lib/models/config';
import type { ProviderId } from '@/lib/models/config';
export const maxDuration = 300;
/**
* Get the appropriate AI model instance based on model ID and API keys
*/
function getModel(modelId: string, apiKeys: Record<ProviderId, string | null>) {
const provider = getProviderFromModelId(modelId);
if (!provider) {
// Fallback to OpenAI default if model not found
const openaiKey = apiKeys.openai;
if (!openaiKey) {
throw new Error('OpenAI API key is required');
}
const openai = createOpenAI({ apiKey: openaiKey });
return openai(DEFAULT_MODELS.openai);
}
const apiKey = apiKeys[provider];
if (!apiKey) {
throw new Error(`${provider} API key is required for model ${modelId}`);
}
switch (provider) {
case 'openai': {
const openai = createOpenAI({ apiKey });
return openai(modelId);
}
case 'anthropic': {
const anthropic = createAnthropic({ apiKey });
return anthropic(modelId);
}
case 'google': {
const google = createGoogleGenerativeAI({ apiKey });
return google(modelId);
}
default:
throw new Error(`Unsupported provider: ${provider}`);
}
}
export async function POST(req: NextRequest) {
try {
const { messages, modelId }: { messages: UIMessage[]; modelId?: string } = await req.json();
// Get API keys from query parameters
const openaiKey = req.nextUrl.searchParams.get('openaiKey');
const anthropicKey = req.nextUrl.searchParams.get('anthropicKey');
const googleKey = req.nextUrl.searchParams.get('googleKey');
// Build API keys object
const apiKeys: Record<ProviderId, string | null> = {
openai: openaiKey,
anthropic: anthropicKey,
google: googleKey,
};
// Determine which model to use
// Only use default if no modelId was explicitly provided
let targetModelId = modelId;
// If no modelId provided, use best available based on API keys
if (!targetModelId || targetModelId.trim() === '') {
targetModelId = getBestDefaultModel(apiKeys);
}
// Validate model exists
let modelConfig = getModelConfig(targetModelId);
if (!modelConfig) {
// If model was explicitly provided but not found, return error
if (modelId && modelId.trim() !== '') {
return new Response(
JSON.stringify({ error: `Model "${targetModelId}" not found. Please select a valid model.` }),
{ status: 400, headers: { 'Content-Type': 'application/json' } }
);
}
// If it was a default that's not found, try to find any valid model for the provider
const fallbackModelId = getBestDefaultModel(apiKeys);
const fallbackConfig = getModelConfig(fallbackModelId);
if (fallbackConfig) {
targetModelId = fallbackModelId;
modelConfig = fallbackConfig;
} else {
return new Response(
JSON.stringify({ error: `No valid model configuration available` }),
{ status: 400, headers: { 'Content-Type': 'application/json' } }
);
}
}
// Get the model instance
let model;
try {
model = getModel(targetModelId, apiKeys);
} catch (error: any) {
console.error('Error creating model instance:', error);
const errorMessage = error.message || 'API key is required. Please add your API key in settings.';
return new Response(
JSON.stringify({ error: errorMessage }),
{ status: 401, headers: { 'Content-Type': 'application/json' } }
);
}
const result = streamText({
model,
messages: convertToModelMessages(messages),
onError: (e) => {
console.error("Error in agent: ", e);
},
stopWhen: stepCountIs(15),
tools: {}
});
return result.toUIMessageStreamResponse();
} catch (error: any) {
console.error('Error in API route:', error);
return new Response(
JSON.stringify({ error: error.message || 'Internal server error' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
}