error.go

 1package google
 2
 3import (
 4	"cmp"
 5	"errors"
 6	"io"
 7	"regexp"
 8	"strconv"
 9
10	"charm.land/fantasy"
11	"google.golang.org/genai"
12)
13
14var googleContextPattern = regexp.MustCompile(`input token count.*?(\d+).*?exceeds.*?maximum.*?(\d+)`)
15
16func toProviderErr(err error) error {
17	var apiErr genai.APIError
18	if !errors.As(err, &apiErr) {
19		// Wrap in a `ProviderError` so `.IsRetriable()` works.
20		if errors.Is(err, io.ErrUnexpectedEOF) {
21			return &fantasy.ProviderError{
22				Title:   "stream transport error",
23				Message: err.Error(),
24				Cause:   err,
25			}
26		}
27		return err
28	}
29
30	providerErr := &fantasy.ProviderError{
31		Message:      apiErr.Message,
32		Title:        cmp.Or(fantasy.ErrorTitleForStatusCode(apiErr.Code), "provider request failed"),
33		Cause:        err,
34		StatusCode:   apiErr.Code,
35		ResponseBody: []byte(apiErr.Message),
36	}
37
38	parseContextTooLargeError(apiErr.Message, providerErr)
39
40	return providerErr
41}
42
43func parseContextTooLargeError(message string, providerErr *fantasy.ProviderError) {
44	matches := googleContextPattern.FindStringSubmatch(message)
45	if matches == nil {
46		return
47	}
48	providerErr.ContextTooLargeErr = true
49	providerErr.ContextUsedTokens, _ = strconv.Atoi(matches[1])
50	providerErr.ContextMaxTokens, _ = strconv.Atoi(matches[2])
51}