From 1d6f1c66523d29c339c6e218325e0753d9294d76 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 11:52:07 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=93=9D=20CodeRabbit=20Chat:=20Impleme?= =?UTF-8?q?nt=20requested=20code=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.local.example | 5 ++-- bun.lock | 13 ---------- lib/utils/index.ts | 60 ++++++++++++++-------------------------------- package.json | 3 +-- 4 files changed, 21 insertions(+), 60 deletions(-) diff --git a/.env.local.example b/.env.local.example index cbe3c452..2762d581 100644 --- a/.env.local.example +++ b/.env.local.example @@ -17,9 +17,8 @@ NEXT_PUBLIC_COMPOSIO_USER_ID=user@example.com # NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN=your_mapbox_public_token_here # AI Provider API Keys -# Azure AI Foundry (Azure OpenAI) -AZURE_RESOURCE_NAME=your_azure_resource_name_here -AZURE_ENDPOINT=your_azure_endpoint_here +# Azure AI Foundry (OpenAI-compatible endpoint) +AZURE_ENDPOINT=https://your-resource.services.ai.azure.com/openai/v1 AZURE_API_KEY=your_azure_api_key_here AZURE_DEPLOYMENT_NAME=gpt-5.5 diff --git a/bun.lock b/bun.lock index d123cca0..f101e5d7 100644 --- a/bun.lock +++ b/bun.lock @@ -6,7 +6,6 @@ "dependencies": { "@ai-sdk/amazon-bedrock": "^1.1.6", "@ai-sdk/anthropic": "^1.2.12", - "@ai-sdk/azure": "^3.0.64", "@ai-sdk/google": "^1.2.22", "@ai-sdk/openai": "^1.3.24", "@ai-sdk/xai": "^1.2.18", @@ -112,8 +111,6 @@ "@ai-sdk/anthropic": ["@ai-sdk/anthropic@1.2.12", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-YSzjlko7JvuiyQFmI9RN1tNZdEiZxc+6xld/0tq/VkJaHpEzGAb1yiNxxvmYVcjvfu/PcvCxAAYXmTYQQ63IHQ=="], - "@ai-sdk/azure": ["@ai-sdk/azure@3.0.64", "", { "dependencies": { "@ai-sdk/openai": "3.0.63", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-jNcgI9tPzpuPJhAvB6twCiH9UGOOBFRPxFWOuDI4qts347q/+iFtc+AvkrKU/JsbSSwGeeW4qslQRri4SmWipg=="], - "@ai-sdk/google": ["@ai-sdk/google@1.2.22", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-Ppxu3DIieF1G9pyQ5O1Z646GYR0gkC57YdBqXJ82qvCdhEhZHu0TWhmnOoeIWe2olSbuDeoOY+MfJrW8dzS3Hw=="], "@ai-sdk/openai": ["@ai-sdk/openai@1.3.24", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-GYXnGJTHRTZc4gJMSmFRgEQudjqd4PUN0ZjQhPwOAYH1yOAvQoG/Ikqs+HyISRbLPCrhbZnPKCNHuRU4OfpW0Q=="], @@ -658,8 +655,6 @@ "@so-ric/colorspace": ["@so-ric/colorspace@1.1.6", "", { "dependencies": { "color": "^5.0.2", "text-hex": "1.0.x" } }, "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw=="], - "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], - "@supabase/auth-js": ["@supabase/auth-js@2.90.1", "", { "dependencies": { "tslib": "2.8.1" } }, "sha512-vxb66dgo6h3yyPbR06735Ps+dK3hj0JwS8w9fdQPVZQmocSTlKUW5MfxSy99mN0XqCCuLMQ3jCEiIIUU23e9ng=="], "@supabase/functions-js": ["@supabase/functions-js@2.90.1", "", { "dependencies": { "tslib": "2.8.1" } }, "sha512-x9mV9dF1Lam9qL3zlpP6mSM5C9iqMPtF5B/tU1Jj/F0ufX5mjDf9ghVBaErVxmrQJRL4+iMKWKY2GnODkpS8tw=="], @@ -2554,12 +2549,6 @@ "@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="], - "@ai-sdk/azure/@ai-sdk/openai": ["@ai-sdk/openai@3.0.63", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-4yY/m8a57MNNVoJCsXuNblKf6BO4yuAuLKRX4tzSNffBEBSp1FlcWdPE0Z4FkqUeS0AJhYSSqp0GIiA/cIcDNA=="], - - "@ai-sdk/azure/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], - - "@ai-sdk/azure/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], - "@ai-sdk/google/@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="], "@ai-sdk/google/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="], @@ -2792,8 +2781,6 @@ "yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "@ai-sdk/azure/@ai-sdk/provider-utils/eventsource-parser": ["eventsource-parser@3.0.8", "", {}, "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ=="], - "@ai-sdk/react/@ai-sdk/provider-utils/@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="], "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 81220a29..6853dab2 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -5,7 +5,6 @@ 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 { createAzure } from '@ai-sdk/azure'; import { v4 as uuidv4 } from 'uuid'; import { LanguageModel } from 'ai' @@ -33,7 +32,6 @@ export async function getModel(requireVision: boolean = false): Promise Gemini -> Grok -> Bedrock -> OpenAI - if (azureEndpoint && azureApiKey) { - const azureOpenAI = createOpenAI({ - baseURL: azureEndpoint, - apiKey: azureApiKey, - }); - try { - return azureOpenAI(azureDeploymentName); - } catch (error) { - console.warn('Azure OpenAI API (via endpoint) unavailable, falling back to next provider:', error); - } - } - - if (azureResourceName && azureApiKey) { - const azure = createAzure({ - resourceName: azureResourceName, - apiKey: azureApiKey, - }); - try { - return azure(azureDeploymentName) as unknown as LanguageModel; - } catch (error) { - console.warn('Azure OpenAI API (via resource) unavailable, falling back to next provider:', error); - } - } - + // Default behavior: Gemini -> Grok -> Azure -> Bedrock -> OpenAI if (gemini3ProApiKey) { const google = createGoogleGenerativeAI({ apiKey: gemini3ProApiKey, @@ -160,6 +124,18 @@ export async function getModel(requireVision: boolean = false): Promise Date: Thu, 14 May 2026 12:21:18 +0300 Subject: [PATCH 2/2] Update index.ts --- lib/utils/index.ts | 184 +++++++++++++++++++-------------------------- 1 file changed, 76 insertions(+), 108 deletions(-) diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 6853dab2..29e5c616 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -4,8 +4,8 @@ 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'; +import { createXai } from '@ai-sdk/xai' +import { v4 as uuidv4 } from 'uuid' import { LanguageModel } from 'ai' export function cn(...inputs: ClassValue[]) { @@ -13,127 +13,97 @@ export function cn(...inputs: ClassValue[]) { } export function generateUUID(): string { - return uuidv4(); + return uuidv4() } +export { generateUUID as nanoid } + /** - * Re-export generateUUID as nanoid for shorter naming and compatibility with existing code. - * Returns a UUID v4 string. + * Toggle whether Azure should be the primary/default model + * Set USE_AZURE=true in your .env file to enable */ -export { generateUUID as nanoid }; +const USE_AZURE = process.env.USE_AZURE === 'true' || process.env.USE_AZURE === '1' export async function getModel(requireVision: boolean = false): Promise { - const selectedModel = await getSelectedModel(); - - const xaiApiKey = process.env.XAI_API_KEY; - const gemini3ProApiKey = process.env.GEMINI_3_PRO_API_KEY; - const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID; - const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; - const awsRegion = process.env.AWS_REGION; - const bedrockModelId = process.env.BEDROCK_MODEL_ID || 'anthropic.claude-3-5-sonnet-20241022-v2:0'; - const openaiApiKey = process.env.OPENAI_API_KEY; - const azureApiKey = process.env.AZURE_API_KEY; - const azureEndpoint = process.env.AZURE_ENDPOINT; - const azureDeploymentName = process.env.AZURE_DEPLOYMENT_NAME || 'gpt-5.5'; + const selectedModel = await getSelectedModel() + + // Environment variables + const xaiApiKey = process.env.XAI_API_KEY + const gemini3ProApiKey = process.env.GEMINI_3_PRO_API_KEY + const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID + const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY + const awsRegion = process.env.AWS_REGION + const bedrockModelId = process.env.BEDROCK_MODEL_ID || 'anthropic.claude-3-5-sonnet-20241022-v2:0' + const openaiApiKey = process.env.OPENAI_API_KEY + const azureApiKey = process.env.AZURE_API_KEY + const azureEndpoint = process.env.AZURE_ENDPOINT + const azureDeploymentName = process.env.AZURE_DEPLOYMENT_NAME || 'gpt-5.5' + // ====================== USER SELECTED MODEL ====================== if (selectedModel) { switch (selectedModel) { case 'Grok 4.2': - if (xaiApiKey) { - const xai = createXai({ - 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.'); - } - } else { - console.error('User selected "Grok 4.2" but XAI_API_KEY is not set.'); - throw new Error('Selected model is not configured.'); - } + if (!xaiApiKey) throw new Error('Grok 4.2 selected but XAI_API_KEY not configured') + return createXai({ apiKey: xaiApiKey, baseURL: 'https://api.x.ai/v1' })('grok-4-fast-non-reasoning') + 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.'); - } - } 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.'); - } + if (!gemini3ProApiKey) throw new Error('Gemini 3.1 Pro selected but GEMINI_3_PRO_API_KEY not configured') + return createGoogleGenerativeAI({ apiKey: gemini3ProApiKey })('gemini-3.1-pro-preview') + case 'GPT-5.1': - if (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.'); - } + if (!openaiApiKey) throw new Error('GPT-5.1 selected but OPENAI_API_KEY not configured') + return createOpenAI({ apiKey: openaiApiKey })('gpt-4o') + case 'Azure GPT 5.5': - if (azureEndpoint && azureApiKey) { - const azureOpenai = createOpenAI({ - baseURL: azureEndpoint, - apiKey: azureApiKey, - compatibility: 'compatible', - }); - try { - return azureOpenai(azureDeploymentName); - } catch (error) { - console.error('Selected model "Azure GPT 5.5" is configured but failed to initialize.', error); - throw new Error('Failed to initialize selected model.'); - } - } else { - console.error('User selected "Azure GPT 5.5" but AZURE_ENDPOINT and AZURE_API_KEY are not set.'); - throw new Error('Selected model is not configured.'); + if (!azureEndpoint || !azureApiKey) { + throw new Error('Azure GPT 5.5 selected but AZURE_ENDPOINT or AZURE_API_KEY not configured') } + return createOpenAI({ + baseURL: azureEndpoint, + apiKey: azureApiKey, + compatibility: 'compatible', + })(azureDeploymentName) + + default: + console.warn(`Unknown selected model: ${selectedModel}, falling back to default`) } } - // Default behavior: Gemini -> Grok -> Azure -> Bedrock -> OpenAI - 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); + // ====================== DEFAULT FALLBACK LOGIC ====================== + + // Azure is primary when toggle is enabled + if (USE_AZURE) { + if (azureEndpoint && azureApiKey) { + try { + const azureOpenai = createOpenAI({ + baseURL: azureEndpoint, + apiKey: azureApiKey, + compatibility: 'compatible', + }) + return azureOpenai(azureDeploymentName) + } catch (error) { + console.warn('Azure unavailable, falling back to other providers:', error) + } + } else { + console.warn('USE_AZURE=true but Azure credentials not configured. Falling back...') } } - if (xaiApiKey) { - const xai = createXai({ - apiKey: xaiApiKey, - baseURL: 'https://api.x.ai/v1', - }); + // Fallback order when Azure is disabled or unavailable: Gemini → Grok → Bedrock → OpenAI + if (gemini3ProApiKey) { try { - return xai('grok-4-fast-non-reasoning'); + return createGoogleGenerativeAI({ apiKey: gemini3ProApiKey })('gemini-3.1-pro-preview') } catch (error) { - console.warn('xAI API unavailable, falling back to next provider:'); + console.warn('Gemini unavailable:', error) } } - if (azureEndpoint && azureApiKey) { - const azureOpenai = createOpenAI({ - baseURL: azureEndpoint, - apiKey: azureApiKey, - compatibility: 'compatible', - }); + if (xaiApiKey) { try { - return azureOpenai(azureDeploymentName); + return createXai({ apiKey: xaiApiKey, baseURL: 'https://api.x.ai/v1' })('grok-4-fast-non-reasoning') } catch (error) { - console.warn('Azure OpenAI API unavailable, falling back to next provider:', error); + console.warn('xAI unavailable:', error) } } @@ -141,20 +111,18 @@ export async function getModel(requireVision: boolean = false): Promise