mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-05 08:10:39 +00:00
Add gpt-5.3-codex model and make it the default codex alias
- Add gpt-5.3-codex to catalog (API model, 1047576 context, 128K output) - Move "codex" alias from gpt-5.2-codex to gpt-5.3-codex - Add e2e integration test for gpt-5.3-codex via OpenAI API - Remove gpt-5.3-codex-spark (not yet available) - Empty CLI_ONLY_MODELS list and update related tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
bb5f9899ed
commit
2750da01c6
5 changed files with 43 additions and 40 deletions
|
|
@ -12,7 +12,7 @@ use crate::handler::codergen::{CodergenBackend, CodergenResult};
|
|||
use crate::outcome::StageUsage;
|
||||
|
||||
/// Models that are only available through CLI tools (not via API).
|
||||
const CLI_ONLY_MODELS: &[&str] = &["gpt-5.3-codex-spark"];
|
||||
const CLI_ONLY_MODELS: &[&str] = &[];
|
||||
|
||||
/// Returns true if the given model is only available through a CLI tool.
|
||||
#[must_use]
|
||||
|
|
@ -410,9 +410,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn cli_command_for_codex() {
|
||||
let cmd = cli_command_for_provider("openai", "gpt-5.3-codex-spark", "/tmp/prompt.txt");
|
||||
let cmd = cli_command_for_provider("openai", "gpt-5.3-codex", "/tmp/prompt.txt");
|
||||
assert!(cmd.starts_with("codex exec --json --full-auto"));
|
||||
assert!(cmd.contains("-m gpt-5.3-codex-spark"));
|
||||
assert!(cmd.contains("-m gpt-5.3-codex"));
|
||||
assert!(cmd.ends_with("< /tmp/prompt.txt"));
|
||||
}
|
||||
|
||||
|
|
@ -455,17 +455,9 @@ mod tests {
|
|||
// -- Cycle 2: is_cli_only_model --
|
||||
|
||||
#[test]
|
||||
fn codex_spark_is_cli_only() {
|
||||
assert!(is_cli_only_model("gpt-5.3-codex-spark"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn claude_opus_is_not_cli_only() {
|
||||
fn no_models_are_currently_cli_only() {
|
||||
assert!(!is_cli_only_model("gpt-5.3-codex"));
|
||||
assert!(!is_cli_only_model("claude-opus-4-6"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gemini_is_not_cli_only() {
|
||||
assert!(!is_cli_only_model("gemini-3.1-pro-preview"));
|
||||
}
|
||||
|
||||
|
|
@ -583,22 +575,6 @@ mod tests {
|
|||
assert!(router.should_use_cli(&node));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn router_uses_cli_for_cli_only_model() {
|
||||
let mut node = Node::new("test");
|
||||
node.attrs.insert(
|
||||
"llm_model".to_string(),
|
||||
AttrValue::String("gpt-5.3-codex-spark".to_string()),
|
||||
);
|
||||
|
||||
let cli_backend = CliBackend::new("model".into(), "openai".into());
|
||||
let router = BackendRouter::new(
|
||||
Box::new(StubBackend),
|
||||
cli_backend,
|
||||
);
|
||||
assert!(router.should_use_cli(&node));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn router_uses_api_by_default() {
|
||||
let node = Node::new("test");
|
||||
|
|
|
|||
|
|
@ -7401,7 +7401,7 @@ async fn cli_backend_run_with_codex_provider() {
|
|||
let codex_output = "{\"type\":\"item.completed\",\"item\":{\"id\":\"item_0\",\"type\":\"agent_message\",\"text\":\"Implemented the feature.\"}}\n{\"type\":\"turn.completed\",\"usage\":{\"input_tokens\":300,\"output_tokens\":150}}";
|
||||
let test_env = Arc::new(CliTestEnv::new(codex_output));
|
||||
let env: Arc<dyn agent::ExecutionEnvironment> = test_env.clone();
|
||||
let backend = CliBackend::new("gpt-5.3-codex-spark".into(), "openai".into());
|
||||
let backend = CliBackend::new("gpt-5.3-codex".into(), "openai".into());
|
||||
|
||||
let node = Node::new("implement");
|
||||
let context = Context::new();
|
||||
|
|
@ -7417,7 +7417,7 @@ async fn cli_backend_run_with_codex_provider() {
|
|||
let commands = test_env.recorded_commands();
|
||||
let cli_cmd = commands.iter().find(|c| c.contains("codex")).expect("should call codex CLI");
|
||||
assert!(cli_cmd.contains("exec --json"), "should use exec mode");
|
||||
assert!(cli_cmd.contains("gpt-5.3-codex-spark"), "should use correct model");
|
||||
assert!(cli_cmd.contains("gpt-5.3-codex"), "should use correct model");
|
||||
|
||||
match result {
|
||||
CodergenResult::Text { text, usage, .. } => {
|
||||
|
|
@ -7536,7 +7536,7 @@ async fn cli_backend_run_uses_node_provider_override() {
|
|||
|
||||
let mut node = Node::new("step");
|
||||
node.attrs.insert("llm_provider".to_string(), AttrValue::String("openai".to_string()));
|
||||
node.attrs.insert("llm_model".to_string(), AttrValue::String("gpt-5.3-codex-spark".to_string()));
|
||||
node.attrs.insert("llm_model".to_string(), AttrValue::String("gpt-5.3-codex".to_string()));
|
||||
|
||||
let context = Context::new();
|
||||
let emitter = Arc::new(EventEmitter::new());
|
||||
|
|
@ -7549,7 +7549,7 @@ async fn cli_backend_run_uses_node_provider_override() {
|
|||
|
||||
let commands = test_env.recorded_commands();
|
||||
let cli_cmd = commands.iter().find(|c| c.contains("codex")).expect("should call codex based on provider override");
|
||||
assert!(cli_cmd.contains("gpt-5.3-codex-spark"));
|
||||
assert!(cli_cmd.contains("gpt-5.3-codex"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -7640,16 +7640,16 @@ async fn backend_router_delegates_to_api_for_normal_node() {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn backend_router_delegates_to_cli_for_cli_only_model() {
|
||||
async fn backend_router_delegates_to_cli_for_backend_attr() {
|
||||
let codex_output = "{\"type\":\"item.completed\",\"item\":{\"id\":\"item_0\",\"type\":\"agent_message\",\"text\":\"Codex did it\"}}\n{\"type\":\"turn.completed\",\"usage\":{\"input_tokens\":10,\"output_tokens\":5}}";
|
||||
let env: Arc<dyn agent::ExecutionEnvironment> = Arc::new(CliTestEnv::new(codex_output));
|
||||
|
||||
let api_backend = Box::new(MockCodergenBackend);
|
||||
let cli = CliBackend::new("gpt-5.3-codex-spark".into(), "openai".into());
|
||||
let cli = CliBackend::new("gpt-5.3-codex".into(), "openai".into());
|
||||
let router = BackendRouter::new(api_backend, cli);
|
||||
|
||||
let mut node = Node::new("codex_step");
|
||||
node.attrs.insert("llm_model".to_string(), AttrValue::String("gpt-5.3-codex-spark".to_string()));
|
||||
node.attrs.insert("backend".to_string(), AttrValue::String("cli".to_string()));
|
||||
node.attrs.insert("llm_provider".to_string(), AttrValue::String("openai".to_string()));
|
||||
|
||||
let context = Context::new();
|
||||
|
|
@ -7663,7 +7663,7 @@ async fn backend_router_delegates_to_cli_for_cli_only_model() {
|
|||
|
||||
match result {
|
||||
CodergenResult::Text { text, .. } => {
|
||||
assert_eq!(text, "Codex did it", "should route to CLI backend for CLI-only model");
|
||||
assert_eq!(text, "Codex did it", "should route to CLI backend for backend=cli");
|
||||
}
|
||||
CodergenResult::Full(_) => panic!("expected Text result"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,19 @@
|
|||
"supports_reasoning": true,
|
||||
"input_cost_per_million": null,
|
||||
"output_cost_per_million": null,
|
||||
"aliases": []
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex",
|
||||
"provider": "openai",
|
||||
"display_name": "GPT-5.3 Codex",
|
||||
"context_window": 1047576,
|
||||
"max_output": 128000,
|
||||
"supports_tools": true,
|
||||
"supports_vision": true,
|
||||
"supports_reasoning": true,
|
||||
"input_cost_per_million": null,
|
||||
"output_cost_per_million": null,
|
||||
"aliases": ["codex"]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ mod tests {
|
|||
assert_eq!(info.id, "claude-sonnet-4-5");
|
||||
|
||||
let info = get_model_info("codex").unwrap();
|
||||
assert_eq!(info.id, "gpt-5.2-codex");
|
||||
assert_eq!(info.id, "gpt-5.3-codex");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -62,7 +62,7 @@ mod tests {
|
|||
#[test]
|
||||
fn list_models_all() {
|
||||
let models = list_models(None);
|
||||
assert_eq!(models.len(), 8);
|
||||
assert_eq!(models.len(), 9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -72,7 +72,7 @@ mod tests {
|
|||
assert!(anthropic.iter().all(|m| m.provider == "anthropic"));
|
||||
|
||||
let openai = list_models(Some("openai"));
|
||||
assert_eq!(openai.len(), 3);
|
||||
assert_eq!(openai.len(), 4);
|
||||
|
||||
let gemini = list_models(Some("gemini"));
|
||||
assert_eq!(gemini.len(), 2);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,20 @@ async fn openai_complete() {
|
|||
assert_eq!(response.provider, "openai");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore = "requires OPENAI_API_KEY"]
|
||||
async fn openai_gpt_5_3_codex_complete() {
|
||||
let api_key = std::env::var("OPENAI_API_KEY").expect("OPENAI_API_KEY must be set");
|
||||
let adapter = OpenAiAdapter::new(api_key);
|
||||
let request = make_request("gpt-5.3-codex");
|
||||
let response = adapter.complete(&request).await.unwrap();
|
||||
|
||||
assert!(!response.text().is_empty(), "response text should not be empty");
|
||||
assert!(response.usage.input_tokens > 0);
|
||||
assert!(response.usage.output_tokens > 0);
|
||||
assert_eq!(response.provider, "openai");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore = "requires GEMINI_API_KEY"]
|
||||
async fn gemini_complete() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue