use serde_json::{Map, Value, json};
use std::path::{Path, PathBuf};
const PATH_KEYS: &[&str] = &["path", "file", "file_path", "filePath", "cwd"];
const PATH_COLLECTION_KEYS: &[&str] = &["edits", "changes", "operations"];
pub fn normalize_workspace_paths(obj: &mut Map<String, Value>, workspace_dir: &Path) {
for key in PATH_KEYS {
if let Some(value) = obj.get_mut(*key) {
normalize_path_value(value, workspace_dir);
}
}
for key in PATH_COLLECTION_KEYS {
if let Some(items) = obj.get_mut(*key).and_then(Value::as_array_mut) {
for item in items.iter_mut().filter_map(Value::as_object_mut) {
for nested_key in PATH_KEYS {
if let Some(value) = item.get_mut(*nested_key) {
normalize_path_value(value, workspace_dir);
}
}
}
}
}
}
pub fn normalize_path_value(value: &mut Value, workspace_dir: &Path) {
let Some(raw) = value.as_str() else {
return;
};
let resolved = resolve_workspace_path(workspace_dir, raw);
if !resolved.as_os_str().is_empty() {
*value = json!(resolved.display().to_string());
}
}
pub fn resolve_workspace_path(workspace_dir: &Path, raw: &str) -> PathBuf {
if raw.is_empty() || raw.contains("://") || raw.starts_with("data:") || raw.starts_with('~') {
return PathBuf::from(raw);
}
let candidate = PathBuf::from(raw);
if candidate.is_absolute() {
candidate
} else {
workspace_dir.join(candidate)
}
}