From 44bffb9700210d130d4593ba6418ff1d02c6c6e0 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 08:54:40 +0000 Subject: [PATCH 1/5] feat: add support for GPT-5.5 via Azure Foundry - Added GPT-5.5 to ModelSelectionForm with premium badge and description. - Implemented GPT-5.5 initialization in getModel using Azure OpenAI provider. - Configured AZURE_ENDPOINT, AZURE_API_KEY, and AZURE_DEPLOYMENT_NAME environment variables. - Updated .env.local.example with new Azure configuration. Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com> --- .env.local.example | 6 ++++++ .../components/model-selection-form.tsx | 8 ++++++++ lib/utils/index.ts | 19 +++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/.env.local.example b/.env.local.example index e52eec0c..956b921d 100644 --- a/.env.local.example +++ b/.env.local.example @@ -17,6 +17,12 @@ NEXT_PUBLIC_COMPOSIO_USER_ID=user@example.com # NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN=your_mapbox_public_token_here # AI Provider API Keys +# GPT-5.5 (Azure Foundry) +# AZURE_ENDPOINT should be the full V1 endpoint, e.g. https://your-resource.services.ai.azure.com/openai/v1 +AZURE_ENDPOINT=your_azure_endpoint_here +AZURE_API_KEY=your_azure_api_key_here +AZURE_DEPLOYMENT_NAME=gpt-5.5 + # Gemini 3.1 Pro (Google Generative AI) GEMINI_3_PRO_API_KEY=your_gemini_3_pro_api_key_here diff --git a/components/settings/components/model-selection-form.tsx b/components/settings/components/model-selection-form.tsx index bc6164ba..9abb9676 100644 --- a/components/settings/components/model-selection-form.tsx +++ b/components/settings/components/model-selection-form.tsx @@ -58,6 +58,14 @@ const models = [ badge: "Expert", badgeVariant: "outline" as const, }, + { + id: "GPT-5.5", + name: "GPT-5.5", + description: "The next generation of OpenAI models, exclusively via Azure Foundry, delivering superior reasoning and efficiency.", + icon: Cpu, + badge: "Premium", + badgeVariant: "default" as const, + }, ]; export function ModelSelectionForm({ form }: ModelSelectionFormProps) { diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 15565281..018867f1 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -31,6 +31,9 @@ export async function getModel(requireVision: boolean = false) { 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 azureEndpoint = process.env.AZURE_ENDPOINT; + const azureApiKey = process.env.AZURE_API_KEY; + const azureDeploymentName = process.env.AZURE_DEPLOYMENT_NAME || 'gpt-5.5'; if (selectedModel) { switch (selectedModel) { @@ -76,6 +79,22 @@ export async function getModel(requireVision: boolean = false) { 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.'); + } + } 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.'); + } } } From 48ec6037f5608e6fe3cca38d4b7d9aaa5cf00711 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 09:10:52 +0000 Subject: [PATCH 2/5] feat: prioritize Azure GPT-5.5 as default model provider - Moved Azure (GPT-5.5) to be the first option in the default fallback chain in getModel. - Maintained support for selecting GPT-5.5 explicitly via UI settings. Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com> --- lib/utils/index.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 018867f1..fbff2de2 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -98,7 +98,19 @@ export async function getModel(requireVision: boolean = false) { } } - // Default behavior: Gemini -> Grok -> Bedrock -> OpenAI + // Default behavior: Azure -> Gemini -> Grok -> Bedrock -> OpenAI + if (azureApiKey && azureEndpoint) { + const azure = createOpenAI({ + baseURL: azureEndpoint, + apiKey: azureApiKey, + }); + try { + return azure(azureDeploymentName); + } catch (error) { + console.warn('Azure GPT-5.5 unavailable, falling back to next provider:', error); + } + } + if (gemini3ProApiKey) { const google = createGoogleGenerativeAI({ apiKey: gemini3ProApiKey, From 9b843244e03dfc9883f3421cc361a438f0dafc6e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 09:32:37 +0000 Subject: [PATCH 3/5] feat: finalize GPT-5.5 support and refactor getModel - Integrated GPT-5.5 via Azure Foundry with premium branding. - Refactored getModel in lib/utils/index.ts for better clarity and robust error handling. - Set Azure (GPT-5.5) as the primary provider in the fallback chain. - Added comprehensive Azure AI configuration to .env.local.example. Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com> --- lib/utils/index.ts | 79 +++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 50 deletions(-) diff --git a/lib/utils/index.ts b/lib/utils/index.ts index fbff2de2..33a2b057 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -43,83 +43,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: Azure -> Gemini -> Grok -> Bedrock -> OpenAI + // === Default fallback order: Azure → Gemini → Grok → Bedrock → OpenAI === if (azureApiKey && azureEndpoint) { const azure = createOpenAI({ baseURL: azureEndpoint, apiKey: azureApiKey, }); - try { - return azure(azureDeploymentName); - } catch (error) { - console.warn('Azure GPT-5.5 unavailable, falling back to next provider:', error); - } + 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) { @@ -127,11 +108,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) { @@ -144,14 +121,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 133acf8467a19c4b4e7b833e037a074a87fb561a Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 10:23:45 +0000 Subject: [PATCH 4/5] feat: finalize GPT-5.5 support with Azure priority and logic cleanup - Refactored getModel in lib/utils/index.ts for better readability and robust error handling. - Established Azure AI Foundry (GPT-5.5) as the primary provider in the default fallback chain. - Integrated GPT-5.5 into the model selection UI with appropriate metadata. - Updated .env.local.example with necessary Azure configuration. - Removed redundant try-catch blocks and debug artifacts. Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com> From 53d908859e8f7c55fd850f63771d7cd4ae8dbb63 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 11:05:19 +0000 Subject: [PATCH 5/5] Add GPT-5.5 support via Azure Foundry and fix Next.js 15 async issues - Added GPT-5.5 to the ModelSelectionForm UI. - Created lib/utils/model.ts and refactored getModel to support Azure Foundry. - Prioritized Azure in the model fallback chain. - Fixed Next.js 15 async cookies issue in lib/auth/get-current-user.ts. - Updated all agent import paths for getModel. - Updated .env.local.example with Azure configuration variables. Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com> --- lib/actions/suggest.ts | 2 +- lib/agents/inquire.tsx | 2 +- lib/agents/query-suggestor.tsx | 2 +- lib/agents/researcher.tsx | 2 +- lib/agents/resolution-search.tsx | 2 +- lib/agents/task-manager.tsx | 2 +- lib/agents/writer.tsx | 2 +- lib/auth/get-current-user.ts | 14 ++-- lib/utils/index.ts | 119 ------------------------------- lib/utils/model.ts | 119 +++++++++++++++++++++++++++++++ mapbox_mcp/hooks.ts | 2 +- 11 files changed, 133 insertions(+), 135 deletions(-) create mode 100644 lib/utils/model.ts diff --git a/lib/actions/suggest.ts b/lib/actions/suggest.ts index 8555461c..6bcd5342 100644 --- a/lib/actions/suggest.ts +++ b/lib/actions/suggest.ts @@ -3,7 +3,7 @@ import { createStreamableUI, createStreamableValue } from 'ai/rsc' import { CoreMessage, LanguageModel, streamObject } from 'ai' import { PartialRelated, relatedSchema } from '@/lib/schema/related' -import { getModel } from '../utils' +import { getModel } from '../utils/model' import { MapData } from '@/components/map/map-data-context' export async function getSuggestions( diff --git a/lib/agents/inquire.tsx b/lib/agents/inquire.tsx index 9026bbc0..16a09609 100644 --- a/lib/agents/inquire.tsx +++ b/lib/agents/inquire.tsx @@ -2,7 +2,7 @@ import { Copilot } from '@/components/copilot'; import { createStreamableUI, createStreamableValue } from 'ai/rsc'; import { CoreMessage, LanguageModel, streamObject } from 'ai'; import { PartialInquiry, inquirySchema } from '@/lib/schema/inquiry'; -import { getModel } from '../utils'; +import { getModel } from '../utils/model'; // Define a plain object type for the inquiry prop interface InquiryProp { diff --git a/lib/agents/query-suggestor.tsx b/lib/agents/query-suggestor.tsx index 7cb8e50c..76f73e8a 100644 --- a/lib/agents/query-suggestor.tsx +++ b/lib/agents/query-suggestor.tsx @@ -3,7 +3,7 @@ import { CoreMessage, LanguageModel, streamObject } from 'ai' import { PartialRelated, relatedSchema } from '@/lib/schema/related' import { Section } from '@/components/section' import SearchRelated from '@/components/search-related' -import { getModel } from '../utils' +import { getModel } from '../utils/model' interface CacheEntry { data: PartialRelated; diff --git a/lib/agents/researcher.tsx b/lib/agents/researcher.tsx index ce801af4..d8f16a2f 100644 --- a/lib/agents/researcher.tsx +++ b/lib/agents/researcher.tsx @@ -10,7 +10,7 @@ import { import { Section } from '@/components/section' import { BotMessage } from '@/components/message' import { getTools } from './tools' -import { getModel } from '../utils' +import { getModel } from '../utils/model' import { MapProvider } from '@/lib/store/settings' import { DrawnFeature } from './resolution-search' diff --git a/lib/agents/resolution-search.tsx b/lib/agents/resolution-search.tsx index d456fe49..14f9690c 100644 --- a/lib/agents/resolution-search.tsx +++ b/lib/agents/resolution-search.tsx @@ -1,5 +1,5 @@ import { CoreMessage, streamObject } from 'ai' -import { getModel } from '@/lib/utils' +import { getModel } from '@/lib/utils/model' import { z } from 'zod' import { tavily } from '@tavily/core' diff --git a/lib/agents/task-manager.tsx b/lib/agents/task-manager.tsx index 90a72b67..96dbfba5 100644 --- a/lib/agents/task-manager.tsx +++ b/lib/agents/task-manager.tsx @@ -1,6 +1,6 @@ import { CoreMessage, generateObject, LanguageModel } from 'ai' import { nextActionSchema } from '../schema/next-action' -import { getModel } from '../utils' +import { getModel } from '../utils/model' // Decide whether inquiry is required for the user input export async function taskManager(messages: CoreMessage[]) { diff --git a/lib/agents/writer.tsx b/lib/agents/writer.tsx index f4e4d0ac..a6af442b 100644 --- a/lib/agents/writer.tsx +++ b/lib/agents/writer.tsx @@ -2,7 +2,7 @@ import { createStreamableUI, createStreamableValue } from 'ai/rsc' import { CoreMessage, LanguageModel, streamText as nonexperimental_streamText } from 'ai' import { Section } from '@/components/section' import { BotMessage } from '@/components/message' -import { getModel } from '../utils' +import { getModel } from '../utils/model' export async function writer( dynamicSystemPrompt: string, // New parameter diff --git a/lib/auth/get-current-user.ts b/lib/auth/get-current-user.ts index 6d08ba09..764b68f0 100644 --- a/lib/auth/get-current-user.ts +++ b/lib/auth/get-current-user.ts @@ -58,25 +58,23 @@ export async function getSupabaseUserAndSessionOnServer(): Promise<{ return { user: null, session: null, error: new Error('Missing Supabase environment variables') }; } - const cookieStore = cookies(); + const cookieStore = await cookies(); const supabase = createServerClient(supabaseUrl, supabaseAnonKey, { cookies: { async get(name: string): Promise { - const cookie = (await cookieStore).get(name); // Use the correct get method - return cookie?.value; // Return the value or undefined + const cookie = cookieStore.get(name); + return cookie?.value; }, async set(name: string, value: string, options: CookieOptions): Promise { try { - const store = await cookieStore; - store.set({ name, value, ...options }); // Set cookie with options + cookieStore.set({ name, value, ...options }); } catch (error) { // console.warn(`[Auth] Failed to set cookie ${name}:`, error); } }, async remove(name: string, options: CookieOptions): Promise { try { - const store = await cookieStore; - store.set({ name, value: '', ...options, maxAge: 0 }); // Delete cookie by setting maxAge to 0 + cookieStore.set({ name, value: '', ...options, maxAge: 0 }); } catch (error) { // console.warn(`[Auth] Failed to delete cookie ${name}:`, error); } @@ -124,4 +122,4 @@ export async function getCurrentUserIdOnServer(): Promise { return null; } return user?.id || null; -} \ No newline at end of file +} diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 33a2b057..5733ad4b 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -1,10 +1,5 @@ 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[]) { @@ -20,117 +15,3 @@ export function generateUUID(): string { * Returns a UUID v4 string. */ export { generateUUID as nanoid }; - -export async function getModel(requireVision: boolean = false) { - 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 azureEndpoint = process.env.AZURE_ENDPOINT; - const azureApiKey = process.env.AZURE_API_KEY; - const azureDeploymentName = process.env.AZURE_DEPLOYMENT_NAME || 'gpt-5.5'; - - if (selectedModel) { - switch (selectedModel) { - case 'Grok 4.2': - if (xaiApiKey) { - const xai = createXai({ - apiKey: xaiApiKey, - baseURL: 'https://api.x.ai/v1', - }); - 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.'); - } - - case 'Gemini 3': - case 'Gemini 3.1 Pro': - if (gemini3ProApiKey) { - const google = createGoogleGenerativeAI({ - apiKey: gemini3ProApiKey, - }); - 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.'); - } - - 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.'); - } - - case 'GPT-5.5': - if (azureApiKey && azureEndpoint) { - const azure = createOpenAI({ - baseURL: azureEndpoint, - apiKey: azureApiKey, - }); - 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.'); - } - - default: - console.warn(`Unknown selected model: ${selectedModel}, falling back to default.`); - } - } - - // === 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, - }); - return google('gemini-3.1-pro-preview'); - } - - if (xaiApiKey) { - const xai = createXai({ - apiKey: xaiApiKey, - baseURL: 'https://api.x.ai/v1', - }); - return xai('grok-4-fast-non-reasoning'); - } - - if (awsAccessKeyId && awsSecretAccessKey) { - const bedrock = createAmazonBedrock({ - bedrockOptions: { - region: awsRegion, - credentials: { - accessKeyId: awsAccessKeyId, - secretAccessKey: awsSecretAccessKey, - }, - }, - }); - return bedrock(bedrockModelId, { - additionalModelRequestFields: { top_k: 350 }, - }); - } - - // 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'); -} diff --git a/lib/utils/model.ts b/lib/utils/model.ts new file mode 100644 index 00000000..b3fe7272 --- /dev/null +++ b/lib/utils/model.ts @@ -0,0 +1,119 @@ +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' + +export async function getModel(requireVision: boolean = false) { + 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 azureEndpoint = process.env.AZURE_ENDPOINT; + const azureApiKey = process.env.AZURE_API_KEY; + const azureDeploymentName = process.env.AZURE_DEPLOYMENT_NAME || 'gpt-5.5'; + + if (selectedModel) { + switch (selectedModel) { + case 'Grok 4.2': + if (xaiApiKey) { + const xai = createXai({ + apiKey: xaiApiKey, + baseURL: 'https://api.x.ai/v1', + }); + 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.'); + } + + case 'Gemini 3': + case 'Gemini 3.1 Pro': + if (gemini3ProApiKey) { + const google = createGoogleGenerativeAI({ + apiKey: gemini3ProApiKey, + }); + 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.'); + } + + 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.'); + } + + case 'GPT-5.5': + if (azureApiKey && azureEndpoint) { + const azure = createOpenAI({ + baseURL: azureEndpoint, + apiKey: azureApiKey, + }); + 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.'); + } + + default: + console.warn(`Unknown selected model: ${selectedModel}, falling back to default.`); + } + } + + // === 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, + }); + return google('gemini-3.1-pro-preview'); + } + + if (xaiApiKey) { + const xai = createXai({ + apiKey: xaiApiKey, + baseURL: 'https://api.x.ai/v1', + }); + return xai('grok-4-fast-non-reasoning'); + } + + if (awsAccessKeyId && awsSecretAccessKey) { + const bedrock = createAmazonBedrock({ + bedrockOptions: { + region: awsRegion, + credentials: { + accessKeyId: awsAccessKeyId, + secretAccessKey: awsSecretAccessKey, + }, + }, + }); + return bedrock(bedrockModelId, { + additionalModelRequestFields: { top_k: 350 }, + }); + } + + // 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'); +} diff --git a/mapbox_mcp/hooks.ts b/mapbox_mcp/hooks.ts index 797f8852..420e5e54 100644 --- a/mapbox_mcp/hooks.ts +++ b/mapbox_mcp/hooks.ts @@ -1,6 +1,6 @@ import { useState, useCallback, useRef, useEffect } from 'react'; import { generateText } from 'ai'; -import { getModel } from '@/lib/utils'; +import { getModel } from '@/lib/utils/model'; // Define Tool type locally if needed type Tool = {