# `Cyclium.Conversations.LiveHelpers`
[🔗](https://github.com/Cyclium/cyclium_ex/blob/main/lib/cyclium/conversations/live_helpers.ex#L1)

Reusable helpers for conversation LiveViews.

Provides bus event handling, message loading from episodes, and conversation
lifecycle management. Consuming apps `use` this module to get module attributes
and import the helper functions.

## Usage

    defmodule MyAppWeb.ConversationLive.Show do
      use MyAppWeb, :live_view
      use Cyclium.Conversations.LiveHelpers, actor_id: "my_actor"

      # @__actor_id and @__dispatch are set for you.
      # All helper functions are imported.
    end

## Options

  - `:actor_id` — required, the actor identifier for filtering bus events
  - `:dispatch` — dispatch module (default: `Cyclium.Conversations.Dispatch`)

# `cancel_current_turn`

Cancel the current turn (the conversation's active episode), keeping the
conversation open. Returns the result of `Episodes.request_cancel/2`, or
`{:error, :no_active_episode}` if nothing is running.

# `dispatch_message`

Dispatch a user message. Appends the user message to the message list and
creates the episode.

Returns `{:ok, updated_messages}` or `{:error, updated_messages, reason}`.

# `load_messages_from_episodes`

Reconstruct chat messages from completed episodes in a conversation.

# `load_or_create_conversation`

Load or create a conversation based on params and live_action.
Returns `{conversation, messages}`.

# `on_conversation_status_change`

Handle a conversation status change event. Returns updated conversation or `:ignore`.

# `on_episode_canceled`

Handle an `episode.canceled` bus event. Appends a "stopped" marker and clears
the sending state. Returns `{:ok, assigns_map}` or `:ignore`.

# `on_episode_completed`

Handle an `episode.completed` bus event for a conversation LiveView.

Verifies the episode belongs to **both** the current conversation and the given
actor before reacting. Passing `actor_id` (use `@__actor_id`) bakes the actor
check into the helper, so it holds even if the `handle_info` pattern is later
broadened to drop the `actor_id:` match. Returns `{:ok, assigns_map}` on a
match, `:ignore` otherwise.

## Example

    def handle_info({:bus, "episode.completed", %{episode_id: eid, actor_id: @__actor_id}}, socket) do
      case on_episode_completed(eid, socket.assigns.conversation.id, @__actor_id, socket.assigns.messages) do
        {:ok, new_assigns} -> {:noreply, assign(socket, new_assigns)}
        :ignore -> {:noreply, socket}
      end
    end

# `on_episode_failed`

Handle an `episode.failed` bus event for a conversation LiveView.

Verifies the episode matches both the conversation and `actor_id` (see
`on_episode_completed/4`). Returns `{:ok, assigns_map}` or `:ignore`.

---

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