1package fantasy
2
3import (
4 "context"
5 "encoding/json"
6)
7
8// ProviderOptionsData is an interface for provider-specific options data.
9// All implementations MUST also implement encoding/json.Marshaler and
10// encoding/json.Unmarshaler interfaces to ensure proper JSON serialization
11// with the provider registry system.
12//
13// Recommended implementation pattern using generic helpers:
14//
15// // Define type constants at the top of your file
16// const TypeMyProviderOptions = "myprovider.options"
17//
18// type MyProviderOptions struct {
19// Field string `json:"field"`
20// }
21//
22// // Register the type in init() - place at top of file after constants
23// func init() {
24// fantasy.RegisterProviderType(TypeMyProviderOptions, func(data []byte) (fantasy.ProviderOptionsData, error) {
25// var opts MyProviderOptions
26// if err := json.Unmarshal(data, &opts); err != nil {
27// return nil, err
28// }
29// return &opts, nil
30// })
31// }
32//
33// // Implement ProviderOptionsData interface
34// func (*MyProviderOptions) Options() {}
35//
36// // Implement json.Marshaler using the generic helper
37// func (m MyProviderOptions) MarshalJSON() ([]byte, error) {
38// type plain MyProviderOptions
39// return fantasy.MarshalProviderType(TypeMyProviderOptions, plain(m))
40// }
41//
42// // Implement json.Unmarshaler using the generic helper
43// // Note: Receives inner data after type routing by the registry.
44// func (m *MyProviderOptions) UnmarshalJSON(data []byte) error {
45// type plain MyProviderOptions
46// var p plain
47// if err := fantasy.UnmarshalProviderType(data, &p); err != nil {
48// return err
49// }
50// *m = MyProviderOptions(p)
51// return nil
52// }
53type ProviderOptionsData interface {
54 // Options is a marker method that identifies types implementing this interface.
55 Options()
56 json.Marshaler
57 json.Unmarshaler
58}
59
60// ProviderMetadata represents additional provider-specific metadata.
61// They are passed through from the provider to the AI SDK and enable
62// provider-specific results that can be fully encapsulated in the provider.
63//
64// The outer map is keyed by the provider name, and the inner
65// map is keyed by the provider-specific metadata key.
66//
67// Example:
68//
69// {
70// "anthropic": {
71// "signature": "sig....."
72// }
73// }
74type ProviderMetadata map[string]ProviderOptionsData
75
76// ProviderOptions represents additional provider-specific options.
77// Options are additional input to the provider. They are passed through
78// to the provider from the AI SDK and enable provider-specific functionality
79// that can be fully encapsulated in the provider.
80//
81// This enables us to quickly ship provider-specific functionality
82// without affecting the core AI SDK.
83//
84// The outer map is keyed by the provider name, and the inner
85// map is keyed by the provider-specific option key.
86//
87// Example:
88//
89// {
90// "anthropic": {
91// "cacheControl": { "type": "ephemeral" }
92// }
93// }
94type ProviderOptions map[string]ProviderOptionsData
95
96// FinishReason represents why a language model finished generating a response.
97//
98// Can be one of the following:
99// - `stop`: model generated stop sequence
100// - `length`: model generated maximum number of tokens
101// - `content-filter`: content filter violation stopped the model
102// - `tool-calls`: model triggered tool calls
103// - `error`: model stopped because of an error
104// - `other`: model stopped for other reasons
105// - `unknown`: the model has not transmitted a finish reason.
106type FinishReason string
107
108const (
109 // FinishReasonStop indicates the model generated a stop sequence.
110 FinishReasonStop FinishReason = "stop" // model generated stop sequence
111 // FinishReasonLength indicates the model generated maximum number of tokens.
112 FinishReasonLength FinishReason = "length" // model generated maximum number of tokens
113 // FinishReasonContentFilter indicates content filter violation stopped the model.
114 FinishReasonContentFilter FinishReason = "content-filter" // content filter violation stopped the model
115 // FinishReasonToolCalls indicates the model triggered tool calls.
116 FinishReasonToolCalls FinishReason = "tool-calls" // model triggered tool calls
117 // FinishReasonError indicates the model stopped because of an error.
118 FinishReasonError FinishReason = "error" // model stopped because of an error
119 // FinishReasonOther indicates the model stopped for other reasons.
120 FinishReasonOther FinishReason = "other" // model stopped for other reasons
121 // FinishReasonUnknown indicates the model has not transmitted a finish reason.
122 FinishReasonUnknown FinishReason = "unknown" // the model has not transmitted a finish reason
123)
124
125// Prompt represents a list of messages for the language model.
126type Prompt []Message
127
128// MessageRole represents the role of a message.
129type MessageRole string
130
131const (
132 // MessageRoleSystem represents a system message.
133 MessageRoleSystem MessageRole = "system"
134 // MessageRoleUser represents a user message.
135 MessageRoleUser MessageRole = "user"
136 // MessageRoleAssistant represents an assistant message.
137 MessageRoleAssistant MessageRole = "assistant"
138 // MessageRoleTool represents a tool message.
139 MessageRoleTool MessageRole = "tool"
140)
141
142// Message represents a message in a prompt.
143type Message struct {
144 Role MessageRole `json:"role"`
145 Content []MessagePart `json:"content"`
146 ProviderOptions ProviderOptions `json:"provider_options"`
147}
148
149// AsContentType converts a Content interface to a specific content type.
150func AsContentType[T Content](content Content) (T, bool) {
151 var zero T
152 if content == nil {
153 return zero, false
154 }
155 switch v := any(content).(type) {
156 case T:
157 return v, true
158 case *T:
159 return *v, true
160 default:
161 return zero, false
162 }
163}
164
165// AsMessagePart converts a MessagePart interface to a specific message part type.
166func AsMessagePart[T MessagePart](content MessagePart) (T, bool) {
167 var zero T
168 if content == nil {
169 return zero, false
170 }
171 switch v := any(content).(type) {
172 case T:
173 return v, true
174 case *T:
175 return *v, true
176 default:
177 return zero, false
178 }
179}
180
181// MessagePart represents a part of a message content.
182type MessagePart interface {
183 GetType() ContentType
184 Options() ProviderOptions
185}
186
187// TextPart represents text content in a message.
188type TextPart struct {
189 Text string `json:"text"`
190 ProviderOptions ProviderOptions `json:"provider_options"`
191}
192
193// GetType returns the type of the text part.
194func (t TextPart) GetType() ContentType {
195 return ContentTypeText
196}
197
198// Options returns the provider options for the text part.
199func (t TextPart) Options() ProviderOptions {
200 return t.ProviderOptions
201}
202
203// ReasoningPart represents reasoning content in a message.
204type ReasoningPart struct {
205 Text string `json:"text"`
206 ProviderOptions ProviderOptions `json:"provider_options"`
207}
208
209// GetType returns the type of the reasoning part.
210func (r ReasoningPart) GetType() ContentType {
211 return ContentTypeReasoning
212}
213
214// Options returns the provider options for the reasoning part.
215func (r ReasoningPart) Options() ProviderOptions {
216 return r.ProviderOptions
217}
218
219// FilePart represents file content in a message.
220type FilePart struct {
221 Filename string `json:"filename"`
222 Data []byte `json:"data"`
223 MediaType string `json:"media_type"`
224 ProviderOptions ProviderOptions `json:"provider_options"`
225}
226
227// GetType returns the type of the file part.
228func (f FilePart) GetType() ContentType {
229 return ContentTypeFile
230}
231
232// Options returns the provider options for the file part.
233func (f FilePart) Options() ProviderOptions {
234 return f.ProviderOptions
235}
236
237// ToolCallPart represents a tool call in a message.
238type ToolCallPart struct {
239 ToolCallID string `json:"tool_call_id"`
240 ToolName string `json:"tool_name"`
241 Input string `json:"input"` // the json string
242 ProviderExecuted bool `json:"provider_executed"`
243 ProviderOptions ProviderOptions `json:"provider_options"`
244}
245
246// GetType returns the type of the tool call part.
247func (t ToolCallPart) GetType() ContentType {
248 return ContentTypeToolCall
249}
250
251// Options returns the provider options for the tool call part.
252func (t ToolCallPart) Options() ProviderOptions {
253 return t.ProviderOptions
254}
255
256// ToolResultPart represents a tool result in a message.
257type ToolResultPart struct {
258 ToolCallID string `json:"tool_call_id"`
259 Output ToolResultOutputContent `json:"output"`
260 ProviderExecuted bool `json:"provider_executed"`
261 ProviderOptions ProviderOptions `json:"provider_options"`
262}
263
264// GetType returns the type of the tool result part.
265func (t ToolResultPart) GetType() ContentType {
266 return ContentTypeToolResult
267}
268
269// Options returns the provider options for the tool result part.
270func (t ToolResultPart) Options() ProviderOptions {
271 return t.ProviderOptions
272}
273
274// ToolResultContentType represents the type of tool result output.
275type ToolResultContentType string
276
277const (
278 // ToolResultContentTypeText represents text output.
279 ToolResultContentTypeText ToolResultContentType = "text"
280 // ToolResultContentTypeError represents error text output.
281 ToolResultContentTypeError ToolResultContentType = "error"
282 // ToolResultContentTypeMedia represents content output.
283 ToolResultContentTypeMedia ToolResultContentType = "media"
284)
285
286// ToolResultOutputContent represents the output content of a tool result.
287type ToolResultOutputContent interface {
288 GetType() ToolResultContentType
289}
290
291// ToolResultOutputContentText represents text output content of a tool result.
292type ToolResultOutputContentText struct {
293 Text string `json:"text"`
294}
295
296// GetType returns the type of the tool result output content text.
297func (t ToolResultOutputContentText) GetType() ToolResultContentType {
298 return ToolResultContentTypeText
299}
300
301// ToolResultOutputContentError represents error output content of a tool result.
302type ToolResultOutputContentError struct {
303 Error error `json:"error"`
304}
305
306// GetType returns the type of the tool result output content error.
307func (t ToolResultOutputContentError) GetType() ToolResultContentType {
308 return ToolResultContentTypeError
309}
310
311// ToolResultOutputContentMedia represents media output content of a tool result.
312type ToolResultOutputContentMedia struct {
313 Data string `json:"data"` // for media type (base64)
314 MediaType string `json:"media_type"` // for media type
315 Text string `json:"text,omitempty"` // optional text content accompanying the media
316}
317
318// GetType returns the type of the tool result output content media.
319func (t ToolResultOutputContentMedia) GetType() ToolResultContentType {
320 return ToolResultContentTypeMedia
321}
322
323// AsToolResultOutputType converts a ToolResultOutputContent interface to a specific type.
324func AsToolResultOutputType[T ToolResultOutputContent](content ToolResultOutputContent) (T, bool) {
325 var zero T
326 if content == nil {
327 return zero, false
328 }
329 switch v := any(content).(type) {
330 case T:
331 return v, true
332 case *T:
333 return *v, true
334 default:
335 return zero, false
336 }
337}
338
339// ContentType represents the type of content.
340type ContentType string
341
342const (
343 // ContentTypeText represents text content.
344 ContentTypeText ContentType = "text"
345 // ContentTypeReasoning represents reasoning content.
346 ContentTypeReasoning ContentType = "reasoning"
347 // ContentTypeFile represents file content.
348 ContentTypeFile ContentType = "file"
349 // ContentTypeSource represents source content.
350 ContentTypeSource ContentType = "source"
351 // ContentTypeToolCall represents a tool call.
352 ContentTypeToolCall ContentType = "tool-call"
353 // ContentTypeToolResult represents a tool result.
354 ContentTypeToolResult ContentType = "tool-result"
355)
356
357// Content represents generated content from the model.
358type Content interface {
359 GetType() ContentType
360}
361
362// TextContent represents text that the model has generated.
363type TextContent struct {
364 // The text content.
365 Text string `json:"text"`
366 ProviderMetadata ProviderMetadata `json:"provider_metadata"`
367}
368
369// GetType returns the type of the text content.
370func (t TextContent) GetType() ContentType {
371 return ContentTypeText
372}
373
374// ReasoningContent represents reasoning that the model has generated.
375type ReasoningContent struct {
376 Text string `json:"text"`
377 ProviderMetadata ProviderMetadata `json:"provider_metadata"`
378}
379
380// GetType returns the type of the reasoning content.
381func (r ReasoningContent) GetType() ContentType {
382 return ContentTypeReasoning
383}
384
385// FileContent represents a file that has been generated by the model.
386// Generated files as base64 encoded strings or binary data.
387// The files should be returned without any unnecessary conversion.
388type FileContent struct {
389 // The IANA media type of the file, e.g. `image/png` or `audio/mp3`.
390 // @see https://www.iana.org/assignments/media-types/media-types.xhtml
391 MediaType string `json:"media_type"`
392 // Generated file data as binary data.
393 Data []byte `json:"data"`
394 ProviderMetadata ProviderMetadata `json:"provider_metadata"`
395}
396
397// GetType returns the type of the file content.
398func (f FileContent) GetType() ContentType {
399 return ContentTypeFile
400}
401
402// SourceType represents the type of source.
403type SourceType string
404
405const (
406 // SourceTypeURL represents a URL source.
407 SourceTypeURL SourceType = "url"
408 // SourceTypeDocument represents a document source.
409 SourceTypeDocument SourceType = "document"
410)
411
412// SourceContent represents a source that has been used as input to generate the response.
413type SourceContent struct {
414 SourceType SourceType `json:"source_type"` // "url" or "document"
415 ID string `json:"id"`
416 URL string `json:"url"` // for URL sources
417 Title string `json:"title"`
418 MediaType string `json:"media_type"` // for document sources (IANA media type)
419 Filename string `json:"filename"` // for document sources
420 ProviderMetadata ProviderMetadata `json:"provider_metadata"`
421}
422
423// GetType returns the type of the source content.
424func (s SourceContent) GetType() ContentType {
425 return ContentTypeSource
426}
427
428// ToolCallContent represents tool calls that the model has generated.
429type ToolCallContent struct {
430 ToolCallID string `json:"tool_call_id"`
431 ToolName string `json:"tool_name"`
432 // Stringified JSON object with the tool call arguments.
433 // Must match the parameters schema of the tool.
434 Input string `json:"input"`
435 // Whether the tool call will be executed by the provider.
436 // If this flag is not set or is false, the tool call will be executed by the client.
437 ProviderExecuted bool `json:"provider_executed"`
438 // Additional provider-specific metadata for the tool call.
439 ProviderMetadata ProviderMetadata `json:"provider_metadata"`
440 // Whether this tool call is invalid (failed validation/parsing)
441 Invalid bool `json:"invalid,omitempty"`
442 // Error that occurred during validation/parsing (only set if Invalid is true)
443 ValidationError error `json:"validation_error,omitempty"`
444}
445
446// GetType returns the type of the tool call content.
447func (t ToolCallContent) GetType() ContentType {
448 return ContentTypeToolCall
449}
450
451// ToolResultContent represents result of a tool call that has been executed by the provider.
452type ToolResultContent struct {
453 // The ID of the tool call that this result is associated with.
454 ToolCallID string `json:"tool_call_id"`
455 // Name of the tool that generated this result.
456 ToolName string `json:"tool_name"`
457 // Result of the tool call. This is a JSON-serializable object.
458 Result ToolResultOutputContent `json:"result"`
459 ClientMetadata string `json:"client_metadata"` // Metadata from the client that executed the tool
460 // Whether the tool result was generated by the provider.
461 // If this flag is set to true, the tool result was generated by the provider.
462 // If this flag is not set or is false, the tool result was generated by the client.
463 ProviderExecuted bool `json:"provider_executed"`
464 // Additional provider-specific metadata for the tool result.
465 ProviderMetadata ProviderMetadata `json:"provider_metadata"`
466}
467
468// GetType returns the type of the tool result content.
469func (t ToolResultContent) GetType() ContentType {
470 return ContentTypeToolResult
471}
472
473// ToolType represents the type of tool.
474type ToolType string
475
476const (
477 // ToolTypeFunction represents a function tool.
478 ToolTypeFunction ToolType = "function"
479 // ToolTypeProviderDefined represents a provider-defined tool.
480 ToolTypeProviderDefined ToolType = "provider-defined"
481)
482
483// Tool represents a tool that can be used by the model.
484//
485// Note: this is **not** the user-facing tool definition. The AI SDK methods will
486// map the user-facing tool definitions to this format.
487type Tool interface {
488 GetType() ToolType
489 GetName() string
490}
491
492// FunctionTool represents a function tool.
493//
494// A tool has a name, a description, and a set of parameters.
495type FunctionTool struct {
496 // Name of the tool. Unique within this model call.
497 Name string `json:"name"`
498 // Description of the tool. The language model uses this to understand the
499 // tool's purpose and to provide better completion suggestions.
500 Description string `json:"description"`
501 // InputSchema - the parameters that the tool expects. The language model uses this to
502 // understand the tool's input requirements and to provide matching suggestions.
503 InputSchema map[string]any `json:"input_schema"` // JSON Schema
504 // ProviderOptions are provider-specific options for the tool.
505 ProviderOptions ProviderOptions `json:"provider_options"`
506}
507
508// GetType returns the type of the function tool.
509func (f FunctionTool) GetType() ToolType {
510 return ToolTypeFunction
511}
512
513// GetName returns the name of the function tool.
514func (f FunctionTool) GetName() string {
515 return f.Name
516}
517
518// ProviderTool is a tool whose schema and wire format are defined by
519// the model provider. Both pure provider-executed tools
520// (ProviderDefinedTool) and client-executed provider tools
521// (ExecutableProviderTool) implement this interface. The unexported
522// method seals this interface to the types in this package.
523// External packages should use NewExecutableProviderTool instead.
524type ProviderTool interface {
525 providerDefinedTool() ProviderDefinedTool
526}
527
528// ProviderDefinedTool represents the configuration of a tool that is defined by the provider.
529type ProviderDefinedTool struct {
530 // ID of the tool. Should follow the format `<provider-name>.<unique-tool-name>`.
531 ID string `json:"id"`
532 // Name of the tool that the user must use in the tool set.
533 Name string `json:"name"`
534 // Args for configuring the tool. Must match the expected arguments defined by the provider for this tool.
535 Args map[string]any `json:"args"`
536}
537
538// GetType returns the type of the provider-defined tool.
539func (p ProviderDefinedTool) GetType() ToolType {
540 return ToolTypeProviderDefined
541}
542
543// GetName returns the name of the provider-defined tool.
544func (p ProviderDefinedTool) GetName() string {
545 return p.Name
546}
547
548func (p ProviderDefinedTool) providerDefinedTool() ProviderDefinedTool {
549 return p
550}
551
552// ExecutableProviderTool pairs a ProviderDefinedTool with a
553// client-side execution function. Use this for provider-defined tools
554// that require local execution (e.g. Anthropic computer use). Register
555// it via WithProviderDefinedTools.
556type ExecutableProviderTool struct {
557 pdt ProviderDefinedTool
558 run func(ctx context.Context, call ToolCall) (ToolResponse, error)
559}
560
561func (e ExecutableProviderTool) providerDefinedTool() ProviderDefinedTool {
562 return e.pdt
563}
564
565// GetType returns the type of the underlying ProviderDefinedTool.
566func (e ExecutableProviderTool) GetType() ToolType {
567 return e.pdt.GetType()
568}
569
570// GetName returns the name of the underlying ProviderDefinedTool.
571func (e ExecutableProviderTool) GetName() string {
572 return e.pdt.GetName()
573}
574
575// Definition returns the underlying ProviderDefinedTool.
576func (e ExecutableProviderTool) Definition() ProviderDefinedTool {
577 return e.pdt
578}
579
580// Run executes the tool's client-side function.
581func (e ExecutableProviderTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) {
582 return e.run(ctx, call)
583}
584
585// NewExecutableProviderTool creates a provider-defined tool with
586// client-side execution. The tool is sent to the API using the
587// provider's native wire format, but executed locally by run.
588func NewExecutableProviderTool(
589 pdt ProviderDefinedTool,
590 run func(ctx context.Context, call ToolCall) (ToolResponse, error),
591) ExecutableProviderTool {
592 return ExecutableProviderTool{pdt: pdt, run: run}
593}
594
595// NewUserMessage creates a new user message with the given prompt and optional files.
596func NewUserMessage(prompt string, files ...FilePart) Message {
597 content := make([]MessagePart, 0, len(files)+1)
598 content = append(content, TextPart{Text: prompt})
599
600 for _, f := range files {
601 content = append(content, f)
602 }
603
604 return Message{
605 Role: MessageRoleUser,
606 Content: content,
607 }
608}
609
610// NewSystemMessage creates a new system message with the given prompts.
611func NewSystemMessage(prompt ...string) Message {
612 content := make([]MessagePart, 0, len(prompt))
613 for _, p := range prompt {
614 content = append(content, TextPart{Text: p})
615 }
616
617 return Message{
618 Role: MessageRoleSystem,
619 Content: content,
620 }
621}