diff --git a/apps/sim/app/(landing)/models/utils.ts b/apps/sim/app/(landing)/models/utils.ts index 6f54de56b6c..0e75c76e230 100644 --- a/apps/sim/app/(landing)/models/utils.ts +++ b/apps/sim/app/(landing)/models/utils.ts @@ -483,7 +483,7 @@ const rawProviders = Object.values(PROVIDER_DEFINITIONS).map((provider) => { providerSlug, contextWindow: model.contextWindow ?? null, releaseDate: model.releaseDate ?? null, - deprecated: model.deprecated ?? false, + deprecated: !!model.sunset, pricing: model.pricing, capabilities: mergedCapabilities, capabilityTags, diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx index 8d9a4fb85e0..4794bd82128 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx @@ -66,7 +66,7 @@ import { useTablesList } from '@/hooks/queries/tables' import { useWorkflowMap } from '@/hooks/queries/workflows' import { useReactiveConditions } from '@/hooks/use-reactive-conditions' import { useSelectorDisplayName } from '@/hooks/use-selector-display-name' -import { isModelDeprecated } from '@/providers/models' +import { getModelSunsetStatus } from '@/providers/models' import { useVariablesStore } from '@/stores/variables/store' import { useSubBlockStore } from '@/stores/workflows/subblock/store' import { useWorkflowStore } from '@/stores/workflows/workflow/store' @@ -132,12 +132,23 @@ function getBlockSunset( } } - if (typeof model === 'string' && isModelDeprecated(model)) { - return { - status: 'legacy', - kind: 'model', - tooltip: `${model} is deprecated. Click to upgrade`, - prompt: `The "${name}" block uses the deprecated model "${model}". Switch it to the latest equivalent model.`, + if (typeof model === 'string') { + const modelStatus = getModelSunsetStatus(model) + if (modelStatus === 'deprecated') { + return { + status: 'deprecated', + kind: 'model', + tooltip: `${model} is no longer available. Click to switch models`, + prompt: `The "${name}" block uses "${model}", which the provider has retired — calls to it now fail. Switch it to the latest equivalent model.`, + } + } + if (modelStatus === 'legacy') { + return { + status: 'legacy', + kind: 'model', + tooltip: `${model} is a legacy model. Click to upgrade`, + prompt: `The "${name}" block uses the legacy model "${model}". Switch it to the latest equivalent model.`, + } } } diff --git a/apps/sim/blocks/utils.ts b/apps/sim/blocks/utils.ts index f740a0026bd..f0c7d11f13a 100644 --- a/apps/sim/blocks/utils.ts +++ b/apps/sim/blocks/utils.ts @@ -11,6 +11,7 @@ import type { BlockOutput, OutputFieldDefinition, SubBlockConfig } from '@/block import { getBaseModelProviders, getHostedModels, + getModelSunsetStatus, getProviderIcon, getProviderModels, orderModelIdsByReleaseDate, @@ -74,10 +75,12 @@ export function getModelOptions() { ]) ) - return allModels.map((model) => { - const icon = getProviderIcon(model) - return { label: model, id: model, ...(icon && { icon }) } - }) + return allModels + .filter((model) => getModelSunsetStatus(model) !== 'deprecated') + .map((model) => { + const icon = getProviderIcon(model) + return { label: model, id: model, ...(icon && { icon }) } + }) } /** diff --git a/apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts b/apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts index 7828f89ec98..6dbb214de80 100644 --- a/apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts +++ b/apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts @@ -782,6 +782,9 @@ function getStaticModelOptions(): { id: string; label?: string }[] { } if (provider?.models) { for (const model of provider.models) { + // Exclude retired models — the agent must not receive a model whose API + // calls fail (mirrors the user picker + VFS menu). + if (model.sunset?.status === 'deprecated') continue models.push({ id: model.id, label: model.id }) } } diff --git a/apps/sim/lib/copilot/vfs/serializers.ts b/apps/sim/lib/copilot/vfs/serializers.ts index 6e3ff25277c..2750383005e 100644 --- a/apps/sim/lib/copilot/vfs/serializers.ts +++ b/apps/sim/lib/copilot/vfs/serializers.ts @@ -453,6 +453,9 @@ function getStaticModelOptionsForVFS(): StaticModelOption[] { for (const [providerId, def] of Object.entries(PROVIDER_DEFINITIONS)) { if (dynamicProviders.has(providerId)) continue for (const model of def.models) { + // Retired models are hidden from the agent's menu (mirrors the user picker) + // so it never suggests a model whose API calls fail; legacy stays available. + if (model.sunset?.status === 'deprecated') continue const option: StaticModelOption = { id: model.id, provider: providerId, @@ -460,7 +463,7 @@ function getStaticModelOptionsForVFS(): StaticModelOption[] { } if (model.recommended) option.recommended = true if (model.speedOptimized) option.speedOptimized = true - if (model.deprecated) option.deprecated = true + if (model.sunset) option.deprecated = true models.push(option) } } diff --git a/apps/sim/providers/bedrock/utils.ts b/apps/sim/providers/bedrock/utils.ts index a385ffd053b..82919624d09 100644 --- a/apps/sim/providers/bedrock/utils.ts +++ b/apps/sim/providers/bedrock/utils.ts @@ -89,7 +89,6 @@ export function generateToolUseId(toolName: string): string { */ const GEO_PROFILE_UNSUPPORTED_MODEL_IDS = new Set([ 'mistral.mistral-large-3-675b-instruct', - 'mistral.mistral-large-2411-v1:0', 'mistral.mistral-large-2407-v1:0', 'mistral.magistral-small-2509', 'mistral.ministral-3-14b-instruct', diff --git a/apps/sim/providers/models.test.ts b/apps/sim/providers/models.test.ts index 1df24dad98b..56eddcbeb6b 100644 --- a/apps/sim/providers/models.test.ts +++ b/apps/sim/providers/models.test.ts @@ -24,7 +24,7 @@ const DYNAMIC_PROVIDERS = new Set([ function firstDeprecatedModelId(): string | undefined { for (const [providerId, provider] of Object.entries(PROVIDER_DEFINITIONS)) { if (DYNAMIC_PROVIDERS.has(providerId)) continue - const dep = provider.models.find((m) => m.deprecated) + const dep = provider.models.find((m) => m.sunset) if (dep) return dep.id } return undefined diff --git a/apps/sim/providers/models.ts b/apps/sim/providers/models.ts index d307316520d..5f7ab3cd7ce 100644 --- a/apps/sim/providers/models.ts +++ b/apps/sim/providers/models.ts @@ -69,7 +69,15 @@ interface ModelDefinition { releaseDate?: string recommended?: boolean speedOptimized?: boolean - deprecated?: boolean + /** + * Post-availability lifecycle, mirroring `BlockConfig.sunset`. `legacy` — + * superseded but still callable (amber); `deprecated` — the provider retired + * it and API calls now fail (red). `deprecated` models are hidden from pickers + * but stay {@link isKnownModelId} so existing pinned workflows still validate. + */ + sunset?: { + status: 'legacy' | 'deprecated' + } } export interface ProviderDefinition { @@ -284,7 +292,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1047576, releaseDate: '2025-04-14', - deprecated: true, + sunset: { status: 'legacy' }, }, // GPT-5.6 family { @@ -615,7 +623,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2025-08-07', - deprecated: true, + sunset: { status: 'legacy' }, }, // o-series reasoning models { @@ -634,7 +642,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 200000, releaseDate: '2025-04-16', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'o3-pro', @@ -665,7 +673,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 200000, releaseDate: '2025-04-16', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'o3-mini', @@ -683,7 +691,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 200000, releaseDate: '2025-01-31', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'o1', @@ -701,7 +709,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 200000, releaseDate: '2024-12-17', - deprecated: true, + sunset: { status: 'legacy' }, }, // Legacy { @@ -718,7 +726,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2024-05-13', - deprecated: true, + sunset: { status: 'legacy' }, }, ], }, @@ -891,7 +899,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 200000, releaseDate: '2025-08-05', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'claude-opus-4-0', @@ -911,7 +919,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 200000, releaseDate: '2025-05-22', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'claude-sonnet-4-5', @@ -951,7 +959,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 200000, releaseDate: '2025-05-22', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'claude-haiku-4-5', @@ -988,7 +996,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 200000, releaseDate: '2024-03-13', - deprecated: true, + sunset: { status: 'deprecated' }, }, ], }, @@ -1018,7 +1026,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2024-11-20', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'azure/gpt-5.4', @@ -1398,7 +1406,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 200000, releaseDate: '2025-08-05', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'azure-anthropic/claude-haiku-4-5', @@ -1585,7 +1593,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1048576, releaseDate: '2025-02-05', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'gemini-2.0-flash-lite', @@ -1600,7 +1608,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1048576, releaseDate: '2025-02-25', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'deep-research-pro-preview-12-2025', @@ -1708,7 +1716,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2025-11-18', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'vertex/gemini-3-flash-preview', @@ -1800,7 +1808,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1048576, releaseDate: '2025-02-05', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'vertex/gemini-2.0-flash-lite', @@ -1814,7 +1822,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1048576, releaseDate: '2025-02-25', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'vertex/deep-research-pro-preview-12-2025', @@ -1899,7 +1907,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2024-12-26', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'deepseek-r1', @@ -1912,7 +1920,7 @@ export const PROVIDER_DEFINITIONS: Record = { capabilities: {}, contextWindow: 128000, releaseDate: '2025-01-20', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'deepseek-reasoner', @@ -1982,7 +1990,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2025-07-09', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'grok-4-0709', @@ -1997,7 +2005,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2025-07-09', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'grok-4-1-fast-reasoning', @@ -2012,7 +2020,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2025-11-19', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'grok-4-1-fast-non-reasoning', @@ -2027,7 +2035,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2025-11-19', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'grok-4-fast-reasoning', @@ -2042,7 +2050,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2025-09-19', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'grok-4-fast-non-reasoning', @@ -2057,7 +2065,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2025-09-19', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'grok-code-fast-1', @@ -2072,7 +2080,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 256000, releaseDate: '2025-08-28', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'grok-4.20-0309-reasoning', @@ -2129,7 +2137,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2025-02-17', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'grok-3-fast-latest', @@ -2144,7 +2152,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2025-02-17', - deprecated: true, + sunset: { status: 'deprecated' }, }, ], }, @@ -2184,7 +2192,7 @@ export const PROVIDER_DEFINITIONS: Record = { capabilities: {}, contextWindow: 32768, releaseDate: '2024-08-27', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'cerebras/qwen-3-235b-a22b-instruct-2507', @@ -2196,7 +2204,7 @@ export const PROVIDER_DEFINITIONS: Record = { capabilities: {}, contextWindow: 131072, releaseDate: '2025-07-29', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'cerebras/zai-glm-4.7', @@ -2297,7 +2305,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 131072, releaseDate: '2025-04-29', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'groq/qwen/qwen3.6-27b', @@ -2351,7 +2359,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 131072, releaseDate: '2025-04-05', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'groq/moonshotai/kimi-k2-instruct-0905', @@ -2363,7 +2371,7 @@ export const PROVIDER_DEFINITIONS: Record = { capabilities: {}, contextWindow: 262144, releaseDate: '2025-09-05', - deprecated: true, + sunset: { status: 'deprecated' }, }, ], }, @@ -2940,7 +2948,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2024-11-18', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'magistral-medium-latest', @@ -2980,7 +2988,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2025-09-18', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'magistral-small-2509', @@ -2994,7 +3002,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2025-09-18', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'mistral-medium-latest', @@ -3073,7 +3081,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2025-06-20', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'open-mistral-nemo', @@ -3139,7 +3147,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 256000, releaseDate: '2025-12-09', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'devstral-small-2507', @@ -3153,7 +3161,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2025-07-10', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'devstral-medium-2507', @@ -3167,7 +3175,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2025-07-10', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'ministral-14b-latest', @@ -3347,21 +3355,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 200000, releaseDate: '2025-08-05', - deprecated: true, - }, - { - id: 'bedrock/amazon.nova-2-pro-v1:0', - pricing: { - input: 1.375, - output: 11.0, - updatedAt: '2026-06-11', - }, - capabilities: { - temperature: { min: 0, max: 1 }, - }, - contextWindow: 1000000, - releaseDate: '2025-12-02', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'bedrock/amazon.nova-2-lite-v1:0', @@ -3391,7 +3385,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2025-04-30', - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'bedrock/amazon.nova-pro-v1:0', @@ -3493,7 +3487,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2024-09-25', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'bedrock/meta.llama3-2-11b-instruct-v1:0', @@ -3507,7 +3501,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2024-09-25', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'bedrock/meta.llama3-2-3b-instruct-v1:0', @@ -3521,7 +3515,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2024-09-25', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'bedrock/meta.llama3-2-1b-instruct-v1:0', @@ -3535,7 +3529,7 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 128000, releaseDate: '2024-09-25', - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'bedrock/meta.llama3-1-405b-instruct-v1:0', @@ -3548,7 +3542,7 @@ export const PROVIDER_DEFINITIONS: Record = { temperature: { min: 0, max: 1 }, }, contextWindow: 128000, - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'bedrock/meta.llama3-1-70b-instruct-v1:0', @@ -3592,19 +3586,6 @@ export const PROVIDER_DEFINITIONS: Record = { contextWindow: 256000, releaseDate: '2025-12-02', }, - { - id: 'bedrock/mistral.mistral-large-2411-v1:0', - pricing: { - input: 2.0, - output: 6.0, - updatedAt: '2026-04-01', - }, - capabilities: { - temperature: { min: 0, max: 1 }, - }, - contextWindow: 128000, - deprecated: true, - }, { id: 'bedrock/mistral.mistral-large-2407-v1:0', pricing: { @@ -3616,7 +3597,7 @@ export const PROVIDER_DEFINITIONS: Record = { temperature: { min: 0, max: 1 }, }, contextWindow: 128000, - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'bedrock/mistral.pixtral-large-2502-v1:0', @@ -3710,7 +3691,7 @@ export const PROVIDER_DEFINITIONS: Record = { temperature: { min: 0, max: 1 }, }, contextWindow: 32000, - deprecated: true, + sunset: { status: 'deprecated' }, }, { id: 'bedrock/cohere.command-r-plus-v1:0', @@ -3723,7 +3704,7 @@ export const PROVIDER_DEFINITIONS: Record = { temperature: { min: 0, max: 1 }, }, contextWindow: 128000, - deprecated: true, + sunset: { status: 'legacy' }, }, { id: 'bedrock/cohere.command-r-v1:0', @@ -3736,7 +3717,7 @@ export const PROVIDER_DEFINITIONS: Record = { temperature: { min: 0, max: 1 }, }, contextWindow: 128000, - deprecated: true, + sunset: { status: 'legacy' }, }, ], }, @@ -3850,20 +3831,29 @@ export function isKnownModelId(modelId: string): boolean { return false } -const DEPRECATED_STATIC_MODEL_IDS = new Set() +const MODEL_SUNSET_STATUS = new Map() for (const [providerId, provider] of Object.entries(PROVIDER_DEFINITIONS)) { if ((DYNAMIC_MODEL_PROVIDERS as readonly string[]).includes(providerId)) continue for (const model of provider.models) { - if (model.deprecated) DEPRECATED_STATIC_MODEL_IDS.add(model.id.toLowerCase()) + if (model.sunset) MODEL_SUNSET_STATUS.set(model.id.toLowerCase(), model.sunset.status) } } /** - * Whether a stored model id is a deprecated static-catalog model. Dynamic-provider - * and unknown ids are never deprecated (they carry no static catalog entry). + * The sunset tier of a static-catalog model — `legacy` (superseded, callable) or + * `deprecated` (retired, API fails) — or `undefined` when not sunset. Mirrors + * reading `BlockConfig.sunset.status`. Dynamic-provider and unknown ids return + * `undefined` (no static catalog entry). */ +export function getModelSunsetStatus( + modelId: string | undefined | null +): 'legacy' | 'deprecated' | undefined { + return modelId ? MODEL_SUNSET_STATUS.get(modelId.toLowerCase()) : undefined +} + +/** Whether a stored model id is sunset (either tier). */ export function isModelDeprecated(modelId: string | undefined | null): boolean { - return !!modelId && DEPRECATED_STATIC_MODEL_IDS.has(modelId.toLowerCase()) + return getModelSunsetStatus(modelId) !== undefined } function getRecommendedModels(): string[] {