Current section

Files

Jump to
agent_session_manager lib asm error.ex
Raw

lib/asm/error.ex

defmodule ASM.Error do
@moduledoc """
Canonical runtime error type for ASM.
"""
@enforce_keys [:kind, :domain, :message]
defexception [:kind, :domain, :message, :cause, :provider, :exit_code, :retryable, :recovery]
@type domain ::
:transport | :parser | :provider | :approval | :guardrail | :tool | :runtime | :config
@type kind ::
:cli_not_found
| :connection_failed
| :timeout
| :parse_error
| :json_decode_error
| :auth_error
| :rate_limit
| :buffer_overflow
| :transport_error
| :transport_busy
| :queue_full
| :at_capacity
| :user_cancelled
| :approval_denied
| :guardrail_blocked
| :tool_failed
| :config_invalid
| :unknown
@type t :: %__MODULE__{
kind: kind(),
domain: domain(),
message: String.t(),
cause: term() | nil,
provider: atom() | nil,
exit_code: integer() | nil,
retryable: boolean() | nil,
recovery: map() | nil
}
@spec new(kind(), domain(), String.t(), keyword()) :: t()
def new(kind, domain, message, opts \\ []) when is_binary(message) do
%__MODULE__{
kind: kind,
domain: domain,
message: message,
cause: Keyword.get(opts, :cause),
provider: Keyword.get(opts, :provider),
exit_code: Keyword.get(opts, :exit_code),
retryable: Keyword.get(opts, :retryable),
recovery: Keyword.get(opts, :recovery)
}
end
@impl true
def exception(opts) when is_list(opts) do
kind = Keyword.get(opts, :kind, :unknown)
domain = Keyword.get(opts, :domain, :runtime)
message = Keyword.get(opts, :message, "ASM runtime error")
new(kind, domain, message,
cause: Keyword.get(opts, :cause),
provider: Keyword.get(opts, :provider),
exit_code: Keyword.get(opts, :exit_code),
retryable: Keyword.get(opts, :retryable),
recovery: Keyword.get(opts, :recovery)
)
end
@impl true
def message(%__MODULE__{domain: domain, kind: kind, message: msg}) do
"[#{domain}/#{kind}] #{msg}"
end
end