openaicompat_test.go

  1package providertests
  2
  3import (
  4	"net/http"
  5	"os"
  6	"testing"
  7
  8	"charm.land/fantasy"
  9	"charm.land/fantasy/providers/openai"
 10	"charm.land/fantasy/providers/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		{"huggingface-qwen3-coder", builderHuggingFace, nil},
 22	})
 23}
 24
 25func TestOpenAICompatibleThinking(t *testing.T) {
 26	opts := fantasy.ProviderOptions{
 27		openaicompat.Name: &openaicompat.ProviderOptions{
 28			ReasoningEffort: openai.ReasoningEffortOption(openai.ReasoningEffortHigh),
 29		},
 30	}
 31	testThinking(t, []builderPair{
 32		{"xai-grok-3-mini", builderXAIGrok3Mini, opts},
 33		{"zai-glm-4.5", builderZAIGLM45, opts},
 34	}, testOpenAICompatThinking)
 35}
 36
 37func testOpenAICompatThinking(t *testing.T, result *fantasy.AgentResult) {
 38	reasoningContentCount := 0
 39	for _, step := range result.Steps {
 40		for _, msg := range step.Messages {
 41			for _, content := range msg.Content {
 42				if content.GetType() == fantasy.ContentTypeReasoning {
 43					reasoningContentCount += 1
 44				}
 45			}
 46		}
 47	}
 48	require.Greater(t, reasoningContentCount, 0, "expected reasoning content, got none")
 49}
 50
 51func builderXAIGrokCodeFast(r *recorder.Recorder) (fantasy.LanguageModel, error) {
 52	provider := openaicompat.New(
 53		openaicompat.WithBaseURL("https://api.x.ai/v1"),
 54		openaicompat.WithAPIKey(os.Getenv("FANTASY_XAI_API_KEY")),
 55		openaicompat.WithHTTPClient(&http.Client{Transport: r}),
 56	)
 57	return provider.LanguageModel("grok-code-fast-1")
 58}
 59
 60func builderXAIGrok4Fast(r *recorder.Recorder) (fantasy.LanguageModel, error) {
 61	provider := openaicompat.New(
 62		openaicompat.WithBaseURL("https://api.x.ai/v1"),
 63		openaicompat.WithAPIKey(os.Getenv("FANTASY_XAI_API_KEY")),
 64		openaicompat.WithHTTPClient(&http.Client{Transport: r}),
 65	)
 66	return provider.LanguageModel("grok-4-fast")
 67}
 68
 69func builderXAIGrok3Mini(r *recorder.Recorder) (fantasy.LanguageModel, error) {
 70	provider := openaicompat.New(
 71		openaicompat.WithBaseURL("https://api.x.ai/v1"),
 72		openaicompat.WithAPIKey(os.Getenv("FANTASY_XAI_API_KEY")),
 73		openaicompat.WithHTTPClient(&http.Client{Transport: r}),
 74	)
 75	return provider.LanguageModel("grok-3-mini")
 76}
 77
 78func builderZAIGLM45(r *recorder.Recorder) (fantasy.LanguageModel, error) {
 79	provider := openaicompat.New(
 80		openaicompat.WithBaseURL("https://api.z.ai/api/coding/paas/v4"),
 81		openaicompat.WithAPIKey(os.Getenv("FANTASY_ZAI_API_KEY")),
 82		openaicompat.WithHTTPClient(&http.Client{Transport: r}),
 83	)
 84	return provider.LanguageModel("glm-4.5")
 85}
 86
 87func builderGroq(r *recorder.Recorder) (fantasy.LanguageModel, error) {
 88	provider := openaicompat.New(
 89		openaicompat.WithBaseURL("https://api.groq.com/openai/v1"),
 90		openaicompat.WithAPIKey(os.Getenv("FANTASY_GROQ_API_KEY")),
 91		openaicompat.WithHTTPClient(&http.Client{Transport: r}),
 92	)
 93	return provider.LanguageModel("moonshotai/kimi-k2-instruct-0905")
 94}
 95
 96func builderHuggingFace(r *recorder.Recorder) (fantasy.LanguageModel, error) {
 97	provider := openaicompat.New(
 98		openaicompat.WithBaseURL("https://router.huggingface.co/v1"),
 99		openaicompat.WithAPIKey(os.Getenv("FANTASY_HUGGINGFACE_API_KEY")),
100		openaicompat.WithHTTPClient(&http.Client{Transport: r}),
101	)
102	return provider.LanguageModel("Qwen/Qwen3-Coder-480B-A35B-Instruct:cerebras")
103}