addType('id', 'integer'); $this->addType('appIconMode', 'string'); $this->addType('defaultTemperature', 'float'); $this->addType('allowMultipleModels', 'bool'); $this->addType('embeddingRateLimitMode', 'string'); $this->addType('embeddingRateLimitSecond', 'integer'); $this->addType('embeddingRateLimitMinute', 'integer'); $this->addType('embeddingRateLimitHour', 'integer'); $this->addType('embeddingRateLimitDay', 'integer'); $this->addType('ragChunkSize', 'integer'); $this->addType('ragChunkOverlap', 'integer'); $this->addType('ragTopK', 'integer'); $this->addType('ragMaxContextTokens', 'integer'); $this->addType('ragEnabled', 'bool'); $this->addType('catalogueEnabled', 'bool'); $this->addType('catalogueReindexHours', 'integer'); $this->addType('catalogueLastIndexed', 'integer'); $this->addType('catalogueCourseCount', 'integer'); $this->addType('doclingEnabled', 'bool'); $this->addType('rateLimitEnabled', 'bool'); $this->addType('rateLimitSecond', 'integer'); $this->addType('rateLimitMinute', 'integer'); $this->addType('rateLimitHour', 'integer'); $this->addType('rateLimitDay', 'integer'); $this->addType('conversationContextTokens', 'integer'); $this->addType('llmChatTimeout', 'integer'); $this->addType('llmStreamTimeout', 'integer'); $this->addType('llmModelsTimeout', 'integer'); $this->addType('updatedAt', 'integer'); } public function jsonSerialize(): array { return [ 'id' => $this->id, 'api_provider' => $this->apiProvider, 'api_key' => $this->apiKey ? '***' : '', // Mask API key in JSON 'api_endpoint' => $this->apiEndpoint ?? '', 'secondary_api_endpoint' => $this->secondaryApiEndpoint ?? '', 'secondary_api_key' => $this->secondaryApiKey ? '***' : '', 'default_model' => $this->defaultModel, 'fallback_model' => $this->fallbackModel, 'app_icon_url' => $this->appIconUrl, 'app_icon_mode' => $this->appIconMode ?: 'default', 'app_icon_black_url' => $this->appIconBlackUrl, 'app_icon_white_url' => $this->appIconWhiteUrl, 'default_temperature' => $this->defaultTemperature ?? 0.2, 'allow_multiple_models' => (bool)$this->allowMultipleModels, 'allowed_models' => $this->decodeAllowedModels(), 'webhook_secret' => $this->webhookSecret ? '***' : '', // Mask secret in JSON 'embedding_api_endpoint' => $this->embeddingApiEndpoint, 'embedding_api_key' => $this->embeddingApiKey ? '***' : '', 'embedding_model' => $this->embeddingModel, 'embedding_rate_limit_mode' => $this->embeddingRateLimitMode, 'embedding_rate_limit_second' => $this->embeddingRateLimitSecond, 'embedding_rate_limit_minute' => $this->embeddingRateLimitMinute, 'embedding_rate_limit_hour' => $this->embeddingRateLimitHour, 'embedding_rate_limit_day' => $this->embeddingRateLimitDay, 'rag_chunk_size' => $this->ragChunkSize, 'rag_chunk_overlap' => $this->ragChunkOverlap, 'rag_top_k' => $this->ragTopK, 'rag_max_context_tokens' => $this->ragMaxContextTokens, 'rag_enabled' => (bool)$this->ragEnabled, 'catalogue_enabled' => (bool)$this->catalogueEnabled, 'catalogue_api_endpoint' => $this->catalogueApiEndpoint, 'catalogue_reindex_hours' => $this->catalogueReindexHours ?? 24, 'catalogue_last_indexed' => $this->catalogueLastIndexed, 'catalogue_course_count' => $this->catalogueCourseCount ?? 0, 'docling_enabled' => (bool)$this->doclingEnabled, 'docling_api_endpoint' => $this->doclingApiEndpoint, 'docling_api_key' => $this->doclingApiKey ? '***' : '', 'vision_api_endpoint' => $this->visionApiEndpoint, 'vision_api_key' => $this->visionApiKey ? '***' : '', 'vision_model' => $this->visionModel, 'speech_api_endpoint' => $this->speechApiEndpoint, 'speech_api_key' => $this->speechApiKey ? '***' : '', 'speech_model' => $this->speechModel, 'rate_limit_enabled' => (bool)$this->rateLimitEnabled, 'rate_limit_second' => $this->rateLimitSecond, 'rate_limit_minute' => $this->rateLimitMinute, 'rate_limit_hour' => $this->rateLimitHour, 'rate_limit_day' => $this->rateLimitDay, 'rate_limit_queue_message' => $this->rateLimitQueueMessage, 'conversation_context_tokens' => $this->conversationContextTokens ?? 8000, 'llm_chat_timeout' => $this->llmChatTimeout ?? 90, 'llm_stream_timeout' => $this->llmStreamTimeout ?? 240, 'llm_models_timeout' => $this->llmModelsTimeout ?? 20, 'updated_at' => $this->updatedAt, ]; } /** * @return array */ private function decodeAllowedModels(): array { $raw = $this->allowedModels; if ($raw === null || $raw === '') { return []; } $decoded = json_decode((string)$raw, true); if (is_array($decoded)) { return array_values(array_map('strval', $decoded)); } return []; } }