Always expose view_image and return unsupported image-input error (#11336)

- Keep `view_image` in the advertised tool list for all models.
- Return a clear error when the current model does not support image
inputs, and cover it with a unit test.
This commit is contained in:
Ahmed Ibrahim
2026-02-10 11:25:12 -08:00
committed by GitHub
parent 847a6092e6
commit 6e96e4837e
3 changed files with 144 additions and 30 deletions

View File

@@ -17,7 +17,6 @@ use codex_protocol::dynamic_tools::DynamicToolSpec;
use codex_protocol::models::VIEW_IMAGE_TOOL_NAME;
use codex_protocol::openai_models::ApplyPatchToolType;
use codex_protocol::openai_models::ConfigShellToolType;
use codex_protocol::openai_models::InputModality;
use codex_protocol::openai_models::ModelInfo;
use serde::Deserialize;
use serde::Serialize;
@@ -31,7 +30,6 @@ pub(crate) struct ToolsConfig {
pub shell_type: ConfigShellToolType,
pub apply_patch_tool_type: Option<ApplyPatchToolType>,
pub web_search_mode: Option<WebSearchMode>,
pub supports_image_input: bool,
pub search_tool: bool,
pub collab_tools: bool,
pub collaboration_modes_tools: bool,
@@ -87,7 +85,6 @@ impl ToolsConfig {
shell_type,
apply_patch_tool_type,
web_search_mode: *web_search_mode,
supports_image_input: model_info.input_modalities.contains(&InputModality::Image),
search_tool: include_search_tool,
collab_tools: include_collab_tools,
collaboration_modes_tools: include_collaboration_modes_tools,
@@ -1498,10 +1495,8 @@ pub(crate) fn build_specs(
Some(WebSearchMode::Disabled) | None => {}
}
if config.supports_image_input {
builder.push_spec_with_parallel_support(create_view_image_tool(), true);
builder.register_handler("view_image", view_image_handler);
}
builder.push_spec_with_parallel_support(create_view_image_tool(), true);
builder.register_handler("view_image", view_image_handler);
if config.collab_tools {
let collab_handler = Arc::new(CollabHandler);
@@ -2076,29 +2071,6 @@ mod tests {
);
}
#[test]
fn test_non_multimodal_models_exclude_view_image() {
let config = test_config();
let mut model_info = ModelsManager::construct_model_info_offline("gpt-5.1", &config);
model_info.input_modalities = vec![InputModality::Text];
let mut features = Features::with_defaults();
features.enable(Feature::CollaborationModes);
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
features: &features,
web_search_mode: Some(WebSearchMode::Cached),
});
let (tools, _) = build_specs(&tools_config, Some(HashMap::new()), &[]).build();
assert!(
!tools
.iter()
.map(|t| t.spec.name())
.any(|name| name == VIEW_IMAGE_TOOL_NAME),
"view_image should be excluded for non-multimodal models"
);
}
#[test]
fn test_gpt_5_1_codex_max_unified_exec_web_search() {
let mut features = Features::with_defaults();