refactor: remove dead code and unused state

This commit is contained in:
xiaoxixi 2026-07-14 11:41:07 +08:00
parent 560ace50c1
commit c2d4fc5f09
17 changed files with 80 additions and 224 deletions

View File

@ -5,7 +5,6 @@ edition = "2024"
[dependencies] [dependencies]
reqwest = { version = "0.13.3", default-features = false, features = ["json", "rustls", "multipart"] } reqwest = { version = "0.13.3", default-features = false, features = ["json", "rustls", "multipart"] }
dotenv = "0.15"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
regex = "1.12" regex = "1.12"
serde_json = "1.0" serde_json = "1.0"
@ -35,7 +34,6 @@ crossterm = { version = "0.29", features = ["event-stream"] }
termimad = "0.34" termimad = "0.34"
textwrap = "0.16" textwrap = "0.16"
chrono = "0.4" chrono = "0.4"
hostname = "0.4"
sqlx = { version = "0.8", features = ["sqlite", "macros", "chrono", "runtime-tokio"] } sqlx = { version = "0.8", features = ["sqlite", "macros", "chrono", "runtime-tokio"] }
jieba-rs = "0.9" jieba-rs = "0.9"
which = "8" which = "8"
@ -52,6 +50,9 @@ tar = "0.4"
fantoccini = { version = "0.22", default-features = false, features = ["rustls-tls"] } fantoccini = { version = "0.22", default-features = false, features = ["rustls-tls"] }
portable-pty = "0.9" portable-pty = "0.9"
[dev-dependencies]
dotenv = "0.15"
[build-dependencies] [build-dependencies]
zstd = "0.13" zstd = "0.13"
tar = "0.4" tar = "0.4"

View File

@ -391,16 +391,15 @@ impl SubAgentManager {
// Update DB: running // Update DB: running
if let Some(ref s) = storage { if let Some(ref s) = storage {
let _ = s let _ = s
.update_background_task_status( .update_background_task_status(&tid, crate::storage::background_task::BackgroundTaskUpdate {
&tid, status: "running",
"running", result: None,
None, error: None,
None, started_at: Some(started_at),
Some(started_at), finished_at: None,
None, tool_calls_count: None,
None, iterations: None,
None, })
)
.await; .await;
} }
@ -513,16 +512,15 @@ impl SubAgentManager {
if let Some(ref s) = storage { if let Some(ref s) = storage {
let _ = s let _ = s
.update_background_task_status( .update_background_task_status(&tid, crate::storage::background_task::BackgroundTaskUpdate {
&tid, status: &status_str,
&status_str, result: Some(&result.content),
Some(&result.content), error: error_val.as_deref(),
error_val.as_deref(), started_at: Some(started_at),
Some(started_at), finished_at: Some(finished_at),
Some(finished_at), tool_calls_count: Some(result.tool_calls_count as i64),
Some(result.tool_calls_count as i64), iterations: Some(result.iterations as i64),
Some(result.iterations as i64), })
)
.await; .await;
} }
@ -544,13 +542,15 @@ impl SubAgentManager {
let _ = storage let _ = storage
.update_background_task_status( .update_background_task_status(
&task_id, &task_id,
"cancelled", crate::storage::background_task::BackgroundTaskUpdate {
None, status: "cancelled",
Some("gateway shutdown"), result: None,
None, error: Some("gateway shutdown"),
Some(chrono::Utc::now().timestamp_millis()), started_at: None,
None, finished_at: Some(chrono::Utc::now().timestamp_millis()),
None, tool_calls_count: None,
iterations: None,
},
) )
.await; .await;
} }
@ -568,13 +568,15 @@ impl SubAgentManager {
if let Some(ref s) = self.storage { if let Some(ref s) = self.storage {
s.update_background_task_status( s.update_background_task_status(
task_id, task_id,
"cancelled", crate::storage::background_task::BackgroundTaskUpdate {
None, status: "cancelled",
None, result: None,
None, error: None,
Some(chrono::Utc::now().timestamp_millis()), started_at: None,
None, finished_at: Some(chrono::Utc::now().timestamp_millis()),
None, tool_calls_count: None,
iterations: None,
},
) )
.await .await
.map_err(|e| SubAgentError::Storage(e.to_string()))?; .map_err(|e| SubAgentError::Storage(e.to_string()))?;
@ -662,6 +664,16 @@ fn truncate_sub_agent_result(content: &str) -> (String, bool) {
} }
} }
fn summarize_for_notification(content: &str, _duration_ms: u64) -> String {
const MAX_SUMMARY_BYTES: usize = 500;
if content.len() <= MAX_SUMMARY_BYTES {
content.to_string()
} else {
let truncate_at = content.floor_char_boundary(MAX_SUMMARY_BYTES);
format!("{}...", &content[..truncate_at])
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -723,13 +735,3 @@ mod tests {
assert!(matches!(error, SubAgentError::TooManyTasks(1))); assert!(matches!(error, SubAgentError::TooManyTasks(1)));
} }
} }
fn summarize_for_notification(content: &str, _duration_ms: u64) -> String {
const MAX_SUMMARY_BYTES: usize = 500;
if content.len() <= MAX_SUMMARY_BYTES {
content.to_string()
} else {
let truncate_at = content.floor_char_boundary(MAX_SUMMARY_BYTES);
format!("{}...", &content[..truncate_at])
}
}

View File

@ -264,12 +264,6 @@ pub struct InboundMessage {
pub forwarded_metadata: HashMap<String, String>, pub forwarded_metadata: HashMap<String, String>,
} }
impl InboundMessage {
pub fn session_key(&self) -> String {
format!("{}:{}", self.channel, self.chat_id)
}
}
// ============================================================================ // ============================================================================
// OutboundMessage - Message from Agent to Channel (bot response) // OutboundMessage - Message from Agent to Channel (bot response)
// ============================================================================ // ============================================================================
@ -284,12 +278,6 @@ pub struct OutboundMessage {
pub metadata: HashMap<String, String>, pub metadata: HashMap<String, String>,
} }
impl OutboundMessage {
pub fn is_stream_delta(&self) -> bool {
self.metadata.contains_key("_stream_delta")
}
}
// ============================================================================ // ============================================================================
// ControlMessage - Message for control channel (session management) // ControlMessage - Message for control channel (session management)
// Uses SessionCommand from session module // Uses SessionCommand from session module

View File

@ -90,7 +90,6 @@ struct LarkEvent {
#[derive(Deserialize)] #[derive(Deserialize)]
struct LarkEventHeader { struct LarkEventHeader {
event_type: String, event_type: String,
#[allow(dead_code)]
event_id: String, event_id: String,
} }
@ -122,19 +121,13 @@ struct LarkSenderId {
} }
#[derive(Deserialize)] #[derive(Deserialize)]
#[allow(dead_code)]
struct LarkMessage { struct LarkMessage {
message_id: String, message_id: String,
chat_id: String, chat_id: String,
chat_type: String,
message_type: String, message_type: String,
#[serde(default)] #[serde(default)]
content: String, content: String,
#[serde(default)] #[serde(default)]
mentions: Vec<serde_json::Value>,
#[serde(default)]
root_id: Option<String>,
#[serde(default)]
parent_id: Option<String>, parent_id: Option<String>,
} }

View File

@ -21,7 +21,7 @@ pub async fn run(gateway_url: &str) -> Result<(), Box<dyn std::error::Error>> {
let (ws_sender, ws_receiver) = ws_stream.split(); let (ws_sender, ws_receiver) = ws_stream.split();
let mut app = App::new(gateway_url.to_string()); let mut app = App::new();
app.ws_sender = Some(ws_sender); app.ws_sender = Some(ws_sender);
app.ws_receiver = Some(ws_receiver); app.ws_receiver = Some(ws_receiver);

View File

@ -1,16 +1,7 @@
#![allow(dead_code)]
use crate::protocol::{SessionSummary, SlashCommandInfo}; use crate::protocol::{SessionSummary, SlashCommandInfo};
use std::collections::VecDeque; use std::collections::VecDeque;
use tokio_tungstenite::tungstenite::Message; use tokio_tungstenite::tungstenite::Message;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FocusArea {
TitleBar,
SessionList,
ChatHistory,
InputArea,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum MessageRole { pub enum MessageRole {
User, User,
@ -25,7 +16,6 @@ pub struct ChatMessage {
} }
pub struct App { pub struct App {
pub gateway_url: String,
pub ws_sender: Option< pub ws_sender: Option<
futures_util::stream::SplitSink< futures_util::stream::SplitSink<
tokio_tungstenite::WebSocketStream< tokio_tungstenite::WebSocketStream<
@ -47,12 +37,10 @@ pub struct App {
pub messages: VecDeque<ChatMessage>, pub messages: VecDeque<ChatMessage>,
pub focus: FocusArea,
pub input: String, pub input: String,
pub input_cursor_pos: usize, pub input_cursor_pos: usize,
pub show_help: bool, pub show_help: bool,
pub chat_scroll_offset: u16, pub chat_scroll_offset: u16,
pub session_scroll_offset: u16,
pub should_quit: bool, pub should_quit: bool,
// Quit confirmation state (double Ctrl+C to exit) // Quit confirmation state (double Ctrl+C to exit)
@ -66,20 +54,17 @@ pub struct App {
} }
impl App { impl App {
pub fn new(gateway_url: String) -> Self { pub fn new() -> Self {
Self { Self {
gateway_url,
ws_sender: None, ws_sender: None,
ws_receiver: None, ws_receiver: None,
current_session_id: None, current_session_id: None,
sessions: Vec::new(), sessions: Vec::new(),
messages: VecDeque::new(), messages: VecDeque::new(),
focus: FocusArea::InputArea,
input: String::new(), input: String::new(),
input_cursor_pos: 0, input_cursor_pos: 0,
show_help: false, show_help: false,
chat_scroll_offset: 0, chat_scroll_offset: 0,
session_scroll_offset: 0,
should_quit: false, should_quit: false,
ctrl_c_count: 0, ctrl_c_count: 0,
pending_quit: false, pending_quit: false,
@ -111,14 +96,6 @@ impl App {
self.chat_scroll_offset = self.chat_scroll_offset.saturating_sub(1); self.chat_scroll_offset = self.chat_scroll_offset.saturating_sub(1);
} }
pub fn scroll_session_up(&mut self) {
self.session_scroll_offset = self.session_scroll_offset.saturating_add(1);
}
pub fn scroll_session_down(&mut self) {
self.session_scroll_offset = self.session_scroll_offset.saturating_sub(1);
}
pub fn input_insert_char(&mut self, c: char) { pub fn input_insert_char(&mut self, c: char) {
self.input.insert(self.input_cursor_pos, c); self.input.insert(self.input_cursor_pos, c);
self.input_cursor_pos += 1; self.input_cursor_pos += 1;
@ -149,11 +126,6 @@ impl App {
self.input_cursor_pos = self.input.len(); self.input_cursor_pos = self.input.len();
} }
pub fn input_clear(&mut self) {
self.input.clear();
self.input_cursor_pos = 0;
}
pub fn take_input(&mut self) -> String { pub fn take_input(&mut self) -> String {
let input = std::mem::take(&mut self.input); let input = std::mem::take(&mut self.input);
self.input_cursor_pos = 0; self.input_cursor_pos = 0;

View File

@ -1,5 +0,0 @@
#![allow(dead_code)]
pub fn render_markdown(content: &str) -> String {
content.to_string()
}

View File

@ -1,5 +1,4 @@
pub mod app; pub mod app;
pub mod components; pub mod components;
pub mod event; pub mod event;
pub mod markdown;
pub mod ui; pub mod ui;

View File

@ -59,20 +59,3 @@ pub fn init_logging() {
tracing::info!("Logging initialized. Log directory: {}", log_dir.display()); tracing::info!("Logging initialized. Log directory: {}", log_dir.display());
} }
/// Initialize logging without file output (console only)
pub fn init_logging_console_only() {
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
let console_layer = fmt::layer()
.with_timer(LocalTime::rfc_3339())
.with_target(true)
.with_level(true);
tracing_subscriber::registry()
.with(env_filter)
.with(console_layer)
.init();
tracing::info!("Logging initialized (console only)");
}

View File

@ -47,8 +47,6 @@ fn update_mcp_status(servers: Vec<McpServerStatus>) {
/// A connected MCP server. Holds a clonable Peer handle for tool calls, /// A connected MCP server. Holds a clonable Peer handle for tool calls,
/// and keeps the underlying service alive via a background task. /// and keeps the underlying service alive via a background task.
pub struct McpConnection { pub struct McpConnection {
#[allow(dead_code)]
pub name: String,
peer: Peer<RoleClient>, peer: Peer<RoleClient>,
/// Keep the service alive. When dropped, the MCP connection is closed. /// Keep the service alive. When dropped, the MCP connection is closed.
_service: Option<Box<dyn std::any::Any + Send + Sync>>, _service: Option<Box<dyn std::any::Any + Send + Sync>>,
@ -230,7 +228,6 @@ async fn connect_server(config: &McpServerConfig) -> anyhow::Result<McpConnectio
let peer = service.peer().clone(); let peer = service.peer().clone();
Ok(McpConnection { Ok(McpConnection {
name: config.name.clone(),
peer, peer,
_service: Some(Box::new(service)), _service: Some(Box::new(service)),
}) })
@ -268,7 +265,6 @@ async fn connect_server(config: &McpServerConfig) -> anyhow::Result<McpConnectio
let peer = service.peer().clone(); let peer = service.peer().clone();
Ok(McpConnection { Ok(McpConnection {
name: config.name.clone(),
peer, peer,
_service: Some(Box::new(service)), _service: Some(Box::new(service)),
}) })

View File

@ -70,16 +70,6 @@ impl ToolExecutionOutcome {
} }
} }
/// Create a successful outcome with duration.
pub fn success_with_duration(output: String, duration: Duration) -> Self {
Self {
output,
success: true,
error_reason: None,
duration,
}
}
/// Create a failed outcome with zero duration. /// Create a failed outcome with zero duration.
pub fn failure(output: String, error_reason: Option<String>) -> Self { pub fn failure(output: String, error_reason: Option<String>) -> Self {
Self { Self {
@ -89,20 +79,6 @@ impl ToolExecutionOutcome {
duration: Duration::ZERO, duration: Duration::ZERO,
} }
} }
/// Create a failed outcome with duration.
pub fn failure_with_duration(
output: String,
error_reason: Option<String>,
duration: Duration,
) -> Self {
Self {
output,
success: false,
error_reason,
duration,
}
}
} }
/// MultiObserver broadcasts events to multiple observers. /// MultiObserver broadcasts events to multiple observers.
@ -204,16 +180,6 @@ mod tests {
assert_eq!(outcome.duration, Duration::ZERO); assert_eq!(outcome.duration, Duration::ZERO);
} }
#[test]
fn test_tool_execution_outcome_success_with_duration() {
let outcome = ToolExecutionOutcome::success_with_duration(
"output content".to_string(),
Duration::from_millis(100),
);
assert!(outcome.success);
assert_eq!(outcome.duration, Duration::from_millis(100));
}
#[test] #[test]
fn test_tool_execution_outcome_failure() { fn test_tool_execution_outcome_failure() {
let outcome = ToolExecutionOutcome::failure( let outcome = ToolExecutionOutcome::failure(

View File

@ -167,7 +167,6 @@ enum AnthropicContent {
}, },
Thinking { Thinking {
#[serde(alias = "content")] #[serde(alias = "content")]
#[allow(dead_code)]
thinking: String, thinking: String,
}, },
#[serde(rename = "tool_use")] #[serde(rename = "tool_use")]

View File

@ -28,17 +28,6 @@ impl Message {
} }
} }
pub fn user_with_blocks(content: Vec<ContentBlock>) -> Self {
Self {
role: "user".to_string(),
content,
reasoning_content: None,
tool_call_id: None,
name: None,
tool_calls: None,
}
}
pub fn assistant(content: impl Into<String>) -> Self { pub fn assistant(content: impl Into<String>) -> Self {
Self { Self {
role: "assistant".to_string(), role: "assistant".to_string(),

View File

@ -82,7 +82,6 @@ pub struct Session {
/// Messages before this time have been compressed into memory. /// Messages before this time have been compressed into memory.
pub last_consolidated_at: Option<i64>, pub last_consolidated_at: Option<i64>,
pub last_compressed_message_at: Option<i64>, pub last_compressed_message_at: Option<i64>,
#[allow(dead_code)]
memory_manager: Arc<crate::memory::MemoryManager>, memory_manager: Arc<crate::memory::MemoryManager>,
/// Task queue for per-session serial agent processing /// Task queue for per-session serial agent processing
@ -2681,28 +2680,3 @@ fn format_task_notification(
crate::agent::TaskStatus::TimedOut => format!("📋 后台任务超时\n\n任务 ID: {}", task_id), crate::agent::TaskStatus::TimedOut => format!("📋 后台任务超时\n\n任务 ID: {}", task_id),
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
#[allow(dead_code)]
fn test_provider_config() -> LLMProviderConfig {
LLMProviderConfig {
provider_type: "openai".to_string(),
name: "test".to_string(),
base_url: "http://localhost".to_string(),
api_key: "test-key".to_string(),
extra_headers: HashMap::new(),
model_id: "test-model".to_string(),
temperature: Some(0.0),
max_tokens: Some(32),
model_extra: HashMap::new(),
max_tool_iterations: 1,
token_limit: 4096,
workspace_dir: std::path::PathBuf::from("/tmp/test-workspace"),
input_types: vec!["text".to_string()],
}
}
}

View File

@ -17,3 +17,13 @@ pub struct BackgroundTask {
pub finished_at: Option<i64>, pub finished_at: Option<i64>,
pub created_at: i64, pub created_at: i64,
} }
pub(crate) struct BackgroundTaskUpdate<'a> {
pub status: &'a str,
pub result: Option<&'a str>,
pub error: Option<&'a str>,
pub started_at: Option<i64>,
pub finished_at: Option<i64>,
pub tool_calls_count: Option<i64>,
pub iterations: Option<i64>,
}

View File

@ -1056,16 +1056,10 @@ impl Storage {
Ok(()) Ok(())
} }
pub async fn update_background_task_status( pub(crate) async fn update_background_task_status(
&self, &self,
id: &str, id: &str,
status: &str, update: crate::storage::background_task::BackgroundTaskUpdate<'_>,
result: Option<&str>,
error: Option<&str>,
started_at: Option<i64>,
finished_at: Option<i64>,
tool_calls_count: Option<i64>,
iterations: Option<i64>,
) -> Result<(), StorageError> { ) -> Result<(), StorageError> {
sqlx::query( sqlx::query(
r#" r#"
@ -1077,13 +1071,13 @@ impl Storage {
WHERE id = ? WHERE id = ?
"#, "#,
) )
.bind(status) .bind(update.status)
.bind(result) .bind(update.result)
.bind(error) .bind(update.error)
.bind(started_at) .bind(update.started_at)
.bind(finished_at) .bind(update.finished_at)
.bind(tool_calls_count) .bind(update.tool_calls_count)
.bind(iterations) .bind(update.iterations)
.bind(id) .bind(id)
.execute(self.pool()) .execute(self.pool())
.await?; .await?;
@ -1270,13 +1264,15 @@ mod tests {
storage storage
.update_background_task_status( .update_background_task_status(
&task.id, &task.id,
"completed", crate::storage::background_task::BackgroundTaskUpdate {
Some("done"), status: "completed",
None, result: Some("done"),
Some(2), error: None,
Some(3), started_at: Some(2),
Some(4), finished_at: Some(3),
Some(5), tool_calls_count: Some(4),
iterations: Some(5),
},
) )
.await .await
.unwrap(); .unwrap();

View File

@ -96,11 +96,7 @@ enum SessionStatus {
} }
struct PtySession { struct PtySession {
#[allow(dead_code)]
id: String,
#[allow(dead_code)]
command: String, command: String,
#[allow(dead_code)]
started_at: Instant, started_at: Instant,
status: SessionStatus, status: SessionStatus,
child: Arc<Mutex<Option<Box<dyn portable_pty::Child + Send + Sync>>>>, child: Arc<Mutex<Option<Box<dyn portable_pty::Child + Send + Sync>>>>,
@ -111,13 +107,11 @@ struct PtySession {
impl PtySession { impl PtySession {
fn new( fn new(
id: String,
command: String, command: String,
child: Box<dyn portable_pty::Child + Send + Sync>, child: Box<dyn portable_pty::Child + Send + Sync>,
writer: Box<dyn Write + Send>, writer: Box<dyn Write + Send>,
) -> Self { ) -> Self {
Self { Self {
id,
command, command,
started_at: Instant::now(), started_at: Instant::now(),
status: SessionStatus::Running, status: SessionStatus::Running,
@ -225,8 +219,7 @@ impl PtyManager {
.try_clone_reader() .try_clone_reader()
.map_err(|e| format!("Failed to clone reader: {}", e))?; .map_err(|e| format!("Failed to clone reader: {}", e))?;
let session_id_clone = session_id.clone(); let session = PtySession::new(command.to_string(), child, writer);
let session = PtySession::new(session_id_clone, command.to_string(), child, writer);
let session = Arc::new(Mutex::new(session)); let session = Arc::new(Mutex::new(session));
sessions.insert(session_id.clone(), session.clone()); sessions.insert(session_id.clone(), session.clone());