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

View File

@ -391,16 +391,15 @@ impl SubAgentManager {
// Update DB: running
if let Some(ref s) = storage {
let _ = s
.update_background_task_status(
&tid,
"running",
None,
None,
Some(started_at),
None,
None,
None,
)
.update_background_task_status(&tid, crate::storage::background_task::BackgroundTaskUpdate {
status: "running",
result: None,
error: None,
started_at: Some(started_at),
finished_at: None,
tool_calls_count: None,
iterations: None,
})
.await;
}
@ -513,16 +512,15 @@ impl SubAgentManager {
if let Some(ref s) = storage {
let _ = s
.update_background_task_status(
&tid,
&status_str,
Some(&result.content),
error_val.as_deref(),
Some(started_at),
Some(finished_at),
Some(result.tool_calls_count as i64),
Some(result.iterations as i64),
)
.update_background_task_status(&tid, crate::storage::background_task::BackgroundTaskUpdate {
status: &status_str,
result: Some(&result.content),
error: error_val.as_deref(),
started_at: Some(started_at),
finished_at: Some(finished_at),
tool_calls_count: Some(result.tool_calls_count as i64),
iterations: Some(result.iterations as i64),
})
.await;
}
@ -544,13 +542,15 @@ impl SubAgentManager {
let _ = storage
.update_background_task_status(
&task_id,
"cancelled",
None,
Some("gateway shutdown"),
None,
Some(chrono::Utc::now().timestamp_millis()),
None,
None,
crate::storage::background_task::BackgroundTaskUpdate {
status: "cancelled",
result: None,
error: Some("gateway shutdown"),
started_at: None,
finished_at: Some(chrono::Utc::now().timestamp_millis()),
tool_calls_count: None,
iterations: None,
},
)
.await;
}
@ -568,13 +568,15 @@ impl SubAgentManager {
if let Some(ref s) = self.storage {
s.update_background_task_status(
task_id,
"cancelled",
None,
None,
None,
Some(chrono::Utc::now().timestamp_millis()),
None,
None,
crate::storage::background_task::BackgroundTaskUpdate {
status: "cancelled",
result: None,
error: None,
started_at: None,
finished_at: Some(chrono::Utc::now().timestamp_millis()),
tool_calls_count: None,
iterations: None,
},
)
.await
.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)]
mod tests {
use super::*;
@ -723,13 +735,3 @@ mod tests {
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>,
}
impl InboundMessage {
pub fn session_key(&self) -> String {
format!("{}:{}", self.channel, self.chat_id)
}
}
// ============================================================================
// OutboundMessage - Message from Agent to Channel (bot response)
// ============================================================================
@ -284,12 +278,6 @@ pub struct OutboundMessage {
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)
// Uses SessionCommand from session module

View File

@ -90,7 +90,6 @@ struct LarkEvent {
#[derive(Deserialize)]
struct LarkEventHeader {
event_type: String,
#[allow(dead_code)]
event_id: String,
}
@ -122,19 +121,13 @@ struct LarkSenderId {
}
#[derive(Deserialize)]
#[allow(dead_code)]
struct LarkMessage {
message_id: String,
chat_id: String,
chat_type: String,
message_type: String,
#[serde(default)]
content: String,
#[serde(default)]
mentions: Vec<serde_json::Value>,
#[serde(default)]
root_id: Option<String>,
#[serde(default)]
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 mut app = App::new(gateway_url.to_string());
let mut app = App::new();
app.ws_sender = Some(ws_sender);
app.ws_receiver = Some(ws_receiver);

View File

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

View File

@ -59,20 +59,3 @@ pub fn init_logging() {
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,
/// and keeps the underlying service alive via a background task.
pub struct McpConnection {
#[allow(dead_code)]
pub name: String,
peer: Peer<RoleClient>,
/// Keep the service alive. When dropped, the MCP connection is closed.
_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();
Ok(McpConnection {
name: config.name.clone(),
peer,
_service: Some(Box::new(service)),
})
@ -268,7 +265,6 @@ async fn connect_server(config: &McpServerConfig) -> anyhow::Result<McpConnectio
let peer = service.peer().clone();
Ok(McpConnection {
name: config.name.clone(),
peer,
_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.
pub fn failure(output: String, error_reason: Option<String>) -> Self {
Self {
@ -89,20 +79,6 @@ impl ToolExecutionOutcome {
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.
@ -204,16 +180,6 @@ mod tests {
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]
fn test_tool_execution_outcome_failure() {
let outcome = ToolExecutionOutcome::failure(

View File

@ -167,7 +167,6 @@ enum AnthropicContent {
},
Thinking {
#[serde(alias = "content")]
#[allow(dead_code)]
thinking: String,
},
#[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 {
Self {
role: "assistant".to_string(),

View File

@ -82,7 +82,6 @@ pub struct Session {
/// Messages before this time have been compressed into memory.
pub last_consolidated_at: Option<i64>,
pub last_compressed_message_at: Option<i64>,
#[allow(dead_code)]
memory_manager: Arc<crate::memory::MemoryManager>,
/// 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),
}
}
#[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 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(())
}
pub async fn update_background_task_status(
pub(crate) async fn update_background_task_status(
&self,
id: &str,
status: &str,
result: Option<&str>,
error: Option<&str>,
started_at: Option<i64>,
finished_at: Option<i64>,
tool_calls_count: Option<i64>,
iterations: Option<i64>,
update: crate::storage::background_task::BackgroundTaskUpdate<'_>,
) -> Result<(), StorageError> {
sqlx::query(
r#"
@ -1077,13 +1071,13 @@ impl Storage {
WHERE id = ?
"#,
)
.bind(status)
.bind(result)
.bind(error)
.bind(started_at)
.bind(finished_at)
.bind(tool_calls_count)
.bind(iterations)
.bind(update.status)
.bind(update.result)
.bind(update.error)
.bind(update.started_at)
.bind(update.finished_at)
.bind(update.tool_calls_count)
.bind(update.iterations)
.bind(id)
.execute(self.pool())
.await?;
@ -1270,13 +1264,15 @@ mod tests {
storage
.update_background_task_status(
&task.id,
"completed",
Some("done"),
None,
Some(2),
Some(3),
Some(4),
Some(5),
crate::storage::background_task::BackgroundTaskUpdate {
status: "completed",
result: Some("done"),
error: None,
started_at: Some(2),
finished_at: Some(3),
tool_calls_count: Some(4),
iterations: Some(5),
},
)
.await
.unwrap();

View File

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