mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:32:32 +00:00
fix(core/agents): default codex to gpt-5.3 and align CLI checks
This commit is contained in:
@@ -35,7 +35,7 @@ const CLOUD_GPT5_CODEX_WRITE: &[&str] = &[];
|
||||
pub const DEFAULT_AGENT_NAMES: &[&str] = &[
|
||||
// Frontline for moderate/challenging tasks
|
||||
"code-gpt-5.2",
|
||||
"code-gpt-5.2-codex",
|
||||
"code-gpt-5.3-codex",
|
||||
"claude-opus-4.6",
|
||||
"gemini-3-pro",
|
||||
// Straightforward / cost-aware
|
||||
@@ -107,18 +107,20 @@ const AGENT_MODEL_SPECS: &[AgentModelSpec] = &[
|
||||
is_frontline: true,
|
||||
},
|
||||
AgentModelSpec {
|
||||
slug: "code-gpt-5.2-codex",
|
||||
slug: "code-gpt-5.3-codex",
|
||||
family: "code",
|
||||
cli: "coder",
|
||||
read_only_args: CODE_GPT5_CODEX_READ_ONLY,
|
||||
write_args: CODE_GPT5_CODEX_WRITE,
|
||||
model_args: &["--model", "gpt-5.2-codex"],
|
||||
model_args: &["--model", "gpt-5.3-codex"],
|
||||
description: "Primary coding agent for implementation and multi-file edits; strong speed and reliability.",
|
||||
enabled_by_default: true,
|
||||
aliases: &[
|
||||
"code-gpt-5.2-codex",
|
||||
"code-gpt-5.1-codex-max",
|
||||
"code-gpt-5.1-codex",
|
||||
"code-gpt-5-codex",
|
||||
"gpt-5.3-codex",
|
||||
"gpt-5.2-codex",
|
||||
"gpt-5.1-codex-max",
|
||||
"gpt-5.1-codex",
|
||||
@@ -444,10 +446,17 @@ mod tests {
|
||||
#[test]
|
||||
fn gpt_codex_aliases_resolve() {
|
||||
let codex = agent_model_spec("gpt-5.1-codex").expect("alias for codex present");
|
||||
assert_eq!(codex.slug, "code-gpt-5.2-codex");
|
||||
assert_eq!(codex.slug, "code-gpt-5.3-codex");
|
||||
|
||||
let codex_direct = agent_model_spec("gpt-5.1-codex-max").expect("codex present");
|
||||
assert_eq!(codex_direct.slug, "code-gpt-5.2-codex");
|
||||
assert_eq!(codex_direct.slug, "code-gpt-5.3-codex");
|
||||
|
||||
let codex_upgrade = agent_model_spec("gpt-5.2-codex").expect("upgrade alias present");
|
||||
assert_eq!(codex_upgrade.slug, "code-gpt-5.3-codex");
|
||||
|
||||
let codex_slug_upgrade =
|
||||
agent_model_spec("code-gpt-5.2-codex").expect("slug upgrade alias present");
|
||||
assert_eq!(codex_slug_upgrade.slug, "code-gpt-5.3-codex");
|
||||
|
||||
let mini = agent_model_spec("gpt-5.1-codex-mini").expect("mini alias present");
|
||||
assert_eq!(mini.slug, "code-gpt-5.1-codex-mini");
|
||||
|
||||
@@ -2061,7 +2061,7 @@ pub fn create_agent_tool(allowed_models: &[String]) -> OpenAiTool {
|
||||
},
|
||||
}),
|
||||
description: Some(
|
||||
"Optional array of model names (e.g., ['code-gpt-5.2','claude-sonnet-4.5','code-gpt-5.2-codex','gemini-3-flash'])".to_string(),
|
||||
"Optional array of model names (e.g., ['code-gpt-5.2','claude-sonnet-4.5','code-gpt-5.3-codex','gemini-3-flash'])".to_string(),
|
||||
),
|
||||
},
|
||||
);
|
||||
@@ -2513,7 +2513,7 @@ mod tests {
|
||||
|
||||
fn agent_with_command(command: &str) -> AgentConfig {
|
||||
AgentConfig {
|
||||
name: "code-gpt-5.2-codex".to_string(),
|
||||
name: "code-gpt-5.3-codex".to_string(),
|
||||
command: command.to_string(),
|
||||
args: Vec::new(),
|
||||
read_only: false,
|
||||
@@ -2577,7 +2577,7 @@ mod tests {
|
||||
|
||||
let output = execute_model_with_permissions(
|
||||
"agent-test",
|
||||
"code-gpt-5.2-codex",
|
||||
"code-gpt-5.3-codex",
|
||||
"ok",
|
||||
true,
|
||||
None,
|
||||
|
||||
@@ -1161,7 +1161,7 @@ impl Config {
|
||||
|| agent.name.eq_ignore_ascii_case("cloud")
|
||||
{
|
||||
tracing::warn!(
|
||||
"legacy agent name '{}' detected; update config to use model slugs (e.g., code-gpt-5.2-codex)",
|
||||
"legacy agent name '{}' detected; update config to use model slugs (e.g., code-gpt-5.3-codex)",
|
||||
agent.name
|
||||
);
|
||||
}
|
||||
@@ -2618,7 +2618,7 @@ model_verbosity = "high"
|
||||
|
||||
let mut cfg = fixture.cfg.clone();
|
||||
cfg.agents = vec![AgentConfig {
|
||||
name: "code-gpt-5.2-codex".to_string(),
|
||||
name: "code-gpt-5.3-codex".to_string(),
|
||||
command: String::new(),
|
||||
args: Vec::new(),
|
||||
read_only: false,
|
||||
@@ -2648,7 +2648,7 @@ model_verbosity = "high"
|
||||
.map(|agent| agent.name.to_ascii_lowercase())
|
||||
.collect();
|
||||
|
||||
assert!(enabled_names.contains("code-gpt-5.2-codex"));
|
||||
assert!(enabled_names.contains("code-gpt-5.3-codex"));
|
||||
assert!(enabled_names.contains("code-gpt-5.2"));
|
||||
assert!(enabled_names.contains("claude-sonnet-4.5"));
|
||||
assert!(enabled_names.contains("gemini-3-pro"));
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::agent_defaults::agent_model_spec;
|
||||
use crate::agent_defaults::enabled_agent_model_specs;
|
||||
use crate::config_types::AgentConfig;
|
||||
use crate::config_types::SubagentCommandConfig;
|
||||
use crate::external_agent_command_exists;
|
||||
|
||||
// NOTE: These are the prompt formatters for the prompt‑expanding slash commands
|
||||
// (/plan, /solve, /code). If you add or change a slash command, please update
|
||||
@@ -9,34 +10,7 @@ use crate::config_types::SubagentCommandConfig;
|
||||
// with the UI and behavior.
|
||||
|
||||
fn command_exists(cmd: &str) -> bool {
|
||||
if cmd.contains(std::path::MAIN_SEPARATOR) || cmd.contains('/') || cmd.contains('\\') {
|
||||
return std::fs::metadata(cmd).map(|m| m.is_file()).unwrap_or(false);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
which::which(cmd).map(|p| p.is_file()).unwrap_or(false)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let Some(path_os) = std::env::var_os("PATH") else {
|
||||
return false;
|
||||
};
|
||||
for dir in std::env::split_paths(&path_os) {
|
||||
if dir.as_os_str().is_empty() {
|
||||
continue;
|
||||
}
|
||||
let candidate = dir.join(cmd);
|
||||
if let Ok(meta) = std::fs::metadata(&candidate) {
|
||||
if meta.is_file() && (meta.permissions().mode() & 0o111 != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
external_agent_command_exists(cmd)
|
||||
}
|
||||
|
||||
/// Get the list of enabled agent names from the configuration
|
||||
@@ -293,29 +267,78 @@ pub fn handle_slash_command(input: &str, agents: Option<&[AgentConfig]>) -> Opti
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::ffi::OsString;
|
||||
use std::sync::{LazyLock, Mutex};
|
||||
use tempfile::tempdir;
|
||||
|
||||
static ENV_LOCK: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
|
||||
|
||||
fn restore_var(name: &str, value: Option<OsString>) {
|
||||
match value {
|
||||
Some(v) => unsafe { std::env::set_var(name, v) },
|
||||
None => unsafe { std::env::remove_var(name) },
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_models_skip_missing_agent_clis() {
|
||||
let _guard = ENV_LOCK.lock().expect("env lock");
|
||||
let orig_path = std::env::var_os("PATH");
|
||||
let orig_home = std::env::var_os("HOME");
|
||||
let orig_claude_config_dir = std::env::var_os("CLAUDE_CONFIG_DIR");
|
||||
let fake_home = tempdir().expect("temp home");
|
||||
|
||||
unsafe {
|
||||
std::env::set_var("PATH", "");
|
||||
std::env::set_var("HOME", fake_home.path());
|
||||
std::env::remove_var("CLAUDE_CONFIG_DIR");
|
||||
}
|
||||
|
||||
let defaults = get_default_models();
|
||||
assert!(defaults.iter().any(|v| v == "code-gpt-5.2"));
|
||||
assert!(defaults.iter().any(|v| v == "code-gpt-5.3-codex"));
|
||||
assert!(!defaults.iter().any(|v| v == "qwen-3-coder"));
|
||||
assert!(!defaults.iter().any(|v| v == "gemini-3-flash"));
|
||||
assert!(!defaults.iter().any(|v| v == "claude-sonnet-4.5"));
|
||||
|
||||
if let Some(path) = orig_path {
|
||||
unsafe {
|
||||
std::env::set_var("PATH", path);
|
||||
}
|
||||
} else {
|
||||
unsafe {
|
||||
std::env::remove_var("PATH");
|
||||
}
|
||||
restore_var("PATH", orig_path);
|
||||
restore_var("HOME", orig_home);
|
||||
restore_var("CLAUDE_CONFIG_DIR", orig_claude_config_dir);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[test]
|
||||
fn default_models_include_claude_when_home_fallback_exists() {
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
let _guard = ENV_LOCK.lock().expect("env lock");
|
||||
let orig_path = std::env::var_os("PATH");
|
||||
let orig_home = std::env::var_os("HOME");
|
||||
let orig_claude_config_dir = std::env::var_os("CLAUDE_CONFIG_DIR");
|
||||
|
||||
let fake_home = tempdir().expect("temp home");
|
||||
let claude_dir = fake_home.path().join(".claude").join("local");
|
||||
std::fs::create_dir_all(&claude_dir).expect("create fallback dir");
|
||||
let claude_path = claude_dir.join("claude");
|
||||
std::fs::write(&claude_path, "#!/bin/sh\nexit 0\n").expect("write fallback binary");
|
||||
let mut perms = std::fs::metadata(&claude_path)
|
||||
.expect("stat fallback binary")
|
||||
.permissions();
|
||||
perms.set_mode(0o755);
|
||||
std::fs::set_permissions(&claude_path, perms).expect("chmod fallback binary");
|
||||
|
||||
unsafe {
|
||||
std::env::set_var("PATH", "");
|
||||
std::env::set_var("HOME", fake_home.path());
|
||||
std::env::remove_var("CLAUDE_CONFIG_DIR");
|
||||
}
|
||||
|
||||
let defaults = get_default_models();
|
||||
assert!(defaults.iter().any(|v| v == "claude-sonnet-4.5"));
|
||||
|
||||
restore_var("PATH", orig_path);
|
||||
restore_var("HOME", orig_home);
|
||||
restore_var("CLAUDE_CONFIG_DIR", orig_claude_config_dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -327,6 +350,7 @@ mod tests {
|
||||
assert!(plan_prompt.contains("final, comprehensive plan"));
|
||||
// Default agents list should include non-Codex providers when no [[agents]] configured
|
||||
assert!(plan_prompt.contains("code-gpt-5.2"));
|
||||
assert!(plan_prompt.contains("code-gpt-5.3-codex"));
|
||||
assert!(!plan_prompt.contains("cloud-gpt-5.1-codex-max"));
|
||||
|
||||
// Test /solve command
|
||||
|
||||
Reference in New Issue
Block a user