Skip to content

Commit 7dd6584

Browse files
committed
feat(providers): add Fireworks AI provider integration
1 parent df62502 commit 7dd6584

File tree

17 files changed

+829
-6
lines changed

17 files changed

+829
-6
lines changed

apps/sim/.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ API_ENCRYPTION_KEY=your_api_encryption_key # Use `openssl rand -hex 32` to gener
2828
# OLLAMA_URL=http://localhost:11434 # URL for local Ollama server - uncomment if using local models
2929
# VLLM_BASE_URL=http://localhost:8000 # Base URL for your self-hosted vLLM (OpenAI-compatible)
3030
# VLLM_API_KEY= # Optional bearer token if your vLLM instance requires auth
31+
# FIREWORKS_API_KEY= # Optional Fireworks AI API key for dynamic model listing
3132

3233
# Admin API (Optional - for self-hosted GitOps)
3334
# ADMIN_API_KEY= # Use `openssl rand -hex 32` to generate. Enables admin API for workflow export/import.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { createLogger } from '@sim/logger'
2+
import { type NextRequest, NextResponse } from 'next/server'
3+
import { env } from '@/lib/core/config/env'
4+
import { filterBlacklistedModels, isProviderBlacklisted } from '@/providers/utils'
5+
6+
const logger = createLogger('FireworksModelsAPI')
7+
8+
interface FireworksModel {
9+
id: string
10+
object?: string
11+
created?: number
12+
owned_by?: string
13+
}
14+
15+
interface FireworksModelsResponse {
16+
data: FireworksModel[]
17+
object?: string
18+
}
19+
20+
export interface FireworksModelInfo {
21+
id: string
22+
supportsStructuredOutputs?: boolean
23+
supportsTools?: boolean
24+
}
25+
26+
export async function GET(_request: NextRequest) {
27+
if (isProviderBlacklisted('fireworks')) {
28+
logger.info('Fireworks provider is blacklisted, returning empty models')
29+
return NextResponse.json({ models: [], modelInfo: {} })
30+
}
31+
32+
const apiKey = env.FIREWORKS_API_KEY
33+
if (!apiKey) {
34+
logger.info('No FIREWORKS_API_KEY configured, returning empty models')
35+
return NextResponse.json({ models: [], modelInfo: {} })
36+
}
37+
38+
try {
39+
const response = await fetch('https://api.fireworks.ai/inference/v1/models', {
40+
headers: {
41+
Authorization: `Bearer ${apiKey}`,
42+
'Content-Type': 'application/json',
43+
},
44+
next: { revalidate: 300 },
45+
})
46+
47+
if (!response.ok) {
48+
logger.warn('Failed to fetch Fireworks models', {
49+
status: response.status,
50+
statusText: response.statusText,
51+
})
52+
return NextResponse.json({ models: [], modelInfo: {} })
53+
}
54+
55+
const data = (await response.json()) as FireworksModelsResponse
56+
57+
const modelInfo: Record<string, FireworksModelInfo> = {}
58+
const allModels: string[] = []
59+
60+
for (const model of data.data ?? []) {
61+
const modelId = `fireworks/${model.id}`
62+
allModels.push(modelId)
63+
64+
modelInfo[modelId] = {
65+
id: modelId,
66+
supportsStructuredOutputs: true,
67+
supportsTools: true,
68+
}
69+
}
70+
71+
const uniqueModels = Array.from(new Set(allModels))
72+
const models = filterBlacklistedModels(uniqueModels)
73+
74+
logger.info('Successfully fetched Fireworks models', {
75+
count: models.length,
76+
filtered: uniqueModels.length - models.length,
77+
})
78+
79+
return NextResponse.json({ models, modelInfo })
80+
} catch (error) {
81+
logger.error('Error fetching Fireworks models', {
82+
error: error instanceof Error ? error.message : 'Unknown error',
83+
})
84+
return NextResponse.json({ models: [], modelInfo: {} })
85+
}
86+
}

apps/sim/app/workspace/[workspaceId]/providers/provider-models-loader.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useEffect } from 'react'
44
import { createLogger } from '@sim/logger'
55
import { useProviderModels } from '@/hooks/queries/providers'
66
import {
7+
updateFireworksProviderModels,
78
updateOllamaProviderModels,
89
updateOpenRouterProviderModels,
910
updateVLLMProviderModels,
@@ -35,6 +36,8 @@ function useSyncProvider(provider: ProviderName) {
3536
if (data.modelInfo) {
3637
setOpenRouterModelInfo(data.modelInfo)
3738
}
39+
} else if (provider === 'fireworks') {
40+
void updateFireworksProviderModels(data.models)
3841
}
3942
} catch (syncError) {
4043
logger.warn(`Failed to sync provider definitions for ${provider}`, syncError as Error)
@@ -55,5 +58,6 @@ export function ProviderModelsLoader() {
5558
useSyncProvider('ollama')
5659
useSyncProvider('vllm')
5760
useSyncProvider('openrouter')
61+
useSyncProvider('fireworks')
5862
return null
5963
}

apps/sim/blocks/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ export function getModelOptions() {
1717
const ollamaModels = providersState.providers.ollama.models
1818
const vllmModels = providersState.providers.vllm.models
1919
const openrouterModels = providersState.providers.openrouter.models
20+
const fireworksModels = providersState.providers.fireworks.models
2021
const allModels = Array.from(
21-
new Set([...baseModels, ...ollamaModels, ...vllmModels, ...openrouterModels])
22+
new Set([...baseModels, ...ollamaModels, ...vllmModels, ...openrouterModels, ...fireworksModels])
2223
)
2324

2425
return allModels.map((model) => {

apps/sim/components/icons.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3420,6 +3420,21 @@ export function MySQLIcon(props: SVGProps<SVGSVGElement>) {
34203420
)
34213421
}
34223422

3423+
export function FireworksIcon(props: SVGProps<SVGSVGElement>) {
3424+
return (
3425+
<svg
3426+
{...props}
3427+
fill='currentColor'
3428+
height='1em'
3429+
viewBox='0 0 24 24'
3430+
width='1em'
3431+
xmlns='http://www.w3.org/2000/svg'
3432+
>
3433+
<path d='M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.894 7.37l-2.453 4.248a.5.5 0 01-.433.25h-2.516l-1.226 2.124h3.742a.5.5 0 01.433.75l-2.453 4.248a.5.5 0 01-.866 0L9.67 14.742a.5.5 0 01.433-.75h2.516l1.226-2.124H10.1a.5.5 0 01-.433-.75l2.453-4.248a.5.5 0 01.866 0l2.453 4.248a.5.5 0 01-.433.75h-.516l1.97-3.412a.5.5 0 01.866 0l.568.914z' />
3434+
</svg>
3435+
)
3436+
}
3437+
34233438
export function OpenRouterIcon(props: SVGProps<SVGSVGElement>) {
34243439
return (
34253440
<svg

apps/sim/hooks/queries/providers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const providerEndpoints: Record<ProviderName, string> = {
99
ollama: '/api/providers/ollama/models',
1010
vllm: '/api/providers/vllm/models',
1111
openrouter: '/api/providers/openrouter/models',
12+
fireworks: '/api/providers/fireworks/models',
1213
}
1314

1415
interface ProviderModelsResponse {

apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -696,14 +696,19 @@ function resolveAuthType(
696696
/**
697697
* Gets all available models from PROVIDER_DEFINITIONS as static options.
698698
* This provides fallback data when store state is not available server-side.
699-
* Excludes dynamic providers (ollama, vllm, openrouter) which require runtime fetching.
699+
* Excludes dynamic providers (ollama, vllm, openrouter, fireworks) which require runtime fetching.
700700
*/
701701
function getStaticModelOptions(): { id: string; label?: string }[] {
702702
const models: { id: string; label?: string }[] = []
703703

704704
for (const provider of Object.values(PROVIDER_DEFINITIONS)) {
705705
// Skip providers with dynamic/fetched models
706-
if (provider.id === 'ollama' || provider.id === 'vllm' || provider.id === 'openrouter') {
706+
if (
707+
provider.id === 'ollama' ||
708+
provider.id === 'vllm' ||
709+
provider.id === 'openrouter' ||
710+
provider.id === 'fireworks'
711+
) {
707712
continue
708713
}
709714
if (provider?.models) {
@@ -737,6 +742,7 @@ function callOptionsWithFallback(
737742
ollama: { models: [] },
738743
vllm: { models: [] },
739744
openrouter: { models: [] },
745+
fireworks: { models: [] },
740746
},
741747
}
742748

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ function getStaticModelOptionsForVFS(): Array<{
324324
hosted: boolean
325325
}> {
326326
const hostedProviders = new Set(['openai', 'anthropic', 'google'])
327-
const dynamicProviders = new Set(['ollama', 'vllm', 'openrouter'])
327+
const dynamicProviders = new Set(['ollama', 'vllm', 'openrouter', 'fireworks'])
328328

329329
const models: Array<{ id: string; provider: string; hosted: boolean }> = []
330330

apps/sim/lib/core/config/env.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export const env = createEnv({
105105
OLLAMA_URL: z.string().url().optional(), // Ollama local LLM server URL
106106
VLLM_BASE_URL: z.string().url().optional(), // vLLM self-hosted base URL (OpenAI-compatible)
107107
VLLM_API_KEY: z.string().optional(), // Optional bearer token for vLLM
108+
FIREWORKS_API_KEY: z.string().optional(), // Optional Fireworks AI API key for model listing
108109
ELEVENLABS_API_KEY: z.string().min(1).optional(), // ElevenLabs API key for text-to-speech in deployed chat
109110
SERPER_API_KEY: z.string().min(1).optional(), // Serper API key for online search
110111
EXA_API_KEY: z.string().min(1).optional(), // Exa AI API key for enhanced online search

0 commit comments

Comments
 (0)