fix(gateway): bot.toml is read; perm_rx channel stays open
Two latent bugs in `service/gateway/io.rs::spawn_gateway_bot`, exposed today after a long-overdue gateway rebuild: 1. The permission channel sender was bound as `_perm_tx` (the underscore prefix signalling "unused") and dropped at function return. The matrix bot's permission_listener task — which holds `perm_rx` for its lifetime per story 884 — then saw the channel close immediately and exited with "perm_rx channel closed" 1s after starting. Net effect: the listener was effectively absent on every gateway boot, so non-MCP tool permission requests had no destination at all (separate from the architectural mismatch that 898 will fix; this was a strictly worse "listener never even ran" version of the same problem). Bind as `perm_tx` and `mem::forget` it to keep the channel open for the gateway's lifetime, mirroring the existing `shutdown_tx` pattern two lines below. 2. `bot_name` was hardcoded to `"Assistant"`, ignoring `bot.toml::display_name`. So the gateway's matrix bot announced itself as "Assistant" and treated user messages addressed to "Timmy" (the actual configured display_name) as unaddressed, silently dropping them. `ambient_rooms` and `permission_timeout_secs` were similarly ignored. Load `BotConfig::load(config_dir)` and apply the same field plumbing the standard-mode initialisation in `main.rs:211-232` already uses. Symptoms seen in production today: - gateway.log: `Sending startup announcement: Assistant is online.` followed by repeated `Ignoring unaddressed message from @yossarian:crashlabs.io` lines. - gateway.log: `permission listener started` immediately followed (same timestamp) by `permission listener exiting (perm_rx channel closed)`. After this lands, rebuild the gateway binary and restart so it picks up `bot.toml` correctly and the listener stays alive for the bot's lifetime. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -422,7 +422,16 @@ pub fn spawn_gateway_bot(
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
|
||||
let (watcher_tx, _) = broadcast::channel(16);
|
||||
let (_perm_tx, perm_rx) = mpsc::unbounded_channel();
|
||||
let (perm_tx, perm_rx) = mpsc::unbounded_channel();
|
||||
// Keep the sender alive for the gateway's lifetime so the matrix bot's
|
||||
// `permission_listener` task doesn't exit immediately with
|
||||
// "perm_rx channel closed". Previously `_perm_tx` was dropped when
|
||||
// `spawn_gateway_bot` returned, closing the channel before the
|
||||
// listener could even register. Story 898 (sled→gateway WS uplink)
|
||||
// will eventually wire in a real sender; for now the leak keeps the
|
||||
// channel open with no senders writing to it, matching the original
|
||||
// intent of "listener watches forever, waiting for requests".
|
||||
std::mem::forget(perm_tx);
|
||||
let perm_rx = std::sync::Arc::new(tokio::sync::Mutex::new(perm_rx));
|
||||
|
||||
let (shutdown_tx, shutdown_rx) =
|
||||
@@ -431,18 +440,36 @@ pub fn spawn_gateway_bot(
|
||||
|
||||
let agents = std::sync::Arc::new(AgentPool::new(port, watcher_tx.clone()));
|
||||
|
||||
// Read the gateway's bot.toml so display_name, ambient_rooms, and
|
||||
// permission_timeout_secs are honoured (matches the standard-mode
|
||||
// initialisation in main.rs). Previously this path hardcoded
|
||||
// `bot_name = "Assistant"` regardless of bot.toml's display_name,
|
||||
// breaking @-addressing for users who configured a different name.
|
||||
let bot_cfg = crate::chat::transport::matrix::BotConfig::load(config_dir);
|
||||
|
||||
let services = std::sync::Arc::new(Services {
|
||||
project_root: config_dir.to_path_buf(),
|
||||
status: agents.status_broadcaster(),
|
||||
agents,
|
||||
bot_name: "Assistant".to_string(),
|
||||
bot_name: bot_cfg
|
||||
.as_ref()
|
||||
.and_then(|c| c.display_name.clone())
|
||||
.unwrap_or_else(|| "Assistant".to_string()),
|
||||
bot_user_id: String::new(),
|
||||
ambient_rooms: std::sync::Arc::new(std::sync::Mutex::new(std::collections::HashSet::new())),
|
||||
ambient_rooms: std::sync::Arc::new(std::sync::Mutex::new(
|
||||
bot_cfg
|
||||
.as_ref()
|
||||
.map(|c| c.ambient_rooms.iter().cloned().collect())
|
||||
.unwrap_or_default(),
|
||||
)),
|
||||
perm_rx,
|
||||
pending_perm_replies: std::sync::Arc::new(tokio::sync::Mutex::new(
|
||||
std::collections::HashMap::new(),
|
||||
)),
|
||||
permission_timeout_secs: 120,
|
||||
permission_timeout_secs: bot_cfg
|
||||
.as_ref()
|
||||
.map(|c| c.permission_timeout_secs)
|
||||
.unwrap_or(120),
|
||||
});
|
||||
|
||||
let timer_store = std::sync::Arc::new(crate::service::timer::TimerStore::load(
|
||||
|
||||
Reference in New Issue
Block a user