package textgen import "log/slog" // Provider Ordering Strategy // // Production ordering: LaoZhang (primary) -> Gemini (terminus) // // LaoZhang is primary because: // - Pay-per-use pricing, no hard daily limits // - More predictable availability for production traffic // - Gemini's unpredictable quota exhaustion would frustrate users // - Cost is acceptable for revenue-generating features // // Gemini is terminus because: // - Daily quota limits (resets at midnight PT) // - Free tier was reduced ~92% in December 2025 // - Terminus is ALWAYS tried regardless of cooldown // // The fallback strategy ensures requests succeed when possible. // ProviderSet holds text providers for easy configuration. type ProviderSet struct { LaoZhang TextGenerator Gemini TextGenerator } // ProductionConfig returns a ManagerConfig optimized for production workloads. // // Primary: LaoZhang (reliable pay-per-use) // Terminus: Gemini (may fail on quota, but always tried as last resort) // // Use this for: // - User-initiated text generation // - Production API endpoints // - Any feature where reliability matters more than cost func ProductionConfig(providers ProviderSet, opts ...ConfigOption) ManagerConfig { textProviders := []TextGenerator{} // Build provider list in order: LaoZhang -> Gemini (terminus) if providers.LaoZhang != nil { textProviders = append(textProviders, providers.LaoZhang) } if providers.Gemini != nil { textProviders = append(textProviders, providers.Gemini) } cfg := ManagerConfig{ Providers: textProviders, Strategy: StrategyFallback, } for _, opt := range opts { opt(&cfg) } return cfg } // ConfigOption allows customizing preset configurations. type ConfigOption func(*ManagerConfig) // WithLogger sets a custom logger. func WithLogger(logger *slog.Logger) ConfigOption { return func(cfg *ManagerConfig) { cfg.Logger = logger } } // WithMetrics sets a metrics hook for observability. func WithMetrics(hook MetricsHook) ConfigOption { return func(cfg *ManagerConfig) { cfg.OnMetrics = hook } } // WithStrategy overrides the default fallback strategy. // Use sparingly - the presets use StrategyFallback for a reason. func WithStrategy(strategy Strategy) ConfigOption { return func(cfg *ManagerConfig) { cfg.Strategy = strategy } }