Skip to content

Commit 0d34ac6

Browse files
Rust: set in-process runtime worker cwd to the client working directory
The in-process FFI host never set the runtime worker's current directory, so it inherited the SDK process's cwd instead of the client's working_directory. Unlike the stdio/tcp transports (build_command sets .current_dir(working_directory)), workspace-relative file operations therefore resolved against the wrong directory: the model's tool calls used a relative path (e.g. 'order.txt') that the runtime rejected as 'not absolute', diverging from the recorded replay snapshot and surfacing as a proxy 500 / send_and_wait failure — but only in-process. Mirror the Node in-process host: switch cwd to working_directory for the duration of the blocking host_start (which spawns the worker), then restore it. Confirmed locally: the affected event_fidelity + hooks tests pass in-process, and the test already passed over stdio. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent b6dba81 commit 0d34ac6

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

rust/src/ffi.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ pub(crate) struct FfiHost {
194194
library_path: PathBuf,
195195
entrypoint: PathBuf,
196196
environment: Vec<(String, String)>,
197+
working_directory: Option<PathBuf>,
197198
host_start: HostStartFn,
198199
host_shutdown: HostShutdownFn,
199200
connection_open: ConnectionOpenFn,
@@ -215,6 +216,7 @@ impl FfiHost {
215216
pub(crate) fn create(
216217
entrypoint: &Path,
217218
environment: Vec<(String, String)>,
219+
working_directory: Option<PathBuf>,
218220
) -> Result<Self, Error> {
219221
let library_path = resolve_library_path(entrypoint)?;
220222
let lib = load_library(&library_path)?;
@@ -233,6 +235,7 @@ impl FfiHost {
233235
library_path,
234236
entrypoint: entrypoint.to_path_buf(),
235237
environment,
238+
working_directory,
236239
host_start,
237240
host_shutdown,
238241
connection_open,
@@ -265,7 +268,28 @@ impl FfiHost {
265268
Some(bytes) => (bytes.as_ptr(), bytes.len()),
266269
None => (std::ptr::null(), 0),
267270
};
271+
272+
// The native host spawns the CLI worker itself and exposes no cwd
273+
// parameter, so the worker inherits this process's current directory.
274+
// Mirror the stdio child's `current_dir(working_directory)` by switching
275+
// cwd for the duration of the blocking `host_start` (which spawns the
276+
// worker), then restoring it. This matches the Node in-process host and
277+
// ensures workspace-relative file operations resolve against the
278+
// client's working directory rather than the SDK process's cwd.
279+
let previous_cwd = std::env::current_dir().ok();
280+
let switched_cwd = match &self.working_directory {
281+
Some(dir) if previous_cwd.as_deref() != Some(dir.as_path()) => {
282+
std::env::set_current_dir(dir).is_ok()
283+
}
284+
_ => false,
285+
};
286+
268287
let server_id = unsafe { (self.host_start)(argv.as_ptr(), argv.len(), env_ptr, env_len) };
288+
289+
if switched_cwd && let Some(previous) = &previous_cwd {
290+
let _ = std::env::set_current_dir(previous);
291+
}
292+
269293
if server_id == 0 {
270294
return Err(Error::with_message(
271295
ErrorKind::InvalidConfig,

rust/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1169,7 +1169,11 @@ impl Client {
11691169
// env; configure the runtime via the host process environment instead.
11701170
// See https://github.com/github/copilot-sdk/issues/1934.
11711171
info!(entrypoint = %program.display(), "hosting copilot runtime in-process (FFI)");
1172-
let host = crate::ffi::FfiHost::create(&program, Vec::new())?;
1172+
let host = crate::ffi::FfiHost::create(
1173+
&program,
1174+
Vec::new(),
1175+
Some(options.working_directory.clone()),
1176+
)?;
11731177
let (reader, writer, shared) = host.start().await?;
11741178
let client = Self::from_transport(
11751179
reader,

0 commit comments

Comments
 (0)