Allow session configuration with codex agents (#39870)

## Why

`codex agents` rejected invocation-specific configuration, preventing the
dashboard from applying settings when starting a shared thread.

## What changed

- Accept interactive options such as model, approval, sandbox, search, working
  directory, and configuration overrides when opening the agents dashboard.
- Forward supported session-flag configuration into threads started through an
  embedded or remote app server, while excluding unrelated values.
- Continue to reject initial prompts and images, along with local provider and
  additional-directory settings that cannot be applied to a remote server.

## Testing

- Cover accepted dashboard options and rejected incompatible inputs.
- Verify that explicit feature and sandbox overrides reach shared threads in
  both embedded and remote modes.

GitOrigin-RevId: f10aa1e16ff62b49d55679e987d9e458438ba3f8
This commit is contained in:
Eric Traut
2026-08-21 06:02:19 +00:00
committed by copyberry
parent 9ab176f488
commit 44e95c857f
4 changed files with 195 additions and 29 deletions

View File

@@ -1092,25 +1092,31 @@ async fn cli_main(
let open_agents_overview = matches!(&subcommand, Some(Subcommand::Agents(_)));
match subcommand {
None | Some(Subcommand::Agents(_)) => {
prepend_config_flags(
&mut interactive.config_overrides,
root_config_overrides.clone(),
);
if open_agents_overview {
if !root_config_overrides.raw_overrides.is_empty()
|| root_strict_config
|| interactive.prompt.is_some()
|| !interactive.images.is_empty()
|| interactive.model.is_some()
|| interactive.oss
|| interactive.oss_provider.is_some()
|| interactive.config_profile_v2.is_some()
|| interactive.sandbox_mode.is_some()
|| interactive.dangerously_bypass_approvals_and_sandbox
|| interactive.bypass_hook_trust
|| interactive.cwd.is_some() && root_remote.is_none()
|| !interactive.add_dir.is_empty()
|| interactive.approval_policy.is_some()
|| interactive.web_search
if interactive.prompt.is_some() || !interactive.images.is_empty() {
anyhow::bail!("`codex agents` does not accept an initial prompt or images");
}
if root_remote.is_some()
&& (interactive.oss
|| interactive.oss_provider.is_some()
|| !interactive.add_dir.is_empty()
|| interactive
.config_overrides
.parse_overrides()
.map_err(anyhow::Error::msg)?
.iter()
.any(|(key, value)| {
key == "sandbox_workspace_write.writable_roots"
|| (key == "sandbox_workspace_write"
&& value.get("writable_roots").is_some())
}))
{
anyhow::bail!(
"`codex agents` cannot attach to shared sessions with invocation-specific configuration overrides"
"`codex agents` cannot apply local provider or additional-directory overrides to a remote server"
);
}
if is_workload_identity_selected() {
@@ -1128,10 +1134,6 @@ async fn cli_main(
}
interactive.agents_overview = true;
}
prepend_config_flags(
&mut interactive.config_overrides,
root_config_overrides.clone(),
);
let exit_info = run_interactive_tui(
interactive,
root_remote.clone(),

View File

@@ -33,19 +33,72 @@ foo = "bar"
}
#[test]
fn agents_reject_session_overrides_before_starting_the_daemon() -> Result<()> {
fn agents_accept_interactive_configuration_overrides() -> Result<()> {
let codex_home = TempDir::new()?;
for args in [
["-c", "features.multi_agent_mode=true", "agents"].as_slice(),
["--enable", "multi_agent_mode", "agents"].as_slice(),
["--yolo", "agents"].as_slice(),
["--search", "agents"].as_slice(),
["--model", "gpt-5", "agents"].as_slice(),
["--approve-for-me", "agents"].as_slice(),
["--cd", ".", "agents"].as_slice(),
] {
let mut cmd = codex_command(codex_home.path())?;
cmd.env("TERM", "xterm-256color").args(args);
#[cfg(not(unix))]
cmd.args(["--remote", "ws://127.0.0.1:4512"]);
cmd.assert()
.failure()
.stderr(contains("stdin is not a terminal"));
}
Ok(())
}
#[test]
fn agents_reject_inputs_that_cannot_be_applied() -> Result<()> {
let codex_home = TempDir::new()?;
for (args, expected_error) in [
(
["--image=image.png", "agents"].as_slice(),
"does not accept an initial prompt or images",
),
(
["--oss", "agents", "--remote", "ws://127.0.0.1:4512"].as_slice(),
"cannot apply local provider or additional-directory overrides",
),
(
[
"--add-dir",
".",
"agents",
"--remote",
"ws://127.0.0.1:4512",
]
.as_slice(),
"cannot apply local provider or additional-directory overrides",
),
(
[
"-c",
"sandbox_workspace_write.writable_roots=[\"../shared\"]",
"agents",
"--remote",
"ws://127.0.0.1:4512",
]
.as_slice(),
"cannot apply local provider or additional-directory overrides",
),
] {
let mut cmd = codex_command(codex_home.path())?;
cmd.args(args)
.assert()
.failure()
.stderr(contains("invocation-specific configuration overrides"));
.stderr(contains(expected_error));
}
Ok(())