huskies: merge 558_story_matrix_bot_can_run_on_the_gateway_to_manage_multiple_projects_from_one_chat

This commit is contained in:
dave
2026-04-14 09:57:11 +00:00
parent 28777b0c77
commit d824dc4b73
6 changed files with 239 additions and 4 deletions
@@ -450,6 +450,47 @@ pub(super) async fn on_room_message(
return;
}
// In gateway mode, handle the "switch <project>" command to change the
// active project without invoking the LLM.
if let Some(ref active_project) = ctx.gateway_active_project {
let stripped = crate::chat::util::strip_bot_mention(
&user_message,
&ctx.bot_name,
ctx.bot_user_id.as_str(),
)
.trim()
.trim_start_matches(|c: char| !c.is_alphanumeric())
.to_string();
let (cmd, arg) = match stripped.split_once(char::is_whitespace) {
Some((c, a)) => (c.to_string(), a.trim().to_string()),
None => (stripped.clone(), String::new()),
};
if cmd.eq_ignore_ascii_case("switch") {
let response = if arg.is_empty() {
let available = ctx.gateway_projects.join(", ");
format!("Usage: `switch <project>`. Available projects: {available}")
} else if ctx.gateway_projects.iter().any(|p| p == &arg) {
*active_project.write().await = arg.clone();
format!("Switched to project **{arg}**.")
} else {
let available = ctx.gateway_projects.join(", ");
format!("Unknown project `{arg}`. Available: {available}")
};
let html = markdown_to_html(&response);
if let Ok(msg_id) = ctx
.transport
.send_message(&room_id_str, &response, &html)
.await
&& let Ok(event_id) = msg_id.parse()
{
ctx.bot_sent_event_ids.lock().await.insert(event_id);
}
return;
}
}
// Check for the timer command, which requires async file I/O and cannot
// be handled by the sync command registry.
if let Some(timer_cmd) = crate::chat::timer::extract_timer_command(
@@ -501,8 +542,14 @@ pub(super) async fn handle_message(
// The prompt is just the current message with sender attribution.
// Prior conversation context is carried by the Claude Code session.
let bot_name = &ctx.bot_name;
let active_project_ctx = if let Some(ref ap) = ctx.gateway_active_project {
let name = ap.read().await.clone();
format!("[Active project: {name}]\n")
} else {
String::new()
};
let prompt = format!(
"[Your name is {bot_name}. Refer to yourself as {bot_name}, not Claude.]\n\n{}",
"[Your name is {bot_name}. Refer to yourself as {bot_name}, not Claude.]\n{active_project_ctx}\n{}",
format_user_prompt(&sender, &user_message)
);