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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Fixed

- Keep the Interactions test mocks working with google-genai 2.34, which
copies the interaction that `interactions.create` returns with
`model_copy` to merge automatic continuation hops.

## Version 0.9.0 (2026-09-07)

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@
from typing import Any


def create_mock_model(**fields: Any) -> Any:
"""Mock a pydantic model of the Interactions API with these fields.

Since google-genai 2.34, ``interactions.create`` copies the interaction
it returns, and its usage, with ``model_copy(update=...)`` (to merge
automatic continuation hops, even for a single hop). On a plain
``MagicMock`` that copy would be a new mock without these fields.
"""
mock = unittest.mock.MagicMock()
mock.configure_mock(**fields)

def model_copy(update: Any = None, **kwargs: Any) -> Any:
return create_mock_model(**{**fields, **(update or {})})

mock.model_copy.side_effect = model_copy
return mock


def create_mock_interaction(
interaction_id: str = "test-id",
model_name: str = "test-model",
Expand All @@ -29,11 +47,12 @@ def create_mock_interaction(
input_tokens: int = 10,
output_tokens: int = 20,
) -> Any:
mock_usage = unittest.mock.MagicMock()
mock_usage.total_input_tokens = input_tokens
mock_usage.total_output_tokens = output_tokens
mock_usage.total_thought_tokens = 0
mock_usage.total_cached_tokens = 0
mock_usage = create_mock_model(
total_input_tokens=input_tokens,
total_output_tokens=output_tokens,
total_thought_tokens=0,
total_cached_tokens=0,
)

mock_user_step = unittest.mock.MagicMock()
mock_user_step.type = "user_input"
Expand All @@ -47,14 +66,13 @@ def create_mock_interaction(
mock_model_part.text = output_text
mock_model_step.content = [mock_model_part]

mock_interaction = unittest.mock.MagicMock()
mock_interaction.id = interaction_id
mock_interaction.model = model_name
mock_interaction.usage = mock_usage
mock_interaction.steps = [mock_user_step, mock_model_step]
mock_interaction.output_text = output_text

return mock_interaction
return create_mock_model(
id=interaction_id,
model=model_name,
usage=mock_usage,
steps=[mock_user_step, mock_model_step],
output_text=output_text,
)


def create_mock_completed_event(interaction: Any) -> Any:
Expand Down
3 changes: 3 additions & 0 deletions util/opentelemetry-util-genai/CHANGELOG-loongsuite.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
event coverage, Provider setup, context lifetimes, and version troubleshooting.
Present GenAI Utils as a standalone library configured through the OpenTelemetry
SDK, with optional storage backends separate from the setup guide.
- Fix the API docs build: Sphinx read the "Streaming:" prefix of the
`InvokeAgentInvocation.monotonic_first_token_s` docstring as a type and
failed on the missing `Streaming` class.

## Version 0.9.0 (2026-09-07)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ class InvokeAgentInvocation:
monotonic_start_s: float | None = None
monotonic_end_s: float | None = None
monotonic_first_token_s: float | None = None
"""Streaming: first-token time; TTFT attribute derived like ``LLMInvocation``."""
"""Monotonic time when the first token of a streaming response arrived.
The time-to-first-token attribute is derived from it as for
``LLMInvocation``."""


@dataclass
Expand Down
Loading