Add tool namespace metadata configuration (#37389)

## What changed

- Add `features.tool_registry.include_tool_namespaces_info` to the TOML model,
  generated schema, and resolved runtime configuration. The setting defaults to
  `false` and controls whether per-turn request metadata includes the resolved
  tool namespace inventory.
- Preserve the resolved setting in session configuration locks.
- Cover top-level and profile-scoped strict configuration, deserialization,
  resolution, and lock-file persistence.

GitOrigin-RevId: 74124086c0d7de30094b411001f0ec0af490935d
This commit is contained in:
rka-oai
2026-08-07 06:29:09 +00:00
committed by copyberry
parent 0bdce9f424
commit 4ee41929ea
7 changed files with 43 additions and 6 deletions
@@ -95,6 +95,8 @@ fn strict_config_accepts_tool_registry_config() {
for contents in [
"[features.tool_registry]\nerror_on_tool_collisions = true\n",
"[profiles.work.features.tool_registry]\nerror_on_tool_collisions = true\n",
"[features.tool_registry]\ninclude_tool_namespaces_info = true\n",
"[profiles.work.features.tool_registry]\ninclude_tool_namespaces_info = true\n",
] {
assert_eq!(
config_error_from_ignored_toml_fields::<ConfigToml>(path, contents),
+4
View File
@@ -3218,6 +3218,10 @@
"error_on_tool_collisions": {
"description": "Fail the turn when multiple tools share the same effective name.",
"type": "boolean"
},
"include_tool_namespaces_info": {
"description": "Include the resolved tool namespace inventory in per-turn request metadata.",
"type": "boolean"
}
},
"type": "object"
+12 -2
View File
@@ -574,11 +574,17 @@ disable_in_process_fallback = true
async fn load_config_resolves_tool_registry_config() -> std::io::Result<()> {
let codex_home = tempdir()?;
for (config_toml, error_on_tool_collisions) in [
("", false),
for (config_toml, error_on_tool_collisions, include_tool_namespaces_info) in [
("", false, false),
(
"[features.tool_registry]\nerror_on_tool_collisions = true\n",
true,
false,
),
(
"[features.tool_registry]\ninclude_tool_namespaces_info = true\n",
false,
true,
),
] {
let config_toml: ConfigToml =
@@ -594,6 +600,10 @@ async fn load_config_resolves_tool_registry_config() -> std::io::Result<()> {
config.tool_registry.error_on_tool_collisions,
error_on_tool_collisions
);
assert_eq!(
config.tool_registry.include_tool_namespaces_info,
include_tool_namespaces_info
);
assert!(!config.features.enabled(Feature::CodeMode));
}
+8
View File
@@ -1115,6 +1115,8 @@ pub struct Config {
pub struct ToolRegistryConfig {
/// Fail the turn when multiple tools share the same effective name.
pub error_on_tool_collisions: bool,
/// Include the resolved tool namespace inventory in per-turn request metadata.
pub include_tool_namespaces_info: bool,
}
const DEFAULT_CODE_MODE_EXEC_YIELD_TIME_MS: u64 = 30_000;
@@ -3717,6 +3719,12 @@ impl Config {
.and_then(|features| features.tool_registry.as_ref())
.and_then(|config| config.error_on_tool_collisions)
.unwrap_or_default(),
include_tool_namespaces_info: cfg
.features
.as_ref()
.and_then(|features| features.tool_registry.as_ref())
.and_then(|config| config.include_tool_namespaces_info)
.unwrap_or_default(),
};
let code_mode = resolve_code_mode_config(&cfg);
let multi_agent_v2 = resolve_multi_agent_v2_config(&cfg);
+7 -1
View File
@@ -154,9 +154,13 @@ fn save_config_resolved_fields(
.features
.get_or_insert_with(FeaturesToml::default);
features.materialize_resolved_enabled(config.features.get());
if config.tool_registry.error_on_tool_collisions || features.tool_registry.is_some() {
if config.tool_registry.error_on_tool_collisions
|| config.tool_registry.include_tool_namespaces_info
|| features.tool_registry.is_some()
{
features.tool_registry = Some(ToolRegistryConfigToml {
error_on_tool_collisions: Some(config.tool_registry.error_on_tool_collisions),
include_tool_namespaces_info: Some(config.tool_registry.include_tool_namespaces_info),
});
}
let mut multi_agent_v2: MultiAgentV2ConfigToml =
@@ -269,6 +273,7 @@ mod tests {
let mut sc = crate::session::tests::make_session_configuration_for_tests().await;
let mut config = (*sc.original_config_do_not_use).clone();
config.tool_registry.error_on_tool_collisions = true;
config.tool_registry.include_tool_namespaces_info = true;
config.multi_agent_v2.subagent_developer_instructions =
Some("Locked subagent developer instructions.".to_string());
config.token_budget = Some(crate::config::TokenBudgetConfig {
@@ -329,6 +334,7 @@ mod tests {
features.tool_registry,
Some(ToolRegistryConfigToml {
error_on_tool_collisions: Some(true),
include_tool_namespaces_info: Some(true),
})
);
let feature_entries = features.entries();
+3
View File
@@ -10,6 +10,9 @@ pub struct ToolRegistryConfigToml {
/// Fail the turn when multiple tools share the same effective name.
#[serde(skip_serializing_if = "Option::is_none")]
pub error_on_tool_collisions: Option<bool>,
/// Include the resolved tool namespace inventory in per-turn request metadata.
#[serde(skip_serializing_if = "Option::is_none")]
pub include_tool_namespaces_info: Option<bool>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
+7 -3
View File
@@ -29,14 +29,16 @@ fn under_development_features_are_disabled_by_default() {
#[test]
fn tool_registry_config_is_not_a_feature_toggle() {
let features: FeaturesToml =
toml::from_str("[tool_registry]\nerror_on_tool_collisions = true\n")
.expect("tool registry settings should deserialize");
let features: FeaturesToml = toml::from_str(
"[tool_registry]\nerror_on_tool_collisions = true\ninclude_tool_namespaces_info = true\n",
)
.expect("tool registry settings should deserialize");
assert_eq!(
features.tool_registry,
Some(crate::ToolRegistryConfigToml {
error_on_tool_collisions: Some(true),
include_tool_namespaces_info: Some(true),
})
);
assert!(features.entries().is_empty());
@@ -552,6 +554,7 @@ fn materialize_resolved_enabled_writes_all_features_and_preserves_custom_config(
let mut features_toml = FeaturesToml {
tool_registry: Some(crate::ToolRegistryConfigToml {
error_on_tool_collisions: Some(true),
include_tool_namespaces_info: Some(true),
}),
code_mode_host: Some(FeatureToml::Config(crate::CodeModeHostConfigToml {
enabled: Some(false),
@@ -584,6 +587,7 @@ fn materialize_resolved_enabled_writes_all_features_and_preserves_custom_config(
features_toml.tool_registry,
Some(crate::ToolRegistryConfigToml {
error_on_tool_collisions: Some(true),
include_tool_namespaces_info: Some(true),
})
);
let entries = features_toml.entries();