1package providertests
  2
  3import (
  4	"net/http"
  5	"os"
  6	"testing"
  7
  8	"github.com/charmbracelet/fantasy/ai"
  9	"github.com/charmbracelet/fantasy/openrouter"
 10	"github.com/stretchr/testify/require"
 11	"gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
 12)
 13
 14func TestOpenRouterCommon(t *testing.T) {
 15	testCommon(t, []builderPair{
 16		{"kimi-k2", builderOpenRouterKimiK2, nil},
 17		{"grok-code-fast-1", builderOpenRouterGrokCodeFast1, nil},
 18		{"claude-sonnet-4", builderOpenRouterClaudeSonnet4, nil},
 19		{"grok-4-fast-free", builderOpenRouterGrok4FastFree, nil},
 20		{"gemini-2.5-flash", builderOpenRouterGemini25Flash, nil},
 21		{"gemini-2.0-flash", builderOpenRouterGemini20Flash, nil},
 22		{"deepseek-chat-v3.1-free", builderOpenRouterDeepseekV31Free, nil},
 23		{"gpt-5", builderOpenRouterGPT5, nil},
 24		{"glm-4.5", builderOpenRouterGLM45, nil},
 25	})
 26	opts := ai.ProviderOptions{
 27		openrouter.Name: &openrouter.ProviderOptions{
 28			Reasoning: &openrouter.ReasoningOptions{
 29				Effort: openrouter.ReasoningEffortOption(openrouter.ReasoningEffortMedium),
 30			},
 31		},
 32	}
 33	testThinking(t, []builderPair{
 34		{"gpt-5", builderOpenRouterGPT5, opts},
 35		{"glm-4.5", builderOpenRouterGLM45, opts},
 36	}, testOpenrouterThinking)
 37}
 38
 39func testOpenrouterThinking(t *testing.T, result *ai.AgentResult) {
 40	reasoningContentCount := 0
 41	for _, step := range result.Steps {
 42		for _, msg := range step.Messages {
 43			for _, content := range msg.Content {
 44				if content.GetType() == ai.ContentTypeReasoning {
 45					reasoningContentCount += 1
 46				}
 47			}
 48		}
 49	}
 50	require.Greater(t, reasoningContentCount, 0)
 51}
 52
 53func builderOpenRouterKimiK2(r *recorder.Recorder) (ai.LanguageModel, error) {
 54	provider := openrouter.New(
 55		openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")),
 56		openrouter.WithHTTPClient(&http.Client{Transport: r}),
 57	)
 58	return provider.LanguageModel("moonshotai/kimi-k2-0905")
 59}
 60
 61func builderOpenRouterGrokCodeFast1(r *recorder.Recorder) (ai.LanguageModel, error) {
 62	provider := openrouter.New(
 63		openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")),
 64		openrouter.WithHTTPClient(&http.Client{Transport: r}),
 65	)
 66	return provider.LanguageModel("x-ai/grok-code-fast-1")
 67}
 68
 69func builderOpenRouterGrok4FastFree(r *recorder.Recorder) (ai.LanguageModel, error) {
 70	provider := openrouter.New(
 71		openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")),
 72		openrouter.WithHTTPClient(&http.Client{Transport: r}),
 73	)
 74	return provider.LanguageModel("x-ai/grok-4-fast:free")
 75}
 76
 77func builderOpenRouterGemini25Flash(r *recorder.Recorder) (ai.LanguageModel, error) {
 78	provider := openrouter.New(
 79		openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")),
 80		openrouter.WithHTTPClient(&http.Client{Transport: r}),
 81	)
 82	return provider.LanguageModel("google/gemini-2.5-flash")
 83}
 84
 85func builderOpenRouterGemini20Flash(r *recorder.Recorder) (ai.LanguageModel, error) {
 86	provider := openrouter.New(
 87		openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")),
 88		openrouter.WithHTTPClient(&http.Client{Transport: r}),
 89	)
 90	return provider.LanguageModel("google/gemini-2.0-flash-001")
 91}
 92
 93func builderOpenRouterDeepseekV31Free(r *recorder.Recorder) (ai.LanguageModel, error) {
 94	provider := openrouter.New(
 95		openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")),
 96		openrouter.WithHTTPClient(&http.Client{Transport: r}),
 97	)
 98	return provider.LanguageModel("deepseek/deepseek-chat-v3.1:free")
 99}
100
101func builderOpenRouterClaudeSonnet4(r *recorder.Recorder) (ai.LanguageModel, error) {
102	provider := openrouter.New(
103		openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")),
104		openrouter.WithHTTPClient(&http.Client{Transport: r}),
105	)
106	return provider.LanguageModel("anthropic/claude-sonnet-4")
107}
108
109func builderOpenRouterGPT5(r *recorder.Recorder) (ai.LanguageModel, error) {
110	provider := openrouter.New(
111		openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")),
112		openrouter.WithHTTPClient(&http.Client{Transport: r}),
113	)
114	return provider.LanguageModel("openai/gpt-5")
115}
116
117func builderOpenRouterGLM45(r *recorder.Recorder) (ai.LanguageModel, error) {
118	provider := openrouter.New(
119		openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")),
120		openrouter.WithHTTPClient(&http.Client{Transport: r}),
121	)
122	return provider.LanguageModel("z-ai/glm-4.5")
123}