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