# `SuperPi.UI.Broker`
[🔗](https://github.com/oleksandr/super-pi-beam/blob/v0.1.0/lib/super_pi/ui/broker.ex#L1)

Carries a question from a running turn to a client that can answer it, and the answer back.
Works across nodes: the machine that asks and the client that answers can be on different nodes.

A tool (`ask_question`) calls `ask/3`. The broker publishes a `ui_request` event on the
conversation topic and blocks the caller until a client calls `respond/2`, the conversation is
cancelled (`cancel_pending/1`), every responder has left, or the timeout passes.

`ask/4` can publish a `permission_request` event instead of a `ui_request` (`event: :permission_request`).
Either way, `ui_resolved` follows when the question ends, so a second watcher can dismiss a prompt
that someone else answered, or that was cancelled or timed out.

Only a client that has registered with `register_responder/1` can answer. The CLI chat and an RPC
client that watches a conversation register. The HTTP gateway cannot prompt a user, so with no
responder `ask/3` returns `{:error, :no_interactive_client}` at once instead of waiting.

Membership lives in `:pg` process groups (scope `:super_pi_pg`). `:pg` spans the connected nodes
and drops a process that exits, so no table needs cleaning.

Pending questions are in memory. If the node that asks stops mid-question, the task engine
restarts the turn elsewhere and the model asks again. Nothing is answered by default.

# `ask`

Asks `request` (a map such as `%{"kind" => "questionnaire", "questions" => [...]}`) and waits.

Returns `{:ok, value}`, `{:error, :no_interactive_client}`, `{:error, :cancelled}` or
`{:error, :timeout}`.

Options: `event: :permission_request` publishes a `permission_request` event (the request map
holds its fields, see `SuperPi.Event.permission_request/3`); `turn_id:` sets the turn id of the event.

# `cancel_pending`

Ends every question that waits on the conversation with `{:error, :cancelled}`.

# `conversation_of`

The conversation a waiting question belongs to, or `nil`.

# `register_responder`

Registers the calling process as able to answer questions for `conversation_id`.

# `respond`

Delivers an answer. `{:error, :unknown_request}` when no question is waiting under that id.

# `responder?`

True when at least one live process, on any node, can answer for the conversation.

---

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