refactor: improve readability of streaming and file ops code

Agent: carmack

databricks.rs:
- Extract ToolCallAccumulator struct to replace opaque (String, String, String) tuple
- Add decode_utf8_streaming() helper for cleaner UTF-8 handling
- Add is_incomplete_json_error() helper for JSON parse error detection
- Add make_final_chunk() helper to reduce duplication
- Add finalize_tool_calls() to convert accumulators to final format
- Refactor parse_streaming_response from ~270 lines to ~100 lines
- Reduce nesting depth from 8+ levels to 4 levels
- Use early returns and let-else for cleaner control flow

file_ops.rs:
- Replace repetitive if-let chains with declarative PATH_CONTENT_KEYS table
- Use match expression instead of nested if-else
- Reduce extract_path_and_content from 44 lines to 20 lines

All tests pass. Behavior unchanged.
This commit is contained in:
Dhanji R. Prasanna
2026-01-07 12:39:05 +11:00
parent 532ed132f7
commit bb63050779
2 changed files with 233 additions and 406 deletions

View File

@@ -345,48 +345,35 @@ pub async fn execute_str_replace<W: UiWriter>(
// Helper functions
/// Known argument key pairs for path and content.
const PATH_CONTENT_KEYS: &[(&str, &str)] = &[
("file_path", "content"), // Standard format
("path", "content"), // Anthropic-style
("filename", "text"), // Alternative naming
("file", "data"), // Alternative naming
];
/// Extract path and content from various argument formats.
fn extract_path_and_content(args: &serde_json::Value) -> (Option<&str>, Option<&str>) {
if let Some(args_obj) = args.as_object() {
// Format 1: Standard format with file_path and content
if let (Some(path_val), Some(content_val)) =
(args_obj.get("file_path"), args_obj.get("content"))
{
if let (Some(path), Some(content)) = (path_val.as_str(), content_val.as_str()) {
return (Some(path), Some(content));
}
}
// Format 2: Anthropic-style with path and content
if let (Some(path_val), Some(content_val)) =
(args_obj.get("path"), args_obj.get("content"))
{
if let (Some(path), Some(content)) = (path_val.as_str(), content_val.as_str()) {
return (Some(path), Some(content));
}
}
// Format 3: Alternative naming with filename and text
if let (Some(path_val), Some(content_val)) =
(args_obj.get("filename"), args_obj.get("text"))
{
if let (Some(path), Some(content)) = (path_val.as_str(), content_val.as_str()) {
return (Some(path), Some(content));
}
}
// Format 4: Alternative naming with file and data
if let (Some(path_val), Some(content_val)) = (args_obj.get("file"), args_obj.get("data")) {
if let (Some(path), Some(content)) = (path_val.as_str(), content_val.as_str()) {
return (Some(path), Some(content));
}
}
} else if let Some(args_array) = args.as_array() {
// Format 5: Args might be an array [path, content]
if args_array.len() >= 2 {
if let (Some(path), Some(content)) = (args_array[0].as_str(), args_array[1].as_str()) {
return (Some(path), Some(content));
match args {
serde_json::Value::Object(obj) => {
for &(path_key, content_key) in PATH_CONTENT_KEYS {
if let (Some(p), Some(c)) = (obj.get(path_key), obj.get(content_key)) {
if let (Some(path), Some(content)) = (p.as_str(), c.as_str()) {
return (Some(path), Some(content));
}
}
}
(None, None)
}
serde_json::Value::Array(arr) if arr.len() >= 2 => {
match (arr[0].as_str(), arr[1].as_str()) {
(Some(path), Some(content)) => (Some(path), Some(content)),
_ => (None, None),
}
}
_ => (None, None),
}
(None, None)
}
/// Get image dimensions from raw bytes.