From 3364dc4beefbd8660f11119af2a6498e569523a4 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Mon, 25 May 2026 11:51:44 +0900 Subject: [PATCH] chore: fix conflict markers and cargo fmt drift in main (commands, openai_compat, trident, config, tools) --- .../crates/api/src/providers/openai_compat.rs | 19 ++- rust/crates/commands/src/lib.rs | 4 - rust/crates/runtime/src/compact.rs | 11 +- rust/crates/runtime/src/config.rs | 20 ++- rust/crates/runtime/src/lib.rs | 2 +- rust/crates/runtime/src/trident.rs | 139 ++++++++++++------ rust/crates/rusty-claude-cli/src/main.rs | 102 +++++++++---- rust/crates/tools/src/lib.rs | 18 ++- 8 files changed, 225 insertions(+), 90 deletions(-) diff --git a/rust/crates/api/src/providers/openai_compat.rs b/rust/crates/api/src/providers/openai_compat.rs index 9f08edf0..de2660e6 100644 --- a/rust/crates/api/src/providers/openai_compat.rs +++ b/rust/crates/api/src/providers/openai_compat.rs @@ -510,7 +510,11 @@ impl StreamState { .delta .reasoning_content .filter(|value| !value.is_empty()) - .or(choice.delta.thinking.and_then(|t| t.content).filter(|value| !value.is_empty())) + .or(choice + .delta + .thinking + .and_then(|t| t.content) + .filter(|value| !value.is_empty())) { if !self.thinking_started { self.thinking_started = true; @@ -942,7 +946,10 @@ fn wire_model_for_base_url<'a>( if lowered_prefix == "openai" { let trimmed_base_url = base_url.trim_end_matches('/'); let default_openai = DEFAULT_OPENAI_BASE_URL.trim_end_matches('/'); - if matches!(lowered_prefix.as_str(), "xai" | "grok" | "kimi" | "gemini" | "gemma") { + if matches!( + lowered_prefix.as_str(), + "xai" | "grok" | "kimi" | "gemini" | "gemma" + ) { return Cow::Borrowed(&model[pos + 1..]); } if config.provider_name == "OpenAI" && trimmed_base_url != default_openai { @@ -1505,7 +1512,9 @@ fn parse_sse_frame( return Err(ApiError::Api { status: reqwest::StatusCode::BAD_REQUEST, error_type: Some("invalid_response".to_string()), - message: Some("provider returned HTML instead of JSON (check endpoint URL)".to_string()), + message: Some( + "provider returned HTML instead of JSON (check endpoint URL)".to_string(), + ), request_id: None, body: trimmed.chars().take(200).collect(), retryable: false, @@ -1555,7 +1564,9 @@ fn parse_sse_frame( return Err(ApiError::Api { status: reqwest::StatusCode::BAD_REQUEST, error_type: Some("invalid_response".to_string()), - message: Some("provider returned HTML instead of JSON (check endpoint URL)".to_string()), + message: Some( + "provider returned HTML instead of JSON (check endpoint URL)".to_string(), + ), request_id: None, body: payload.chars().take(200).collect(), retryable: false, diff --git a/rust/crates/commands/src/lib.rs b/rust/crates/commands/src/lib.rs index 2f4f3462..7c49ce13 100644 --- a/rust/crates/commands/src/lib.rs +++ b/rust/crates/commands/src/lib.rs @@ -1477,10 +1477,6 @@ pub fn validate_slash_command_input( "theme" => SlashCommand::Theme { name: remainder }, "voice" => SlashCommand::Voice { mode: remainder }, "usage" => SlashCommand::Usage { scope: remainder }, -<<<<<<< HEAD -======= - "setup" => SlashCommand::Setup, ->>>>>>> 2f6a225 (fix: make id field optional in OpenAI response parsing) "rename" => SlashCommand::Rename { name: remainder }, "copy" => SlashCommand::Copy { target: remainder }, "hooks" => SlashCommand::Hooks { args: remainder }, diff --git a/rust/crates/runtime/src/compact.rs b/rust/crates/runtime/src/compact.rs index e19058c3..5b3076f1 100644 --- a/rust/crates/runtime/src/compact.rs +++ b/rust/crates/runtime/src/compact.rs @@ -115,7 +115,10 @@ pub fn compact_session(session: &Session, config: CompactionConfig) -> Compactio let raw_keep_from = if config.preserve_recent_messages == 0 { session.messages.len() } else { - session.messages.len().saturating_sub(config.preserve_recent_messages) + session + .messages + .len() + .saturating_sub(config.preserve_recent_messages) }; // Ensure we do not split a tool-use / tool-result pair at the compaction // boundary. If the first preserved message is a user message whose first @@ -300,7 +303,11 @@ fn merge_compact_summaries(existing_summary: Option<&str>, new_summary: &str) -> // "- Previously compacted context:" or the nesting compounds with each // compaction cycle, inflating the summary by ~depth * overhead per turn. if !previous_highlights.is_empty() { - lines.extend(previous_highlights.into_iter().map(|line| format!("- {line}"))); + lines.extend( + previous_highlights + .into_iter() + .map(|line| format!("- {line}")), + ); } if !new_highlights.is_empty() { diff --git a/rust/crates/runtime/src/config.rs b/rust/crates/runtime/src/config.rs index a979e24c..4eccdabc 100644 --- a/rust/crates/runtime/src/config.rs +++ b/rust/crates/runtime/src/config.rs @@ -608,16 +608,28 @@ pub fn save_user_provider_settings( let mut root = read_settings_root(&settings_path); let mut provider = serde_json::Map::new(); - provider.insert("kind".to_string(), serde_json::Value::String(kind.to_string())); - provider.insert("apiKey".to_string(), serde_json::Value::String(api_key.to_string())); + provider.insert( + "kind".to_string(), + serde_json::Value::String(kind.to_string()), + ); + provider.insert( + "apiKey".to_string(), + serde_json::Value::String(api_key.to_string()), + ); if let Some(base_url) = base_url { - provider.insert("baseUrl".to_string(), serde_json::Value::String(base_url.to_string())); + provider.insert( + "baseUrl".to_string(), + serde_json::Value::String(base_url.to_string()), + ); } else { provider.remove("baseUrl"); } root.insert("provider".to_string(), serde_json::Value::Object(provider)); if let Some(model) = model { - root.insert("model".to_string(), serde_json::Value::String(model.to_string())); + root.insert( + "model".to_string(), + serde_json::Value::String(model.to_string()), + ); } else { root.remove("model"); } diff --git a/rust/crates/runtime/src/lib.rs b/rust/crates/runtime/src/lib.rs index 81eb0aba..35d8bf02 100644 --- a/rust/crates/runtime/src/lib.rs +++ b/rust/crates/runtime/src/lib.rs @@ -10,7 +10,6 @@ pub mod bash_validation; mod bootstrap; pub mod branch_lock; mod compact; -pub mod trident; mod config; pub mod config_validate; mod conversation; @@ -40,6 +39,7 @@ mod report_schema; pub mod sandbox; mod session; pub mod session_control; +pub mod trident; pub use session_control::SessionStore; mod sse; pub mod stale_base; diff --git a/rust/crates/runtime/src/trident.rs b/rust/crates/runtime/src/trident.rs index b455761e..de981219 100644 --- a/rust/crates/runtime/src/trident.rs +++ b/rust/crates/runtime/src/trident.rs @@ -78,7 +78,10 @@ impl TridentStats { self.messages_clustered, self.clusters_found ), format!(" Original: {} messages", self.original_message_count), - format!(" Final: {} messages ({:.1}x compression)", self.final_message_count, compression), + format!( + " Final: {} messages ({:.1}x compression)", + self.final_message_count, compression + ), ]; if self.tokens_saved_estimate > 0 { lines.push(format!( @@ -121,7 +124,8 @@ pub fn trident_compact_session( } if trident_config.collapse_enabled { - let (collapsed, chains, collapsed_count) = stage2_collapse(&messages, trident_config.collapse_threshold); + let (collapsed, chains, collapsed_count) = + stage2_collapse(&messages, trident_config.collapse_threshold); stats.collapsed_chains = chains; stats.messages_collapsed = collapsed_count; messages = collapsed; @@ -178,10 +182,10 @@ fn stage1_supersede(messages: &[ConversationMessage]) -> (Vec Option<(String, FileOp)> { }; Some((path, op_type)) } - ContentBlock::ToolResult { tool_name, output, .. } => { + ContentBlock::ToolResult { + tool_name, output, .. + } => { let path = extract_path_from_tool_output(tool_name, output)?; let op_type = match tool_name.as_str() { "read_file" | "Read" => FileOp::Read, @@ -250,8 +256,10 @@ fn extract_file_operation(block: &ContentBlock) -> Option<(String, FileOp)> { } fn extract_path_from_tool_input(tool_name: &str, input: &str) -> Option { - if !matches!(tool_name, "read_file" | "write_file" | "edit_file" | "Read" | "Write" | "Edit") - { + if !matches!( + tool_name, + "read_file" | "write_file" | "edit_file" | "Read" | "Write" | "Edit" + ) { return None; } serde_json::from_str::(input) @@ -265,8 +273,10 @@ fn extract_path_from_tool_input(tool_name: &str, input: &str) -> Option } fn extract_path_from_tool_output(tool_name: &str, output: &str) -> Option { - if !matches!(tool_name, "read_file" | "write_file" | "edit_file" | "Read" | "Write" | "Edit") - { + if !matches!( + tool_name, + "read_file" | "write_file" | "edit_file" | "Read" | "Write" | "Edit" + ) { return None; } serde_json::from_str::(output) @@ -340,14 +350,24 @@ fn stage2_collapse( } fn is_chatty_message(msg: &ConversationMessage) -> bool { - let total_chars: usize = msg.blocks.iter().map(|b| match b { - ContentBlock::Text { text } => text.len(), - ContentBlock::ToolUse { input, .. } => input.len(), - ContentBlock::ToolResult { output, .. } => output.len(), - }).sum(); + let total_chars: usize = msg + .blocks + .iter() + .map(|b| match b { + ContentBlock::Text { text } => text.len(), + ContentBlock::ToolUse { input, .. } => input.len(), + ContentBlock::ToolResult { output, .. } => output.len(), + }) + .sum(); - let has_tool_use = msg.blocks.iter().any(|b| matches!(b, ContentBlock::ToolUse { .. })); - let has_tool_result = msg.blocks.iter().any(|b| matches!(b, ContentBlock::ToolResult { .. })); + let has_tool_use = msg + .blocks + .iter() + .any(|b| matches!(b, ContentBlock::ToolUse { .. })); + let has_tool_result = msg + .blocks + .iter() + .any(|b| matches!(b, ContentBlock::ToolResult { .. })); if has_tool_use || has_tool_result { return false; @@ -463,16 +483,12 @@ fn stage3_cluster( cluster_buffers.entry(cid).or_default().push(*msg_idx); } - - for (i, msg) in messages.iter().enumerate() { if let Some(&cid) = cluster_assignments.get(&i) { if let Some(buffer) = cluster_buffers.get_mut(&cid) { if buffer[0] == i { - let cluster_messages: Vec<&ConversationMessage> = buffer - .iter() - .filter_map(|&idx| messages.get(idx)) - .collect(); + let cluster_messages: Vec<&ConversationMessage> = + buffer.iter().filter_map(|&idx| messages.get(idx)).collect(); let summary = generate_cluster_summary(&cluster_messages); result.push(ConversationMessage { role: MessageRole::System, @@ -518,7 +534,9 @@ fn fingerprint_message(index: usize, msg: &ConversationMessage) -> Option { + ContentBlock::ToolResult { + tool_name, output, .. + } => { tool_names.insert(tool_name.clone()); if let Some(path) = extract_path_from_tool_output(tool_name, output) { file_paths.insert(path); @@ -591,7 +609,9 @@ fn generate_cluster_summary(messages: &[&ConversationMessage]) -> String { file_paths.insert(path); } } - ContentBlock::ToolResult { tool_name, output, .. } => { + ContentBlock::ToolResult { + tool_name, output, .. + } => { tool_names.insert(tool_name.clone()); if let Some(path) = extract_path_from_tool_output(tool_name, output) { file_paths.insert(path); @@ -660,13 +680,23 @@ mod tests { name: "read_file".to_string(), input: r#"{"path":"src/main.rs"}"#.to_string(), }]), - ConversationMessage::tool_result("1", "read_file", r#"{"path":"src/main.rs","content":"old"}"#, false), + ConversationMessage::tool_result( + "1", + "read_file", + r#"{"path":"src/main.rs","content":"old"}"#, + false, + ), ConversationMessage::assistant(vec![ContentBlock::ToolUse { id: "2".to_string(), name: "edit_file".to_string(), input: r#"{"path":"src/main.rs","old":"old","new":"new"}"#.to_string(), }]), - ConversationMessage::tool_result("2", "edit_file", r#"{"path":"src/main.rs","ok":true}"#, false), + ConversationMessage::tool_result( + "2", + "edit_file", + r#"{"path":"src/main.rs","ok":true}"#, + false, + ), ]; let (kept, superseded) = stage1_supersede(&messages); @@ -682,7 +712,12 @@ mod tests { name: "read_file".to_string(), input: r#"{"path":"src/main.rs"}"#.to_string(), }]), - ConversationMessage::tool_result("1", "read_file", r#"{"path":"src/main.rs","content":"data"}"#, false), + ConversationMessage::tool_result( + "1", + "read_file", + r#"{"path":"src/main.rs","content":"data"}"#, + false, + ), ]; let (kept, superseded) = stage1_supersede(&messages); @@ -699,11 +734,13 @@ mod tests { text: format!("got {i}"), }])); } - messages.push(ConversationMessage::assistant(vec![ContentBlock::ToolUse { - id: "t".to_string(), - name: "bash".to_string(), - input: r#"{"command":"ls"}"#.to_string(), - }])); + messages.push(ConversationMessage::assistant(vec![ + ContentBlock::ToolUse { + id: "t".to_string(), + name: "bash".to_string(), + input: r#"{"command":"ls"}"#.to_string(), + }, + ])); let (result, chains, collapsed) = stage2_collapse(&messages, 4); assert!(chains > 0, "should collapse at least one chain"); @@ -715,11 +752,13 @@ mod tests { fn stage3_clusters_similar_messages() { let mut messages = vec![]; for i in 0..5 { - messages.push(ConversationMessage::assistant(vec![ContentBlock::ToolUse { - id: format!("read_{i}"), - name: "read_file".to_string(), - input: format!(r#"{{"path":"src/{i}.rs"}}"#), - }])); + messages.push(ConversationMessage::assistant(vec![ + ContentBlock::ToolUse { + id: format!("read_{i}"), + name: "read_file".to_string(), + input: format!(r#"{{"path":"src/{i}.rs"}}"#), + }, + ])); messages.push(ConversationMessage::tool_result( &format!("read_{i}"), "read_file", @@ -728,8 +767,7 @@ mod tests { )); } - let (result, clusters, clustered) = - stage3_cluster(&messages, 3, 0.4); + let (result, clusters, clustered) = stage3_cluster(&messages, 3, 0.4); assert!(clusters > 0, "should find at least one cluster"); assert!(clustered > 0); assert!(result.len() < messages.len()); @@ -745,13 +783,23 @@ mod tests { name: "read_file".to_string(), input: r#"{"path":"src/main.rs"}"#.to_string(), }]), - ConversationMessage::tool_result("1", "read_file", r#"{"path":"src/main.rs","content":"fn main() { buggy }"}"#, false), + ConversationMessage::tool_result( + "1", + "read_file", + r#"{"path":"src/main.rs","content":"fn main() { buggy }"}"#, + false, + ), ConversationMessage::assistant(vec![ContentBlock::ToolUse { id: "2".to_string(), name: "edit_file".to_string(), input: r#"{"path":"src/main.rs","old":"buggy","new":"fixed"}"#.to_string(), }]), - ConversationMessage::tool_result("2", "edit_file", r#"{"path":"src/main.rs","ok":true}"#, false), + ConversationMessage::tool_result( + "2", + "edit_file", + r#"{"path":"src/main.rs","ok":true}"#, + false, + ), ConversationMessage::assistant(vec![ContentBlock::Text { text: "Fixed the bug in main.rs".to_string(), }]), @@ -767,7 +815,10 @@ mod tests { &trident_config, ); - assert!(result.removed_message_count > 0 || result.compacted_session.messages.len() < session.messages.len()); + assert!( + result.removed_message_count > 0 + || result.compacted_session.messages.len() < session.messages.len() + ); } #[test] diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index 46c139ad..43892f0b 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -2201,8 +2201,16 @@ fn check_auth_health() -> DiagnosticCheck { let env_details = format!( "Environment api_key={} auth_token={} openai_key={}", if api_key_present { "present" } else { "absent" }, - if auth_token_present { "present" } else { "absent" }, - if openai_key_present { "present" } else { "absent" } + if auth_token_present { + "present" + } else { + "absent" + }, + if openai_key_present { + "present" + } else { + "absent" + } ); match load_oauth_credentials() { @@ -5047,7 +5055,7 @@ impl LiveCli { TerminalRenderer::new().color_theme(), &mut stdout, )?; - + // ============================================================================ // Auto-compact retry on context window errors // ============================================================================ @@ -5066,7 +5074,7 @@ impl LiveCli { // - "Context window blocked" // - "This model's maximum context length is X tokens..." // ============================================================================ - + let error_str = error.to_string(); // Detect context window overflow. Some providers (e.g. OpenAI-compat backends) // return 400 with "no parseable body" instead of a proper context_length_exceeded @@ -5074,7 +5082,7 @@ impl LiveCli { let is_context_window = error_str.contains("context_window") || error_str.contains("Context window") || error_str.contains("no parseable body"); - + if is_context_window { // A single compaction pass may not free enough context space. // Progressive retry: each round preserves fewer recent messages (4→2→1→0), @@ -5082,7 +5090,7 @@ impl LiveCli { // Max 4 rounds before giving up and surfacing the error to the user. let max_compact_rounds = 4; let preserve_schedule = [4, 2, 1, 0]; - + for round in 0..max_compact_rounds { let preserve = preserve_schedule[round]; println!( @@ -5091,7 +5099,7 @@ impl LiveCli { max_compact_rounds, preserve ); - + // Run Trident pipeline then summary-based compaction let result = runtime::trident::trident_compact_session( runtime.session(), @@ -5102,38 +5110,53 @@ impl LiveCli { &runtime::trident::TridentConfig::default(), ); let removed = result.removed_message_count; - + if removed == 0 && round > 0 { // No more messages to compact — further rounds won't help println!(" No further compaction possible."); break; } - + if removed > 0 { - println!("{}", format_compact_report(removed, result.compacted_session.messages.len(), false)); + println!( + "{}", + format_compact_report( + removed, + result.compacted_session.messages.len(), + false + ) + ); } - + // Without this, prepare_turn_runtime() reads from self.runtime.session() // which still holds the ORIGINAL un-compacted session, so every retry round // would send the same bloated request — compaction was wasted. *self.runtime.session_mut() = result.compacted_session.clone(); - + // Build a new runtime with the compacted session and retry - let (mut new_runtime, hook_abort_monitor) = self.prepare_turn_runtime(true)?; + let (mut new_runtime, hook_abort_monitor) = + self.prepare_turn_runtime(true)?; drop(hook_abort_monitor); - + let mut rp = CliPermissionPrompter::new(self.permission_mode); match new_runtime.run_turn(input, Some(&mut rp)) { Ok(summary) => { self.replace_runtime(new_runtime)?; spinner.finish( - if round == 0 { "✨ Done (after auto-compact)" } else { "✨ Done (after aggressive auto-compact)" }, + if round == 0 { + "✨ Done (after auto-compact)" + } else { + "✨ Done (after aggressive auto-compact)" + }, TerminalRenderer::new().color_theme(), &mut stdout, )?; println!(); if let Some(event) = summary.auto_compaction { - println!("{}", format_auto_compaction_notice(event.removed_message_count)); + println!( + "{}", + format_auto_compaction_notice(event.removed_message_count) + ); } self.persist_session()?; return Ok(()); @@ -5143,7 +5166,7 @@ impl LiveCli { let still_context_window = retry_str.contains("context_window") || retry_str.contains("Context window") || retry_str.contains("no parseable body"); - + if still_context_window && round + 1 < max_compact_rounds { // The compacted session was still too large for the model's context. // Shut down the old runtime, adopt the partially-compacted one, @@ -5152,14 +5175,14 @@ impl LiveCli { runtime = new_runtime; continue; } - + // Not a context window error, or out of rounds return Err(Box::new(retry_error)); } } } } - + // If not a context window error, return original error Err(Box::new(error)) } @@ -8942,7 +8965,11 @@ impl AnthropicRuntimeClient { } ApiStreamEvent::ContentBlockStart(start) => { // 特判 Thinking 块:初始化 pending_thinking(用于累积后续 ThinkingDelta) - if let OutputContentBlock::Thinking { thinking, signature } = &start.content_block { + if let OutputContentBlock::Thinking { + thinking, + signature, + } = &start.content_block + { pending_thinking = Some((thinking.clone(), signature.clone())); } push_output_block( @@ -8999,7 +9026,10 @@ impl AnthropicRuntimeClient { } // 把累积的 thinking 转成 AssistantEvent::Thinking(让 build_assistant_message 写入 session) if let Some((thinking, signature)) = pending_thinking.take() { - events.push(AssistantEvent::Thinking { thinking, signature }); + events.push(AssistantEvent::Thinking { + thinking, + signature, + }); } if let Some((id, name, input)) = pending_tool.take() { if let Some(progress_reporter) = &self.progress_reporter { @@ -10137,7 +10167,10 @@ fn convert_messages(messages: &[ConversationMessage]) -> Vec { ContentBlock::Text { text } => { Some(InputContentBlock::Text { text: text.clone() }) } - ContentBlock::Thinking { thinking, signature } => { + ContentBlock::Thinking { + thinking, + signature, + } => { // 保留 Thinking 块:OpenAI 兼容协议会把它转成 reasoning_content 字段 // 回传给 DeepSeek V4(避免 400 "reasoning_content must be passed back" 错误) Some(InputContentBlock::Thinking { @@ -11024,7 +11057,10 @@ mod tests { fn resolves_known_model_aliases() { assert_eq!(resolve_model_alias("opus"), "anthropic/claude-opus-4-6"); assert_eq!(resolve_model_alias("sonnet"), "anthropic/claude-sonnet-4-6"); - assert_eq!(resolve_model_alias("haiku"), "anthropic/claude-haiku-4-5-20251213"); + assert_eq!( + resolve_model_alias("haiku"), + "anthropic/claude-haiku-4-5-20251213" + ); assert_eq!(resolve_model_alias("claude-opus"), "claude-opus"); } @@ -11498,7 +11534,10 @@ mod tests { model_flag_raw, .. } => { - assert_eq!(model, "anthropic/claude-sonnet-4-6", "sonnet alias should resolve"); + assert_eq!( + model, "anthropic/claude-sonnet-4-6", + "sonnet alias should resolve" + ); assert_eq!( model_flag_raw.as_deref(), Some("sonnet"), @@ -15220,9 +15259,18 @@ mod alias_resolution_tests { #[test] fn test_alias_resolution_builtin() { // Built-in aliases should resolve to their full IDs - assert_eq!(resolve_model_alias_with_config("opus"), "anthropic/claude-opus-4-6"); - assert_eq!(resolve_model_alias_with_config("sonnet"), "anthropic/claude-sonnet-4-6"); - assert_eq!(resolve_model_alias_with_config("haiku"), "anthropic/claude-haiku-4-5-20251213"); + assert_eq!( + resolve_model_alias_with_config("opus"), + "anthropic/claude-opus-4-6" + ); + assert_eq!( + resolve_model_alias_with_config("sonnet"), + "anthropic/claude-sonnet-4-6" + ); + assert_eq!( + resolve_model_alias_with_config("haiku"), + "anthropic/claude-haiku-4-5-20251213" + ); } #[test] diff --git a/rust/crates/tools/src/lib.rs b/rust/crates/tools/src/lib.rs index 63eb3773..a42bdcb3 100644 --- a/rust/crates/tools/src/lib.rs +++ b/rust/crates/tools/src/lib.rs @@ -1937,7 +1937,10 @@ fn run_git_status(input: GitStatusInput) -> Result { Some(output) => to_pretty_json(json!({ "output": output })), - None => Err("git status failed. Ensure the current directory is inside a git repository.".to_string()), + None => Err( + "git status failed. Ensure the current directory is inside a git repository." + .to_string(), + ), } } @@ -1965,7 +1968,9 @@ fn run_git_diff(input: GitDiffInput) -> Result { Some(output) => to_pretty_json(json!({ "output": output })), - None => Err("git diff failed. Ensure the current directory is inside a git repository.".to_string()), + None => Err( + "git diff failed. Ensure the current directory is inside a git repository.".to_string(), + ), } } @@ -1997,7 +2002,9 @@ fn run_git_log(input: GitLogInput) -> Result { Some(output) => to_pretty_json(json!({ "output": output })), - None => Err("git log failed. Ensure the current directory is inside a git repository.".to_string()), + None => Err( + "git log failed. Ensure the current directory is inside a git repository.".to_string(), + ), } } @@ -2019,7 +2026,10 @@ fn run_git_show(input: GitShowInput) -> Result { Some(output) => to_pretty_json(json!({ "output": output })), - None => Err(format!("git show {} failed. Ensure the commit exists.", input.commit)), + None => Err(format!( + "git show {} failed. Ensure the commit exists.", + input.commit + )), } }