Repository: onlook-dev/onlook
File: packages/ai/src/chat/providers.ts (TypeScript)

Code before:
import { bedrock } from '@ai-sdk/amazon-bedrock';
import { createAnthropic } from '@ai-sdk/anthropic';
import { createGoogleGenerativeAI } from '@ai-sdk/google';
import { createVertexAnthropic } from '@ai-sdk/google-vertex/anthropic/edge';
import { createOpenAI } from '@ai-sdk/openai';
import {
    BEDROCK_MODEL_MAP,
    CLAUDE_MODELS,
    GEMINI_MODELS,
    OPENAI_MODELS,
    LLMProvider,
    VERTEX_MODEL_MAP,
} from '@onlook/models';
import { assertNever } from '@onlook/utility';
import { type LanguageModelV1 } from 'ai';

export async function initModel(
    provider: LLMProvider,
    model: CLAUDE_MODELS | OPENAI_MODELS | GEMINI_MODELS,
): Promise<{ model: LanguageModelV1; providerOptions: Record<string, any> }> {
    switch (provider) {
        case LLMProvider.ANTHROPIC:
            return {
                model: await getAnthropicProvider(model as CLAUDE_MODELS),
                providerOptions: { anthropic: { cacheControl: { type: 'ephemeral' } } },
            };
        case LLMProvider.BEDROCK:
            return {
                model: await getBedrockProvider(model as CLAUDE_MODELS),
                providerOptions: { bedrock: { cachePoint: { type: 'default' } } },
            };
        case LLMProvider.GOOGLE_VERTEX:
            return {
                model: await getVertexProvider(model as CLAUDE_MODELS),
                providerOptions: {},
            };
        case LLMProvider.OPENAI:
            return {
                model: await getOpenAIProvider(model as OPENAI_MODELS),
                providerOptions: { openai: { cacheControl: { type: 'ephemeral' } } },
            };
        case LLMProvider.GOOGLE:
            return {
                model: await getGoogleProvider(model as GEMINI_MODELS),

Review comment (bug):
This type definition doesn't enforce the relationship between provider and its corresponding model.
For example, this would incorrectly pass the type check:
`{ provider: LLMProvider.ANTHROPIC, model: OPENAI_MODELS }`

Suggestion : 
We should use a discriminated union with a mapping like:
```
interface ModelMapping {
  [LLMProvider.ANTHROPIC]: CLAUDE_MODELS;
  [LLMProvider.BEDROCK]: CLAUDE_MODELS;
  [LLMProvider.GOOGLE_VERTEX]: CLAUDE_MODELS;
  [LLMProvider.OPENAI]: OPENAI_MODELS;
  [LLMProvider.GOOGLE]: GEMINI_MODELS;
}

type InitialModelPayload = {
  [K in keyof ModelMapping]: {
    provider: K;
    model: ModelMapping[K];
  };
}[keyof ModelMapping];
```
Then use the type InitialModelPayload and simple Object destructuring for model and provider


Code after:
import { bedrock } from '@ai-sdk/amazon-bedrock';
import { createAnthropic } from '@ai-sdk/anthropic';
import { createGoogleGenerativeAI } from '@ai-sdk/google';
import { createVertexAnthropic } from '@ai-sdk/google-vertex/anthropic/edge';
import { createOpenAI } from '@ai-sdk/openai';
import {
    BEDROCK_MODEL_MAP,
    CLAUDE_MODELS,
    GEMINI_MODELS,
    LLMProvider,
    OPENAI_MODELS,
    VERTEX_MODEL_MAP,
    type InitialModelPayload,
} from '@onlook/models';
import { assertNever } from '@onlook/utility';
import { type LanguageModelV1 } from 'ai';

export async function initModel({
    provider,
    model,
}: InitialModelPayload): Promise<{ model: LanguageModelV1; providerOptions: Record<string, any> }> {
    switch (provider) {
        case LLMProvider.ANTHROPIC:
            return {
                model: await getAnthropicProvider(model),
                providerOptions: { anthropic: { cacheControl: { type: 'ephemeral' } } },
            };
        case LLMProvider.BEDROCK:
            return {
                model: await getBedrockProvider(model),
                providerOptions: { bedrock: { cachePoint: { type: 'default' } } },
            };
        case LLMProvider.GOOGLE_VERTEX:
            return {
                model: await getVertexProvider(model),
                providerOptions: {},
            };
        case LLMProvider.OPENAI:
            return {
                model: await getOpenAIProvider(model),
                providerOptions: { openai: { cacheControl: { type: 'ephemeral' } } },
            };
        case LLMProvider.GOOGLE_AI_STUDIO:
            return {