errors.go

  1package fantasy
  2
  3import (
  4	"encoding/json"
  5	"errors"
  6	"fmt"
  7)
  8
  9// markerSymbol is used for identifying AI SDK Error instances.
 10var markerSymbol = "fantasy.error"
 11
 12// AIError is a custom error type for AI SDK related errors.
 13type AIError struct {
 14	Name    string
 15	Message string
 16	Cause   error
 17	marker  string
 18}
 19
 20// Error implements the error interface.
 21func (e *AIError) Error() string {
 22	return e.Message
 23}
 24
 25// Unwrap returns the underlying cause of the error.
 26func (e *AIError) Unwrap() error {
 27	return e.Cause
 28}
 29
 30// NewAIError creates a new AI SDK Error.
 31func NewAIError(name, message string, cause error) *AIError {
 32	return &AIError{
 33		Name:    name,
 34		Message: message,
 35		Cause:   cause,
 36		marker:  markerSymbol,
 37	}
 38}
 39
 40// IsAIError checks if the given error is an AI SDK Error.
 41func IsAIError(err error) bool {
 42	var sdkErr *AIError
 43	return errors.As(err, &sdkErr) && sdkErr.marker == markerSymbol
 44}
 45
 46// APICallError represents an error from an API call.
 47type APICallError struct {
 48	*AIError
 49	URL             string
 50	RequestDump     string
 51	StatusCode      int
 52	ResponseHeaders map[string]string
 53	ResponseDump    string
 54	IsRetryable     bool
 55}
 56
 57// NewAPICallError creates a new API call error.
 58func NewAPICallError(message, url string, requestDump string, statusCode int, responseHeaders map[string]string, responseDump string, cause error, isRetryable bool) *APICallError {
 59	if !isRetryable && statusCode != 0 {
 60		isRetryable = statusCode == 408 || statusCode == 409 || statusCode == 429 || statusCode >= 500
 61	}
 62
 63	return &APICallError{
 64		AIError:         NewAIError("AI_APICallError", message, cause),
 65		URL:             url,
 66		RequestDump:     requestDump,
 67		StatusCode:      statusCode,
 68		ResponseHeaders: responseHeaders,
 69		ResponseDump:    responseDump,
 70		IsRetryable:     isRetryable,
 71	}
 72}
 73
 74// InvalidArgumentError represents an invalid function argument error.
 75type InvalidArgumentError struct {
 76	*AIError
 77	Argument string
 78}
 79
 80// NewInvalidArgumentError creates a new invalid argument error.
 81func NewInvalidArgumentError(argument, message string, cause error) *InvalidArgumentError {
 82	return &InvalidArgumentError{
 83		AIError:  NewAIError("AI_InvalidArgumentError", message, cause),
 84		Argument: argument,
 85	}
 86}
 87
 88// InvalidPromptError represents an invalid prompt error.
 89type InvalidPromptError struct {
 90	*AIError
 91	Prompt any
 92}
 93
 94// NewInvalidPromptError creates a new invalid prompt error.
 95func NewInvalidPromptError(prompt any, message string, cause error) *InvalidPromptError {
 96	return &InvalidPromptError{
 97		AIError: NewAIError("AI_InvalidPromptError", fmt.Sprintf("Invalid prompt: %s", message), cause),
 98		Prompt:  prompt,
 99	}
100}
101
102// InvalidResponseDataError represents invalid response data from the server.
103type InvalidResponseDataError struct {
104	*AIError
105	Data any
106}
107
108// NewInvalidResponseDataError creates a new invalid response data error.
109func NewInvalidResponseDataError(data any, message string) *InvalidResponseDataError {
110	if message == "" {
111		dataJSON, _ := json.Marshal(data)
112		message = fmt.Sprintf("Invalid response data: %s.", string(dataJSON))
113	}
114	return &InvalidResponseDataError{
115		AIError: NewAIError("AI_InvalidResponseDataError", message, nil),
116		Data:    data,
117	}
118}
119
120// UnsupportedFunctionalityError represents an unsupported functionality error.
121type UnsupportedFunctionalityError struct {
122	*AIError
123	Functionality string
124}
125
126// NewUnsupportedFunctionalityError creates a new unsupported functionality error.
127func NewUnsupportedFunctionalityError(functionality, message string) *UnsupportedFunctionalityError {
128	if message == "" {
129		message = fmt.Sprintf("'%s' functionality not supported.", functionality)
130	}
131	return &UnsupportedFunctionalityError{
132		AIError:       NewAIError("AI_UnsupportedFunctionalityError", message, nil),
133		Functionality: functionality,
134	}
135}
136
137// GetErrorMessage extracts a message from an error.
138func GetErrorMessage(err error) string {
139	if err == nil {
140		return "unknown error"
141	}
142	return err.Error()
143}