Skip to content

Commit 11d4f3f

Browse files
celia-oaibolinfest
andauthored
[app-server] fix config loading for conversations (#8765)
Currently we don't load config properly for app server conversations. see: https://linear.app/openai/issue/CODEX-3956/config-flags-not-respected-in-codex-app-server. This PR fixes that by respecting the config passed in. Tested by running `cargo build -p codex-cli && RUST_LOG=codex_app_server=debug CODEX_BIN=target/debug/codex cargo run -p codex-app-server-test-client -- \ --config model_providers.mock_provider.base_url=\"http://localhost:4010/v2\" \ --config model_provider=\"mock_provider\" \ --config model_providers.mock_provider.name="hello" \ send-message-v2 "hello"` and verified that the mock_provider is called instead of default provider. #closes https://linear.app/openai/issue/CODEX-3956/config-flags-not-respected-in-codex-app-server --------- Co-authored-by: Michael Bolin <mbolin@openai.com>
1 parent 8b7ec31 commit 11d4f3f

File tree

2 files changed

+149
-65
lines changed

2 files changed

+149
-65
lines changed

codex-rs/app-server-test-client/src/main.rs

Lines changed: 77 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::time::Duration;
1313
use anyhow::Context;
1414
use anyhow::Result;
1515
use anyhow::bail;
16+
use clap::ArgAction;
1617
use clap::Parser;
1718
use clap::Subcommand;
1819
use codex_app_server_protocol::AddConversationListenerParams;
@@ -67,6 +68,19 @@ struct Cli {
6768
#[arg(long, env = "CODEX_BIN", default_value = "codex")]
6869
codex_bin: String,
6970

71+
/// Forwarded to the `codex` CLI as `--config key=value`. Repeatable.
72+
///
73+
/// Example:
74+
/// `--config 'model_providers.mock.base_url="http://localhost:4010/v2"'`
75+
#[arg(
76+
short = 'c',
77+
long = "config",
78+
value_name = "key=value",
79+
action = ArgAction::Append,
80+
global = true
81+
)]
82+
config_overrides: Vec<String>,
83+
7084
#[command(subcommand)]
7185
command: CliCommand,
7286
}
@@ -121,30 +135,43 @@ enum CliCommand {
121135
}
122136

123137
fn main() -> Result<()> {
124-
let Cli { codex_bin, command } = Cli::parse();
138+
let Cli {
139+
codex_bin,
140+
config_overrides,
141+
command,
142+
} = Cli::parse();
125143

126144
match command {
127-
CliCommand::SendMessage { user_message } => send_message(codex_bin, user_message),
128-
CliCommand::SendMessageV2 { user_message } => send_message_v2(codex_bin, user_message),
145+
CliCommand::SendMessage { user_message } => {
146+
send_message(&codex_bin, &config_overrides, user_message)
147+
}
148+
CliCommand::SendMessageV2 { user_message } => {
149+
send_message_v2(&codex_bin, &config_overrides, user_message)
150+
}
129151
CliCommand::TriggerCmdApproval { user_message } => {
130-
trigger_cmd_approval(codex_bin, user_message)
152+
trigger_cmd_approval(&codex_bin, &config_overrides, user_message)
131153
}
132154
CliCommand::TriggerPatchApproval { user_message } => {
133-
trigger_patch_approval(codex_bin, user_message)
155+
trigger_patch_approval(&codex_bin, &config_overrides, user_message)
134156
}
135-
CliCommand::NoTriggerCmdApproval => no_trigger_cmd_approval(codex_bin),
157+
CliCommand::NoTriggerCmdApproval => no_trigger_cmd_approval(&codex_bin, &config_overrides),
136158
CliCommand::SendFollowUpV2 {
137159
first_message,
138160
follow_up_message,
139-
} => send_follow_up_v2(codex_bin, first_message, follow_up_message),
140-
CliCommand::TestLogin => test_login(codex_bin),
141-
CliCommand::GetAccountRateLimits => get_account_rate_limits(codex_bin),
142-
CliCommand::ModelList => model_list(codex_bin),
161+
} => send_follow_up_v2(
162+
&codex_bin,
163+
&config_overrides,
164+
first_message,
165+
follow_up_message,
166+
),
167+
CliCommand::TestLogin => test_login(&codex_bin, &config_overrides),
168+
CliCommand::GetAccountRateLimits => get_account_rate_limits(&codex_bin, &config_overrides),
169+
CliCommand::ModelList => model_list(&codex_bin, &config_overrides),
143170
}
144171
}
145172

146-
fn send_message(codex_bin: String, user_message: String) -> Result<()> {
147-
let mut client = CodexClient::spawn(codex_bin)?;
173+
fn send_message(codex_bin: &str, config_overrides: &[String], user_message: String) -> Result<()> {
174+
let mut client = CodexClient::spawn(codex_bin, config_overrides)?;
148175

149176
let initialize = client.initialize()?;
150177
println!("< initialize response: {initialize:?}");
@@ -165,46 +192,61 @@ fn send_message(codex_bin: String, user_message: String) -> Result<()> {
165192
Ok(())
166193
}
167194

168-
fn send_message_v2(codex_bin: String, user_message: String) -> Result<()> {
169-
send_message_v2_with_policies(codex_bin, user_message, None, None)
195+
fn send_message_v2(
196+
codex_bin: &str,
197+
config_overrides: &[String],
198+
user_message: String,
199+
) -> Result<()> {
200+
send_message_v2_with_policies(codex_bin, config_overrides, user_message, None, None)
170201
}
171202

172-
fn trigger_cmd_approval(codex_bin: String, user_message: Option<String>) -> Result<()> {
203+
fn trigger_cmd_approval(
204+
codex_bin: &str,
205+
config_overrides: &[String],
206+
user_message: Option<String>,
207+
) -> Result<()> {
173208
let default_prompt =
174209
"Run `touch /tmp/should-trigger-approval` so I can confirm the file exists.";
175210
let message = user_message.unwrap_or_else(|| default_prompt.to_string());
176211
send_message_v2_with_policies(
177212
codex_bin,
213+
config_overrides,
178214
message,
179215
Some(AskForApproval::OnRequest),
180216
Some(SandboxPolicy::ReadOnly),
181217
)
182218
}
183219

184-
fn trigger_patch_approval(codex_bin: String, user_message: Option<String>) -> Result<()> {
220+
fn trigger_patch_approval(
221+
codex_bin: &str,
222+
config_overrides: &[String],
223+
user_message: Option<String>,
224+
) -> Result<()> {
185225
let default_prompt =
186226
"Create a file named APPROVAL_DEMO.txt containing a short hello message using apply_patch.";
187227
let message = user_message.unwrap_or_else(|| default_prompt.to_string());
188228
send_message_v2_with_policies(
189229
codex_bin,
230+
config_overrides,
190231
message,
191232
Some(AskForApproval::OnRequest),
192233
Some(SandboxPolicy::ReadOnly),
193234
)
194235
}
195236

196-
fn no_trigger_cmd_approval(codex_bin: String) -> Result<()> {
237+
fn no_trigger_cmd_approval(codex_bin: &str, config_overrides: &[String]) -> Result<()> {
197238
let prompt = "Run `touch should_not_trigger_approval.txt`";
198-
send_message_v2_with_policies(codex_bin, prompt.to_string(), None, None)
239+
send_message_v2_with_policies(codex_bin, config_overrides, prompt.to_string(), None, None)
199240
}
200241

201242
fn send_message_v2_with_policies(
202-
codex_bin: String,
243+
codex_bin: &str,
244+
config_overrides: &[String],
203245
user_message: String,
204246
approval_policy: Option<AskForApproval>,
205247
sandbox_policy: Option<SandboxPolicy>,
206248
) -> Result<()> {
207-
let mut client = CodexClient::spawn(codex_bin)?;
249+
let mut client = CodexClient::spawn(codex_bin, config_overrides)?;
208250

209251
let initialize = client.initialize()?;
210252
println!("< initialize response: {initialize:?}");
@@ -228,11 +270,12 @@ fn send_message_v2_with_policies(
228270
}
229271

230272
fn send_follow_up_v2(
231-
codex_bin: String,
273+
codex_bin: &str,
274+
config_overrides: &[String],
232275
first_message: String,
233276
follow_up_message: String,
234277
) -> Result<()> {
235-
let mut client = CodexClient::spawn(codex_bin)?;
278+
let mut client = CodexClient::spawn(codex_bin, config_overrides)?;
236279

237280
let initialize = client.initialize()?;
238281
println!("< initialize response: {initialize:?}");
@@ -265,8 +308,8 @@ fn send_follow_up_v2(
265308
Ok(())
266309
}
267310

268-
fn test_login(codex_bin: String) -> Result<()> {
269-
let mut client = CodexClient::spawn(codex_bin)?;
311+
fn test_login(codex_bin: &str, config_overrides: &[String]) -> Result<()> {
312+
let mut client = CodexClient::spawn(codex_bin, config_overrides)?;
270313

271314
let initialize = client.initialize()?;
272315
println!("< initialize response: {initialize:?}");
@@ -295,8 +338,8 @@ fn test_login(codex_bin: String) -> Result<()> {
295338
}
296339
}
297340

298-
fn get_account_rate_limits(codex_bin: String) -> Result<()> {
299-
let mut client = CodexClient::spawn(codex_bin)?;
341+
fn get_account_rate_limits(codex_bin: &str, config_overrides: &[String]) -> Result<()> {
342+
let mut client = CodexClient::spawn(codex_bin, config_overrides)?;
300343

301344
let initialize = client.initialize()?;
302345
println!("< initialize response: {initialize:?}");
@@ -307,8 +350,8 @@ fn get_account_rate_limits(codex_bin: String) -> Result<()> {
307350
Ok(())
308351
}
309352

310-
fn model_list(codex_bin: String) -> Result<()> {
311-
let mut client = CodexClient::spawn(codex_bin)?;
353+
fn model_list(codex_bin: &str, config_overrides: &[String]) -> Result<()> {
354+
let mut client = CodexClient::spawn(codex_bin, config_overrides)?;
312355

313356
let initialize = client.initialize()?;
314357
println!("< initialize response: {initialize:?}");
@@ -327,8 +370,12 @@ struct CodexClient {
327370
}
328371

329372
impl CodexClient {
330-
fn spawn(codex_bin: String) -> Result<Self> {
331-
let mut codex_app_server = Command::new(&codex_bin)
373+
fn spawn(codex_bin: &str, config_overrides: &[String]) -> Result<Self> {
374+
let mut cmd = Command::new(codex_bin);
375+
for override_kv in config_overrides {
376+
cmd.arg("--config").arg(override_kv);
377+
}
378+
let mut codex_app_server = cmd
332379
.arg("app-server")
333380
.stdin(Stdio::piped())
334381
.stdout(Stdio::piped())

0 commit comments

Comments
 (0)