export const CREDITS_PER_CNY = 10; export const CONSULTATION_DOMAIN_DURATION_MS = 21_000; const MICROUSD_PER_USD = 1_000_000; export type Metric = Readonly<{ runs: number; avg: number | null; p50: number | null; p95: number | null; max: number | null }>; export type UsageAggregate = Readonly<{ hasData: boolean; metrics: Readonly<{ costMicrousd: Metric; inputTokens: Metric; outputTokens: Metric; durationMs: Metric }>; }>; export type ModelPrice = Readonly<{ modelTier: string; inputCostMicrousdPerMillion: number; outputCostMicrousdPerMillion: number; }>; export type DistributionBand = Readonly<{ weight: number; monthlyMessages: number }>; export type FeatureSimulationInput = Readonly<{ featureKey: string; creditCost: number | null; model: ModelPrice | null; usage: UsageAggregate | null; usdToCny: number | null; }>; export type FeatureSimulation = Readonly<{ featureKey: string; saleCny: number | null; costMicrousd: number | null; costCny: number | null; marginPercent: number | null; source: "ledger" | "model_estimate" | "unavailable"; }>; function metricValue(metric: Metric, percentile: "p50" | "p95" | "max"): number | null { return metric[percentile]; } export function estimateFeature(input: FeatureSimulationInput, percentile: "p50" | "p95" | "max" = "p50"): FeatureSimulation { const saleCny = input.creditCost === null ? null : input.creditCost / CREDITS_PER_CNY; if (input.creditCost === null || !input.usage?.hasData) { return { featureKey: input.featureKey, saleCny, costMicrousd: null, costCny: null, marginPercent: null, source: "unavailable" }; } const observedCost = metricValue(input.usage.metrics.costMicrousd, percentile); const modelCost = input.model && input.usage.metrics.inputTokens[percentile] !== null && input.usage.metrics.outputTokens[percentile] !== null ? (input.usage.metrics.inputTokens[percentile]! * input.model.inputCostMicrousdPerMillion + input.usage.metrics.outputTokens[percentile]! * input.model.outputCostMicrousdPerMillion) / 1_000_000 : null; const costMicrousd = observedCost ?? modelCost; const costCny = costMicrousd === null || input.usdToCny === null ? null : (costMicrousd / MICROUSD_PER_USD) * input.usdToCny; return { featureKey: input.featureKey, saleCny, costMicrousd, costCny, marginPercent: costCny === null || saleCny === null || saleCny === 0 ? null : ((saleCny - costCny) / saleCny) * 100, source: observedCost !== null ? "ledger" : costMicrousd === null ? "unavailable" : "model_estimate", }; } export function weightedAverageMessages(distribution: readonly DistributionBand[]): number | null { const usable = distribution.filter((band) => Number.isFinite(band.weight) && band.weight > 0 && Number.isFinite(band.monthlyMessages)); const totalWeight = usable.reduce((sum, band) => sum + band.weight, 0); if (totalWeight <= 0) return null; return usable.reduce((sum, band) => sum + (band.weight / totalWeight) * Math.max(0, band.monthlyMessages), 0); } // billingLimit is an anomaly-account circuit breaker, not the member-facing total allowance. export function membershipCost(distribution: readonly DistributionBand[], unitCostCny: number | null, billingLimit: number | null) { const averageMessages = weightedAverageMessages(distribution); return { averageMessages, averageCostCny: averageMessages === null || unitCostCny === null ? null : averageMessages * unitCostCny, worstCostCny: billingLimit === null || unitCostCny === null ? null : billingLimit * unitCostCny, unlimitedWorstCase: billingLimit === null, }; } export function dailySerialCapacity(durationMs = CONSULTATION_DOMAIN_DURATION_MS): number | null { if (!Number.isFinite(durationMs) || durationMs <= 0) return null; return Math.floor(86_400_000 / durationMs); } export function memberCapacity(distribution: readonly DistributionBand[], unitDurationMs: number): number | null { const averageMessages = weightedAverageMessages(distribution); const dailyCapacity = dailySerialCapacity(unitDurationMs); if (averageMessages === null || dailyCapacity === null || averageMessages <= 0) return null; return Math.floor(dailyCapacity / (averageMessages / 30)); }