'boolean', 'options' => 'array', ]; /** * Provider별 기본 Base URL */ public const DEFAULT_BASE_URLS = [ 'gemini' => 'https://generativelanguage.googleapis.com/v1beta', 'claude' => 'https://api.anthropic.com/v1', 'openai' => 'https://api.openai.com/v1', ]; /** * Provider별 기본 모델 */ public const DEFAULT_MODELS = [ 'gemini' => 'gemini-2.0-flash', 'claude' => 'claude-sonnet-4-20250514', 'openai' => 'gpt-4o', ]; /** * 활성화된 Gemini 설정 조회 */ public static function getActiveGemini(): ?self { return self::where('provider', 'gemini') ->where('is_active', true) ->first(); } /** * 활성화된 Claude 설정 조회 */ public static function getActiveClaude(): ?self { return self::where('provider', 'claude') ->where('is_active', true) ->first(); } /** * Provider별 활성 설정 조회 */ public static function getActive(string $provider): ?self { return self::where('provider', $provider) ->where('is_active', true) ->first(); } /** * Base URL 가져오기 (설정 또는 기본값) */ public function getBaseUrlAttribute($value): string { return $value ?? self::DEFAULT_BASE_URLS[$this->provider] ?? ''; } /** * Provider 라벨 */ public function getProviderLabelAttribute(): string { return match ($this->provider) { 'gemini' => 'Google Gemini', 'claude' => 'Anthropic Claude', 'openai' => 'OpenAI', default => $this->provider, }; } /** * 상태 라벨 */ public function getStatusLabelAttribute(): string { return $this->is_active ? '활성' : '비활성'; } /** * 상태 색상 (Tailwind) */ public function getStatusColorAttribute(): string { return $this->is_active ? 'green' : 'gray'; } /** * 마스킹된 API 키 (앞 8자리만 표시) */ public function getMaskedApiKeyAttribute(): string { if (strlen($this->api_key) <= 8) { return $this->api_key; } return substr($this->api_key, 0, 8) . str_repeat('*', 8) . '...'; } }