openai_responses_test.go

 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/stretchr/testify/require"
11	"gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
12)
13
14func TestOpenAIResponsesCommon(t *testing.T) {
15	var pairs []builderPair
16	for _, m := range openaiTestModels {
17		pairs = append(pairs, builderPair{m.name, openAIReasoningBuilder(m.model), nil})
18	}
19	testCommon(t, pairs)
20}
21
22func openAIReasoningBuilder(model string) builderFunc {
23	return func(r *recorder.Recorder) (ai.LanguageModel, error) {
24		provider := openai.New(
25			openai.WithAPIKey(os.Getenv("FANTASY_OPENAI_API_KEY")),
26			openai.WithHTTPClient(&http.Client{Transport: r}),
27			openai.WithUseResponsesAPI(),
28		)
29		return provider.LanguageModel(model)
30	}
31}
32
33func TestOpenAIResponsesWithSummaryThinking(t *testing.T) {
34	opts := ai.ProviderOptions{
35		openai.Name: &openai.ResponsesProviderOptions{
36			Include: []openai.IncludeType{
37				openai.IncludeReasoningEncryptedContent,
38			},
39			ReasoningEffort:  openai.ReasoningEffortOption(openai.ReasoningEffortHigh),
40			ReasoningSummary: ai.Opt("auto"),
41		},
42	}
43	var pairs []builderPair
44	for _, m := range openaiTestModels {
45		if !m.reasoning {
46			continue
47		}
48		pairs = append(pairs, builderPair{m.name, openAIReasoningBuilder(m.model), opts})
49	}
50	testThinking(t, pairs, testOpenAIResponsesThinkingWithSummaryThinking)
51}
52
53func testOpenAIResponsesThinkingWithSummaryThinking(t *testing.T, result *ai.AgentResult) {
54	reasoningContentCount := 0
55	encryptedData := 0
56	// Test if we got the signature
57	for _, step := range result.Steps {
58		for _, msg := range step.Messages {
59			for _, content := range msg.Content {
60				if content.GetType() == ai.ContentTypeReasoning {
61					reasoningContentCount += 1
62					reasoningContent, ok := ai.AsContentType[ai.ReasoningPart](content)
63					if !ok {
64						continue
65					}
66					if len(reasoningContent.ProviderOptions) == 0 {
67						continue
68					}
69
70					openaiReasoningMetadata, ok := reasoningContent.ProviderOptions[openai.Name]
71					if !ok {
72						continue
73					}
74					if typed, ok := openaiReasoningMetadata.(*openai.ResponsesReasoningMetadata); ok {
75						require.NotEmpty(t, typed.EncryptedContent)
76						encryptedData += 1
77					}
78				}
79			}
80		}
81	}
82	require.Greater(t, reasoningContentCount, 0)
83	require.Greater(t, encryptedData, 0)
84	require.Equal(t, reasoningContentCount, encryptedData)
85}