import os from sqlalchemy.orm import Session as DBSession from app.db.models import AppSetting # GUIから編集可能な環境変数の許可リスト。ここに無いキーは save()/clear() で拒否する。 CONFIGURABLE_KEYS = [ "OPENAI_API_KEY", "ANTHROPIC_API_KEY", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN", "AWS_BEARER_TOKEN_BEDROCK", "AWS_REGION_NAME", "OLLAMA_API_BASE", "TAVILY_API_KEY", "LOCAL_KB_EMBEDDING_MODEL", "SEARCH_SUMMARY_MODEL", ] # 秘匿情報ではないキー。値をマスクせずそのまま返し、GUIでも通常のテキスト入力として扱う。 # モデル名やURLは「今どれが効いているか」が見えないと設定しづらいため。 NON_SECRET_KEYS = { "AWS_REGION_NAME", "OLLAMA_API_BASE", "LOCAL_KB_EMBEDDING_MODEL", "SEARCH_SUMMARY_MODEL", } # .env由来の起動時の値のスナップショット。clear() で戻す先として使う。 _env_defaults: dict[str, str | None] = {} _snapshot_taken = False def _ensure_snapshot() -> None: global _snapshot_taken if _snapshot_taken: return for key in CONFIGURABLE_KEYS: _env_defaults[key] = os.environ.get(key) _snapshot_taken = True def _mask(value: str) -> str: if len(value) <= 4: return "••••" return f"••••{value[-4:]}" def load_into_env(db: DBSession) -> None: """DBに保存済みの値をos.environに適用する。起動時に一度呼ぶ。""" _ensure_snapshot() for row in db.query(AppSetting).all(): if row.key in CONFIGURABLE_KEYS: os.environ[row.key] = row.value def list_masked(db: DBSession) -> list[dict]: """GUI設定画面に出す一覧。秘匿キーの値はマスクし、そうでないキーは現在値をそのまま見せる。""" _ensure_snapshot() saved = {row.key: row.value for row in db.query(AppSetting).all()} result = [] for key in CONFIGURABLE_KEYS: current = os.environ.get(key) secret = key not in NON_SECRET_KEYS result.append({ "key": key, "is_set": bool(current), "display_value": (_mask(current) if secret else current) if current else None, "secret": secret, "overridden": key in saved, }) return result def save(db: DBSession, key: str, value: str) -> None: if key not in CONFIGURABLE_KEYS: raise ValueError(f"Unknown setting key: {key}") _ensure_snapshot() row = db.get(AppSetting, key) if row: row.value = value else: db.add(AppSetting(key=key, value=value)) db.commit() os.environ[key] = value def clear(db: DBSession, key: str) -> None: if key not in CONFIGURABLE_KEYS: raise ValueError(f"Unknown setting key: {key}") _ensure_snapshot() row = db.get(AppSetting, key) if row: db.delete(row) db.commit() original = _env_defaults.get(key) if original is None: os.environ.pop(key, None) else: os.environ[key] = original