lib/openagents/providers/provider_event.ex

main at 58e6347eeb72 · 1 KB

defmodule OpenAgents.Providers.ProviderEvent do
  @moduledoc """
  Provider-neutral lifecycle and content events consumed by Sarah's turn runtime.

  `{:model_served, name}` is what the provider said answered, read back off the
  response rather than assumed from the request. It exists because a request
  and its answer can name different models: the Vercel AI Gateway is configured
  with a fallback list, and a primary that fails is replaced by another model
  without the request being refused. An adapter that can be substituted for
  emits this so the host prices and attributes the call against the model that
  actually served it (METER-001, PROVIDER-002).
  """

  defmodule ToolCall do
    @moduledoc "A provider-requested function call awaiting host admission and validation."

    @enforce_keys [:item_id, :call_id, :name, :raw_arguments]
    defstruct @enforce_keys

    @type t :: %__MODULE__{
            item_id: String.t(),
            call_id: String.t(),
            name: String.t(),
            raw_arguments: String.t()
          }
  end

  @type failure_reason ::
          :cancelled
          | :invalid_provider_event
          | :missing_api_key
          | :missing_terminal_event
          | :truncated_stream
          | :unsupported_tool_call
          | {:http_status, pos_integer()}
          | {:provider_failed, String.t() | nil}
          | {:transport, atom()}
          | {:unexpected_provider_result, term()}

  @type t ::
          {:response_started, String.t()}
          | {:model_served, String.t()}
          | {:text_delta, String.t()}
          | {:reasoning_delta, String.t()}
          | {:tool_call, ToolCall.t()}
          | {:usage, map()}
          | {:response_completed, String.t()}
          | {:failed, failure_reason()}
          | :cancelled
end