Add process-scoped PSP routing for ChatGPT requests (#36986)

## What changed

- Add a hidden global `--psp` runtime flag and propagate it through TUI, exec,
  app-server, remote-control, and in-process startup paths.
- Attach the `oai-chat-psp=true` cookie to first-party ChatGPT requests when
  enabled, using a cached cookie-aware client with sensitive request logging
  disabled.
- Keep the routing selection out of persistent configuration layers while
  preserving it across config refreshes and agent role changes.

## Testing

- Cover global flag parsing, app-server propagation, config-layer isolation,
  and preservation across config rebuilds and role changes.

GitOrigin-RevId: 05cdc61ffd7162d8e48fc1e166f4732113e5a816
This commit is contained in:
stevenlee-oai authored and copyberry committed 2026-08-04 22:23:40 +00:00
1 parent 411f3f0680
commit 1d952f027e
25 files changed
+199 -16

No files matched your search

+26
View File
@@ -104,6 +104,10 @@ use codex_terminal_detection::TerminalName;
override_usage = "codex [OPTIONS] [PROMPT]\n codex [OPTIONS] <COMMAND> [ARGS]"
)]
struct MultitoolCli {
/// Enable process-only PSP routing for first-party ChatGPT requests.
#[arg(long, global = true, hide = true)]
psp: bool,
#[clap(flatten)]
pub config_overrides: CliConfigOverrides,
@@ -977,12 +981,14 @@ async fn cli_main(
remote_control_disabled: bool,
) -> anyhow::Result<()> {
let MultitoolCli {
psp,
config_overrides: mut root_config_overrides,
feature_toggles,
remote,
mut interactive,
subcommand,
} = MultitoolCli::parse();
interactive.psp = psp;
// Fold --enable/--disable into config overrides so they flow to all subcommands.
let toggle_overrides = feature_toggles.to_overrides()?;
@@ -1022,6 +1028,7 @@ async fn cli_main(
exec_cli
.shared
.inherit_exec_root_options(&interactive.shared);
exec_cli.psp = psp;
exec_cli.strict_config |= root_strict_config;
prepend_config_flags(
&mut exec_cli.config_overrides,
@@ -1042,6 +1049,7 @@ async fn cli_main(
exec_cli
.shared
.inherit_exec_root_options(&interactive.shared);
exec_cli.psp = psp;
exec_cli.command = Some(ExecCommand::Review(review_args));
exec_cli.strict_config = strict_config || root_strict_config;
prepend_config_flags(
@@ -1151,6 +1159,7 @@ async fn cli_main(
codex_app_server::RemoteControlStartupMode::ResolvePersisted
}
},
psp,
..Default::default()
};
codex_app_server::run_main_with_transport_options(
@@ -1253,6 +1262,7 @@ async fn cli_main(
remote_control_cli,
arg0_paths.clone(),
root_config_overrides,
psp,
)
.await?;
}
@@ -2707,6 +2717,7 @@ mod tests {
fn finalize_resume_from_args(args: &[&str]) -> TuiCli {
let cli = MultitoolCli::try_parse_from(args).expect("parse");
let MultitoolCli {
psp: _,
mut interactive,
config_overrides: mut root_overrides,
subcommand,
@@ -2744,6 +2755,7 @@ mod tests {
fn finalize_fork_from_args(args: &[&str]) -> TuiCli {
let cli = MultitoolCli::try_parse_from(args).expect("parse");
let MultitoolCli {
psp: _,
mut interactive,
config_overrides: mut root_overrides,
subcommand,
@@ -2788,6 +2800,7 @@ mod tests {
fn finalize_archive_from_args(args: &[&str]) -> (String, TuiCli, InteractiveRemoteOptions) {
let cli = MultitoolCli::try_parse_from(args).expect("parse");
let MultitoolCli {
psp: _,
interactive,
config_overrides: root_overrides,
subcommand,
@@ -4016,6 +4029,19 @@ mod tests {
assert!(err.to_string().contains("is empty"));
}
#[test]
fn psp_is_a_global_runtime_argument() {
for args in [
["codex", "--psp"].as_slice(),
["codex", "app-server", "--psp"].as_slice(),
["codex", "remote-control", "--psp"].as_slice(),
] {
let cli = MultitoolCli::try_parse_from(args).expect("parse runtime PSP flag");
assert!(cli.psp);
assert!(cli.config_overrides.raw_overrides.is_empty());
}
}
#[test]
fn app_server_code_mode_host_url_parses_independently_of_listen_transport() {
let app_server = app_server_from_args(