Packages

A well-typed, idiomatic Gleam client for Anthropic's Claude API with streaming support and tool use

Current section

Files

Jump to
anthropic_gleam src anthropic@tools@builder.erl
Raw

src/anthropic@tools@builder.erl

-module(anthropic@tools@builder).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/anthropic/tools/builder.gleam").
-export([tool_builder/1, tool_builder_with_description/2, with_description/2, add_property/4, add_string_param/4, add_number_param/4, add_integer_param/4, add_boolean_param/4, add_enum_param/5, add_string_array_param/5, add_number_array_param/4, add_object_param/6, build/1, build_simple/1, builder_error_to_string/1, validate_name/1, build_validated/1]).
-export_type([tool_builder/0, tool_builder_error/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(
" Fluent builder for tool definitions\n"
"\n"
" This module provides an ergonomic builder API for creating tool definitions.\n"
" The builder pattern allows for type-safe, readable tool construction.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" let weather_tool =\n"
" tool_builder(\"get_weather\")\n"
" |> with_description(\"Get the current weather for a location\")\n"
" |> add_string_param(\"location\", \"City and state, e.g. 'San Francisco, CA'\", True)\n"
" |> add_enum_param(\"unit\", \"Temperature unit\", [\"celsius\", \"fahrenheit\"], False)\n"
" |> build()\n"
"\n"
" // For tools with no parameters\n"
" let time_tool =\n"
" tool_builder(\"get_time\")\n"
" |> with_description(\"Get the current time\")\n"
" |> build_simple()\n"
" ```\n"
).
-type tool_builder() :: {tool_builder,
binary(),
gleam@option:option(binary()),
list({binary(), anthropic@tool:property_schema()}),
list(binary())}.
-type tool_builder_error() :: {invalid_tool_name,
anthropic@tool:tool_name_error()} |
{duplicate_property, binary()}.
-file("src/anthropic/tools/builder.gleam", 55).
?DOC(" Start building a new tool with the given name\n").
-spec tool_builder(binary()) -> tool_builder().
tool_builder(Name) ->
{tool_builder, Name, none, [], []}.
-file("src/anthropic/tools/builder.gleam", 60).
?DOC(" Start building a new tool with name and description\n").
-spec tool_builder_with_description(binary(), binary()) -> tool_builder().
tool_builder_with_description(Name, Description) ->
{tool_builder, Name, {some, Description}, [], []}.
-file("src/anthropic/tools/builder.gleam", 77).
?DOC(" Set the description for the tool\n").
-spec with_description(tool_builder(), binary()) -> tool_builder().
with_description(Builder, Description) ->
{tool_builder,
erlang:element(2, Builder),
{some, Description},
erlang:element(4, Builder),
erlang:element(5, Builder)}.
-file("src/anthropic/tools/builder.gleam", 247).
?DOC(" Add a custom property schema\n").
-spec add_property(
tool_builder(),
binary(),
anthropic@tool:property_schema(),
boolean()
) -> tool_builder().
add_property(Builder, Name, Property, Is_required) ->
New_properties = lists:append(
erlang:element(4, Builder),
[{Name, Property}]
),
New_required = case Is_required of
true ->
lists:append(erlang:element(5, Builder), [Name]);
false ->
erlang:element(5, Builder)
end,
{tool_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
New_properties,
New_required}.
-file("src/anthropic/tools/builder.gleam", 85).
?DOC(" Add a string parameter\n").
-spec add_string_param(tool_builder(), binary(), binary(), boolean()) -> tool_builder().
add_string_param(Builder, Name, Description, Is_required) ->
Prop = {property_schema,
<<"string"/utf8>>,
{some, Description},
none,
none,
none,
none},
add_property(Builder, Name, Prop, Is_required).
-file("src/anthropic/tools/builder.gleam", 105).
?DOC(" Add a number parameter\n").
-spec add_number_param(tool_builder(), binary(), binary(), boolean()) -> tool_builder().
add_number_param(Builder, Name, Description, Is_required) ->
Prop = {property_schema,
<<"number"/utf8>>,
{some, Description},
none,
none,
none,
none},
add_property(Builder, Name, Prop, Is_required).
-file("src/anthropic/tools/builder.gleam", 125).
?DOC(" Add an integer parameter\n").
-spec add_integer_param(tool_builder(), binary(), binary(), boolean()) -> tool_builder().
add_integer_param(Builder, Name, Description, Is_required) ->
Prop = {property_schema,
<<"integer"/utf8>>,
{some, Description},
none,
none,
none,
none},
add_property(Builder, Name, Prop, Is_required).
-file("src/anthropic/tools/builder.gleam", 145).
?DOC(" Add a boolean parameter\n").
-spec add_boolean_param(tool_builder(), binary(), binary(), boolean()) -> tool_builder().
add_boolean_param(Builder, Name, Description, Is_required) ->
Prop = {property_schema,
<<"boolean"/utf8>>,
{some, Description},
none,
none,
none,
none},
add_property(Builder, Name, Prop, Is_required).
-file("src/anthropic/tools/builder.gleam", 165).
?DOC(" Add an enum parameter (string with allowed values)\n").
-spec add_enum_param(
tool_builder(),
binary(),
binary(),
list(binary()),
boolean()
) -> tool_builder().
add_enum_param(Builder, Name, Description, Values, Is_required) ->
Prop = {property_schema,
<<"string"/utf8>>,
{some, Description},
{some, Values},
none,
none,
none},
add_property(Builder, Name, Prop, Is_required).
-file("src/anthropic/tools/builder.gleam", 186).
?DOC(" Add an array parameter with string items\n").
-spec add_string_array_param(
tool_builder(),
binary(),
binary(),
binary(),
boolean()
) -> tool_builder().
add_string_array_param(
Builder,
Name,
Description,
Item_description,
Is_required
) ->
Item_schema = {property_schema,
<<"string"/utf8>>,
{some, Item_description},
none,
none,
none,
none},
Prop = {property_schema,
<<"array"/utf8>>,
{some, Description},
none,
{some, Item_schema},
none,
none},
add_property(Builder, Name, Prop, Is_required).
-file("src/anthropic/tools/builder.gleam", 217).
?DOC(" Add an array parameter with number items\n").
-spec add_number_array_param(tool_builder(), binary(), binary(), boolean()) -> tool_builder().
add_number_array_param(Builder, Name, Description, Is_required) ->
Item_schema = {property_schema,
<<"number"/utf8>>,
none,
none,
none,
none,
none},
Prop = {property_schema,
<<"array"/utf8>>,
{some, Description},
none,
{some, Item_schema},
none,
none},
add_property(Builder, Name, Prop, Is_required).
-file("src/anthropic/tools/builder.gleam", 263).
?DOC(" Add an object parameter with nested properties\n").
-spec add_object_param(
tool_builder(),
binary(),
binary(),
list({binary(), anthropic@tool:property_schema()}),
list(binary()),
boolean()
) -> tool_builder().
add_object_param(
Builder,
Name,
Description,
Nested_properties,
Nested_required,
Is_required
) ->
Prop = {property_schema,
<<"object"/utf8>>,
{some, Description},
none,
none,
{some, Nested_properties},
{some, Nested_required}},
add_property(Builder, Name, Prop, Is_required).
-file("src/anthropic/tools/builder.gleam", 292).
?DOC(
" Build the tool from the builder state without validation.\n"
"\n"
" Use this when you trust the tool name is valid (e.g., hardcoded constants).\n"
" For untrusted input, use `build_validated()` instead.\n"
).
-spec build(tool_builder()) -> anthropic@tool:tool().
build(Builder) ->
Input_schema = case erlang:element(4, Builder) of
[] ->
{input_schema, <<"object"/utf8>>, none, none};
Props ->
{input_schema,
<<"object"/utf8>>,
{some, Props},
case erlang:element(5, Builder) of
[] ->
none;
Reqs ->
{some, Reqs}
end}
end,
{tool,
anthropic@tool:tool_name_unchecked(erlang:element(2, Builder)),
erlang:element(3, Builder),
Input_schema}.
-file("src/anthropic/tools/builder.gleam", 317).
?DOC(
" Build a simple tool with no parameters without validation.\n"
"\n"
" Use this when you trust the tool name is valid (e.g., hardcoded constants).\n"
" For untrusted input, use `build_validated()` instead.\n"
).
-spec build_simple(tool_builder()) -> anthropic@tool:tool().
build_simple(Builder) ->
{tool,
anthropic@tool:tool_name_unchecked(erlang:element(2, Builder)),
erlang:element(3, Builder),
{input_schema, <<"object"/utf8>>, none, none}}.
-file("src/anthropic/tools/builder.gleam", 342).
?DOC(" Convert a ToolBuilderError to a human-readable string\n").
-spec builder_error_to_string(tool_builder_error()) -> binary().
builder_error_to_string(Error) ->
case Error of
{invalid_tool_name, Name_error} ->
anthropic@tool:tool_name_error_to_string(Name_error);
{duplicate_property, Name} ->
<<"Duplicate property name: "/utf8, Name/binary>>
end.
-file("src/anthropic/tools/builder.gleam", 354).
?DOC(
" Validate a tool name according to Anthropic's requirements.\n"
"\n"
" Must match regex: ^[a-zA-Z0-9_-]{1,64}$\n"
"\n"
" Returns the validated ToolName on success.\n"
).
-spec validate_name(binary()) -> {ok, anthropic@tool:tool_name()} |
{error, tool_builder_error()}.
validate_name(Name) ->
_pipe = anthropic@tool:tool_name(Name),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {invalid_tool_name, Field@0} end
).
-file("src/anthropic/tools/builder.gleam", 410).
-spec has_duplicates(list(binary())) -> boolean().
has_duplicates(Items) ->
erlang:length(Items) /= erlang:length(gleam@list:unique(Items)).
-file("src/anthropic/tools/builder.gleam", 418).
-spec find_first_duplicate_helper(list(binary()), list(binary())) -> gleam@option:option(binary()).
find_first_duplicate_helper(Remaining, Seen) ->
case Remaining of
[] ->
none;
[First | Rest] ->
case gleam@list:contains(Seen, First) of
true ->
{some, First};
false ->
find_first_duplicate_helper(Rest, [First | Seen])
end
end.
-file("src/anthropic/tools/builder.gleam", 414).
-spec find_first_duplicate(list(binary())) -> gleam@option:option(binary()).
find_first_duplicate(Items) ->
find_first_duplicate_helper(Items, []).
-file("src/anthropic/tools/builder.gleam", 366).
?DOC(
" Build and validate the tool.\n"
"\n"
" This validates that:\n"
" - The tool name matches Anthropic's requirements (alphanumeric, _, -, 1-64 chars)\n"
" - No duplicate property names exist\n"
"\n"
" Use this for user-provided or untrusted tool names.\n"
).
-spec build_validated(tool_builder()) -> {ok, anthropic@tool:tool()} |
{error, tool_builder_error()}.
build_validated(Builder) ->
case validate_name(erlang:element(2, Builder)) of
{error, Err} ->
{error, Err};
{ok, Validated_name} ->
Prop_names = gleam@list:map(
erlang:element(4, Builder),
fun(P) -> erlang:element(1, P) end
),
case has_duplicates(Prop_names) of
true ->
Dup = find_first_duplicate(Prop_names),
{error,
{duplicate_property,
gleam@option:unwrap(Dup, <<""/utf8>>)}};
false ->
Input_schema = case erlang:element(4, Builder) of
[] ->
{input_schema, <<"object"/utf8>>, none, none};
Props ->
{input_schema,
<<"object"/utf8>>,
{some, Props},
case erlang:element(5, Builder) of
[] ->
none;
Reqs ->
{some, Reqs}
end}
end,
{ok,
{tool,
Validated_name,
erlang:element(3, Builder),
Input_schema}}
end
end.