storkit: merge 400_bug_whatsapp_and_slack_missing_reset_command_handler
This commit is contained in:
@@ -863,6 +863,28 @@ async fn handle_incoming_message(
|
||||
return;
|
||||
}
|
||||
|
||||
if crate::chat::transport::matrix::reset::extract_reset_command(
|
||||
message,
|
||||
&ctx.bot_name,
|
||||
&ctx.bot_user_id,
|
||||
)
|
||||
.is_some()
|
||||
{
|
||||
slog!("[slack] Handling reset command from {user} in {channel}");
|
||||
{
|
||||
let mut guard = ctx.history.lock().await;
|
||||
let conv = guard.entry(channel.to_string()).or_insert_with(RoomConversation::default);
|
||||
conv.session_id = None;
|
||||
conv.entries.clear();
|
||||
save_slack_history(&ctx.project_root, &guard);
|
||||
}
|
||||
let _ = ctx
|
||||
.transport
|
||||
.send_message(channel, "Session cleared.", "")
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
// No command matched — forward to LLM for conversational response.
|
||||
slog!("[slack] No command matched, forwarding to LLM for {user} in {channel}");
|
||||
handle_llm_message(ctx, channel, user, message).await;
|
||||
@@ -1725,4 +1747,63 @@ mod tests {
|
||||
);
|
||||
assert!(result.is_none(), "'status' should not be recognised as rebuild");
|
||||
}
|
||||
|
||||
// ── reset command extraction ───────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn reset_command_extracted_from_slack_message() {
|
||||
let result = crate::chat::transport::matrix::reset::extract_reset_command(
|
||||
"Storkit reset",
|
||||
"Storkit",
|
||||
"slack-bot",
|
||||
);
|
||||
assert!(result.is_some(), "'Storkit reset' should be recognised");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reset_command_extracted_plain_no_mention() {
|
||||
let result = crate::chat::transport::matrix::reset::extract_reset_command(
|
||||
"reset",
|
||||
"Storkit",
|
||||
"slack-bot",
|
||||
);
|
||||
assert!(result.is_some(), "plain 'reset' should be recognised");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn reset_command_clears_slack_session() {
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex as TokioMutex;
|
||||
|
||||
let channel = "C01ABCDEF";
|
||||
let history: SlackConversationHistory = Arc::new(TokioMutex::new({
|
||||
let mut m = HashMap::new();
|
||||
m.insert(channel.to_string(), RoomConversation {
|
||||
session_id: Some("old-session".to_string()),
|
||||
entries: vec![ConversationEntry {
|
||||
role: ConversationRole::User,
|
||||
sender: "U01GHIJKL".to_string(),
|
||||
content: "previous message".to_string(),
|
||||
}],
|
||||
});
|
||||
m
|
||||
}));
|
||||
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let sk = tmp.path().join(".storkit");
|
||||
std::fs::create_dir_all(&sk).unwrap();
|
||||
|
||||
{
|
||||
let mut guard = history.lock().await;
|
||||
let conv = guard.entry(channel.to_string()).or_insert_with(RoomConversation::default);
|
||||
conv.session_id = None;
|
||||
conv.entries.clear();
|
||||
save_slack_history(tmp.path(), &guard);
|
||||
}
|
||||
|
||||
let guard = history.lock().await;
|
||||
let conv = guard.get(channel).unwrap();
|
||||
assert!(conv.session_id.is_none(), "session_id should be cleared");
|
||||
assert!(conv.entries.is_empty(), "entries should be cleared");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1124,6 +1124,28 @@ async fn handle_incoming_message(ctx: &WhatsAppWebhookContext, sender: &str, mes
|
||||
return;
|
||||
}
|
||||
|
||||
if crate::chat::transport::matrix::reset::extract_reset_command(
|
||||
message,
|
||||
&ctx.bot_name,
|
||||
&ctx.bot_user_id,
|
||||
)
|
||||
.is_some()
|
||||
{
|
||||
slog!("[whatsapp] Handling reset command from {sender}");
|
||||
{
|
||||
let mut guard = ctx.history.lock().await;
|
||||
let conv = guard.entry(sender.to_string()).or_insert_with(RoomConversation::default);
|
||||
conv.session_id = None;
|
||||
conv.entries.clear();
|
||||
save_whatsapp_history(&ctx.project_root, &guard);
|
||||
}
|
||||
let _ = ctx
|
||||
.transport
|
||||
.send_message(sender, "Session cleared.", "")
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
// No command matched — forward to LLM for conversational response.
|
||||
slog!("[whatsapp] No command matched, forwarding to LLM for {sender}");
|
||||
handle_llm_message(ctx, sender, message).await;
|
||||
@@ -2127,4 +2149,63 @@ mod tests {
|
||||
assert!(loaded.contains_key("222"));
|
||||
assert_eq!(loaded["222"].session_id.as_deref(), Some("sess-222"));
|
||||
}
|
||||
|
||||
// ── reset command extraction ───────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn reset_command_extracted_from_plain_message() {
|
||||
let result = crate::chat::transport::matrix::reset::extract_reset_command(
|
||||
"reset",
|
||||
"Timmy",
|
||||
"@timmy:home.local",
|
||||
);
|
||||
assert!(result.is_some(), "plain 'reset' should be recognised");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reset_command_extracted_with_bot_name_prefix() {
|
||||
let result = crate::chat::transport::matrix::reset::extract_reset_command(
|
||||
"Timmy reset",
|
||||
"Timmy",
|
||||
"@timmy:home.local",
|
||||
);
|
||||
assert!(result.is_some(), "'Timmy reset' should be recognised");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn reset_command_clears_whatsapp_session() {
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex as TokioMutex;
|
||||
|
||||
let sender = "+15555550100";
|
||||
let history: WhatsAppConversationHistory = Arc::new(TokioMutex::new({
|
||||
let mut m = HashMap::new();
|
||||
m.insert(sender.to_string(), RoomConversation {
|
||||
session_id: Some("old-session".to_string()),
|
||||
entries: vec![ConversationEntry {
|
||||
role: ConversationRole::User,
|
||||
sender: sender.to_string(),
|
||||
content: "previous message".to_string(),
|
||||
}],
|
||||
});
|
||||
m
|
||||
}));
|
||||
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let sk = tmp.path().join(".storkit");
|
||||
std::fs::create_dir_all(&sk).unwrap();
|
||||
|
||||
{
|
||||
let mut guard = history.lock().await;
|
||||
let conv = guard.entry(sender.to_string()).or_insert_with(RoomConversation::default);
|
||||
conv.session_id = None;
|
||||
conv.entries.clear();
|
||||
save_whatsapp_history(tmp.path(), &guard);
|
||||
}
|
||||
|
||||
let guard = history.lock().await;
|
||||
let conv = guard.get(sender).unwrap();
|
||||
assert!(conv.session_id.is_none(), "session_id should be cleared");
|
||||
assert!(conv.entries.is_empty(), "entries should be cleared");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user