mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
core: keep remote exec on reported shell (#28983)
## Why We need to avoid resolving shells on the app-server's host for remote environments. We might make it possible to do fancier shell resolution from remote envs but for now just require the model to produce a shell that matches the environment's default. This gets my e2e demo working for shell commands after #28854 moved shell resolution to PathUri and caused remote envs to hit the fallback shell when the shell wasn't available on the host. ## What Remote `exec_command` calls now accept only the environment's reported default shell name or exact path, and execute with that reported path. Other explicit shells return a concise error. A Wine-backed integration test covers explicit PowerShell execution in the Windows cwd.
This commit is contained in:
committed by
GitHub
Unverified
parent
195c936fa2
commit
346d2c163f
@@ -1,3 +1,4 @@
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::function_tool::FunctionCallError;
|
||||
@@ -31,6 +32,7 @@ use codex_otel::TOOL_CALL_UNIFIED_EXEC_METRIC;
|
||||
use codex_sandboxing::SandboxManager;
|
||||
use codex_sandboxing::SandboxType;
|
||||
use codex_sandboxing::SandboxablePreference;
|
||||
use codex_shell_command::shell_detect::detect_shell_type;
|
||||
use codex_tools::ToolName;
|
||||
use codex_tools::ToolSpec;
|
||||
use codex_utils_output_truncation::approx_token_count;
|
||||
@@ -172,7 +174,7 @@ impl ExecCommandHandler {
|
||||
)));
|
||||
}
|
||||
};
|
||||
let args: ExecCommandArgs = match native_cwd.as_ref() {
|
||||
let mut args: ExecCommandArgs = match native_cwd.as_ref() {
|
||||
Some(native_cwd) => {
|
||||
// The base path only resolves paths nested in the permissions config types.
|
||||
parse_arguments_with_base_path(&arguments, native_cwd)?
|
||||
@@ -195,7 +197,6 @@ impl ExecCommandHandler {
|
||||
)
|
||||
.await;
|
||||
}
|
||||
let process_id = manager.allocate_process_id().await;
|
||||
let shell_mode =
|
||||
shell_mode_for_environment(&turn.unified_exec_shell_mode, environment.as_ref());
|
||||
// Remote environments may use a different OS and must build commands with their native
|
||||
@@ -205,6 +206,26 @@ impl ExecCommandHandler {
|
||||
.clone()
|
||||
.map(Arc::new)
|
||||
.unwrap_or_else(|| session.user_shell());
|
||||
// TODO(anp): Resolve requested shells in remote environments instead of restricting
|
||||
// commands to the reported default shell.
|
||||
if environment.is_remote()
|
||||
&& let Some(requested_shell) = args.shell.take()
|
||||
{
|
||||
let Some(remote_shell) = turn_environment.shell.as_ref() else {
|
||||
return Err(FunctionCallError::RespondToModel(format!(
|
||||
"environment `{}` does not report a shell",
|
||||
turn_environment.environment_id
|
||||
)));
|
||||
};
|
||||
if detect_shell_type(Path::new(&requested_shell)) != Some(remote_shell.shell_type) {
|
||||
return Err(FunctionCallError::RespondToModel(format!(
|
||||
"environment `{}` only supports `{}`",
|
||||
turn_environment.environment_id,
|
||||
remote_shell.name()
|
||||
)));
|
||||
}
|
||||
}
|
||||
let process_id = manager.allocate_process_id().await;
|
||||
let resolved_command = get_command(
|
||||
&args,
|
||||
shell,
|
||||
|
||||
Reference in New Issue
Block a user