huskies: merge 1153 story huskies projects chat command — list every registered project with port and status

This commit is contained in:
dave
2026-05-20 00:23:44 +00:00
parent 0c207981e9
commit 846b3e1b4c
5 changed files with 337 additions and 0 deletions
@@ -33,6 +33,19 @@ fn extract_health_command(message: &str, bot_name: &str, bot_user_id: &str) -> b
cmd.eq_ignore_ascii_case("health")
}
/// Return `true` when the message is a `projects` command addressed to the bot.
///
/// Recognised case-insensitively as the single word `projects` after stripping the bot
/// mention prefix. Any trailing whitespace is ignored.
fn extract_projects_command(message: &str, bot_name: &str, bot_user_id: &str) -> bool {
let stripped = crate::chat::util::strip_bot_mention(message, bot_name, bot_user_id);
let trimmed = stripped
.trim()
.trim_start_matches(|c: char| !c.is_alphanumeric());
let cmd = trimmed.split_whitespace().next().unwrap_or("");
cmd.eq_ignore_ascii_case("projects")
}
/// Return `true` when the message is a "rebuild gateway" command addressed to the bot.
///
/// The command is recognised case-insensitively as `rebuild gateway` after stripping
@@ -270,6 +283,7 @@ pub(in crate::chat::transport::matrix::bot) async fn on_room_message(
"project-rebuild",
"upgrade",
"health",
"projects",
];
let stripped = crate::chat::util::strip_bot_mention(
@@ -587,6 +601,28 @@ pub(in crate::chat::transport::matrix::bot) async fn on_room_message(
return;
}
// `projects` — gateway-only project enumeration (no liveness checks).
if ctx.is_gateway()
&& extract_projects_command(
&user_message,
&ctx.services.bot_name,
ctx.matrix_user_id.as_str(),
)
{
slog!("[matrix-bot] Handling 'projects' from {sender}");
let response = super::super::super::projects::run_projects_list(&ctx).await;
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 bot-level commands (help, status, ambient, …) before invoking
// the LLM. All commands are registered in commands.rs — no special-casing
// needed here.