Skip to content

Commit 81b3673

Browse files
committed
file size check; http request timeout; fix error handling
1 parent 6df793c commit 81b3673

4 files changed

Lines changed: 25 additions & 12 deletions

File tree

src/api/client.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ use super::types::*;
33
use futures::stream::{Stream, StreamExt};
44
use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE};
55
use std::pin::Pin;
6+
use std::time::Duration;
67

78
const API_BASE: &str = "https://api.anthropic.com/v1";
89
const API_VERSION: &str = "2023-06-01";
10+
const REQUEST_TIMEOUT: Duration = Duration::from_secs(60);
911

1012
pub struct AnthropicClient {
1113
client: reqwest::Client,
12-
_api_key: String,
1314
}
1415

1516
impl AnthropicClient {
@@ -28,10 +29,11 @@ impl AnthropicClient {
2829

2930
let client = reqwest::Client::builder()
3031
.default_headers(headers)
32+
.timeout(REQUEST_TIMEOUT)
3133
.build()
3234
.map_err(|e| SofosError::Config(format!("Failed to create HTTP client: {}", e)))?;
3335

34-
Ok(Self { client, _api_key: api_key })
36+
Ok(Self { client })
3537
}
3638

3739
pub async fn create_message(

src/repl.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::api::{AnthropicClient, ContentBlock, CreateMessageRequest, MorphClien
22
use crate::conversation::ConversationHistory;
33
use crate::error::{Result, SofosError};
44
use crate::tools::{add_code_search_tool, get_tools, get_tools_with_morph, ToolExecutor};
5-
use colored::Colorize;
5+
use colored::{Colorize};
66
use rustyline::error::ReadlineError;
77
use rustyline::DefaultEditor;
88
use std::path::PathBuf;
@@ -313,7 +313,7 @@ impl Repl {
313313
let mut frame_idx = 0;
314314

315315
while thinking_clone.load(Ordering::Relaxed) {
316-
print!("\r{} {}", frames[frame_idx].bright_cyan(), "Thinking...".bright_cyan());
316+
print!("\r{} {}", frames[frame_idx].truecolor(0xFF, 0x99, 0x33), "Thinking...".truecolor(0xFF, 0x99, 0x33));
317317
let _ = io::stdout().flush();
318318
frame_idx = (frame_idx + 1) % frames.len();
319319
thread::sleep(Duration::from_millis(80));
@@ -350,13 +350,17 @@ impl Repl {
350350
Ok(resp) => {
351351
// Stop animation
352352
thinking.store(false, Ordering::Relaxed);
353-
let _ = animation_handle.join();
353+
if let Err(e) = animation_handle.join() {
354+
eprintln!("{} Animation thread panicked: {:?}", "Warning:".bright_yellow().bold(), e);
355+
}
354356
resp
355357
},
356358
Err(e) => {
357359
// Stop animation on error
358360
thinking.store(false, Ordering::Relaxed);
359-
let _ = animation_handle.join();
361+
if let Err(panic_err) = animation_handle.join() {
362+
eprintln!("{} Animation thread panicked: {:?}", "Warning:".bright_yellow().bold(), panic_err);
363+
}
360364
eprintln!("{} Failed to get response after tool execution: {}", "Error:".bright_red().bold(), e);
361365
return Err(e);
362366
}

src/tools/filesystem.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use crate::error::{Result, SofosError};
22
use std::fs;
33
use std::path::{Path, PathBuf};
44

5+
const MAX_FILE_SIZE: u64 = 50 * 1024 * 1024; // 50MB limit
6+
57
/// FileSystemTool provides secure file operations sandboxed to a workspace directory
68
pub struct FileSystemTool {
79
workspace: PathBuf,
@@ -82,6 +84,17 @@ impl FileSystemTool {
8284
)));
8385
}
8486

87+
// Check file size before reading to prevent OOM
88+
let metadata = fs::metadata(&full_path).map_err(SofosError::Io)?;
89+
if metadata.len() > MAX_FILE_SIZE {
90+
return Err(SofosError::InvalidPath(format!(
91+
"File '{}' is too large ({} bytes). Maximum size is {} MB",
92+
path,
93+
metadata.len(),
94+
MAX_FILE_SIZE / (1024 * 1024)
95+
)));
96+
}
97+
8598
fs::read_to_string(&full_path).map_err(|e| {
8699
SofosError::Io(e)
87100
})

src/tools/search.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,6 @@ impl WebSearchTool {
130130
}
131131
}
132132

133-
impl Default for WebSearchTool {
134-
fn default() -> Self {
135-
Self::new().expect("Failed to create WebSearchTool")
136-
}
137-
}
138-
139133
#[cfg(test)]
140134
mod tests {
141135
use super::*;

0 commit comments

Comments
 (0)