Map Windows attachment paths for WSL view_image

This commit is contained in:
David Wiesen
2026-06-11 09:20:06 -07:00
parent 0035d7bd18
commit c180a79a68
3 changed files with 70 additions and 2 deletions
+5 -2
View File
@@ -8,6 +8,7 @@ use codex_protocol::protocol::TurnEnvironmentSelection;
use codex_sandboxing::compatibility_sandbox_policy_for_permission_profile;
use codex_sandboxing::policy_transforms::effective_file_system_sandbox_policy;
use codex_sandboxing::policy_transforms::effective_network_sandbox_policy;
use codex_utils_path::normalize_input_path_for_wsl;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
@@ -268,8 +269,10 @@ impl TurnContext {
}
pub(crate) fn resolve_path(&self, path: Option<String>) -> AbsolutePathBuf {
path.as_ref()
.map_or_else(|| self.cwd.clone(), |path| self.cwd.join(path))
path.as_ref().map_or_else(
|| self.cwd.clone(),
|path| self.cwd.join(normalize_input_path_for_wsl(path)),
)
}
pub(crate) fn file_system_sandbox_context(
+36
View File
@@ -32,6 +32,42 @@ pub fn normalize_for_native_workdir(path: impl AsRef<Path>) -> PathBuf {
normalize_for_native_workdir_with_flag(path.as_ref().to_path_buf(), cfg!(windows))
}
/// Convert a Windows absolute path (`C:\foo\bar` or `C:/foo/bar`) to a WSL mount
/// path (`/mnt/c/foo/bar`). Returns `None` if the input does not look like a Windows
/// drive path.
pub fn win_path_to_wsl(path: &str) -> Option<String> {
let bytes = path.as_bytes();
if bytes.len() < 3
|| bytes[1] != b':'
|| !(bytes[2] == b'\\' || bytes[2] == b'/')
|| !bytes[0].is_ascii_alphabetic()
{
return None;
}
let drive = (bytes[0] as char).to_ascii_lowercase();
let tail = path[3..].replace('\\', "/");
if tail.is_empty() {
return Some(format!("/mnt/{drive}"));
}
Some(format!("/mnt/{drive}/{tail}"))
}
/// When running under WSL, translate Windows drive paths into the equivalent
/// `/mnt/<drive>/...` form before path resolution. Other inputs are returned unchanged.
pub fn normalize_input_path_for_wsl(path: &str) -> PathBuf {
normalize_input_path_for_wsl_with_flag(path, env::is_wsl())
}
fn normalize_input_path_for_wsl_with_flag(path: &str, is_wsl: bool) -> PathBuf {
if is_wsl && let Some(mapped) = win_path_to_wsl(path) {
return PathBuf::from(mapped);
}
PathBuf::from(path)
}
pub struct SymlinkWritePaths {
pub read_path: Option<PathBuf>,
pub write_path: PathBuf,
@@ -24,6 +24,8 @@ mod symlinks {
#[cfg(target_os = "linux")]
mod wsl {
use super::super::normalize_for_wsl_with_flag;
use super::super::normalize_input_path_for_wsl_with_flag;
use super::super::win_path_to_wsl;
use pretty_assertions::assert_eq;
use std::path::PathBuf;
@@ -50,6 +52,33 @@ mod wsl {
assert_eq!(normalized, path);
}
#[test]
fn converts_windows_drive_paths_to_wsl_mounts() {
assert_eq!(
win_path_to_wsl(r"C:\Users\SLee\AppData\Local\Temp\image.png").as_deref(),
Some("/mnt/c/Users/SLee/AppData/Local/Temp/image.png")
);
assert_eq!(
win_path_to_wsl("D:/Work/codex.png").as_deref(),
Some("/mnt/d/Work/codex.png")
);
}
#[test]
fn normalize_input_path_maps_windows_paths_in_wsl() {
assert_eq!(
normalize_input_path_for_wsl_with_flag(
r"C:\Users\SLee\AppData\Local\Temp\image.png",
/*is_wsl*/ true
),
PathBuf::from("/mnt/c/Users/SLee/AppData/Local/Temp/image.png")
);
assert_eq!(
normalize_input_path_for_wsl_with_flag("/tmp/copied-image.png", /*is_wsl*/ true),
PathBuf::from("/tmp/copied-image.png")
);
}
}
mod native_workdir {