# `AgentSessionManager.Core.CapabilityResolver`
[🔗](https://github.com/nshkrdotcom/agent_session_manager/blob/v0.8.0/lib/agent_session_manager/core/capability_resolver.ex#L1)

Negotiates capabilities between required/optional sets and available provider capabilities.

The CapabilityResolver accepts a set of required and optional capability types,
then negotiates against a list of provider capabilities to determine which
capabilities are supported, unsupported, and whether the negotiation succeeds.

## Negotiation Behavior

- **Required capabilities**: If any required capability type is missing from the
  provider, negotiation fails immediately with an error.
- **Optional capabilities**: Missing optional capabilities result in a `degraded`
  status with warnings, but negotiation still succeeds.
- **Full support**: When all required and optional capabilities are satisfied,
  the result status is `full`.

## Usage

    # Create a resolver with required and optional capabilities
    {:ok, resolver} = CapabilityResolver.new(
      required: [:tool, :resource],
      optional: [:sampling]
    )

    # Negotiate against provider capabilities
    provider_capabilities = [
      %Capability{name: "web_search", type: :tool, enabled: true},
      %Capability{name: "file_access", type: :resource, enabled: true}
    ]

    case CapabilityResolver.negotiate(resolver, provider_capabilities) do
      {:ok, result} ->
        IO.puts("Status: #{result.status}")
        IO.puts("Supported: #{inspect(result.supported)}")
        IO.puts("Warnings: #{inspect(result.warnings)}")

      {:error, error} ->
        IO.puts("Negotiation failed: #{error.message}")
    end

## Helper Functions

The module also provides utilities for working with capability lists:

    # Check if a capability type is present
    CapabilityResolver.has_capability_type?(capabilities, :tool)

    # Get all capabilities of a specific type
    tools = CapabilityResolver.capabilities_of_type(capabilities, :tool)

# `t`

```elixir
@type t() :: %AgentSessionManager.Core.CapabilityResolver{
  optional: MapSet.t(atom()),
  required: MapSet.t(atom())
}
```

# `capabilities_of_type`

```elixir
@spec capabilities_of_type([AgentSessionManager.Core.Capability.t()], atom()) :: [
  AgentSessionManager.Core.Capability.t()
]
```

Returns all capabilities from the list that have the specified type.

Only considers enabled capabilities.

## Examples

    iex> capabilities = [%Capability{name: "search", type: :tool, enabled: true}]
    iex> CapabilityResolver.capabilities_of_type(capabilities, :tool)
    [%Capability{name: "search", type: :tool, enabled: true}]

# `has_capability_type?`

```elixir
@spec has_capability_type?([AgentSessionManager.Core.Capability.t()], atom()) ::
  boolean()
```

Checks if the capability list contains at least one enabled capability of the given type.

## Examples

    iex> capabilities = [%Capability{name: "search", type: :tool, enabled: true}]
    iex> CapabilityResolver.has_capability_type?(capabilities, :tool)
    true

    iex> CapabilityResolver.has_capability_type?(capabilities, :sampling)
    false

# `negotiate`

```elixir
@spec negotiate(t(), [AgentSessionManager.Core.Capability.t()]) ::
  {:ok, AgentSessionManager.Core.CapabilityResolver.NegotiationResult.t()}
  | {:error, AgentSessionManager.Core.Error.t()}
```

Negotiates capabilities between the resolver's requirements and provider capabilities.

Returns `{:ok, result}` if all required capabilities are satisfied, or
`{:error, error}` if any required capability is missing.

## Examples

    iex> {:ok, resolver} = CapabilityResolver.new(required: [:tool])
    iex> capabilities = [%Capability{name: "search", type: :tool, enabled: true}]
    iex> {:ok, result} = CapabilityResolver.negotiate(resolver, capabilities)
    iex> result.status
    :full

# `new`

```elixir
@spec new(keyword()) :: {:ok, t()} | {:error, AgentSessionManager.Core.Error.t()}
```

Creates a new CapabilityResolver with the given required and optional capability types.

## Options

- `:required` - List of required capability types (atoms or strings)
- `:optional` - List of optional capability types (atoms or strings)

## Examples

    iex> CapabilityResolver.new(required: [:tool], optional: [:sampling])
    {:ok, %CapabilityResolver{required: MapSet.new([:tool]), optional: MapSet.new([:sampling])}}

    iex> CapabilityResolver.new(required: [:invalid_type])
    {:error, %Error{code: :invalid_capability_type}}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
