1// Package anthropic provides an implementation of the fantasy AI SDK for Anthropic's language models.
2package anthropic
3
4import (
5 "encoding/json"
6
7 "charm.land/fantasy"
8)
9
10// Effort represents the output effort level for Anthropic models.
11//
12// This maps to Messages API `output_config.effort`.
13type Effort string
14
15const (
16 // EffortLow represents low output effort.
17 EffortLow Effort = "low"
18 // EffortMedium represents medium output effort.
19 EffortMedium Effort = "medium"
20 // EffortHigh represents high output effort.
21 EffortHigh Effort = "high"
22 // EffortXHigh represents extra-high output effort.
23 EffortXHigh Effort = "xhigh"
24 // EffortMax represents maximum output effort.
25 EffortMax Effort = "max"
26)
27
28// Global type identifiers for Anthropic-specific provider data.
29const (
30 TypeProviderOptions = Name + ".options"
31 TypeReasoningOptionMetadata = Name + ".reasoning_metadata"
32 TypeProviderCacheControl = Name + ".cache_control_options"
33 TypeWebSearchResultMetadata = Name + ".web_search_result_metadata"
34)
35
36// Register Anthropic provider-specific types with the global registry.
37func init() {
38 fantasy.RegisterProviderType(TypeProviderOptions, func(data []byte) (fantasy.ProviderOptionsData, error) {
39 var v ProviderOptions
40 if err := json.Unmarshal(data, &v); err != nil {
41 return nil, err
42 }
43 return &v, nil
44 })
45 fantasy.RegisterProviderType(TypeReasoningOptionMetadata, func(data []byte) (fantasy.ProviderOptionsData, error) {
46 var v ReasoningOptionMetadata
47 if err := json.Unmarshal(data, &v); err != nil {
48 return nil, err
49 }
50 return &v, nil
51 })
52 fantasy.RegisterProviderType(TypeProviderCacheControl, func(data []byte) (fantasy.ProviderOptionsData, error) {
53 var v ProviderCacheControlOptions
54 if err := json.Unmarshal(data, &v); err != nil {
55 return nil, err
56 }
57 return &v, nil
58 })
59 fantasy.RegisterProviderType(TypeWebSearchResultMetadata, func(data []byte) (fantasy.ProviderOptionsData, error) {
60 var v WebSearchResultMetadata
61 if err := json.Unmarshal(data, &v); err != nil {
62 return nil, err
63 }
64 return &v, nil
65 })
66}
67
68// ProviderOptions represents additional options for the Anthropic provider.
69type ProviderOptions struct {
70 SendReasoning *bool `json:"send_reasoning"`
71 Thinking *ThinkingProviderOption `json:"thinking"`
72 Effort *Effort `json:"effort"`
73 DisableParallelToolUse *bool `json:"disable_parallel_tool_use"`
74}
75
76// Options implements the ProviderOptions interface.
77func (o *ProviderOptions) Options() {}
78
79// MarshalJSON implements custom JSON marshaling with type info for ProviderOptions.
80func (o ProviderOptions) MarshalJSON() ([]byte, error) {
81 type plain ProviderOptions
82 return fantasy.MarshalProviderType(TypeProviderOptions, plain(o))
83}
84
85// UnmarshalJSON implements custom JSON unmarshaling with type info for ProviderOptions.
86func (o *ProviderOptions) UnmarshalJSON(data []byte) error {
87 type plain ProviderOptions
88 var p plain
89 if err := fantasy.UnmarshalProviderType(data, &p); err != nil {
90 return err
91 }
92 *o = ProviderOptions(p)
93 return nil
94}
95
96// ThinkingProviderOption represents thinking options for the Anthropic provider.
97type ThinkingProviderOption struct {
98 BudgetTokens int64 `json:"budget_tokens"`
99}
100
101// ReasoningOptionMetadata represents reasoning metadata for the Anthropic provider.
102type ReasoningOptionMetadata struct {
103 Signature string `json:"signature"`
104 RedactedData string `json:"redacted_data"`
105}
106
107// Options implements the ProviderOptions interface.
108func (*ReasoningOptionMetadata) Options() {}
109
110// MarshalJSON implements custom JSON marshaling with type info for ReasoningOptionMetadata.
111func (m ReasoningOptionMetadata) MarshalJSON() ([]byte, error) {
112 type plain ReasoningOptionMetadata
113 return fantasy.MarshalProviderType(TypeReasoningOptionMetadata, plain(m))
114}
115
116// UnmarshalJSON implements custom JSON unmarshaling with type info for ReasoningOptionMetadata.
117func (m *ReasoningOptionMetadata) UnmarshalJSON(data []byte) error {
118 type plain ReasoningOptionMetadata
119 var p plain
120 if err := fantasy.UnmarshalProviderType(data, &p); err != nil {
121 return err
122 }
123 *m = ReasoningOptionMetadata(p)
124 return nil
125}
126
127// ProviderCacheControlOptions represents cache control options for the Anthropic provider.
128type ProviderCacheControlOptions struct {
129 CacheControl CacheControl `json:"cache_control"`
130}
131
132// Options implements the ProviderOptions interface.
133func (*ProviderCacheControlOptions) Options() {}
134
135// MarshalJSON implements custom JSON marshaling with type info for ProviderCacheControlOptions.
136func (o ProviderCacheControlOptions) MarshalJSON() ([]byte, error) {
137 type plain ProviderCacheControlOptions
138 return fantasy.MarshalProviderType(TypeProviderCacheControl, plain(o))
139}
140
141// UnmarshalJSON implements custom JSON unmarshaling with type info for ProviderCacheControlOptions.
142func (o *ProviderCacheControlOptions) UnmarshalJSON(data []byte) error {
143 type plain ProviderCacheControlOptions
144 var p plain
145 if err := fantasy.UnmarshalProviderType(data, &p); err != nil {
146 return err
147 }
148 *o = ProviderCacheControlOptions(p)
149 return nil
150}
151
152// WebSearchResultItem represents a single web search result for round-tripping.
153type WebSearchResultItem struct {
154 URL string `json:"url"`
155 Title string `json:"title"`
156 EncryptedContent string `json:"encrypted_content"`
157 // PageAge may be empty when the API does not return age info.
158 PageAge string `json:"page_age,omitempty"`
159}
160
161// WebSearchResultMetadata stores web search results from Anthropic's
162// server-executed web_search tool. The structured data (especially
163// EncryptedContent) must be preserved for multi-turn conversations.
164type WebSearchResultMetadata struct {
165 Results []WebSearchResultItem `json:"results"`
166}
167
168// Options implements the ProviderOptions interface.
169func (*WebSearchResultMetadata) Options() {}
170
171// MarshalJSON implements custom JSON marshaling with type info for WebSearchResultMetadata.
172func (m WebSearchResultMetadata) MarshalJSON() ([]byte, error) {
173 type plain WebSearchResultMetadata
174 return fantasy.MarshalProviderType(TypeWebSearchResultMetadata, plain(m))
175}
176
177// UnmarshalJSON implements custom JSON unmarshaling with type info for WebSearchResultMetadata.
178func (m *WebSearchResultMetadata) UnmarshalJSON(data []byte) error {
179 type plain WebSearchResultMetadata
180 var p plain
181 if err := fantasy.UnmarshalProviderType(data, &p); err != nil {
182 return err
183 }
184 *m = WebSearchResultMetadata(p)
185 return nil
186}
187
188// CacheControl represents cache control settings for the Anthropic provider.
189type CacheControl struct {
190 Type string `json:"type"`
191}
192
193// NewProviderOptions creates new provider options for the Anthropic provider.
194func NewProviderOptions(opts *ProviderOptions) fantasy.ProviderOptions {
195 return fantasy.ProviderOptions{
196 Name: opts,
197 }
198}
199
200// NewProviderCacheControlOptions creates new cache control options for the Anthropic provider.
201func NewProviderCacheControlOptions(opts *ProviderCacheControlOptions) fantasy.ProviderOptions {
202 return fantasy.ProviderOptions{
203 Name: opts,
204 }
205}
206
207// ParseOptions parses provider options from a map for the Anthropic provider.
208func ParseOptions(data map[string]any) (*ProviderOptions, error) {
209 var options ProviderOptions
210 if err := fantasy.ParseOptions(data, &options); err != nil {
211 return nil, err
212 }
213 return &options, nil
214}
215
216// UserLocation provides geographic context for web search results.
217type UserLocation struct {
218 City string `json:"city,omitempty"`
219 Region string `json:"region,omitempty"`
220 Country string `json:"country,omitempty"`
221 Timezone string `json:"timezone,omitempty"`
222}
223
224// WebSearchToolOptions configures the Anthropic web search tool.
225type WebSearchToolOptions struct {
226 // MaxUses limits the number of web searches the model can
227 // perform within a single API request. Zero means no limit.
228 MaxUses int64
229 // AllowedDomains restricts results to these domains. Cannot
230 // be used together with BlockedDomains.
231 AllowedDomains []string
232 // BlockedDomains excludes these domains from results. Cannot
233 // be used together with AllowedDomains.
234 BlockedDomains []string
235 // UserLocation provides geographic context for more relevant
236 // search results.
237 UserLocation *UserLocation
238}
239
240// WebSearchTool creates a provider-defined web search tool for
241// Anthropic models. Pass nil for default options.
242func WebSearchTool(opts *WebSearchToolOptions) fantasy.ProviderDefinedTool {
243 tool := fantasy.ProviderDefinedTool{
244 ID: "web_search",
245 Name: "web_search",
246 }
247 if opts == nil {
248 return tool
249 }
250 args := map[string]any{}
251 if opts.MaxUses > 0 {
252 args["max_uses"] = opts.MaxUses
253 }
254 if len(opts.AllowedDomains) > 0 {
255 args["allowed_domains"] = opts.AllowedDomains
256 }
257 if len(opts.BlockedDomains) > 0 {
258 args["blocked_domains"] = opts.BlockedDomains
259 }
260 if opts.UserLocation != nil {
261 args["user_location"] = opts.UserLocation
262 }
263 if len(args) > 0 {
264 tool.Args = args
265 }
266 return tool
267}