fix: add --all to cargo fmt in script/test and autoformat codebase

cargo fmt without --all fails with "Failed to find targets" in
workspace repos. This was blocking every story's gates. Also ran
cargo fmt --all to fix all existing formatting issues.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dave
2026-04-13 14:07:08 +00:00
co-authored by Claude Opus 4.6
parent ed2526ce41
commit 845b85e7a7
128 changed files with 3566 additions and 2395 deletions
+60 -35
View File
@@ -1,22 +1,24 @@
//! WhatsApp command handling — processes incoming WhatsApp messages as bot commands.
use std::sync::Arc;
use crate::chat::transport::matrix::{ConversationEntry, ConversationRole, RoomConversation};
use crate::chat::util::is_permission_approval;
use crate::http::context::{PermissionDecision};
use crate::slog;
use super::WhatsAppWebhookContext;
use super::format::{chunk_for_whatsapp, markdown_to_whatsapp};
use super::history::save_whatsapp_history;
use crate::chat::transport::matrix::{ConversationEntry, ConversationRole, RoomConversation};
use crate::chat::util::is_permission_approval;
use crate::http::context::PermissionDecision;
use crate::slog;
/// Dispatch an incoming WhatsApp message to bot commands.
pub(super) async fn handle_incoming_message(ctx: &WhatsAppWebhookContext, sender: &str, message: &str) {
pub(super) async fn handle_incoming_message(
ctx: &WhatsAppWebhookContext,
sender: &str,
message: &str,
) {
use crate::chat::commands::{CommandDispatch, try_handle_command};
// Allowlist check: when configured, silently ignore unauthorized senders.
if !ctx.allowed_phones.is_empty()
&& !ctx.allowed_phones.iter().any(|p| p == sender)
{
if !ctx.allowed_phones.is_empty() && !ctx.allowed_phones.iter().any(|p| p == sender) {
slog!("[whatsapp] Ignoring message from unauthorized sender: {sender}");
return;
}
@@ -173,7 +175,9 @@ pub(super) async fn handle_incoming_message(ctx: &WhatsAppWebhookContext, sender
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);
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);
@@ -219,8 +223,13 @@ pub(super) async fn handle_incoming_message(ctx: &WhatsAppWebhookContext, sender
&ctx.bot_user_id,
) {
let response = match assign_cmd {
crate::chat::transport::matrix::assign::AssignCommand::Assign { story_number, model } => {
slog!("[whatsapp] Handling assign command from {sender}: story {story_number} model {model}");
crate::chat::transport::matrix::assign::AssignCommand::Assign {
story_number,
model,
} => {
slog!(
"[whatsapp] Handling assign command from {sender}: story {story_number} model {model}"
);
crate::chat::transport::matrix::assign::handle_assign(
&ctx.bot_name,
&story_number,
@@ -385,9 +394,7 @@ async fn handle_llm_message(ctx: &WhatsAppWebhookContext, sender: &str, user_mes
Err(e) => {
slog!("[whatsapp] LLM error: {e}");
let err_msg = if let Some(url) = crate::llm::oauth::extract_login_url_from_error(&e) {
format!(
"Authentication required. Log in to Claude here: {url}"
)
format!("Authentication required. Log in to Claude here: {url}")
} else {
format!("Error processing your request: {e}")
};
@@ -434,20 +441,18 @@ async fn handle_llm_message(ctx: &WhatsAppWebhookContext, sender: &str, user_mes
#[cfg(test)]
mod tests {
use crate::agents::AgentPool;
use crate::io::watcher::WatcherEvent;
use crate::chat::transport::matrix::{ConversationEntry, ConversationRole, RoomConversation};
use super::super::history::{MessagingWindowTracker, WhatsAppConversationHistory};
use super::super::WhatsAppWebhookContext;
use super::super::history::{MessagingWindowTracker, WhatsAppConversationHistory};
use super::*;
use crate::agents::AgentPool;
use crate::chat::transport::matrix::{ConversationEntry, ConversationRole, RoomConversation};
use crate::io::watcher::WatcherEvent;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::Mutex as TokioMutex;
/// Build a minimal WhatsAppWebhookContext for allowlist tests.
fn make_ctx_with_allowlist(
allowed_phones: Vec<String>,
) -> Arc<WhatsAppWebhookContext> {
fn make_ctx_with_allowlist(allowed_phones: Vec<String>) -> Arc<WhatsAppWebhookContext> {
struct NullTransport;
#[async_trait::async_trait]
@@ -505,9 +510,15 @@ mod tests {
let err = "OAuth session expired or credentials missing. Please log in: http://localhost:3001/oauth/authorize";
let url = crate::llm::oauth::extract_login_url_from_error(err);
assert!(url.is_some(), "should extract URL from OAuth error");
let msg = format!("Authentication required. Log in to Claude here: {}", url.unwrap());
let msg = format!(
"Authentication required. Log in to Claude here: {}",
url.unwrap()
);
assert!(msg.contains("http://localhost:3001/oauth/authorize"));
assert!(!msg.contains('['), "WhatsApp message should not use Markdown link syntax");
assert!(
!msg.contains('['),
"WhatsApp message should not use Markdown link syntax"
);
}
#[test]
@@ -594,7 +605,10 @@ mod tests {
"Timmy",
"@timmy:home.local",
);
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 ───────────────────────────────────────
@@ -624,14 +638,17 @@ mod tests {
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.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
}));
@@ -641,7 +658,9 @@ mod tests {
{
let mut guard = history.lock().await;
let conv = guard.entry(sender.to_string()).or_insert_with(RoomConversation::default);
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);
@@ -748,7 +767,10 @@ mod tests {
"Timmy",
"@timmy:home.local",
);
assert!(result.is_none(), "'status' should not be recognised as rmtree");
assert!(
result.is_none(),
"'status' should not be recognised as rmtree"
);
}
// ── assign command extraction ──────────────────────────────────────
@@ -805,6 +827,9 @@ mod tests {
"Timmy",
"@timmy:home.local",
);
assert!(result.is_none(), "'status' should not be recognised as assign");
assert!(
result.is_none(),
"'status' should not be recognised as assign"
);
}
}
+3 -6
View File
@@ -66,14 +66,11 @@ pub fn markdown_to_whatsapp(text: &str) -> String {
LazyLock::new(|| Regex::new(r"(?m)^#{1,6}\s+(.+)$").unwrap());
static RE_BOLD_ITALIC: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"\*\*\*(.+?)\*\*\*").unwrap());
static RE_BOLD: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"\*\*(.+?)\*\*").unwrap());
static RE_STRIKETHROUGH: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"~~(.+?)~~").unwrap());
static RE_BOLD: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"\*\*(.+?)\*\*").unwrap());
static RE_STRIKETHROUGH: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"~~(.+?)~~").unwrap());
static RE_LINK: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"\[([^\]]+)\]\(([^)]+)\)").unwrap());
static RE_HR: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"(?m)^---+$").unwrap());
static RE_HR: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"(?m)^---+$").unwrap());
// 1. Protect fenced code blocks by replacing them with placeholders.
let mut code_blocks: Vec<String> = Vec::new();
+6 -2
View File
@@ -2,9 +2,9 @@
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use super::history::MessagingWindowTracker;
use crate::chat::{ChatTransport, MessageId};
use crate::slog;
use super::history::MessagingWindowTracker;
// ── API base URLs (overridable for tests) ────────────────────────────────
@@ -55,7 +55,11 @@ impl WhatsAppTransport {
}
#[cfg(test)]
pub(crate) fn with_api_base(phone_number_id: String, access_token: String, api_base: String) -> Self {
pub(crate) fn with_api_base(
phone_number_id: String,
access_token: String,
api_base: String,
) -> Self {
Self {
phone_number_id,
access_token,
+3 -4
View File
@@ -13,9 +13,9 @@ pub mod history;
pub mod meta;
pub mod twilio;
pub use history::{load_whatsapp_history, MessagingWindowTracker, WhatsAppConversationHistory};
pub use history::{MessagingWindowTracker, WhatsAppConversationHistory, load_whatsapp_history};
pub use meta::WhatsAppTransport;
pub use twilio::{extract_twilio_text_messages, TwilioWhatsAppTransport};
pub use twilio::{TwilioWhatsAppTransport, extract_twilio_text_messages};
use serde::Deserialize;
use std::collections::{HashMap, HashSet};
@@ -132,8 +132,7 @@ pub struct WhatsAppWebhookContext {
/// Permission requests from the MCP `prompt_permission` tool arrive here.
pub perm_rx: Arc<TokioMutex<tokio::sync::mpsc::UnboundedReceiver<PermissionForward>>>,
/// Pending permission replies keyed by sender phone number.
pub pending_perm_replies:
Arc<TokioMutex<HashMap<String, oneshot::Sender<PermissionDecision>>>>,
pub pending_perm_replies: Arc<TokioMutex<HashMap<String, oneshot::Sender<PermissionDecision>>>>,
/// Seconds before an unanswered permission prompt is auto-denied.
pub permission_timeout_secs: u64,
}