"""OS keyring wrapper for storing provider API keys. Service name: 'my-deepagent'.""" from __future__ import annotations from typing import Final import keyring as keyring _SERVICE: Final[str] = "my-deepagent" def _make_username(provider: str) -> str: return f"{provider}_api_key" def get_api_key(provider: str) -> str | None: """Return the stored key for ``provider``, or None if absent.""" return keyring.get_password(_SERVICE, _make_username(provider)) def set_api_key(provider: str, value: str) -> None: """Persist ``value`` in the OS keyring under provider's slot.""" keyring.set_password(_SERVICE, _make_username(provider), value) def delete_api_key(provider: str) -> bool: """Remove the stored key. Returns True if a key existed and was removed.""" if keyring.get_password(_SERVICE, _make_username(provider)) is None: return False keyring.delete_password(_SERVICE, _make_username(provider)) return True def list_providers() -> list[str]: """Return the providers we recognise (we don't enumerate keyring contents). Callers iterate this list and call get_api_key for each to detect presence. """ return ["openrouter", "anthropic", "openai", "google", "langsmith"] def mask(value: str | None) -> str: """Mask an API key for display: 'sk-or-v1-...c2e7' or '(not set)' if None.""" if not value: return "(not set)" if len(value) <= 8: return "***" return f"{value[:8]}...{value[-4:]}"