From 40e5f91777ac9d4a50b2d280c8d13e8bcdde4f70 Mon Sep 17 00:00:00 2001 From: Argenis Date: Fri, 20 Mar 2026 12:17:16 -0400 Subject: [PATCH] fix: add interrupt_on_new_message support for Matrix channel (#4070) Add the missing interrupt_on_new_message field to MatrixConfig and wire it through InterruptOnNewMessageConfig so Matrix behaves consistently with Telegram, Slack, Discord, and Mattermost. Closes #4058 --- src/channels/mod.rs | 43 ++++++++++++++++++++++++++++++++++++ src/config/schema.rs | 6 +++++ src/integrations/registry.rs | 1 + src/onboard/wizard.rs | 1 + 4 files changed, 51 insertions(+) diff --git a/src/channels/mod.rs b/src/channels/mod.rs index cb42f92ac..70f04aad5 100644 --- a/src/channels/mod.rs +++ b/src/channels/mod.rs @@ -294,6 +294,7 @@ struct InterruptOnNewMessageConfig { slack: bool, discord: bool, mattermost: bool, + matrix: bool, } impl InterruptOnNewMessageConfig { @@ -303,6 +304,7 @@ impl InterruptOnNewMessageConfig { "slack" => self.slack, "discord" => self.discord, "mattermost" => self.mattermost, + "matrix" => self.matrix, _ => false, } } @@ -4410,6 +4412,11 @@ pub async fn start_channels(config: Config) -> Result<()> { .mattermost .as_ref() .is_some_and(|mm| mm.interrupt_on_new_message); + let interrupt_on_new_message_matrix = config + .channels_config + .matrix + .as_ref() + .is_some_and(|mx| mx.interrupt_on_new_message); let runtime_ctx = Arc::new(ChannelRuntimeContext { channels_by_name, @@ -4440,6 +4447,7 @@ pub async fn start_channels(config: Config) -> Result<()> { slack: interrupt_on_new_message_slack, discord: interrupt_on_new_message_discord, mattermost: interrupt_on_new_message_mattermost, + matrix: interrupt_on_new_message_matrix, }, multimodal: config.multimodal.clone(), hooks: if config.hooks.enabled { @@ -4758,6 +4766,7 @@ mod tests { slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -4872,6 +4881,7 @@ mod tests { slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -4942,6 +4952,7 @@ mod tests { slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -5031,6 +5042,7 @@ mod tests { slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -5572,6 +5584,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, non_cli_excluded_tools: Arc::new(Vec::new()), tool_call_dedup_exempt: Arc::new(Vec::new()), @@ -5650,6 +5663,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, non_cli_excluded_tools: Arc::new(Vec::new()), autonomy_level: AutonomyLevel::default(), @@ -5743,6 +5757,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -5821,6 +5836,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -5909,6 +5925,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -6018,6 +6035,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -6108,6 +6126,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -6213,6 +6232,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -6303,6 +6323,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -6383,6 +6404,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -6574,6 +6596,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -6674,6 +6697,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -6789,6 +6813,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: true, discord: false, mattermost: false, + matrix: false, }, ack_reactions: true, show_tool_calls: true, @@ -6901,6 +6926,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -6995,6 +7021,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -7073,6 +7100,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -7837,6 +7865,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -7966,6 +7995,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -8135,6 +8165,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -8239,6 +8270,7 @@ BTC is currently around $65,000 based on latest tool output."# slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -8808,6 +8840,7 @@ This is an example JSON object for profile settings."#; slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -8893,6 +8926,7 @@ This is an example JSON object for profile settings."#; slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -9053,6 +9087,7 @@ This is an example JSON object for profile settings."#; slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -9162,6 +9197,7 @@ This is an example JSON object for profile settings."#; slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -9263,6 +9299,7 @@ This is an example JSON object for profile settings."#; slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -9384,6 +9421,7 @@ This is an example JSON object for profile settings."#; slack: false, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, @@ -9514,6 +9552,7 @@ This is an example JSON object for profile settings."#; slack: false, discord: false, mattermost: true, + matrix: false, }; assert!(cfg.enabled_for_channel("mattermost")); } @@ -9525,6 +9564,7 @@ This is an example JSON object for profile settings."#; slack: false, discord: false, mattermost: false, + matrix: false, }; assert!(!cfg.enabled_for_channel("mattermost")); } @@ -9536,6 +9576,7 @@ This is an example JSON object for profile settings."#; slack: false, discord: true, mattermost: false, + matrix: false, }; assert!(cfg.enabled_for_channel("discord")); } @@ -9547,6 +9588,7 @@ This is an example JSON object for profile settings."#; slack: false, discord: false, mattermost: false, + matrix: false, }; assert!(!cfg.enabled_for_channel("discord")); } @@ -9638,6 +9680,7 @@ This is an example JSON object for profile settings."#; slack: true, discord: false, mattermost: false, + matrix: false, }, multimodal: crate::config::MultimodalConfig::default(), hooks: None, diff --git a/src/config/schema.rs b/src/config/schema.rs index b49381201..4c1cabdf0 100644 --- a/src/config/schema.rs +++ b/src/config/schema.rs @@ -4932,6 +4932,9 @@ pub struct MatrixConfig { pub room_id: String, /// Allowed Matrix user IDs. Empty = deny all. pub allowed_users: Vec, + /// Whether to interrupt an in-flight agent response when a new message arrives. + #[serde(default)] + pub interrupt_on_new_message: bool, } impl ChannelConfig for MatrixConfig { @@ -9767,6 +9770,7 @@ tool_dispatcher = "xml" device_id: Some("DEVICE123".into()), room_id: "!room123:matrix.org".into(), allowed_users: vec!["@user:matrix.org".into()], + interrupt_on_new_message: false, }; let json = serde_json::to_string(&mc).unwrap(); let parsed: MatrixConfig = serde_json::from_str(&json).unwrap(); @@ -9787,6 +9791,7 @@ tool_dispatcher = "xml" device_id: None, room_id: "!abc:synapse.local".into(), allowed_users: vec!["@admin:synapse.local".into(), "*".into()], + interrupt_on_new_message: false, }; let toml_str = toml::to_string(&mc).unwrap(); let parsed: MatrixConfig = toml::from_str(&toml_str).unwrap(); @@ -9876,6 +9881,7 @@ allowed_users = ["@ops:matrix.org"] device_id: None, room_id: "!r:m".into(), allowed_users: vec!["@u:m".into()], + interrupt_on_new_message: false, }), signal: None, whatsapp: None, diff --git a/src/integrations/registry.rs b/src/integrations/registry.rs index be88f9b1e..8ef7815b3 100644 --- a/src/integrations/registry.rs +++ b/src/integrations/registry.rs @@ -890,6 +890,7 @@ mod tests { device_id: None, room_id: "!r:m".into(), allowed_users: vec![], + interrupt_on_new_message: false, }); let entries = all_integrations(); let mx = entries.iter().find(|e| e.name == "Matrix").unwrap(); diff --git a/src/onboard/wizard.rs b/src/onboard/wizard.rs index da327bc3f..2178bfb58 100644 --- a/src/onboard/wizard.rs +++ b/src/onboard/wizard.rs @@ -4159,6 +4159,7 @@ fn setup_channels() -> Result { device_id: detected_device_id, room_id, allowed_users, + interrupt_on_new_message: false, }); } ChannelMenuChoice::Signal => {