Skip to content

Commit 7956706

Browse files
committed
remove regex based checks'
1 parent 87257dc commit 7956706

4 files changed

Lines changed: 35 additions & 43 deletions

File tree

apps/sim/lib/copilot/tools/server/workflow/edit-workflow/validation.test.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,25 @@ describe('validateInputsForBlock', () => {
172172
expect(result.validInputs.model).toBe('mistralai/Mistral-7B-Instruct-v0.3')
173173
})
174174

175-
it('accepts date-suffixed variants of known Anthropic ids', () => {
175+
it('rejects a bare Ollama-style tag without the provider prefix', () => {
176+
const result = validateInputsForBlock('agent', { model: 'llama3.1:8b' }, 'agent-1')
177+
178+
expect(result.validInputs.model).toBeUndefined()
179+
expect(result.errors).toHaveLength(1)
180+
expect(result.errors[0]?.error).toContain('Unknown model id')
181+
expect(result.errors[0]?.error).toContain('ollama/')
182+
})
183+
184+
it('rejects date-pinned ids that are not literally in the catalog', () => {
176185
const result = validateInputsForBlock(
177186
'agent',
178187
{ model: 'claude-sonnet-4-5-20250929' },
179188
'agent-1'
180189
)
181190

182-
expect(result.errors).toHaveLength(0)
183-
expect(result.validInputs.model).toBe('claude-sonnet-4-5-20250929')
191+
expect(result.validInputs.model).toBeUndefined()
192+
expect(result.errors).toHaveLength(1)
193+
expect(result.errors[0]?.error).toContain('Unknown model id')
184194
})
185195

186196
it('trims whitespace around catalog model ids and stores the trimmed value', () => {

apps/sim/lib/copilot/tools/server/workflow/edit-workflow/validation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ export function validateValueForSubBlockType(
375375
blockType,
376376
field: fieldName,
377377
value,
378-
error: `Unknown model id "${trimmed}" for block "${blockType}". Read components/blocks/${blockType}.json (the model.options array) for valid ids; prefer entries with recommended: true and avoid deprecated: true.${suggestionText}`,
378+
error: `Unknown model id "${trimmed}" for block "${blockType}". Read components/blocks/${blockType}.json (the model.options array) for valid ids; prefer entries with recommended: true and avoid deprecated: true. For user-configured models (Ollama, vLLM, OpenRouter, Fireworks), prefix the id with the provider slash, e.g. "ollama/llama3.1:8b".${suggestionText}`,
379379
},
380380
}
381381
}

apps/sim/lib/copilot/vfs/serializers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { getCopilotToolDescription } from '@/lib/copilot/tools/descriptions'
22
import { isHosted } from '@/lib/core/config/feature-flags'
33
import { isSubBlockHidden } from '@/lib/workflows/subblocks/visibility'
44
import type { BlockConfig, SubBlockConfig } from '@/blocks/types'
5-
import { PROVIDER_DEFINITIONS } from '@/providers/models'
5+
import { DYNAMIC_MODEL_PROVIDERS, PROVIDER_DEFINITIONS } from '@/providers/models'
66
import type { ToolConfig } from '@/tools/types'
77

88
/**
@@ -342,8 +342,8 @@ const RESELLER_BASE_PREFIX: Record<string, string> = {
342342
}
343343

344344
const DYNAMIC_PROVIDERS_NOTE = {
345-
note: 'The options array above lists Sim\'s static provider catalog. These four providers also accept user-configured models that are NOT enumerated here: the user may have additional ids available at runtime. Any model id prefixed with one of the slashes below is accepted by the server, as is any bare id that does not match a static provider pattern (typically a local Ollama tag like "llama3.1:8b"). The UI dropdown shows the user\'s actual installed models; if the user references one by name, use that id verbatim.',
346-
prefixes: ['ollama/', 'vllm/', 'openrouter/', 'fireworks/'],
345+
note: 'The options array above lists Sim\'s static provider catalog. These providers also accept user-configured models that are NOT enumerated here: the user may have additional ids available at runtime. Any model id prefixed with one of the slashes below is accepted by the server, as is any bare id that does not match a static provider pattern (typically a local Ollama tag like "llama3.1:8b"). The UI dropdown shows the user\'s actual installed models; if the user references one by name, use that id verbatim.',
346+
prefixes: DYNAMIC_MODEL_PROVIDERS.map((p) => `${p}/`),
347347
} as const
348348

349349
function getStaticModelOptionsForVFS(): StaticModelOption[] {

apps/sim/providers/models.ts

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2711,32 +2711,32 @@ export function getProviderModels(providerId: string): string[] {
27112711
return PROVIDER_DEFINITIONS[providerId]?.models.map((m) => m.id) || []
27122712
}
27132713

2714-
const DYNAMIC_MODEL_PROVIDERS = ['ollama', 'vllm', 'openrouter', 'fireworks'] as const
2714+
export const DYNAMIC_MODEL_PROVIDERS = ['ollama', 'vllm', 'openrouter', 'fireworks'] as const
2715+
2716+
export function getAllStaticModelIds(): string[] {
2717+
const ids: string[] = []
2718+
for (const [providerId, provider] of Object.entries(PROVIDER_DEFINITIONS)) {
2719+
if ((DYNAMIC_MODEL_PROVIDERS as readonly string[]).includes(providerId)) continue
2720+
for (const model of provider.models) ids.push(model.id)
2721+
}
2722+
return ids
2723+
}
2724+
2725+
const STATIC_MODEL_ID_SET = new Set(getAllStaticModelIds().map((id) => id.toLowerCase()))
27152726

27162727
export function isKnownModelId(modelId: string): boolean {
27172728
if (!modelId || typeof modelId !== 'string') return false
27182729
const trimmed = modelId.trim()
27192730
if (!trimmed) return false
2720-
const normalized = trimmed.toLowerCase()
2721-
2722-
for (const provider of Object.values(PROVIDER_DEFINITIONS)) {
2723-
for (const model of provider.models) {
2724-
const base = model.id.toLowerCase()
2725-
if (normalized === base || normalized.startsWith(`${base}-`)) return true
2726-
}
2727-
}
27282731

2729-
const dynamicPrefixes = [/^ollama\//i, /^vllm\//i, /^openrouter\//i, /^fireworks\//i]
2730-
if (dynamicPrefixes.some((re) => re.test(trimmed))) return true
2732+
if (STATIC_MODEL_ID_SET.has(trimmed.toLowerCase())) return true
27312733

2732-
for (const [providerId, provider] of Object.entries(PROVIDER_DEFINITIONS)) {
2733-
if ((DYNAMIC_MODEL_PROVIDERS as readonly string[]).includes(providerId)) continue
2734-
if (provider.modelPatterns?.some((re) => re.test(normalized))) {
2735-
return false
2736-
}
2734+
const lowered = trimmed.toLowerCase()
2735+
for (const provider of DYNAMIC_MODEL_PROVIDERS) {
2736+
if (lowered.startsWith(`${provider}/`)) return true
27372737
}
27382738

2739-
return true
2739+
return false
27402740
}
27412741

27422742
export function getRecommendedModels(): string[] {
@@ -2750,25 +2750,7 @@ export function getRecommendedModels(): string[] {
27502750
return models
27512751
}
27522752

2753-
export function suggestModelIdsForUnknownModel(modelId: string, limit = 5): string[] {
2754-
if (!modelId || typeof modelId !== 'string') return []
2755-
const normalized = modelId.trim().toLowerCase()
2756-
if (!normalized) return []
2757-
2758-
for (const [providerId, provider] of Object.entries(PROVIDER_DEFINITIONS)) {
2759-
if ((DYNAMIC_MODEL_PROVIDERS as readonly string[]).includes(providerId)) continue
2760-
if (provider.modelPatterns?.some((re) => re.test(normalized))) {
2761-
const recommendedFirst = [...provider.models].sort((a, b) => {
2762-
if (a.deprecated && !b.deprecated) return 1
2763-
if (!a.deprecated && b.deprecated) return -1
2764-
if (a.recommended && !b.recommended) return -1
2765-
if (!a.recommended && b.recommended) return 1
2766-
return 0
2767-
})
2768-
return recommendedFirst.map((m) => m.id).slice(0, limit)
2769-
}
2770-
}
2771-
2753+
export function suggestModelIdsForUnknownModel(_modelId: string, limit = 5): string[] {
27722754
const recommended = getRecommendedModels()
27732755
if (recommended.length > 0) return recommended.slice(0, limit)
27742756

0 commit comments

Comments
 (0)