-module(anthropic@client). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/anthropic/client.gleam"). -export([new/1, handle_response/1, post_json/3, post_and_handle/3]). -export_type([client/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " HTTP client wrapper for Anthropic API calls\n" "\n" " This module provides a client for making requests to the Anthropic Messages API,\n" " handling headers, timeouts, and response parsing.\n" ). -type client() :: {client, anthropic@config:config()}. -file("src/anthropic/client.gleam", 45). ?DOC(" Create a new client from configuration\n"). -spec new(anthropic@config:config()) -> client(). new(Config) -> {client, Config}. -file("src/anthropic/client.gleam", 102). ?DOC(" Convert ConnectError to string\n"). -spec connect_error_to_string(gleam@httpc:connect_error()) -> binary(). connect_error_to_string(Err) -> case Err of {posix, Code} -> <<"POSIX error: "/utf8, Code/binary>>; {tls_alert, Code@1, Detail} -> <<<<<<"TLS alert "/utf8, Code@1/binary>>/binary, ": "/utf8>>/binary, Detail/binary>> end. -file("src/anthropic/client.gleam", 86). ?DOC(" Convert httpc error to AnthropicError\n"). -spec http_error_to_anthropic_error(gleam@httpc:http_error()) -> anthropic@types@error:anthropic_error(). http_error_to_anthropic_error(Err) -> case Err of invalid_utf8_response -> anthropic@types@error:http_error( <<"Invalid UTF-8 in response"/utf8>> ); {failed_to_connect, Ip4, Ip6} -> anthropic@types@error:network_error( <<<<<<<<"Failed to connect to server (IPv4: "/utf8, (connect_error_to_string(Ip4))/binary>>/binary, ", IPv6: "/utf8>>/binary, (connect_error_to_string(Ip6))/binary>>/binary, ")"/utf8>> ); response_timeout -> anthropic@types@error:timeout_error(0) end. -file("src/anthropic/client.gleam", 174). ?DOC(" Error details decoder\n"). -spec error_details_decoder() -> gleam@dynamic@decode:decoder({anthropic@types@error:api_error_type(), binary(), gleam@option:option(binary()), gleam@option:option(binary())}). error_details_decoder() -> gleam@dynamic@decode:field( <<"type"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Error_type_str) -> gleam@dynamic@decode:field( <<"message"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Message) -> gleam@dynamic@decode:optional_field( <<"param"/utf8>>, none, begin _pipe = {decoder, fun gleam@dynamic@decode:decode_string/1}, gleam@dynamic@decode:map( _pipe, fun(Field@0) -> {some, Field@0} end ) end, fun(Param) -> gleam@dynamic@decode:optional_field( <<"code"/utf8>>, none, begin _pipe@1 = {decoder, fun gleam@dynamic@decode:decode_string/1}, gleam@dynamic@decode:map( _pipe@1, fun(Field@0) -> {some, Field@0} end ) end, fun(Code) -> Error_type = anthropic@types@error:api_error_type_from_string( Error_type_str ), gleam@dynamic@decode:success( {Error_type, Message, Param, Code} ) end ) end ) end ) end ). -file("src/anthropic/client.gleam", 195). ?DOC(" Error wrapper decoder\n"). -spec error_wrapper_decoder() -> gleam@dynamic@decode:decoder({anthropic@types@error:api_error_type(), binary(), gleam@option:option(binary()), gleam@option:option(binary())}). error_wrapper_decoder() -> gleam@dynamic@decode:field( <<"error"/utf8>>, error_details_decoder(), fun(Details) -> gleam@dynamic@decode:success(Details) end ). -file("src/anthropic/client.gleam", 203). ?DOC(" Parse error body JSON\n"). -spec parse_error_body(binary()) -> {ok, {anthropic@types@error:api_error_type(), binary(), gleam@option:option(binary()), gleam@option:option(binary())}} | {error, nil}. parse_error_body(Body) -> case gleam_json_ffi:decode(Body) of {ok, Dyn} -> case gleam@dynamic@decode:run(Dyn, error_wrapper_decoder()) of {ok, Details} -> {ok, Details}; {error, _} -> {error, nil} end; {error, _} -> {error, nil} end. -file("src/anthropic/client.gleam", 151). ?DOC(" Parse an error response body into ApiError\n"). -spec parse_api_error( integer(), binary(), anthropic@types@error:api_error_type() ) -> anthropic@types@error:anthropic_error(). parse_api_error(Status_code, Body, Default_type) -> case parse_error_body(Body) of {ok, {Error_type, Message, Param, Code}} -> anthropic@types@error:api_error( Status_code, anthropic@types@error:api_error_details_full( Error_type, Message, Param, Code ) ); {error, _} -> anthropic@types@error:api_error( Status_code, anthropic@types@error:api_error_details(Default_type, Body) ) end. -file("src/anthropic/client.gleam", 114). ?DOC(" Handle an API response, parsing success or error\n"). -spec handle_response(gleam@http@response:response(binary())) -> {ok, binary()} | {error, anthropic@types@error:anthropic_error()}. handle_response(Response) -> Status = erlang:element(2, Response), case Status of 200 -> {ok, erlang:element(4, Response)}; 400 -> {error, parse_api_error( Status, erlang:element(4, Response), invalid_request_error )}; 401 -> {error, parse_api_error( Status, erlang:element(4, Response), authentication_error )}; 403 -> {error, parse_api_error( Status, erlang:element(4, Response), permission_error )}; 404 -> {error, parse_api_error( Status, erlang:element(4, Response), not_found_error )}; 429 -> {error, parse_api_error( Status, erlang:element(4, Response), rate_limit_error )}; 500 -> {error, parse_api_error( Status, erlang:element(4, Response), internal_api_error )}; 529 -> {error, parse_api_error( Status, erlang:element(4, Response), overloaded_error )}; _ when (Status >= 400) andalso (Status < 500) -> {error, parse_api_error( Status, erlang:element(4, Response), invalid_request_error )}; _ when Status >= 500 -> {error, parse_api_error( Status, erlang:element(4, Response), internal_api_error )}; _ -> {error, anthropic@types@error:http_error( <<"Unexpected status code: "/utf8, (gleam@string:inspect(Status))/binary>> )} end. -file("src/anthropic/client.gleam", 54). ?DOC(" Make a POST request with JSON body to the specified path\n"). -spec post_json(client(), binary(), binary()) -> {ok, gleam@http@response:response(binary())} | {error, anthropic@types@error:anthropic_error()}. post_json(Client, Path, Body) -> Base_url = erlang:element(3, erlang:element(2, Client)), Full_url = <>, gleam@result:'try'( begin _pipe = gleam@http@request:to(Full_url), gleam@result:map_error( _pipe, fun(_) -> anthropic@types@error:config_error( <<"Invalid URL: "/utf8, Full_url/binary>> ) end ) end, fun(Req) -> Req@1 = begin _pipe@1 = Req, _pipe@2 = gleam@http@request:set_method(_pipe@1, post), _pipe@3 = gleam@http@request:set_header( _pipe@2, <<"content-type"/utf8>>, <<"application/json"/utf8>> ), _pipe@4 = gleam@http@request:set_header( _pipe@3, <<"x-api-key"/utf8>>, erlang:element(2, erlang:element(2, Client)) ), _pipe@5 = gleam@http@request:set_header( _pipe@4, <<"anthropic-version"/utf8>>, <<"2023-06-01"/utf8>> ), gleam@http@request:set_body(_pipe@5, Body) end, _pipe@6 = gleam@httpc:send(Req@1), gleam@result:map_error( _pipe@6, fun(Err) -> http_error_to_anthropic_error(Err) end ) end ). -file("src/anthropic/client.gleam", 225). ?DOC(" Make a POST request and handle the response\n"). -spec post_and_handle(client(), binary(), binary()) -> {ok, binary()} | {error, anthropic@types@error:anthropic_error()}. post_and_handle(Client, Path, Body) -> gleam@result:'try'( post_json(Client, Path, Body), fun(Response) -> handle_response(Response) end ).