Fixing code warnings
This commit is contained in:
@@ -15,9 +15,6 @@ use async_trait::async_trait;
|
||||
/// producing and consuming these identifiers.
|
||||
pub type MessageId = String;
|
||||
|
||||
/// A platform-agnostic identifier for a chat room / channel / conversation.
|
||||
pub type RoomId = String;
|
||||
|
||||
/// Abstraction over a chat platform's message-sending capabilities.
|
||||
///
|
||||
/// Implementations must be `Send + Sync` so they can be shared across
|
||||
|
||||
@@ -15,8 +15,8 @@ use tokio::sync::Mutex as TokioMutex;
|
||||
|
||||
use crate::agents::AgentPool;
|
||||
use crate::chat::transport::matrix::{ConversationEntry, ConversationRole, RoomConversation};
|
||||
use crate::slog;
|
||||
use crate::chat::{ChatTransport, MessageId};
|
||||
use crate::slog;
|
||||
|
||||
// ── API base URLs (overridable for tests) ────────────────────────────────
|
||||
|
||||
@@ -46,6 +46,7 @@ const OUTSIDE_WINDOW_ERR: &str = "OUTSIDE_MESSAGING_WINDOW";
|
||||
/// between free-form text and a template message.
|
||||
pub struct MessagingWindowTracker {
|
||||
last_message: std::sync::Mutex<HashMap<String, std::time::Instant>>,
|
||||
#[allow(dead_code)] // Used by Meta provider path (is_within_window → send_notification)
|
||||
window_duration: std::time::Duration,
|
||||
}
|
||||
|
||||
@@ -83,6 +84,7 @@ impl MessagingWindowTracker {
|
||||
|
||||
/// Returns `true` when the last inbound message from `phone` arrived within
|
||||
/// the 24-hour window, meaning free-form replies are still permitted.
|
||||
#[allow(dead_code)] // Used by Meta provider path (send_notification)
|
||||
pub fn is_within_window(&self, phone: &str) -> bool {
|
||||
let map = self.last_message.lock().unwrap();
|
||||
match map.get(phone) {
|
||||
@@ -105,6 +107,7 @@ pub struct WhatsAppTransport {
|
||||
client: reqwest::Client,
|
||||
/// Name of the approved Meta message template used for notifications
|
||||
/// outside the 24-hour messaging window.
|
||||
#[allow(dead_code)] // Used by Meta provider path (send_template_notification)
|
||||
notification_template_name: String,
|
||||
/// Optional base URL override for tests.
|
||||
api_base: String,
|
||||
@@ -126,11 +129,7 @@ impl WhatsAppTransport {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn with_api_base(
|
||||
phone_number_id: String,
|
||||
access_token: String,
|
||||
api_base: String,
|
||||
) -> Self {
|
||||
fn with_api_base(phone_number_id: String, access_token: String, api_base: String) -> Self {
|
||||
Self {
|
||||
phone_number_id,
|
||||
access_token,
|
||||
@@ -209,6 +208,7 @@ impl WhatsAppTransport {
|
||||
///
|
||||
/// The template body is expected to accept two positional parameters:
|
||||
/// `{{1}}` = story name, `{{2}}` = pipeline stage.
|
||||
#[allow(dead_code)] // Meta provider path — template fallback for expired 24h window
|
||||
pub async fn send_template_notification(
|
||||
&self,
|
||||
to: &str,
|
||||
@@ -282,6 +282,7 @@ impl WhatsAppTransport {
|
||||
///
|
||||
/// This method never crashes on a messaging-window error — it always
|
||||
/// attempts the template fallback and logs what happened.
|
||||
#[allow(dead_code)] // Meta provider path — window-aware notification dispatch
|
||||
pub async fn send_notification(
|
||||
&self,
|
||||
to: &str,
|
||||
@@ -423,7 +424,11 @@ impl TwilioWhatsAppTransport {
|
||||
format!("whatsapp:{}", to)
|
||||
};
|
||||
|
||||
let params = [("From", from.as_str()), ("To", to_wa.as_str()), ("Body", body)];
|
||||
let params = [
|
||||
("From", from.as_str()),
|
||||
("To", to_wa.as_str()),
|
||||
("Body", body),
|
||||
];
|
||||
|
||||
let resp = self
|
||||
.client
|
||||
@@ -444,9 +449,8 @@ impl TwilioWhatsAppTransport {
|
||||
return Err(format!("Twilio API returned {status}: {resp_text}"));
|
||||
}
|
||||
|
||||
let parsed: TwilioSendResponse = serde_json::from_str(&resp_text).map_err(|e| {
|
||||
format!("Failed to parse Twilio API response: {e} — body: {resp_text}")
|
||||
})?;
|
||||
let parsed: TwilioSendResponse = serde_json::from_str(&resp_text)
|
||||
.map_err(|e| format!("Failed to parse Twilio API response: {e} — body: {resp_text}"))?;
|
||||
|
||||
Ok(parsed.sid.unwrap_or_default())
|
||||
}
|
||||
@@ -472,7 +476,9 @@ impl ChatTransport for TwilioWhatsAppTransport {
|
||||
html: &str,
|
||||
) -> Result<(), String> {
|
||||
// Twilio does not support message editing — send a new message.
|
||||
slog!("[whatsapp/twilio] edit_message — Twilio does not support edits, sending new message");
|
||||
slog!(
|
||||
"[whatsapp/twilio] edit_message — Twilio does not support edits, sending new message"
|
||||
);
|
||||
self.send_message(recipient, plain, html).await.map(|_| ())
|
||||
}
|
||||
|
||||
@@ -525,10 +531,7 @@ pub fn extract_twilio_text_messages(bytes: &[u8]) -> Vec<(String, String)> {
|
||||
};
|
||||
|
||||
// Strip the "whatsapp:" prefix so the sender is stored as a plain phone number.
|
||||
let sender = from
|
||||
.strip_prefix("whatsapp:")
|
||||
.unwrap_or(&from)
|
||||
.to_string();
|
||||
let sender = from.strip_prefix("whatsapp:").unwrap_or(&from).to_string();
|
||||
|
||||
vec![(sender, body)]
|
||||
}
|
||||
@@ -575,6 +578,7 @@ struct GraphApiError {
|
||||
|
||||
// ── Template message types ──────────────────────────────────────────────
|
||||
|
||||
#[allow(dead_code)] // Meta provider path — template message types
|
||||
#[derive(Serialize)]
|
||||
struct GraphTemplateMessage<'a> {
|
||||
messaging_product: &'a str,
|
||||
@@ -583,6 +587,7 @@ struct GraphTemplateMessage<'a> {
|
||||
template: GraphTemplate<'a>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Serialize)]
|
||||
struct GraphTemplate<'a> {
|
||||
name: &'a str,
|
||||
@@ -590,17 +595,20 @@ struct GraphTemplate<'a> {
|
||||
components: Vec<GraphTemplateComponent>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Serialize)]
|
||||
struct GraphLanguage {
|
||||
code: &'static str,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Serialize)]
|
||||
struct GraphTemplateComponent {
|
||||
r#type: &'static str,
|
||||
parameters: Vec<GraphTemplateParameter>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Serialize)]
|
||||
struct GraphTemplateParameter {
|
||||
r#type: &'static str,
|
||||
@@ -631,11 +639,13 @@ pub struct WebhookChange {
|
||||
pub struct WebhookValue {
|
||||
#[serde(default)]
|
||||
pub messages: Vec<WebhookMessage>,
|
||||
#[allow(dead_code)] // Present in Meta webhook JSON, kept for deserialization
|
||||
pub metadata: Option<WebhookMetadata>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct WebhookMetadata {
|
||||
#[allow(dead_code)]
|
||||
pub phone_number_id: Option<String>,
|
||||
}
|
||||
|
||||
@@ -733,9 +743,7 @@ struct PersistedWhatsAppHistory {
|
||||
const WHATSAPP_HISTORY_FILE: &str = ".storkit/whatsapp_history.json";
|
||||
|
||||
/// Load WhatsApp conversation history from disk.
|
||||
pub fn load_whatsapp_history(
|
||||
project_root: &std::path::Path,
|
||||
) -> HashMap<String, RoomConversation> {
|
||||
pub fn load_whatsapp_history(project_root: &std::path::Path) -> HashMap<String, RoomConversation> {
|
||||
let path = project_root.join(WHATSAPP_HISTORY_FILE);
|
||||
let data = match std::fs::read_to_string(&path) {
|
||||
Ok(d) => d,
|
||||
@@ -828,9 +836,7 @@ pub async fn webhook_verify(
|
||||
&& let Some(challenge) = q.hub_challenge
|
||||
{
|
||||
slog!("[whatsapp] Webhook verification succeeded");
|
||||
return Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.body(challenge);
|
||||
return Response::builder().status(StatusCode::OK).body(challenge);
|
||||
}
|
||||
slog!("[whatsapp] Webhook verification failed");
|
||||
Response::builder()
|
||||
@@ -897,17 +903,11 @@ pub async fn webhook_receive(
|
||||
}
|
||||
});
|
||||
|
||||
Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.body("ok")
|
||||
Response::builder().status(StatusCode::OK).body("ok")
|
||||
}
|
||||
|
||||
/// Dispatch an incoming WhatsApp message to bot commands.
|
||||
async fn handle_incoming_message(
|
||||
ctx: &WhatsAppWebhookContext,
|
||||
sender: &str,
|
||||
message: &str,
|
||||
) {
|
||||
async fn handle_incoming_message(ctx: &WhatsAppWebhookContext, sender: &str, message: &str) {
|
||||
use crate::chat::transport::matrix::commands::{CommandDispatch, try_handle_command};
|
||||
|
||||
// Record this inbound message to keep the 24-hour window open.
|
||||
@@ -950,12 +950,12 @@ async fn handle_incoming_message(
|
||||
HtopCommand::Start { duration_secs } => {
|
||||
// On WhatsApp, send a single snapshot instead of a live-updating
|
||||
// dashboard since we can't edit messages.
|
||||
let snapshot =
|
||||
crate::chat::transport::matrix::htop::build_htop_message(&ctx.agents, 0, duration_secs);
|
||||
let _ = ctx
|
||||
.transport
|
||||
.send_message(sender, &snapshot, "")
|
||||
.await;
|
||||
let snapshot = crate::chat::transport::matrix::htop::build_htop_message(
|
||||
&ctx.agents,
|
||||
0,
|
||||
duration_secs,
|
||||
);
|
||||
let _ = ctx.transport.send_message(sender, &snapshot, "").await;
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -991,22 +991,16 @@ async fn handle_incoming_message(
|
||||
}
|
||||
|
||||
/// Forward a message to Claude Code and send the response back via WhatsApp.
|
||||
async fn handle_llm_message(
|
||||
ctx: &WhatsAppWebhookContext,
|
||||
sender: &str,
|
||||
user_message: &str,
|
||||
) {
|
||||
use crate::llm::providers::claude_code::{ClaudeCodeProvider, ClaudeCodeResult};
|
||||
async fn handle_llm_message(ctx: &WhatsAppWebhookContext, sender: &str, user_message: &str) {
|
||||
use crate::chat::transport::matrix::drain_complete_paragraphs;
|
||||
use crate::llm::providers::claude_code::{ClaudeCodeProvider, ClaudeCodeResult};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use tokio::sync::watch;
|
||||
|
||||
// Look up existing session ID for this sender.
|
||||
let resume_session_id: Option<String> = {
|
||||
let guard = ctx.history.lock().await;
|
||||
guard
|
||||
.get(sender)
|
||||
.and_then(|conv| conv.session_id.clone())
|
||||
guard.get(sender).and_then(|conv| conv.session_id.clone())
|
||||
};
|
||||
|
||||
let bot_name = &ctx.bot_name;
|
||||
@@ -1077,9 +1071,7 @@ async fn handle_llm_message(
|
||||
let last_text = messages
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|m| {
|
||||
m.role == crate::llm::types::Role::Assistant && !m.content.is_empty()
|
||||
})
|
||||
.find(|m| m.role == crate::llm::types::Role::Assistant && !m.content.is_empty())
|
||||
.map(|m| m.content.clone())
|
||||
.unwrap_or_default();
|
||||
if !last_text.is_empty() {
|
||||
@@ -1220,7 +1212,10 @@ mod tests {
|
||||
let result = transport.send_message("15551234567", "hello", "").await;
|
||||
assert!(result.is_err());
|
||||
let msg = result.unwrap_err();
|
||||
assert!(msg.contains("24-hour messaging window"), "unexpected: {msg}");
|
||||
assert!(
|
||||
msg.contains("24-hour messaging window"),
|
||||
"unexpected: {msg}"
|
||||
);
|
||||
}
|
||||
|
||||
// ── send_template_notification ────────────────────────────────────
|
||||
|
||||
@@ -414,7 +414,8 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
startup_agents.auto_assign_available_work(&root).await;
|
||||
});
|
||||
}
|
||||
let addr = format!("127.0.0.1:{port}");
|
||||
let host = std::env::var("STORKIT_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
|
||||
let addr = format!("{host}:{port}");
|
||||
|
||||
println!(
|
||||
"\x1b[95;1m ____ _ _ ___ _ \n / ___|| |_ ___ _ __| | _|_ _| |_ \n \\___ \\| __/ _ \\| '__| |/ /| || __|\n ___) | || (_) | | | < | || |_ \n |____/ \\__\\___/|_| |_|\\_\\___|\\__|\n\x1b[0m"
|
||||
|
||||
Reference in New Issue
Block a user