## Why
App-server clients that configure named execution environments need to
discover an environment's shell and working directory before selecting
it for a thread or turn. Because the environment can run on a different
operating system than app-server, its working directory is represented
as a canonical `file:` URI rather than a host-local path string. The
probe also needs a bounded response time: an exec-server that completes
initialization but never answers `environment/info` must not hold the
environment serialization queue indefinitely.
## What changed
- Add an experimental `environment/info` app-server RPC for named
environments.
- Route the probe through the managed environment connection and return
target-native shell metadata plus the default working directory as a
`PathUri`.
- Return connection and protocol failures as JSON-RPC errors.
- Bound the exec-server probe response to 30 seconds and remove
timed-out calls from the pending-request table so later environment
mutations can proceed.
- Cover successful responses, omitted working directories, unknown
environments, connection failures, and pending-call cleanup.
## Protocol examples
Request:
```json
{
"id": 42,
"method": "environment/info",
"params": {
"environmentId": "remote-a"
}
}
```
Successful response:
```json
{
"id": 42,
"result": {
"shell": {
"name": "zsh",
"path": "/bin/zsh"
},
"cwd": "file:///workspace"
}
}
```
If the exec-server initializes but does not answer the probe within 30
seconds:
```json
{
"id": 42,
"error": {
"code": -32603,
"message": "failed to get info for environment `remote-a`: exec-server protocol error: timed out waiting for exec-server `environment/info` response after 30s"
}
}
```
## Testing
- App-server integration coverage for successful info (including omitted
`cwd`), unknown environments, and connection failures.
- Exec-server RPC coverage verifying a timed-out call is removed from
the pending-request table.
---------
Co-authored-by: Michael Bolin <mbolin@openai.com>
## Why
Remote environments registered through `environment/add` currently use
the fixed 10-second WebSocket connection timeout. Slow-starting
executors need a caller-selected connection window, but this should not
add retry policy or couple exec-server behavior to Core’s
`deferred_executor` feature.
Make the timeout an optional part of the existing experimental request.
Existing clients continue using the current default, while callers that
know an executor may take longer can request a larger window explicitly.
Depends on #28683.
## What changed
- Add optional `connectTimeoutMs` to `EnvironmentAddParams` and document
it in the app-server README.
- Pass the optional timeout through `EnvironmentRequestProcessor` into
one `EnvironmentManager::upsert_environment()` path; the manager applies
the existing default when it is omitted.
- Preserve the existing single-attempt lifecycle. The configured value
controls WebSocket connection and handshake time for both initial
connection and later reconnects; initialization retains its separate
timeout.
- Add an app-server integration test that sends the real JSON-RPC
request and verifies a stalled handshake observes the requested timeout.
## Test plan
- `just test -p codex-app-server-protocol`
- `just test -p codex-exec-server`
- `just test -p codex-app-server
environment_add_applies_connect_timeout`
## Rollout
This is additive and does not enable `deferred_executor`. Callers should
send a non-default timeout only after a compatible app-server is
deployed; omitted or `null` values retain the existing 10-second
default.
## Summary
Support registry-backed remote executors end to end so downstream
services can resolve an executor id into an exec-server URL and make
that environment available to Codex without relying on the legacy cloud
environments flow.
## What changed
- switch remote executor registration to the executor registry bootstrap
contract
- allow named remote environments to be inserted into
`EnvironmentManager` at runtime
- add the experimental app-server RPC `environment/add` so initialized
experimental clients can register those remote environments for later
`thread/start` and `turn/start` selection
## Validation
Ran focused validation locally:
- `cargo test -p codex-exec-server environment_manager_`
- `cargo test -p codex-exec-server
register_executor_posts_with_bearer_token_header`
- `cargo test -p codex-app-server-protocol`