Implement Admin UI to disable AI components
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
"""
|
||||
Global AI feature flags stored in Firestore at config/ai_features.
|
||||
|
||||
Defaults to all-on when the document does not exist yet. Uses a short
|
||||
in-memory TTL cache so flag reads don't add a Firestore round-trip to every
|
||||
call upload.
|
||||
"""
|
||||
import time
|
||||
from typing import Any
|
||||
from app.internal.logger import logger
|
||||
from app.internal import firestore as fstore
|
||||
|
||||
_COLLECTION = "config"
|
||||
_DOC_ID = "ai_features"
|
||||
_TTL = 30.0 # seconds before re-reading from Firestore
|
||||
|
||||
_DEFAULTS: dict[str, bool] = {
|
||||
"stt_enabled": True,
|
||||
"correlation_enabled": True,
|
||||
"summaries_enabled": True,
|
||||
"vocabulary_learning_enabled": True,
|
||||
}
|
||||
|
||||
_cache: dict[str, Any] = {}
|
||||
_cache_ts: float = 0.0
|
||||
|
||||
|
||||
async def get_flags() -> dict[str, bool]:
|
||||
"""Return the current feature flags, using the TTL cache when fresh."""
|
||||
global _cache, _cache_ts
|
||||
|
||||
now = time.monotonic()
|
||||
if _cache and (now - _cache_ts) < _TTL:
|
||||
return dict(_cache)
|
||||
|
||||
try:
|
||||
doc = await fstore.doc_get(_COLLECTION, _DOC_ID)
|
||||
if doc:
|
||||
merged = {**_DEFAULTS, **{k: bool(v) for k, v in doc.items() if k in _DEFAULTS}}
|
||||
else:
|
||||
merged = dict(_DEFAULTS)
|
||||
except Exception as e:
|
||||
logger.warning(f"Feature flags: could not read from Firestore ({e}), using defaults")
|
||||
merged = dict(_DEFAULTS)
|
||||
|
||||
_cache = merged
|
||||
_cache_ts = now
|
||||
return dict(_cache)
|
||||
|
||||
|
||||
async def set_flags(updates: dict[str, bool]) -> dict[str, bool]:
|
||||
"""Write flag updates to Firestore and invalidate the cache."""
|
||||
global _cache, _cache_ts
|
||||
|
||||
clean = {k: bool(v) for k, v in updates.items() if k in _DEFAULTS}
|
||||
if not clean:
|
||||
raise ValueError(f"No recognised flag keys in update: {list(updates)}")
|
||||
|
||||
await fstore.doc_set(_COLLECTION, _DOC_ID, clean)
|
||||
_cache_ts = 0.0 # force re-read on next get_flags()
|
||||
logger.info(f"Feature flags updated: {clean}")
|
||||
return await get_flags()
|
||||
Reference in New Issue
Block a user