use super::*;

pub fn typescript_binding() -> Result<String, serde_json::Error> {
    Ok(typescript_binding_from_json(&artifact_json()?))
}

/// Hermetic counterpart of [`typescript_binding`] for generating the
/// checked-in `harn-provider-catalog.ts` artifact. See [`artifact_embedded`].
pub fn typescript_binding_embedded(
    explicit_overlay: Option<&crate::llm_config::ProvidersConfig>,
) -> Result<String, serde_json::Error> {
    Ok(typescript_binding_from_json(&artifact_json_embedded(
        explicit_overlay,
    )?))
}

fn typescript_binding_from_json(json: &str) -> String {
    format!(
        "{}{}{}{}{}",
        generated_header("//", "typescript"),
        TYPESCRIPT_TYPES,
        "\nexport const harnProviderCatalog: HarnProviderCatalog = ",
        json.trim_end(),
        ";\n",
    ) + TYPESCRIPT_COMPAT_EXPORTS
}

pub fn swift_binding() -> Result<String, serde_json::Error> {
    Ok(swift_binding_from_json(&artifact_json()?))
}

/// Hermetic counterpart of [`swift_binding`] for generating the checked-in
/// `HarnProviderCatalog.swift` artifact. See [`artifact_embedded`].
pub fn swift_binding_embedded(
    explicit_overlay: Option<&crate::llm_config::ProvidersConfig>,
) -> Result<String, serde_json::Error> {
    Ok(swift_binding_from_json(&artifact_json_embedded(
        explicit_overlay,
    )?))
}

fn swift_binding_from_json(json: &str) -> String {
    format!(
        "{}{}\npublic let harnProviderCatalogJSON = #\"\"\"\n{}\"\"\"#\n",
        generated_header("//", "swift"),
        SWIFT_TYPES,
        json
    )
}

fn generated_header(comment: &str, language: &str) -> String {
    format!(
        "{comment} GENERATED by `{PROVIDER_CATALOG_GENERATOR}` - do not edit by hand.\n{comment} Source: Harn runtime provider catalog schema v{PROVIDER_CATALOG_SCHEMA_VERSION}.\n{comment} Language: {language}.\n\n"
    )
}

const TYPESCRIPT_TYPES: &str = r#"export interface HarnProviderCatalog {
  schema_version: 2
  schema: string
  generated_by: string
  providers: HarnCatalogProvider[]
  models: HarnCatalogModel[]
  aliases: HarnCatalogAlias[]
  variants: HarnCatalogVariant[]
  qc_defaults: Record<string, string>
}

export interface HarnCatalogProvider {
  id: string
  display_name: string
  icon?: string
  classification: "hosted" | "local"
  endpoint: HarnProviderEndpoint
  auth: HarnProviderAuth
  protocols: string[]
  features: string[]
  caveats: string[]
  rpm?: number
  rate_limits?: HarnRateLimits
  local_runtime?: HarnLocalRuntime
  latency_p50_ms?: number
}

export interface HarnLocalRuntime {
  kind?: "daemon_api" | "managed_process" | "external"
  command?: string
  model_source?: string
  model_source_env?: string
  default_port?: number
  model_arg?: string
  served_model_arg?: string
  host_arg?: string
  port_arg?: string
  ctx_arg?: string
  parallel_arg?: string
  gpu_layers_arg?: string
  cache_type_k_arg?: string
  cache_type_v_arg?: string
  cache_ram_arg?: string
  default_args?: string[]
  stop?: "keep_alive_zero" | "pid" | "external"
  source_url?: string
  last_verified?: string
  notes?: string
}

export interface HarnProviderEndpoint {
  base_url: string
  base_url_env?: string
  chat_endpoint: string
  completion_endpoint?: string
}

export interface HarnProviderAuth {
  style: string
  header?: string
  env: string[]
  required: boolean
}

export interface HarnCatalogAlias {
  name: string
  model_id: string
  provider: string
  tool_format?: string
  tool_calling?: HarnAliasToolCalling
}

export interface HarnAliasToolCalling {
  native?: string
  text?: string
  streaming_native?: string
  fallback_mode?: string
  failure_reason?: string
  last_probe_at?: string
}

export interface HarnCatalogModel {
  id: string
  name: string
  provider: string
  aliases: string[]
  context_window: number
  logical_model?: string
  equivalence_group?: string
  served_variant?: string
  wire_model?: string
  api_dialect?: string
  rate_limits?: HarnRateLimits
  architecture?: HarnModelArchitecture
  local_memory?: HarnLocalMemory
  runtime_context_window?: number
  stream_timeout?: number
  modalities: { input: string[]; output: string[] }
  tool_support: {
    native: boolean
    text: boolean
    preferred_format?: string
    parity?: string
    parity_notes?: string
    empirical_parity?: HarnToolEmpiricalParity
    tool_search: string[]
    max_tools?: number
  }
  structured_output: string
  format_preferences: {
    prefers_xml_scaffolding: boolean
    prefers_markdown_scaffolding: boolean
    structured_output_mode: "native_json" | "delimited" | "xml_tagged" | "none"
    supports_assistant_prefill: boolean
    prefers_role_developer: boolean
    prefers_xml_tools: boolean
    thinking_block_style: "none" | "thinking_blocks" | "reasoning_summary" | "inline"
  }
  reasoning: {
    modes: string[]
    effort_supported: boolean
    none_supported: boolean
    interleaved_supported: boolean
    preserve_thinking: boolean
  }
  prompt_cache: boolean
  pricing?: HarnModelPricing
  deprecation: { status: "active" | "deprecated"; note?: string; superseded_by?: string }
  availability: "serverless" | "dedicated" | "unknown"
  quality_tags: string[]
  capability_tags: string[]
  family: string
  lineage: string
  complementary_with?: string[]
  avoid_as_reviewer_for?: string[]
  tier: "small" | "mid" | "frontier" | "reasoning"
  open_weight?: boolean
  strengths?: string[]
  benchmarks?: Record<string, number>
  fast_mode?: HarnModelFastMode
}

export interface HarnToolEmpiricalParity {
  verdict: string
  preferred_format: string
  confidence: string
  sample_size: number
  last_evaluated: string
  native_pass_rate: number
  text_pass_rate: number
  verifier_divergence_rate: number
}

export interface HarnModelPricing {
  input_per_mtok: number
  output_per_mtok: number
  cache_read_per_mtok?: number | null
  cache_write_per_mtok?: number | null
}

export interface HarnRateLimits {
  rpm?: number
  rph?: number
  rpd?: number
  tpm?: number
  tph?: number
  tpd?: number
  input_tpm?: number
  output_tpm?: number
  concurrency?: number
  tier?: string
  source_url?: string
  last_verified?: string
  notes?: string
}

export interface HarnModelArchitecture {
  parameter_count_b?: number
  active_parameter_count_b?: number
  moe?: boolean
  quantization?: string
  precision?: string
  license?: string
  tokenizer?: string
  knowledge_cutoff?: string
  source_url?: string
  last_verified?: string
}

export interface HarnLocalMemory {
  measured_resident_gib?: number
  measured_context_window?: number
  measured_cache_type?: string
  base_resident_gib?: number
  kv_cache_gib_per_1k_ctx?: number
  cache_type_multipliers?: Record<string, number>
  default_cache_type?: string
  safety_margin_gib?: number
  max_recommended_context?: number
  source_url?: string
  last_verified?: string
  notes?: string
}

export interface HarnModelFastMode {
  param: string
  value: string
  beta_header?: string
  otps_speedup?: number
  status?: string
  pricing?: HarnModelPricing
  note?: string
}

export interface HarnCatalogVariant {
  id: string
  label: string
  description: string
  model_id: string
  provider: string
  source: string
}

export interface CatalogEntry {
  id: string
  name: string
  provider: string
  contextWindow: number
  runtimeContextWindow?: number
  capabilities: string[]
  family: string
  lineage: string
  pricing?: {
    inputPerMTok: number
    outputPerMTok: number
    cacheReadPerMTok?: number | null
    cacheWritePerMTok?: number | null
  }
  streamTimeout?: number
}

export interface CatalogAlias {
  alias: string
  id: string
  provider: string
  toolFormat?: string
  toolCalling?: HarnAliasToolCalling
}

"#;

const TYPESCRIPT_COMPAT_EXPORTS: &str = r#"
export const MODEL_CATALOG: readonly CatalogEntry[] = harnProviderCatalog.models.map((model) => ({
  id: model.id,
  name: model.name,
  provider: model.provider,
  contextWindow: model.context_window,
  runtimeContextWindow: model.runtime_context_window,
  capabilities: model.capability_tags,
  family: model.family,
  lineage: model.lineage,
  pricing: model.pricing
    ? {
        inputPerMTok: model.pricing.input_per_mtok,
        outputPerMTok: model.pricing.output_per_mtok,
        cacheReadPerMTok: model.pricing.cache_read_per_mtok,
        cacheWritePerMTok: model.pricing.cache_write_per_mtok,
      }
    : undefined,
  streamTimeout: model.stream_timeout,
}))

export const ALIASES: readonly CatalogAlias[] = harnProviderCatalog.aliases.map((alias) => ({
  alias: alias.name,
  id: alias.model_id,
  provider: alias.provider,
  toolFormat: alias.tool_format,
  toolCalling: alias.tool_calling,
}))

export const QC_DEFAULTS: Readonly<Record<string, string>> = harnProviderCatalog.qc_defaults

export function pricingFor(modelId: string): CatalogEntry["pricing"] | undefined {
  return entryFor(modelId)?.pricing
}

export function entryFor(modelId: string): CatalogEntry | undefined {
  return MODEL_CATALOG.find((entry) => entry.id === modelId)
}

export function aliasesByProvider(provider: string): readonly CatalogAlias[] {
  return ALIASES.filter((alias) => alias.provider === provider)
}

export function qcDefaultModel(provider: string): string | undefined {
  return QC_DEFAULTS[provider]
}
"#;

const SWIFT_TYPES: &str = r#"public struct HarnProviderCatalog: Codable, Sendable, Equatable {
    public let schemaVersion: Int
    public let schema: String
    public let generatedBy: String
    public let providers: [HarnCatalogProvider]
    public let models: [HarnCatalogModel]
    public let aliases: [HarnCatalogAlias]
    public let variants: [HarnCatalogVariant]
    public let qcDefaults: [String: String]

    enum CodingKeys: String, CodingKey {
        case schemaVersion = "schema_version"
        case schema
        case generatedBy = "generated_by"
        case providers
        case models
        case aliases
        case variants
        case qcDefaults = "qc_defaults"
    }
}

public struct HarnCatalogProvider: Codable, Sendable, Equatable {
    public let id: String
    public let displayName: String
    public let icon: String?
    public let classification: String
    public let endpoint: HarnProviderEndpoint
    public let auth: HarnProviderAuth
    public let protocols: [String]
    public let features: [String]
    public let caveats: [String]
    public let rpm: Int?
    public let rateLimits: HarnRateLimits?
    public let localRuntime: HarnLocalRuntime?
    public let latencyP50Ms: Int?

    enum CodingKeys: String, CodingKey {
        case id
        case displayName = "display_name"
        case icon
        case classification
        case endpoint
        case auth
        case protocols
        case features
        case caveats
        case rpm
        case rateLimits = "rate_limits"
        case localRuntime = "local_runtime"
        case latencyP50Ms = "latency_p50_ms"
    }
}

public struct HarnLocalRuntime: Codable, Sendable, Equatable {
    public let kind: String?
    public let command: String?
    public let modelSource: String?
    public let modelSourceEnv: String?
    public let defaultPort: Int?
    public let modelArg: String?
    public let servedModelArg: String?
    public let hostArg: String?
    public let portArg: String?
    public let ctxArg: String?
    public let parallelArg: String?
    public let gpuLayersArg: String?
    public let cacheTypeKArg: String?
    public let cacheTypeVArg: String?
    public let cacheRamArg: String?
    public let defaultArgs: [String]?
    public let stop: String?
    public let sourceURL: String?
    public let lastVerified: String?
    public let notes: String?

    enum CodingKeys: String, CodingKey {
        case kind
        case command
        case modelSource = "model_source"
        case modelSourceEnv = "model_source_env"
        case defaultPort = "default_port"
        case modelArg = "model_arg"
        case servedModelArg = "served_model_arg"
        case hostArg = "host_arg"
        case portArg = "port_arg"
        case ctxArg = "ctx_arg"
        case parallelArg = "parallel_arg"
        case gpuLayersArg = "gpu_layers_arg"
        case cacheTypeKArg = "cache_type_k_arg"
        case cacheTypeVArg = "cache_type_v_arg"
        case cacheRamArg = "cache_ram_arg"
        case defaultArgs = "default_args"
        case stop
        case sourceURL = "source_url"
        case lastVerified = "last_verified"
        case notes
    }
}

public struct HarnProviderEndpoint: Codable, Sendable, Equatable {
    public let baseURL: String
    public let baseURLEnv: String?
    public let chatEndpoint: String
    public let completionEndpoint: String?

    enum CodingKeys: String, CodingKey {
        case baseURL = "base_url"
        case baseURLEnv = "base_url_env"
        case chatEndpoint = "chat_endpoint"
        case completionEndpoint = "completion_endpoint"
    }
}

public struct HarnProviderAuth: Codable, Sendable, Equatable {
    public let style: String
    public let header: String?
    public let env: [String]
    public let required: Bool
}

public struct HarnCatalogAlias: Codable, Sendable, Equatable {
    public let name: String
    public let modelID: String
    public let provider: String
    public let toolFormat: String?
    public let toolCalling: HarnAliasToolCalling?

    enum CodingKeys: String, CodingKey {
        case name
        case modelID = "model_id"
        case provider
        case toolFormat = "tool_format"
        case toolCalling = "tool_calling"
    }
}

public struct HarnAliasToolCalling: Codable, Sendable, Equatable {
    public let native: String?
    public let text: String?
    public let streamingNative: String?
    public let fallbackMode: String?
    public let failureReason: String?
    public let lastProbeAt: String?

    enum CodingKeys: String, CodingKey {
        case native
        case text
        case streamingNative = "streaming_native"
        case fallbackMode = "fallback_mode"
        case failureReason = "failure_reason"
        case lastProbeAt = "last_probe_at"
    }
}

public struct HarnCatalogModel: Codable, Sendable, Equatable {
    public let id: String
    public let name: String
    public let provider: String
    public let aliases: [String]
    public let contextWindow: Int
    public let logicalModel: String?
    public let equivalenceGroup: String?
    public let servedVariant: String?
    public let wireModel: String?
    public let apiDialect: String?
    public let rateLimits: HarnRateLimits?
    public let architecture: HarnModelArchitecture?
    public let localMemory: HarnLocalMemory?
    public let runtimeContextWindow: Int?
    public let streamTimeout: Double?
    public let modalities: HarnModelModalities
    public let toolSupport: HarnModelToolSupport
    public let structuredOutput: String
    public let formatPreferences: HarnModelFormatPreferences
    public let reasoning: HarnModelReasoning
    public let promptCache: Bool
    public let pricing: HarnModelPricing?
    public let deprecation: HarnModelDeprecation
    public let availability: String
    public let qualityTags: [String]
    public let capabilityTags: [String]
    public let family: String
    public let lineage: String
    public let complementaryWith: [String]
    public let avoidAsReviewerFor: [String]
    /// Popular-consensus tier label: "small" | "mid" | "frontier" | "reasoning".
    public let tier: String
    /// True when weights are downloadable / self-hostable; nil when the
    /// catalog row predates the field.
    public let openWeight: Bool?
    /// Workload-shaped strength tags (`coding`, `summarization`, `vision`, ...).
    public let strengths: [String]
    /// Public benchmark numbers keyed by `snake_case` identifier.
    public let benchmarks: [String: Double]
    /// Accelerated-serving ("fast mode") tier metadata, when offered.
    public let fastMode: HarnModelFastMode?

    enum CodingKeys: String, CodingKey {
        case id
        case name
        case provider
        case aliases
        case contextWindow = "context_window"
        case logicalModel = "logical_model"
        case equivalenceGroup = "equivalence_group"
        case servedVariant = "served_variant"
        case wireModel = "wire_model"
        case apiDialect = "api_dialect"
        case rateLimits = "rate_limits"
        case architecture
        case localMemory = "local_memory"
        case runtimeContextWindow = "runtime_context_window"
        case streamTimeout = "stream_timeout"
        case modalities
        case toolSupport = "tool_support"
        case structuredOutput = "structured_output"
        case formatPreferences = "format_preferences"
        case reasoning
        case promptCache = "prompt_cache"
        case pricing
        case deprecation
        case availability
        case qualityTags = "quality_tags"
        case capabilityTags = "capability_tags"
        case family
        case lineage
        case complementaryWith = "complementary_with"
        case avoidAsReviewerFor = "avoid_as_reviewer_for"
        case tier
        case openWeight = "open_weight"
        case strengths
        case benchmarks
        case fastMode = "fast_mode"
    }

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(String.self, forKey: .id)
        name = try container.decode(String.self, forKey: .name)
        provider = try container.decode(String.self, forKey: .provider)
        aliases = try container.decode([String].self, forKey: .aliases)
        contextWindow = try container.decode(Int.self, forKey: .contextWindow)
        logicalModel = try container.decodeIfPresent(String.self, forKey: .logicalModel)
        equivalenceGroup = try container.decodeIfPresent(String.self, forKey: .equivalenceGroup)
        servedVariant = try container.decodeIfPresent(String.self, forKey: .servedVariant)
        wireModel = try container.decodeIfPresent(String.self, forKey: .wireModel)
        apiDialect = try container.decodeIfPresent(String.self, forKey: .apiDialect)
        rateLimits = try container.decodeIfPresent(HarnRateLimits.self, forKey: .rateLimits)
        architecture = try container.decodeIfPresent(HarnModelArchitecture.self, forKey: .architecture)
        localMemory = try container.decodeIfPresent(HarnLocalMemory.self, forKey: .localMemory)
        runtimeContextWindow = try container.decodeIfPresent(Int.self, forKey: .runtimeContextWindow)
        streamTimeout = try container.decodeIfPresent(Double.self, forKey: .streamTimeout)
        modalities = try container.decode(HarnModelModalities.self, forKey: .modalities)
        toolSupport = try container.decode(HarnModelToolSupport.self, forKey: .toolSupport)
        structuredOutput = try container.decode(String.self, forKey: .structuredOutput)
        formatPreferences = try container.decode(HarnModelFormatPreferences.self, forKey: .formatPreferences)
        reasoning = try container.decode(HarnModelReasoning.self, forKey: .reasoning)
        promptCache = try container.decode(Bool.self, forKey: .promptCache)
        pricing = try container.decodeIfPresent(HarnModelPricing.self, forKey: .pricing)
        deprecation = try container.decode(HarnModelDeprecation.self, forKey: .deprecation)
        availability = try container.decode(String.self, forKey: .availability)
        qualityTags = try container.decode([String].self, forKey: .qualityTags)
        capabilityTags = try container.decode([String].self, forKey: .capabilityTags)
        family = try container.decode(String.self, forKey: .family)
        lineage = try container.decode(String.self, forKey: .lineage)
        complementaryWith = try container.decodeIfPresent([String].self, forKey: .complementaryWith) ?? []
        avoidAsReviewerFor = try container.decodeIfPresent([String].self, forKey: .avoidAsReviewerFor) ?? []
        tier = try container.decode(String.self, forKey: .tier)
        openWeight = try container.decodeIfPresent(Bool.self, forKey: .openWeight)
        strengths = try container.decodeIfPresent([String].self, forKey: .strengths) ?? []
        benchmarks = try container.decodeIfPresent([String: Double].self, forKey: .benchmarks) ?? [:]
        fastMode = try container.decodeIfPresent(HarnModelFastMode.self, forKey: .fastMode)
    }
}

public struct HarnModelModalities: Codable, Sendable, Equatable {
    public let input: [String]
    public let output: [String]
}

public struct HarnModelToolSupport: Codable, Sendable, Equatable {
    public let native: Bool
    public let text: Bool
    public let preferredFormat: String?
    public let parity: String?
    public let parityNotes: String?
    public let empiricalParity: HarnToolEmpiricalParity?
    public let toolSearch: [String]
    public let maxTools: Int?

    enum CodingKeys: String, CodingKey {
        case native
        case text
        case preferredFormat = "preferred_format"
        case parity
        case parityNotes = "parity_notes"
        case empiricalParity = "empirical_parity"
        case toolSearch = "tool_search"
        case maxTools = "max_tools"
    }
}

public struct HarnToolEmpiricalParity: Codable, Sendable, Equatable {
    public let verdict: String
    public let preferredFormat: String
    public let confidence: String
    public let sampleSize: Int
    public let lastEvaluated: String
    public let nativePassRate: Double
    public let textPassRate: Double
    public let verifierDivergenceRate: Double

    enum CodingKeys: String, CodingKey {
        case verdict
        case preferredFormat = "preferred_format"
        case confidence
        case sampleSize = "sample_size"
        case lastEvaluated = "last_evaluated"
        case nativePassRate = "native_pass_rate"
        case textPassRate = "text_pass_rate"
        case verifierDivergenceRate = "verifier_divergence_rate"
    }
}

public struct HarnModelFormatPreferences: Codable, Sendable, Equatable {
    public let prefersXMLScaffolding: Bool
    public let prefersMarkdownScaffolding: Bool
    public let structuredOutputMode: String
    public let supportsAssistantPrefill: Bool
    public let prefersRoleDeveloper: Bool
    public let prefersXMLTools: Bool
    public let thinkingBlockStyle: String

    enum CodingKeys: String, CodingKey {
        case prefersXMLScaffolding = "prefers_xml_scaffolding"
        case prefersMarkdownScaffolding = "prefers_markdown_scaffolding"
        case structuredOutputMode = "structured_output_mode"
        case supportsAssistantPrefill = "supports_assistant_prefill"
        case prefersRoleDeveloper = "prefers_role_developer"
        case prefersXMLTools = "prefers_xml_tools"
        case thinkingBlockStyle = "thinking_block_style"
    }
}

public struct HarnModelReasoning: Codable, Sendable, Equatable {
    public let modes: [String]
    public let effortSupported: Bool
    public let noneSupported: Bool
    public let interleavedSupported: Bool
    public let preserveThinking: Bool

    enum CodingKeys: String, CodingKey {
        case modes
        case effortSupported = "effort_supported"
        case noneSupported = "none_supported"
        case interleavedSupported = "interleaved_supported"
        case preserveThinking = "preserve_thinking"
    }
}

public struct HarnModelPricing: Codable, Sendable, Equatable {
    public let inputPerMTok: Double
    public let outputPerMTok: Double
    public let cacheReadPerMTok: Double?
    public let cacheWritePerMTok: Double?

    enum CodingKeys: String, CodingKey {
        case inputPerMTok = "input_per_mtok"
        case outputPerMTok = "output_per_mtok"
        case cacheReadPerMTok = "cache_read_per_mtok"
        case cacheWritePerMTok = "cache_write_per_mtok"
    }
}

public struct HarnRateLimits: Codable, Sendable, Equatable {
    public let rpm: Int?
    public let rph: Int?
    public let rpd: Int?
    public let tpm: Int?
    public let tph: Int?
    public let tpd: Int?
    public let inputTpm: Int?
    public let outputTpm: Int?
    public let concurrency: Int?
    public let tier: String?
    public let sourceURL: String?
    public let lastVerified: String?
    public let notes: String?

    enum CodingKeys: String, CodingKey {
        case rpm
        case rph
        case rpd
        case tpm
        case tph
        case tpd
        case inputTpm = "input_tpm"
        case outputTpm = "output_tpm"
        case concurrency
        case tier
        case sourceURL = "source_url"
        case lastVerified = "last_verified"
        case notes
    }
}

public struct HarnModelArchitecture: Codable, Sendable, Equatable {
    public let parameterCountB: Double?
    public let activeParameterCountB: Double?
    public let moe: Bool?
    public let quantization: String?
    public let precision: String?
    public let license: String?
    public let tokenizer: String?
    public let knowledgeCutoff: String?
    public let sourceURL: String?
    public let lastVerified: String?

    enum CodingKeys: String, CodingKey {
        case parameterCountB = "parameter_count_b"
        case activeParameterCountB = "active_parameter_count_b"
        case moe
        case quantization
        case precision
        case license
        case tokenizer
        case knowledgeCutoff = "knowledge_cutoff"
        case sourceURL = "source_url"
        case lastVerified = "last_verified"
    }
}

public struct HarnLocalMemory: Codable, Sendable, Equatable {
    public let measuredResidentGiB: Double?
    public let measuredContextWindow: Int?
    public let measuredCacheType: String?
    public let baseResidentGiB: Double?
    public let kvCacheGiBPer1KContext: Double?
    public let cacheTypeMultipliers: [String: Double]?
    public let defaultCacheType: String?
    public let safetyMarginGiB: Double?
    public let maxRecommendedContext: Int?
    public let sourceURL: String?
    public let lastVerified: String?
    public let notes: String?

    enum CodingKeys: String, CodingKey {
        case measuredResidentGiB = "measured_resident_gib"
        case measuredContextWindow = "measured_context_window"
        case measuredCacheType = "measured_cache_type"
        case baseResidentGiB = "base_resident_gib"
        case kvCacheGiBPer1KContext = "kv_cache_gib_per_1k_ctx"
        case cacheTypeMultipliers = "cache_type_multipliers"
        case defaultCacheType = "default_cache_type"
        case safetyMarginGiB = "safety_margin_gib"
        case maxRecommendedContext = "max_recommended_context"
        case sourceURL = "source_url"
        case lastVerified = "last_verified"
        case notes
    }
}

public struct HarnModelDeprecation: Codable, Sendable, Equatable {
    public let status: String
    public let note: String?
    public let supersededBy: String?

    enum CodingKeys: String, CodingKey {
        case status
        case note
        case supersededBy = "superseded_by"
    }
}

public struct HarnModelFastMode: Codable, Sendable, Equatable {
    public let param: String
    public let value: String
    public let betaHeader: String?
    public let otpsSpeedup: Double?
    public let status: String?
    public let pricing: HarnModelPricing?
    public let note: String?

    enum CodingKeys: String, CodingKey {
        case param
        case value
        case betaHeader = "beta_header"
        case otpsSpeedup = "otps_speedup"
        case status
        case pricing
        case note
    }
}

public struct HarnCatalogVariant: Codable, Sendable, Equatable {
    public let id: String
    public let label: String
    public let description: String
    public let modelID: String
    public let provider: String
    public let source: String

    enum CodingKeys: String, CodingKey {
        case id
        case label
        case description
        case modelID = "model_id"
        case provider
        case source
    }
}
"#;
