errors.go

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