caarleexx commited on
Commit
527ab2e
·
verified ·
1 Parent(s): bc8b116

Upload config.py

Browse files
Files changed (1) hide show
  1. api/config.py +150 -98
api/config.py CHANGED
@@ -1,171 +1,186 @@
1
  """
2
- Configurações centralizadas da API para.AI v3.0
3
- Gerencia todas as variáveis de ambiente e configurações do sistema
4
  """
5
  import os
6
  from typing import Optional, List
7
  from pydantic_settings import BaseSettings
8
  from pydantic import Field
9
  from functools import lru_cache
 
10
 
11
 
12
  class Settings(BaseSettings):
13
  """
14
- Configurações da aplicação para.AI.
15
 
16
- Todas as configurações podem ser sobrescritas via variáveis de ambiente.
17
- Carrega automaticamente de arquivo .env se presente.
 
 
 
18
  """
19
 
20
  # ========================================================================
21
  # API SETTINGS
22
  # ========================================================================
23
- APP_NAME: str = "para.AI API"
24
- APP_VERSION: str = "3.0.0"
25
- APP_DESCRIPTION: str = "API para análise automatizada de acórdãos jurisprudenciais"
26
- APP_ENV: str = Field(default="production", env="APP_ENV")
27
- DEBUG: bool = Field(default=False, env="DEBUG")
28
 
29
  # ========================================================================
30
  # SERVER SETTINGS
31
  # ========================================================================
32
  HOST: str = Field(default="0.0.0.0", env="HOST")
33
  PORT: int = Field(default=8000, env="PORT")
34
- WORKERS: int = Field(default=4, env="WORKERS")
35
- RELOAD: bool = Field(default=False, env="RELOAD")
36
 
37
  # ========================================================================
38
- # DATABASE SETTINGS
39
  # ========================================================================
 
 
 
 
 
 
 
 
40
  DATABASE_URL: str = Field(
41
- default="postgresql://para_ai:para_ai@localhost:5432/para_ai",
42
  env="DATABASE_URL",
43
- description="PostgreSQL connection string"
44
  )
45
- DB_POOL_SIZE: int = Field(default=20, env="DB_POOL_SIZE")
46
- DB_MAX_OVERFLOW: int = Field(default=40, env="DB_MAX_OVERFLOW")
 
 
 
 
 
 
 
 
47
  DB_POOL_TIMEOUT: int = Field(default=30, env="DB_POOL_TIMEOUT")
48
  DB_POOL_RECYCLE: int = Field(default=3600, env="DB_POOL_RECYCLE")
49
  SQL_ECHO: bool = Field(default=False, env="SQL_ECHO")
50
 
51
  # ========================================================================
52
- # FILES & STORAGE SETTINGS
53
  # ========================================================================
54
  FILES_BASE_PATH: str = Field(default="./data/files", env="FILES_BASE_PATH")
55
  UPLOAD_PATH: str = Field(default="./data/uploads", env="UPLOAD_PATH")
56
  OUTPUT_PATH: str = Field(default="./data/outputs", env="OUTPUT_PATH")
57
  TEMP_PATH: str = Field(default="./data/temp", env="TEMP_PATH")
58
  BACKUP_PATH: str = Field(default="./data/backups", env="BACKUP_PATH")
59
-
60
- MAX_UPLOAD_SIZE_MB: int = Field(default=500, env="MAX_UPLOAD_SIZE_MB")
61
 
62
  # ========================================================================
63
- # LLM PROVIDERS API KEYS
64
  # ========================================================================
65
  GROQ_API_KEY: Optional[str] = Field(default=None, env="GROQ_API_KEY")
66
  OPENAI_API_KEY: Optional[str] = Field(default=None, env="OPENAI_API_KEY")
67
  ANTHROPIC_API_KEY: Optional[str] = Field(default=None, env="ANTHROPIC_API_KEY")
68
 
69
  DEFAULT_LLM_PROVIDER: str = Field(default="groq", env="DEFAULT_LLM_PROVIDER")
70
- DEFAULT_MODEL_TYPE: str = Field(default="balanced", env="DEFAULT_MODEL_TYPE")
71
 
72
- # LLM Request defaults
73
  LLM_DEFAULT_TEMPERATURE: float = Field(default=0.7, env="LLM_DEFAULT_TEMPERATURE")
74
- LLM_DEFAULT_MAX_TOKENS: int = Field(default=2048, env="LLM_DEFAULT_MAX_TOKENS")
75
- LLM_TIMEOUT_SECONDS: int = Field(default=60, env="LLM_TIMEOUT_SECONDS")
76
 
77
  # ========================================================================
78
- # PROCESSING SETTINGS
79
  # ========================================================================
80
- MAX_CONCURRENT_PROCESSES: int = Field(default=5, env="MAX_CONCURRENT_PROCESSES")
81
- PROCESS_TIMEOUT_SECONDS: int = Field(default=600, env="PROCESS_TIMEOUT_SECONDS")
82
- ENABLE_PARALLEL_PROCESSING: bool = Field(default=True, env="ENABLE_PARALLEL")
83
- DEFAULT_MAX_WORKERS: int = Field(default=3, env="DEFAULT_MAX_WORKERS")
84
 
85
- # Batch processing
86
- BATCH_SIZE: int = Field(default=10, env="BATCH_SIZE")
87
- BATCH_DELAY_MS: int = Field(default=100, env="BATCH_DELAY_MS")
88
 
89
  # ========================================================================
90
- # LOGGING SETTINGS
91
  # ========================================================================
92
- LOG_LEVEL: str = Field(default="INFO", env="LOG_LEVEL")
93
  LOG_FORMAT: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
94
  LOG_FILE_ENABLED: bool = Field(default=True, env="LOG_FILE_ENABLED")
95
  LOG_FILE_PATH: str = Field(default="./logs", env="LOG_FILE_PATH")
96
- LOG_FILE_MAX_BYTES: int = Field(default=10485760, env="LOG_FILE_MAX_BYTES")
97
- LOG_FILE_BACKUP_COUNT: int = Field(default=5, env="LOG_FILE_BACKUP_COUNT")
98
 
99
  # ========================================================================
100
- # SECURITY SETTINGS
101
  # ========================================================================
102
- # CORS - usar string ao invés de List para evitar erro de parsing
103
  CORS_ORIGINS: str = Field(default="*", env="CORS_ORIGINS")
104
  CORS_ALLOW_CREDENTIALS: bool = True
105
 
106
- # API Keys - usar string ao invés de List
107
  API_KEY_HEADER: str = Field(default="X-API-Key", env="API_KEY_HEADER")
108
  REQUIRE_API_KEY: bool = Field(default=False, env="REQUIRE_API_KEY")
109
- VALID_API_KEYS: str = Field(default="", env="VALID_API_KEYS")
110
 
111
- # Rate limiting
112
  RATE_LIMIT_ENABLED: bool = Field(default=False, env="RATE_LIMIT_ENABLED")
113
- RATE_LIMIT_PER_MINUTE: int = Field(default=60, env="RATE_LIMIT_PER_MINUTE")
114
 
115
  # ========================================================================
116
- # CACHE SETTINGS
117
  # ========================================================================
118
- ENABLE_CACHE: bool = Field(default=False, env="ENABLE_CACHE")
119
- CACHE_TTL_SECONDS: int = Field(default=3600, env="CACHE_TTL_SECONDS")
120
  CACHE_BACKEND: str = Field(default="memory", env="CACHE_BACKEND")
121
  REDIS_URL: Optional[str] = Field(default=None, env="REDIS_URL")
122
 
123
  # ========================================================================
124
- # MONITORING & METRICS
125
  # ========================================================================
126
  ENABLE_METRICS: bool = Field(default=True, env="ENABLE_METRICS")
127
  METRICS_EXPORT_INTERVAL: int = Field(default=60, env="METRICS_EXPORT_INTERVAL")
128
-
129
- # Prometheus
130
  PROMETHEUS_ENABLED: bool = Field(default=False, env="PROMETHEUS_ENABLED")
131
  PROMETHEUS_PORT: int = Field(default=9090, env="PROMETHEUS_PORT")
132
 
133
  # ========================================================================
134
- # PROCESSORS SETTINGS
135
  # ========================================================================
136
- MIN_CONFIDENCE_THRESHOLD: float = Field(default=0.7, env="MIN_CONFIDENCE_THRESHOLD")
137
 
138
  # ========================================================================
139
- # DEVELOPMENT & DEBUG
140
  # ========================================================================
141
- DEV_MODE: bool = Field(default=False, env="DEV_MODE")
142
  MOCK_LLM_RESPONSES: bool = Field(default=False, env="MOCK_LLM_RESPONSES")
143
- SAVE_DEBUG_FILES: bool = Field(default=False, env="SAVE_DEBUG_FILES")
144
 
145
  # ========================================================================
146
- # ADVANCED SETTINGS
147
  # ========================================================================
148
  ENABLE_REQUEST_ID: bool = Field(default=True, env="ENABLE_REQUEST_ID")
149
  REQUEST_ID_HEADER: str = "X-Request-ID"
150
-
151
  ENABLE_GZIP: bool = Field(default=True, env="ENABLE_GZIP")
152
  GZIP_MIN_SIZE: int = Field(default=1000, env="GZIP_MIN_SIZE")
153
-
154
- HTTP_TIMEOUT_SECONDS: int = Field(default=300, env="HTTP_TIMEOUT_SECONDS")
155
-
156
- TASK_RETENTION_HOURS: int = Field(default=24, env="TASK_RETENTION_HOURS")
157
  AUTO_CLEANUP_ENABLED: bool = Field(default=True, env="AUTO_CLEANUP_ENABLED")
158
 
 
 
 
 
 
 
 
 
159
  class Config:
160
- """Pydantic config."""
161
  env_file = ".env"
162
  env_file_encoding = "utf-8"
163
  case_sensitive = True
164
- extra = "ignore" # Ignorar variáveis extras
165
 
166
  @property
167
  def cors_origins_list(self) -> List[str]:
168
- """Retorna CORS_ORIGINS como lista."""
169
  if isinstance(self.CORS_ORIGINS, str):
170
  if self.CORS_ORIGINS == "*":
171
  return ["*"]
@@ -174,7 +189,6 @@ class Settings(BaseSettings):
174
 
175
  @property
176
  def valid_api_keys_list(self) -> List[str]:
177
- """Retorna VALID_API_KEYS como lista."""
178
  if not self.VALID_API_KEYS:
179
  return []
180
  if isinstance(self.VALID_API_KEYS, str):
@@ -183,34 +197,55 @@ class Settings(BaseSettings):
183
 
184
  @property
185
  def is_production(self) -> bool:
186
- """Verifica se está em produção."""
187
  return self.APP_ENV.lower() == "production"
188
 
189
  @property
190
  def is_development(self) -> bool:
191
- """Verifica se está em desenvolvimento."""
192
- return self.APP_ENV.lower() in ["development", "dev"]
 
 
 
193
 
194
  @property
195
  def database_url_masked(self) -> str:
196
- """Retorna DATABASE_URL com senha mascarada."""
 
197
  if "@" in self.DATABASE_URL:
198
  parts = self.DATABASE_URL.split("@")
199
  return f"***@{parts[1]}"
200
  return self.DATABASE_URL
201
 
 
 
 
 
 
 
 
202
  def get_llm_providers_status(self) -> dict:
203
- """Retorna status de configuração dos provedores LLM."""
204
  return {
205
  "groq": bool(self.GROQ_API_KEY),
206
  "openai": bool(self.OPENAI_API_KEY),
207
  "anthropic": bool(self.ANTHROPIC_API_KEY)
208
  }
209
 
210
- def validate_paths(self) -> None:
211
- """Cria diretórios necessários se não existirem."""
212
- from pathlib import Path
 
 
213
 
 
 
 
 
 
 
 
 
 
 
214
  paths = [
215
  self.FILES_BASE_PATH,
216
  self.UPLOAD_PATH,
@@ -224,16 +259,16 @@ class Settings(BaseSettings):
224
  path = Path(path_str)
225
  path.mkdir(parents=True, exist_ok=True)
226
 
 
 
 
227
  def to_dict(self) -> dict:
228
- """Converte settings para dict (sem expor secrets)."""
229
  data = self.model_dump()
230
 
231
- # Mascarar informações sensíveis
232
  sensitive_keys = [
233
  "GROQ_API_KEY",
234
  "OPENAI_API_KEY",
235
  "ANTHROPIC_API_KEY",
236
- "DATABASE_URL",
237
  "VALID_API_KEYS",
238
  "REDIS_URL"
239
  ]
@@ -242,46 +277,63 @@ class Settings(BaseSettings):
242
  if key in data and data[key]:
243
  data[key] = "***HIDDEN***"
244
 
245
- return data
 
 
 
 
 
 
 
 
 
246
 
 
247
 
248
- # ============================================================================
249
- # SINGLETON INSTANCE
250
- # ============================================================================
251
 
252
  @lru_cache()
253
  def get_settings() -> Settings:
254
- """
255
- Retorna instância singleton das configurações.
256
-
257
- Usa lru_cache para garantir que Settings é criado apenas uma vez
258
- e reutilizado em toda a aplicação.
259
-
260
- Returns:
261
- Settings: Instância configurada
262
- """
263
  settings = Settings()
264
-
265
- # Validar e criar paths necessários
266
  settings.validate_paths()
267
-
268
  return settings
269
 
270
 
271
- # ============================================================================
272
- # HELPER FUNCTIONS
273
- # ============================================================================
274
-
275
  def get_env(key: str, default: any = None) -> any:
276
- """Helper para pegar variável de ambiente."""
277
  return os.getenv(key, default)
278
 
279
 
280
  def is_production() -> bool:
281
- """Verifica se está rodando em produção."""
282
  return get_settings().is_production
283
 
284
 
285
  def is_development() -> bool:
286
- """Verifica se está rodando em desenvolvimento."""
287
  return get_settings().is_development
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
+ Configurações para para.AI v3.0 - VERSÃO TESTE INTERNO (SQLite)
3
+ Otimizado para desenvolvimento, testes e deploys leves sem PostgreSQL
4
  """
5
  import os
6
  from typing import Optional, List
7
  from pydantic_settings import BaseSettings
8
  from pydantic import Field
9
  from functools import lru_cache
10
+ from pathlib import Path
11
 
12
 
13
  class Settings(BaseSettings):
14
  """
15
+ Configurações para ambiente de TESTE INTERNO com SQLite.
16
 
17
+ Características:
18
+ - SQLite em vez de PostgreSQL (sem container DB)
19
+ - Configurações simplificadas
20
+ - Otimizado para desenvolvimento e CI/CD
21
+ - Build rápido (~2min vs 8min)
22
  """
23
 
24
  # ========================================================================
25
  # API SETTINGS
26
  # ========================================================================
27
+ APP_NAME: str = "para.AI API - SQLite Test"
28
+ APP_VERSION: str = "3.0.0-sqlite"
29
+ APP_DESCRIPTION: str = "API de teste para análise de acórdãos (SQLite)"
30
+ APP_ENV: str = Field(default="development", env="APP_ENV")
31
+ DEBUG: bool = Field(default=True, env="DEBUG")
32
 
33
  # ========================================================================
34
  # SERVER SETTINGS
35
  # ========================================================================
36
  HOST: str = Field(default="0.0.0.0", env="HOST")
37
  PORT: int = Field(default=8000, env="PORT")
38
+ WORKERS: int = Field(default=1, env="WORKERS") # 1 worker para SQLite
39
+ RELOAD: bool = Field(default=True, env="RELOAD")
40
 
41
  # ========================================================================
42
+ # DATABASE SETTINGS - SQLITE
43
  # ========================================================================
44
+ DATABASE_TYPE: str = Field(default="sqlite", env="DATABASE_TYPE")
45
+
46
+ SQLITE_DB_PATH: str = Field(
47
+ default="./data/para_ai.db",
48
+ env="SQLITE_DB_PATH",
49
+ description="Caminho do arquivo SQLite"
50
+ )
51
+
52
  DATABASE_URL: str = Field(
53
+ default="sqlite:///./data/para_ai.db",
54
  env="DATABASE_URL",
55
+ description="SQLite connection string"
56
  )
57
+
58
+ SQLITE_TIMEOUT: int = Field(default=30, env="SQLITE_TIMEOUT")
59
+ SQLITE_CHECK_SAME_THREAD: bool = Field(
60
+ default=False,
61
+ env="SQLITE_CHECK_SAME_THREAD"
62
+ )
63
+
64
+ # Pool settings (reduzidos)
65
+ DB_POOL_SIZE: int = Field(default=5, env="DB_POOL_SIZE")
66
+ DB_MAX_OVERFLOW: int = Field(default=10, env="DB_MAX_OVERFLOW")
67
  DB_POOL_TIMEOUT: int = Field(default=30, env="DB_POOL_TIMEOUT")
68
  DB_POOL_RECYCLE: int = Field(default=3600, env="DB_POOL_RECYCLE")
69
  SQL_ECHO: bool = Field(default=False, env="SQL_ECHO")
70
 
71
  # ========================================================================
72
+ # FILES & STORAGE
73
  # ========================================================================
74
  FILES_BASE_PATH: str = Field(default="./data/files", env="FILES_BASE_PATH")
75
  UPLOAD_PATH: str = Field(default="./data/uploads", env="UPLOAD_PATH")
76
  OUTPUT_PATH: str = Field(default="./data/outputs", env="OUTPUT_PATH")
77
  TEMP_PATH: str = Field(default="./data/temp", env="TEMP_PATH")
78
  BACKUP_PATH: str = Field(default="./data/backups", env="BACKUP_PATH")
79
+ MAX_UPLOAD_SIZE_MB: int = Field(default=100, env="MAX_UPLOAD_SIZE_MB")
 
80
 
81
  # ========================================================================
82
+ # LLM PROVIDERS
83
  # ========================================================================
84
  GROQ_API_KEY: Optional[str] = Field(default=None, env="GROQ_API_KEY")
85
  OPENAI_API_KEY: Optional[str] = Field(default=None, env="OPENAI_API_KEY")
86
  ANTHROPIC_API_KEY: Optional[str] = Field(default=None, env="ANTHROPIC_API_KEY")
87
 
88
  DEFAULT_LLM_PROVIDER: str = Field(default="groq", env="DEFAULT_LLM_PROVIDER")
89
+ DEFAULT_MODEL_TYPE: str = Field(default="fast", env="DEFAULT_MODEL_TYPE")
90
 
 
91
  LLM_DEFAULT_TEMPERATURE: float = Field(default=0.7, env="LLM_DEFAULT_TEMPERATURE")
92
+ LLM_DEFAULT_MAX_TOKENS: int = Field(default=1024, env="LLM_DEFAULT_MAX_TOKENS")
93
+ LLM_TIMEOUT_SECONDS: int = Field(default=30, env="LLM_TIMEOUT_SECONDS")
94
 
95
  # ========================================================================
96
+ # PROCESSING
97
  # ========================================================================
98
+ MAX_CONCURRENT_PROCESSES: int = Field(default=2, env="MAX_CONCURRENT_PROCESSES")
99
+ PROCESS_TIMEOUT_SECONDS: int = Field(default=300, env="PROCESS_TIMEOUT_SECONDS")
100
+ ENABLE_PARALLEL_PROCESSING: bool = Field(default=False, env="ENABLE_PARALLEL")
101
+ DEFAULT_MAX_WORKERS: int = Field(default=1, env="DEFAULT_MAX_WORKERS")
102
 
103
+ BATCH_SIZE: int = Field(default=5, env="BATCH_SIZE")
104
+ BATCH_DELAY_MS: int = Field(default=200, env="BATCH_DELAY_MS")
 
105
 
106
  # ========================================================================
107
+ # LOGGING
108
  # ========================================================================
109
+ LOG_LEVEL: str = Field(default="DEBUG", env="LOG_LEVEL")
110
  LOG_FORMAT: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
111
  LOG_FILE_ENABLED: bool = Field(default=True, env="LOG_FILE_ENABLED")
112
  LOG_FILE_PATH: str = Field(default="./logs", env="LOG_FILE_PATH")
113
+ LOG_FILE_MAX_BYTES: int = Field(default=5242880, env="LOG_FILE_MAX_BYTES")
114
+ LOG_FILE_BACKUP_COUNT: int = Field(default=3, env="LOG_FILE_BACKUP_COUNT")
115
 
116
  # ========================================================================
117
+ # SECURITY
118
  # ========================================================================
 
119
  CORS_ORIGINS: str = Field(default="*", env="CORS_ORIGINS")
120
  CORS_ALLOW_CREDENTIALS: bool = True
121
 
 
122
  API_KEY_HEADER: str = Field(default="X-API-Key", env="API_KEY_HEADER")
123
  REQUIRE_API_KEY: bool = Field(default=False, env="REQUIRE_API_KEY")
124
+ VALID_API_KEYS: str = Field(default="test-key-123,dev-key-456", env="VALID_API_KEYS")
125
 
 
126
  RATE_LIMIT_ENABLED: bool = Field(default=False, env="RATE_LIMIT_ENABLED")
127
+ RATE_LIMIT_PER_MINUTE: int = Field(default=1000, env="RATE_LIMIT_PER_MINUTE")
128
 
129
  # ========================================================================
130
+ # CACHE
131
  # ========================================================================
132
+ ENABLE_CACHE: bool = Field(default=True, env="ENABLE_CACHE")
133
+ CACHE_TTL_SECONDS: int = Field(default=300, env="CACHE_TTL_SECONDS")
134
  CACHE_BACKEND: str = Field(default="memory", env="CACHE_BACKEND")
135
  REDIS_URL: Optional[str] = Field(default=None, env="REDIS_URL")
136
 
137
  # ========================================================================
138
+ # METRICS
139
  # ========================================================================
140
  ENABLE_METRICS: bool = Field(default=True, env="ENABLE_METRICS")
141
  METRICS_EXPORT_INTERVAL: int = Field(default=60, env="METRICS_EXPORT_INTERVAL")
 
 
142
  PROMETHEUS_ENABLED: bool = Field(default=False, env="PROMETHEUS_ENABLED")
143
  PROMETHEUS_PORT: int = Field(default=9090, env="PROMETHEUS_PORT")
144
 
145
  # ========================================================================
146
+ # PROCESSORS
147
  # ========================================================================
148
+ MIN_CONFIDENCE_THRESHOLD: float = Field(default=0.5, env="MIN_CONFIDENCE_THRESHOLD")
149
 
150
  # ========================================================================
151
+ # DEVELOPMENT
152
  # ========================================================================
153
+ DEV_MODE: bool = Field(default=True, env="DEV_MODE")
154
  MOCK_LLM_RESPONSES: bool = Field(default=False, env="MOCK_LLM_RESPONSES")
155
+ SAVE_DEBUG_FILES: bool = Field(default=True, env="SAVE_DEBUG_FILES")
156
 
157
  # ========================================================================
158
+ # ADVANCED
159
  # ========================================================================
160
  ENABLE_REQUEST_ID: bool = Field(default=True, env="ENABLE_REQUEST_ID")
161
  REQUEST_ID_HEADER: str = "X-Request-ID"
 
162
  ENABLE_GZIP: bool = Field(default=True, env="ENABLE_GZIP")
163
  GZIP_MIN_SIZE: int = Field(default=1000, env="GZIP_MIN_SIZE")
164
+ HTTP_TIMEOUT_SECONDS: int = Field(default=60, env="HTTP_TIMEOUT_SECONDS")
165
+ TASK_RETENTION_HOURS: int = Field(default=6, env="TASK_RETENTION_HOURS")
 
 
166
  AUTO_CLEANUP_ENABLED: bool = Field(default=True, env="AUTO_CLEANUP_ENABLED")
167
 
168
+ # ========================================================================
169
+ # SQLITE-SPECIFIC
170
+ # ========================================================================
171
+ SQLITE_JOURNAL_MODE: str = Field(default="WAL", env="SQLITE_JOURNAL_MODE")
172
+ SQLITE_SYNCHRONOUS: str = Field(default="NORMAL", env="SQLITE_SYNCHRONOUS")
173
+ SQLITE_CACHE_SIZE: int = Field(default=10000, env="SQLITE_CACHE_SIZE")
174
+ SQLITE_AUTO_VACUUM: bool = Field(default=True, env="SQLITE_AUTO_VACUUM")
175
+
176
  class Config:
 
177
  env_file = ".env"
178
  env_file_encoding = "utf-8"
179
  case_sensitive = True
180
+ extra = "ignore"
181
 
182
  @property
183
  def cors_origins_list(self) -> List[str]:
 
184
  if isinstance(self.CORS_ORIGINS, str):
185
  if self.CORS_ORIGINS == "*":
186
  return ["*"]
 
189
 
190
  @property
191
  def valid_api_keys_list(self) -> List[str]:
 
192
  if not self.VALID_API_KEYS:
193
  return []
194
  if isinstance(self.VALID_API_KEYS, str):
 
197
 
198
  @property
199
  def is_production(self) -> bool:
 
200
  return self.APP_ENV.lower() == "production"
201
 
202
  @property
203
  def is_development(self) -> bool:
204
+ return self.APP_ENV.lower() in ["development", "dev", "test"]
205
+
206
+ @property
207
+ def is_sqlite(self) -> bool:
208
+ return self.DATABASE_TYPE.lower() == "sqlite" or self.DATABASE_URL.startswith("sqlite")
209
 
210
  @property
211
  def database_url_masked(self) -> str:
212
+ if self.is_sqlite:
213
+ return self.DATABASE_URL
214
  if "@" in self.DATABASE_URL:
215
  parts = self.DATABASE_URL.split("@")
216
  return f"***@{parts[1]}"
217
  return self.DATABASE_URL
218
 
219
+ @property
220
+ def sqlite_db_file_path(self) -> Path:
221
+ if self.DATABASE_URL.startswith("sqlite:///"):
222
+ path_str = self.DATABASE_URL.replace("sqlite:///", "")
223
+ return Path(path_str)
224
+ return Path(self.SQLITE_DB_PATH)
225
+
226
  def get_llm_providers_status(self) -> dict:
 
227
  return {
228
  "groq": bool(self.GROQ_API_KEY),
229
  "openai": bool(self.OPENAI_API_KEY),
230
  "anthropic": bool(self.ANTHROPIC_API_KEY)
231
  }
232
 
233
+ def get_sqlite_connection_args(self) -> dict:
234
+ return {
235
+ "check_same_thread": self.SQLITE_CHECK_SAME_THREAD,
236
+ "timeout": self.SQLITE_TIMEOUT
237
+ }
238
 
239
+ def get_sqlite_pragma_statements(self) -> List[str]:
240
+ return [
241
+ f"PRAGMA journal_mode={self.SQLITE_JOURNAL_MODE}",
242
+ f"PRAGMA synchronous={self.SQLITE_SYNCHRONOUS}",
243
+ f"PRAGMA cache_size={self.SQLITE_CACHE_SIZE}",
244
+ "PRAGMA foreign_keys=ON",
245
+ f"PRAGMA auto_vacuum={'FULL' if self.SQLITE_AUTO_VACUUM else 'NONE'}"
246
+ ]
247
+
248
+ def validate_paths(self) -> None:
249
  paths = [
250
  self.FILES_BASE_PATH,
251
  self.UPLOAD_PATH,
 
259
  path = Path(path_str)
260
  path.mkdir(parents=True, exist_ok=True)
261
 
262
+ db_path = self.sqlite_db_file_path
263
+ db_path.parent.mkdir(parents=True, exist_ok=True)
264
+
265
  def to_dict(self) -> dict:
 
266
  data = self.model_dump()
267
 
 
268
  sensitive_keys = [
269
  "GROQ_API_KEY",
270
  "OPENAI_API_KEY",
271
  "ANTHROPIC_API_KEY",
 
272
  "VALID_API_KEYS",
273
  "REDIS_URL"
274
  ]
 
277
  if key in data and data[key]:
278
  data[key] = "***HIDDEN***"
279
 
280
+ data["_runtime_info"] = {
281
+ "is_sqlite": self.is_sqlite,
282
+ "is_development": self.is_development,
283
+ "database_file_exists": self.sqlite_db_file_path.exists() if self.is_sqlite else None,
284
+ "database_file_size_mb": (
285
+ self.sqlite_db_file_path.stat().st_size / (1024**2)
286
+ if self.is_sqlite and self.sqlite_db_file_path.exists()
287
+ else None
288
+ )
289
+ }
290
 
291
+ return data
292
 
 
 
 
293
 
294
  @lru_cache()
295
  def get_settings() -> Settings:
 
 
 
 
 
 
 
 
 
296
  settings = Settings()
 
 
297
  settings.validate_paths()
 
298
  return settings
299
 
300
 
 
 
 
 
301
  def get_env(key: str, default: any = None) -> any:
 
302
  return os.getenv(key, default)
303
 
304
 
305
  def is_production() -> bool:
 
306
  return get_settings().is_production
307
 
308
 
309
  def is_development() -> bool:
 
310
  return get_settings().is_development
311
+
312
+
313
+ def is_sqlite() -> bool:
314
+ return get_settings().is_sqlite
315
+
316
+
317
+ def get_database_info() -> dict:
318
+ settings = get_settings()
319
+
320
+ info = {
321
+ "type": "sqlite" if settings.is_sqlite else "postgresql",
322
+ "url_masked": settings.database_url_masked
323
+ }
324
+
325
+ if settings.is_sqlite:
326
+ db_path = settings.sqlite_db_file_path
327
+ info.update({
328
+ "file_path": str(db_path),
329
+ "file_exists": db_path.exists(),
330
+ "file_size_mb": (
331
+ db_path.stat().st_size / (1024**2)
332
+ if db_path.exists()
333
+ else 0
334
+ ),
335
+ "journal_mode": settings.SQLITE_JOURNAL_MODE,
336
+ "synchronous": settings.SQLITE_SYNCHRONOUS
337
+ })
338
+
339
+ return info