style: cargo fmt after parallel stream merges

This commit is contained in:
Hunter Bown
2026-04-27 19:43:48 -05:00
parent f10d5d1829
commit 8be032b6bd
9 changed files with 126 additions and 93 deletions
+1
View File
@@ -72,3 +72,4 @@ apps/
# Claude Code runtime artifacts # Claude Code runtime artifacts
.claude/scheduled_tasks.lock .claude/scheduled_tasks.lock
.claude/worktrees/ .claude/worktrees/
.worktrees/
+5 -6
View File
@@ -3298,12 +3298,11 @@ impl Engine {
"tool_id": tool_id.clone(), "tool_id": tool_id.clone(),
"tool_name": tool_name.clone(), "tool_name": tool_name.clone(),
})); }));
let approval_key = let approval_key = crate::tools::approval_cache::build_approval_key(
crate::tools::approval_cache::build_approval_key( &tool_name,
&tool_name, &tool_input,
&tool_input, )
) .0;
.0;
let _ = self let _ = self
.tx_event .tx_event
.send(Event::ApprovalRequired { .send(Event::ApprovalRequired {
+13 -35
View File
@@ -319,9 +319,7 @@ pub enum ClientError {
retryable: bool, retryable: bool,
}, },
/// Generic internal error that doesn't fit a provider taxonomy. /// Generic internal error that doesn't fit a provider taxonomy.
Internal { Internal { envelope: ErrorEnvelope },
envelope: ErrorEnvelope,
},
} }
impl ClientError { impl ClientError {
@@ -412,25 +410,15 @@ impl std::error::Error for ClientError {}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum StreamError { pub enum StreamError {
/// Stream stalled — no chunk received within the idle timeout. /// Stream stalled — no chunk received within the idle timeout.
Stall { Stall { timeout_secs: u64 },
timeout_secs: u64,
},
/// Chunk decode / JSON parse failure. /// Chunk decode / JSON parse failure.
Decode { Decode { message: String },
message: String,
},
/// Stream exceeded content size limit. /// Stream exceeded content size limit.
Overflow { Overflow { limit_bytes: usize },
limit_bytes: usize,
},
/// Stream exceeded wallclock duration limit. /// Stream exceeded wallclock duration limit.
DurationLimit { DurationLimit { limit_secs: u64 },
limit_secs: u64,
},
/// Transport error from the underlying SSE connection. /// Transport error from the underlying SSE connection.
Transport { Transport { message: String },
message: String,
},
} }
impl StreamError { impl StreamError {
@@ -439,29 +427,19 @@ impl StreamError {
pub fn into_client_error(self) -> ClientError { pub fn into_client_error(self) -> ClientError {
match self { match self {
Self::Stall { timeout_secs } => { Self::Stall { timeout_secs } => {
ClientError::stream( ClientError::stream(format!("Stream stalled after {timeout_secs}s idle"), true)
format!("Stream stalled after {timeout_secs}s idle"),
true,
)
} }
Self::Decode { message } => { Self::Decode { message } => {
ClientError::stream(format!("Stream decode error: {message}"), true) ClientError::stream(format!("Stream decode error: {message}"), true)
} }
Self::Overflow { limit_bytes } => { Self::Overflow { limit_bytes } => {
ClientError::stream( ClientError::stream(format!("Stream exceeded {limit_bytes} bytes limit"), false)
format!("Stream exceeded {limit_bytes} bytes limit"),
false,
)
}
Self::DurationLimit { limit_secs } => {
ClientError::stream(
format!("Stream exceeded {limit_secs}s duration limit"),
false,
)
}
Self::Transport { message } => {
ClientError::stream(message, true)
} }
Self::DurationLimit { limit_secs } => ClientError::stream(
format!("Stream exceeded {limit_secs}s duration limit"),
false,
),
Self::Transport { message } => ClientError::stream(message, true),
} }
} }
} }
+8 -5
View File
@@ -134,9 +134,8 @@ pub fn compose_prompt(mode: AppMode, personality: Personality) -> String {
approval_prompt(mode).trim(), approval_prompt(mode).trim(),
]; ];
let mut out = String::with_capacity( let mut out =
parts.iter().map(|p| p.len()).sum::<usize>() + (parts.len() - 1) * 2, String::with_capacity(parts.iter().map(|p| p.len()).sum::<usize>() + (parts.len() - 1) * 2);
);
for (i, part) in parts.iter().enumerate() { for (i, part) in parts.iter().enumerate() {
if i > 0 { if i > 0 {
out.push('\n'); out.push('\n');
@@ -335,9 +334,13 @@ mod tests {
#[test] #[test]
fn each_mode_gets_correct_approval() { fn each_mode_gets_correct_approval() {
assert!(compose_prompt(AppMode::Agent, Personality::Calm).contains("Approval Policy: Suggest")); assert!(
compose_prompt(AppMode::Agent, Personality::Calm).contains("Approval Policy: Suggest")
);
assert!(compose_prompt(AppMode::Yolo, Personality::Calm).contains("Approval Policy: Auto")); assert!(compose_prompt(AppMode::Yolo, Personality::Calm).contains("Approval Policy: Auto"));
assert!(compose_prompt(AppMode::Plan, Personality::Calm).contains("Approval Policy: Never")); assert!(
compose_prompt(AppMode::Plan, Personality::Calm).contains("Approval Policy: Never")
);
} }
#[test] #[test]
+2 -1
View File
@@ -3177,7 +3177,8 @@ mod tests {
harness harness
.tx_event .tx_event
.send(EngineEvent::ApprovalRequired { approval_key: "test_key".to_string(), .send(EngineEvent::ApprovalRequired {
approval_key: "test_key".to_string(),
id: "tool_stale".to_string(), id: "tool_stale".to_string(),
tool_name: "exec_command".to_string(), tool_name: "exec_command".to_string(),
description: "stale approval".to_string(), description: "stale approval".to_string(),
+7 -10
View File
@@ -121,8 +121,11 @@ pub fn build_approval_key(tool_name: &str, input: &serde_json::Value) -> Approva
let paths_hash = hash_patch_paths(input); let paths_hash = hash_patch_paths(input);
format!("patch:{paths_hash}") format!("patch:{paths_hash}")
} }
"exec_shell" | "exec_shell_wait" | "exec_shell_interact" "exec_shell"
| "exec_wait" | "exec_interact" => { | "exec_shell_wait"
| "exec_shell_interact"
| "exec_wait"
| "exec_interact" => {
let prefix = command_prefix(input); let prefix = command_prefix(input);
format!("shell:{prefix}") format!("shell:{prefix}")
} }
@@ -137,10 +140,7 @@ pub fn build_approval_key(tool_name: &str, input: &serde_json::Value) -> Approva
/// Extract the first three nonflag tokens from the command string. /// Extract the first three nonflag tokens from the command string.
fn command_prefix(input: &serde_json::Value) -> String { fn command_prefix(input: &serde_json::Value) -> String {
let cmd = input let cmd = input.get("command").and_then(|v| v.as_str()).unwrap_or("");
.get("command")
.and_then(|v| v.as_str())
.unwrap_or("");
let tokens: Vec<&str> = cmd let tokens: Vec<&str> = cmd
.split_whitespace() .split_whitespace()
.filter(|t| !t.starts_with('-')) .filter(|t| !t.starts_with('-'))
@@ -190,10 +190,7 @@ fn hash_patch_paths(input: &serde_json::Value) -> String {
/// Parse the host portion from a URL input. /// Parse the host portion from a URL input.
fn parse_host(input: &serde_json::Value) -> String { fn parse_host(input: &serde_json::Value) -> String {
let url = input let url = input.get("url").and_then(|v| v.as_str()).unwrap_or("");
.get("url")
.and_then(|v| v.as_str())
.unwrap_or("");
if let Ok(parsed) = reqwest::Url::parse(url) { if let Ok(parsed) = reqwest::Url::parse(url) {
parsed.host_str().unwrap_or(url).to_string() parsed.host_str().unwrap_or(url).to_string()
+3 -11
View File
@@ -607,10 +607,7 @@ impl ToolSpec for McpToolAdapter {
fn description(&self) -> &str { fn description(&self) -> &str {
// McpTool.description is Option<String>; fall back to the // McpTool.description is Option<String>; fall back to the
// prefixed name when absent. // prefixed name when absent.
self.tool self.tool.description.as_deref().unwrap_or(&self.name)
.description
.as_deref()
.unwrap_or(&self.name)
} }
fn input_schema(&self) -> Value { fn input_schema(&self) -> Value {
@@ -645,18 +642,13 @@ impl ToolSpec for McpToolAdapter {
!keep_loaded !keep_loaded
} }
async fn execute( async fn execute(&self, input: Value, _context: &ToolContext) -> Result<ToolResult, ToolError> {
&self,
input: Value,
_context: &ToolContext,
) -> Result<ToolResult, ToolError> {
let mut pool = self.pool.lock().await; let mut pool = self.pool.lock().await;
let result = pool let result = pool
.call_tool(&self.name, input) .call_tool(&self.name, input)
.await .await
.map_err(|e| ToolError::execution_failed(format!("MCP tool failed: {e}")))?; .map_err(|e| ToolError::execution_failed(format!("MCP tool failed: {e}")))?;
let content = let content = serde_json::to_string_pretty(&result).unwrap_or_else(|_| result.to_string());
serde_json::to_string_pretty(&result).unwrap_or_else(|_| result.to_string());
Ok(ToolResult::success(content)) Ok(ToolResult::success(content))
} }
} }
+77 -21
View File
@@ -668,8 +668,13 @@ mod tests {
#[test] #[test]
fn test_approval_request_new() { fn test_approval_request_new() {
let params = json!({"path": "src/main.rs", "content": "test"}); let params = json!({"path": "src/main.rs", "content": "test"});
let request = let request = ApprovalRequest::new(
ApprovalRequest::new("test-id", "write_file", "Write a file to disk", &params, "test_key"); "test-id",
"write_file",
"Write a file to disk",
&params,
"test_key",
);
assert_eq!(request.id, "test-id"); assert_eq!(request.id, "test-id");
assert_eq!(request.tool_name, "write_file"); assert_eq!(request.tool_name, "write_file");
@@ -682,8 +687,13 @@ mod tests {
// Create params with a very long string // Create params with a very long string
let long_content = "x".repeat(300); let long_content = "x".repeat(300);
let params = json!({"path": "src/main.rs", "content": long_content}); let params = json!({"path": "src/main.rs", "content": long_content});
let request = let request = ApprovalRequest::new(
ApprovalRequest::new("test-id", "write_file", "Write a file to disk", &params, "test_key"); "test-id",
"write_file",
"Write a file to disk",
&params,
"test_key",
);
let display = request.params_display(); let display = request.params_display();
// Should be truncated to around 200 chars // Should be truncated to around 200 chars
@@ -694,8 +704,13 @@ mod tests {
#[test] #[test]
fn test_approval_request_params_display_short() { fn test_approval_request_params_display_short() {
let params = json!({"path": "src/main.rs"}); let params = json!({"path": "src/main.rs"});
let request = let request = ApprovalRequest::new(
ApprovalRequest::new("test-id", "read_file", "Read a file from disk", &params, "test_key"); "test-id",
"read_file",
"Read a file from disk",
&params,
"test_key",
);
let display = request.params_display(); let display = request.params_display();
assert!(display.contains("src/main.rs")); assert!(display.contains("src/main.rs"));
@@ -704,7 +719,13 @@ mod tests {
#[test] #[test]
fn test_approval_request_derives_impact_summary() { fn test_approval_request_derives_impact_summary() {
let params = json!({"cmd": "cargo test", "workdir": "/tmp/project"}); let params = json!({"cmd": "cargo test", "workdir": "/tmp/project"});
let request = ApprovalRequest::new("test-id", "exec_shell", "Run a shell command", &params, "test_key"); let request = ApprovalRequest::new(
"test-id",
"exec_shell",
"Run a shell command",
&params,
"test_key",
);
assert_eq!(request.category, ToolCategory::Shell); assert_eq!(request.category, ToolCategory::Shell);
assert!( assert!(
@@ -728,8 +749,13 @@ mod tests {
#[test] #[test]
fn test_approval_view_initial_state() { fn test_approval_view_initial_state() {
let params = json!({"path": "src/main.rs"}); let params = json!({"path": "src/main.rs"});
let request = let request = ApprovalRequest::new(
ApprovalRequest::new("test-id", "read_file", "Read a file from disk", &params, "test_key"); "test-id",
"read_file",
"Read a file from disk",
&params,
"test_key",
);
let view = ApprovalView::new(request.clone()); let view = ApprovalView::new(request.clone());
assert_eq!(view.selected, 0); assert_eq!(view.selected, 0);
@@ -739,8 +765,13 @@ mod tests {
#[test] #[test]
fn test_approval_view_navigation() { fn test_approval_view_navigation() {
let params = json!({"path": "src/main.rs"}); let params = json!({"path": "src/main.rs"});
let request = let request = ApprovalRequest::new(
ApprovalRequest::new("test-id", "read_file", "Read a file from disk", &params, "test_key"); "test-id",
"read_file",
"Read a file from disk",
&params,
"test_key",
);
let mut view = ApprovalView::new(request); let mut view = ApprovalView::new(request);
// Initially at 0 // Initially at 0
@@ -768,8 +799,13 @@ mod tests {
#[test] #[test]
fn test_approval_view_keybindings_decisions() { fn test_approval_view_keybindings_decisions() {
let params = json!({"path": "src/main.rs"}); let params = json!({"path": "src/main.rs"});
let request = let request = ApprovalRequest::new(
ApprovalRequest::new("test-id", "read_file", "Read a file from disk", &params, "test_key"); "test-id",
"read_file",
"Read a file from disk",
&params,
"test_key",
);
let mut view = ApprovalView::new(request.clone()); let mut view = ApprovalView::new(request.clone());
// Test 'y' -> Approved // Test 'y' -> Approved
@@ -819,8 +855,13 @@ mod tests {
#[test] #[test]
fn test_approval_view_enter_uses_selected_option() { fn test_approval_view_enter_uses_selected_option() {
let params = json!({"path": "src/main.rs"}); let params = json!({"path": "src/main.rs"});
let request = let request = ApprovalRequest::new(
ApprovalRequest::new("test-id", "read_file", "Read a file from disk", &params, "test_key"); "test-id",
"read_file",
"Read a file from disk",
&params,
"test_key",
);
let mut view = ApprovalView::new(request); let mut view = ApprovalView::new(request);
// Navigate to index 2 (Denied) // Navigate to index 2 (Denied)
@@ -842,8 +883,13 @@ mod tests {
#[test] #[test]
fn test_approval_view_navigation_keys() { fn test_approval_view_navigation_keys() {
let params = json!({"path": "src/main.rs"}); let params = json!({"path": "src/main.rs"});
let request = let request = ApprovalRequest::new(
ApprovalRequest::new("test-id", "read_file", "Read a file from disk", &params, "test_key"); "test-id",
"read_file",
"Read a file from disk",
&params,
"test_key",
);
let mut view = ApprovalView::new(request); let mut view = ApprovalView::new(request);
// Test Up arrow // Test Up arrow
@@ -866,8 +912,13 @@ mod tests {
#[test] #[test]
fn test_approval_view_view_params() { fn test_approval_view_view_params() {
let params = json!({"path": "src/main.rs", "content": "test"}); let params = json!({"path": "src/main.rs", "content": "test"});
let request = let request = ApprovalRequest::new(
ApprovalRequest::new("test-id", "read_file", "Read a file from disk", &params, "test_key"); "test-id",
"read_file",
"Read a file from disk",
&params,
"test_key",
);
let mut view = ApprovalView::new(request.clone()); let mut view = ApprovalView::new(request.clone());
// Test 'v' to view params // Test 'v' to view params
@@ -889,8 +940,13 @@ mod tests {
#[test] #[test]
fn test_approval_view_current_decision_mapping() { fn test_approval_view_current_decision_mapping() {
let params = json!({"path": "src/main.rs"}); let params = json!({"path": "src/main.rs"});
let request = let request = ApprovalRequest::new(
ApprovalRequest::new("test-id", "read_file", "Read a file from disk", &params, "test_key"); "test-id",
"read_file",
"Read a file from disk",
&params,
"test_key",
);
let mut view = ApprovalView::new(request); let mut view = ApprovalView::new(request);
// Index 0 -> Approved // Index 0 -> Approved
+10 -4
View File
@@ -771,8 +771,9 @@ async fn run_event_loop(
description, description,
approval_key, approval_key,
} => { } => {
let session_approved = app.approval_session_approved.contains(&approval_key) let session_approved =
|| app.approval_session_approved.contains(&tool_name); app.approval_session_approved.contains(&approval_key)
|| app.approval_session_approved.contains(&tool_name);
if session_approved || app.approval_mode == ApprovalMode::Auto { if session_approved || app.approval_mode == ApprovalMode::Auto {
log_sensitive_event( log_sensitive_event(
"tool.approval.auto_approve", "tool.approval.auto_approve",
@@ -809,8 +810,13 @@ async fn run_event_loop(
} }
// Create approval request and show overlay // Create approval request and show overlay
let request = let request = ApprovalRequest::new(
ApprovalRequest::new(&id, &tool_name, &description, &tool_input, &approval_key); &id,
&tool_name,
&description,
&tool_input,
&approval_key,
);
log_sensitive_event( log_sensitive_event(
"tool.approval.prompted", "tool.approval.prompted",
serde_json::json!({ serde_json::json!({