mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
core: allow excluding tool namespaces from code mode (#26320)
## Why Research and training setups need to control which tool namespaces appear inside code mode's nested `tools` surface without disabling those tools entirely. This makes it possible to train against a deliberately reduced nested-tool setup while preserving the normal direct and deferred tool paths. ## What - Extend `features.code_mode` to accept structured configuration while preserving the existing boolean syntax. - Add an exact `excluded_tool_namespaces` list under `[features.code_mode]`: ```toml [features.code_mode] enabled = true excluded_tool_namespaces = ["mcp__codex_apps", "multi_agent_v1"] ``` - Filter matching canonical `ToolName` namespaces when constructing code mode's nested router and code-mode-specific direct tool descriptions. - Keep excluded tools registered, directly exposed in mixed code mode, and discoverable through top-level `tool_search` when otherwise eligible. - Derive deferred nested-tool guidance after namespace filtering so the `exec` description does not advertise excluded-only deferred tools. - Preserve the boolean/table representation when materializing config locks and update the generated config schema. ## Testing - `just test -p codex-features` - `just test -p codex-config` - `just test -p codex-core load_config_resolves_code_mode_config` - `just test -p codex-core lock_contains_prompts_and_materializes_features` - `just test -p codex-core excluded_deferred_namespaces_do_not_enable_nested_tool_guidance` - `just test -p codex-core code_mode_excludes_configured_nested_tool_namespaces` - `cargo check -p codex-thread-manager-sample`
This commit is contained in:
committed by
GitHub
Unverified
parent
9e41f8ddbe
commit
8b1238856b
@@ -25,6 +25,15 @@ pub fn features_schema(schema_gen: &mut SchemaGenerator) -> Schema {
|
||||
if feature.id == codex_features::Feature::Artifact {
|
||||
continue;
|
||||
}
|
||||
if feature.id == codex_features::Feature::CodeMode {
|
||||
validation.properties.insert(
|
||||
feature.key.to_string(),
|
||||
schema_gen.subschema_for::<codex_features::FeatureToml<
|
||||
codex_features::CodeModeConfigToml,
|
||||
>>(),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if feature.id == codex_features::Feature::MultiAgentV2 {
|
||||
validation.properties.insert(
|
||||
feature.key.to_string(),
|
||||
|
||||
@@ -355,6 +355,22 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"CodeModeConfigToml": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"excluded_tool_namespaces": {
|
||||
"description": "Exact tool namespaces to omit from the code-mode nested tool surface.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ConfigProfile": {
|
||||
"additionalProperties": false,
|
||||
"description": "Collection of common configuration options that a user can define as a unit in `config.toml`.",
|
||||
@@ -410,7 +426,7 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"code_mode": {
|
||||
"type": "boolean"
|
||||
"$ref": "#/definitions/FeatureToml_for_CodeModeConfigToml"
|
||||
},
|
||||
"code_mode_only": {
|
||||
"type": "boolean"
|
||||
@@ -830,6 +846,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"FeatureToml_for_CodeModeConfigToml": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/CodeModeConfigToml"
|
||||
}
|
||||
]
|
||||
},
|
||||
"FeatureToml_for_MultiAgentV2ConfigToml": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -4533,7 +4559,7 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"code_mode": {
|
||||
"type": "boolean"
|
||||
"$ref": "#/definitions/FeatureToml_for_CodeModeConfigToml"
|
||||
},
|
||||
"code_mode_only": {
|
||||
"type": "boolean"
|
||||
|
||||
@@ -476,6 +476,32 @@ async fn load_config_resolves_experimental_request_user_input_enabled() -> std::
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn load_config_resolves_code_mode_config() -> std::io::Result<()> {
|
||||
let codex_home = tempdir()?;
|
||||
let config_toml: ConfigToml = toml::from_str(
|
||||
r#"
|
||||
[features.code_mode]
|
||||
enabled = true
|
||||
excluded_tool_namespaces = ["mcp__codex_apps", "multi_agent_v1"]
|
||||
"#,
|
||||
)
|
||||
.expect("TOML deserialization should succeed");
|
||||
let config = Config::load_from_base_config_with_overrides(
|
||||
config_toml,
|
||||
ConfigOverrides::default(),
|
||||
codex_home.abs(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_eq!(
|
||||
config.code_mode.excluded_tool_namespaces,
|
||||
vec!["mcp__codex_apps".to_string(), "multi_agent_v1".to_string()]
|
||||
);
|
||||
assert!(config.features.enabled(Feature::CodeMode));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_provider_auth_with_env_key() {
|
||||
let err = toml::from_str::<ConfigToml>(
|
||||
|
||||
@@ -58,6 +58,7 @@ use codex_core_plugins::PluginsConfigInput;
|
||||
use codex_exec_server::ExecutorFileSystem;
|
||||
use codex_exec_server::LOCAL_FS;
|
||||
use codex_features::AppsMcpPathOverrideConfigToml;
|
||||
use codex_features::CodeModeConfigToml;
|
||||
use codex_features::Feature;
|
||||
use codex_features::FeatureConfigSource;
|
||||
use codex_features::FeatureOverrides;
|
||||
@@ -977,6 +978,9 @@ pub struct Config {
|
||||
/// Whether to register the experimental request_user_input tool.
|
||||
pub experimental_request_user_input_enabled: bool,
|
||||
|
||||
/// Configuration for the experimental code-mode tool surface.
|
||||
pub code_mode: CodeModeConfig,
|
||||
|
||||
/// If set to `true`, used only the experimental unified exec tool.
|
||||
pub use_experimental_unified_exec_tool: bool,
|
||||
|
||||
@@ -1029,6 +1033,11 @@ pub struct Config {
|
||||
pub otel: codex_config::types::OtelConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
|
||||
pub struct CodeModeConfig {
|
||||
pub excluded_tool_namespaces: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
||||
pub struct MultiAgentV2Config {
|
||||
pub max_concurrent_threads_per_session: usize,
|
||||
@@ -2290,6 +2299,17 @@ fn resolve_experimental_request_user_input_enabled(config_toml: &ConfigToml) ->
|
||||
.is_none_or(|config| config.enabled)
|
||||
}
|
||||
|
||||
fn resolve_code_mode_config(config_toml: &ConfigToml) -> CodeModeConfig {
|
||||
let base = code_mode_toml_config(config_toml.features.as_ref());
|
||||
|
||||
CodeModeConfig {
|
||||
excluded_tool_namespaces: base
|
||||
.and_then(|config| config.excluded_tool_namespaces.as_ref())
|
||||
.cloned()
|
||||
.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_multi_agent_v2_config(config_toml: &ConfigToml) -> MultiAgentV2Config {
|
||||
let base = multi_agent_v2_toml_config(config_toml.features.as_ref());
|
||||
let default = MultiAgentV2Config::default();
|
||||
@@ -2372,6 +2392,13 @@ fn resolve_optional_prompt_text(
|
||||
}
|
||||
}
|
||||
|
||||
fn code_mode_toml_config(features: Option<&FeaturesToml>) -> Option<&CodeModeConfigToml> {
|
||||
match features?.code_mode.as_ref()? {
|
||||
FeatureToml::Enabled(_) => None,
|
||||
FeatureToml::Config(config) => Some(config),
|
||||
}
|
||||
}
|
||||
|
||||
fn multi_agent_v2_toml_config(features: Option<&FeaturesToml>) -> Option<&MultiAgentV2ConfigToml> {
|
||||
match features?.multi_agent_v2.as_ref()? {
|
||||
FeatureToml::Enabled(_) => None,
|
||||
@@ -3013,6 +3040,7 @@ impl Config {
|
||||
let web_search_config = resolve_web_search_config(&cfg);
|
||||
let experimental_request_user_input_enabled =
|
||||
resolve_experimental_request_user_input_enabled(&cfg);
|
||||
let code_mode = resolve_code_mode_config(&cfg);
|
||||
let multi_agent_v2 = resolve_multi_agent_v2_config(&cfg);
|
||||
let apps_mcp_path_override = if features.enabled(Feature::AppsMcpPathOverride) {
|
||||
let base = apps_mcp_path_override_toml_config(cfg.features.as_ref());
|
||||
@@ -3554,6 +3582,7 @@ impl Config {
|
||||
web_search_mode: constrained_web_search_mode.value,
|
||||
web_search_config,
|
||||
experimental_request_user_input_enabled,
|
||||
code_mode,
|
||||
use_experimental_unified_exec_tool,
|
||||
background_terminal_max_timeout,
|
||||
ghost_snapshot,
|
||||
|
||||
@@ -251,6 +251,14 @@ mod tests {
|
||||
spec.key
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
features.code_mode,
|
||||
Some(FeatureToml::Enabled(
|
||||
sc.original_config_do_not_use
|
||||
.features
|
||||
.enabled(Feature::CodeMode)
|
||||
))
|
||||
);
|
||||
|
||||
let multi_agent_v2 = features
|
||||
.multi_agent_v2
|
||||
|
||||
@@ -207,7 +207,12 @@ fn build_model_visible_specs_and_registry(
|
||||
if exposure.is_direct() && !is_hidden_by_code_mode_only(turn_context, &tool_name, exposure)
|
||||
{
|
||||
let spec = runtime.spec();
|
||||
specs.push(spec_for_model_request(turn_context, exposure, spec));
|
||||
specs.push(spec_for_model_request(
|
||||
turn_context,
|
||||
exposure,
|
||||
&tool_name,
|
||||
spec,
|
||||
));
|
||||
}
|
||||
}
|
||||
specs.extend(hosted_specs);
|
||||
@@ -226,12 +231,14 @@ fn build_model_visible_specs_and_registry(
|
||||
fn spec_for_model_request(
|
||||
turn_context: &TurnContext,
|
||||
exposure: ToolExposure,
|
||||
tool_name: &ToolName,
|
||||
spec: ToolSpec,
|
||||
) -> ToolSpec {
|
||||
if matches!(
|
||||
turn_context.tool_mode,
|
||||
ToolMode::CodeMode | ToolMode::CodeModeOnly
|
||||
) && exposure != ToolExposure::DirectModelOnly
|
||||
&& !is_excluded_from_code_mode(turn_context, tool_name)
|
||||
&& codex_code_mode::is_code_mode_nested_tool(spec.name())
|
||||
{
|
||||
codex_tools::augment_tool_spec_for_code_mode(spec)
|
||||
@@ -405,10 +412,19 @@ fn is_hidden_by_code_mode_only(
|
||||
))
|
||||
}
|
||||
|
||||
fn is_excluded_from_code_mode(turn_context: &TurnContext, tool_name: &ToolName) -> bool {
|
||||
tool_name.namespace.as_ref().is_some_and(|namespace| {
|
||||
turn_context
|
||||
.config
|
||||
.code_mode
|
||||
.excluded_tool_namespaces
|
||||
.contains(namespace)
|
||||
})
|
||||
}
|
||||
|
||||
fn build_code_mode_executors(
|
||||
turn_context: &TurnContext,
|
||||
executors: &[Arc<dyn CoreToolRuntime>],
|
||||
deferred_tools_available: bool,
|
||||
) -> Vec<Arc<dyn CoreToolRuntime>> {
|
||||
if !matches!(
|
||||
turn_context.tool_mode,
|
||||
@@ -419,6 +435,8 @@ fn build_code_mode_executors(
|
||||
|
||||
let mut code_mode_nested_tool_specs = Vec::new();
|
||||
let mut exec_prompt_tool_specs = Vec::new();
|
||||
let mut deferred_tools_available = false;
|
||||
let deferred_tools_guidance_enabled = search_tool_enabled(turn_context);
|
||||
for executor in executors {
|
||||
let exposure = executor.exposure();
|
||||
if exposure == ToolExposure::DirectModelOnly {
|
||||
@@ -428,9 +446,19 @@ fn build_code_mode_executors(
|
||||
if exposure == ToolExposure::Hidden {
|
||||
continue;
|
||||
}
|
||||
|
||||
if is_excluded_from_code_mode(turn_context, &executor.tool_name()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let spec = executor.spec();
|
||||
|
||||
if exposure != ToolExposure::Deferred {
|
||||
if exposure == ToolExposure::Deferred {
|
||||
// Only show deferred-tool guidance when supported and an included spec is usable by code mode.
|
||||
deferred_tools_available |= deferred_tools_guidance_enabled
|
||||
&& !collect_code_mode_exec_prompt_tool_definitions(std::iter::once(&spec))
|
||||
.is_empty();
|
||||
} else {
|
||||
exec_prompt_tool_specs.push(spec.clone());
|
||||
}
|
||||
code_mode_nested_tool_specs.push(spec);
|
||||
@@ -839,16 +867,7 @@ fn prepend_code_mode_executors(
|
||||
planned_tools: &mut PlannedTools,
|
||||
) {
|
||||
let turn_context = context.turn_context;
|
||||
let deferred_tools_available = search_tool_enabled(turn_context)
|
||||
&& planned_tools
|
||||
.runtimes()
|
||||
.iter()
|
||||
.any(|executor| executor.exposure() == ToolExposure::Deferred);
|
||||
let code_mode_executors = build_code_mode_executors(
|
||||
turn_context,
|
||||
planned_tools.runtimes(),
|
||||
deferred_tools_available,
|
||||
);
|
||||
let code_mode_executors = build_code_mode_executors(turn_context, planned_tools.runtimes());
|
||||
planned_tools.runtimes.splice(0..0, code_mode_executors);
|
||||
}
|
||||
|
||||
|
||||
@@ -938,6 +938,42 @@ async fn code_mode_only_exposes_code_executor_and_hides_nested_tools() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn excluded_deferred_namespaces_do_not_enable_nested_tool_guidance() {
|
||||
let plan = probe_with(
|
||||
|turn| {
|
||||
set_features(turn, &[Feature::CodeMode, Feature::CodeModeOnly]);
|
||||
set_feature(turn, Feature::Collab, /*enabled*/ false);
|
||||
turn.model_info.supports_search_tool = true;
|
||||
update_config(turn, |config| {
|
||||
config.code_mode.excluded_tool_namespaces = vec!["excluded".to_string()];
|
||||
});
|
||||
},
|
||||
ToolPlanInputs {
|
||||
dynamic_tools: vec![dynamic_tool(
|
||||
Some("excluded"),
|
||||
"lookup",
|
||||
/*defer_loading*/ true,
|
||||
)],
|
||||
..ToolPlanInputs::default()
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
let ToolSpec::Freeform(exec) = plan.visible_spec(codex_code_mode::PUBLIC_TOOL_NAME) else {
|
||||
panic!("expected code mode exec tool");
|
||||
};
|
||||
assert!(
|
||||
!exec
|
||||
.description
|
||||
.contains("Some deferred nested tools may be omitted")
|
||||
);
|
||||
plan.assert_registered_contains(&[
|
||||
&ToolName::namespaced("excluded", "lookup").to_string(),
|
||||
"tool_search",
|
||||
]);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn multi_agent_feature_selects_one_agent_tool_family() {
|
||||
let v1 = probe(|turn| {
|
||||
|
||||
@@ -3165,6 +3165,93 @@ text(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn code_mode_excludes_configured_nested_tool_namespaces() -> Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let server = responses::start_mock_server().await;
|
||||
let mut builder = test_codex().with_config(|config| {
|
||||
let _ = config.features.enable(Feature::CodeMode);
|
||||
config.code_mode.excluded_tool_namespaces = vec!["excluded".to_string()];
|
||||
});
|
||||
let base_test = builder.build(&server).await?;
|
||||
let new_thread = base_test
|
||||
.thread_manager
|
||||
.start_thread_with_tools(
|
||||
base_test.config.clone(),
|
||||
vec![DynamicToolSpec {
|
||||
namespace: Some("excluded".to_string()),
|
||||
name: "lookup".to_string(),
|
||||
description: "An excluded dynamic tool.".to_string(),
|
||||
input_schema: serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"additionalProperties": false,
|
||||
}),
|
||||
defer_loading: false,
|
||||
}],
|
||||
)
|
||||
.await?;
|
||||
let mut test = base_test;
|
||||
test.codex = new_thread.thread;
|
||||
test.session_configured = new_thread.session_configured;
|
||||
|
||||
let first_mock = responses::mount_sse_once(
|
||||
&server,
|
||||
sse(vec![
|
||||
ev_response_created("resp-1"),
|
||||
ev_custom_tool_call(
|
||||
"call-1",
|
||||
"exec",
|
||||
r#"
|
||||
text(JSON.stringify({
|
||||
excludedType: typeof tools.excluded__lookup,
|
||||
excludedMetadata: ALL_TOOLS.some(({ name }) => name === "excluded__lookup"),
|
||||
allowedType: typeof tools.update_plan,
|
||||
allowedMetadata: ALL_TOOLS.some(({ name }) => name === "update_plan"),
|
||||
}));
|
||||
"#,
|
||||
),
|
||||
ev_completed("resp-1"),
|
||||
]),
|
||||
)
|
||||
.await;
|
||||
let second_mock = responses::mount_sse_once(
|
||||
&server,
|
||||
sse(vec![
|
||||
ev_assistant_message("msg-1", "done"),
|
||||
ev_completed("resp-2"),
|
||||
]),
|
||||
)
|
||||
.await;
|
||||
|
||||
test.submit_turn("use exec to inspect nested tool namespaces")
|
||||
.await?;
|
||||
|
||||
assert!(
|
||||
tool_names(&first_mock.single_request().body_json()).contains(&"excluded".to_string()),
|
||||
"excluded namespace should remain directly exposed in mixed code mode"
|
||||
);
|
||||
let request = second_mock.single_request();
|
||||
let (output, success) = custom_tool_output_body_and_success(&request, "call-1");
|
||||
assert_ne!(
|
||||
success,
|
||||
Some(false),
|
||||
"exec configured namespace exclusion failed unexpectedly: {output}"
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Value>(&output)?,
|
||||
serde_json::json!({
|
||||
"excludedType": "undefined",
|
||||
"excludedMetadata": false,
|
||||
"allowedType": "function",
|
||||
"allowedMetadata": true,
|
||||
})
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn code_mode_can_print_content_only_mcp_tool_result_fields() -> Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
@@ -4,6 +4,26 @@ use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CodeModeConfigToml {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub enabled: Option<bool>,
|
||||
/// Exact tool namespaces to omit from the code-mode nested tool surface.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub excluded_tool_namespaces: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl FeatureConfig for CodeModeConfigToml {
|
||||
fn enabled(&self) -> Option<bool> {
|
||||
self.enabled
|
||||
}
|
||||
|
||||
fn set_enabled(&mut self, enabled: bool) {
|
||||
self.enabled = Some(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MultiAgentV2ConfigToml {
|
||||
|
||||
@@ -17,6 +17,7 @@ use toml::Table;
|
||||
mod feature_configs;
|
||||
mod legacy;
|
||||
pub use feature_configs::AppsMcpPathOverrideConfigToml;
|
||||
pub use feature_configs::CodeModeConfigToml;
|
||||
pub use feature_configs::MultiAgentV2ConfigToml;
|
||||
pub use feature_configs::NetworkProxyConfigToml;
|
||||
pub use feature_configs::NetworkProxyDomainPermissionToml;
|
||||
@@ -600,6 +601,8 @@ pub fn is_known_feature_key(key: &str) -> bool {
|
||||
/// Deserializable features table for TOML.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema)]
|
||||
pub struct FeaturesToml {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub code_mode: Option<FeatureToml<CodeModeConfigToml>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub multi_agent_v2: Option<FeatureToml<MultiAgentV2ConfigToml>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@@ -620,6 +623,9 @@ impl Features {
|
||||
impl FeaturesToml {
|
||||
pub fn entries(&self) -> BTreeMap<String, bool> {
|
||||
let mut entries = self.entries.clone();
|
||||
if let Some(enabled) = self.code_mode.as_ref().and_then(FeatureToml::enabled) {
|
||||
entries.insert(Feature::CodeMode.key().to_string(), enabled);
|
||||
}
|
||||
if let Some(enabled) = self.multi_agent_v2.as_ref().and_then(FeatureToml::enabled) {
|
||||
entries.insert(Feature::MultiAgentV2.key().to_string(), enabled);
|
||||
}
|
||||
@@ -638,6 +644,7 @@ impl FeaturesToml {
|
||||
|
||||
pub fn materialize_resolved_enabled(&mut self, features: &Features) {
|
||||
let Self {
|
||||
code_mode,
|
||||
multi_agent_v2,
|
||||
apps_mcp_path_override,
|
||||
network_proxy,
|
||||
@@ -648,7 +655,9 @@ impl FeaturesToml {
|
||||
}
|
||||
for spec in FEATURES {
|
||||
let enabled = features.enabled(spec.id);
|
||||
if spec.id == Feature::MultiAgentV2 {
|
||||
if spec.id == Feature::CodeMode {
|
||||
materialize_resolved_feature_enabled(code_mode, enabled);
|
||||
} else if spec.id == Feature::MultiAgentV2 {
|
||||
materialize_resolved_feature_enabled(multi_agent_v2, enabled);
|
||||
} else if spec.id == Feature::AppsMcpPathOverride {
|
||||
materialize_resolved_feature_enabled(apps_mcp_path_override, enabled);
|
||||
|
||||
@@ -266,6 +266,7 @@ fn new_config(model: Option<String>, arg0_paths: Arg0DispatchPaths) -> anyhow::R
|
||||
web_search_mode: Constrained::allow_any(WebSearchMode::Disabled),
|
||||
web_search_config: None,
|
||||
experimental_request_user_input_enabled: true,
|
||||
code_mode: Default::default(),
|
||||
use_experimental_unified_exec_tool: false,
|
||||
background_terminal_max_timeout: 300_000,
|
||||
ghost_snapshot: GhostSnapshotConfig::default(),
|
||||
|
||||
Reference in New Issue
Block a user