@@ -1,6 +1,7 @@
1package config
1package config
6 "github.com/charmbracelet/crush/internal/fur/provider"
7 "github.com/charmbracelet/crush/internal/fur/provider"
@@ -103,3 +104,177 @@ func TestResetProviders(t *testing.T) {
103 // Should get the same mock data
104 // Should get the same mock data
104 assert.Equal(t, len(providers1), len(providers2))
105 assert.Equal(t, len(providers1), len(providers2))
108+func TestReasoningEffortSupport(t *testing.T) {
109+ originalUseMock := UseMockProviders
110+ UseMockProviders = true
112+ UseMockProviders = originalUseMock
117+ providers := Providers()
119+ var openaiProvider provider.Provider
120+ for _, p := range providers {
121+ if p.ID == provider.InferenceProviderOpenAI {
126+ require.NotEmpty(t, openaiProvider.ID)
128+ var reasoningModel, nonReasoningModel provider.Model
129+ for _, model := range openaiProvider.Models {
130+ if model.CanReason && model.HasReasoningEffort {
131+ reasoningModel = model
132+ } else if !model.CanReason {
133+ nonReasoningModel = model
137+ require.NotEmpty(t, reasoningModel.ID)
138+ assert.Equal(t, "medium", reasoningModel.DefaultReasoningEffort)
139+ assert.True(t, reasoningModel.HasReasoningEffort)
141+ require.NotEmpty(t, nonReasoningModel.ID)
142+ assert.False(t, nonReasoningModel.HasReasoningEffort)
143+ assert.Empty(t, nonReasoningModel.DefaultReasoningEffort)
146+func TestReasoningEffortConfigTransfer(t *testing.T) {
147+ originalUseMock := UseMockProviders
148+ UseMockProviders = true
150+ UseMockProviders = originalUseMock
155+ t.Setenv("OPENAI_API_KEY", "test-openai-key")
157+ cfg, err := Init(t.TempDir(), false)
158+ require.NoError(t, err)
160+ openaiProviderConfig, exists := cfg.Providers[provider.InferenceProviderOpenAI]
161+ require.True(t, exists)
163+ var foundReasoning, foundNonReasoning bool
164+ for _, model := range openaiProviderConfig.Models {
165+ if model.CanReason && model.HasReasoningEffort && model.ReasoningEffort != "" {
166+ assert.Equal(t, "medium", model.ReasoningEffort)
167+ assert.True(t, model.HasReasoningEffort)
168+ foundReasoning = true
169+ } else if !model.CanReason {
170+ assert.Empty(t, model.ReasoningEffort)
171+ assert.False(t, model.HasReasoningEffort)
172+ foundNonReasoning = true
176+ assert.True(t, foundReasoning, "Should find at least one reasoning model")
177+ assert.True(t, foundNonReasoning, "Should find at least one non-reasoning model")
180+func TestNewProviders(t *testing.T) {
181+ originalUseMock := UseMockProviders
182+ UseMockProviders = true
184+ UseMockProviders = originalUseMock
189+ providers := Providers()
190+ require.NotEmpty(t, providers)
192+ var xaiProvider, openRouterProvider provider.Provider
193+ for _, p := range providers {
195+ case provider.InferenceProviderXAI:
197+ case provider.InferenceProviderOpenRouter:
198+ openRouterProvider = p
202+ require.NotEmpty(t, xaiProvider.ID)
203+ assert.Equal(t, "xAI", xaiProvider.Name)
204+ assert.Equal(t, "grok-beta", xaiProvider.DefaultLargeModelID)
206+ require.NotEmpty(t, openRouterProvider.ID)
207+ assert.Equal(t, "OpenRouter", openRouterProvider.Name)
208+ assert.Equal(t, "anthropic/claude-3.5-sonnet", openRouterProvider.DefaultLargeModelID)
211+func TestO1ModelsInMockProvider(t *testing.T) {
212+ originalUseMock := UseMockProviders
213+ UseMockProviders = true
215+ UseMockProviders = originalUseMock
220+ providers := Providers()
222+ var openaiProvider provider.Provider
223+ for _, p := range providers {
224+ if p.ID == provider.InferenceProviderOpenAI {
229+ require.NotEmpty(t, openaiProvider.ID)
231+ modelTests := []struct {
235+ {"o1-preview", "o1-preview"},
236+ {"o1-mini", "o1-mini"},
239+ for _, test := range modelTests {
240+ var model provider.Model
242+ for _, m := range openaiProvider.Models {
243+ if m.ID == test.id {
249+ require.True(t, found, "Should find %s model", test.id)
250+ assert.Equal(t, test.name, model.Name)
251+ assert.True(t, model.CanReason)
252+ assert.True(t, model.HasReasoningEffort)
253+ assert.Equal(t, "medium", model.DefaultReasoningEffort)
257+func TestPreferredModelReasoningEffort(t *testing.T) {
258+ // Test that PreferredModel struct can hold reasoning effort
259+ preferredModel := PreferredModel{
260+ ModelID: "o1-preview",
261+ Provider: provider.InferenceProviderOpenAI,
262+ ReasoningEffort: "high",
265+ assert.Equal(t, "o1-preview", preferredModel.ModelID)
266+ assert.Equal(t, provider.InferenceProviderOpenAI, preferredModel.Provider)
267+ assert.Equal(t, "high", preferredModel.ReasoningEffort)
269+ // Test JSON marshaling/unmarshaling
270+ jsonData, err := json.Marshal(preferredModel)
271+ require.NoError(t, err)
273+ var unmarshaled PreferredModel
274+ err = json.Unmarshal(jsonData, &unmarshaled)
275+ require.NoError(t, err)
277+ assert.Equal(t, preferredModel.ModelID, unmarshaled.ModelID)
278+ assert.Equal(t, preferredModel.Provider, unmarshaled.Provider)
279+ assert.Equal(t, preferredModel.ReasoningEffort, unmarshaled.ReasoningEffort)