mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
7e07ec8f73
###### Summary - Add input_modalities to model metadata so clients can determine supported input types. - Gate image paste/attach in TUI when the selected model does not support images. - Block submits that include images for unsupported models and show a clear warning. - Propagate modality metadata through app-server protocol/model-list responses. - Update related tests/fixtures. ###### Rationale - Models support different input modalities. - Clients need an explicit capability signal to prevent unsupported requests. - Backward-compatible defaults preserve existing behavior when modality metadata is absent. ###### Scope - codex-rs/protocol, codex-rs/core, codex-rs/tui - codex-rs/app-server-protocol, codex-rs/app-server - Generated app-server types / schema fixtures ###### Trade-offs - Default behavior assumes text + image when field is absent for compatibility. - Server-side validation remains the source of truth. ###### Follow-up - Non-TUI clients should consume input_modalities to disable unsupported attachments. - Model catalogs should explicitly set input_modalities for text-only models. ###### Testing - cargo fmt --all - cargo test -p codex-tui - env -u GITHUB_APP_KEY cargo test -p codex-core --lib - just write-app-server-schema - cargo run -p codex-cli --bin codex -- app-server generate-ts --out app-server-types - test against local backend <img width="695" height="199" alt="image" src="https://github.com/user-attachments/assets/d22dd04f-5eba-4db9-a7c5-a2506f60ec44" /> --------- Co-authored-by: Josh McKinney <joshka@openai.com>
48 lines
1.5 KiB
Rust
48 lines
1.5 KiB
Rust
use std::sync::Arc;
|
|
|
|
use codex_app_server_protocol::Model;
|
|
use codex_app_server_protocol::ReasoningEffortOption;
|
|
use codex_core::ThreadManager;
|
|
use codex_core::config::Config;
|
|
use codex_core::models_manager::manager::RefreshStrategy;
|
|
use codex_protocol::openai_models::ModelPreset;
|
|
use codex_protocol::openai_models::ReasoningEffortPreset;
|
|
|
|
pub async fn supported_models(thread_manager: Arc<ThreadManager>, config: &Config) -> Vec<Model> {
|
|
thread_manager
|
|
.list_models(config, RefreshStrategy::OnlineIfUncached)
|
|
.await
|
|
.into_iter()
|
|
.filter(|preset| preset.show_in_picker)
|
|
.map(model_from_preset)
|
|
.collect()
|
|
}
|
|
|
|
fn model_from_preset(preset: ModelPreset) -> Model {
|
|
Model {
|
|
id: preset.id.to_string(),
|
|
model: preset.model.to_string(),
|
|
display_name: preset.display_name.to_string(),
|
|
description: preset.description.to_string(),
|
|
supported_reasoning_efforts: reasoning_efforts_from_preset(
|
|
preset.supported_reasoning_efforts,
|
|
),
|
|
default_reasoning_effort: preset.default_reasoning_effort,
|
|
input_modalities: preset.input_modalities,
|
|
supports_personality: preset.supports_personality,
|
|
is_default: preset.is_default,
|
|
}
|
|
}
|
|
|
|
fn reasoning_efforts_from_preset(
|
|
efforts: Vec<ReasoningEffortPreset>,
|
|
) -> Vec<ReasoningEffortOption> {
|
|
efforts
|
|
.iter()
|
|
.map(|preset| ReasoningEffortOption {
|
|
reasoning_effort: preset.effort,
|
|
description: preset.description.to_string(),
|
|
})
|
|
.collect()
|
|
}
|