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