provider_mock.go

  1package config
  2
  3import (
  4	"github.com/charmbracelet/crush/internal/fur/provider"
  5)
  6
  7// MockProviders returns a mock list of providers for testing.
  8// This avoids making API calls during tests and provides consistent test data.
  9// Simplified version with only default models from each provider.
 10func MockProviders() []provider.Provider {
 11	return []provider.Provider{
 12		{
 13			Name:                "Anthropic",
 14			ID:                  provider.InferenceProviderAnthropic,
 15			APIKey:              "$ANTHROPIC_API_KEY",
 16			APIEndpoint:         "$ANTHROPIC_API_ENDPOINT",
 17			Type:                provider.TypeAnthropic,
 18			DefaultLargeModelID: "claude-sonnet-4-20250514",
 19			DefaultSmallModelID: "claude-3-5-haiku-20241022",
 20			Models: []provider.Model{
 21				{
 22					ID:                 "claude-sonnet-4-20250514",
 23					Name:               "Claude Sonnet 4",
 24					CostPer1MIn:        3.0,
 25					CostPer1MOut:       15.0,
 26					CostPer1MInCached:  3.75,
 27					CostPer1MOutCached: 0.3,
 28					ContextWindow:      200000,
 29					DefaultMaxTokens:   50000,
 30					CanReason:          true,
 31					SupportsImages:     true,
 32				},
 33				{
 34					ID:                 "claude-3-5-haiku-20241022",
 35					Name:               "Claude 3.5 Haiku",
 36					CostPer1MIn:        0.8,
 37					CostPer1MOut:       4.0,
 38					CostPer1MInCached:  1.0,
 39					CostPer1MOutCached: 0.08,
 40					ContextWindow:      200000,
 41					DefaultMaxTokens:   5000,
 42					CanReason:          false,
 43					SupportsImages:     true,
 44				},
 45			},
 46		},
 47		{
 48			Name:                "OpenAI",
 49			ID:                  provider.InferenceProviderOpenAI,
 50			APIKey:              "$OPENAI_API_KEY",
 51			APIEndpoint:         "$OPENAI_API_ENDPOINT",
 52			Type:                provider.TypeOpenAI,
 53			DefaultLargeModelID: "codex-mini-latest",
 54			DefaultSmallModelID: "gpt-4o",
 55			Models: []provider.Model{
 56				{
 57					ID:                     "codex-mini-latest",
 58					Name:                   "Codex Mini",
 59					CostPer1MIn:            1.5,
 60					CostPer1MOut:           6.0,
 61					CostPer1MInCached:      0.0,
 62					CostPer1MOutCached:     0.375,
 63					ContextWindow:          200000,
 64					DefaultMaxTokens:       50000,
 65					CanReason:              true,
 66					HasReasoningEffort:     true,
 67					DefaultReasoningEffort: "medium",
 68					SupportsImages:         true,
 69				},
 70				{
 71					ID:                 "gpt-4o",
 72					Name:               "GPT-4o",
 73					CostPer1MIn:        2.5,
 74					CostPer1MOut:       10.0,
 75					CostPer1MInCached:  0.0,
 76					CostPer1MOutCached: 1.25,
 77					ContextWindow:      128000,
 78					DefaultMaxTokens:   20000,
 79					CanReason:          false,
 80					SupportsImages:     true,
 81				},
 82			},
 83		},
 84		{
 85			Name:                "Google Gemini",
 86			ID:                  provider.InferenceProviderGemini,
 87			APIKey:              "$GEMINI_API_KEY",
 88			APIEndpoint:         "$GEMINI_API_ENDPOINT",
 89			Type:                provider.TypeGemini,
 90			DefaultLargeModelID: "gemini-2.5-pro",
 91			DefaultSmallModelID: "gemini-2.5-flash",
 92			Models: []provider.Model{
 93				{
 94					ID:                 "gemini-2.5-pro",
 95					Name:               "Gemini 2.5 Pro",
 96					CostPer1MIn:        1.25,
 97					CostPer1MOut:       10.0,
 98					CostPer1MInCached:  1.625,
 99					CostPer1MOutCached: 0.31,
100					ContextWindow:      1048576,
101					DefaultMaxTokens:   50000,
102					CanReason:          true,
103					SupportsImages:     true,
104				},
105				{
106					ID:                 "gemini-2.5-flash",
107					Name:               "Gemini 2.5 Flash",
108					CostPer1MIn:        0.3,
109					CostPer1MOut:       2.5,
110					CostPer1MInCached:  0.3833,
111					CostPer1MOutCached: 0.075,
112					ContextWindow:      1048576,
113					DefaultMaxTokens:   50000,
114					CanReason:          true,
115					SupportsImages:     true,
116				},
117			},
118		},
119		{
120			Name:                "xAI",
121			ID:                  provider.InferenceProviderXAI,
122			APIKey:              "$XAI_API_KEY",
123			APIEndpoint:         "https://api.x.ai/v1",
124			Type:                provider.TypeXAI,
125			DefaultLargeModelID: "grok-3",
126			DefaultSmallModelID: "grok-3-mini",
127			Models: []provider.Model{
128				{
129					ID:               "grok-3",
130					Name:             "Grok 3",
131					CostPer1MIn:      3.0,
132					CostPer1MOut:     15.0,
133					CostPer1MInCached: 0.0,
134					CostPer1MOutCached: 0.75,
135					ContextWindow:    131072,
136					DefaultMaxTokens: 20000,
137					CanReason:        false,
138					SupportsImages:   false,
139				},
140				{
141					ID:               "grok-3-mini",
142					Name:             "Grok 3 Mini",
143					CostPer1MIn:      0.3,
144					CostPer1MOut:     0.5,
145					CostPer1MInCached: 0.0,
146					CostPer1MOutCached: 0.075,
147					ContextWindow:    131072,
148					DefaultMaxTokens: 20000,
149					CanReason:        true,
150					SupportsImages:   false,
151				},
152			},
153		},
154		{
155			Name:                "Azure OpenAI",
156			ID:                  provider.InferenceProviderAzure,
157			APIKey:              "$AZURE_OPENAI_API_KEY",
158			APIEndpoint:         "$AZURE_OPENAI_API_ENDPOINT",
159			Type:                provider.TypeAzure,
160			DefaultLargeModelID: "o4-mini",
161			DefaultSmallModelID: "gpt-4o",
162			Models: []provider.Model{
163				{
164					ID:                     "o4-mini",
165					Name:                   "o4 Mini",
166					CostPer1MIn:            1.1,
167					CostPer1MOut:           4.4,
168					CostPer1MInCached:      0.0,
169					CostPer1MOutCached:     0.275,
170					ContextWindow:          200000,
171					DefaultMaxTokens:       50000,
172					CanReason:              true,
173					HasReasoningEffort:     false,
174					DefaultReasoningEffort: "medium",
175					SupportsImages:         true,
176				},
177				{
178					ID:                 "gpt-4o",
179					Name:               "GPT-4o",
180					CostPer1MIn:        2.5,
181					CostPer1MOut:       10.0,
182					CostPer1MInCached:  0.0,
183					CostPer1MOutCached: 1.25,
184					ContextWindow:      128000,
185					DefaultMaxTokens:   20000,
186					CanReason:          false,
187					SupportsImages:     true,
188				},
189			},
190		},
191		{
192			Name:                "AWS Bedrock",
193			ID:                  provider.InferenceProviderBedrock,
194			Type:                provider.TypeBedrock,
195			DefaultLargeModelID: "anthropic.claude-sonnet-4-20250514-v1:0",
196			DefaultSmallModelID: "anthropic.claude-3-5-haiku-20241022-v1:0",
197			Models: []provider.Model{
198				{
199					ID:                 "anthropic.claude-sonnet-4-20250514-v1:0",
200					Name:               "AWS Claude Sonnet 4",
201					CostPer1MIn:        3.0,
202					CostPer1MOut:       15.0,
203					CostPer1MInCached:  3.75,
204					CostPer1MOutCached: 0.3,
205					ContextWindow:      200000,
206					DefaultMaxTokens:   50000,
207					CanReason:          true,
208					SupportsImages:     true,
209				},
210				{
211					ID:                 "anthropic.claude-3-5-haiku-20241022-v1:0",
212					Name:               "AWS Claude 3.5 Haiku",
213					CostPer1MIn:        0.8,
214					CostPer1MOut:       4.0,
215					CostPer1MInCached:  1.0,
216					CostPer1MOutCached: 0.08,
217					ContextWindow:      200000,
218					DefaultMaxTokens:   50000,
219					CanReason:          false,
220					SupportsImages:     true,
221				},
222			},
223		},
224		{
225			Name:                "Google Vertex AI",
226			ID:                  provider.InferenceProviderVertexAI,
227			Type:                provider.TypeVertexAI,
228			DefaultLargeModelID: "gemini-2.5-pro",
229			DefaultSmallModelID: "gemini-2.5-flash",
230			Models: []provider.Model{
231				{
232					ID:                 "gemini-2.5-pro",
233					Name:               "Gemini 2.5 Pro",
234					CostPer1MIn:        1.25,
235					CostPer1MOut:       10.0,
236					CostPer1MInCached:  1.625,
237					CostPer1MOutCached: 0.31,
238					ContextWindow:      1048576,
239					DefaultMaxTokens:   50000,
240					CanReason:          true,
241					SupportsImages:     true,
242				},
243				{
244					ID:                 "gemini-2.5-flash",
245					Name:               "Gemini 2.5 Flash",
246					CostPer1MIn:        0.3,
247					CostPer1MOut:       2.5,
248					CostPer1MInCached:  0.3833,
249					CostPer1MOutCached: 0.075,
250					ContextWindow:      1048576,
251					DefaultMaxTokens:   50000,
252					CanReason:          true,
253					SupportsImages:     true,
254				},
255			},
256		},
257		{
258			Name:                "OpenRouter",
259			ID:                  provider.InferenceProviderOpenRouter,
260			APIKey:              "$OPENROUTER_API_KEY",
261			APIEndpoint:         "https://openrouter.ai/api/v1",
262			Type:                provider.TypeOpenAI,
263			DefaultLargeModelID: "anthropic/claude-sonnet-4",
264			DefaultSmallModelID: "anthropic/claude-haiku-3.5",
265			Models: []provider.Model{
266				{
267					ID:                 "anthropic/claude-sonnet-4",
268					Name:               "Anthropic: Claude Sonnet 4",
269					CostPer1MIn:        3.0,
270					CostPer1MOut:       15.0,
271					CostPer1MInCached:  3.75,
272					CostPer1MOutCached: 0.3,
273					ContextWindow:      200000,
274					DefaultMaxTokens:   32000,
275					CanReason:          true,
276					SupportsImages:     true,
277				},
278				{
279					ID:                 "anthropic/claude-haiku-3.5",
280					Name:               "Anthropic: Claude 3.5 Haiku",
281					CostPer1MIn:        0.8,
282					CostPer1MOut:       4.0,
283					CostPer1MInCached:  1.0,
284					CostPer1MOutCached: 0.08,
285					ContextWindow:      200000,
286					DefaultMaxTokens:   4096,
287					CanReason:          false,
288					SupportsImages:     true,
289				},
290			},
291		},
292	}
293}