Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion py/noxfile.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,7 +187,7 @@ def test_anthropic(session, version):
def test_google_genai(session, version):
_install_test_deps(session)
_install(session, "google-genai", version)
_run_tests(session, f"{WRAPPER_DIR}/test_google_genai.py")
_run_tests(session, f"{INTEGRATION_DIR}/google_genai/test_google_genai.py")
_run_core_tests(session)


Expand Down
18 changes: 8 additions & 10 deletions py/src/braintrust/auto.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,13 @@
import logging
from contextlib import contextmanager

from braintrust.integrations import ADKIntegration, AgnoIntegration, AnthropicIntegration, ClaudeAgentSDKIntegration
from braintrust.integrations import (
ADKIntegration,
AgnoIntegration,
AnthropicIntegration,
ClaudeAgentSDKIntegration,
GoogleGenAIIntegration,
)


__all__ = ["auto_instrument"]
Expand DownExpand Up@@ -113,7 +119,7 @@ def auto_instrument(
if pydantic_ai:
results["pydantic_ai"] = _instrument_pydantic_ai()
if google_genai:
results["google_genai"] = _instrument_google_genai()
results["google_genai"] = _instrument_integration(GoogleGenAIIntegration)
if agno:
results["agno"] = _instrument_integration(AgnoIntegration)
if claude_agent_sdk:
Expand DownExpand Up@@ -156,14 +162,6 @@ def _instrument_pydantic_ai() -> bool:
return False


def _instrument_google_genai() -> bool:
with _try_patch():
from braintrust.wrappers.google_genai import setup_genai

return setup_genai()
return False


def _instrument_dspy() -> bool:
with _try_patch():
from braintrust.wrappers.dspy import patch_dspy
Expand Down
9 changes: 8 additions & 1 deletion py/src/braintrust/integrations/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,13 @@
from .agno import AgnoIntegration
from .anthropic import AnthropicIntegration
from .claude_agent_sdk import ClaudeAgentSDKIntegration
from .google_genai import GoogleGenAIIntegration


__all__ = ["ADKIntegration", "AgnoIntegration", "AnthropicIntegration", "ClaudeAgentSDKIntegration"]
__all__ = [
"ADKIntegration",
"AgnoIntegration",
"AnthropicIntegration",
"ClaudeAgentSDKIntegration",
"GoogleGenAIIntegration",
]
39 changes: 39 additions & 0 deletions py/src/braintrust/integrations/google_genai/__init__.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
"""Braintrust integration for Google GenAI."""

import logging

from braintrust.logger import NOOP_SPAN, current_span, init_logger

from .integration import GoogleGenAIIntegration


logger = logging.getLogger(__name__)

__all__ = [
"GoogleGenAIIntegration",
"setup_genai",
]


def setup_genai(
api_key: str | None = None,
project_id: str | None = None,
project_name: str | None = None,
) -> bool:
"""Setup Braintrust integration with Google GenAI.

Will automatically patch Google GenAI models for automatic tracing.

Args:
api_key: Braintrust API key.
project_id: Braintrust project ID.
project_name: Braintrust project name.

Returns:
True if setup was successful, False if google-genai is not installed.
"""
span = current_span()
if span == NOOP_SPAN:
init_logger(project=project_name, api_key=api_key, project_id=project_id)

return GoogleGenAIIntegration.setup()
32 changes: 32 additions & 0 deletions py/src/braintrust/integrations/google_genai/integration.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
"""Google GenAI integration — orchestration class and setup entry-point."""

import logging

from braintrust.integrations.base import BaseIntegration

from .patchers import (
AsyncModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
)


logger = logging.getLogger(__name__)


class GoogleGenAIIntegration(BaseIntegration):
"""Braintrust instrumentation for the Google GenAI Python SDK."""

name = "google_genai"
import_names = ("google.genai",)
patchers = (
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
AsyncModelsEmbedContentPatcher,
)
76 changes: 76 additions & 0 deletions py/src/braintrust/integrations/google_genai/patchers.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
"""Google GenAI patchers — one patcher per coherent patch target."""

from braintrust.integrations.base import FunctionWrapperPatcher

from .tracing import (
_async_embed_content_wrapper,
_async_generate_content_stream_wrapper,
_async_generate_content_wrapper,
_embed_content_wrapper,
_generate_content_stream_wrapper,
_generate_content_wrapper,
)


# ---------------------------------------------------------------------------
# Sync Models patchers
# ---------------------------------------------------------------------------


class ModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models._generate_content`` for tracing."""

name = "google_genai.models.generate_content"
target_module = "google.genai.models"
target_path = "Models._generate_content"
wrapper = _generate_content_wrapper


class ModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``Models.generate_content_stream`` for tracing."""

name = "google_genai.models.generate_content_stream"
target_module = "google.genai.models"
target_path = "Models.generate_content_stream"
wrapper = _generate_content_stream_wrapper


class ModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models.embed_content`` for tracing."""

name = "google_genai.models.embed_content"
target_module = "google.genai.models"
target_path = "Models.embed_content"
wrapper = _embed_content_wrapper


# ---------------------------------------------------------------------------
# Async Models patchers
# ---------------------------------------------------------------------------


class AsyncModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content`` for tracing."""

name = "google_genai.async_models.generate_content"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content"
wrapper = _async_generate_content_wrapper


class AsyncModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content_stream`` for tracing."""

name = "google_genai.async_models.generate_content_stream"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content_stream"
wrapper = _async_generate_content_stream_wrapper


class AsyncModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.embed_content`` for tracing."""

name = "google_genai.async_models.embed_content"
target_module = "google.genai.models"
target_path = "AsyncModels.embed_content"
wrapper = _async_embed_content_wrapper
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,8 @@

import pytest
from braintrust import logger
from braintrust.integrations.google_genai import setup_genai
from braintrust.test_helpers import init_test_logger
from braintrust.wrappers.google_genai import setup_genai
from braintrust.wrappers.test_utils import verify_autoinstrument_script
from google.genai import types
from google.genai.client import Client
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion py/noxfile.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,7 +187,7 @@ def test_anthropic(session, version):
def test_google_genai(session, version):
_install_test_deps(session)
_install(session, "google-genai", version)
_run_tests(session, f"{WRAPPER_DIR}/test_google_genai.py")
_run_tests(session, f"{INTEGRATION_DIR}/google_genai/test_google_genai.py")
_run_core_tests(session)


Expand Down
18 changes: 8 additions & 10 deletions py/src/braintrust/auto.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,13 @@
import logging
from contextlib import contextmanager

from braintrust.integrations import ADKIntegration, AgnoIntegration, AnthropicIntegration, ClaudeAgentSDKIntegration
from braintrust.integrations import (
ADKIntegration,
AgnoIntegration,
AnthropicIntegration,
ClaudeAgentSDKIntegration,
GoogleGenAIIntegration,
)


__all__ = ["auto_instrument"]
Expand DownExpand Up@@ -113,7 +119,7 @@ def auto_instrument(
if pydantic_ai:
results["pydantic_ai"] = _instrument_pydantic_ai()
if google_genai:
results["google_genai"] = _instrument_google_genai()
results["google_genai"] = _instrument_integration(GoogleGenAIIntegration)
if agno:
results["agno"] = _instrument_integration(AgnoIntegration)
if claude_agent_sdk:
Expand DownExpand Up@@ -156,14 +162,6 @@ def _instrument_pydantic_ai() -> bool:
return False


def _instrument_google_genai() -> bool:
with _try_patch():
from braintrust.wrappers.google_genai import setup_genai

return setup_genai()
return False


def _instrument_dspy() -> bool:
with _try_patch():
from braintrust.wrappers.dspy import patch_dspy
Expand Down
9 changes: 8 additions & 1 deletion py/src/braintrust/integrations/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,13 @@
from .agno import AgnoIntegration
from .anthropic import AnthropicIntegration
from .claude_agent_sdk import ClaudeAgentSDKIntegration
from .google_genai import GoogleGenAIIntegration


__all__ = ["ADKIntegration", "AgnoIntegration", "AnthropicIntegration", "ClaudeAgentSDKIntegration"]
__all__ = [
"ADKIntegration",
"AgnoIntegration",
"AnthropicIntegration",
"ClaudeAgentSDKIntegration",
"GoogleGenAIIntegration",
]
39 changes: 39 additions & 0 deletions py/src/braintrust/integrations/google_genai/__init__.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
"""Braintrust integration for Google GenAI."""

import logging

from braintrust.logger import NOOP_SPAN, current_span, init_logger

from .integration import GoogleGenAIIntegration


logger = logging.getLogger(__name__)

__all__ = [
"GoogleGenAIIntegration",
"setup_genai",
]


def setup_genai(
api_key: str | None = None,
project_id: str | None = None,
project_name: str | None = None,
) -> bool:
"""Setup Braintrust integration with Google GenAI.

Will automatically patch Google GenAI models for automatic tracing.

Args:
api_key: Braintrust API key.
project_id: Braintrust project ID.
project_name: Braintrust project name.

Returns:
True if setup was successful, False if google-genai is not installed.
"""
span = current_span()
if span == NOOP_SPAN:
init_logger(project=project_name, api_key=api_key, project_id=project_id)

return GoogleGenAIIntegration.setup()
32 changes: 32 additions & 0 deletions py/src/braintrust/integrations/google_genai/integration.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
"""Google GenAI integration — orchestration class and setup entry-point."""

import logging

from braintrust.integrations.base import BaseIntegration

from .patchers import (
AsyncModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
)


logger = logging.getLogger(__name__)


class GoogleGenAIIntegration(BaseIntegration):
"""Braintrust instrumentation for the Google GenAI Python SDK."""

name = "google_genai"
import_names = ("google.genai",)
patchers = (
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
AsyncModelsEmbedContentPatcher,
)
76 changes: 76 additions & 0 deletions py/src/braintrust/integrations/google_genai/patchers.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
"""Google GenAI patchers — one patcher per coherent patch target."""

from braintrust.integrations.base import FunctionWrapperPatcher

from .tracing import (
_async_embed_content_wrapper,
_async_generate_content_stream_wrapper,
_async_generate_content_wrapper,
_embed_content_wrapper,
_generate_content_stream_wrapper,
_generate_content_wrapper,
)


# ---------------------------------------------------------------------------
# Sync Models patchers
# ---------------------------------------------------------------------------


class ModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models._generate_content`` for tracing."""

name = "google_genai.models.generate_content"
target_module = "google.genai.models"
target_path = "Models._generate_content"
wrapper = _generate_content_wrapper


class ModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``Models.generate_content_stream`` for tracing."""

name = "google_genai.models.generate_content_stream"
target_module = "google.genai.models"
target_path = "Models.generate_content_stream"
wrapper = _generate_content_stream_wrapper


class ModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models.embed_content`` for tracing."""

name = "google_genai.models.embed_content"
target_module = "google.genai.models"
target_path = "Models.embed_content"
wrapper = _embed_content_wrapper


# ---------------------------------------------------------------------------
# Async Models patchers
# ---------------------------------------------------------------------------


class AsyncModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content`` for tracing."""

name = "google_genai.async_models.generate_content"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content"
wrapper = _async_generate_content_wrapper


class AsyncModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content_stream`` for tracing."""

name = "google_genai.async_models.generate_content_stream"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content_stream"
wrapper = _async_generate_content_stream_wrapper


class AsyncModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.embed_content`` for tracing."""

name = "google_genai.async_models.embed_content"
target_module = "google.genai.models"
target_path = "AsyncModels.embed_content"
wrapper = _async_embed_content_wrapper
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,8 @@

import pytest
from braintrust import logger
from braintrust.integrations.google_genai import setup_genai
from braintrust.test_helpers import init_test_logger
from braintrust.wrappers.google_genai import setup_genai
from braintrust.wrappers.test_utils import verify_autoinstrument_script
from google.genai import types
from google.genai.client import Client
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion py/noxfile.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,7 +187,7 @@ def test_anthropic(session, version):
def test_google_genai(session, version):
_install_test_deps(session)
_install(session, "google-genai", version)
_run_tests(session, f"{WRAPPER_DIR}/test_google_genai.py")
_run_tests(session, f"{INTEGRATION_DIR}/google_genai/test_google_genai.py")
_run_core_tests(session)


Expand Down
18 changes: 8 additions & 10 deletions py/src/braintrust/auto.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,13 @@
import logging
from contextlib import contextmanager

from braintrust.integrations import ADKIntegration, AgnoIntegration, AnthropicIntegration, ClaudeAgentSDKIntegration
from braintrust.integrations import (
ADKIntegration,
AgnoIntegration,
AnthropicIntegration,
ClaudeAgentSDKIntegration,
GoogleGenAIIntegration,
)


__all__ = ["auto_instrument"]
Expand DownExpand Up@@ -113,7 +119,7 @@ def auto_instrument(
if pydantic_ai:
results["pydantic_ai"] = _instrument_pydantic_ai()
if google_genai:
results["google_genai"] = _instrument_google_genai()
results["google_genai"] = _instrument_integration(GoogleGenAIIntegration)
if agno:
results["agno"] = _instrument_integration(AgnoIntegration)
if claude_agent_sdk:
Expand DownExpand Up@@ -156,14 +162,6 @@ def _instrument_pydantic_ai() -> bool:
return False


def _instrument_google_genai() -> bool:
with _try_patch():
from braintrust.wrappers.google_genai import setup_genai

return setup_genai()
return False


def _instrument_dspy() -> bool:
with _try_patch():
from braintrust.wrappers.dspy import patch_dspy
Expand Down
9 changes: 8 additions & 1 deletion py/src/braintrust/integrations/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,13 @@
from .agno import AgnoIntegration
from .anthropic import AnthropicIntegration
from .claude_agent_sdk import ClaudeAgentSDKIntegration
from .google_genai import GoogleGenAIIntegration


__all__ = ["ADKIntegration", "AgnoIntegration", "AnthropicIntegration", "ClaudeAgentSDKIntegration"]
__all__ = [
"ADKIntegration",
"AgnoIntegration",
"AnthropicIntegration",
"ClaudeAgentSDKIntegration",
"GoogleGenAIIntegration",
]
39 changes: 39 additions & 0 deletions py/src/braintrust/integrations/google_genai/__init__.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
"""Braintrust integration for Google GenAI."""

import logging

from braintrust.logger import NOOP_SPAN, current_span, init_logger

from .integration import GoogleGenAIIntegration


logger = logging.getLogger(__name__)

__all__ = [
"GoogleGenAIIntegration",
"setup_genai",
]


def setup_genai(
api_key: str | None = None,
project_id: str | None = None,
project_name: str | None = None,
) -> bool:
"""Setup Braintrust integration with Google GenAI.

Will automatically patch Google GenAI models for automatic tracing.

Args:
api_key: Braintrust API key.
project_id: Braintrust project ID.
project_name: Braintrust project name.

Returns:
True if setup was successful, False if google-genai is not installed.
"""
span = current_span()
if span == NOOP_SPAN:
init_logger(project=project_name, api_key=api_key, project_id=project_id)

return GoogleGenAIIntegration.setup()
32 changes: 32 additions & 0 deletions py/src/braintrust/integrations/google_genai/integration.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
"""Google GenAI integration — orchestration class and setup entry-point."""

import logging

from braintrust.integrations.base import BaseIntegration

from .patchers import (
AsyncModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
)


logger = logging.getLogger(__name__)


class GoogleGenAIIntegration(BaseIntegration):
"""Braintrust instrumentation for the Google GenAI Python SDK."""

name = "google_genai"
import_names = ("google.genai",)
patchers = (
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
AsyncModelsEmbedContentPatcher,
)
76 changes: 76 additions & 0 deletions py/src/braintrust/integrations/google_genai/patchers.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
"""Google GenAI patchers — one patcher per coherent patch target."""

from braintrust.integrations.base import FunctionWrapperPatcher

from .tracing import (
_async_embed_content_wrapper,
_async_generate_content_stream_wrapper,
_async_generate_content_wrapper,
_embed_content_wrapper,
_generate_content_stream_wrapper,
_generate_content_wrapper,
)


# ---------------------------------------------------------------------------
# Sync Models patchers
# ---------------------------------------------------------------------------


class ModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models._generate_content`` for tracing."""

name = "google_genai.models.generate_content"
target_module = "google.genai.models"
target_path = "Models._generate_content"
wrapper = _generate_content_wrapper


class ModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``Models.generate_content_stream`` for tracing."""

name = "google_genai.models.generate_content_stream"
target_module = "google.genai.models"
target_path = "Models.generate_content_stream"
wrapper = _generate_content_stream_wrapper


class ModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models.embed_content`` for tracing."""

name = "google_genai.models.embed_content"
target_module = "google.genai.models"
target_path = "Models.embed_content"
wrapper = _embed_content_wrapper


# ---------------------------------------------------------------------------
# Async Models patchers
# ---------------------------------------------------------------------------


class AsyncModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content`` for tracing."""

name = "google_genai.async_models.generate_content"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content"
wrapper = _async_generate_content_wrapper


class AsyncModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content_stream`` for tracing."""

name = "google_genai.async_models.generate_content_stream"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content_stream"
wrapper = _async_generate_content_stream_wrapper


class AsyncModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.embed_content`` for tracing."""

name = "google_genai.async_models.embed_content"
target_module = "google.genai.models"
target_path = "AsyncModels.embed_content"
wrapper = _async_embed_content_wrapper
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,8 @@

import pytest
from braintrust import logger
from braintrust.integrations.google_genai import setup_genai
from braintrust.test_helpers import init_test_logger
from braintrust.wrappers.google_genai import setup_genai
from braintrust.wrappers.test_utils import verify_autoinstrument_script
from google.genai import types
from google.genai.client import Client
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion py/noxfile.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,7 +187,7 @@ def test_anthropic(session, version):
def test_google_genai(session, version):
_install_test_deps(session)
_install(session, "google-genai", version)
_run_tests(session, f"{WRAPPER_DIR}/test_google_genai.py")
_run_tests(session, f"{INTEGRATION_DIR}/google_genai/test_google_genai.py")
_run_core_tests(session)


Expand Down
18 changes: 8 additions & 10 deletions py/src/braintrust/auto.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,13 @@
import logging
from contextlib import contextmanager

from braintrust.integrations import ADKIntegration, AgnoIntegration, AnthropicIntegration, ClaudeAgentSDKIntegration
from braintrust.integrations import (
ADKIntegration,
AgnoIntegration,
AnthropicIntegration,
ClaudeAgentSDKIntegration,
GoogleGenAIIntegration,
)


__all__ = ["auto_instrument"]
Expand DownExpand Up@@ -113,7 +119,7 @@ def auto_instrument(
if pydantic_ai:
results["pydantic_ai"] = _instrument_pydantic_ai()
if google_genai:
results["google_genai"] = _instrument_google_genai()
results["google_genai"] = _instrument_integration(GoogleGenAIIntegration)
if agno:
results["agno"] = _instrument_integration(AgnoIntegration)
if claude_agent_sdk:
Expand DownExpand Up@@ -156,14 +162,6 @@ def _instrument_pydantic_ai() -> bool:
return False


def _instrument_google_genai() -> bool:
with _try_patch():
from braintrust.wrappers.google_genai import setup_genai

return setup_genai()
return False


def _instrument_dspy() -> bool:
with _try_patch():
from braintrust.wrappers.dspy import patch_dspy
Expand Down
9 changes: 8 additions & 1 deletion py/src/braintrust/integrations/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,13 @@
from .agno import AgnoIntegration
from .anthropic import AnthropicIntegration
from .claude_agent_sdk import ClaudeAgentSDKIntegration
from .google_genai import GoogleGenAIIntegration


__all__ = ["ADKIntegration", "AgnoIntegration", "AnthropicIntegration", "ClaudeAgentSDKIntegration"]
__all__ = [
"ADKIntegration",
"AgnoIntegration",
"AnthropicIntegration",
"ClaudeAgentSDKIntegration",
"GoogleGenAIIntegration",
]
39 changes: 39 additions & 0 deletions py/src/braintrust/integrations/google_genai/__init__.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
"""Braintrust integration for Google GenAI."""

import logging

from braintrust.logger import NOOP_SPAN, current_span, init_logger

from .integration import GoogleGenAIIntegration


logger = logging.getLogger(__name__)

__all__ = [
"GoogleGenAIIntegration",
"setup_genai",
]


def setup_genai(
api_key: str | None = None,
project_id: str | None = None,
project_name: str | None = None,
) -> bool:
"""Setup Braintrust integration with Google GenAI.

Will automatically patch Google GenAI models for automatic tracing.

Args:
api_key: Braintrust API key.
project_id: Braintrust project ID.
project_name: Braintrust project name.

Returns:
True if setup was successful, False if google-genai is not installed.
"""
span = current_span()
if span == NOOP_SPAN:
init_logger(project=project_name, api_key=api_key, project_id=project_id)

return GoogleGenAIIntegration.setup()
32 changes: 32 additions & 0 deletions py/src/braintrust/integrations/google_genai/integration.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
"""Google GenAI integration — orchestration class and setup entry-point."""

import logging

from braintrust.integrations.base import BaseIntegration

from .patchers import (
AsyncModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
)


logger = logging.getLogger(__name__)


class GoogleGenAIIntegration(BaseIntegration):
"""Braintrust instrumentation for the Google GenAI Python SDK."""

name = "google_genai"
import_names = ("google.genai",)
patchers = (
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
AsyncModelsEmbedContentPatcher,
)
76 changes: 76 additions & 0 deletions py/src/braintrust/integrations/google_genai/patchers.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
"""Google GenAI patchers — one patcher per coherent patch target."""

from braintrust.integrations.base import FunctionWrapperPatcher

from .tracing import (
_async_embed_content_wrapper,
_async_generate_content_stream_wrapper,
_async_generate_content_wrapper,
_embed_content_wrapper,
_generate_content_stream_wrapper,
_generate_content_wrapper,
)


# ---------------------------------------------------------------------------
# Sync Models patchers
# ---------------------------------------------------------------------------


class ModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models._generate_content`` for tracing."""

name = "google_genai.models.generate_content"
target_module = "google.genai.models"
target_path = "Models._generate_content"
wrapper = _generate_content_wrapper


class ModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``Models.generate_content_stream`` for tracing."""

name = "google_genai.models.generate_content_stream"
target_module = "google.genai.models"
target_path = "Models.generate_content_stream"
wrapper = _generate_content_stream_wrapper


class ModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models.embed_content`` for tracing."""

name = "google_genai.models.embed_content"
target_module = "google.genai.models"
target_path = "Models.embed_content"
wrapper = _embed_content_wrapper


# ---------------------------------------------------------------------------
# Async Models patchers
# ---------------------------------------------------------------------------


class AsyncModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content`` for tracing."""

name = "google_genai.async_models.generate_content"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content"
wrapper = _async_generate_content_wrapper


class AsyncModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content_stream`` for tracing."""

name = "google_genai.async_models.generate_content_stream"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content_stream"
wrapper = _async_generate_content_stream_wrapper


class AsyncModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.embed_content`` for tracing."""

name = "google_genai.async_models.embed_content"
target_module = "google.genai.models"
target_path = "AsyncModels.embed_content"
wrapper = _async_embed_content_wrapper
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,8 @@

import pytest
from braintrust import logger
from braintrust.integrations.google_genai import setup_genai
from braintrust.test_helpers import init_test_logger
from braintrust.wrappers.google_genai import setup_genai
from braintrust.wrappers.test_utils import verify_autoinstrument_script
from google.genai import types
from google.genai.client import Client
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion py/noxfile.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,7 +187,7 @@ def test_anthropic(session, version):
def test_google_genai(session, version):
_install_test_deps(session)
_install(session, "google-genai", version)
_run_tests(session, f"{WRAPPER_DIR}/test_google_genai.py")
_run_tests(session, f"{INTEGRATION_DIR}/google_genai/test_google_genai.py")
_run_core_tests(session)


Expand Down
18 changes: 8 additions & 10 deletions py/src/braintrust/auto.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,13 @@
import logging
from contextlib import contextmanager

from braintrust.integrations import ADKIntegration, AgnoIntegration, AnthropicIntegration, ClaudeAgentSDKIntegration
from braintrust.integrations import (
ADKIntegration,
AgnoIntegration,
AnthropicIntegration,
ClaudeAgentSDKIntegration,
GoogleGenAIIntegration,
)


__all__ = ["auto_instrument"]
Expand DownExpand Up@@ -113,7 +119,7 @@ def auto_instrument(
if pydantic_ai:
results["pydantic_ai"] = _instrument_pydantic_ai()
if google_genai:
results["google_genai"] = _instrument_google_genai()
results["google_genai"] = _instrument_integration(GoogleGenAIIntegration)
if agno:
results["agno"] = _instrument_integration(AgnoIntegration)
if claude_agent_sdk:
Expand DownExpand Up@@ -156,14 +162,6 @@ def _instrument_pydantic_ai() -> bool:
return False


def _instrument_google_genai() -> bool:
with _try_patch():
from braintrust.wrappers.google_genai import setup_genai

return setup_genai()
return False


def _instrument_dspy() -> bool:
with _try_patch():
from braintrust.wrappers.dspy import patch_dspy
Expand Down
9 changes: 8 additions & 1 deletion py/src/braintrust/integrations/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,13 @@
from .agno import AgnoIntegration
from .anthropic import AnthropicIntegration
from .claude_agent_sdk import ClaudeAgentSDKIntegration
from .google_genai import GoogleGenAIIntegration


__all__ = ["ADKIntegration", "AgnoIntegration", "AnthropicIntegration", "ClaudeAgentSDKIntegration"]
__all__ = [
"ADKIntegration",
"AgnoIntegration",
"AnthropicIntegration",
"ClaudeAgentSDKIntegration",
"GoogleGenAIIntegration",
]
39 changes: 39 additions & 0 deletions py/src/braintrust/integrations/google_genai/__init__.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
"""Braintrust integration for Google GenAI."""

import logging

from braintrust.logger import NOOP_SPAN, current_span, init_logger

from .integration import GoogleGenAIIntegration


logger = logging.getLogger(__name__)

__all__ = [
"GoogleGenAIIntegration",
"setup_genai",
]


def setup_genai(
api_key: str | None = None,
project_id: str | None = None,
project_name: str | None = None,
) -> bool:
"""Setup Braintrust integration with Google GenAI.

Will automatically patch Google GenAI models for automatic tracing.

Args:
api_key: Braintrust API key.
project_id: Braintrust project ID.
project_name: Braintrust project name.

Returns:
True if setup was successful, False if google-genai is not installed.
"""
span = current_span()
if span == NOOP_SPAN:
init_logger(project=project_name, api_key=api_key, project_id=project_id)

return GoogleGenAIIntegration.setup()
32 changes: 32 additions & 0 deletions py/src/braintrust/integrations/google_genai/integration.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
"""Google GenAI integration — orchestration class and setup entry-point."""

import logging

from braintrust.integrations.base import BaseIntegration

from .patchers import (
AsyncModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
)


logger = logging.getLogger(__name__)


class GoogleGenAIIntegration(BaseIntegration):
"""Braintrust instrumentation for the Google GenAI Python SDK."""

name = "google_genai"
import_names = ("google.genai",)
patchers = (
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
AsyncModelsEmbedContentPatcher,
)
76 changes: 76 additions & 0 deletions py/src/braintrust/integrations/google_genai/patchers.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
"""Google GenAI patchers — one patcher per coherent patch target."""

from braintrust.integrations.base import FunctionWrapperPatcher

from .tracing import (
_async_embed_content_wrapper,
_async_generate_content_stream_wrapper,
_async_generate_content_wrapper,
_embed_content_wrapper,
_generate_content_stream_wrapper,
_generate_content_wrapper,
)


# ---------------------------------------------------------------------------
# Sync Models patchers
# ---------------------------------------------------------------------------


class ModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models._generate_content`` for tracing."""

name = "google_genai.models.generate_content"
target_module = "google.genai.models"
target_path = "Models._generate_content"
wrapper = _generate_content_wrapper


class ModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``Models.generate_content_stream`` for tracing."""

name = "google_genai.models.generate_content_stream"
target_module = "google.genai.models"
target_path = "Models.generate_content_stream"
wrapper = _generate_content_stream_wrapper


class ModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models.embed_content`` for tracing."""

name = "google_genai.models.embed_content"
target_module = "google.genai.models"
target_path = "Models.embed_content"
wrapper = _embed_content_wrapper


# ---------------------------------------------------------------------------
# Async Models patchers
# ---------------------------------------------------------------------------


class AsyncModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content`` for tracing."""

name = "google_genai.async_models.generate_content"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content"
wrapper = _async_generate_content_wrapper


class AsyncModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content_stream`` for tracing."""

name = "google_genai.async_models.generate_content_stream"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content_stream"
wrapper = _async_generate_content_stream_wrapper


class AsyncModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.embed_content`` for tracing."""

name = "google_genai.async_models.embed_content"
target_module = "google.genai.models"
target_path = "AsyncModels.embed_content"
wrapper = _async_embed_content_wrapper
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,8 @@

import pytest
from braintrust import logger
from braintrust.integrations.google_genai import setup_genai
from braintrust.test_helpers import init_test_logger
from braintrust.wrappers.google_genai import setup_genai
from braintrust.wrappers.test_utils import verify_autoinstrument_script
from google.genai import types
from google.genai.client import Client
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion py/noxfile.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,7 +187,7 @@ def test_anthropic(session, version):
def test_google_genai(session, version):
_install_test_deps(session)
_install(session, "google-genai", version)
_run_tests(session, f"{WRAPPER_DIR}/test_google_genai.py")
_run_tests(session, f"{INTEGRATION_DIR}/google_genai/test_google_genai.py")
_run_core_tests(session)


Expand Down
18 changes: 8 additions & 10 deletions py/src/braintrust/auto.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,13 @@
import logging
from contextlib import contextmanager

from braintrust.integrations import ADKIntegration, AgnoIntegration, AnthropicIntegration, ClaudeAgentSDKIntegration
from braintrust.integrations import (
ADKIntegration,
AgnoIntegration,
AnthropicIntegration,
ClaudeAgentSDKIntegration,
GoogleGenAIIntegration,
)


__all__ = ["auto_instrument"]
Expand DownExpand Up@@ -113,7 +119,7 @@ def auto_instrument(
if pydantic_ai:
results["pydantic_ai"] = _instrument_pydantic_ai()
if google_genai:
results["google_genai"] = _instrument_google_genai()
results["google_genai"] = _instrument_integration(GoogleGenAIIntegration)
if agno:
results["agno"] = _instrument_integration(AgnoIntegration)
if claude_agent_sdk:
Expand DownExpand Up@@ -156,14 +162,6 @@ def _instrument_pydantic_ai() -> bool:
return False


def _instrument_google_genai() -> bool:
with _try_patch():
from braintrust.wrappers.google_genai import setup_genai

return setup_genai()
return False


def _instrument_dspy() -> bool:
with _try_patch():
from braintrust.wrappers.dspy import patch_dspy
Expand Down
9 changes: 8 additions & 1 deletion py/src/braintrust/integrations/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,13 @@
from .agno import AgnoIntegration
from .anthropic import AnthropicIntegration
from .claude_agent_sdk import ClaudeAgentSDKIntegration
from .google_genai import GoogleGenAIIntegration


__all__ = ["ADKIntegration", "AgnoIntegration", "AnthropicIntegration", "ClaudeAgentSDKIntegration"]
__all__ = [
"ADKIntegration",
"AgnoIntegration",
"AnthropicIntegration",
"ClaudeAgentSDKIntegration",
"GoogleGenAIIntegration",
]
39 changes: 39 additions & 0 deletions py/src/braintrust/integrations/google_genai/__init__.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
"""Braintrust integration for Google GenAI."""

import logging

from braintrust.logger import NOOP_SPAN, current_span, init_logger

from .integration import GoogleGenAIIntegration


logger = logging.getLogger(__name__)

__all__ = [
"GoogleGenAIIntegration",
"setup_genai",
]


def setup_genai(
api_key: str | None = None,
project_id: str | None = None,
project_name: str | None = None,
) -> bool:
"""Setup Braintrust integration with Google GenAI.

Will automatically patch Google GenAI models for automatic tracing.

Args:
api_key: Braintrust API key.
project_id: Braintrust project ID.
project_name: Braintrust project name.

Returns:
True if setup was successful, False if google-genai is not installed.
"""
span = current_span()
if span == NOOP_SPAN:
init_logger(project=project_name, api_key=api_key, project_id=project_id)

return GoogleGenAIIntegration.setup()
32 changes: 32 additions & 0 deletions py/src/braintrust/integrations/google_genai/integration.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
"""Google GenAI integration — orchestration class and setup entry-point."""

import logging

from braintrust.integrations.base import BaseIntegration

from .patchers import (
AsyncModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
)


logger = logging.getLogger(__name__)


class GoogleGenAIIntegration(BaseIntegration):
"""Braintrust instrumentation for the Google GenAI Python SDK."""

name = "google_genai"
import_names = ("google.genai",)
patchers = (
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
AsyncModelsEmbedContentPatcher,
)
76 changes: 76 additions & 0 deletions py/src/braintrust/integrations/google_genai/patchers.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
"""Google GenAI patchers — one patcher per coherent patch target."""

from braintrust.integrations.base import FunctionWrapperPatcher

from .tracing import (
_async_embed_content_wrapper,
_async_generate_content_stream_wrapper,
_async_generate_content_wrapper,
_embed_content_wrapper,
_generate_content_stream_wrapper,
_generate_content_wrapper,
)


# ---------------------------------------------------------------------------
# Sync Models patchers
# ---------------------------------------------------------------------------


class ModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models._generate_content`` for tracing."""

name = "google_genai.models.generate_content"
target_module = "google.genai.models"
target_path = "Models._generate_content"
wrapper = _generate_content_wrapper


class ModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``Models.generate_content_stream`` for tracing."""

name = "google_genai.models.generate_content_stream"
target_module = "google.genai.models"
target_path = "Models.generate_content_stream"
wrapper = _generate_content_stream_wrapper


class ModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models.embed_content`` for tracing."""

name = "google_genai.models.embed_content"
target_module = "google.genai.models"
target_path = "Models.embed_content"
wrapper = _embed_content_wrapper


# ---------------------------------------------------------------------------
# Async Models patchers
# ---------------------------------------------------------------------------


class AsyncModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content`` for tracing."""

name = "google_genai.async_models.generate_content"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content"
wrapper = _async_generate_content_wrapper


class AsyncModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content_stream`` for tracing."""

name = "google_genai.async_models.generate_content_stream"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content_stream"
wrapper = _async_generate_content_stream_wrapper


class AsyncModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.embed_content`` for tracing."""

name = "google_genai.async_models.embed_content"
target_module = "google.genai.models"
target_path = "AsyncModels.embed_content"
wrapper = _async_embed_content_wrapper
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,8 @@

import pytest
from braintrust import logger
from braintrust.integrations.google_genai import setup_genai
from braintrust.test_helpers import init_test_logger
from braintrust.wrappers.google_genai import setup_genai
from braintrust.wrappers.test_utils import verify_autoinstrument_script
from google.genai import types
from google.genai.client import Client
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion py/noxfile.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,7 +187,7 @@ def test_anthropic(session, version):
def test_google_genai(session, version):
_install_test_deps(session)
_install(session, "google-genai", version)
_run_tests(session, f"{WRAPPER_DIR}/test_google_genai.py")
_run_tests(session, f"{INTEGRATION_DIR}/google_genai/test_google_genai.py")
_run_core_tests(session)


Expand Down
18 changes: 8 additions & 10 deletions py/src/braintrust/auto.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,13 @@
import logging
from contextlib import contextmanager

from braintrust.integrations import ADKIntegration, AgnoIntegration, AnthropicIntegration, ClaudeAgentSDKIntegration
from braintrust.integrations import (
ADKIntegration,
AgnoIntegration,
AnthropicIntegration,
ClaudeAgentSDKIntegration,
GoogleGenAIIntegration,
)


__all__ = ["auto_instrument"]
Expand DownExpand Up@@ -113,7 +119,7 @@ def auto_instrument(
if pydantic_ai:
results["pydantic_ai"] = _instrument_pydantic_ai()
if google_genai:
results["google_genai"] = _instrument_google_genai()
results["google_genai"] = _instrument_integration(GoogleGenAIIntegration)
if agno:
results["agno"] = _instrument_integration(AgnoIntegration)
if claude_agent_sdk:
Expand DownExpand Up@@ -156,14 +162,6 @@ def _instrument_pydantic_ai() -> bool:
return False


def _instrument_google_genai() -> bool:
with _try_patch():
from braintrust.wrappers.google_genai import setup_genai

return setup_genai()
return False


def _instrument_dspy() -> bool:
with _try_patch():
from braintrust.wrappers.dspy import patch_dspy
Expand Down
9 changes: 8 additions & 1 deletion py/src/braintrust/integrations/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,13 @@
from .agno import AgnoIntegration
from .anthropic import AnthropicIntegration
from .claude_agent_sdk import ClaudeAgentSDKIntegration
from .google_genai import GoogleGenAIIntegration


__all__ = ["ADKIntegration", "AgnoIntegration", "AnthropicIntegration", "ClaudeAgentSDKIntegration"]
__all__ = [
"ADKIntegration",
"AgnoIntegration",
"AnthropicIntegration",
"ClaudeAgentSDKIntegration",
"GoogleGenAIIntegration",
]
39 changes: 39 additions & 0 deletions py/src/braintrust/integrations/google_genai/__init__.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
"""Braintrust integration for Google GenAI."""

import logging

from braintrust.logger import NOOP_SPAN, current_span, init_logger

from .integration import GoogleGenAIIntegration


logger = logging.getLogger(__name__)

__all__ = [
"GoogleGenAIIntegration",
"setup_genai",
]


def setup_genai(
api_key: str | None = None,
project_id: str | None = None,
project_name: str | None = None,
) -> bool:
"""Setup Braintrust integration with Google GenAI.

Will automatically patch Google GenAI models for automatic tracing.

Args:
api_key: Braintrust API key.
project_id: Braintrust project ID.
project_name: Braintrust project name.

Returns:
True if setup was successful, False if google-genai is not installed.
"""
span = current_span()
if span == NOOP_SPAN:
init_logger(project=project_name, api_key=api_key, project_id=project_id)

return GoogleGenAIIntegration.setup()
32 changes: 32 additions & 0 deletions py/src/braintrust/integrations/google_genai/integration.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
"""Google GenAI integration — orchestration class and setup entry-point."""

import logging

from braintrust.integrations.base import BaseIntegration

from .patchers import (
AsyncModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
)


logger = logging.getLogger(__name__)


class GoogleGenAIIntegration(BaseIntegration):
"""Braintrust instrumentation for the Google GenAI Python SDK."""

name = "google_genai"
import_names = ("google.genai",)
patchers = (
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
AsyncModelsEmbedContentPatcher,
)
76 changes: 76 additions & 0 deletions py/src/braintrust/integrations/google_genai/patchers.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
"""Google GenAI patchers — one patcher per coherent patch target."""

from braintrust.integrations.base import FunctionWrapperPatcher

from .tracing import (
_async_embed_content_wrapper,
_async_generate_content_stream_wrapper,
_async_generate_content_wrapper,
_embed_content_wrapper,
_generate_content_stream_wrapper,
_generate_content_wrapper,
)


# ---------------------------------------------------------------------------
# Sync Models patchers
# ---------------------------------------------------------------------------


class ModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models._generate_content`` for tracing."""

name = "google_genai.models.generate_content"
target_module = "google.genai.models"
target_path = "Models._generate_content"
wrapper = _generate_content_wrapper


class ModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``Models.generate_content_stream`` for tracing."""

name = "google_genai.models.generate_content_stream"
target_module = "google.genai.models"
target_path = "Models.generate_content_stream"
wrapper = _generate_content_stream_wrapper


class ModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models.embed_content`` for tracing."""

name = "google_genai.models.embed_content"
target_module = "google.genai.models"
target_path = "Models.embed_content"
wrapper = _embed_content_wrapper


# ---------------------------------------------------------------------------
# Async Models patchers
# ---------------------------------------------------------------------------


class AsyncModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content`` for tracing."""

name = "google_genai.async_models.generate_content"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content"
wrapper = _async_generate_content_wrapper


class AsyncModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content_stream`` for tracing."""

name = "google_genai.async_models.generate_content_stream"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content_stream"
wrapper = _async_generate_content_stream_wrapper


class AsyncModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.embed_content`` for tracing."""

name = "google_genai.async_models.embed_content"
target_module = "google.genai.models"
target_path = "AsyncModels.embed_content"
wrapper = _async_embed_content_wrapper
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,8 @@

import pytest
from braintrust import logger
from braintrust.integrations.google_genai import setup_genai
from braintrust.test_helpers import init_test_logger
from braintrust.wrappers.google_genai import setup_genai
from braintrust.wrappers.test_utils import verify_autoinstrument_script
from google.genai import types
from google.genai.client import Client
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion py/noxfile.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,7 +187,7 @@ def test_anthropic(session, version):
def test_google_genai(session, version):
_install_test_deps(session)
_install(session, "google-genai", version)
_run_tests(session, f"{WRAPPER_DIR}/test_google_genai.py")
_run_tests(session, f"{INTEGRATION_DIR}/google_genai/test_google_genai.py")
_run_core_tests(session)


Expand Down
18 changes: 8 additions & 10 deletions py/src/braintrust/auto.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,13 @@
import logging
from contextlib import contextmanager

from braintrust.integrations import ADKIntegration, AgnoIntegration, AnthropicIntegration, ClaudeAgentSDKIntegration
from braintrust.integrations import (
ADKIntegration,
AgnoIntegration,
AnthropicIntegration,
ClaudeAgentSDKIntegration,
GoogleGenAIIntegration,
)


__all__ = ["auto_instrument"]
Expand DownExpand Up@@ -113,7 +119,7 @@ def auto_instrument(
if pydantic_ai:
results["pydantic_ai"] = _instrument_pydantic_ai()
if google_genai:
results["google_genai"] = _instrument_google_genai()
results["google_genai"] = _instrument_integration(GoogleGenAIIntegration)
if agno:
results["agno"] = _instrument_integration(AgnoIntegration)
if claude_agent_sdk:
Expand DownExpand Up@@ -156,14 +162,6 @@ def _instrument_pydantic_ai() -> bool:
return False


def _instrument_google_genai() -> bool:
with _try_patch():
from braintrust.wrappers.google_genai import setup_genai

return setup_genai()
return False


def _instrument_dspy() -> bool:
with _try_patch():
from braintrust.wrappers.dspy import patch_dspy
Expand Down
9 changes: 8 additions & 1 deletion py/src/braintrust/integrations/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,13 @@
from .agno import AgnoIntegration
from .anthropic import AnthropicIntegration
from .claude_agent_sdk import ClaudeAgentSDKIntegration
from .google_genai import GoogleGenAIIntegration


__all__ = ["ADKIntegration", "AgnoIntegration", "AnthropicIntegration", "ClaudeAgentSDKIntegration"]
__all__ = [
"ADKIntegration",
"AgnoIntegration",
"AnthropicIntegration",
"ClaudeAgentSDKIntegration",
"GoogleGenAIIntegration",
]
39 changes: 39 additions & 0 deletions py/src/braintrust/integrations/google_genai/__init__.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
"""Braintrust integration for Google GenAI."""

import logging

from braintrust.logger import NOOP_SPAN, current_span, init_logger

from .integration import GoogleGenAIIntegration


logger = logging.getLogger(__name__)

__all__ = [
"GoogleGenAIIntegration",
"setup_genai",
]


def setup_genai(
api_key: str | None = None,
project_id: str | None = None,
project_name: str | None = None,
) -> bool:
"""Setup Braintrust integration with Google GenAI.

Will automatically patch Google GenAI models for automatic tracing.

Args:
api_key: Braintrust API key.
project_id: Braintrust project ID.
project_name: Braintrust project name.

Returns:
True if setup was successful, False if google-genai is not installed.
"""
span = current_span()
if span == NOOP_SPAN:
init_logger(project=project_name, api_key=api_key, project_id=project_id)

return GoogleGenAIIntegration.setup()
32 changes: 32 additions & 0 deletions py/src/braintrust/integrations/google_genai/integration.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
"""Google GenAI integration — orchestration class and setup entry-point."""

import logging

from braintrust.integrations.base import BaseIntegration

from .patchers import (
AsyncModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
)


logger = logging.getLogger(__name__)


class GoogleGenAIIntegration(BaseIntegration):
"""Braintrust instrumentation for the Google GenAI Python SDK."""

name = "google_genai"
import_names = ("google.genai",)
patchers = (
ModelsGenerateContentPatcher,
ModelsGenerateContentStreamPatcher,
ModelsEmbedContentPatcher,
AsyncModelsGenerateContentPatcher,
AsyncModelsGenerateContentStreamPatcher,
AsyncModelsEmbedContentPatcher,
)
76 changes: 76 additions & 0 deletions py/src/braintrust/integrations/google_genai/patchers.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
"""Google GenAI patchers — one patcher per coherent patch target."""

from braintrust.integrations.base import FunctionWrapperPatcher

from .tracing import (
_async_embed_content_wrapper,
_async_generate_content_stream_wrapper,
_async_generate_content_wrapper,
_embed_content_wrapper,
_generate_content_stream_wrapper,
_generate_content_wrapper,
)


# ---------------------------------------------------------------------------
# Sync Models patchers
# ---------------------------------------------------------------------------


class ModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models._generate_content`` for tracing."""

name = "google_genai.models.generate_content"
target_module = "google.genai.models"
target_path = "Models._generate_content"
wrapper = _generate_content_wrapper


class ModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``Models.generate_content_stream`` for tracing."""

name = "google_genai.models.generate_content_stream"
target_module = "google.genai.models"
target_path = "Models.generate_content_stream"
wrapper = _generate_content_stream_wrapper


class ModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``Models.embed_content`` for tracing."""

name = "google_genai.models.embed_content"
target_module = "google.genai.models"
target_path = "Models.embed_content"
wrapper = _embed_content_wrapper


# ---------------------------------------------------------------------------
# Async Models patchers
# ---------------------------------------------------------------------------


class AsyncModelsGenerateContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content`` for tracing."""

name = "google_genai.async_models.generate_content"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content"
wrapper = _async_generate_content_wrapper


class AsyncModelsGenerateContentStreamPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.generate_content_stream`` for tracing."""

name = "google_genai.async_models.generate_content_stream"
target_module = "google.genai.models"
target_path = "AsyncModels.generate_content_stream"
wrapper = _async_generate_content_stream_wrapper


class AsyncModelsEmbedContentPatcher(FunctionWrapperPatcher):
"""Patch ``AsyncModels.embed_content`` for tracing."""

name = "google_genai.async_models.embed_content"
target_module = "google.genai.models"
target_path = "AsyncModels.embed_content"
wrapper = _async_embed_content_wrapper
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,8 +4,8 @@

import pytest
from braintrust import logger
from braintrust.integrations.google_genai import setup_genai
from braintrust.test_helpers import init_test_logger
from braintrust.wrappers.google_genai import setup_genai
from braintrust.wrappers.test_utils import verify_autoinstrument_script
from google.genai import types
from google.genai.client import Client
Expand Down
Loading
Loading