mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Allow bool web_search in ToolsToml (#14352)
Summary - add a custom deserializer so `[tools].web_search` can be a bool (treated as disabled) or a config object - extend core and app-server tests to cover bool handling in TOML config Testing - Not run (not requested)
This commit is contained in:
committed by
Michael Bolin
Unverified
parent
7f22329389
commit
548583198a
@@ -218,6 +218,38 @@ location = { country = "US", city = "New York", timezone = "America/New_York" }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn config_read_ignores_bool_web_search_tool_config() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
write_config(
|
||||
&codex_home,
|
||||
r#"
|
||||
[tools]
|
||||
web_search = true
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
.send_config_read_request(ConfigReadParams {
|
||||
include_layers: false,
|
||||
cwd: None,
|
||||
})
|
||||
.await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
|
||||
)
|
||||
.await??;
|
||||
let ConfigReadResponse { config, .. } = to_response(resp)?;
|
||||
|
||||
assert_eq!(config.tools.expect("tools present").web_search, None,);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn config_read_includes_apps() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
|
||||
@@ -175,6 +175,44 @@ enabled = false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tools_web_search_true_deserializes_to_none() {
|
||||
let cfg: ConfigToml = toml::from_str(
|
||||
r#"
|
||||
[tools]
|
||||
web_search = true
|
||||
"#,
|
||||
)
|
||||
.expect("TOML deserialization should succeed");
|
||||
|
||||
assert_eq!(
|
||||
cfg.tools,
|
||||
Some(ToolsToml {
|
||||
web_search: None,
|
||||
view_image: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tools_web_search_false_deserializes_to_none() {
|
||||
let cfg: ConfigToml = toml::from_str(
|
||||
r#"
|
||||
[tools]
|
||||
web_search = false
|
||||
"#,
|
||||
)
|
||||
.expect("TOML deserialization should succeed");
|
||||
|
||||
assert_eq!(
|
||||
cfg.tools,
|
||||
Some(ToolsToml {
|
||||
web_search: None,
|
||||
view_image: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_toml_deserializes_model_availability_nux() {
|
||||
let toml = r#"
|
||||
|
||||
@@ -82,6 +82,7 @@ use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_absolute_path::AbsolutePathBufGuard;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Deserializer;
|
||||
use serde::Serialize;
|
||||
use similar::DiffableStr;
|
||||
use std::collections::BTreeMap;
|
||||
@@ -1392,7 +1393,10 @@ pub struct RealtimeAudioToml {
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct ToolsToml {
|
||||
#[serde(default)]
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "deserialize_optional_web_search_tool_config"
|
||||
)]
|
||||
pub web_search: Option<WebSearchToolConfig>,
|
||||
|
||||
/// Enable the `view_image` tool that lets the agent attach local images.
|
||||
@@ -1400,6 +1404,31 @@ pub struct ToolsToml {
|
||||
pub view_image: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum WebSearchToolConfigInput {
|
||||
Enabled(bool),
|
||||
Config(WebSearchToolConfig),
|
||||
}
|
||||
|
||||
fn deserialize_optional_web_search_tool_config<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<WebSearchToolConfig>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let value = Option::<WebSearchToolConfigInput>::deserialize(deserializer)?;
|
||||
|
||||
Ok(match value {
|
||||
None => None,
|
||||
Some(WebSearchToolConfigInput::Enabled(enabled)) => {
|
||||
let _ = enabled;
|
||||
None
|
||||
}
|
||||
Some(WebSearchToolConfigInput::Config(config)) => Some(config),
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct AgentsToml {
|
||||
|
||||
@@ -168,10 +168,12 @@ impl ConfigService {
|
||||
};
|
||||
|
||||
let effective = layers.effective_config();
|
||||
validate_config(&effective)
|
||||
|
||||
let effective_config_toml: ConfigToml = effective
|
||||
.try_into()
|
||||
.map_err(|err| ConfigServiceError::toml("invalid configuration", err))?;
|
||||
|
||||
let json_value = serde_json::to_value(&effective)
|
||||
let json_value = serde_json::to_value(&effective_config_toml)
|
||||
.map_err(|err| ConfigServiceError::json("failed to serialize configuration", err))?;
|
||||
let config: ApiConfig = serde_json::from_value(json_value)
|
||||
.map_err(|err| ConfigServiceError::json("failed to deserialize configuration", err))?;
|
||||
|
||||
Reference in New Issue
Block a user