use std::any::{TypeId, type_name}; use fabro_api::types::{Model as ApiModel, ModelControls as ApiModelControls}; use fabro_model::{ Model, ModelControls, ModelCosts, ModelFeatures, ModelLimits, ProviderId, ReasoningEffort, ReasoningEffortFeature, }; #[test] fn model_reuses_canonical_type() { assert_same_type::(); assert_same_type::(); } #[test] fn model_json_matches_openapi_shape() { let model = Model { id: "claude-opus-4-7".into(), provider: ProviderId::anthropic(), family: "claude-4".to_string(), display_name: "Claude Opus 4.7".to_string(), limits: ModelLimits { context_window: 1_000_000, max_output: Some(128_000), }, training: Some("2025-08-01".to_string()), knowledge_cutoff: Some("May 2025".to_string()), features: ModelFeatures { tools: true, vision: true, reasoning: true, reasoning_effort: ReasoningEffortFeature::Levels, prompt_cache: true, cache_control_breakpoints: false, sampling_params: true, }, controls: ModelControls { reasoning_effort: vec![ ReasoningEffort::Low, ReasoningEffort::High, ReasoningEffort::Max, ], }, costs: ModelCosts { input_cost_per_mtok: Some(5.0), output_cost_per_mtok: Some(25.0), cache_input_cost_per_mtok: Some(0.5), }, estimated_output_tps: Some(25.0), aliases: vec!["opus".to_string()], default: false, small_default: true, configured: true, }; let json = serde_json::to_value(&model).unwrap(); assert_eq!(json["id"], "claude-opus-4-7"); assert_eq!(json["provider"], "anthropic"); assert_eq!(json["knowledge_cutoff"], "May 2025"); assert_eq!(json["features"]["reasoning_effort"], "levels"); assert_eq!(json["features"]["prompt_cache"], true); assert_eq!( json["controls"]["reasoning_effort"], serde_json::json!(["low", "high", "max"]) ); assert_eq!(json["estimated_output_tps"], 25.0); assert_eq!(json["small_default"], true); assert_eq!(json["configured"], true); let round_trip: ApiModel = serde_json::from_value(json).unwrap(); assert_eq!(round_trip, model); } fn assert_same_type() { assert_eq!( TypeId::of::(), TypeId::of::(), "{} should be the same type as {}", type_name::(), type_name::() ); }