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