Skip to content

Make local environment optional in EnvironmentManager#23369

Merged
starr-openai merged 23 commits into
mainfrom
starr/optional-local-env-cand1
May 19, 2026
Merged

Make local environment optional in EnvironmentManager#23369
starr-openai merged 23 commits into
mainfrom
starr/optional-local-env-cand1

Conversation

@starr-openai
Copy link
Copy Markdown
Contributor

Summary

  • make EnvironmentManager local environment/runtime paths optional
  • simplify constructor surface around snapshot materialization
  • rename local env accessors to require_local_environment / try_local_environment

Validation

  • devbox Bazel build for touched crate surfaces
  • //codex-rs/exec-server:exec-server-unit-tests
  • //codex-rs/app-server-client:app-server-client-unit-tests
  • filtered touched //codex-rs/core:core-unit-tests cases

@starr-openai starr-openai force-pushed the starr/optional-local-env-cand1 branch from fef203d to 51e12c7 Compare May 19, 2026 00:54
@starr-openai starr-openai marked this pull request as ready for review May 19, 2026 05:36
@starr-openai starr-openai requested a review from a team as a code owner May 19, 2026 05:36
Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 49c3495b60

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codex-rs/codex-mcp/src/runtime.rs Outdated
Copy link
Copy Markdown
Collaborator

@jif-oai jif-oai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we mix a bit everything here? I feel like this PR is collapsion “is local selectable?”, “which env is selected/default?”, and “does this process still have host-local capability at all?”
Is it on purpose? I get that this is a temporary thing (right?)
I'm a bit worried on the blast radius. Are we sure no prod clients + training won't be impacted?

@starr-openai
Copy link
Copy Markdown
Contributor Author

Don't we mix a bit everything here? I feel like this PR is collapsion “is local selectable?”, “which env is selected/default?”, and “does this process still have host-local capability at all?”
Is it on purpose? I get that this is a temporary thing (right?)
I'm a bit worried on the blast radius. Are we sure no prod clients + training won't be impacted?

This isn't temporary - if anything the current code is the temporary path due to the 'fallback to local' paths.

The purpose is to make 'local' environment truly optional, and if unset remove these fallback paths. Likewise, we want to shift towards no reliance on a 'default' environment, and instead always have a turn chosen or model selected (via tool call params) environment.

The startup configuration (environments.toml or CODEX_EXEC_SERVER_URL) determine which environments are available (including local), and what the default is. Wherever possible, our code is using / should switch to using the turn_environment - fallback to default is only for cases where we haven't connected selection logic yet. This PR is making it so we don't transparently fall back to local in cases where local was never configured in the first place.

@starr-openai starr-openai requested a review from jif-oai May 19, 2026 17:16
@starr-openai
Copy link
Copy Markdown
Contributor Author

Prod clients should be quite safe, since local env is enabled by default and we don't have any real remote client users yet.

)?;
let environment_manager = if loader_overrides.ignore_user_config {
EnvironmentManager::from_env(local_runtime_paths).await
EnvironmentManager::from_env(Some(local_runtime_paths)).await
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't hink local_runtime_paths should be optional. This is just wiring for sandbox when local runtime is available. It shouldn't be the signal on whether the local runtime is available or not.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ local_runtime_paths is only ever used to construct the local environment. If there is no local env, we don't need local_runtime_paths.

}

impl MessageProcessor {
fn fs_processor(&self) -> Result<&FsRequestProcessor, JSONRPCErrorError> {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in why do we need to make fs_processor conditional today?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if no local env, we should disable app-server fs/* apis

Comment thread codex-rs/exec-server/src/environment.rs Outdated
pub fn require_local_environment(&self) -> Arc<Environment> {
match self.try_local_environment() {
Some(environment) => environment,
None => panic!("local environment is not configured"),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should never ever panic.

HashMap::with_capacity(environments.len() + usize::from(include_local));
let local_environment = Arc::new(Environment::local(local_runtime_paths));
if include_local {
let local_environment = if include_local {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like how many ways to control the presence of local environment there is.

I'm even more convinced that EnvironmentProvider should be responsible for returning an instance of local Environment when it has it and local_environment method should just be a filter over the list of available environments.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If EnvironmentProvider creates local, then we need to either use a convention (e.g. 'local' environment id) or another param (e.g. 'is_local') on the return here to indicate which is which.

However, this is still clumsy - since now the creation and meaning of 'local' can vary across providers when 'local' env should always refer to the same thing regardless.

It's possible we wouldn't need to have 'local_environment' on EnvironmentManager at all if we provide a different way to access it for internal use-cases - e.g. the RuntimeCapabilities struct I was proposing yesterday.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another param (e.g. 'is_local')

We already have is_remote don't we?

}
// `thread/shellCommand` is app-server's local-host shell escape hatch,
// not the normal turn-selected shell tool path.
if self
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this check needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes - thread/shellCommand cannot run without a local env

Comment thread codex-rs/exec-server/src/environment.rs Outdated
Comment thread codex-rs/exec-server/src/environment.rs Outdated
}

#[cfg(test)]
mod tests {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it better for these to be integration tests?

let config = match server.launch() {
McpServerLaunch::Configured(config) => config.as_ref().clone(),
};
if let Some(reason) = runtime_environment.startup_unavailable_reason(server_name, &config) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have 2 places that interpret experimental_environment.

should startup_unavailable_reason return an environment to run on or an error?

we can remove extra defensive checks below.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have 2 places that interpret experimental_environment.

we honestly need to kill this and change the semantics here. MCP servers shouldn't be bool on/off remote, but should be made per env

@starr-openai starr-openai merged commit 5c43a64 into main May 19, 2026
31 checks passed
@starr-openai starr-openai deleted the starr/optional-local-env-cand1 branch May 19, 2026 19:55
@github-actions github-actions Bot locked and limited conversation to collaborators May 19, 2026
@starr-openai starr-openai restored the starr/optional-local-env-cand1 branch May 19, 2026 20:07
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants