mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
chore(config) tools.request_user_input
This commit is contained in:
@@ -38,6 +38,7 @@ use codex_model_provider_info::OLLAMA_CHAT_PROVIDER_REMOVED_ERROR;
|
||||
use codex_model_provider_info::OLLAMA_OSS_PROVIDER_ID;
|
||||
use codex_model_provider_info::OPENAI_PROVIDER_ID;
|
||||
use codex_protocol::config_types::ForcedLoginMethod;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
@@ -610,6 +611,22 @@ pub struct ToolsToml {
|
||||
/// Enable the `view_image` tool that lets the agent attach local images.
|
||||
#[serde(default)]
|
||||
pub view_image: Option<bool>,
|
||||
|
||||
/// Configure registration and collaboration-mode availability for `request_user_input`.
|
||||
#[serde(default)]
|
||||
pub request_user_input: Option<RequestUserInputToolConfigToml>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
|
||||
#[schemars(deny_unknown_fields)]
|
||||
pub struct RequestUserInputToolConfigToml {
|
||||
/// Whether to register the built-in `request_user_input` tool.
|
||||
#[serde(default)]
|
||||
pub enabled: Option<bool>,
|
||||
|
||||
/// Collaboration modes where `request_user_input` may be invoked.
|
||||
#[serde(default)]
|
||||
pub allowed_modes: Option<Vec<ModeKind>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
||||
@@ -1290,6 +1290,14 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
"plan",
|
||||
"default"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ModelAvailabilityNuxConfig": {
|
||||
"additionalProperties": {
|
||||
"format": "uint32",
|
||||
@@ -2276,6 +2284,25 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"RequestUserInputToolConfigToml": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"allowed_modes": {
|
||||
"default": null,
|
||||
"description": "Collaboration modes where `request_user_input` may be invoked.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ModeKind"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"enabled": {
|
||||
"default": null,
|
||||
"description": "Whether to register the built-in `request_user_input` tool.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"SandboxMode": {
|
||||
"enum": [
|
||||
"read-only",
|
||||
@@ -2501,6 +2528,15 @@
|
||||
"ToolsToml": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"request_user_input": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RequestUserInputToolConfigToml"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Configure registration and collaboration-mode availability for `request_user_input`."
|
||||
},
|
||||
"view_image": {
|
||||
"default": null,
|
||||
"description": "Enable the `view_image` tool that lets the agent attach local images.",
|
||||
|
||||
@@ -61,11 +61,13 @@ use codex_config::types::WindowsToml;
|
||||
use codex_core_plugins::PluginsManager;
|
||||
use codex_exec_server::LOCAL_FS;
|
||||
use codex_features::Feature;
|
||||
use codex_features::Features;
|
||||
use codex_features::FeaturesToml;
|
||||
use codex_model_provider_info::LMSTUDIO_OSS_PROVIDER_ID;
|
||||
use codex_model_provider_info::OLLAMA_OSS_PROVIDER_ID;
|
||||
use codex_model_provider_info::WireApi;
|
||||
use codex_models_manager::bundled_models_response;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::ServiceTier;
|
||||
use codex_protocol::models::ActivePermissionProfile;
|
||||
use codex_protocol::models::ActivePermissionProfileModification;
|
||||
@@ -381,6 +383,7 @@ web_search = true
|
||||
Some(ToolsToml {
|
||||
web_search: None,
|
||||
view_image: None,
|
||||
request_user_input: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -400,10 +403,51 @@ web_search = false
|
||||
Some(ToolsToml {
|
||||
web_search: None,
|
||||
view_image: None,
|
||||
request_user_input: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tools_request_user_input_deserializes_registration_and_modes() {
|
||||
let cfg: ConfigToml = toml::from_str(
|
||||
r#"
|
||||
[tools.request_user_input]
|
||||
enabled = false
|
||||
allowed_modes = ["plan", "default"]
|
||||
"#,
|
||||
)
|
||||
.expect("TOML deserialization should succeed");
|
||||
|
||||
let request_user_input = cfg
|
||||
.tools
|
||||
.and_then(|tools| tools.request_user_input)
|
||||
.expect("request_user_input tool config should deserialize");
|
||||
assert_eq!(request_user_input.enabled, Some(false));
|
||||
assert_eq!(
|
||||
request_user_input.allowed_modes,
|
||||
Some(vec![ModeKind::Plan, ModeKind::Default])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_user_input_tool_config_defaults_to_plan_and_legacy_feature_adds_default() {
|
||||
let cfg = ConfigToml::default();
|
||||
let profile = ConfigProfile::default();
|
||||
|
||||
assert_eq!(
|
||||
resolve_request_user_input_tool_config(&cfg, &profile, &Features::with_defaults()),
|
||||
(true, vec![ModeKind::Plan])
|
||||
);
|
||||
|
||||
let mut features = Features::with_defaults();
|
||||
features.enable(Feature::DefaultModeRequestUserInput);
|
||||
assert_eq!(
|
||||
resolve_request_user_input_tool_config(&cfg, &profile, &features),
|
||||
(true, vec![ModeKind::Plan, ModeKind::Default])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_provider_auth_with_env_key() {
|
||||
let err = toml::from_str::<ConfigToml>(
|
||||
@@ -7363,6 +7407,8 @@ async fn test_precedence_fixture_with_o3_profile() -> std::io::Result<()> {
|
||||
include_apply_patch_tool: true,
|
||||
web_search_mode: Constrained::allow_any(WebSearchMode::Cached),
|
||||
web_search_config: None,
|
||||
request_user_input_tool_enabled: true,
|
||||
request_user_input_allowed_modes: vec![ModeKind::Plan],
|
||||
use_experimental_unified_exec_tool: !cfg!(windows),
|
||||
background_terminal_max_timeout: DEFAULT_MAX_BACKGROUND_TERMINAL_TIMEOUT_MS,
|
||||
ghost_snapshot: GhostSnapshotConfig::default(),
|
||||
@@ -7810,6 +7856,8 @@ async fn test_precedence_fixture_with_gpt3_profile() -> std::io::Result<()> {
|
||||
include_apply_patch_tool: true,
|
||||
web_search_mode: Constrained::allow_any(WebSearchMode::Cached),
|
||||
web_search_config: None,
|
||||
request_user_input_tool_enabled: true,
|
||||
request_user_input_allowed_modes: vec![ModeKind::Plan],
|
||||
use_experimental_unified_exec_tool: !cfg!(windows),
|
||||
background_terminal_max_timeout: DEFAULT_MAX_BACKGROUND_TERMINAL_TIMEOUT_MS,
|
||||
ghost_snapshot: GhostSnapshotConfig::default(),
|
||||
@@ -7971,6 +8019,8 @@ async fn test_precedence_fixture_with_zdr_profile() -> std::io::Result<()> {
|
||||
include_apply_patch_tool: true,
|
||||
web_search_mode: Constrained::allow_any(WebSearchMode::Cached),
|
||||
web_search_config: None,
|
||||
request_user_input_tool_enabled: true,
|
||||
request_user_input_allowed_modes: vec![ModeKind::Plan],
|
||||
use_experimental_unified_exec_tool: !cfg!(windows),
|
||||
background_terminal_max_timeout: DEFAULT_MAX_BACKGROUND_TERMINAL_TIMEOUT_MS,
|
||||
ghost_snapshot: GhostSnapshotConfig::default(),
|
||||
@@ -8117,6 +8167,8 @@ async fn test_precedence_fixture_with_gpt5_profile() -> std::io::Result<()> {
|
||||
include_apply_patch_tool: true,
|
||||
web_search_mode: Constrained::allow_any(WebSearchMode::Cached),
|
||||
web_search_config: None,
|
||||
request_user_input_tool_enabled: true,
|
||||
request_user_input_allowed_modes: vec![ModeKind::Plan],
|
||||
use_experimental_unified_exec_tool: !cfg!(windows),
|
||||
background_terminal_max_timeout: DEFAULT_MAX_BACKGROUND_TERMINAL_TIMEOUT_MS,
|
||||
ghost_snapshot: GhostSnapshotConfig::default(),
|
||||
|
||||
@@ -78,6 +78,7 @@ use codex_model_provider_info::merge_configured_model_providers;
|
||||
use codex_models_manager::ModelsManagerConfig;
|
||||
use codex_protocol::config_types::AltScreenMode;
|
||||
use codex_protocol::config_types::ForcedLoginMethod;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
@@ -773,6 +774,12 @@ pub struct Config {
|
||||
/// Additional parameters for the web search tool when it is enabled.
|
||||
pub web_search_config: Option<WebSearchConfig>,
|
||||
|
||||
/// Whether to register the built-in request_user_input tool.
|
||||
pub request_user_input_tool_enabled: bool,
|
||||
|
||||
/// Collaboration modes where request_user_input may be invoked.
|
||||
pub request_user_input_allowed_modes: Vec<ModeKind>,
|
||||
|
||||
/// If set to `true`, used only the experimental unified exec tool.
|
||||
pub use_experimental_unified_exec_tool: bool,
|
||||
|
||||
@@ -1957,6 +1964,38 @@ fn resolve_web_search_config(
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_request_user_input_tool_config(
|
||||
config_toml: &ConfigToml,
|
||||
config_profile: &ConfigProfile,
|
||||
features: &Features,
|
||||
) -> (bool, Vec<ModeKind>) {
|
||||
let base = config_toml
|
||||
.tools
|
||||
.as_ref()
|
||||
.and_then(|tools| tools.request_user_input.as_ref());
|
||||
let profile = config_profile
|
||||
.tools
|
||||
.as_ref()
|
||||
.and_then(|tools| tools.request_user_input.as_ref());
|
||||
|
||||
let enabled = profile
|
||||
.and_then(|config| config.enabled)
|
||||
.or_else(|| base.and_then(|config| config.enabled))
|
||||
.unwrap_or(true);
|
||||
let mut allowed_modes = profile
|
||||
.and_then(|config| config.allowed_modes.clone())
|
||||
.or_else(|| base.and_then(|config| config.allowed_modes.clone()))
|
||||
.unwrap_or_else(|| vec![ModeKind::Plan]);
|
||||
|
||||
if features.enabled(Feature::DefaultModeRequestUserInput)
|
||||
&& !allowed_modes.contains(&ModeKind::Default)
|
||||
{
|
||||
allowed_modes.push(ModeKind::Default);
|
||||
}
|
||||
|
||||
(enabled, allowed_modes)
|
||||
}
|
||||
|
||||
fn resolve_multi_agent_v2_config(
|
||||
config_toml: &ConfigToml,
|
||||
config_profile: &ConfigProfile,
|
||||
@@ -2592,6 +2631,8 @@ impl Config {
|
||||
let web_search_mode = resolve_web_search_mode(&cfg, &config_profile, &features)
|
||||
.unwrap_or(WebSearchMode::Cached);
|
||||
let web_search_config = resolve_web_search_config(&cfg, &config_profile);
|
||||
let (request_user_input_tool_enabled, request_user_input_allowed_modes) =
|
||||
resolve_request_user_input_tool_config(&cfg, &config_profile, &features);
|
||||
let multi_agent_v2 = resolve_multi_agent_v2_config(&cfg, &config_profile);
|
||||
let apps_mcp_path_override = if features.enabled(Feature::AppsMcpPathOverride) {
|
||||
let base = apps_mcp_path_override_toml_config(cfg.features.as_ref());
|
||||
@@ -3161,6 +3202,8 @@ impl Config {
|
||||
include_apply_patch_tool: include_apply_patch_tool_flag,
|
||||
web_search_mode: constrained_web_search_mode.value,
|
||||
web_search_config,
|
||||
request_user_input_tool_enabled,
|
||||
request_user_input_allowed_modes,
|
||||
use_experimental_unified_exec_tool,
|
||||
background_terminal_max_timeout,
|
||||
ghost_snapshot,
|
||||
|
||||
@@ -51,6 +51,10 @@ pub(super) async fn spawn_review_thread(
|
||||
sess.services.main_execve_wrapper_exe.as_ref(),
|
||||
)
|
||||
.with_web_search_config(/*web_search_config*/ None)
|
||||
.with_request_user_input_config(
|
||||
config.request_user_input_tool_enabled,
|
||||
config.request_user_input_allowed_modes.clone(),
|
||||
)
|
||||
.with_allow_login_shell(config.permissions.allow_login_shell)
|
||||
.with_environment_mode(parent_turn_context.tools_config.environment_mode)
|
||||
.with_spawn_agent_usage_hint(config.multi_agent_v2.usage_hint_enabled)
|
||||
|
||||
@@ -212,6 +212,10 @@ impl TurnContext {
|
||||
.with_web_search_capability(provider_capabilities.web_search)
|
||||
.with_unified_exec_shell_mode(self.tools_config.unified_exec_shell_mode.clone())
|
||||
.with_web_search_config(self.tools_config.web_search_config.clone())
|
||||
.with_request_user_input_config(
|
||||
self.tools_config.request_user_input_tool_enabled,
|
||||
self.tools_config.request_user_input_available_modes.clone(),
|
||||
)
|
||||
.with_allow_login_shell(self.tools_config.allow_login_shell)
|
||||
.with_environment_mode(self.tools_config.environment_mode)
|
||||
.with_spawn_agent_usage_hint(config.multi_agent_v2.usage_hint_enabled)
|
||||
@@ -491,6 +495,10 @@ impl Session {
|
||||
main_execve_wrapper_exe,
|
||||
)
|
||||
.with_web_search_config(per_turn_config.web_search_config.clone())
|
||||
.with_request_user_input_config(
|
||||
per_turn_config.request_user_input_tool_enabled,
|
||||
per_turn_config.request_user_input_allowed_modes.clone(),
|
||||
)
|
||||
.with_allow_login_shell(per_turn_config.permissions.allow_login_shell)
|
||||
.with_environment_mode(ToolEnvironmentMode::from_count(
|
||||
environments.turn_environments.len(),
|
||||
|
||||
@@ -332,9 +332,11 @@ fn collect_handler_tools(
|
||||
handlers.push(Arc::new(UpdateGoalHandler));
|
||||
}
|
||||
|
||||
handlers.push(Arc::new(RequestUserInputHandler {
|
||||
available_modes: config.request_user_input_available_modes.clone(),
|
||||
}));
|
||||
if config.request_user_input_tool_enabled {
|
||||
handlers.push(Arc::new(RequestUserInputHandler {
|
||||
available_modes: config.request_user_input_available_modes.clone(),
|
||||
}));
|
||||
}
|
||||
|
||||
if config.request_permissions_tool_enabled {
|
||||
handlers.push(Arc::new(RequestPermissionsHandler));
|
||||
|
||||
@@ -868,6 +868,32 @@ fn request_user_input_description_reflects_default_mode_feature_flag() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_user_input_registration_respects_tool_config() {
|
||||
let model_info = model_info();
|
||||
let features = Features::with_defaults();
|
||||
let available_models = Vec::new();
|
||||
let tools_config = ToolsConfig::new(&ToolsConfigParams {
|
||||
model_info: &model_info,
|
||||
available_models: &available_models,
|
||||
features: &features,
|
||||
image_generation_tool_auth_allowed: true,
|
||||
web_search_mode: Some(WebSearchMode::Cached),
|
||||
session_source: SessionSource::Cli,
|
||||
permission_profile: &PermissionProfile::Disabled,
|
||||
windows_sandbox_level: WindowsSandboxLevel::Disabled,
|
||||
})
|
||||
.with_request_user_input_config(/*enabled*/ false, vec![ModeKind::Plan]);
|
||||
let (tools, _) = build_specs(
|
||||
&tools_config,
|
||||
/*mcp_tools*/ None,
|
||||
/*deferred_mcp_tools*/ None,
|
||||
&[],
|
||||
);
|
||||
|
||||
assert_lacks_tool_name(&tools, REQUEST_USER_INPUT_TOOL_NAME);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_permissions_requires_feature_flag() {
|
||||
let model_info = model_info();
|
||||
|
||||
@@ -203,3 +203,50 @@ async fn emits_deprecation_notice_for_use_legacy_landlock() -> anyhow::Result<()
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn emits_deprecation_notice_for_default_mode_request_user_input() -> anyhow::Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let server = start_mock_server().await;
|
||||
|
||||
let mut builder = test_codex().with_config(|config| {
|
||||
let mut entries = BTreeMap::new();
|
||||
entries.insert("default_mode_request_user_input".to_string(), true);
|
||||
let mut features = config.features.get().clone();
|
||||
features.apply_map(&entries);
|
||||
config
|
||||
.features
|
||||
.set(features)
|
||||
.expect("test config should allow managed feature map updates");
|
||||
});
|
||||
|
||||
let TestCodex { codex, .. } = builder.build(&server).await?;
|
||||
|
||||
let notice = wait_for_event_match(&codex, |event| match event {
|
||||
EventMsg::DeprecationNotice(ev)
|
||||
if ev
|
||||
.summary
|
||||
.contains("[features].default_mode_request_user_input") =>
|
||||
{
|
||||
Some(ev.clone())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.await;
|
||||
|
||||
let DeprecationNoticeEvent { summary, details } = notice;
|
||||
assert_eq!(
|
||||
summary,
|
||||
"`[features].default_mode_request_user_input` is deprecated and will be removed soon."
|
||||
.to_string(),
|
||||
);
|
||||
assert_eq!(
|
||||
details.as_deref(),
|
||||
Some(
|
||||
"Use `[tools.request_user_input].allowed_modes = [\"plan\", \"default\"]` in config.toml instead."
|
||||
),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -437,6 +437,12 @@ impl Features {
|
||||
Feature::UseLegacyLandlock,
|
||||
);
|
||||
}
|
||||
"default_mode_request_user_input" => {
|
||||
self.record_legacy_usage_force(
|
||||
"features.default_mode_request_user_input",
|
||||
Feature::DefaultModeRequestUserInput,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match feature_for_key(k) {
|
||||
@@ -531,6 +537,17 @@ fn legacy_usage_notice(alias: &str, feature: Feature) -> (String, Option<String>
|
||||
.to_string();
|
||||
(summary, Some(details))
|
||||
}
|
||||
Feature::DefaultModeRequestUserInput => {
|
||||
let label = match alias {
|
||||
"features.default_mode_request_user_input" | "default_mode_request_user_input" => {
|
||||
"[features].default_mode_request_user_input"
|
||||
}
|
||||
_ => alias,
|
||||
};
|
||||
let summary = format!("`{label}` is deprecated and will be removed soon.");
|
||||
let details = "Use `[tools.request_user_input].allowed_modes = [\"plan\", \"default\"]` in config.toml instead.".to_string();
|
||||
(summary, Some(details))
|
||||
}
|
||||
_ => {
|
||||
let label = if alias.contains('.') || alias.starts_with('[') {
|
||||
alias.to_string()
|
||||
@@ -1062,7 +1079,7 @@ pub const FEATURES: &[FeatureSpec] = &[
|
||||
FeatureSpec {
|
||||
id: Feature::DefaultModeRequestUserInput,
|
||||
key: "default_mode_request_user_input",
|
||||
stage: Stage::UnderDevelopment,
|
||||
stage: Stage::Deprecated,
|
||||
default_enabled: false,
|
||||
},
|
||||
FeatureSpec {
|
||||
|
||||
@@ -119,6 +119,18 @@ fn request_permissions_tool_is_under_development() {
|
||||
assert_eq!(Feature::RequestPermissionsTool.default_enabled(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_mode_request_user_input_is_deprecated_and_disabled_by_default() {
|
||||
assert_eq!(
|
||||
Feature::DefaultModeRequestUserInput.stage(),
|
||||
Stage::Deprecated
|
||||
);
|
||||
assert_eq!(
|
||||
Feature::DefaultModeRequestUserInput.default_enabled(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remote_compaction_v2_is_under_development() {
|
||||
assert_eq!(Feature::RemoteCompactionV2.stage(), Stage::UnderDevelopment);
|
||||
@@ -248,6 +260,30 @@ fn use_legacy_landlock_config_records_deprecation_notice() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_mode_request_user_input_config_records_deprecation_notice() {
|
||||
let mut entries = BTreeMap::new();
|
||||
entries.insert("default_mode_request_user_input".to_string(), true);
|
||||
|
||||
let mut features = Features::with_defaults();
|
||||
features.apply_map(&entries);
|
||||
|
||||
let usages = features.legacy_feature_usages().collect::<Vec<_>>();
|
||||
assert_eq!(usages.len(), 1);
|
||||
assert_eq!(usages[0].alias, "features.default_mode_request_user_input");
|
||||
assert_eq!(usages[0].feature, Feature::DefaultModeRequestUserInput);
|
||||
assert_eq!(
|
||||
usages[0].summary,
|
||||
"`[features].default_mode_request_user_input` is deprecated and will be removed soon."
|
||||
);
|
||||
assert_eq!(
|
||||
usages[0].details.as_deref(),
|
||||
Some(
|
||||
"Use `[tools.request_user_input].allowed_modes = [\"plan\", \"default\"]` in config.toml instead."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn image_detail_original_is_a_removed_feature_key() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -122,6 +122,7 @@ pub struct ToolsConfig {
|
||||
pub spawn_agent_usage_hint_text: Option<String>,
|
||||
pub max_concurrent_threads_per_session: Option<usize>,
|
||||
pub wait_agent_min_timeout_ms: Option<i64>,
|
||||
pub request_user_input_tool_enabled: bool,
|
||||
pub request_user_input_available_modes: Vec<ModeKind>,
|
||||
pub experimental_supported_tools: Vec<String>,
|
||||
pub agent_jobs_tools: bool,
|
||||
@@ -259,6 +260,7 @@ impl ToolsConfig {
|
||||
spawn_agent_usage_hint_text: None,
|
||||
max_concurrent_threads_per_session: None,
|
||||
wait_agent_min_timeout_ms: None,
|
||||
request_user_input_tool_enabled: true,
|
||||
request_user_input_available_modes: request_user_input_available_modes(features),
|
||||
experimental_supported_tools: model_info.experimental_supported_tools.clone(),
|
||||
agent_jobs_tools: include_agent_jobs,
|
||||
@@ -272,6 +274,16 @@ impl ToolsConfig {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_request_user_input_config(
|
||||
mut self,
|
||||
enabled: bool,
|
||||
available_modes: Vec<ModeKind>,
|
||||
) -> Self {
|
||||
self.request_user_input_tool_enabled = enabled;
|
||||
self.request_user_input_available_modes = available_modes;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_namespace_tools_capability(mut self, namespace_tools: bool) -> Self {
|
||||
if !namespace_tools {
|
||||
self.namespace_tools = false;
|
||||
|
||||
Reference in New Issue
Block a user