diff --git a/crates/rustyclaw-core/src/security/safety_layer.rs b/crates/rustyclaw-core/src/security/safety_layer.rs index 3eb84a9..676bf4c 100644 --- a/crates/rustyclaw-core/src/security/safety_layer.rs +++ b/crates/rustyclaw-core/src/security/safety_layer.rs @@ -19,8 +19,8 @@ //! //! ## Usage //! -//! ```rust -//! use rustyclaw::security::{SafetyConfig, SafetyLayer, PolicyAction}; +//! ```rust,ignore +//! use rustyclaw_core::security::{SafetyConfig, SafetyLayer, PolicyAction}; //! //! let config = SafetyConfig { //! prompt_injection_policy: PolicyAction::Block, @@ -644,9 +644,9 @@ mod tests { }; let safety = SafetyLayer::new(config); - // Clean request should pass + // Clean request should pass (use IP to avoid DNS resolution in CI) let result = safety.validate_http_request( - "https://api.example.com/data", + "https://93.184.215.14/data", &[("Content-Type".to_string(), "application/json".to_string())], Some(b"{\"query\": \"hello\"}"), ); diff --git a/crates/rustyclaw-tui/src/components/message_bubble.rs b/crates/rustyclaw-tui/src/components/message_bubble.rs index 9483ccc..39d0ff7 100644 --- a/crates/rustyclaw-tui/src/components/message_bubble.rs +++ b/crates/rustyclaw-tui/src/components/message_bubble.rs @@ -9,6 +9,8 @@ use rustyclaw_core::types::MessageRole; pub struct MessageBubbleProps { pub role: Option, pub content: String, + /// Custom name to display for assistant messages (falls back to "Assistant"). + pub assistant_name: Option, } #[component] @@ -20,16 +22,19 @@ pub fn MessageBubble(props: &MessageBubbleProps) -> impl Into "You", - MessageRole::Assistant => "Assistant", - MessageRole::Info => "Info", - MessageRole::Success => "Success", - MessageRole::Warning => "Warning", - MessageRole::Error => "Error", - MessageRole::System => "System", - MessageRole::ToolCall => "Tool Call", - MessageRole::ToolResult => "Tool Result", - MessageRole::Thinking => "Thinking", + MessageRole::User => "You".to_string(), + MessageRole::Assistant => props + .assistant_name + .clone() + .unwrap_or_else(|| "Assistant".to_string()), + MessageRole::Info => "Info".to_string(), + MessageRole::Success => "Success".to_string(), + MessageRole::Warning => "Warning".to_string(), + MessageRole::Error => "Error".to_string(), + MessageRole::System => "System".to_string(), + MessageRole::ToolCall => "Tool Call".to_string(), + MessageRole::ToolResult => "Tool Result".to_string(), + MessageRole::Thinking => "Thinking".to_string(), }; // Render markdown for assistant messages, plain text for others diff --git a/crates/rustyclaw-tui/src/components/messages.rs b/crates/rustyclaw-tui/src/components/messages.rs index 6d89213..05a9229 100644 --- a/crates/rustyclaw-tui/src/components/messages.rs +++ b/crates/rustyclaw-tui/src/components/messages.rs @@ -25,11 +25,14 @@ pub struct MessagesProps { pub spinner_tick: usize, /// Elapsed time string (e.g., "2.3s"). pub elapsed: String, + /// Custom name to display for assistant messages. + pub assistant_name: Option, } #[component] pub fn Messages(props: &MessagesProps) -> impl Into> { let spinner = SPINNER_FRAMES[props.spinner_tick % SPINNER_FRAMES.len()]; + let assistant_name = props.assistant_name.clone(); element! { View( @@ -45,11 +48,13 @@ pub fn Messages(props: &MessagesProps) -> impl Into> { bottom: -(props.scroll_offset), ) { #(props.messages.iter().enumerate().map(|(i, msg)| { + let name = assistant_name.clone(); element! { MessageBubble( key: i as u64, role: msg.role, content: msg.content.clone(), + assistant_name: name, ) } })) diff --git a/crates/rustyclaw-tui/src/components/root.rs b/crates/rustyclaw-tui/src/components/root.rs index 2d2fc1e..e969bb0 100644 --- a/crates/rustyclaw-tui/src/components/root.rs +++ b/crates/rustyclaw-tui/src/components/root.rs @@ -161,6 +161,11 @@ pub fn Root(props: &mut RootProps) -> impl Into> { streaming: props.streaming, spinner_tick: props.spinner_tick, elapsed: props.elapsed.clone(), + assistant_name: if props.soul_name.is_empty() { + None + } else { + Some(props.soul_name.clone()) + }, ) CommandMenu( completions: props.command_completions.clone(),