Packages
claude_code
0.2.0
0.36.5
0.36.4
0.36.3
0.36.2
0.36.1
0.36.0
0.35.0
0.34.0
0.33.1
0.32.2
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.1
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Claude Agent SDK for Elixir – Build AI agents with Claude Code
Current section
Files
Jump to
Current section
Files
lib/claude_code/message/result.ex
defmodule ClaudeCode.Message.Result do
@moduledoc """
Represents a result message from the Claude CLI.
Result messages are the final message in a conversation, containing
the final response, timing information, token usage, and cost.
Matches the official SDK schema for successful results:
```
{
type: "result",
subtype: "success",
duration_ms: float,
duration_api_ms: float,
is_error: boolean,
num_turns: int,
result: string,
session_id: string,
total_cost_usd: float
}
```
And for error results:
```
{
type: "result",
subtype: "error_max_turns" | "error_during_execution",
duration_ms: float,
duration_api_ms: float,
is_error: boolean,
num_turns: int,
session_id: string,
total_cost_usd: float
}
```
"""
alias ClaudeCode.Types
@enforce_keys [
:type,
:subtype,
:is_error,
:duration_ms,
:duration_api_ms,
:num_turns,
:result,
:session_id,
:total_cost_usd,
:usage
]
defstruct [
:type,
:subtype,
:is_error,
:duration_ms,
:duration_api_ms,
:num_turns,
:result,
:session_id,
:total_cost_usd,
:usage
]
@type t :: %__MODULE__{
type: :result,
subtype: Types.result_subtype(),
is_error: boolean(),
duration_ms: float(),
duration_api_ms: float(),
num_turns: non_neg_integer(),
result: String.t(),
session_id: Types.session_id(),
total_cost_usd: float(),
usage: Types.usage()
}
@doc """
Creates a new Result message from JSON data.
## Examples
iex> Result.new(%{"type" => "result", "subtype" => "success", ...})
{:ok, %Result{...}}
iex> Result.new(%{"type" => "assistant"})
{:error, :invalid_message_type}
"""
@spec new(map()) :: {:ok, t()} | {:error, atom() | {:missing_fields, [atom()]}}
def new(%{"type" => "result"} = json) do
required_fields = [
"subtype",
"is_error",
"duration_ms",
"duration_api_ms",
"num_turns",
"result",
"session_id",
"total_cost_usd",
"usage"
]
missing = Enum.filter(required_fields, &(not Map.has_key?(json, &1)))
if Enum.empty?(missing) do
message = %__MODULE__{
type: :result,
subtype: parse_subtype(json["subtype"]),
is_error: json["is_error"],
duration_ms: json["duration_ms"],
duration_api_ms: json["duration_api_ms"],
num_turns: json["num_turns"],
result: json["result"],
session_id: json["session_id"],
total_cost_usd: parse_float(json["total_cost_usd"]),
usage: parse_usage(json["usage"])
}
{:ok, message}
else
{:error, {:missing_fields, Enum.map(missing, &String.to_atom/1)}}
end
end
def new(_), do: {:error, :invalid_message_type}
@doc """
Type guard to check if a value is a Result message.
"""
@spec result_message?(any()) :: boolean()
def result_message?(%__MODULE__{type: :result}), do: true
def result_message?(_), do: false
defp parse_subtype("success"), do: :success
defp parse_subtype("error_max_turns"), do: :error_max_turns
defp parse_subtype("error_during_execution"), do: :error_during_execution
defp parse_subtype(other) when is_binary(other), do: String.to_atom(other)
defp parse_float(value) when is_float(value), do: value
defp parse_float(value) when is_integer(value), do: value * 1.0
defp parse_float(_), do: 0.0
defp parse_usage(usage_data) when is_map(usage_data) do
%{
input_tokens: usage_data["input_tokens"] || 0,
cache_creation_input_tokens: usage_data["cache_creation_input_tokens"] || 0,
cache_read_input_tokens: usage_data["cache_read_input_tokens"] || 0,
output_tokens: usage_data["output_tokens"] || 0,
server_tool_use: parse_server_tool_use(usage_data["server_tool_use"])
}
end
defp parse_usage(_),
do: %{
input_tokens: 0,
cache_creation_input_tokens: 0,
cache_read_input_tokens: 0,
output_tokens: 0,
server_tool_use: %{web_search_requests: 0}
}
defp parse_server_tool_use(%{"web_search_requests" => count}), do: %{web_search_requests: count}
defp parse_server_tool_use(_), do: %{web_search_requests: 0}
end