VibeAround
InternalsModules

Module: channels

src/core/src/channels/ — everything between "a message arrived from some surface" and "a thread runtime got a prompt", plus the reverse direction. Flows through it: IM message, web chat, permission.

Documentation notice: these docs are currently generated with Codex and are being actively reviewed, expanded, and refined.

src/core/src/channels/ — everything between "a message arrived from some surface" and "a thread runtime got a prompt", plus the reverse direction. Flows through it: IM message, web chat, permission.

Responsibility

Host channel plugins (out-of-process stdio and in-process websocket), normalize all inbound traffic into ChannelInput, dispatch it to the workspace-thread layer, and route every ChannelOutput back to the surface that should render it. It owns message transport and routing — never conversation state (that is workspace) and never process spawning (that is process).

Key types

TypeFileRole
ChannelManagermod.rsDaemon-lifetime facade: input queue, plugin registration, sync, shutdown
ChannelInput / ChannelOutput / ChannelEnvelopetypes.rsThe wire vocabulary every surface speaks
PluginHostplugin_host.rsRouting table: channel kind → live runtime; pending-permissions table
PluginRuntimeplugin_runtime.rsEnum over stdio / websocket runtimes
ChannelPluginBridgeplugin_bridge.rsProcessBridge impl driving one stdio plugin's ACP connection
ChannelMonitormonitor.rsDashboard facade over the supervisor for plugin lifecycle
ChannelOutboxoutbox.rsDurable queue for replayable outputs (system texts, permission cards)
ChannelBridgeHandlerbridge_handler.rsPer-thread ACP client handler: notification fan-out + permission round-trip
handle_channel_inputprompt/The single dispatch entry: command parse → thread ops → prompt

Interactions

  • ← plugins/surfaces: stdio plugins via the bridge; web/TUI via WebChannelManager's registered senders.
  • → workspace: prompt/handler.rs calls WorkspaceThreadManager for route resolution, commands, prompts.
  • → process: the monitor registers plugin manifests with the Supervisor; the bridge factory re-registers the live runtime in PluginHost on every respawn.
  • ← agent: ChannelBridgeHandler receives ACP notifications/permission requests from hosted agents and turns them into outputs.

Invariants — do not break

  1. Per-route ordering comes from the server's shard workers; nothing in this module may spawn per-message tasks that bypass it.
  2. handle_input never blocks — it is a queue send; platform-facing code must never wait on agent work.
  3. Every pending permission terminates: registered oneshots are consumed by the tap, by cancel_channel_permissions on bridge death (exactly once per death), or by shutdown_all. Add a new exit path for a plugin and you must drain there too.
  4. Replayable vs direct outputs: only durable kinds go through the outbox (should_replay_output); streaming chunks are intentionally lossy across plugin restarts.
  5. Outbound sends for one channel hold that channel's send lock so respawn-replay and live sends cannot interleave.

Known debt

  • channel_kind == "web" string special-cases (7 sites across core) should become declared channel traits — remediation M4.
  • Web-chat session-intent side effects run before queue serialization — remediation M6.
  • send_locks map entries are never pruned (bounded by channel count; cosmetic).

Source anchors: src/core/src/channels/ (all files above), src/server/src/lib.rs (shard workers). Last verified: v0.7.11

On this page