Co-authored-by: Bastien <bastien.baret@gmail.com>
Co-authored-by: Clément Sirieix <clement.sirieix@mistral.ai>
Co-authored-by: Julien Legrand <72564015+JulienLGRD@users.noreply.github.com>
Co-authored-by: Kim-Adeline Miguel <51720070+kimadeline@users.noreply.github.com>
Co-authored-by: Mathias Gesbert <mathias.gesbert@mistral.ai>
Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai>
Co-authored-by: Quentin <quentin.torroba@mistral.ai>
Co-authored-by: Vincent G <10739306+VinceOPS@users.noreply.github.com>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
Clément Drouin 2026-04-14 10:33:15 +02:00 committed by GitHub
parent e9a9217cc8
commit e1a25caa52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
85 changed files with 2830 additions and 594 deletions

View file

@ -4,19 +4,20 @@ import asyncio
from collections.abc import Callable
import os
from typing import TYPE_CHECKING, Any, Literal
from urllib.parse import urljoin
import httpx
from vibe import __version__
from vibe.core.config import VibeConfig
from vibe.core.config import ProviderConfig, VibeConfig
from vibe.core.llm.format import ResolvedToolCall
from vibe.core.types import Backend
from vibe.core.utils import get_user_agent
from vibe.core.utils import get_server_url_from_api_base, get_user_agent
if TYPE_CHECKING:
from vibe.core.agent_loop import ToolDecision
DATALAKE_EVENTS_URL = "https://codestral.mistral.ai/v1/datalake/events"
_DEFAULT_TELEMETRY_BASE_URL = "https://codestral.mistral.ai"
_DATALAKE_EVENTS_PATH = "/v1/datalake/events"
class TelemetryClient:
@ -31,31 +32,35 @@ class TelemetryClient:
self._pending_tasks: set[asyncio.Task[Any]] = set()
self.last_correlation_id: str | None = None
def _get_telemetry_user_agent(self) -> str:
try:
config = self._config_getter()
active_model = config.get_active_model()
provider = config.get_provider_for_model(active_model)
return get_user_agent(provider.backend)
except ValueError:
return get_user_agent(None)
def _get_telemetry_url(self, api_base: str) -> str:
base = get_server_url_from_api_base(api_base) or _DEFAULT_TELEMETRY_BASE_URL
return urljoin(base.rstrip("/"), _DATALAKE_EVENTS_PATH)
def _get_mistral_api_key(self) -> str | None:
"""Get the current API key from the active provider.
"""Get the API key from the active provider if it's Mistral,
otherwise the first Mistral provider.
Only returns an API key if the provider is a Mistral provider
to avoid leaking third-party credentials to the telemetry endpoint.
"""
provider_and_api_key = self._get_mistral_provider_and_api_key()
if provider_and_api_key is None:
return None
_, api_key = provider_and_api_key
return api_key
def _get_mistral_provider_and_api_key(self) -> tuple[ProviderConfig, str] | None:
try:
config = self._config_getter()
model = config.get_active_model()
provider = config.get_provider_for_model(model)
if provider.backend != Backend.MISTRAL:
return None
env_var = provider.api_key_env_var
return os.getenv(env_var) if env_var else None
provider = self._config_getter().get_mistral_provider()
except ValueError:
return None
if provider is None:
return None
env_var = provider.api_key_env_var
api_key = os.getenv(env_var) if env_var else None
if api_key is None:
return None
return provider, api_key
def _is_enabled(self) -> bool:
"""Check if telemetry is enabled in the current config."""
@ -83,10 +88,14 @@ class TelemetryClient:
*,
correlation_id: str | None = None,
) -> None:
mistral_api_key = self._get_mistral_api_key()
if mistral_api_key is None or not self._is_enabled():
if not self._is_enabled():
return
user_agent = self._get_telemetry_user_agent()
provider_and_api_key = self._get_mistral_provider_and_api_key()
if provider_and_api_key is None:
return
provider, mistral_api_key = provider_and_api_key
telemetry_url = self._get_telemetry_url(provider.api_base)
user_agent = get_user_agent(provider.backend)
if (
self._session_id_getter is not None
and (session_id := self._session_id_getter()) is not None
@ -100,7 +109,7 @@ class TelemetryClient:
async def _send() -> None:
try:
await self.client.post(
DATALAKE_EVENTS_URL,
telemetry_url,
json=payload,
headers={
"Content-Type": "application/json",