content.go

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