A Raxol.Gateway.Handler that runs a full TEA app per chat under
environment: :gateway.
init/2 starts a Raxol.Core.Runtime.Lifecycle for the configured
:app_module. The :gateway environment starts no terminal driver and no
plugin manager, and registers no process names, so any number of chats can
run the same app module concurrently. Each inbound gateway event is
translated to a Raxol event, dispatched into the app's update cycle, and
the reply is the app's next rendered frame as plain text (the engine
delivers frames through an io_writer closure pointing at the session
process).
Requires the optional :raxol dependency; init/2 returns
{:error, :raxol_not_loaded} without it.
Options
:app_module(required) - the TEA app module:width/:height- frame dimensions (default 80x24):render_timeout_ms- budget for the post-event fold barrier and the synchronous render (default 5000); on timeout the event is absorbed with no reply:event_fn-(gateway_event -> raxol_event | nil); default maps%{text: t}to a char key event (single grapheme) or a paste event, mirroring the Telegram input adapter.nilskips the event.:format_fn-(render_data -> binary | nil); default renders the delivered buffer to plain text.nil(or an empty result) skips the reply.:lifecycle_opts- extra options appended toRaxol.Core.Runtime.Lifecycle.start_link/2
Turn semantics
The handler runs inside the per-chat Raxol.Gateway.Session process, so
the render io_writer targets that process. A turn is collected
deterministically: stale frames (startup renders, a late frame from a
previous turn) are flushed, the event is cast to the dispatcher, a :sys
barrier confirms the model fold, and a synchronous engine render produces
the reply frame (the newest wins if several arrive). Frames the app
renders BETWEEN turns are consumed and discarded by the session's
catch-all handle_info -- a chat surface replies to messages;
spontaneous pushes are Raxol.Gateway.Delivery's job.
Teardown
The Lifecycle GenServer is linked to the session, but a session's idle
timeout is a :normal exit, which does not propagate over links. The
handler's terminate/2 (invoked by the session on clean stops) stops the
Lifecycle explicitly so per-chat apps never outlive their chat.