'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', 'gcs' => 'https://storage.googleapis.com', 'notion' => 'https://api.notion.com/v1', ]; /** * Provider별 기본 모델 */ public const DEFAULT_MODELS = [ 'gemini' => 'gemini-2.5-flash', 'claude' => 'claude-sonnet-4-20250514', 'openai' => 'gpt-4o', 'gcs' => '-', 'notion' => '2025-09-03', ]; /** * AI Provider 목록 (GCS 제외) */ public const AI_PROVIDERS = ['gemini', 'claude', 'openai']; /** * 스토리지 Provider 목록 */ public const STORAGE_PROVIDERS = ['gcs']; /** * API 서비스 Provider 목록 */ public const API_SERVICE_PROVIDERS = ['notion']; /** * 활성화된 Gemini 설정 조회 (.env 기반) */ public static function getActiveGemini(): ?self { $apiKey = config('services.gemini.api_key'); if (! $apiKey) { return null; } $instance = new self; $instance->provider = 'gemini'; $instance->api_key = $apiKey; $instance->model = config('services.gemini.model', 'gemini-2.5-flash'); $instance->base_url = config('services.gemini.base_url', 'https://generativelanguage.googleapis.com/v1beta'); $instance->is_active = true; $instance->options = [ 'auth_type' => 'api_key', 'project_id' => config('services.gemini.project_id', 'codebridge-chatbot'), 'region' => config('services.vertex_ai.location', 'us-central1'), ]; return $instance; } /** * 활성화된 Claude 설정 조회 (.env 기반) */ public static function getActiveClaude(): ?self { $apiKey = config('services.claude.api_key'); if (! $apiKey) { return null; } $instance = new self; $instance->provider = 'claude'; $instance->api_key = $apiKey; $instance->model = 'claude-sonnet-4-20250514'; $instance->base_url = 'https://api.anthropic.com/v1'; $instance->is_active = true; $instance->options = []; return $instance; } /** * 활성화된 Notion 설정 조회 (.env 기반) */ public static function getActiveNotion(): ?self { $apiKey = config('services.notion.api_key'); if (! $apiKey) { return null; } $instance = new self; $instance->provider = 'notion'; $instance->api_key = $apiKey; $instance->model = config('services.notion.version', '2025-09-03'); $instance->base_url = config('services.notion.base_url', 'https://api.notion.com/v1'); $instance->is_active = true; $instance->options = []; return $instance; } /** * Provider별 활성 설정 조회 (.env 기반) */ public static function getActive(string $provider): ?self { return match ($provider) { 'gemini' => self::getActiveGemini(), 'claude' => self::getActiveClaude(), 'notion' => self::getActiveNotion(), 'gcs' => self::getActiveGcs(), default => null, }; } /** * 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', 'gcs' => 'Google Cloud Storage', 'notion' => 'Notion', default => $this->provider, }; } /** * 활성화된 GCS 설정 조회 (.env 기반) */ public static function getActiveGcs(): ?self { $credentialsPath = config('services.google.credentials_path'); $bucket = config('services.google.storage_bucket'); if (! $bucket) { return null; } $instance = new self; $instance->provider = 'gcs'; $instance->api_key = 'gcs_service_account'; $instance->model = '-'; $instance->base_url = 'https://storage.googleapis.com'; $instance->is_active = true; $instance->options = [ 'bucket_name' => $bucket, 'service_account_path' => $credentialsPath, ]; return $instance; } /** * GCS 버킷 이름 */ public function getBucketName(): ?string { return $this->options['bucket_name'] ?? null; } /** * GCS 서비스 계정 JSON (직접 저장된 경우) */ public function getServiceAccountJson(): ?array { return $this->options['service_account_json'] ?? null; } /** * GCS 설정인지 확인 */ public function isGcs(): bool { return $this->provider === 'gcs'; } /** * AI 설정인지 확인 */ public function isAi(): bool { return in_array($this->provider, self::AI_PROVIDERS); } /** * 상태 라벨 */ 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).'...'; } /** * Vertex AI 사용 여부 */ public function isVertexAi(): bool { return ($this->options['auth_type'] ?? 'api_key') === 'vertex_ai'; } /** * Vertex AI 프로젝트 ID */ public function getProjectId(): ?string { return $this->options['project_id'] ?? null; } /** * Vertex AI 리전 */ public function getRegion(): string { return $this->options['region'] ?? 'us-central1'; } /** * 서비스 계정 파일 경로 */ public function getServiceAccountPath(): ?string { return $this->options['service_account_path'] ?? null; } /** * 인증 방식 라벨 */ public function getAuthTypeLabelAttribute(): string { if ($this->isVertexAi()) { return 'Vertex AI (서비스 계정)'; } return 'API 키'; } }