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;
|
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.
|
// No command matched — forward to LLM for conversational response.
|
||||||
slog!("[slack] No command matched, forwarding to LLM for {user} in {channel}");
|
slog!("[slack] No command matched, forwarding to LLM for {user} in {channel}");
|
||||||
handle_llm_message(ctx, channel, user, message).await;
|
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");
|
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;
|
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.
|
// No command matched — forward to LLM for conversational response.
|
||||||
slog!("[whatsapp] No command matched, forwarding to LLM for {sender}");
|
slog!("[whatsapp] No command matched, forwarding to LLM for {sender}");
|
||||||
handle_llm_message(ctx, sender, message).await;
|
handle_llm_message(ctx, sender, message).await;
|
||||||
@@ -2127,4 +2149,63 @@ mod tests {
|
|||||||
assert!(loaded.contains_key("222"));
|
assert!(loaded.contains_key("222"));
|
||||||
assert_eq!(loaded["222"].session_id.as_deref(), Some("sess-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