//! WhatsApp LLM message handler — runs an LLM turn for a non-command message. use std::sync::Arc; use super::super::WhatsAppWebhookContext; use super::super::format::{chunk_for_whatsapp, markdown_to_whatsapp}; use super::super::history::save_whatsapp_history; /// [`crate::chat::llm_turn::TransportFormat`] implementation for WhatsApp: /// messages are markdown-converted then split to fit the platform's size /// limit, and LLM errors are checked for an OAuth login link. #[derive(Clone, Copy)] struct WhatsAppFormat; impl crate::chat::llm_turn::TransportFormat for WhatsAppFormat { fn format_and_chunk(&self, markdown: &str) -> Vec { chunk_for_whatsapp(&markdown_to_whatsapp(markdown)) } fn log_prefix(&self) -> &'static str { "[whatsapp]" } fn format_error(&self, err: &str) -> String { if let Some(url) = crate::llm::oauth::extract_login_url_from_error(err) { format!("Authentication required. Log in to Claude here: {url}") } else { format!("Error processing your request: {err}") } } } /// Forward a message to Claude Code and send the response back via WhatsApp. pub(super) async fn handle_llm_message( ctx: &WhatsAppWebhookContext, sender: &str, user_message: &str, ) { use crate::chat::llm_turn::{LlmTurnContext, run_llm_turn}; run_llm_turn( LlmTurnContext { transport: Arc::clone(&ctx.transport), key: sender, user: sender, services: &ctx.services, history: &ctx.history, history_size: ctx.history_size, save_history: save_whatsapp_history, }, WhatsAppFormat, user_message, ) .await; } // ── Tests ───────────────────────────────────────────────────────────────