Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions rust/crates/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ pub use prompt_cache::{
pub use providers::anthropic::{AnthropicClient, AnthropicClient as ApiClient, AuthSource};
pub use providers::openai_compat::{
build_chat_completion_request, flatten_tool_result_content, is_reasoning_model,
model_rejects_is_error_field, translate_message, OpenAiCompatClient, OpenAiCompatConfig,
model_rejects_is_error_field, model_requires_reasoning_content_in_history, translate_message,
OpenAiCompatClient, OpenAiCompatConfig,
};
pub use providers::{
detect_provider_kind, max_tokens_for_model, max_tokens_for_model_with_override,
resolve_model_alias, ProviderKind,
model_family_identity_for, model_family_identity_for_kind, resolve_model_alias, ProviderKind,
};
pub use sse::{parse_frame, SseParser};
pub use types::{
Expand Down
53 changes: 51 additions & 2 deletions rust/crates/api/src/providers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,19 @@ pub fn detect_provider_kind(model: &str) -> ProviderKind {
ProviderKind::Anthropic
}

#[must_use]
pub const fn model_family_identity_for_kind(kind: ProviderKind) -> runtime::ModelFamilyIdentity {
match kind {
ProviderKind::Anthropic => runtime::ModelFamilyIdentity::Claude,
ProviderKind::Xai | ProviderKind::OpenAi => runtime::ModelFamilyIdentity::Generic,
}
}

#[must_use]
pub fn model_family_identity_for(model: &str) -> runtime::ModelFamilyIdentity {
model_family_identity_for_kind(detect_provider_kind(model))
}

#[must_use]
pub fn max_tokens_for_model(model: &str) -> u32 {
let canonical = resolve_model_alias(model);
Expand Down Expand Up @@ -484,8 +497,8 @@ mod tests {
use super::{
anthropic_missing_credentials, anthropic_missing_credentials_hint, detect_provider_kind,
load_dotenv_file, max_tokens_for_model, max_tokens_for_model_with_override,
model_token_limit, parse_dotenv, preflight_message_request, resolve_model_alias,
ProviderKind,
model_family_identity_for, model_family_identity_for_kind, model_token_limit, parse_dotenv,
preflight_message_request, resolve_model_alias, ProviderKind,
};

/// Serializes every test in this module that mutates process-wide
Expand Down Expand Up @@ -544,6 +557,42 @@ mod tests {
);
}

#[test]
fn maps_provider_kind_to_model_family_identity() {
// given: each supported provider kind
let anthropic = ProviderKind::Anthropic;
let openai = ProviderKind::OpenAi;
let xai = ProviderKind::Xai;

// when: converting provider kinds to prompt model family identities
let anthropic_identity = model_family_identity_for_kind(anthropic);
let openai_identity = model_family_identity_for_kind(openai);
let xai_identity = model_family_identity_for_kind(xai);

// then: Anthropic stays Claude and OpenAI-compatible providers are generic
assert_eq!(anthropic_identity, runtime::ModelFamilyIdentity::Claude);
assert_eq!(openai_identity, runtime::ModelFamilyIdentity::Generic);
assert_eq!(xai_identity, runtime::ModelFamilyIdentity::Generic);
}

#[test]
fn maps_model_name_to_model_family_identity() {
// given: Anthropic, OpenAI-compatible, and xAI model names
let claude_model = "claude-opus-4-6";
let openai_model = "openai/gpt-4.1-mini";
let xai_model = "grok-3";

// when: detecting prompt model family identities from model names
let claude_identity = model_family_identity_for(claude_model);
let openai_identity = model_family_identity_for(openai_model);
let xai_identity = model_family_identity_for(xai_model);

// then: Anthropic stays Claude and OpenAI-compatible providers are generic
assert_eq!(claude_identity, runtime::ModelFamilyIdentity::Claude);
assert_eq!(openai_identity, runtime::ModelFamilyIdentity::Generic);
assert_eq!(xai_identity, runtime::ModelFamilyIdentity::Generic);
}

#[test]
fn openai_namespaced_model_routes_to_openai_not_anthropic() {
// Regression: "openai/gpt-4.1-mini" was misrouted to Anthropic when
Expand Down
Loading
Loading