From 87b4737cb123ad70f4f2b2ed1266a4c5c7eb8a2e Mon Sep 17 00:00:00 2001 From: EreQ Date: Fri, 15 May 2026 12:11:36 +0300 Subject: [PATCH 1/3] Implement Azure model support in utils Add Azure model initialization with error handling. --- lib/utils/index.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 018867f1..5fc73ff1 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -99,6 +99,25 @@ export async function getModel(requireVision: boolean = false) { } // Default behavior: Gemini -> Grok -> Bedrock -> OpenAI + + if (azureApiKey && azureEndpoint) { + const azure = createOpenAI({ + baseURL: azureEndpoint, + apiKey: azureApiKey, + }); + try { + return azure(azureDeploymentName); + } catch (error) { + console.error('Selected model "GPT-5.5" (Azure) is configured but failed to initialize.', error); + throw new Error('Failed to initialize selected model.'); + } + } else { + console.error('User selected "GPT-5.5" but AZURE_API_KEY or AZURE_ENDPOINT is not set.'); + throw new Error('Selected model is not configured.'); + } + } + } + if (gemini3ProApiKey) { const google = createGoogleGenerativeAI({ apiKey: gemini3ProApiKey, From f49aa25e2572cf0e5d9941f1f438d707bf1d5304 Mon Sep 17 00:00:00 2001 From: EreQ Date: Fri, 15 May 2026 12:19:58 +0300 Subject: [PATCH 2/3] Refactor model selection logic and cleanup imports --- lib/utils/index.ts | 119 +++++++++++++-------------------------------- 1 file changed, 34 insertions(+), 85 deletions(-) diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 5fc73ff1..7a1b7ded 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -1,26 +1,3 @@ -import { type ClassValue, clsx } from 'clsx' -import { twMerge } from 'tailwind-merge' -import { getSelectedModel } from '@/lib/actions/users' -import { createOpenAI } from '@ai-sdk/openai' -import { createGoogleGenerativeAI } from '@ai-sdk/google' -import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock' -import { createXai } from '@ai-sdk/xai'; -import { v4 as uuidv4 } from 'uuid'; - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) -} - -export function generateUUID(): string { - return uuidv4(); -} - -/** - * Re-export generateUUID as nanoid for shorter naming and compatibility with existing code. - * Returns a UUID v4 string. - */ -export { generateUUID as nanoid }; - export async function getModel(requireVision: boolean = false) { const selectedModel = await getSelectedModel(); @@ -43,90 +20,64 @@ export async function getModel(requireVision: boolean = false) { apiKey: xaiApiKey, baseURL: 'https://api.x.ai/v1', }); - try { - return xai('grok-4-fast-non-reasoning'); - } catch (error) { - console.error('Selected model "Grok 4.2" is configured but failed to initialize.', error); - throw new Error('Failed to initialize selected model.'); - } + return xai('grok-4-fast-non-reasoning'); } else { - console.error('User selected "Grok 4.2" but XAI_API_KEY is not set.'); - throw new Error('Selected model is not configured.'); + console.error('User selected "Grok 4.2" but XAI_API_KEY is not set.'); + throw new Error('Selected model is not configured.'); } + case 'Gemini 3': case 'Gemini 3.1 Pro': if (gemini3ProApiKey) { const google = createGoogleGenerativeAI({ apiKey: gemini3ProApiKey, }); - try { - return google('gemini-3.1-pro-preview'); - } catch (error) { - console.error('Selected model "Gemini 3.1 Pro" is configured but failed to initialize.', error); - throw new Error('Failed to initialize selected model.'); - } + return google('gemini-3.1-pro-preview'); } else { - console.error('User selected "Gemini 3.1 Pro" but GEMINI_3_PRO_API_KEY is not set.'); - throw new Error('Selected model is not configured.'); + console.error('User selected "Gemini 3.1 Pro" but GEMINI_3_PRO_API_KEY is not set.'); + throw new Error('Selected model is not configured.'); } + case 'GPT-5.1': if (openaiApiKey) { - const openai = createOpenAI({ - apiKey: openaiApiKey, - }); + const openai = createOpenAI({ apiKey: openaiApiKey }); return openai('gpt-4o'); } else { - console.error('User selected "GPT-5.1" but OPENAI_API_KEY is not set.'); - throw new Error('Selected model is not configured.'); + console.error('User selected "GPT-5.1" but OPENAI_API_KEY is not set.'); + throw new Error('Selected model is not configured.'); } + case 'GPT-5.5': if (azureApiKey && azureEndpoint) { const azure = createOpenAI({ baseURL: azureEndpoint, apiKey: azureApiKey, }); - try { - return azure(azureDeploymentName); - } catch (error) { - console.error('Selected model "GPT-5.5" (Azure) is configured but failed to initialize.', error); - throw new Error('Failed to initialize selected model.'); - } + return azure(azureDeploymentName); } else { - console.error('User selected "GPT-5.5" but AZURE_API_KEY or AZURE_ENDPOINT is not set.'); - throw new Error('Selected model is not configured.'); + console.error('User selected "GPT-5.5" but AZURE_API_KEY or AZURE_ENDPOINT is not set.'); + throw new Error('Selected model is not configured.'); } + + default: + console.warn(`Unknown selected model: ${selectedModel}, falling back to default.`); } } - // Default behavior: Gemini -> Grok -> Bedrock -> OpenAI - - if (azureApiKey && azureEndpoint) { - const azure = createOpenAI({ - baseURL: azureEndpoint, - apiKey: azureApiKey, - }); - try { - return azure(azureDeploymentName); - } catch (error) { - console.error('Selected model "GPT-5.5" (Azure) is configured but failed to initialize.', error); - throw new Error('Failed to initialize selected model.'); - } - } else { - console.error('User selected "GPT-5.5" but AZURE_API_KEY or AZURE_ENDPOINT is not set.'); - throw new Error('Selected model is not configured.'); - } - } + // === Default fallback order: Azure → Gemini → Grok → Bedrock → OpenAI === + if (azureApiKey && azureEndpoint) { + const azure = createOpenAI({ + baseURL: azureEndpoint, + apiKey: azureApiKey, + }); + return azure(azureDeploymentName); } if (gemini3ProApiKey) { const google = createGoogleGenerativeAI({ apiKey: gemini3ProApiKey, }); - try { - return google('gemini-3.1-pro-preview'); - } catch (error) { - console.warn('Gemini 3.1 Pro API unavailable, falling back to next provider:', error); - } + return google('gemini-3.1-pro-preview'); } if (xaiApiKey) { @@ -134,11 +85,7 @@ export async function getModel(requireVision: boolean = false) { apiKey: xaiApiKey, baseURL: 'https://api.x.ai/v1', }); - try { - return xai('grok-4-fast-non-reasoning'); - } catch (error) { - console.warn('xAI API unavailable, falling back to next provider:'); - } + return xai('grok-4-fast-non-reasoning'); } if (awsAccessKeyId && awsSecretAccessKey) { @@ -151,14 +98,16 @@ export async function getModel(requireVision: boolean = false) { }, }, }); - const model = bedrock(bedrockModelId, { + return bedrock(bedrockModelId, { additionalModelRequestFields: { top_k: 350 }, }); - return model; } - const openai = createOpenAI({ - apiKey: openaiApiKey, - }); + // Final fallback + if (!openaiApiKey) { + throw new Error('No model providers are configured. Please set at least one API key.'); + } + + const openai = createOpenAI({ apiKey: openaiApiKey }); return openai('gpt-4o'); } From 55dabf88fe4b137630d815182572cc2f28bb12a8 Mon Sep 17 00:00:00 2001 From: EreQ Date: Fri, 15 May 2026 12:24:00 +0300 Subject: [PATCH 3/3] Update index.ts --- lib/utils/index.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 7a1b7ded..54668cc3 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -1,3 +1,22 @@ +import { type ClassValue, clsx } from 'clsx' +import { twMerge } from 'tailwind-merge' +import { getSelectedModel } from '@/lib/actions/users' +import { createOpenAI } from '@ai-sdk/openai' +import { createGoogleGenerativeAI } from '@ai-sdk/google' +import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock' +import { createXai } from '@ai-sdk/xai'; +import { v4 as uuidv4 } from 'uuid'; +export function cn(...inputs: ClassValue[]) { +  return twMerge(clsx(inputs)) +} +export function generateUUID(): string { +  return uuidv4(); +} +/** + * Re-export generateUUID as nanoid for shorter naming and compatibility with existing code. + * Returns a UUID v4 string. + */ + export async function getModel(requireVision: boolean = false) { const selectedModel = await getSelectedModel();