Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
chore: api key validation & middleware handling for ollama models
  • Loading branch information
justserdar committed Jun 18, 2025
commit fa5a6436821c636af9aa7a11b4bc1c7e5ee6e5ef
22 changes: 17 additions & 5 deletions apps/sim/app/w/[id]/components/workflow-block/workflow-block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { parseCronToHumanReadable } from '@/lib/schedules/utils'
import { cn, formatDateTime, validateName } from '@/lib/utils'
import type { BlockConfig, SubBlockConfig } from '@/blocks/types'
import { useExecutionStore } from '@/stores/execution/store'
import { useOllamaStore } from '@/stores/ollama/store'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { mergeSubblockState } from '@/stores/workflows/utils'
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
Expand Down Expand Up @@ -279,6 +280,7 @@ export function WorkflowBlock({ id, data }: NodeProps<WorkflowBlockProps>) {
}

const isAdvancedMode = useWorkflowStore.getState().blocks[blockId]?.advancedMode ?? false
const ollamaModels = useOllamaStore.getState().models

// Filter visible blocks and those that meet their conditions
const visibleSubBlocks = subBlocks.filter((block) => {
Expand All @@ -299,15 +301,25 @@ export function WorkflowBlock({ id, data }: NodeProps<WorkflowBlockProps>) {
? stateToUse[block.condition.and.field]?.value
: undefined

// Special handling for Ollama models condition
let conditionValue = block.condition.value
if (
block.condition.field === 'model' &&
Array.isArray(conditionValue) &&
conditionValue.length === 0
) {
conditionValue = ollamaModels
}

// Check if the condition value is an array
const isValueMatch = Array.isArray(block.condition.value)
const isValueMatch = Array.isArray(conditionValue)
? fieldValue != null &&
(block.condition.not
? !block.condition.value.includes(fieldValue as string | number | boolean)
: block.condition.value.includes(fieldValue as string | number | boolean))
? !conditionValue.includes(fieldValue as string | number | boolean)
: conditionValue.includes(fieldValue as string | number | boolean))
: block.condition.not
? fieldValue !== block.condition.value
: fieldValue === block.condition.value
? fieldValue !== conditionValue
: fieldValue === conditionValue

// Check both conditions if 'and' is present
const isAndValueMatch =
Expand Down
40 changes: 6 additions & 34 deletions apps/sim/blocks/blocks/agent.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { AgentIcon } from '@/components/icons'
import { isHosted } from '@/lib/environment'
import { createLogger } from '@/lib/logs/console-logger'
import { MODELS_TEMP_RANGE_0_1, MODELS_TEMP_RANGE_0_2 } from '@/providers/model-capabilities'
import { getAllModelProviders, getBaseModelProviders } from '@/providers/utils'
Expand Down Expand Up @@ -121,39 +120,12 @@ export const AgentBlock: BlockConfig<AgentResponse> = {
placeholder: 'Enter your API key',
password: true,
connectionDroppable: false,
// Hide API key for all OpenAI and Claude models when running on hosted version
condition: isHosted
? {
field: 'model',
// Include all OpenAI models and Claude models for which we don't show the API key field
value: [
// OpenAI models
'gpt-4o',
'o1',
'o1-mini',
'o1-preview',
'o3',
'o3-preview',
'o4-mini',
'gpt-4.1',
// Claude models
'claude-sonnet-4-20250514',
'claude-opus-4-20250514',
'claude-3-7-sonnet-20250219',
'claude-3-5-sonnet-20240620',

],
not: true, // Show for all models EXCEPT those listed
}
: {
field: 'model',
// Include all Ollama models for which we don't show the API key field
value: [
// Ollama models
...useOllamaStore.getState().models,
],
not: true, // Show for all models EXCEPT those listed
}, // Show for all models in non-hosted environments
condition: {
// Hide API key for all OpenAI and Claude models when running on hosted version
field: 'model', // Include all Ollama models for which we don't show the API key field
value: useOllamaStore.getState().models,
not: true, // Show for all models EXCEPT those listed
}, // Show for all models in non-hosted environments
},
{
id: 'tools',
Expand Down
2 changes: 2 additions & 0 deletions apps/sim/lib/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export const env = createEnv({
NEXT_PUBLIC_GOOGLE_CLIENT_ID: z.string().optional(),
NEXT_PUBLIC_GOOGLE_API_KEY: z.string().optional(),
NEXT_PUBLIC_GOOGLE_PROJECT_NUMBER: z.string().optional(),
NEXT_PUBLIC_OLLAMA_URL: z.string().url().optional(),
},

// Only need to define client variables, server variables are automatically handled
Expand All @@ -123,5 +124,6 @@ export const env = createEnv({
NEXT_PUBLIC_GOOGLE_CLIENT_ID: getEnv('NEXT_PUBLIC_GOOGLE_CLIENT_ID'),
NEXT_PUBLIC_GOOGLE_API_KEY: getEnv('NEXT_PUBLIC_GOOGLE_API_KEY'),
NEXT_PUBLIC_GOOGLE_PROJECT_NUMBER: getEnv('NEXT_PUBLIC_GOOGLE_PROJECT_NUMBER'),
NEXT_PUBLIC_OLLAMA_URL: getEnv('NEXT_PUBLIC_OLLAMA_URL'),
},
})
11 changes: 3 additions & 8 deletions apps/sim/providers/ollama/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { ProviderConfig, ProviderRequest, ProviderResponse, TimeSegment } f
import type { ModelsObject } from './types'

const logger = createLogger('OllamaProvider')
const OLLAMA_HOST = env.OLLAMA_URL || 'http://localhost:11434'
const OLLAMA_HOST = env.NEXT_PUBLIC_OLLAMA_URL || 'http://localhost:11434'

export const ollamaProvider: ProviderConfig = {
id: 'ollama',
Expand All @@ -19,13 +19,9 @@ export const ollamaProvider: ProviderConfig = {

// Initialize the provider by fetching available models
async initialize() {
// Disabled too allow for client side initialization
// if (typeof window !== 'undefined') {
// logger.info('Skipping Ollama initialization on client side to avoid CORS issues')
// return
// }

const OLLAMA_HOST = env.NEXT_PUBLIC_OLLAMA_URL || 'http://localhost:11434'
try {
logger.info('Ollama host', { OLLAMA_HOST })
const response = await fetch(`${OLLAMA_HOST}/api/tags`)
if (!response.ok) {
console.log('response', response)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Avoid using console.log for debugging in production code. Use the logger instead for consistency.

Suggested change
console.log('response', response)
logger.debug('response', response)

Expand All @@ -45,7 +41,6 @@ export const ollamaProvider: ProviderConfig = {
},

executeRequest: async (request: ProviderRequest): Promise<ProviderResponse> => {
console.log(request)
logger.info('Preparing Ollama request', {
model: request.model,
hasSystemPrompt: !!request.systemPrompt,
Expand Down
7 changes: 5 additions & 2 deletions apps/sim/providers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,9 @@ export function getApiKey(provider: string, model: string, userProvidedKey?: str
// Use server key rotation for all OpenAI models and Anthropic's Claude models on the hosted platform
const isOpenAIModel = provider === 'openai'
const isClaudeModel = provider === 'anthropic'
const isOllamaModel = provider === 'ollama'

if (isHosted && (isOpenAIModel || isClaudeModel)) {
if (isHosted && (isOpenAIModel || (isClaudeModel && !isOllamaModel))) {
try {
// Import the key rotation function
const { getRotatingApiKey } = require('@/lib/utils')
Expand All @@ -496,14 +497,16 @@ export function getApiKey(provider: string, model: string, userProvidedKey?: str
if (hasUserKey) {
return userProvidedKey!
}

// Otherwise, throw an error
throw new Error(`No API key available for ${provider} ${model}`)
}
}

// For all other cases, require user-provided key
if (!hasUserKey) {
if (isOllamaModel) {
return 'ollama'
}
throw new Error(`API key is required for ${provider} ${model}`)
}

Expand Down
2 changes: 1 addition & 1 deletion docker-compose.local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ services:
- GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID:-placeholder}
- GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET:-placeholder}
- RESEND_API_KEY=${RESEND_API_KEY:-placeholder}
- OLLAMA_URL=${OLLAMA_URL:-http://localhost:11434}
- NEXT_PUBLIC_OLLAMA_URL=${NEXT_PUBLIC_OLLAMA_URL:-http://localhost:11434}
depends_on:
db:
condition: service_healthy
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ services:
- GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID:-placeholder}
- GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET:-placeholder}
- RESEND_API_KEY=${RESEND_API_KEY:-placeholder}
- OLLAMA_URL=${OLLAMA_URL:-http://localhost:11434}
- NEXT_PUBLIC_OLLAMA_URL=${NEXT_PUBLIC_OLLAMA_URL:-http://localhost:11434}
depends_on:
db:
condition: service_healthy
Expand Down