fix: project model and reasoning_effort into Codex CLI args, stop rewriting .codex/config.toml
- Add model_reasoning_effort field to AgentProfile (domain layer) - Remove model parameter from codex_config_toml, stop rewriting model in TOML - Pass model and model_reasoning_effort via Codex CLI -c overrides on every exec - Update CodexExecSession with new_with_policy_and_overrides factory - Cover new conversation and resume flows with tests
This commit is contained in:
@ -58,7 +58,7 @@ impl PermissionProjector for CodexPermissionProjector {
|
||||
// orthogonal and still gets an explicit env override to avoid stale inheritance.
|
||||
let Some(permissions) = eff else {
|
||||
return PermissionProjection {
|
||||
files: vec![codex_model_and_network_file(ctx, network)],
|
||||
files: vec![codex_network_file(network)],
|
||||
env: codex_network_env(network),
|
||||
..PermissionProjection::empty()
|
||||
};
|
||||
@ -67,15 +67,11 @@ impl PermissionProjector for CodexPermissionProjector {
|
||||
let approval = codex_approval_policy(permissions);
|
||||
let network_access = codex_network_access(network);
|
||||
|
||||
// Permission-only TOML fragment (escaped exactly like the former
|
||||
// `set_top_level_toml_value`). The mcp_servers/trust tables are NOT a
|
||||
// permission concern and stay with the MCP wiring (LP3-3).
|
||||
let mut contents = format!(
|
||||
"sandbox_mode = {}\napproval_policy = {}\n",
|
||||
toml_string(sandbox),
|
||||
toml_string(approval),
|
||||
);
|
||||
append_codex_model_config(&mut contents, ctx);
|
||||
contents.push_str(&format!(
|
||||
"\n[{}]\nnetwork_access = {}\n\n{}",
|
||||
SANDBOX_WORKSPACE_WRITE_TABLE, network_access, CODEX_CODE_MODE_FEATURES_TOML,
|
||||
@ -95,8 +91,8 @@ impl PermissionProjector for CodexPermissionProjector {
|
||||
PermissionProjection {
|
||||
files: vec![ProjectedFile::MergeToml {
|
||||
rel_path: CONFIG_REL_PATH.to_owned(),
|
||||
managed_tables: codex_managed_tables(ctx),
|
||||
managed_keys: codex_managed_keys(ctx, true),
|
||||
managed_tables: codex_managed_tables(),
|
||||
managed_keys: codex_managed_keys(true),
|
||||
contents,
|
||||
}],
|
||||
args,
|
||||
@ -110,53 +106,36 @@ impl PermissionProjector for CodexPermissionProjector {
|
||||
}
|
||||
}
|
||||
|
||||
fn codex_model_and_network_file(
|
||||
ctx: &ProjectionContext,
|
||||
network: Option<NetworkPolicy>,
|
||||
) -> ProjectedFile {
|
||||
let mut contents = String::new();
|
||||
append_codex_model_config(&mut contents, ctx);
|
||||
if !contents.is_empty() {
|
||||
contents.push('\n');
|
||||
}
|
||||
contents.push_str(&format!(
|
||||
fn codex_network_file(network: Option<NetworkPolicy>) -> ProjectedFile {
|
||||
let contents = format!(
|
||||
"[{}]\nnetwork_access = {}\n\n{}",
|
||||
SANDBOX_WORKSPACE_WRITE_TABLE,
|
||||
codex_network_access(network),
|
||||
CODEX_CODE_MODE_FEATURES_TOML,
|
||||
));
|
||||
);
|
||||
ProjectedFile::MergeToml {
|
||||
rel_path: CONFIG_REL_PATH.to_owned(),
|
||||
managed_tables: codex_managed_tables(ctx),
|
||||
managed_keys: codex_managed_keys(ctx, false),
|
||||
managed_tables: codex_managed_tables(),
|
||||
managed_keys: codex_managed_keys(false),
|
||||
contents,
|
||||
}
|
||||
}
|
||||
|
||||
fn codex_managed_keys(ctx: &ProjectionContext, include_permissions: bool) -> Vec<String> {
|
||||
fn codex_managed_keys(include_permissions: bool) -> Vec<String> {
|
||||
let mut keys = Vec::new();
|
||||
if include_permissions {
|
||||
keys.extend(PERMISSION_MANAGED_KEYS.iter().map(|k| (*k).to_owned()));
|
||||
}
|
||||
if ctx.model.is_some() {
|
||||
keys.push("model".to_owned());
|
||||
}
|
||||
keys
|
||||
}
|
||||
|
||||
fn codex_managed_tables(_ctx: &ProjectionContext) -> Vec<String> {
|
||||
fn codex_managed_tables() -> Vec<String> {
|
||||
vec![
|
||||
SANDBOX_WORKSPACE_WRITE_TABLE.to_owned(),
|
||||
CODEX_CODE_MODE_FEATURES_TABLE.to_owned(),
|
||||
]
|
||||
}
|
||||
|
||||
fn append_codex_model_config(contents: &mut String, ctx: &ProjectionContext) {
|
||||
if let Some(model) = ctx.model {
|
||||
contents.push_str(&format!("model = {}\n", toml_string(model)));
|
||||
}
|
||||
}
|
||||
|
||||
fn codex_network_env(network: Option<NetworkPolicy>) -> Vec<(String, String)> {
|
||||
// Codex inherits the parent environment by default. Always set the variable for
|
||||
// Codex launches so a stale `CODEX_SANDBOX_NETWORK_DISABLED=1` in IdeA's own
|
||||
@ -259,7 +238,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn model_projection_without_permissions_writes_only_model() {
|
||||
fn projection_without_permissions_writes_network_only_and_leaves_model_to_exec_args() {
|
||||
let ctx = ProjectionContext {
|
||||
project_root: "/proj",
|
||||
run_dir: "/run/agent",
|
||||
@ -274,10 +253,11 @@ mod tests {
|
||||
contents,
|
||||
..
|
||||
} => {
|
||||
assert!(managed_keys.contains(&"model".to_owned()));
|
||||
assert!(!managed_keys.contains(&"model".to_owned()));
|
||||
assert!(!managed_keys.contains(&"model_provider".to_owned()));
|
||||
assert_eq!(managed_tables, &expected_managed_tables());
|
||||
assert!(contents.contains("model = \"gpt-5\""), "{contents}");
|
||||
assert!(!contents.contains("model ="), "{contents}");
|
||||
assert!(contents.contains("[sandbox_workspace_write]"), "{contents}");
|
||||
assert!(!contents.contains("model_provider"), "{contents}");
|
||||
assert!(!contents.contains("model_providers"), "{contents}");
|
||||
assert!(!contents.contains("base_url"), "{contents}");
|
||||
|
||||
Reference in New Issue
Block a user