feat(cli): validate API key upfront via ping and unify telemetry identity resolution (#4701)

This commit is contained in:
Saket Aryan
2026-04-04 23:03:27 +05:30
committed by GitHub
parent 686d5e987d
commit 4642a1d6e3
6 changed files with 160 additions and 37 deletions
+39 -5
View File
@@ -2,6 +2,7 @@
from __future__ import annotations
import contextlib
import json as _json
import os
import stat as _stat_mod
@@ -12,7 +13,7 @@ import typer
from rich.console import Console
from mem0_cli import __version__
from mem0_cli.branding import BRAND_COLOR, print_error
from mem0_cli.branding import BRAND_COLOR, print_error, print_warning
console = Console()
err_console = Console(stderr=True)
@@ -55,6 +56,10 @@ event_app = typer.Typer(
# entity_app and event_app registered after Memory commands to control panel ordering
# ── Validated user identity (set by _get_backend_and_config) ──────────────
_validated_user_email: str | None = None
# ── Telemetry helper ─────────────────────────────────────────────────────
@@ -66,7 +71,7 @@ def _fire_telemetry(command_name: str, extra: dict | None = None) -> None:
props = {"command": command_name}
if extra:
props.update(extra)
capture_event(f"cli.{command_name}", props)
capture_event(f"cli.{command_name}", props, pre_resolved_email=_validated_user_email)
except Exception:
pass
@@ -96,9 +101,16 @@ def _get_backend_and_config(
api_key: str | None = None,
base_url: str | None = None,
):
"""Build and return the Platform backend plus the loaded config."""
"""Build and return the Platform backend plus the loaded config.
Validates the API key upfront via ``/v1/ping/`` and caches the
resolved user email for telemetry.
"""
global _validated_user_email
from mem0_cli.backend import get_backend
from mem0_cli.config import load_config
from mem0_cli.backend.platform import AuthError
from mem0_cli.config import load_config, save_config
config = load_config()
@@ -115,7 +127,29 @@ def _get_backend_and_config(
)
raise typer.Exit(1)
return get_backend(config), config
backend = get_backend(config)
# Validate the API key upfront with a fast timeout
try:
ping_data = backend.ping(timeout=5.0)
email = ping_data.get("user_email") if isinstance(ping_data, dict) else None
if email:
_validated_user_email = email
if config.platform.user_email != email:
config.platform.user_email = email
with contextlib.suppress(Exception):
save_config(config)
except AuthError:
print_error(
err_console,
"Invalid or expired API key.",
hint="Run 'mem0 init' or set MEM0_API_KEY environment variable.",
)
raise typer.Exit(1) from None
except Exception:
print_warning(err_console, "Could not validate API key (network issue). Proceeding anyway.")
return backend, config
def _get_backend(