# `Jido.Messaging.BridgeRegistry`
[🔗](https://github.com/agentjido/jido_messaging/blob/v1.0.0/lib/jido_messaging/bridge_registry.ex#L1)

Channel bridge discovery and lookup.

Provides a centralized registry for channel bridges, enabling runtime discovery
of available channels, their capabilities, and associated adapters.

## Usage

Register bridges at application startup:

    # In your application.ex or a supervisor
    BridgeRegistry.register(BridgePlugin.from_adapter(MyApp.TelegramAdapter))
    BridgeRegistry.register(BridgePlugin.from_adapter(MyApp.DiscordAdapter))

Query registered bridges:

    BridgeRegistry.list_bridges()
    BridgeRegistry.get_bridge(:telegram)
    BridgeRegistry.capabilities(:telegram)

## Implementation

Uses an ETS table for storage, which provides fast concurrent reads.
The table is created on first access and persists for the lifetime of the BEAM.

# `bootstrap_result`

```elixir
@type bootstrap_result() :: %{
  registered_bridge_ids: [atom()],
  degraded_diagnostics: [manifest_diagnostic()],
  collision_diagnostics: [collision_diagnostic()]
}
```

# `collision_diagnostic`

```elixir
@type collision_diagnostic() :: %{
  type: :bridge_id_collision,
  bridge_id: atom(),
  policy: manifest_collision_policy(),
  winning_path: String.t(),
  discarded_path: String.t()
}
```

# `manifest_collision_policy`

```elixir
@type manifest_collision_policy() :: :prefer_first | :prefer_last
```

# `manifest_diagnostic`

```elixir
@type manifest_diagnostic() :: %{
  :policy =&gt; :fatal_required_bridge_error | :degraded_optional_bridge_error,
  :type =&gt; atom(),
  optional(:bridge_id) =&gt; atom(),
  optional(:path) =&gt; String.t(),
  reason: term()
}
```

# `bootstrap_from_manifests`

```elixir
@spec bootstrap_from_manifests(keyword()) ::
  {:ok, bootstrap_result()}
  | {:error, {:fatal_required_bridge_error, manifest_diagnostic()}}
```

Loads bridge manifests and registers the resulting bridges with deterministic precedence.

## Options

  * `:manifest_paths` - Manifest file paths, wildcard patterns, or directories.
  * `:required_bridges` - Bridge IDs that must load successfully (atoms or strings).
  * `:collision_policy` - `:prefer_first` or `:prefer_last` when bridge IDs collide.
  * `:clear_existing?` - When true, clear the registry before registration.

Returns `{:error, {:fatal_required_bridge_error, diagnostic}}` for required failures.
Optional bridge failures degrade with warnings and telemetry.

# `capabilities`

```elixir
@spec capabilities(atom()) :: [atom()]
```

Gets capabilities for a channel type.

Returns an empty list if the channel is not registered.

## Examples

    BridgeRegistry.capabilities(:telegram)
    # => [:text, :image, :streaming]

    BridgeRegistry.capabilities(:unknown)
    # => []

# `clear`

```elixir
@spec clear() :: :ok
```

Clears all registered bridges.

Primarily useful for testing.

# `get_adapter`

```elixir
@spec get_adapter(atom(), atom()) :: module() | nil
```

Gets an adapter module for a channel type and adapter kind.

## Examples

    BridgeRegistry.get_adapter(:telegram, :mentions)
    # => MyApp.TelegramMentionsAdapter

# `get_adapter_module`

```elixir
@spec get_adapter_module(atom()) :: module() | nil
```

Gets a channel module by its type.

Returns nil if not registered.

## Examples

    BridgeRegistry.get_adapter_module(:telegram)
    # => MyApp.TelegramAdapter

# `get_bridge`

```elixir
@spec get_bridge(atom()) :: Jido.Messaging.BridgePlugin.t() | nil
```

Gets a bridge by its channel type.

## Examples

    BridgeRegistry.get_bridge(:telegram)
    # => %BridgePlugin{id: :telegram, ...}

    BridgeRegistry.get_bridge(:unknown)
    # => nil

# `get_bridge!`

```elixir
@spec get_bridge!(atom()) :: Jido.Messaging.BridgePlugin.t()
```

Gets a bridge by its channel type, raising if not found.

## Examples

    BridgeRegistry.get_bridge!(:telegram)
    # => %BridgePlugin{id: :telegram, ...}

    BridgeRegistry.get_bridge!(:unknown)
    # => ** (KeyError) bridge not found: :unknown

# `has_capability?`

```elixir
@spec has_capability?(atom(), atom()) :: boolean()
```

Checks if a channel type supports a specific capability.

## Examples

    BridgeRegistry.has_capability?(:telegram, :streaming)
    # => true

# `list_bridges`

```elixir
@spec list_bridges() :: [Jido.Messaging.BridgePlugin.t()]
```

Lists all registered bridges.

## Examples

    BridgeRegistry.list_bridges()
    # => [%BridgePlugin{id: :telegram, ...}, %BridgePlugin{id: :discord, ...}]

# `list_channel_types`

```elixir
@spec list_channel_types() :: [atom()]
```

Lists all channel types that have been registered.

## Examples

    BridgeRegistry.list_channel_types()
    # => [:telegram, :discord, :slack]

# `register`

```elixir
@spec register(Jido.Messaging.BridgePlugin.t()) :: :ok
```

Registers a bridge in the registry.

If a bridge with the same ID already exists, it will be replaced.

## Examples

    bridge = BridgePlugin.from_adapter(MyApp.TelegramAdapter)
    BridgeRegistry.register(bridge)
    # => :ok

# `unregister`

```elixir
@spec unregister(atom()) :: :ok
```

Unregisters a bridge from the registry.

## Examples

    BridgeRegistry.unregister(:telegram)
    # => :ok

---

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