mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-07 07:55:16 +02:00
182 lines
6.3 KiB
Python
182 lines
6.3 KiB
Python
import os
|
||
from pathlib import Path
|
||
|
||
from api.enums import Environment
|
||
|
||
ENVIRONMENT = os.getenv("ENVIRONMENT", Environment.LOCAL.value)
|
||
# Absolute path to the project root directory (i.e. the directory containing
|
||
# the top-level api/ package). Having a single canonical location helps
|
||
# when constructing file-system paths elsewhere in the codebase.
|
||
APP_ROOT_DIR: Path = Path(__file__).resolve().parent
|
||
|
||
FILLER_SOUND_PROBABILITY = 0.0
|
||
|
||
VOICEMAIL_RECORDING_DURATION = 5.0
|
||
|
||
# Cloudonix Answering Machine Detection (AMD) constants
|
||
# Ref: https://developers.cloudonix.com/Documentation/apiWorkflow/callControlAndSessionManagement#answering-machine-detection-results
|
||
|
||
# Enables AMD and waits for the full voicemail greeting to finish before reporting a result.
|
||
# Alternative: "Enable" — ends detection immediately upon determination.
|
||
AMD_MACHINE_DETECTION = "DetectMessageEnd"
|
||
|
||
# Runs AMD in the background while the call continues, posting results to asyncAmdStatusCallback.
|
||
# Default: disabled (False).
|
||
AMD_ASYNC = True
|
||
|
||
# HTTP method used when Cloudonix posts the AMD result to the callback URL.
|
||
# Allowed: "POST" or "GET". Default: "POST".
|
||
AMD_CALLBACK_METHOD = "POST"
|
||
|
||
# Maximum seconds to wait for a determination before returning "unknown".
|
||
# Range: 3–59 seconds. Default: 30.
|
||
AMD_MACHINE_DETECTION_TIMEOUT = 30
|
||
|
||
# Minimum greeting duration (ms) expected from an answering machine.
|
||
# Range: 1000–6000 ms. Default: 2400.
|
||
AMD_MACHINE_DETECTION_SPEECH_THRESHOLD = 2400
|
||
|
||
# Duration of silence (ms) after speech that confirms the greeting has ended.
|
||
# Range: 500–5000 ms. Default: 1200.
|
||
AMD_MACHINE_DETECTION_SPEECH_END_THRESHOLD = 1200
|
||
|
||
# Maximum wait (ms) for any audio after the call is answered before timing out.
|
||
# Range: 2000–10000 ms. Default: 5000.
|
||
AMD_MACHINE_DETECTION_SILENCE_TIMEOUT = 5000
|
||
|
||
# Cloudonix AMD final result values
|
||
MACHINE_END_SILENCE = "machine_end_silence"
|
||
MACHINE_END_OTHER = "machine_end_other"
|
||
HUMAN = "human"
|
||
UNKNOWN = "unknown"
|
||
|
||
# Final (non-interim) AMD result values — only these are stored in gathered context.
|
||
AMD_FINAL_RESULTS = {MACHINE_END_SILENCE, MACHINE_END_OTHER, HUMAN, UNKNOWN}
|
||
|
||
# When enabled, Cloudonix calls answered by an answering machine are automatically hung up.
|
||
AMD_HANGUP_ENABLED = os.getenv("AMD_HANGUP_ENABLED", "false").lower() == "true"
|
||
|
||
|
||
# Configuration constants
|
||
ENABLE_TRACING = os.getenv("ENABLE_TRACING", "false").lower() == "true"
|
||
|
||
# Langfuse Configuration
|
||
LANGFUSE_HOST = os.getenv("LANGFUSE_HOST")
|
||
LANGFUSE_PUBLIC_KEY = os.getenv("LANGFUSE_PUBLIC_KEY")
|
||
LANGFUSE_SECRET_KEY = os.getenv("LANGFUSE_SECRET_KEY")
|
||
|
||
# URLs for deployment
|
||
BACKEND_API_ENDPOINT = os.getenv("BACKEND_API_ENDPOINT", "http://localhost:8000")
|
||
UI_APP_URL = os.getenv("UI_APP_URL", "http://localhost:3010")
|
||
|
||
DATABASE_URL = os.environ["DATABASE_URL"]
|
||
REDIS_URL = os.environ["REDIS_URL"]
|
||
|
||
DEPLOYMENT_MODE = os.getenv("DEPLOYMENT_MODE", "oss")
|
||
AUTH_PROVIDER = os.getenv("AUTH_PROVIDER", "local")
|
||
DOGRAH_MPS_SECRET_KEY = os.getenv("DOGRAH_MPS_SECRET_KEY", None)
|
||
MPS_API_URL = os.getenv("MPS_API_URL", "https://services.dograh.com")
|
||
|
||
# Storage Configuration
|
||
ENABLE_AWS_S3 = os.getenv("ENABLE_AWS_S3", "false").lower() == "true"
|
||
|
||
# MinIO Configuration
|
||
MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT", "localhost:9000")
|
||
MINIO_PUBLIC_ENDPOINT = os.getenv("MINIO_PUBLIC_ENDPOINT")
|
||
MINIO_ACCESS_KEY = os.getenv("MINIO_ACCESS_KEY", "minioadmin")
|
||
MINIO_SECRET_KEY = os.getenv("MINIO_SECRET_KEY", "minioadmin")
|
||
MINIO_BUCKET = os.getenv("MINIO_BUCKET", "voice-audio")
|
||
MINIO_SECURE = os.getenv("MINIO_SECURE", "false").lower() == "true"
|
||
|
||
# AWS S3 Configuration
|
||
S3_BUCKET = os.environ.get("S3_BUCKET")
|
||
S3_REGION = os.environ.get("S3_REGION", "us-east-1")
|
||
|
||
# Sentry configuration
|
||
SENTRY_DSN = os.getenv("SENTRY_DSN")
|
||
|
||
|
||
ENABLE_ARI_STASIS = os.getenv("ENABLE_ARI_STASIS", "false").lower() == "true"
|
||
SERIALIZE_LOG_OUTPUT = os.getenv("SERIALIZE_LOG_OUTPUT", "false").lower() == "true"
|
||
|
||
# Logging configuration
|
||
LOG_FILE_PATH = os.getenv("LOG_FILE_PATH", None)
|
||
LOG_LEVEL = os.getenv("LOG_LEVEL", "DEBUG").upper()
|
||
|
||
# Log rotation configuration
|
||
LOG_ROTATION_SIZE = os.getenv("LOG_ROTATION_SIZE", "100 MB")
|
||
LOG_RETENTION = os.getenv("LOG_RETENTION", "7 days")
|
||
LOG_COMPRESSION = os.getenv("LOG_COMPRESSION", "gz")
|
||
ENABLE_TELEMETRY = os.getenv("ENABLE_TELEMETRY", "false").lower() == "true"
|
||
|
||
|
||
def _get_version() -> str:
|
||
"""Read version from pyproject.toml."""
|
||
try:
|
||
import tomllib
|
||
|
||
pyproject_path = APP_ROOT_DIR / "pyproject.toml"
|
||
with open(pyproject_path, "rb") as f:
|
||
pyproject = tomllib.load(f)
|
||
return pyproject.get("project", {}).get("version", "dev")
|
||
except Exception:
|
||
return "dev"
|
||
|
||
|
||
# Application version (read from pyproject.toml)
|
||
APP_VERSION = _get_version()
|
||
|
||
# Country code mapping: ISO country code -> international dialing prefix
|
||
COUNTRY_CODES = {
|
||
"US": "1", # United States
|
||
"CA": "1", # Canada
|
||
"GB": "44", # United Kingdom
|
||
"IN": "91", # India
|
||
"AU": "61", # Australia
|
||
"DE": "49", # Germany
|
||
"FR": "33", # France
|
||
"BR": "55", # Brazil
|
||
"MX": "52", # Mexico
|
||
"IT": "39", # Italy
|
||
"ES": "34", # Spain
|
||
"NL": "31", # Netherlands
|
||
"SE": "46", # Sweden
|
||
"NO": "47", # Norway
|
||
"DK": "45", # Denmark
|
||
"FI": "358", # Finland
|
||
"CH": "41", # Switzerland
|
||
"AT": "43", # Austria
|
||
"BE": "32", # Belgium
|
||
"LU": "352", # Luxembourg
|
||
"IE": "353", # Ireland
|
||
}
|
||
|
||
DEFAULT_ORG_CONCURRENCY_LIMIT = os.getenv("DEFAULT_ORG_CONCURRENCY_LIMIT", 2)
|
||
DEFAULT_CAMPAIGN_RETRY_CONFIG = {
|
||
"enabled": True,
|
||
"max_retries": 1,
|
||
"retry_delay_seconds": 120,
|
||
"retry_on_busy": True,
|
||
"retry_on_no_answer": True,
|
||
"retry_on_voicemail": False,
|
||
}
|
||
|
||
|
||
# Circuit breaker defaults for campaign call failure detection
|
||
DEFAULT_CIRCUIT_BREAKER_CONFIG = {
|
||
"enabled": True,
|
||
"failure_threshold": 0.5, # 50% failure rate trips the breaker
|
||
"window_seconds": 120, # 2-minute sliding window
|
||
"min_calls_in_window": 5, # Don't trip until at least 5 outcomes
|
||
}
|
||
|
||
|
||
TURN_SECRET = os.getenv("TURN_SECRET")
|
||
TURN_HOST = os.getenv("TURN_HOST", "localhost")
|
||
TURN_PORT = int(os.getenv("TURN_PORT", "3478"))
|
||
TURN_TLS_PORT = int(os.getenv("TURN_TLS_PORT", "5349"))
|
||
TURN_CREDENTIAL_TTL = int(os.getenv("TURN_CREDENTIAL_TTL", "86400"))
|
||
|
||
# OSS Email/Password Auth
|
||
OSS_JWT_SECRET = os.getenv("OSS_JWT_SECRET", "change-me-in-production")
|
||
OSS_JWT_EXPIRY_HOURS = int(os.getenv("OSS_JWT_EXPIRY_HOURS", "720")) # 30 days
|