-module(anthropic@tools). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/anthropic/tools.gleam"). -export([needs_tool_execution/1, extract_tool_calls/1, get_tool_call_by_id/2, get_tool_calls_by_name/2, get_first_tool_call/1, count_tool_calls/1, get_tool_names/1, has_tool_call/2, tool_result_to_content_block/1, create_tool_result_message/1, build_tool_result_messages/3, build_continuation_messages/2, success_for_call/2, failure_for_call/2, execute_tool_calls/2, map_tool_calls/2, dispatch_tool_call/2, dispatch_tool_calls/2, all_tools_succeeded/1, any_tools_failed/1, get_failures/1, get_successes/1, get_error_message/1, get_success_content/1]). -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( " Tool use utilities for handling the complete tool workflow\n" "\n" " This module provides utilities for:\n" " - Extracting tool calls from responses\n" " - Building tool result messages\n" " - Managing the tool_use -> execute -> tool_result flow\n" "\n" " ## Tool Use Workflow\n" "\n" " 1. Send a request with tools defined\n" " 2. Claude responds with tool_use blocks (stop_reason: \"tool_use\")\n" " 3. Extract tool calls from the response\n" " 4. Execute the tools and collect results\n" " 5. Send a new request with tool_result blocks\n" " 6. Claude responds with the final answer\n" "\n" " ## Example\n" "\n" " ```gleam\n" " // Step 1: Create request with tools\n" " let request = create_request(model, messages, max_tokens)\n" " |> with_tools([weather_tool])\n" "\n" " // Step 2: Get response\n" " let response = api.create_message(client, request)\n" "\n" " // Step 3: Check for tool use and extract calls\n" " case needs_tool_execution(response) {\n" " True -> {\n" " let tool_calls = extract_tool_calls(response)\n" " // Step 4: Execute tools and build results\n" " let results = list.map(tool_calls, fn(call) {\n" " let result = execute_my_tool(call.name, call.input)\n" " tool_success(call.id, result)\n" " })\n" " // Step 5: Continue conversation with tool results\n" " let messages = build_tool_result_messages(response, results)\n" " let next_request = create_request(model, messages, max_tokens)\n" " api.create_message(client, next_request)\n" " }\n" " False -> response\n" " }\n" " ```\n" ). -file("src/anthropic/tools.gleam", 62). ?DOC( " Check if a response requires tool execution\n" " Returns True if stop_reason is ToolUse\n" ). -spec needs_tool_execution(anthropic@types@request:create_message_response()) -> boolean(). needs_tool_execution(Response) -> case erlang:element(7, Response) of {some, tool_use} -> true; _ -> false end. -file("src/anthropic/tools.gleam", 70). ?DOC(" Extract all tool calls from a response\n"). -spec extract_tool_calls(anthropic@types@request:create_message_response()) -> list(anthropic@types@tool:tool_call()). extract_tool_calls(Response) -> _pipe = erlang:element(5, Response), gleam@list:filter_map(_pipe, fun(Block) -> case Block of {tool_use_block, Id, Name, Input} -> {ok, {tool_call, Id, Name, Input}}; _ -> {error, nil} end end). -file("src/anthropic/tools.gleam", 82). ?DOC(" Extract a specific tool call by ID\n"). -spec get_tool_call_by_id( anthropic@types@request:create_message_response(), binary() ) -> {ok, anthropic@types@tool:tool_call()} | {error, nil}. get_tool_call_by_id(Response, Tool_id) -> _pipe = extract_tool_calls(Response), gleam@list:find(_pipe, fun(Call) -> erlang:element(2, Call) =:= Tool_id end). -file("src/anthropic/tools.gleam", 91). ?DOC(" Extract tool calls by name\n"). -spec get_tool_calls_by_name( anthropic@types@request:create_message_response(), binary() ) -> list(anthropic@types@tool:tool_call()). get_tool_calls_by_name(Response, Tool_name) -> _pipe = extract_tool_calls(Response), gleam@list:filter( _pipe, fun(Call) -> erlang:element(3, Call) =:= Tool_name end ). -file("src/anthropic/tools.gleam", 100). ?DOC(" Get the first tool call from a response\n"). -spec get_first_tool_call(anthropic@types@request:create_message_response()) -> {ok, anthropic@types@tool:tool_call()} | {error, nil}. get_first_tool_call(Response) -> _pipe = extract_tool_calls(Response), gleam@list:first(_pipe). -file("src/anthropic/tools.gleam", 108). ?DOC(" Count the number of tool calls in a response\n"). -spec count_tool_calls(anthropic@types@request:create_message_response()) -> integer(). count_tool_calls(Response) -> _pipe = extract_tool_calls(Response), erlang:length(_pipe). -file("src/anthropic/tools.gleam", 114). ?DOC(" Get all unique tool names from a response\n"). -spec get_tool_names(anthropic@types@request:create_message_response()) -> list(binary()). get_tool_names(Response) -> _pipe = extract_tool_calls(Response), _pipe@1 = gleam@list:map(_pipe, fun(Call) -> erlang:element(3, Call) end), gleam@list:unique(_pipe@1). -file("src/anthropic/tools.gleam", 121). ?DOC(" Check if a response contains a specific tool call\n"). -spec has_tool_call(anthropic@types@request:create_message_response(), binary()) -> boolean(). has_tool_call(Response, Tool_name) -> _pipe = extract_tool_calls(Response), gleam@list:any( _pipe, fun(Call) -> erlang:element(3, Call) =:= Tool_name end ). -file("src/anthropic/tools.gleam", 131). ?DOC(" Create a tool result content block from a ToolResult\n"). -spec tool_result_to_content_block(anthropic@types@tool:tool_result()) -> anthropic@types@message:content_block(). tool_result_to_content_block(Result) -> case Result of {tool_success, Tool_use_id, Content} -> {tool_result_block, Tool_use_id, Content, none}; {tool_failure, Tool_use_id@1, Error} -> {tool_result_block, Tool_use_id@1, Error, {some, true}} end. -file("src/anthropic/tools.gleam", 149). ?DOC(" Create a user message with tool results\n"). -spec create_tool_result_message(list(anthropic@types@tool:tool_result())) -> anthropic@types@message:message(). create_tool_result_message(Results) -> Content = gleam@list:map(Results, fun tool_result_to_content_block/1), {message, user, Content}. -file("src/anthropic/tools.gleam", 157). ?DOC( " Build the complete message list for continuing a conversation after tool use\n" " This includes the original messages, the assistant's tool use response,\n" " and the user's tool results\n" ). -spec build_tool_result_messages( list(anthropic@types@message:message()), anthropic@types@request:create_message_response(), list(anthropic@types@tool:tool_result()) ) -> list(anthropic@types@message:message()). build_tool_result_messages(Original_messages, Assistant_response, Tool_results) -> Assistant_message = {message, assistant, erlang:element(5, Assistant_response)}, Tool_result_message = create_tool_result_message(Tool_results), lists:append(Original_messages, [Assistant_message, Tool_result_message]). -file("src/anthropic/tools.gleam", 174). ?DOC( " Simplified version: build messages from just the response and results\n" " Assumes original messages are tracked elsewhere\n" ). -spec build_continuation_messages( anthropic@types@request:create_message_response(), list(anthropic@types@tool:tool_result()) ) -> list(anthropic@types@message:message()). build_continuation_messages(Assistant_response, Tool_results) -> Assistant_message = {message, assistant, erlang:element(5, Assistant_response)}, Tool_result_message = create_tool_result_message(Tool_results), [Assistant_message, Tool_result_message]. -file("src/anthropic/tools.gleam", 189). ?DOC(" Create a successful tool result for a specific tool call\n"). -spec success_for_call(anthropic@types@tool:tool_call(), binary()) -> anthropic@types@tool:tool_result(). success_for_call(Call, Content) -> {tool_success, erlang:element(2, Call), Content}. -file("src/anthropic/tools.gleam", 194). ?DOC(" Create a failed tool result for a specific tool call\n"). -spec failure_for_call(anthropic@types@tool:tool_call(), binary()) -> anthropic@types@tool:tool_result(). failure_for_call(Call, Error) -> {tool_failure, erlang:element(2, Call), Error}. -file("src/anthropic/tools.gleam", 200). ?DOC( " Execute a handler function on each tool call and collect results\n" " The handler should return Ok(content) for success or Error(message) for failure\n" ). -spec execute_tool_calls( list(anthropic@types@tool:tool_call()), fun((anthropic@types@tool:tool_call()) -> {ok, binary()} | {error, binary()}) ) -> list(anthropic@types@tool:tool_result()). execute_tool_calls(Calls, Handler) -> gleam@list:map(Calls, fun(Call) -> case Handler(Call) of {ok, Content} -> {tool_success, erlang:element(2, Call), Content}; {error, Err} -> {tool_failure, erlang:element(2, Call), Err} end end). -file("src/anthropic/tools.gleam", 213). ?DOC(" Execute a handler that returns a ToolResult directly\n"). -spec map_tool_calls( list(anthropic@types@tool:tool_call()), fun((anthropic@types@tool:tool_call()) -> anthropic@types@tool:tool_result()) ) -> list(anthropic@types@tool:tool_result()). map_tool_calls(Calls, Handler) -> gleam@list:map(Calls, Handler). -file("src/anthropic/tools.gleam", 222). ?DOC( " Match a tool call by name and execute the appropriate handler\n" " Returns an error message if no handler matches\n" ). -spec dispatch_tool_call( anthropic@types@tool:tool_call(), list({binary(), fun((binary()) -> {ok, binary()} | {error, binary()})}) ) -> anthropic@types@tool:tool_result(). dispatch_tool_call(Call, Handlers) -> case gleam@list:find( Handlers, fun(H) -> erlang:element(1, H) =:= erlang:element(3, Call) end ) of {ok, {_, Handler}} -> case Handler(erlang:element(4, Call)) of {ok, Content} -> {tool_success, erlang:element(2, Call), Content}; {error, Err} -> {tool_failure, erlang:element(2, Call), Err} end; {error, _} -> {tool_failure, erlang:element(2, Call), <<"Unknown tool: "/utf8, (erlang:element(3, Call))/binary>>} end. -file("src/anthropic/tools.gleam", 239). ?DOC(" Dispatch multiple tool calls using a handler map\n"). -spec dispatch_tool_calls( list(anthropic@types@tool:tool_call()), list({binary(), fun((binary()) -> {ok, binary()} | {error, binary()})}) ) -> list(anthropic@types@tool:tool_result()). dispatch_tool_calls(Calls, Handlers) -> gleam@list:map(Calls, fun(Call) -> dispatch_tool_call(Call, Handlers) end). -file("src/anthropic/tools.gleam", 251). ?DOC(" Check if all tool results are successful\n"). -spec all_tools_succeeded(list(anthropic@types@tool:tool_result())) -> boolean(). all_tools_succeeded(Results) -> gleam@list:all(Results, fun(R) -> case R of {tool_success, _, _} -> true; {tool_failure, _, _} -> false end end). -file("src/anthropic/tools.gleam", 261). ?DOC(" Check if any tool results failed\n"). -spec any_tools_failed(list(anthropic@types@tool:tool_result())) -> boolean(). any_tools_failed(Results) -> gleam@list:any(Results, fun(R) -> case R of {tool_success, _, _} -> false; {tool_failure, _, _} -> true end end). -file("src/anthropic/tools.gleam", 271). ?DOC(" Get all failed tool results\n"). -spec get_failures(list(anthropic@types@tool:tool_result())) -> list(anthropic@types@tool:tool_result()). get_failures(Results) -> gleam@list:filter(Results, fun(R) -> case R of {tool_success, _, _} -> false; {tool_failure, _, _} -> true end end). -file("src/anthropic/tools.gleam", 281). ?DOC(" Get all successful tool results\n"). -spec get_successes(list(anthropic@types@tool:tool_result())) -> list(anthropic@types@tool:tool_result()). get_successes(Results) -> gleam@list:filter(Results, fun(R) -> case R of {tool_success, _, _} -> true; {tool_failure, _, _} -> false end end). -file("src/anthropic/tools.gleam", 291). ?DOC(" Get the error message from a ToolResult if it's a failure\n"). -spec get_error_message(anthropic@types@tool:tool_result()) -> gleam@option:option(binary()). get_error_message(Result) -> case Result of {tool_success, _, _} -> none; {tool_failure, _, Error} -> {some, Error} end. -file("src/anthropic/tools.gleam", 299). ?DOC(" Get the content from a ToolResult if it's a success\n"). -spec get_success_content(anthropic@types@tool:tool_result()) -> gleam@option:option(binary()). get_success_content(Result) -> case Result of {tool_success, _, Content} -> {some, Content}; {tool_failure, _, _} -> none end.