Enable request_user_input in Default mode (#12735)

## Summary
- allow `request_user_input` in Default collaboration mode as well as
Plan
- update the Default-mode instructions to prefer assumptions first and
use `request_user_input` only when a question is unavoidable
- update request_user_input and app-server tests to match the new
Default-mode behavior
- refactor collaboration-mode availability plumbing into
`CollaborationModesConfig` for future mode-related flags

## Codex author
`codex resume 019c9124-ed28-7c13-96c6-b916b1c97d49`
This commit is contained in:
Charley Cunningham
2026-02-25 15:20:46 -08:00
committed by GitHub
parent 2bd87d1a75
commit 2f4d6ded1d
29 changed files with 426 additions and 147 deletions

View File

@@ -6,6 +6,7 @@ use crate::config::AgentRoleConfig;
use crate::features::Feature;
use crate::features::Features;
use crate::mcp_connection_manager::ToolInfo;
use crate::models_manager::collaboration_mode_presets::CollaborationModesConfig;
use crate::tools::handlers::PLAN_TOOL;
use crate::tools::handlers::SEARCH_TOOL_BM25_DEFAULT_LIMIT;
use crate::tools::handlers::SEARCH_TOOL_BM25_TOOL_NAME;
@@ -54,7 +55,7 @@ pub(crate) struct ToolsConfig {
pub js_repl_enabled: bool,
pub js_repl_tools_only: bool,
pub collab_tools: bool,
pub collaboration_modes_tools: bool,
pub default_mode_request_user_input: bool,
pub experimental_supported_tools: Vec<String>,
pub agent_jobs_tools: bool,
pub agent_jobs_worker_tools: bool,
@@ -80,7 +81,8 @@ impl ToolsConfig {
let include_js_repl_tools_only =
include_js_repl && features.enabled(Feature::JsReplToolsOnly);
let include_collab_tools = features.enabled(Feature::Collab);
let include_collaboration_modes_tools = features.enabled(Feature::CollaborationModes);
let include_default_mode_request_user_input =
features.enabled(Feature::DefaultModeRequestUserInput);
let include_search_tool = features.enabled(Feature::Apps);
let include_agent_jobs = include_collab_tools && features.enabled(Feature::Sqlite);
let request_permission_enabled = features.enabled(Feature::RequestPermissions);
@@ -137,7 +139,7 @@ impl ToolsConfig {
js_repl_enabled: include_js_repl,
js_repl_tools_only: include_js_repl_tools_only,
collab_tools: include_collab_tools,
collaboration_modes_tools: include_collaboration_modes_tools,
default_mode_request_user_input: include_default_mode_request_user_input,
experimental_supported_tools: model_info.experimental_supported_tools.clone(),
agent_jobs_tools: include_agent_jobs,
agent_jobs_worker_tools,
@@ -872,7 +874,9 @@ fn create_wait_tool() -> ToolSpec {
})
}
fn create_request_user_input_tool() -> ToolSpec {
fn create_request_user_input_tool(
collaboration_modes_config: CollaborationModesConfig,
) -> ToolSpec {
let mut option_props = BTreeMap::new();
option_props.insert(
"label".to_string(),
@@ -943,7 +947,9 @@ fn create_request_user_input_tool() -> ToolSpec {
ToolSpec::Function(ResponsesApiTool {
name: "request_user_input".to_string(),
description: request_user_input_tool_description(),
description: request_user_input_tool_description(
collaboration_modes_config.default_mode_request_user_input,
),
strict: false,
parameters: JsonSchema::Object {
properties,
@@ -1664,7 +1670,9 @@ pub(crate) fn build_specs(
let mcp_handler = Arc::new(McpHandler);
let mcp_resource_handler = Arc::new(McpResourceHandler);
let shell_command_handler = Arc::new(ShellCommandHandler::from(config.shell_command_backend));
let request_user_input_handler = Arc::new(RequestUserInputHandler);
let request_user_input_handler = Arc::new(RequestUserInputHandler {
default_mode_request_user_input: config.default_mode_request_user_input,
});
let search_tool_handler = Arc::new(SearchToolBm25Handler);
let js_repl_handler = Arc::new(JsReplHandler);
let js_repl_reset_handler = Arc::new(JsReplResetHandler);
@@ -1727,10 +1735,10 @@ pub(crate) fn build_specs(
builder.register_handler("js_repl_reset", js_repl_reset_handler);
}
if config.collaboration_modes_tools {
builder.push_spec(create_request_user_input_tool());
builder.register_handler("request_user_input", request_user_input_handler);
}
builder.push_spec(create_request_user_input_tool(CollaborationModesConfig {
default_mode_request_user_input: config.default_mode_request_user_input,
}));
builder.register_handler("request_user_input", request_user_input_handler);
if config.search_tool
&& let Some(app_tools) = app_tools
@@ -2024,7 +2032,6 @@ mod tests {
let model_info = model_info_from_models_json("gpt-5-codex");
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
features.enable(Feature::CollaborationModes);
let config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
features: &features,
@@ -2055,7 +2062,7 @@ mod tests {
create_exec_command_tool(true, false),
create_write_stdin_tool(),
PLAN_TOOL.clone(),
create_request_user_input_tool(),
create_request_user_input_tool(CollaborationModesConfig::default()),
create_apply_patch_freeform_tool(),
ToolSpec::WebSearch {
external_web_access: Some(true),
@@ -2087,8 +2094,6 @@ mod tests {
ModelsManager::construct_model_info_offline_for_tests("gpt-5-codex", &config);
let mut features = Features::with_defaults();
features.enable(Feature::Collab);
features.enable(Feature::CollaborationModes);
features.enable(Feature::Sqlite);
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
features: &features,
@@ -2115,7 +2120,6 @@ mod tests {
ModelsManager::construct_model_info_offline_for_tests("gpt-5-codex", &config);
let mut features = Features::with_defaults();
features.enable(Feature::Collab);
features.enable(Feature::CollaborationModes);
features.enable(Feature::Sqlite);
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
@@ -2141,12 +2145,11 @@ mod tests {
}
#[test]
fn request_user_input_requires_collaboration_modes_feature() {
fn request_user_input_description_reflects_default_mode_feature_flag() {
let config = test_config();
let model_info =
ModelsManager::construct_model_info_offline_for_tests("gpt-5-codex", &config);
let mut features = Features::with_defaults();
features.disable(Feature::CollaborationModes);
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
features: &features,
@@ -2154,12 +2157,13 @@ mod tests {
session_source: SessionSource::Cli,
});
let (tools, _) = build_specs(&tools_config, None, None, &[]).build();
assert!(
!tools.iter().any(|t| t.spec.name() == "request_user_input"),
"request_user_input should be disabled when collaboration_modes feature is off"
let request_user_input_tool = find_tool(&tools, "request_user_input");
assert_eq!(
request_user_input_tool.spec,
create_request_user_input_tool(CollaborationModesConfig::default())
);
features.enable(Feature::CollaborationModes);
features.enable(Feature::DefaultModeRequestUserInput);
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
features: &features,
@@ -2167,7 +2171,13 @@ mod tests {
session_source: SessionSource::Cli,
});
let (tools, _) = build_specs(&tools_config, None, None, &[]).build();
assert_contains_tool_names(&tools, &["request_user_input"]);
let request_user_input_tool = find_tool(&tools, "request_user_input");
assert_eq!(
request_user_input_tool.spec,
create_request_user_input_tool(CollaborationModesConfig {
default_mode_request_user_input: true,
})
);
}
#[test]
@@ -2335,8 +2345,7 @@ mod tests {
let config = test_config();
let model_info =
ModelsManager::construct_model_info_offline_for_tests("gpt-5-codex", &config);
let mut features = Features::with_defaults();
features.enable(Feature::CollaborationModes);
let features = Features::with_defaults();
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
features: &features,
@@ -2359,8 +2368,7 @@ mod tests {
let config = test_config();
let model_info =
ModelsManager::construct_model_info_offline_for_tests("gpt-5-codex", &config);
let mut features = Features::with_defaults();
features.enable(Feature::CollaborationModes);
let features = Features::with_defaults();
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
features: &features,
@@ -2381,8 +2389,7 @@ mod tests {
#[test]
fn test_build_specs_gpt5_codex_default() {
let mut features = Features::with_defaults();
features.enable(Feature::CollaborationModes);
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5-codex",
&features,
@@ -2400,8 +2407,7 @@ mod tests {
#[test]
fn test_build_specs_gpt51_codex_default() {
let mut features = Features::with_defaults();
features.enable(Feature::CollaborationModes);
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5.1-codex",
&features,
@@ -2421,7 +2427,6 @@ mod tests {
fn test_build_specs_gpt5_codex_unified_exec_web_search() {
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
features.enable(Feature::CollaborationModes);
assert_model_tools(
"gpt-5-codex",
&features,
@@ -2442,7 +2447,6 @@ mod tests {
fn test_build_specs_gpt51_codex_unified_exec_web_search() {
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
features.enable(Feature::CollaborationModes);
assert_model_tools(
"gpt-5.1-codex",
&features,
@@ -2461,8 +2465,7 @@ mod tests {
#[test]
fn test_gpt_5_1_codex_max_defaults() {
let mut features = Features::with_defaults();
features.enable(Feature::CollaborationModes);
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5.1-codex-max",
&features,
@@ -2480,8 +2483,7 @@ mod tests {
#[test]
fn test_codex_5_1_mini_defaults() {
let mut features = Features::with_defaults();
features.enable(Feature::CollaborationModes);
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5.1-codex-mini",
&features,
@@ -2499,8 +2501,7 @@ mod tests {
#[test]
fn test_gpt_5_defaults() {
let mut features = Features::with_defaults();
features.enable(Feature::CollaborationModes);
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5",
&features,
@@ -2517,8 +2518,7 @@ mod tests {
#[test]
fn test_gpt_5_1_defaults() {
let mut features = Features::with_defaults();
features.enable(Feature::CollaborationModes);
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5.1",
&features,
@@ -2538,7 +2538,6 @@ mod tests {
fn test_gpt_5_1_codex_max_unified_exec_web_search() {
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
features.enable(Feature::CollaborationModes);
assert_model_tools(
"gpt-5.1-codex-max",
&features,