""" Genesys AI Experience token meters and pricing. Every meter carries a :class:`Confidence` flag so the UI can distinguish published Genesys rates from estimates and unknowns. Rates here are *planning inputs* — this tool explicitly does not replace contractual pricing (see README, Non-Goals). """ from __future__ import annotations from dataclasses import dataclass from enum import Enum class MeterType(Enum): PER_USER_PER_MONTH = "per_user_per_month" PER_INTERACTION = "per_interaction" PER_MINUTE = "per_minute" PER_MESSAGE = "per_message" PER_SUMMARY = "per_summary" class Confidence(Enum): CONFIRMED = "confirmed" # published Genesys rate ESTIMATED = "estimated" # reasonable industry assumption UNKNOWN = "unknown" # rate not yet sourced @property def icon(self) -> str: return {"confirmed": "🟢", "estimated": "🟡", "unknown": "🔴"}[self.value] @dataclass class TokenMeter: """One Genesys AI feature's token meter. ``units_per_token`` and ``tokens_per_unit`` are inverses; both are stored because the UI shows whichever reads more naturally (e.g. "17 minutes per token" vs "0.0588 tokens per minute"). For PER_USER_PER_MONTH meters ``units_per_token`` is 0.0 (n/a) and ``tokens_per_unit`` is the flat tokens/user/month figure. """ feature: str meter_type: MeterType units_per_token: float tokens_per_unit: float confidence: Confidence notes: str source_url: str | None = None def __post_init__(self) -> None: if self.tokens_per_unit < 0: raise ValueError(f"{self.feature}: tokens_per_unit must be >= 0") if ( self.meter_type is not MeterType.PER_USER_PER_MONTH and self.units_per_token > 0 and self.tokens_per_unit > 0 ): product = self.units_per_token * self.tokens_per_unit if not 0.95 <= product <= 1.05: raise ValueError( f"{self.feature}: units_per_token ({self.units_per_token}) and " f"tokens_per_unit ({self.tokens_per_unit}) are not inverses" ) @dataclass class TokenPricing: """Per-region token pricing. Default is US list at $1/token.""" region: str # "US", "AU", "EU", "APAC" list_rate_per_token: float = 1.0 contracted_rate_per_token: float | None = None prepay_commit_tokens: int | None = None overage_rate_per_token: float | None = None def __post_init__(self) -> None: if self.list_rate_per_token < 0: raise ValueError(f"{self.region}: list rate must be >= 0") def effective_rate(self, use_contracted: bool = False) -> float: """Contracted rate when requested and known, else list rate.""" if use_contracted and self.contracted_rate_per_token is not None: return self.contracted_rate_per_token return self.list_rate_per_token