1package providertests
2
3import (
4 "net/http"
5 "os"
6 "testing"
7
8 "github.com/charmbracelet/fantasy/ai"
9 "github.com/charmbracelet/fantasy/openai"
10 "github.com/charmbracelet/fantasy/openaicompat"
11 "github.com/stretchr/testify/require"
12 "gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
13)
14
15func TestOpenAICompatibleCommon(t *testing.T) {
16 testCommon(t, []builderPair{
17 {"xai-grok-4-fast", builderXAIGrok4Fast, nil},
18 {"xai-grok-code-fast", builderXAIGrokCodeFast, nil},
19 {"groq-kimi-k2", builderGroq, nil},
20 {"zai-glm-4.5", builderZAIGLM45, nil},
21 })
22}
23
24func TestOpenAICompatibleThinking(t *testing.T) {
25 opts := ai.ProviderOptions{
26 openaicompat.Name: &openaicompat.ProviderOptions{
27 ReasoningEffort: openai.ReasoningEffortOption(openai.ReasoningEffortHigh),
28 },
29 }
30 testThinking(t, []builderPair{
31 {"xai-grok-3-mini", builderXAIGrok3Mini, opts},
32 {"zai-glm-4.5", builderZAIGLM45, opts},
33 }, testOpenAICompatThinking)
34}
35
36func testOpenAICompatThinking(t *testing.T, result *ai.AgentResult) {
37 reasoningContentCount := 0
38 for _, step := range result.Steps {
39 for _, msg := range step.Messages {
40 for _, content := range msg.Content {
41 if content.GetType() == ai.ContentTypeReasoning {
42 reasoningContentCount += 1
43 }
44 }
45 }
46 }
47 require.Greater(t, reasoningContentCount, 0)
48}
49
50func builderXAIGrokCodeFast(r *recorder.Recorder) (ai.LanguageModel, error) {
51 provider := openaicompat.New(
52 "https://api.x.ai/v1",
53 openaicompat.WithAPIKey(os.Getenv("FANTASY_XAI_API_KEY")),
54 openaicompat.WithHTTPClient(&http.Client{Transport: r}),
55 )
56 return provider.LanguageModel("grok-code-fast-1")
57}
58
59func builderXAIGrok4Fast(r *recorder.Recorder) (ai.LanguageModel, error) {
60 provider := openaicompat.New(
61 "https://api.x.ai/v1",
62 openaicompat.WithAPIKey(os.Getenv("FANTASY_XAI_API_KEY")),
63 openaicompat.WithHTTPClient(&http.Client{Transport: r}),
64 )
65 return provider.LanguageModel("grok-4-fast")
66}
67
68func builderXAIGrok3Mini(r *recorder.Recorder) (ai.LanguageModel, error) {
69 provider := openaicompat.New(
70 "https://api.x.ai/v1",
71 openaicompat.WithAPIKey(os.Getenv("FANTASY_XAI_API_KEY")),
72 openaicompat.WithHTTPClient(&http.Client{Transport: r}),
73 )
74 return provider.LanguageModel("grok-3-mini")
75}
76
77func builderZAIGLM45(r *recorder.Recorder) (ai.LanguageModel, error) {
78 provider := openaicompat.New(
79 "https://api.z.ai/api/coding/paas/v4",
80 openaicompat.WithAPIKey(os.Getenv("FANTASY_ZAI_API_KEY")),
81 openaicompat.WithHTTPClient(&http.Client{Transport: r}),
82 )
83 return provider.LanguageModel("glm-4.5")
84}
85
86func builderGroq(r *recorder.Recorder) (ai.LanguageModel, error) {
87 provider := openaicompat.New(
88 "https://api.groq.com/openai/v1",
89 openaicompat.WithAPIKey(os.Getenv("FANTASY_GROQ_API_KEY")),
90 openaicompat.WithHTTPClient(&http.Client{Transport: r}),
91 )
92 return provider.LanguageModel("moonshotai/kimi-k2-instruct-0905")
93}