Source file anthropic_error.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
open Melange_json.Primitives

type anthropic_error_type =
  | Invalid_request_error
  | Authentication_error
  | Permission_error
  | Not_found_error
  | Rate_limit_error
  | Api_error
  | Overloaded_error
  | Unknown_error of string

type anthropic_error = {
  error_type : anthropic_error_type;
  message : string;
}

let error_type_of_string = function
  | "invalid_request_error" -> Invalid_request_error
  | "authentication_error" -> Authentication_error
  | "permission_error" -> Permission_error
  | "not_found_error" -> Not_found_error
  | "rate_limit_error" -> Rate_limit_error
  | "api_error" -> Api_error
  | "overloaded_error" -> Overloaded_error
  | s -> Unknown_error s

type error_detail = {
  typ : string; [@json.key "type"]
  message : string;
}
[@@deriving of_json]

type error_envelope = { error : error_detail } [@@deriving of_json]

let is_retryable = function
  | Rate_limit_error | Overloaded_error -> true
  | Invalid_request_error | Authentication_error | Permission_error | Not_found_error | Api_error | Unknown_error _ ->
    false

let of_response ~status ~body =
  let error_type, message =
    try
      let json = Yojson.Basic.from_string body in
      let { error = { typ; message } } = error_envelope_of_json json in
      Some (error_type_of_string typ), message
    with
    | Yojson.Json_error _ -> None, body
    | Melange_json.Of_json_error _ -> None, body
  in
  let body =
    match error_type with
    | Some t when is_retryable t -> "[retryable] " ^ message
    | Some _ | None -> message
  in
  { Ai_provider.Provider_error.provider = "anthropic"; kind = Api_error { status; body } }