mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Support remote exec cwd in TUI startup (#17142)
When running with remote executor the cwd is the remote path. Today we check for existence of a local directory on startup and attempt to load config from it. For remote executors don't do that.
This commit is contained in:
committed by
GitHub
Unverified
parent
f383cc980d
commit
e4d6702b87
Generated
+1
@@ -1505,6 +1505,7 @@ dependencies = [
|
||||
"codex-app-server-protocol",
|
||||
"codex-arg0",
|
||||
"codex-core",
|
||||
"codex-exec-server",
|
||||
"codex-feedback",
|
||||
"codex-protocol",
|
||||
"futures",
|
||||
|
||||
@@ -16,6 +16,7 @@ codex-app-server = { workspace = true }
|
||||
codex-app-server-protocol = { workspace = true }
|
||||
codex-arg0 = { workspace = true }
|
||||
codex-core = { workspace = true }
|
||||
codex-exec-server = { workspace = true }
|
||||
codex-feedback = { workspace = true }
|
||||
codex-protocol = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
|
||||
@@ -43,6 +43,7 @@ use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config_loader::CloudRequirementsLoader;
|
||||
use codex_core::config_loader::LoaderOverrides;
|
||||
pub use codex_exec_server::EnvironmentManager;
|
||||
use codex_feedback::CodexFeedback;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use serde::de::DeserializeOwned;
|
||||
@@ -268,6 +269,8 @@ pub struct InProcessClientStartArgs {
|
||||
pub cloud_requirements: CloudRequirementsLoader,
|
||||
/// Feedback sink used by app-server/core telemetry and logs.
|
||||
pub feedback: CodexFeedback,
|
||||
/// Environment manager used by core execution and filesystem operations.
|
||||
pub environment_manager: Arc<EnvironmentManager>,
|
||||
/// Startup warnings emitted after initialize succeeds.
|
||||
pub config_warnings: Vec<ConfigWarningNotification>,
|
||||
/// Session source recorded in app-server thread metadata.
|
||||
@@ -317,6 +320,7 @@ impl InProcessClientStartArgs {
|
||||
loader_overrides: self.loader_overrides,
|
||||
cloud_requirements: self.cloud_requirements,
|
||||
feedback: self.feedback,
|
||||
environment_manager: self.environment_manager,
|
||||
config_warnings: self.config_warnings,
|
||||
session_source: self.session_source,
|
||||
enable_codex_api_key_env: self.enable_codex_api_key_env,
|
||||
@@ -893,6 +897,7 @@ mod tests {
|
||||
loader_overrides: LoaderOverrides::default(),
|
||||
cloud_requirements: CloudRequirementsLoader::default(),
|
||||
feedback: CodexFeedback::new(),
|
||||
environment_manager: Arc::new(EnvironmentManager::new(/*exec_server_url*/ None)),
|
||||
config_warnings: Vec::new(),
|
||||
session_source,
|
||||
enable_codex_api_key_env: false,
|
||||
@@ -1891,8 +1896,11 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn runtime_start_args_leave_manager_bootstrap_to_app_server() {
|
||||
async fn runtime_start_args_forward_environment_manager() {
|
||||
let config = Arc::new(build_test_config().await);
|
||||
let environment_manager = Arc::new(EnvironmentManager::new(Some(
|
||||
"ws://127.0.0.1:8765".to_string(),
|
||||
)));
|
||||
|
||||
let runtime_args = InProcessClientStartArgs {
|
||||
arg0_paths: Arg0DispatchPaths::default(),
|
||||
@@ -1901,6 +1909,7 @@ mod tests {
|
||||
loader_overrides: LoaderOverrides::default(),
|
||||
cloud_requirements: CloudRequirementsLoader::default(),
|
||||
feedback: CodexFeedback::new(),
|
||||
environment_manager: environment_manager.clone(),
|
||||
config_warnings: Vec::new(),
|
||||
session_source: SessionSource::Exec,
|
||||
enable_codex_api_key_env: false,
|
||||
@@ -1913,6 +1922,11 @@ mod tests {
|
||||
.into_runtime_start_args();
|
||||
|
||||
assert_eq!(runtime_args.config, config);
|
||||
assert!(Arc::ptr_eq(
|
||||
&runtime_args.environment_manager,
|
||||
&environment_manager
|
||||
));
|
||||
assert!(runtime_args.environment_manager.is_remote());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -117,6 +117,8 @@ pub struct InProcessStartArgs {
|
||||
pub cloud_requirements: CloudRequirementsLoader,
|
||||
/// Feedback sink used by app-server/core telemetry and logs.
|
||||
pub feedback: CodexFeedback,
|
||||
/// Environment manager used by core execution and filesystem operations.
|
||||
pub environment_manager: Arc<EnvironmentManager>,
|
||||
/// Startup warnings emitted after initialize succeeds.
|
||||
pub config_warnings: Vec<ConfigWarningNotification>,
|
||||
/// Session source stamped into thread/session metadata.
|
||||
@@ -388,7 +390,7 @@ fn start_uninitialized(args: InProcessStartArgs) -> InProcessClientHandle {
|
||||
outgoing: Arc::clone(&processor_outgoing),
|
||||
arg0_paths: args.arg0_paths,
|
||||
config: args.config,
|
||||
environment_manager: Arc::new(EnvironmentManager::from_env()),
|
||||
environment_manager: args.environment_manager,
|
||||
cli_overrides: args.cli_overrides,
|
||||
loader_overrides: args.loader_overrides,
|
||||
cloud_requirements: args.cloud_requirements,
|
||||
@@ -721,6 +723,7 @@ mod tests {
|
||||
loader_overrides: LoaderOverrides::default(),
|
||||
cloud_requirements: CloudRequirementsLoader::default(),
|
||||
feedback: CodexFeedback::new(),
|
||||
environment_manager: Arc::new(EnvironmentManager::new(/*exec_server_url*/ None)),
|
||||
config_warnings: Vec::new(),
|
||||
session_source,
|
||||
enable_codex_api_key_env: false,
|
||||
|
||||
@@ -811,12 +811,12 @@ impl Config {
|
||||
/// applied yet, which risks failing to enforce required constraints.
|
||||
pub async fn load_config_as_toml_with_cli_overrides(
|
||||
codex_home: &Path,
|
||||
cwd: &AbsolutePathBuf,
|
||||
cwd: Option<&AbsolutePathBuf>,
|
||||
cli_overrides: Vec<(String, TomlValue)>,
|
||||
) -> std::io::Result<ConfigToml> {
|
||||
let config_layer_stack = load_config_layers_state(
|
||||
codex_home,
|
||||
Some(cwd.clone()),
|
||||
cwd.cloned(),
|
||||
&cli_overrides,
|
||||
LoaderOverrides::default(),
|
||||
CloudRequirementsLoader::default(),
|
||||
|
||||
@@ -69,6 +69,11 @@ impl EnvironmentManager {
|
||||
self.exec_server_url.as_deref()
|
||||
}
|
||||
|
||||
/// Returns true when this manager is configured to use a remote exec server.
|
||||
pub fn is_remote(&self) -> bool {
|
||||
self.exec_server_url.is_some()
|
||||
}
|
||||
|
||||
/// Returns the cached environment, creating it on first access.
|
||||
pub async fn current(&self) -> Result<Option<Arc<Environment>>, ExecServerError> {
|
||||
self.current_environment
|
||||
@@ -227,6 +232,7 @@ mod tests {
|
||||
|
||||
assert!(!manager.disabled);
|
||||
assert_eq!(manager.exec_server_url(), None);
|
||||
assert!(!manager.is_remote());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -235,6 +241,15 @@ mod tests {
|
||||
|
||||
assert!(manager.disabled);
|
||||
assert_eq!(manager.exec_server_url(), None);
|
||||
assert!(!manager.is_remote());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn environment_manager_reports_remote_url() {
|
||||
let manager = EnvironmentManager::new(Some("ws://127.0.0.1:8765".to_string()));
|
||||
|
||||
assert!(manager.is_remote());
|
||||
assert_eq!(manager.exec_server_url(), Some("ws://127.0.0.1:8765"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -14,6 +14,7 @@ pub use cli::Cli;
|
||||
pub use cli::Command;
|
||||
pub use cli::ReviewArgs;
|
||||
use codex_app_server_client::DEFAULT_IN_PROCESS_CHANNEL_CAPACITY;
|
||||
use codex_app_server_client::EnvironmentManager;
|
||||
use codex_app_server_client::InProcessAppServerClient;
|
||||
use codex_app_server_client::InProcessClientStartArgs;
|
||||
use codex_app_server_client::InProcessServerEvent;
|
||||
@@ -293,7 +294,7 @@ pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result
|
||||
#[allow(clippy::print_stderr)]
|
||||
let config_toml = match load_config_as_toml_with_cli_overrides(
|
||||
&codex_home,
|
||||
&config_cwd,
|
||||
Some(&config_cwd),
|
||||
cli_kv_overrides.clone(),
|
||||
)
|
||||
.await
|
||||
@@ -471,6 +472,7 @@ pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result
|
||||
loader_overrides: run_loader_overrides,
|
||||
cloud_requirements: run_cloud_requirements,
|
||||
feedback: CodexFeedback::new(),
|
||||
environment_manager: std::sync::Arc::new(EnvironmentManager::from_env()),
|
||||
config_warnings,
|
||||
session_source: SessionSource::Exec,
|
||||
enable_codex_api_key_env: true,
|
||||
|
||||
@@ -96,6 +96,7 @@ use codex_core::config_loader::ConfigLayerStackOrdering;
|
||||
use codex_core::lookup_message_history_entry;
|
||||
#[cfg(target_os = "windows")]
|
||||
use codex_core::windows_sandbox::WindowsSandboxLevelExt;
|
||||
use codex_exec_server::EnvironmentManager;
|
||||
use codex_features::Feature;
|
||||
use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig;
|
||||
use codex_models_manager::model_presets::HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG;
|
||||
@@ -979,6 +980,7 @@ pub(crate) struct App {
|
||||
pub(crate) backtrack_render_pending: bool,
|
||||
pub(crate) feedback: codex_feedback::CodexFeedback,
|
||||
feedback_audience: FeedbackAudience,
|
||||
environment_manager: Arc<EnvironmentManager>,
|
||||
remote_app_server_url: Option<String>,
|
||||
remote_app_server_auth_token: Option<String>,
|
||||
/// Set when the user confirms an update; propagated on exit.
|
||||
@@ -3595,6 +3597,7 @@ impl App {
|
||||
should_prompt_windows_sandbox_nux_at_startup: bool,
|
||||
remote_app_server_url: Option<String>,
|
||||
remote_app_server_auth_token: Option<String>,
|
||||
environment_manager: Arc<EnvironmentManager>,
|
||||
) -> Result<AppExitInfo> {
|
||||
use tokio_stream::StreamExt;
|
||||
let (app_event_tx, mut app_event_rx) = unbounded_channel();
|
||||
@@ -3807,6 +3810,7 @@ impl App {
|
||||
backtrack_render_pending: false,
|
||||
feedback: feedback.clone(),
|
||||
feedback_audience,
|
||||
environment_manager,
|
||||
remote_app_server_url,
|
||||
remote_app_server_auth_token,
|
||||
pending_update_action: None,
|
||||
@@ -4068,6 +4072,7 @@ impl App {
|
||||
},
|
||||
None => crate::AppServerTarget::Embedded,
|
||||
},
|
||||
self.environment_manager.clone(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
@@ -9199,6 +9204,7 @@ guardian_approval = true
|
||||
backtrack_render_pending: false,
|
||||
feedback: codex_feedback::CodexFeedback::new(),
|
||||
feedback_audience: FeedbackAudience::External,
|
||||
environment_manager: Arc::new(EnvironmentManager::new(/*exec_server_url*/ None)),
|
||||
remote_app_server_url: None,
|
||||
remote_app_server_auth_token: None,
|
||||
pending_update_action: None,
|
||||
@@ -9253,6 +9259,9 @@ guardian_approval = true
|
||||
backtrack_render_pending: false,
|
||||
feedback: codex_feedback::CodexFeedback::new(),
|
||||
feedback_audience: FeedbackAudience::External,
|
||||
environment_manager: Arc::new(EnvironmentManager::new(
|
||||
/*exec_server_url*/ None,
|
||||
)),
|
||||
remote_app_server_url: None,
|
||||
remote_app_server_auth_token: None,
|
||||
pending_update_action: None,
|
||||
|
||||
+66
-14
@@ -37,6 +37,7 @@ use codex_core::format_exec_policy_error_with_source;
|
||||
use codex_core::path_utils;
|
||||
use codex_core::read_session_meta_line;
|
||||
use codex_core::windows_sandbox::WindowsSandboxLevelExt;
|
||||
use codex_exec_server::EnvironmentManager;
|
||||
use codex_login::AuthConfig;
|
||||
use codex_login::default_client::set_default_client_residency_requirement;
|
||||
use codex_login::enforce_login_restrictions;
|
||||
@@ -238,6 +239,7 @@ async fn start_embedded_app_server(
|
||||
loader_overrides: LoaderOverrides,
|
||||
cloud_requirements: CloudRequirementsLoader,
|
||||
feedback: codex_feedback::CodexFeedback,
|
||||
environment_manager: Arc<EnvironmentManager>,
|
||||
) -> color_eyre::Result<InProcessAppServerClient> {
|
||||
start_embedded_app_server_with(
|
||||
arg0_paths,
|
||||
@@ -246,6 +248,7 @@ async fn start_embedded_app_server(
|
||||
loader_overrides,
|
||||
cloud_requirements,
|
||||
feedback,
|
||||
environment_manager,
|
||||
InProcessAppServerClient::start,
|
||||
)
|
||||
.await
|
||||
@@ -352,6 +355,7 @@ async fn connect_remote_app_server(
|
||||
Ok(AppServerClient::Remote(app_server))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn start_app_server(
|
||||
target: &AppServerTarget,
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
@@ -360,6 +364,7 @@ async fn start_app_server(
|
||||
loader_overrides: LoaderOverrides,
|
||||
cloud_requirements: CloudRequirementsLoader,
|
||||
feedback: codex_feedback::CodexFeedback,
|
||||
environment_manager: Arc<EnvironmentManager>,
|
||||
) -> color_eyre::Result<AppServerClient> {
|
||||
match target {
|
||||
AppServerTarget::Embedded => start_embedded_app_server(
|
||||
@@ -369,6 +374,7 @@ async fn start_app_server(
|
||||
loader_overrides,
|
||||
cloud_requirements,
|
||||
feedback,
|
||||
environment_manager,
|
||||
)
|
||||
.await
|
||||
.map(AppServerClient::InProcess),
|
||||
@@ -382,6 +388,7 @@ async fn start_app_server(
|
||||
pub(crate) async fn start_app_server_for_picker(
|
||||
config: &Config,
|
||||
target: &AppServerTarget,
|
||||
environment_manager: Arc<EnvironmentManager>,
|
||||
) -> color_eyre::Result<AppServerSession> {
|
||||
let app_server = start_app_server(
|
||||
target,
|
||||
@@ -391,6 +398,7 @@ pub(crate) async fn start_app_server_for_picker(
|
||||
LoaderOverrides::default(),
|
||||
CloudRequirementsLoader::default(),
|
||||
codex_feedback::CodexFeedback::new(),
|
||||
environment_manager,
|
||||
)
|
||||
.await?;
|
||||
Ok(AppServerSession::new(app_server))
|
||||
@@ -400,9 +408,15 @@ pub(crate) async fn start_app_server_for_picker(
|
||||
pub(crate) async fn start_embedded_app_server_for_picker(
|
||||
config: &Config,
|
||||
) -> color_eyre::Result<AppServerSession> {
|
||||
start_app_server_for_picker(config, &AppServerTarget::Embedded).await
|
||||
start_app_server_for_picker(
|
||||
config,
|
||||
&AppServerTarget::Embedded,
|
||||
Arc::new(EnvironmentManager::new(/*exec_server_url*/ None)),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn start_embedded_app_server_with<F, Fut>(
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
config: Config,
|
||||
@@ -410,6 +424,7 @@ async fn start_embedded_app_server_with<F, Fut>(
|
||||
loader_overrides: LoaderOverrides,
|
||||
cloud_requirements: CloudRequirementsLoader,
|
||||
feedback: codex_feedback::CodexFeedback,
|
||||
environment_manager: Arc<EnvironmentManager>,
|
||||
start_client: F,
|
||||
) -> color_eyre::Result<InProcessAppServerClient>
|
||||
where
|
||||
@@ -433,6 +448,7 @@ where
|
||||
loader_overrides,
|
||||
cloud_requirements,
|
||||
feedback,
|
||||
environment_manager,
|
||||
config_warnings,
|
||||
session_source: codex_protocol::protocol::SessionSource::Cli,
|
||||
enable_codex_api_key_env: false,
|
||||
@@ -590,15 +606,19 @@ fn latest_session_lookup_params(
|
||||
fn config_cwd_for_app_server_target(
|
||||
cwd: Option<&Path>,
|
||||
app_server_target: &AppServerTarget,
|
||||
) -> std::io::Result<AbsolutePathBuf> {
|
||||
if matches!(app_server_target, AppServerTarget::Remote { .. }) {
|
||||
return AbsolutePathBuf::current_dir();
|
||||
environment_manager: &EnvironmentManager,
|
||||
) -> std::io::Result<Option<AbsolutePathBuf>> {
|
||||
if environment_manager.is_remote()
|
||||
|| matches!(app_server_target, AppServerTarget::Remote { .. })
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
match cwd {
|
||||
let cwd = match cwd {
|
||||
Some(path) => AbsolutePathBuf::from_absolute_path(path.canonicalize()?),
|
||||
None => AbsolutePathBuf::current_dir(),
|
||||
}
|
||||
}?;
|
||||
Ok(Some(cwd))
|
||||
}
|
||||
|
||||
fn latest_session_cwd_filter<'a>(
|
||||
@@ -689,13 +709,15 @@ pub async fn run_main(
|
||||
}
|
||||
};
|
||||
|
||||
let environment_manager = Arc::new(EnvironmentManager::from_env());
|
||||
let cwd = cli.cwd.clone();
|
||||
let config_cwd = config_cwd_for_app_server_target(cwd.as_deref(), &app_server_target)?;
|
||||
let config_cwd =
|
||||
config_cwd_for_app_server_target(cwd.as_deref(), &app_server_target, &environment_manager)?;
|
||||
|
||||
#[allow(clippy::print_stderr)]
|
||||
let config_toml = match load_config_as_toml_with_cli_overrides(
|
||||
&codex_home,
|
||||
&config_cwd,
|
||||
config_cwd.as_ref(),
|
||||
cli_kv_overrides.clone(),
|
||||
)
|
||||
.await
|
||||
@@ -952,6 +974,7 @@ pub async fn run_main(
|
||||
feedback,
|
||||
remote_url,
|
||||
remote_auth_token,
|
||||
environment_manager,
|
||||
)
|
||||
.await
|
||||
.map_err(|err| std::io::Error::other(err.to_string()))
|
||||
@@ -971,6 +994,7 @@ async fn run_ratatui_app(
|
||||
feedback: codex_feedback::CodexFeedback,
|
||||
remote_url: Option<String>,
|
||||
remote_auth_token: Option<String>,
|
||||
environment_manager: Arc<EnvironmentManager>,
|
||||
) -> color_eyre::Result<AppExitInfo> {
|
||||
let remote_mode = matches!(&app_server_target, AppServerTarget::Remote { .. });
|
||||
color_eyre::install()?;
|
||||
@@ -1026,6 +1050,7 @@ async fn run_ratatui_app(
|
||||
loader_overrides.clone(),
|
||||
cloud_requirements.clone(),
|
||||
feedback.clone(),
|
||||
environment_manager.clone(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
@@ -1351,6 +1376,7 @@ async fn run_ratatui_app(
|
||||
loader_overrides,
|
||||
cloud_requirements.clone(),
|
||||
feedback.clone(),
|
||||
environment_manager.clone(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
@@ -1379,6 +1405,7 @@ async fn run_ratatui_app(
|
||||
should_prompt_windows_sandbox_nux_at_startup,
|
||||
remote_url,
|
||||
remote_auth_token,
|
||||
environment_manager,
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -1697,6 +1724,7 @@ mod tests {
|
||||
use codex_protocol::protocol::SessionMetaLine;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::TurnContextItem;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
use tempfile::TempDir;
|
||||
|
||||
@@ -1717,6 +1745,7 @@ mod tests {
|
||||
LoaderOverrides::default(),
|
||||
CloudRequirementsLoader::default(),
|
||||
codex_feedback::CodexFeedback::new(),
|
||||
Arc::new(EnvironmentManager::new(/*exec_server_url*/ None)),
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -1865,8 +1894,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_cwd_for_app_server_target_uses_current_dir_for_remote_sessions() -> std::io::Result<()>
|
||||
{
|
||||
fn config_cwd_for_app_server_target_omits_cwd_for_remote_sessions() -> std::io::Result<()> {
|
||||
let remote_only_cwd = if cfg!(windows) {
|
||||
Path::new(r"C:\definitely\not\local\to\this\test")
|
||||
} else {
|
||||
@@ -1876,10 +1904,12 @@ mod tests {
|
||||
websocket_url: "ws://127.0.0.1:1234/".to_string(),
|
||||
auth_token: None,
|
||||
};
|
||||
let environment_manager = EnvironmentManager::new(/*exec_server_url*/ None);
|
||||
|
||||
let config_cwd = config_cwd_for_app_server_target(Some(remote_only_cwd), &target)?;
|
||||
let config_cwd =
|
||||
config_cwd_for_app_server_target(Some(remote_only_cwd), &target, &environment_manager)?;
|
||||
|
||||
assert_eq!(config_cwd, AbsolutePathBuf::current_dir()?);
|
||||
assert_eq!(config_cwd, None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1887,16 +1917,37 @@ mod tests {
|
||||
fn config_cwd_for_app_server_target_canonicalizes_embedded_cli_cwd() -> std::io::Result<()> {
|
||||
let temp_dir = TempDir::new()?;
|
||||
let target = AppServerTarget::Embedded;
|
||||
let environment_manager = EnvironmentManager::new(/*exec_server_url*/ None);
|
||||
|
||||
let config_cwd = config_cwd_for_app_server_target(Some(temp_dir.path()), &target)?;
|
||||
let config_cwd =
|
||||
config_cwd_for_app_server_target(Some(temp_dir.path()), &target, &environment_manager)?;
|
||||
|
||||
assert_eq!(
|
||||
config_cwd,
|
||||
AbsolutePathBuf::from_absolute_path(temp_dir.path().canonicalize()?)?
|
||||
Some(AbsolutePathBuf::from_absolute_path(
|
||||
temp_dir.path().canonicalize()?
|
||||
)?)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_cwd_for_app_server_target_omits_cwd_for_remote_exec_server() -> std::io::Result<()> {
|
||||
let remote_only_cwd = if cfg!(windows) {
|
||||
Path::new(r"C:\definitely\not\local\to\this\test")
|
||||
} else {
|
||||
Path::new("/definitely/not/local/to/this/test")
|
||||
};
|
||||
let target = AppServerTarget::Embedded;
|
||||
let environment_manager = EnvironmentManager::new(Some("ws://127.0.0.1:8765".to_string()));
|
||||
|
||||
let config_cwd =
|
||||
config_cwd_for_app_server_target(Some(remote_only_cwd), &target, &environment_manager)?;
|
||||
|
||||
assert_eq!(config_cwd, None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn read_session_cwd_returns_none_without_sqlite_or_rollout_path() -> std::io::Result<()> {
|
||||
let temp_dir = TempDir::new()?;
|
||||
@@ -2017,6 +2068,7 @@ mod tests {
|
||||
LoaderOverrides::default(),
|
||||
CloudRequirementsLoader::default(),
|
||||
codex_feedback::CodexFeedback::new(),
|
||||
Arc::new(EnvironmentManager::new(/*exec_server_url*/ None)),
|
||||
|_args| async { Err(std::io::Error::other("boom")) },
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -988,6 +988,9 @@ mod tests {
|
||||
"https://chatgpt.com/backend-api/".to_string(),
|
||||
),
|
||||
feedback: codex_feedback::CodexFeedback::new(),
|
||||
environment_manager: Arc::new(codex_app_server_client::EnvironmentManager::new(
|
||||
/*exec_server_url*/ None,
|
||||
)),
|
||||
config_warnings: Vec::new(),
|
||||
session_source: SessionSource::Cli,
|
||||
enable_codex_api_key_env: false,
|
||||
|
||||
@@ -28,6 +28,7 @@ remote_exec_server_start_timeout_seconds="${CODEX_REMOTE_EXEC_SERVER_START_TIMEO
|
||||
remote_exec_server_pid=''
|
||||
remote_exec_server_log_path=''
|
||||
remote_exec_server_pid_path=''
|
||||
remote_repo_root=''
|
||||
|
||||
cleanup() {
|
||||
local exit_code=$?
|
||||
@@ -119,6 +120,7 @@ while (( SECONDS < deadline )); do
|
||||
if [[ "${listen_url}" == ws://* ]]; then
|
||||
printf 'remote_exec_server_pid=%s\n' "${remote_exec_server_pid}"
|
||||
printf 'remote_exec_server_log_path=%s\n' "${remote_exec_server_log_path}"
|
||||
printf 'remote_repo_root=%s\n' "${remote_repo_root}"
|
||||
printf 'listen_url=%s\n' "${listen_url}"
|
||||
exit 0
|
||||
fi
|
||||
@@ -148,13 +150,16 @@ while IFS='=' read -r key value; do
|
||||
remote_exec_server_log_path)
|
||||
remote_exec_server_log_path="${value}"
|
||||
;;
|
||||
remote_repo_root)
|
||||
remote_repo_root="${value}"
|
||||
;;
|
||||
listen_url)
|
||||
listen_url="${value}"
|
||||
;;
|
||||
esac
|
||||
done <<< "${remote_start_output}"
|
||||
|
||||
if [[ -z "${remote_exec_server_pid}" || -z "${listen_url}" ]]; then
|
||||
if [[ -z "${remote_exec_server_pid}" || -z "${listen_url}" || -z "${remote_repo_root}" ]]; then
|
||||
echo "failed to parse remote exec server startup output" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -169,7 +174,9 @@ echo "Remote exec server: ${listen_url}"
|
||||
echo "Remote exec server log: ${remote_exec_server_log_path}"
|
||||
echo "Press Ctrl-C to stop the SSH tunnel and remote exec server."
|
||||
echo "Start codex via: "
|
||||
echo " CODEX_EXEC_SERVER_URL=ws://127.0.0.1:${local_exec_server_port} codex -C /tmp"
|
||||
printf ' CODEX_EXEC_SERVER_URL=ws://127.0.0.1:%s codex -C %q\n' \
|
||||
"${local_exec_server_port}" \
|
||||
"${remote_repo_root}"
|
||||
|
||||
ssh \
|
||||
-nNT \
|
||||
|
||||
Reference in New Issue
Block a user