oxicode_agent/
model_id.rs1use oxicode_ai::Model;
2use oxicode_ai::register_builtins::get_builtin_provider;
3use oxicode_ai::{get_model, get_model_entry, lookup_model};
4use std::collections::HashMap;
5
6pub fn resolve_model_from_id(model_id: &str) -> Option<Model> {
9 let parts: Vec<&str> = model_id.split('/').collect();
10 let provider = if parts.len() >= 2 {
11 parts[0]
12 } else {
13 "anthropic"
14 };
15 let model_id_part = if parts.len() >= 2 {
16 parts[1..].join("/")
17 } else {
18 parts[0].to_string()
19 };
20
21 if let Some(m) = lookup_model(provider, &model_id_part) {
23 return Some(m);
24 }
25 if let Some(m) = get_model(provider, &model_id_part) {
27 return Some(m.clone());
28 }
29 if let Some(entry) = get_model_entry(provider, &model_id_part) {
33 return Some(model_from_entry(provider, entry));
34 }
35 None
36}
37fn model_from_entry(provider: &str, entry: &oxicode_ai::model_db::ModelEntry) -> Model {
42 let builtin = get_builtin_provider(provider);
43 let base_url = builtin.map(|b| b.base_url).unwrap_or("").to_string();
44 let headers: HashMap<String, String> = builtin
45 .map(|b| {
46 b.extra_headers
47 .iter()
48 .map(|(k, v)| (k.to_string(), v.to_string()))
49 .collect()
50 })
51 .unwrap_or_default();
52 let compat = match provider {
53 "zai" => Some(oxicode_ai::CompatSettings {
54 thinking_format: Some(oxicode_ai::ThinkingFormat::Zai),
55 ..Default::default()
56 }),
57 _ => None,
58 };
59
60 Model {
61 id: entry.id.to_string(),
62 name: entry.name.to_string(),
63 api: entry.api,
64 provider: provider.to_string(),
65 base_url,
66 reasoning: entry.reasoning,
67 input: entry.input.to_vec(),
68 cost: oxicode_ai::Cost {
69 input: entry.cost_input,
70 output: entry.cost_output,
71 cache_read: entry.cost_cache_read,
72 cache_write: entry.cost_cache_write,
73 },
74 context_window: entry.context_window as usize,
75 max_tokens: entry.max_tokens as usize,
76 headers,
77 compat,
78 }
79}