Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/apps/desktop/src/api/tool_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ fn build_tool_context(workspace_path: Option<&str>) -> ToolUseContext {
dialog_turn_id: None,
workspace: normalized_workspace_path
.map(|path| WorkspaceBinding::new(None, PathBuf::from(path))),
current_working_directory: normalized_workspace_path.map(str::to_string),
safe_mode: Some(false),
abort_controller: None,
read_file_timestamps: HashMap::new(),
Expand Down
1 change: 0 additions & 1 deletion src/crates/core/src/agentic/execution/execution_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1485,7 +1485,6 @@ impl ExecutionEngine {
session_id: None,
dialog_turn_id: None,
workspace: workspace.cloned(),
current_working_directory: None,
safe_mode: None,
abort_controller: None,
read_file_timestamps: Default::default(),
Expand Down
11 changes: 0 additions & 11 deletions src/crates/core/src/agentic/tools/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ pub struct ToolUseContext {
pub session_id: Option<String>,
pub dialog_turn_id: Option<String>,
pub workspace: Option<WorkspaceBinding>,
pub current_working_directory: Option<String>,
pub safe_mode: Option<bool>,
pub abort_controller: Option<String>,
pub read_file_timestamps: HashMap<String, u64>,
Expand All @@ -44,15 +43,6 @@ impl ToolUseContext {
self.workspace.as_ref().map(|binding| binding.root_path())
}

pub fn current_working_directory(&self) -> Option<&Path> {
self.current_working_directory.as_deref().map(Path::new)
}

pub fn path_resolution_base(&self) -> Option<&Path> {
self.current_working_directory()
.or_else(|| self.workspace_root())
}

pub fn is_remote(&self) -> bool {
self.workspace
.as_ref()
Expand Down Expand Up @@ -88,7 +78,6 @@ impl ToolUseContext {
.map(|w| w.root_path_string());
crate::agentic::tools::workspace_paths::resolve_workspace_tool_path(
path,
self.current_working_directory.as_deref(),
workspace_root_owned.as_deref(),
self.is_remote(),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,13 @@ Usage:
}
};

let cwd_owned = context.and_then(|ctx| ctx.current_working_directory.clone());
let root_owned = context.and_then(|ctx| {
ctx.workspace
.as_ref()
.map(|w| w.root_path_string())
});
let resolved_path = match resolve_workspace_tool_path(
file_path,
cwd_owned.as_deref(),
root_owned.as_deref(),
context.map(|c| c.is_remote()).unwrap_or(false),
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,13 @@ Usage:
};
}

let cwd_owned = context.and_then(|ctx| ctx.current_working_directory.clone());
let root_owned = context.and_then(|ctx| {
ctx.workspace
.as_ref()
.map(|w| w.root_path_string())
});
if let Err(err) = resolve_workspace_tool_path(
file_path,
cwd_owned.as_deref(),
root_owned.as_deref(),
context.map(|c| c.is_remote()).unwrap_or(false),
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,15 +348,13 @@ Usage:

let is_remote = context.map(|c| c.is_remote()).unwrap_or(false);

let cwd_owned = context.and_then(|c| c.current_working_directory.clone());
let root_owned = context.and_then(|c| {
c.workspace
.as_ref()
.map(|w| w.root_path_string())
});
let resolved_path = match resolve_workspace_tool_path(
file_path,
cwd_owned.as_deref(),
root_owned.as_deref(),
is_remote,
) {
Expand Down
10 changes: 4 additions & 6 deletions src/crates/core/src/agentic/tools/implementations/grep_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,10 @@ impl GrepTool {
}

fn display_base(context: &ToolUseContext) -> Option<String> {
context.current_working_directory.clone().or_else(|| {
context
.workspace
.as_ref()
.map(|workspace| workspace.root_path_string())
})
context
.workspace
.as_ref()
.map(|workspace| workspace.root_path_string())
}

fn relativize_result_text(result_text: &str, display_base: Option<&str>) -> String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,6 @@ mod tests {
session_id: None,
dialog_turn_id: None,
workspace: None,
current_working_directory: None,
safe_mode: None,
abort_controller: None,
read_file_timestamps: HashMap::new(),
Expand Down
5 changes: 0 additions & 5 deletions src/crates/core/src/agentic/tools/pipeline/tool_pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,11 +724,6 @@ impl ToolPipeline {
session_id: Some(task.context.session_id.clone()),
dialog_turn_id: Some(task.context.dialog_turn_id.clone()),
workspace: task.context.workspace.clone(),
current_working_directory: task
.context
.context_vars
.get("current_working_directory")
.cloned(),
safe_mode: None,
abort_controller: None,
read_file_timestamps: Default::default(),
Expand Down
52 changes: 14 additions & 38 deletions src/crates/core/src/agentic/tools/workspace_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,14 @@ pub fn normalize_path(path: &str) -> String {

pub fn resolve_path_with_workspace(
path: &str,
current_working_directory: Option<&Path>,
workspace_root: Option<&Path>,
) -> BitFunResult<String> {
if Path::new(path).is_absolute() {
Ok(normalize_path(path))
} else {
let base_path = current_working_directory.or(workspace_root).ok_or_else(|| {
let base_path = workspace_root.ok_or_else(|| {
BitFunError::tool(format!(
"A current working directory or workspace path is required to resolve relative path: {}",
"A workspace path is required to resolve relative path: {}",
path
))
})?;
Expand All @@ -50,7 +49,7 @@ pub fn resolve_path_with_workspace(
}

pub fn resolve_path(path: &str) -> BitFunResult<String> {
resolve_path_with_workspace(path, None, None)
resolve_path_with_workspace(path, None)
}

/// POSIX absolute: after normalizing backslashes, path starts with `/`.
Expand Down Expand Up @@ -84,7 +83,6 @@ fn posix_normalize_components(path: &str) -> String {
/// Resolve a path using POSIX rules (for remote SSH workspaces).
pub fn posix_resolve_path_with_workspace(
path: &str,
current_working_directory: Option<&str>,
workspace_root: Option<&str>,
) -> BitFunResult<String> {
let path = path.trim();
Expand All @@ -97,11 +95,10 @@ pub fn posix_resolve_path_with_workspace(
let combined = if posix_style_path_is_absolute(&normalized_input) {
normalized_input
} else {
let base = current_working_directory
.or(workspace_root)
let base = workspace_root
.ok_or_else(|| {
BitFunError::tool(format!(
"A current working directory or workspace path is required to resolve relative path: {}",
"A workspace path is required to resolve relative path: {}",
path
))
})?
Expand All @@ -117,18 +114,13 @@ pub fn posix_resolve_path_with_workspace(
/// Unified resolver: POSIX semantics when the workspace is remote SSH; otherwise host `Path`.
pub fn resolve_workspace_tool_path(
path: &str,
current_working_directory: Option<&str>,
workspace_root: Option<&str>,
workspace_is_remote: bool,
) -> BitFunResult<String> {
if workspace_is_remote {
posix_resolve_path_with_workspace(path, current_working_directory, workspace_root)
posix_resolve_path_with_workspace(path, workspace_root)
} else {
resolve_path_with_workspace(
path,
current_working_directory.map(Path::new),
workspace_root.map(Path::new),
)
resolve_path_with_workspace(path, workspace_root.map(Path::new))
}
}

Expand All @@ -137,40 +129,24 @@ mod tests {
use super::*;

#[test]
fn resolves_relative_paths_from_current_working_directory_first() {
let resolved = resolve_path_with_workspace(
"src/main.rs",
Some(Path::new("/repo/crates/core")),
Some(Path::new("/repo")),
)
.expect("path should resolve");

assert_eq!(resolved, "/repo/crates/core/src/main.rs");
}

#[test]
fn falls_back_to_workspace_root_when_current_working_directory_missing() {
let resolved =
resolve_path_with_workspace("src/main.rs", None, Some(Path::new("/repo")))
.expect("path should resolve");
fn resolves_relative_paths_from_workspace_root() {
let resolved = resolve_path_with_workspace("src/main.rs", Some(Path::new("/repo")))
.expect("path should resolve");

assert_eq!(resolved, "/repo/src/main.rs");
}

#[test]
fn posix_absolute_starts_with_slash() {
let r = posix_resolve_path_with_workspace(
"/home/user/file.txt",
None,
Some("/should/not/matter"),
)
.unwrap();
let r =
posix_resolve_path_with_workspace("/home/user/file.txt", Some("/should/not/matter"))
.unwrap();
assert_eq!(r, "/home/user/file.txt");
}

#[test]
fn posix_relative_joins_workspace() {
let r = posix_resolve_path_with_workspace("src/main.rs", None, Some("/home/proj")).unwrap();
let r = posix_resolve_path_with_workspace("src/main.rs", Some("/home/proj")).unwrap();
assert_eq!(r, "/home/proj/src/main.rs");
}
}
Loading