mirror of
https://github.com/openai/codex.git
synced 2026-05-04 21:32:21 +03:00
Load agent metadata from role files (#14177)
This commit is contained in:
committed by
Michael Bolin
parent
3d41ff0b77
commit
a67660da2d
@@ -9,6 +9,7 @@
|
||||
use crate::config::AgentRoleConfig;
|
||||
use crate::config::Config;
|
||||
use crate::config::ConfigOverrides;
|
||||
use crate::config::agent_roles::parse_agent_role_file_contents;
|
||||
use crate::config::deserialize_config_toml_with_base;
|
||||
use crate::config_loader::ConfigLayerEntry;
|
||||
use crate::config_loader::ConfigLayerStack;
|
||||
@@ -46,26 +47,34 @@ pub(crate) async fn apply_role_to_config(
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let (role_config_contents, role_config_base) = if is_built_in {
|
||||
(
|
||||
built_in::config_file_contents(config_file)
|
||||
.map(str::to_owned)
|
||||
.ok_or_else(|| AGENT_TYPE_UNAVAILABLE_ERROR.to_string())?,
|
||||
config.codex_home.as_path(),
|
||||
)
|
||||
let (role_config_toml, role_config_base) = if is_built_in {
|
||||
let role_config_contents = built_in::config_file_contents(config_file)
|
||||
.map(str::to_owned)
|
||||
.ok_or_else(|| AGENT_TYPE_UNAVAILABLE_ERROR.to_string())?;
|
||||
let role_config_toml: TomlValue = toml::from_str(&role_config_contents)
|
||||
.map_err(|_| AGENT_TYPE_UNAVAILABLE_ERROR.to_string())?;
|
||||
(role_config_toml, config.codex_home.as_path())
|
||||
} else {
|
||||
let role_config_contents = tokio::fs::read_to_string(config_file)
|
||||
.await
|
||||
.map_err(|_| AGENT_TYPE_UNAVAILABLE_ERROR.to_string())?;
|
||||
let role_config_toml = parse_agent_role_file_contents(
|
||||
&role_config_contents,
|
||||
config_file,
|
||||
config_file
|
||||
.parent()
|
||||
.ok_or_else(|| AGENT_TYPE_UNAVAILABLE_ERROR.to_string())?,
|
||||
Some(role_name),
|
||||
)
|
||||
.map_err(|_| AGENT_TYPE_UNAVAILABLE_ERROR.to_string())?
|
||||
.config;
|
||||
(
|
||||
tokio::fs::read_to_string(config_file)
|
||||
.await
|
||||
.map_err(|_| AGENT_TYPE_UNAVAILABLE_ERROR.to_string())?,
|
||||
role_config_toml,
|
||||
config_file
|
||||
.parent()
|
||||
.ok_or_else(|| AGENT_TYPE_UNAVAILABLE_ERROR.to_string())?,
|
||||
)
|
||||
};
|
||||
|
||||
let role_config_toml: TomlValue = toml::from_str(&role_config_contents)
|
||||
.map_err(|_| AGENT_TYPE_UNAVAILABLE_ERROR.to_string())?;
|
||||
deserialize_config_toml_with_base(role_config_toml.clone(), role_config_base)
|
||||
.map_err(|_| AGENT_TYPE_UNAVAILABLE_ERROR.to_string())?;
|
||||
let role_layer_toml = resolve_relative_paths_in_config_toml(role_config_toml, role_config_base)
|
||||
@@ -391,6 +400,37 @@ mod tests {
|
||||
assert_eq!(err, AGENT_TYPE_UNAVAILABLE_ERROR);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn apply_role_ignores_agent_metadata_fields_in_user_role_file() {
|
||||
let (home, mut config) = test_config_with_cli_overrides(Vec::new()).await;
|
||||
let role_path = write_role_config(
|
||||
&home,
|
||||
"metadata-role.toml",
|
||||
r#"
|
||||
name = "archivist"
|
||||
description = "Role metadata"
|
||||
nickname_candidates = ["Hypatia"]
|
||||
developer_instructions = "Stay focused"
|
||||
model = "role-model"
|
||||
"#,
|
||||
)
|
||||
.await;
|
||||
config.agent_roles.insert(
|
||||
"custom".to_string(),
|
||||
AgentRoleConfig {
|
||||
description: None,
|
||||
config_file: Some(role_path),
|
||||
nickname_candidates: None,
|
||||
},
|
||||
);
|
||||
|
||||
apply_role_to_config(&mut config, Some("custom"))
|
||||
.await
|
||||
.expect("custom role should apply");
|
||||
|
||||
assert_eq!(config.model.as_deref(), Some("role-model"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn apply_role_preserves_unspecified_keys() {
|
||||
let (home, mut config) = test_config_with_cli_overrides(vec![(
|
||||
@@ -403,7 +443,7 @@ mod tests {
|
||||
let role_path = write_role_config(
|
||||
&home,
|
||||
"effort-only.toml",
|
||||
"model_reasoning_effort = \"high\"",
|
||||
"developer_instructions = \"Stay focused\"\nmodel_reasoning_effort = \"high\"",
|
||||
)
|
||||
.await;
|
||||
config.agent_roles.insert(
|
||||
@@ -459,7 +499,12 @@ model_provider = "test-provider"
|
||||
.build()
|
||||
.await
|
||||
.expect("load config");
|
||||
let role_path = write_role_config(&home, "empty-role.toml", "").await;
|
||||
let role_path = write_role_config(
|
||||
&home,
|
||||
"empty-role.toml",
|
||||
"developer_instructions = \"Stay focused\"",
|
||||
)
|
||||
.await;
|
||||
config.agent_roles.insert(
|
||||
"custom".to_string(),
|
||||
AgentRoleConfig {
|
||||
@@ -515,8 +560,12 @@ model_provider = "role-provider"
|
||||
.build()
|
||||
.await
|
||||
.expect("load config");
|
||||
let role_path =
|
||||
write_role_config(&home, "profile-role.toml", "profile = \"role-profile\"").await;
|
||||
let role_path = write_role_config(
|
||||
&home,
|
||||
"profile-role.toml",
|
||||
"developer_instructions = \"Stay focused\"\nprofile = \"role-profile\"",
|
||||
)
|
||||
.await;
|
||||
config.agent_roles.insert(
|
||||
"custom".to_string(),
|
||||
AgentRoleConfig {
|
||||
@@ -572,7 +621,7 @@ model_provider = "base-provider"
|
||||
let role_path = write_role_config(
|
||||
&home,
|
||||
"provider-role.toml",
|
||||
"model_provider = \"role-provider\"",
|
||||
"developer_instructions = \"Stay focused\"\nmodel_provider = \"role-provider\"",
|
||||
)
|
||||
.await;
|
||||
config.agent_roles.insert(
|
||||
@@ -631,7 +680,9 @@ model_reasoning_effort = "low"
|
||||
let role_path = write_role_config(
|
||||
&home,
|
||||
"profile-edit-role.toml",
|
||||
r#"[profiles.base-profile]
|
||||
r#"developer_instructions = "Stay focused"
|
||||
|
||||
[profiles.base-profile]
|
||||
model_provider = "role-provider"
|
||||
model_reasoning_effort = "high"
|
||||
"#,
|
||||
@@ -674,7 +725,9 @@ model_reasoning_effort = "high"
|
||||
let role_path = write_role_config(
|
||||
&home,
|
||||
"sandbox-role.toml",
|
||||
r#"[sandbox_workspace_write]
|
||||
r#"developer_instructions = "Stay focused"
|
||||
|
||||
[sandbox_workspace_write]
|
||||
writable_roots = ["./sandbox-root"]
|
||||
"#,
|
||||
)
|
||||
@@ -732,7 +785,12 @@ writable_roots = ["./sandbox-root"]
|
||||
)])
|
||||
.await;
|
||||
let before_layers = session_flags_layer_count(&config);
|
||||
let role_path = write_role_config(&home, "model-role.toml", "model = \"role-model\"").await;
|
||||
let role_path = write_role_config(
|
||||
&home,
|
||||
"model-role.toml",
|
||||
"developer_instructions = \"Stay focused\"\nmodel = \"role-model\"",
|
||||
)
|
||||
.await;
|
||||
config.agent_roles.insert(
|
||||
"custom".to_string(),
|
||||
AgentRoleConfig {
|
||||
@@ -766,7 +824,9 @@ writable_roots = ["./sandbox-root"]
|
||||
&home,
|
||||
"skills-role.toml",
|
||||
&format!(
|
||||
r#"[[skills.config]]
|
||||
r#"developer_instructions = "Stay focused"
|
||||
|
||||
[[skills.config]]
|
||||
path = "{}"
|
||||
enabled = false
|
||||
"#,
|
||||
|
||||
Reference in New Issue
Block a user