From 063d5d7d99b234fffbdbe2f9b3106cb338d07020 Mon Sep 17 00:00:00 2001 From: Hunter Bown Date: Thu, 7 May 2026 03:37:50 -0500 Subject: [PATCH] fix: prevent panic-prone edge cases Summary: - Use Reverse for job timestamp sorting to avoid negation overflow edge cases. - Make secret redaction UTF-8 safe while preserving the previous short-secret threshold. - Update remaining setup and doctor guidance to use the supported deepseek dispatcher name. Test plan: - cargo test -p deepseek-config list_values_redacts --locked - cargo test -p deepseek-core --locked - cargo test -p deepseek-tui doctor_endpoint_tests --locked - cargo fmt --all -- --check - git diff --check Supersedes #957. --- crates/config/src/lib.rs | 29 +++++++++++++++++++++++++++-- crates/core/src/lib.rs | 4 ++-- crates/tui/src/main.rs | 8 ++++---- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index b0bb82e9..2f3d7f3b 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -1247,10 +1247,20 @@ fn serialize_http_headers(headers: &BTreeMap) -> Option } fn redact_secret(secret: &str) -> String { - if secret.len() <= 16 { + let chars: Vec = secret.chars().collect(); + if chars.len() <= 16 { return "********".to_string(); } - format!("{}***{}", &secret[..4], &secret[secret.len() - 4..]) + let prefix: String = chars.iter().take(4).collect(); + let suffix: String = chars + .iter() + .rev() + .take(4) + .collect::>() + .into_iter() + .rev() + .collect(); + format!("{prefix}***{suffix}") } #[derive(Debug, Clone, Default)] @@ -1729,6 +1739,21 @@ mod tests { assert_eq!(values.get("api_key").map(String::as_str), Some("********")); } + #[test] + fn list_values_redacts_unicode_api_key_without_byte_slicing() { + let config = ConfigToml { + api_key: Some("密钥密钥密钥密钥123456789".to_string()), + ..ConfigToml::default() + }; + + let values = config.list_values(); + + assert_eq!( + values.get("api_key").map(String::as_str), + Some("密钥密钥***6789") + ); + } + #[cfg(unix)] #[test] fn save_clamps_existing_config_permissions() { diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index e9469815..cf32433f 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -292,7 +292,7 @@ impl JobManager { pub fn list(&self) -> Vec { let mut out = self.jobs.values().cloned().collect::>(); - out.sort_by_key(|job| -job.updated_at); + out.sort_by_key(|job| std::cmp::Reverse(job.updated_at)); out } @@ -319,7 +319,7 @@ impl JobManager { pub fn load_from_store(&mut self, store: &StateStore) -> Result<()> { let persisted = store.list_jobs(Some(500))?; for job in persisted { - let fallback_status = job_state_status_to_runtime(job.status.clone()); + let fallback_status = job_state_status_to_runtime(job.status); let parsed = Self::parse_persisted_detail(job.detail.as_deref()); let (status, detail, retry, history) = if let Some(detail_state) = parsed { ( diff --git a/crates/tui/src/main.rs b/crates/tui/src/main.rs index c6e4eb26..286f6410 100644 --- a/crates/tui/src/main.rs +++ b/crates/tui/src/main.rs @@ -1451,7 +1451,7 @@ fn run_setup_status(config: &Config, workspace: &Path) -> Result<()> { println!(" {} {}", "·".dimmed(), dotenv_status_line(workspace)); println!(); - println!("Run `deepseek-tui doctor --json` for a machine-readable check."); + println!("Run `deepseek doctor --json` for a machine-readable check."); Ok(()) } @@ -1979,7 +1979,7 @@ async fn run_doctor(config: &Config, workspace: &Path, config_path_override: Opt "·".dimmed(), crate::utils::display_path(&tools_dir) ); - println!(" Run `deepseek-tui setup --tools` to scaffold a starter dir."); + println!(" Run `deepseek setup --tools` to scaffold a starter dir."); } // Plugins directory @@ -2000,7 +2000,7 @@ async fn run_doctor(config: &Config, workspace: &Path, config_path_override: Opt "·".dimmed(), crate::utils::display_path(&plugins_dir) ); - println!(" Run `deepseek-tui setup --plugins` to scaffold a starter dir."); + println!(" Run `deepseek setup --plugins` to scaffold a starter dir."); } // Storage surfaces (#422 / #440 / #500) @@ -2291,7 +2291,7 @@ fn run_doctor_json( }, "api_connectivity": { "checked": false, - "note": "Skipped in --json mode; run `deepseek-tui doctor` for a live check.", + "note": "Skipped in --json mode; run `deepseek doctor` for a live check.", }, "capability": provider_capability_report(config), });