<%= if @reasoning_content && @reasoning_content != "" do %>
<% end %>
<%= for tool_call <- @tool_calls do %>
<.tool_call_item tool_call={tool_call} />
<% end %>
<%= if @content && @content != "" do %>
<% end %>
"""
end
# Dispatches to the appropriate tool call component based on result state.
# Four states:
# :error key present → error (runtime failure)
# :result key present → success (runtime completed)
# :index key present → pending (streaming in-progress)
# none of the above → called (DB-loaded completed call; result is a separate message)
attr :tool_call, :map, required: true
defp tool_call_item(%{tool_call: tool_call} = assigns) do
cond do
Map.has_key?(tool_call, :error) ->
assigns =
assigns
|> assign(:name, tool_call.name)
|> assign(:arguments, tool_call[:arguments])
|> assign(:error, tool_call.error)
~H"<.error_tool_call name={@name} arguments={@arguments} error={@error} />"
Map.has_key?(tool_call, :result) ->
assigns =
assigns
|> assign(:name, tool_call.name)
|> assign(:arguments, tool_call[:arguments])
|> assign(:result, tool_call.result)
~H"<.success_tool_call name={@name} arguments={@arguments} result={@result} />"
Map.has_key?(tool_call, :index) ->
assigns =
assigns
|> assign(:name, tool_call.name)
|> assign(:arguments, tool_call[:arguments])
~H"<.pending_tool_call name={@name} arguments={@arguments} />"
true ->
assigns =
assigns
|> assign(:name, tool_call.name)
|> assign(:arguments, tool_call[:arguments])
~H"<.called_tool_call name={@name} arguments={@arguments} />"
end
end
attr :name, :string, required: true
attr :arguments, :any, default: nil
defp called_tool_call(assigns) do
~H"""
<.tool_call_icon />
{@name}called
<.tool_call_args arguments={@arguments} />
"""
end
attr :name, :string, required: true
attr :arguments, :any, default: nil
defp pending_tool_call(assigns) do
~H"""
<.tool_call_icon />
{@name}running
<.tool_call_args arguments={@arguments} />
"""
end
attr :name, :string, required: true
attr :arguments, :any, default: nil
attr :result, :any, required: true
defp success_tool_call(assigns) do
assigns =
assign(
assigns,
:result_str,
case assigns.result do
s when is_binary(s) -> s
other -> inspect(other, pretty: true, limit: :infinity)
end
)
~H"""
"""
end
attr :arguments, :any, default: nil
defp tool_call_args(%{arguments: args} = assigns) when not is_nil(args) and args != "" do
assigns =
assign(
assigns,
:pretty_args,
case args do
s when is_binary(s) ->
case Jason.decode(s) do
{:ok, decoded} -> Jason.encode!(decoded, pretty: true)
_ -> s
end
other ->
Jason.encode!(other, pretty: true)
end
)
~H"""
arguments
{@pretty_args}
"""
end
defp tool_call_args(assigns), do: ~H""
defp tool_call_icon(assigns) do
~H"""
"""
end
end