File size: 2,334 Bytes
ec17af3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import json

from pydantic import ConfigDict
from pydantic_settings import BaseSettings


class Settings(BaseSettings):
    model_config = ConfigDict(env_prefix="", case_sensitive=False)

    database_url: str = "sqlite:///./local.db"
    jwt_secret: str = "change-me"
    jwt_algorithm: str = "HS256"
    access_token_expire_minutes: int = 15
    refresh_token_expire_days: int = 7
    cookie_path: str = "/auth"
    environment: str = "development"
    cors_origins: str = "http://localhost:3000"
    max_upload_mb: int = 500
    redis_host: str = "localhost"
    redis_port: int = 6379
    storage_backend: str = "local"
    local_only_mode: bool = False
    local_admin_email: str = "admin@example.local"
    local_admin_password: str = ""
    storage_dir: str = "./data/storage"
    s3_endpoint: str | None = None
    s3_access_key: str | None = None
    s3_secret_key: str | None = None
    s3_bucket: str | None = None
    s3_region: str | None = None
    transcription_backend: str = "server"
    whisper_model: str = "small"
    whisper_device: str = "cpu"
    mlx_audio_model: str = "mlx-community/parakeet-tdt-0.6b-v3"
    ollama_base_url: str = "http://127.0.0.1:11434"
    lmstudio_base_url: str = "http://127.0.0.1:1234/v1"
    llama_cpp_base_url: str = "http://127.0.0.1:8080"
    local_engine_timeout_seconds: float = 0.75
    coaching_enabled: bool = True
    coaching_provider: str = "auto"
    coaching_fallback_builtin: bool = True
    coaching_model: str = "llama3.2:3b"
    coaching_timeout_seconds: float = 90
    coaching_max_transcript_chars: int = 8000
    use_local_worker_fallback: bool = True

    @property
    def cors_origin_list(self) -> list[str]:
        value = self.cors_origins.strip()
        if value.startswith("["):
            try:
                parsed = json.loads(value)
            except json.JSONDecodeError:
                parsed = None
            if isinstance(parsed, list):
                return [str(origin).strip() for origin in parsed if str(origin).strip()]
        return [origin.strip() for origin in value.split(",") if origin.strip()]

    @property
    def max_upload_bytes(self) -> int:
        return self.max_upload_mb * 1024 * 1024

    @property
    def cookie_secure(self) -> bool:
        return self.environment.lower() == "production"


settings = Settings()