1// Package openai provides an implementation of the fantasy AI SDK for OpenAI's language models.
2package openai
3
4import (
5 "encoding/json"
6 "slices"
7
8 "charm.land/fantasy"
9)
10
11// Global type identifiers for OpenAI Responses API-specific data.
12const (
13 TypeResponsesProviderOptions = Name + ".responses.options"
14 TypeResponsesReasoningMetadata = Name + ".responses.reasoning_metadata"
15)
16
17// Register OpenAI Responses API-specific types with the global registry.
18func init() {
19 fantasy.RegisterProviderType(TypeResponsesProviderOptions, func(data []byte) (fantasy.ProviderOptionsData, error) {
20 var v ResponsesProviderOptions
21 if err := json.Unmarshal(data, &v); err != nil {
22 return nil, err
23 }
24 return &v, nil
25 })
26 fantasy.RegisterProviderType(TypeResponsesReasoningMetadata, func(data []byte) (fantasy.ProviderOptionsData, error) {
27 var v ResponsesReasoningMetadata
28 if err := json.Unmarshal(data, &v); err != nil {
29 return nil, err
30 }
31 return &v, nil
32 })
33}
34
35// ResponsesReasoningMetadata represents reasoning metadata for OpenAI Responses API.
36type ResponsesReasoningMetadata struct {
37 ItemID string `json:"item_id"`
38 EncryptedContent *string `json:"encrypted_content"`
39 Summary []string `json:"summary"`
40}
41
42// Options implements the ProviderOptions interface.
43func (*ResponsesReasoningMetadata) Options() {}
44
45// MarshalJSON implements custom JSON marshaling with type info for ResponsesReasoningMetadata.
46func (m ResponsesReasoningMetadata) MarshalJSON() ([]byte, error) {
47 type plain ResponsesReasoningMetadata
48 return fantasy.MarshalProviderType(TypeResponsesReasoningMetadata, plain(m))
49}
50
51// UnmarshalJSON implements custom JSON unmarshaling with type info for ResponsesReasoningMetadata.
52func (m *ResponsesReasoningMetadata) UnmarshalJSON(data []byte) error {
53 type plain ResponsesReasoningMetadata
54 var p plain
55 if err := fantasy.UnmarshalProviderType(data, &p); err != nil {
56 return err
57 }
58 *m = ResponsesReasoningMetadata(p)
59 return nil
60}
61
62// IncludeType represents the type of content to include for OpenAI Responses API.
63type IncludeType string
64
65const (
66 // IncludeReasoningEncryptedContent includes encrypted reasoning content.
67 IncludeReasoningEncryptedContent IncludeType = "reasoning.encrypted_content"
68 // IncludeFileSearchCallResults includes file search call results.
69 IncludeFileSearchCallResults IncludeType = "file_search_call.results"
70 // IncludeMessageOutputTextLogprobs includes message output text log probabilities.
71 IncludeMessageOutputTextLogprobs IncludeType = "message.output_text.logprobs"
72)
73
74// ServiceTier represents the service tier for OpenAI Responses API.
75type ServiceTier string
76
77const (
78 // ServiceTierAuto represents the auto service tier.
79 ServiceTierAuto ServiceTier = "auto"
80 // ServiceTierFlex represents the flex service tier.
81 ServiceTierFlex ServiceTier = "flex"
82 // ServiceTierPriority represents the priority service tier.
83 ServiceTierPriority ServiceTier = "priority"
84)
85
86// TextVerbosity represents the text verbosity level for OpenAI Responses API.
87type TextVerbosity string
88
89const (
90 // TextVerbosityLow represents low text verbosity.
91 TextVerbosityLow TextVerbosity = "low"
92 // TextVerbosityMedium represents medium text verbosity.
93 TextVerbosityMedium TextVerbosity = "medium"
94 // TextVerbosityHigh represents high text verbosity.
95 TextVerbosityHigh TextVerbosity = "high"
96)
97
98// ResponsesProviderOptions represents additional options for OpenAI Responses API.
99type ResponsesProviderOptions struct {
100 Include []IncludeType `json:"include"`
101 Instructions *string `json:"instructions"`
102 Logprobs any `json:"logprobs"`
103 MaxToolCalls *int64 `json:"max_tool_calls"`
104 Metadata map[string]any `json:"metadata"`
105 ParallelToolCalls *bool `json:"parallel_tool_calls"`
106 PromptCacheKey *string `json:"prompt_cache_key"`
107 ReasoningEffort *ReasoningEffort `json:"reasoning_effort"`
108 ReasoningSummary *string `json:"reasoning_summary"`
109 SafetyIdentifier *string `json:"safety_identifier"`
110 ServiceTier *ServiceTier `json:"service_tier"`
111 StrictJSONSchema *bool `json:"strict_json_schema"`
112 TextVerbosity *TextVerbosity `json:"text_verbosity"`
113 User *string `json:"user"`
114}
115
116// Options implements the ProviderOptions interface.
117func (*ResponsesProviderOptions) Options() {}
118
119// MarshalJSON implements custom JSON marshaling with type info for ResponsesProviderOptions.
120func (o ResponsesProviderOptions) MarshalJSON() ([]byte, error) {
121 type plain ResponsesProviderOptions
122 return fantasy.MarshalProviderType(TypeResponsesProviderOptions, plain(o))
123}
124
125// UnmarshalJSON implements custom JSON unmarshaling with type info for ResponsesProviderOptions.
126func (o *ResponsesProviderOptions) UnmarshalJSON(data []byte) error {
127 type plain ResponsesProviderOptions
128 var p plain
129 if err := fantasy.UnmarshalProviderType(data, &p); err != nil {
130 return err
131 }
132 *o = ResponsesProviderOptions(p)
133 return nil
134}
135
136// responsesReasoningModelIds lists the model IDs that support reasoning for OpenAI Responses API.
137var responsesReasoningModelIDs = []string{
138 "o1",
139 "o1-2024-12-17",
140 "o3-mini",
141 "o3-mini-2025-01-31",
142 "o3",
143 "o3-2025-04-16",
144 "o4-mini",
145 "o4-mini-2025-04-16",
146 "codex-mini-latest",
147 "gpt-5",
148 "gpt-5-2025-08-07",
149 "gpt-5-mini",
150 "gpt-5-mini-2025-08-07",
151 "gpt-5-nano",
152 "gpt-5-nano-2025-08-07",
153 "gpt-5-codex",
154}
155
156// responsesModelIds lists all model IDs for OpenAI Responses API.
157var responsesModelIDs = append([]string{
158 "gpt-4.1",
159 "gpt-4.1-2025-04-14",
160 "gpt-4.1-mini",
161 "gpt-4.1-mini-2025-04-14",
162 "gpt-4.1-nano",
163 "gpt-4.1-nano-2025-04-14",
164 "gpt-4o",
165 "gpt-4o-2024-05-13",
166 "gpt-4o-2024-08-06",
167 "gpt-4o-2024-11-20",
168 "gpt-4o-mini",
169 "gpt-4o-mini-2024-07-18",
170 "gpt-4-turbo",
171 "gpt-4-turbo-2024-04-09",
172 "gpt-4-turbo-preview",
173 "gpt-4-0125-preview",
174 "gpt-4-1106-preview",
175 "gpt-4",
176 "gpt-4-0613",
177 "gpt-4.5-preview",
178 "gpt-4.5-preview-2025-02-27",
179 "gpt-3.5-turbo-0125",
180 "gpt-3.5-turbo",
181 "gpt-3.5-turbo-1106",
182 "chatgpt-4o-latest",
183 "gpt-5-chat-latest",
184}, responsesReasoningModelIDs...)
185
186// NewResponsesProviderOptions creates new provider options for OpenAI Responses API.
187func NewResponsesProviderOptions(opts *ResponsesProviderOptions) fantasy.ProviderOptions {
188 return fantasy.ProviderOptions{
189 Name: opts,
190 }
191}
192
193// ParseResponsesOptions parses provider options from a map for OpenAI Responses API.
194func ParseResponsesOptions(data map[string]any) (*ResponsesProviderOptions, error) {
195 var options ResponsesProviderOptions
196 if err := fantasy.ParseOptions(data, &options); err != nil {
197 return nil, err
198 }
199 return &options, nil
200}
201
202// IsResponsesModel checks if a model ID is a Responses API model for OpenAI.
203func IsResponsesModel(modelID string) bool {
204 return slices.Contains(responsesModelIDs, modelID)
205}
206
207// IsResponsesReasoningModel checks if a model ID is a Responses API reasoning model for OpenAI.
208func IsResponsesReasoningModel(modelID string) bool {
209 return slices.Contains(responsesReasoningModelIDs, modelID)
210}