mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-08 22:21:45 +00:00
Centralize model defaults in catalog, upgrade OpenAI default to gpt-5.4
Remove hardcoded default_model_for_provider() from arc-workflows and default_model() from arc-agent, delegating both to the catalog via arc_llm::catalog::default_model_for_provider(). Add claude-sonnet-4-6 to catalog and move "sonnet"/"claude-sonnet" aliases to it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
378c3eb3e3
commit
bb48b0d33b
5 changed files with 35 additions and 140 deletions
|
|
@ -95,18 +95,6 @@ impl AgentArgs {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn default_model(provider: Provider) -> &'static str {
|
||||
match provider {
|
||||
Provider::OpenAi => "gpt-5.2-codex",
|
||||
Provider::Gemini => "gemini-3.1-pro-preview",
|
||||
Provider::Anthropic => "claude-opus-4-6",
|
||||
Provider::Kimi => "kimi-k2.5",
|
||||
Provider::Zai => "glm-4.7",
|
||||
Provider::Minimax => "minimax-m2.5",
|
||||
Provider::Inception => "mercury",
|
||||
}
|
||||
}
|
||||
|
||||
fn tool_category(name: &str) -> &'static str {
|
||||
match name {
|
||||
"read_file" | "read_many_files" | "grep" | "glob" | "list_dir" => "read",
|
||||
|
|
@ -392,12 +380,13 @@ pub async fn run_with_args(args: AgentArgs) -> anyhow::Result<()> {
|
|||
}
|
||||
|
||||
// Resolve model and build profile
|
||||
let model = args
|
||||
.model
|
||||
.as_deref()
|
||||
.unwrap_or_else(|| default_model(provider));
|
||||
let model = args.model.unwrap_or_else(|| {
|
||||
arc_llm::catalog::default_model_for_provider(provider.as_str())
|
||||
.map(|m| m.id)
|
||||
.unwrap_or_else(|| provider.as_str().to_string())
|
||||
});
|
||||
eprintln!("{}", styles.dim.apply_to(format!("Using model: {model}")));
|
||||
let mut profile = build_profile(provider, model, Some(client.clone()));
|
||||
let mut profile = build_profile(provider, &model, Some(client.clone()));
|
||||
|
||||
// Build sandbox
|
||||
let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
||||
|
|
@ -692,43 +681,6 @@ mod tests {
|
|||
assert!(is_auto_approved(PermissionLevel::Full, "shell"));
|
||||
}
|
||||
|
||||
// default_model tests
|
||||
|
||||
#[test]
|
||||
fn default_model_anthropic() {
|
||||
assert_eq!(default_model(Provider::Anthropic), "claude-opus-4-6");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_openai() {
|
||||
assert_eq!(default_model(Provider::OpenAi), "gpt-5.2-codex");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_gemini() {
|
||||
assert_eq!(default_model(Provider::Gemini), "gemini-3.1-pro-preview");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_kimi() {
|
||||
assert_eq!(default_model(Provider::Kimi), "kimi-k2.5");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_zai() {
|
||||
assert_eq!(default_model(Provider::Zai), "glm-4.7");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_minimax() {
|
||||
assert_eq!(default_model(Provider::Minimax), "minimax-m2.5");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_inception() {
|
||||
assert_eq!(default_model(Provider::Inception), "mercury");
|
||||
}
|
||||
|
||||
// build_tool_approval non-interactive tests
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -1,31 +1,15 @@
|
|||
use arc_agent::cli::default_model;
|
||||
use arc_agent::{AnthropicProfile, GeminiProfile, OpenAiProfile, ProviderProfile};
|
||||
use arc_llm::catalog;
|
||||
use arc_llm::provider::Provider;
|
||||
|
||||
#[test]
|
||||
fn every_default_model_exists_in_catalog() {
|
||||
for &provider in Provider::ALL {
|
||||
let model = default_model(provider);
|
||||
assert!(
|
||||
catalog::get_model_info(model).is_some(),
|
||||
"default_model for {:?} is '{}' but it is not in the catalog",
|
||||
provider,
|
||||
model
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_context_window_matches_catalog_for_default_models() {
|
||||
for &provider in Provider::ALL {
|
||||
let model = default_model(provider);
|
||||
let catalog_info = catalog::get_model_info(model).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"default_model '{}' for {:?} not in catalog",
|
||||
model, provider
|
||||
)
|
||||
});
|
||||
let catalog_info = catalog::default_model_for_provider(provider.as_str())
|
||||
.unwrap_or_else(|| {
|
||||
panic!("no default model for {:?} in catalog", provider)
|
||||
});
|
||||
let model = &catalog_info.id;
|
||||
|
||||
let profile: Box<dyn ProviderProfile> = match provider {
|
||||
Provider::OpenAi => Box::new(OpenAiProfile::new(model)),
|
||||
|
|
|
|||
|
|
@ -26,6 +26,20 @@
|
|||
"input_cost_per_million": 3.0,
|
||||
"output_cost_per_million": 15.0,
|
||||
"estimated_output_tps": 50,
|
||||
"aliases": []
|
||||
},
|
||||
{
|
||||
"id": "claude-sonnet-4-6",
|
||||
"provider": "anthropic",
|
||||
"display_name": "Claude Sonnet 4.6",
|
||||
"context_window": 200000,
|
||||
"max_output": 64000,
|
||||
"supports_tools": true,
|
||||
"supports_vision": true,
|
||||
"supports_reasoning": true,
|
||||
"input_cost_per_million": 3.0,
|
||||
"output_cost_per_million": 15.0,
|
||||
"estimated_output_tps": 50,
|
||||
"aliases": ["sonnet", "claude-sonnet"]
|
||||
},
|
||||
{
|
||||
|
|
@ -54,8 +68,7 @@
|
|||
"input_cost_per_million": 1.75,
|
||||
"output_cost_per_million": 14.0,
|
||||
"estimated_output_tps": 65,
|
||||
"aliases": ["gpt5"],
|
||||
"default": true
|
||||
"aliases": ["gpt5"]
|
||||
},
|
||||
{
|
||||
"id": "gpt-5-mini",
|
||||
|
|
@ -111,7 +124,8 @@
|
|||
"input_cost_per_million": 2.5,
|
||||
"output_cost_per_million": 15.0,
|
||||
"estimated_output_tps": 70,
|
||||
"aliases": ["gpt54"]
|
||||
"aliases": ["gpt54"],
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.4-pro",
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ mod tests {
|
|||
assert!(m.default);
|
||||
|
||||
let m = default_model_for_provider("openai").unwrap();
|
||||
assert_eq!(m.id, "gpt-5.2");
|
||||
assert_eq!(m.id, "gpt-5.4");
|
||||
|
||||
let m = default_model_for_provider("gemini").unwrap();
|
||||
assert_eq!(m.id, "gemini-3.1-pro-preview");
|
||||
|
|
@ -221,7 +221,7 @@ mod tests {
|
|||
assert_eq!(info.id, "claude-opus-4-6");
|
||||
|
||||
let info = get_model_info("sonnet").unwrap();
|
||||
assert_eq!(info.id, "claude-sonnet-4-5");
|
||||
assert_eq!(info.id, "claude-sonnet-4-6");
|
||||
|
||||
let info = get_model_info("codex").unwrap();
|
||||
assert_eq!(info.id, "gpt-5.3-codex");
|
||||
|
|
@ -235,7 +235,7 @@ mod tests {
|
|||
#[test]
|
||||
fn list_models_by_provider() {
|
||||
let anthropic = list_models(Some("anthropic"));
|
||||
assert_eq!(anthropic.len(), 3);
|
||||
assert_eq!(anthropic.len(), 4);
|
||||
assert!(anthropic.iter().all(|m| m.provider == "anthropic"));
|
||||
|
||||
let openai = list_models(Some("openai"));
|
||||
|
|
@ -323,7 +323,7 @@ mod tests {
|
|||
assert!(m.supports_reasoning);
|
||||
assert_eq!(m.input_cost_per_million, Some(2.5));
|
||||
assert_eq!(m.output_cost_per_million, Some(15.0));
|
||||
assert!(!m.default);
|
||||
assert!(m.default);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -35,19 +35,6 @@ use super::{
|
|||
RunArgs, SandboxProvider,
|
||||
};
|
||||
|
||||
/// Return the default model string for a given provider.
|
||||
fn default_model_for_provider(provider: Provider) -> &'static str {
|
||||
match provider {
|
||||
Provider::Anthropic => "claude-opus-4-6",
|
||||
Provider::OpenAi => "gpt-5.2",
|
||||
Provider::Gemini => "gemini-3.1-pro-preview",
|
||||
Provider::Kimi => "kimi-k2.5",
|
||||
Provider::Zai => "glm-4.7",
|
||||
Provider::Minimax => "minimax-m2.5",
|
||||
Provider::Inception => "mercury",
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve model and provider through the full precedence chain:
|
||||
/// CLI flag > TOML config > run defaults > DOT graph attrs > provider-specific defaults.
|
||||
/// Then resolve through the catalog for alias expansion.
|
||||
|
|
@ -87,7 +74,9 @@ fn resolve_model_provider(
|
|||
.as_deref()
|
||||
.and_then(|s| s.parse::<Provider>().ok())
|
||||
.unwrap_or(Provider::Anthropic);
|
||||
default_model_for_provider(provider_enum).to_string()
|
||||
arc_llm::catalog::default_model_for_provider(provider_enum.as_str())
|
||||
.map(|m| m.id)
|
||||
.unwrap_or_else(|| provider_enum.as_str().to_string())
|
||||
});
|
||||
|
||||
// Resolve model alias through catalog
|
||||
|
|
@ -1502,50 +1491,6 @@ async fn generate_retro(
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn default_model_for_anthropic() {
|
||||
assert_eq!(
|
||||
default_model_for_provider(Provider::Anthropic),
|
||||
"claude-opus-4-6"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_for_openai() {
|
||||
assert_eq!(default_model_for_provider(Provider::OpenAi), "gpt-5.2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_for_gemini() {
|
||||
assert_eq!(
|
||||
default_model_for_provider(Provider::Gemini),
|
||||
"gemini-3.1-pro-preview"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_for_kimi() {
|
||||
assert_eq!(default_model_for_provider(Provider::Kimi), "kimi-k2.5");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_for_zai() {
|
||||
assert_eq!(default_model_for_provider(Provider::Zai), "glm-4.7");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_for_minimax() {
|
||||
assert_eq!(
|
||||
default_model_for_provider(Provider::Minimax),
|
||||
"minimax-m2.5"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_model_for_inception() {
|
||||
assert_eq!(default_model_for_provider(Provider::Inception), "mercury");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_model_provider_defaults() {
|
||||
let graph = crate::graph::types::Graph::new("test");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue