Skip to content

Commit 55fab7a

Browse files
feat(api): update Codex model catalog (#143)
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
1 parent ccd3894 commit 55fab7a

9 files changed

Lines changed: 133 additions & 91 deletions

File tree

docs/providers.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,22 @@ Runs Claude-style coding sessions against OpenAI's Codex using your ChatGPT/Code
7676

7777
**Authentication:** Sign in with `coven-code codex login` (ChatGPT/Codex OAuth). Tokens are stored per profile under `~/.coven-code/accounts/codex/<id>/`. See [auth.md](auth.md) for the multi-account flow.
7878

79-
**Default model:** `gpt-5.2-codex`
79+
**Default model:** `gpt-5.5`
80+
81+
**Bundled Codex model list:**
82+
83+
| Model ID | Notes |
84+
|---|---|
85+
| `gpt-5.5` | Default; recommended for most Codex tasks |
86+
| `gpt-5.4` | Frontier Codex model |
87+
| `gpt-5.4-mini` | Fast/lower-cost model for lighter coding tasks and subagents |
88+
| `gpt-5.3-codex-spark` | Research preview for ChatGPT Pro users |
89+
| `gpt-5.3-codex` | Deprecated for ChatGPT sign-in; retained for explicit selection |
90+
| `gpt-5.2-codex` | Deprecated for ChatGPT sign-in; retained for explicit selection |
91+
| `gpt-5.1-codex` | Legacy Codex model |
92+
| `gpt-5.1-codex-mini` | Legacy mini model |
93+
| `gpt-5.1-codex-max` | Legacy max model |
94+
| `gpt-5.2` | Deprecated for ChatGPT sign-in; retained for explicit selection |
8095

8196
**Configuration:**
8297

src-rust/crates/api/src/model_registry.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,7 @@ fn flagship_patterns_for(provider_id: &str) -> &'static [&'static str] {
10011001
],
10021002
"zai" => &["glm-5.1", "glm-5", "glm-4.7"],
10031003
"minimax" => &["minimax-m2"],
1004-
"codex" | "openai-codex" => &["gpt-5.2-codex", "gpt-5.1-codex"],
1004+
"codex" | "openai-codex" => &["gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex-spark"],
10051005
"ollama" | "lmstudio" | "lm-studio" | "llamacpp" | "llama-cpp" => &[
10061006
"qwen3-coder",
10071007
"qwen2.5-coder",
@@ -1049,7 +1049,7 @@ fn codex_models_fallback(provider_id: &str, small: bool) -> Option<String> {
10491049
fn small_patterns_for(provider_id: &str) -> &'static [&'static str] {
10501050
match provider_id {
10511051
"anthropic" => &["claude-haiku-4", "claude-haiku-3-5", "claude-haiku"],
1052-
"codex" | "openai" | "openai-codex" => &["gpt-5.1-codex-mini", "gpt-5-mini"],
1052+
"codex" | "openai" | "openai-codex" => &["gpt-5.4-mini", "gpt-5-mini"],
10531053
_ => &["mini", "haiku", "flash", "lite", "small", "nano"],
10541054
}
10551055
}
@@ -1189,15 +1189,19 @@ mod tests {
11891189
.best_model_for_provider("codex")
11901190
.expect("codex best model must fall back to CODEX_MODELS default");
11911191
assert!(
1192-
best.contains("codex"),
1193-
"best codex model should look like a codex id, got {best:?}"
1192+
claurst_core::codex_oauth::CODEX_MODELS
1193+
.iter()
1194+
.any(|(id, _)| *id == best),
1195+
"best codex model should come from CODEX_MODELS, got {best:?}"
11941196
);
11951197
let small = reg
11961198
.best_small_model_for_provider("codex")
11971199
.expect("codex small model must fall back to a mini/default id");
11981200
assert!(
1199-
small.contains("codex"),
1200-
"small codex model should look like a codex id, got {small:?}"
1201+
claurst_core::codex_oauth::CODEX_MODELS
1202+
.iter()
1203+
.any(|(id, _)| *id == small),
1204+
"small codex model should come from CODEX_MODELS, got {small:?}"
12011205
);
12021206
// The alias `openai-codex` must take the same path.
12031207
assert!(reg.best_model_for_provider("openai-codex").is_some());

src-rust/crates/api/src/providers/codex.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -918,12 +918,21 @@ impl LlmProvider for CodexProvider {
918918
provider_id: self.id.clone(),
919919
name: name.to_string(),
920920
context_window: match *id {
921-
"gpt-5.4" | "gpt-5-codex" | "gpt-5-mini" => 400_000,
921+
"gpt-5.5" | "gpt-5.4" => 1_050_000,
922+
"gpt-5.4-mini" | "gpt-5.3-codex" | "gpt-5.2-codex" | "gpt-5.1-codex"
923+
| "gpt-5.1-codex-mini" | "gpt-5.1-codex-max" | "gpt-5.2" | "gpt-5-codex"
924+
| "gpt-5-mini" => 400_000,
925+
"gpt-5.3-codex-spark" => 128_000,
922926
"gpt-4.1" => 128_000,
923927
"o4-mini" => 200_000,
924928
_ => 128_000,
925929
},
926-
max_output_tokens: 32_768,
930+
max_output_tokens: match *id {
931+
"gpt-5.5" | "gpt-5.4" | "gpt-5.4-mini" | "gpt-5.3-codex" | "gpt-5.2-codex"
932+
| "gpt-5.1-codex" | "gpt-5.1-codex-mini" | "gpt-5.1-codex-max" | "gpt-5.2"
933+
| "gpt-5-codex" | "gpt-5-mini" => 128_000,
934+
_ => 32_768,
935+
},
927936
})
928937
.collect();
929938
Ok(models)

src-rust/crates/commands/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ impl SlashCommand for ModelCommand {
773773
/model — open the model picker\n\
774774
/model claude-sonnet-4-6 — switch to Claude Sonnet 4.6\n\
775775
/model claude-haiku-4-5 — switch to Claude Haiku 4.5\n\
776-
/model codex/gpt-5.2-codex — switch to Codex (requires codex login)"
776+
/model codex/gpt-5.5 — switch to Codex (requires codex login)"
777777
}
778778

779779
async fn execute(&self, args: &str, ctx: &mut CommandContext) -> CommandResult {
Lines changed: 81 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,81 @@
1-
//! OpenAI Codex OAuth configuration and constants.
2-
//!
3-
4-
/// OpenAI Codex OAuth client ID (shared with the OpenCode ecosystem).
5-
pub const CODEX_CLIENT_ID: &str = "app_EMoamEEZ73f0CkXaXp7hrann";
6-
7-
/// OpenAI OAuth issuer base URL.
8-
pub const CODEX_ISSUER: &str = "https://auth.openai.com";
9-
10-
/// OpenAI OAuth authorization endpoint
11-
pub const CODEX_AUTHORIZE_URL: &str = "https://auth.openai.com/oauth/authorize";
12-
13-
/// OpenAI OAuth token endpoint
14-
pub const CODEX_TOKEN_URL: &str = "https://auth.openai.com/oauth/token";
15-
16-
/// Codex Responses API endpoint (used for inference after login)
17-
pub const CODEX_API_ENDPOINT: &str = "https://chatgpt.com/backend-api/codex/responses";
18-
19-
/// Local redirect URI for OAuth callback
20-
pub const CODEX_REDIRECT_URI: &str = "http://localhost:1455/auth/callback";
21-
22-
/// OAuth callback port
23-
pub const CODEX_OAUTH_PORT: u16 = 1455;
24-
25-
/// OAuth scopes requested from OpenAI
26-
pub const CODEX_SCOPES: &str = "openid profile email offline_access";
27-
28-
/// Available Codex models
29-
pub const CODEX_MODELS: &[(&str, &str)] = &[
30-
("gpt-5.2-codex", "GPT-5.2 Codex (default)"),
31-
("gpt-5.1-codex", "GPT-5.1 Codex"),
32-
("gpt-5.1-codex-mini", "GPT-5.1 Codex Mini"),
33-
("gpt-5.1-codex-max", "GPT-5.1 Codex Max"),
34-
("gpt-5.4", "GPT-5.4"),
35-
("gpt-5.2", "GPT-5.2"),
36-
];
37-
38-
/// Default Codex model to use
39-
pub const DEFAULT_CODEX_MODEL: &str = "gpt-5.2-codex";
40-
41-
#[cfg(test)]
42-
mod tests {
43-
use super::*;
44-
45-
#[test]
46-
fn test_codex_constants_not_empty() {
47-
assert!(!CODEX_CLIENT_ID.is_empty());
48-
assert!(!CODEX_AUTHORIZE_URL.is_empty());
49-
assert!(!CODEX_TOKEN_URL.is_empty());
50-
assert!(!CODEX_REDIRECT_URI.is_empty());
51-
assert!(!CODEX_SCOPES.is_empty());
52-
assert!(!CODEX_MODELS.is_empty());
53-
assert!(!DEFAULT_CODEX_MODEL.is_empty());
54-
}
55-
56-
#[test]
57-
fn test_codex_models_contains_default() {
58-
let default_found = CODEX_MODELS
59-
.iter()
60-
.any(|(model, _)| model == &DEFAULT_CODEX_MODEL);
61-
assert!(
62-
default_found,
63-
"DEFAULT_CODEX_MODEL must be in CODEX_MODELS list"
64-
);
65-
}
66-
67-
#[test]
68-
fn test_redirect_uri_is_localhost() {
69-
assert!(CODEX_REDIRECT_URI.contains("localhost:1455"));
70-
}
71-
}
1+
//! OpenAI Codex OAuth configuration and constants.
2+
//!
3+
4+
/// OpenAI Codex OAuth client ID (shared with the OpenCode ecosystem).
5+
pub const CODEX_CLIENT_ID: &str = "app_EMoamEEZ73f0CkXaXp7hrann";
6+
7+
/// OpenAI OAuth issuer base URL.
8+
pub const CODEX_ISSUER: &str = "https://auth.openai.com";
9+
10+
/// OpenAI OAuth authorization endpoint
11+
pub const CODEX_AUTHORIZE_URL: &str = "https://auth.openai.com/oauth/authorize";
12+
13+
/// OpenAI OAuth token endpoint
14+
pub const CODEX_TOKEN_URL: &str = "https://auth.openai.com/oauth/token";
15+
16+
/// Codex Responses API endpoint (used for inference after login)
17+
pub const CODEX_API_ENDPOINT: &str = "https://chatgpt.com/backend-api/codex/responses";
18+
19+
/// Local redirect URI for OAuth callback
20+
pub const CODEX_REDIRECT_URI: &str = "http://localhost:1455/auth/callback";
21+
22+
/// OAuth callback port
23+
pub const CODEX_OAUTH_PORT: u16 = 1455;
24+
25+
/// OAuth scopes requested from OpenAI
26+
pub const CODEX_SCOPES: &str = "openid profile email offline_access";
27+
28+
/// Available Codex models
29+
pub const CODEX_MODELS: &[(&str, &str)] = &[
30+
("gpt-5.5", "GPT-5.5 (default)"),
31+
("gpt-5.4", "GPT-5.4"),
32+
("gpt-5.4-mini", "GPT-5.4 Mini"),
33+
("gpt-5.3-codex-spark", "GPT-5.3 Codex Spark (Pro preview)"),
34+
(
35+
"gpt-5.3-codex",
36+
"GPT-5.3 Codex (deprecated for ChatGPT sign-in)",
37+
),
38+
(
39+
"gpt-5.2-codex",
40+
"GPT-5.2 Codex (deprecated for ChatGPT sign-in)",
41+
),
42+
("gpt-5.1-codex", "GPT-5.1 Codex"),
43+
("gpt-5.1-codex-mini", "GPT-5.1 Codex Mini"),
44+
("gpt-5.1-codex-max", "GPT-5.1 Codex Max"),
45+
("gpt-5.2", "GPT-5.2"),
46+
];
47+
48+
/// Default Codex model to use
49+
pub const DEFAULT_CODEX_MODEL: &str = "gpt-5.5";
50+
51+
#[cfg(test)]
52+
mod tests {
53+
use super::*;
54+
55+
#[test]
56+
fn test_codex_constants_not_empty() {
57+
assert!(!CODEX_CLIENT_ID.is_empty());
58+
assert!(!CODEX_AUTHORIZE_URL.is_empty());
59+
assert!(!CODEX_TOKEN_URL.is_empty());
60+
assert!(!CODEX_REDIRECT_URI.is_empty());
61+
assert!(!CODEX_SCOPES.is_empty());
62+
assert!(!CODEX_MODELS.is_empty());
63+
assert!(!DEFAULT_CODEX_MODEL.is_empty());
64+
}
65+
66+
#[test]
67+
fn test_codex_models_contains_default() {
68+
let default_found = CODEX_MODELS
69+
.iter()
70+
.any(|(model, _)| model == &DEFAULT_CODEX_MODEL);
71+
assert!(
72+
default_found,
73+
"DEFAULT_CODEX_MODEL must be in CODEX_MODELS list"
74+
);
75+
}
76+
77+
#[test]
78+
fn test_redirect_uri_is_localhost() {
79+
assert!(CODEX_REDIRECT_URI.contains("localhost:1455"));
80+
}
81+
}

src-rust/crates/core/src/lib.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -832,17 +832,17 @@ pub mod config {
832832
ManagedAgentPreset {
833833
name: "codex-tiered",
834834
label: "Codex Tiered",
835-
description: "gpt-5.2-codex manages, gpt-5.1-codex-mini executes",
836-
manager_model: "codex/gpt-5.2-codex",
837-
executor_model: "codex/gpt-5.1-codex-mini",
835+
description: "gpt-5.5 manages, gpt-5.4-mini executes",
836+
manager_model: "codex/gpt-5.5",
837+
executor_model: "codex/gpt-5.4-mini",
838838
executor_max_turns: 10,
839839
max_concurrent_executors: 4,
840840
},
841841
ManagedAgentPreset {
842842
name: "cross-codex-anthropic",
843843
label: "Cross: Codex + Claude",
844-
description: "gpt-5.2-codex manages, Sonnet 4.6 executes",
845-
manager_model: "codex/gpt-5.2-codex",
844+
description: "gpt-5.5 manages, Sonnet 4.6 executes",
845+
manager_model: "codex/gpt-5.5",
846846
executor_model: "anthropic/claude-sonnet-4-6",
847847
executor_max_turns: 10,
848848
max_concurrent_executors: 4,
@@ -1322,7 +1322,9 @@ pub mod config {
13221322
return m;
13231323
}
13241324
match self.provider.as_deref() {
1325-
Some("openai") | Some("codex") | Some("openai-codex") => "gpt-5.2-codex",
1325+
Some("openai") | Some("codex") | Some("openai-codex") => {
1326+
crate::codex_oauth::DEFAULT_CODEX_MODEL
1327+
}
13261328
_ => crate::constants::DEFAULT_MODEL, // Anthropic default
13271329
}
13281330
}

src-rust/crates/tui/src/dialog_select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ mod tests {
445445
SelectItem {
446446
id: "codex".into(),
447447
title: "Codex".into(),
448-
description: "gpt-5.2-codex via ChatGPT".into(),
448+
description: "gpt-5.5 via ChatGPT".into(),
449449
category: "Recommended".into(),
450450
badge: None,
451451
},

src-rust/crates/tui/src/model_picker.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,10 @@ fn codex_provider_models() -> Vec<ModelEntry> {
361361
.iter()
362362
.map(|(id, name)| {
363363
let ctx = match *id {
364-
"gpt-5.4" | "gpt-5.2" | "gpt-5.2-codex" | "gpt-5.1-codex"
365-
| "gpt-5.1-codex-mini" | "gpt-5.1-codex-max" => "400K ctx",
364+
"gpt-5.5" | "gpt-5.4" => "1M ctx",
365+
"gpt-5.4-mini" | "gpt-5.3-codex" | "gpt-5.2" | "gpt-5.2-codex"
366+
| "gpt-5.1-codex" | "gpt-5.1-codex-mini" | "gpt-5.1-codex-max" => "400K ctx",
367+
"gpt-5.3-codex-spark" => "128K ctx",
366368
_ => "128K ctx",
367369
};
368370
ModelEntry {

src-rust/crates/tui/src/onboarding_dialog.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ const PROVIDER_ENTRIES: &[ProviderEntry] = &[
165165
},
166166
ProviderEntry {
167167
name: "Codex",
168-
tagline: " gpt-5.2-codex via Codex CLI login",
168+
tagline: " gpt-5.5 via Codex CLI login",
169169
setup: "Codex CLI",
170170
setup_suffix: "",
171171
},

0 commit comments

Comments
 (0)