feat(core): support custom model aliases in config.toml

This adds config.toml-defined model aliases that map to provider model slugs while applying alias-specific context settings for the active session.

- added custom_models config entries plus schema and docs coverage
- taught ModelsManager to resolve aliases to a provider-facing request_model while preserving the user-facing alias slug
- applied alias-specific context_window and model_auto_compact_token_limit overrides during model info resolution
- updated session/test plumbing and added regression coverage for alias resolution with local and remote model catalogs

Model selection and per-session context overrides already flow through ModelsManager and Config. Resolving aliases there keeps the provider slug separate from the user-facing alias while reusing the existing override plumbing.

- just write-config-schema
- just fmt
- cargo test -p codex-app-server -p codex-api -p codex-exec -p codex-mcp-server
- cargo test -p codex-tui
- cargo test -p codex-protocol -p codex-core (same two existing seatbelt failures remained in this environment: create_seatbelt_args_with_read_only_git_pointer_file and create_seatbelt_args_with_read_only_git_and_codex_subpaths)
- just fix -p codex-core -p codex-protocol -p codex-app-server -p codex-api -p codex-exec -p codex-mcp-server -p codex-tui
This commit is contained in:
Friel
2026-03-06 19:42:35 -08:00
parent 22ac6b9aaa
commit 043a059919
25 changed files with 438 additions and 9 deletions
+10
View File
@@ -233,6 +233,11 @@ const fn default_effective_context_window_percent() -> i64 {
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, TS, JsonSchema)]
pub struct ModelInfo {
pub slug: String,
/// Provider-facing model slug to send on API requests.
///
/// When unset, `slug` is used.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub request_model: Option<String>,
pub display_name: String,
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -285,6 +290,10 @@ pub struct ModelInfo {
}
impl ModelInfo {
pub fn request_model_slug(&self) -> &str {
self.request_model.as_deref().unwrap_or(self.slug.as_str())
}
pub fn auto_compact_token_limit(&self) -> Option<i64> {
let context_limit = self
.context_window
@@ -510,6 +519,7 @@ mod tests {
fn test_model(spec: Option<ModelMessages>) -> ModelInfo {
ModelInfo {
slug: "test-model".to_string(),
request_model: None,
display_name: "Test Model".to_string(),
description: None,
default_reasoning_level: None,