story-kit: merge 316_refactor_abstract_bot_transport_layer_for_multi_platform_support

This commit is contained in:
Dave
2026-03-19 20:43:38 +00:00
parent 3b9cea22bb
commit 7eb9686bfb
10 changed files with 510 additions and 163 deletions

View File

@@ -7,7 +7,6 @@
use crate::agents::{AgentPool, AgentStatus};
use crate::config::ProjectConfig;
use matrix_sdk::ruma::OwnedRoomId;
use std::collections::{HashMap, HashSet};
use std::path::Path;
use std::sync::{Arc, Mutex};
@@ -31,19 +30,22 @@ pub struct BotCommand {
/// Groups all the caller-supplied context needed to dispatch and execute bot
/// commands. Construct one per incoming message and pass it alongside the raw
/// message body.
///
/// All identifiers are platform-agnostic strings so this struct works with
/// any [`ChatTransport`](crate::transport::ChatTransport) implementation.
pub struct CommandDispatch<'a> {
/// The bot's display name (e.g., "Timmy").
pub bot_name: &'a str,
/// The bot's full Matrix user ID (e.g., `"@timmy:homeserver.local"`).
/// The bot's full user ID (e.g., `"@timmy:homeserver.local"` on Matrix).
pub bot_user_id: &'a str,
/// Project root directory (needed by status, ambient).
pub project_root: &'a Path,
/// Agent pool (needed by status).
pub agents: &'a AgentPool,
/// Set of rooms with ambient mode enabled (needed by ambient).
pub ambient_rooms: &'a Arc<Mutex<HashSet<OwnedRoomId>>>,
/// Set of room IDs with ambient mode enabled (needed by ambient).
pub ambient_rooms: &'a Arc<Mutex<HashSet<String>>>,
/// The room this message came from (needed by ambient).
pub room_id: &'a OwnedRoomId,
pub room_id: &'a str,
/// Whether the message directly addressed the bot (mention/reply).
/// Some commands (e.g. ambient) only operate when directly addressed.
pub is_addressed: bool,
@@ -59,10 +61,10 @@ pub struct CommandContext<'a> {
pub project_root: &'a Path,
/// Agent pool (needed by status).
pub agents: &'a AgentPool,
/// Set of rooms with ambient mode enabled (needed by ambient).
pub ambient_rooms: &'a Arc<Mutex<HashSet<OwnedRoomId>>>,
/// Set of room IDs with ambient mode enabled (needed by ambient).
pub ambient_rooms: &'a Arc<Mutex<HashSet<String>>>,
/// The room this message came from (needed by ambient).
pub room_id: &'a OwnedRoomId,
pub room_id: &'a str,
/// Whether the message directly addressed the bot (mention/reply).
/// Some commands (e.g. ambient) only operate when directly addressed.
pub is_addressed: bool,
@@ -389,11 +391,11 @@ fn handle_ambient(ctx: &CommandContext) -> Option<String> {
let room_ids: Vec<String> = {
let mut ambient = ctx.ambient_rooms.lock().unwrap();
if enable {
ambient.insert(ctx.room_id.clone());
ambient.insert(ctx.room_id.to_string());
} else {
ambient.remove(ctx.room_id);
}
ambient.iter().map(|r| r.to_string()).collect()
ambient.iter().cloned().collect()
};
save_ambient_rooms(ctx.project_root, &room_ids);
let msg = if enable {
@@ -665,11 +667,7 @@ mod tests {
// -- test helpers -------------------------------------------------------
fn make_room_id(s: &str) -> OwnedRoomId {
s.parse().unwrap()
}
fn test_ambient_rooms() -> Arc<Mutex<HashSet<OwnedRoomId>>> {
fn test_ambient_rooms() -> Arc<Mutex<HashSet<String>>> {
Arc::new(Mutex::new(HashSet::new()))
}
@@ -681,11 +679,11 @@ mod tests {
bot_name: &str,
bot_user_id: &str,
message: &str,
ambient_rooms: &Arc<Mutex<HashSet<OwnedRoomId>>>,
ambient_rooms: &Arc<Mutex<HashSet<String>>>,
is_addressed: bool,
) -> Option<String> {
let agents = test_agents();
let room_id = make_room_id("!test:example.com");
let room_id = "!test:example.com".to_string();
let dispatch = CommandDispatch {
bot_name,
bot_user_id,
@@ -855,7 +853,7 @@ mod tests {
#[test]
fn ambient_on_requires_addressed() {
let ambient_rooms = test_ambient_rooms();
let room_id = make_room_id("!myroom:example.com");
let room_id = "!myroom:example.com".to_string();
let result = try_cmd(
"Timmy",
"@timmy:homeserver.local",
@@ -875,7 +873,7 @@ mod tests {
fn ambient_on_enables_ambient_mode() {
let ambient_rooms = test_ambient_rooms();
let agents = test_agents();
let room_id = make_room_id("!myroom:example.com");
let room_id = "!myroom:example.com".to_string();
let dispatch = CommandDispatch {
bot_name: "Timmy",
bot_user_id: "@timmy:homeserver.local",
@@ -902,7 +900,7 @@ mod tests {
fn ambient_off_disables_ambient_mode() {
let ambient_rooms = test_ambient_rooms();
let agents = test_agents();
let room_id = make_room_id("!myroom:example.com");
let room_id = "!myroom:example.com".to_string();
// Pre-insert the room
ambient_rooms.lock().unwrap().insert(room_id.clone());
@@ -1211,7 +1209,7 @@ mod tests {
.unwrap_or(std::path::Path::new("."));
let agents = test_agents();
let ambient_rooms = test_ambient_rooms();
let room_id = make_room_id("!test:example.com");
let room_id = "!test:example.com".to_string();
let dispatch = CommandDispatch {
bot_name: "Timmy",
bot_user_id: "@timmy:homeserver.local",
@@ -1232,7 +1230,7 @@ mod tests {
.unwrap_or(std::path::Path::new("."));
let agents = test_agents();
let ambient_rooms = test_ambient_rooms();
let room_id = make_room_id("!test:example.com");
let room_id = "!test:example.com".to_string();
let dispatch = CommandDispatch {
bot_name: "Timmy",
bot_user_id: "@timmy:homeserver.local",
@@ -1256,7 +1254,7 @@ mod tests {
.unwrap_or(std::path::Path::new("."));
let agents = test_agents();
let ambient_rooms = test_ambient_rooms();
let room_id = make_room_id("!test:example.com");
let room_id = "!test:example.com".to_string();
let dispatch = CommandDispatch {
bot_name: "Timmy",
bot_user_id: "@timmy:homeserver.local",
@@ -1280,7 +1278,7 @@ mod tests {
.unwrap_or(std::path::Path::new("."));
let agents = test_agents();
let ambient_rooms = test_ambient_rooms();
let room_id = make_room_id("!test:example.com");
let room_id = "!test:example.com".to_string();
let dispatch = CommandDispatch {
bot_name: "Timmy",
bot_user_id: "@timmy:homeserver.local",
@@ -1335,7 +1333,7 @@ mod tests {
fn cost_cmd_with_root(root: &std::path::Path) -> Option<String> {
let agents = test_agents();
let ambient_rooms = test_ambient_rooms();
let room_id = make_room_id("!test:example.com");
let room_id = "!test:example.com".to_string();
let dispatch = CommandDispatch {
bot_name: "Timmy",
bot_user_id: "@timmy:homeserver.local",
@@ -1473,7 +1471,7 @@ mod tests {
fn show_cmd_with_root(root: &std::path::Path, args: &str) -> Option<String> {
let agents = test_agents();
let ambient_rooms = test_ambient_rooms();
let room_id = make_room_id("!test:example.com");
let room_id = "!test:example.com".to_string();
let dispatch = CommandDispatch {
bot_name: "Timmy",
bot_user_id: "@timmy:homeserver.local",