From b862834830c62c0c5072ef471100911d116a49e5 Mon Sep 17 00:00:00 2001 From: Marcus Motill Date: Mon, 19 Jan 2026 02:20:32 +0000 Subject: [PATCH 1/6] add google adk plugins --- .../contrib/google_adk_agents/README.md | 81 ++++++ .../contrib/google_adk_agents/__init__.py | 261 ++++++++++++++++++ .../test_temporal_integration.py | 245 ++++++++++++++++ .../google_adk_agents/test_temporal_unit.py | 177 ++++++++++++ 4 files changed, 764 insertions(+) create mode 100644 temporalio/contrib/google_adk_agents/README.md create mode 100644 temporalio/contrib/google_adk_agents/__init__.py create mode 100644 tests/contrib/google_adk_agents/test_temporal_integration.py create mode 100644 tests/contrib/google_adk_agents/test_temporal_unit.py diff --git a/temporalio/contrib/google_adk_agents/README.md b/temporalio/contrib/google_adk_agents/README.md new file mode 100644 index 000000000..632e92c4e --- /dev/null +++ b/temporalio/contrib/google_adk_agents/README.md @@ -0,0 +1,81 @@ +# Google ADK Agents SDK Integration for Temporal + +This package provides the integration layer between the Google ADK and Temporal. It allows ADK Agents to run reliably within Temporal Workflows by ensuring determinism and correctly routing external calls (network I/O) through Temporal Activities. + +## Core Concepts + +### 1. Interception Flow (`AgentPlugin`) + +The `AgentPlugin` acts as a middleware that intercepts model calls (e.g., `agent.generate_content`) *before* they execute. + +**Workflow Interception:** +1. **Intercept**: The ADK invokes `before_model_callback` when an agent attempts to call a model. +2. **Delegate**: The plugin calls `workflow.execute_activity()`, routing the request to Temporal for execution. +3. **Return**: The plugin awaits the activity result and returns it immediately. The ADK stops its own request processing, using the activity result as the final response. + +This ensures that all model interactions are recorded in the Temporal Workflow history, enabling reliable replay and determinism. + +### 2. Dynamic Activity Registration + +To provide visibility in the Temporal UI, activities are dynamically named after the calling agent (e.g., `MyAgent.generate_content`). Since agent names are not known at startup, the integration uses Temporal's dynamic activity registration. + +```python +@activity.defn(dynamic=True) +async def dynamic_activity(args: Sequence[RawValue]) -> Any: + ... +``` + +When the workflow executes an activity with an unknown name (e.g., `MyAgent.generate_content`), the worker routes the call to `dynamic_activity`. This handler inspects the `activity_type` and delegates execution to the appropriate internal logic (`_handle_generate_content`), enabling arbitrary activity names without explicit registration. + +### 3. Usage & Configuration + +The integration requires setup on both the Agent (Workflow) side and the Worker side. + +#### Agent Setup (Workflow Side) +Attach the `AgentPlugin` to your ADK agent. This safely routes model calls through Temporal activities. You **must** provide activity options (e.g., timeouts) as there are no defaults. + +```python +from datetime import timedelta +from temporalio.common import RetryPolicy +from google.adk.integrations.temporal import AgentPlugin + +# 1. Define Temporal Activity Options +activity_options = { + "start_to_close_timeout": timedelta(minutes=1), + "retry_policy": RetryPolicy(maximum_attempts=3) +} + +# 2. Add Plugin to Agent +agent = Agent( + model="gemini-2.5-pro", + plugins=[ + # Routes model calls to Temporal Activities + AgentPlugin(activity_options=activity_options) + ] +) + +# 3. Use Agent in Workflow +# When agent.generate_content() is called, it will execute as a Temporal Activity. +``` + +#### Worker Setup +Install the `WorkerPlugin` on your Temporal Worker. This handles serialization and runtime determinism. + +```python +from temporalio.worker import Worker +from google.adk.integrations.temporal import WorkerPlugin + +async def main(): + worker = Worker( + client, + task_queue="my-queue", + # Configures ADK Runtime & Pydantic Support + plugins=[WorkerPlugin()] + ) + await worker.run() +``` + +**What `WorkerPlugin` Does:** +* **Data Converter**: Enables Pydantic serialization for ADK objects. +* **Interceptors**: Sets up specific ADK runtime hooks for determinism (replacing `time.time`, `uuid.uuid4`) before workflow execution. +* TODO: is this enough . **Unsandboxed Workflow Runner**: Configures the worker to use the `UnsandboxedWorkflowRunner`, allowing standard imports in ADK agents. diff --git a/temporalio/contrib/google_adk_agents/__init__.py b/temporalio/contrib/google_adk_agents/__init__.py new file mode 100644 index 000000000..123aac4bd --- /dev/null +++ b/temporalio/contrib/google_adk_agents/__init__.py @@ -0,0 +1,261 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Temporal Integration for ADK. + +This module provides the necessary components to run ADK Agents within Temporal Workflows. +""" + +from __future__ import annotations + +import asyncio +import dataclasses +import functools +import inspect +import time +import uuid +from collections.abc import Sequence +from datetime import timedelta +from typing import Any, AsyncGenerator, Callable, List, Optional + +from google.adk.agents.callback_context import CallbackContext +from google.adk.agents.invocation_context import InvocationContext +from google.adk.models import BaseLlm, LLMRegistry, LlmRequest, LlmResponse +from google.adk.plugins import BasePlugin +from google.genai import types + +from temporalio import activity, workflow +from temporalio.common import RawValue, RetryPolicy +from temporalio.contrib.pydantic import ( + PydanticPayloadConverter as _DefaultPydanticPayloadConverter, +) +from temporalio.converter import DataConverter, DefaultPayloadConverter +from temporalio.plugin import SimplePlugin +from temporalio.worker import ( + ExecuteWorkflowInput, + Interceptor, + UnsandboxedWorkflowRunner, + WorkflowInboundInterceptor, + WorkflowInterceptorClassInput, + WorkflowRunner, +) + + +def setup_deterministic_runtime(): + """Configures ADK runtime for Temporal determinism. + + This should be called at the start of a Temporal Workflow before any ADK components + (like SessionService) are used, if they rely on runtime.get_time() or runtime.new_uuid(). + """ + try: + from google.adk import runtime + + # Define safer, context-aware providers + def _deterministic_time_provider() -> float: + if workflow.in_workflow(): + return workflow.now().timestamp() + return time.time() + + def _deterministic_id_provider() -> str: + if workflow.in_workflow(): + return str(workflow.uuid4()) + return str(uuid.uuid4()) + + runtime.set_time_provider(_deterministic_time_provider) + runtime.set_id_provider(_deterministic_id_provider) + except ImportError: + pass + except Exception as e: + print(f"Warning: Failed to set deterministic runtime providers: {e}") + + +class AdkWorkflowInboundInterceptor(WorkflowInboundInterceptor): + async def execute_workflow(self, input: ExecuteWorkflowInput) -> Any: + # Global runtime setup before ANY user code runs + setup_deterministic_runtime() + return await super().execute_workflow(input) + + +class AdkInterceptor(Interceptor): + def workflow_interceptor_class( + self, input: WorkflowInterceptorClassInput + ) -> type[WorkflowInboundInterceptor] | None: + return AdkWorkflowInboundInterceptor + + +class AgentPlugin(BasePlugin): + """ADK Plugin for Temporal integration. + + This plugin automatically configures the ADK runtime to be deterministic when running + inside a Temporal workflow, and intercepts model calls to execute them as Temporal Activities. + """ + + def __init__(self, activity_options: Optional[dict[str, Any]] = None): + """Initializes the Temporal Plugin. + + Args: + activity_options: Default options for model activities (e.g. start_to_close_timeout). + """ + super().__init__(name="temporal_plugin") + self.activity_options = activity_options or {} + + @staticmethod + def activity_tool(activity_def: Callable, **kwargs: Any) -> Callable: + """Decorator/Wrapper to wrap a Temporal Activity as an ADK Tool. + + This ensures the activity's signature is preserved for ADK's tool schema generation + while marking it as a tool that executes via 'workflow.execute_activity'. + """ + + async def wrapper(*args, **kw): + # Inspect signature to bind arguments + sig = inspect.signature(activity_def) + bound = sig.bind(*args, **kw) + bound.apply_defaults() + + # Convert to positional args for Temporal + activity_args = list(bound.arguments.values()) + + # Decorator kwargs are defaults. + options = kwargs.copy() + + return await workflow.execute_activity( + activity_def, *activity_args, **options + ) + + # Copy metadata + wrapper.__name__ = activity_def.__name__ + wrapper.__doc__ = activity_def.__doc__ + wrapper.__signature__ = inspect.signature(activity_def) + + return wrapper + + async def before_model_callback( + self, *, callback_context: CallbackContext, llm_request: LlmRequest + ) -> LlmResponse | None: + # Construct dynamic activity name for visibility + agent_name = callback_context.agent_name + activity_name = f"{agent_name}.generate_content" + + # Execute with dynamic name + response_dicts = await workflow.execute_activity( + activity_name, args=[llm_request], **self.activity_options + ) + + # Rehydrate LlmResponse objects safely + responses = [] + for d in response_dicts: + try: + responses.append(LlmResponse.model_validate(d)) + except Exception as e: + raise RuntimeError( + f"Failed to deserialized LlmResponse from activity result: {e}" + ) from e + + # Simple consolidation: return the last complete response + return responses[-1] if responses else None + + +class WorkerPlugin(SimplePlugin): + """A Temporal Worker Plugin configured for ADK. + + This plugin configures: + 1. Pydantic Payload Converter (required for ADK objects). + 2. Sandbox Passthrough for `google.adk` and `google.genai`. + """ + + def __init__(self): + super().__init__( + name="adk_worker_plugin", + data_converter=self._configure_data_converter, + workflow_runner=self._configure_workflow_runner, + activities=[self.dynamic_activity], + worker_interceptors=[AdkInterceptor()], + ) + + @staticmethod + @activity.defn(dynamic=True) + async def dynamic_activity(args: Sequence[RawValue]) -> Any: + """Handles dynamic ADK activities (e.g. 'AgentName.generate_content').""" + activity_type = activity.info().activity_type + + # Check if this is a generate_content call + if ( + activity_type.endswith(".generate_content") + or activity_type == "google.adk.generate_content" + ): + return await WorkerPlugin._handle_generate_content(args) + + raise ValueError(f"Unknown dynamic activity: {activity_type}") + + @staticmethod + async def _handle_generate_content(args: List[Any]) -> list[dict[str, Any]]: + """Implementation of content generation.""" + # 1. Decode Arguments + # Dynamic activities receive RawValue wrappers (which host the Payload). + # We must manually decode them using the activity's configured data converter. + converter = activity.payload_converter() + + # We expect a single argument: LlmRequest + if not args: + raise ValueError("Missing llm_request argument for generate_content") + + # Extract payloads from RawValue wrappers + payloads = [arg.payload for arg in args] + + # Decode + # from_payloads returns a list of decoded objects. + # We specify the types we expect for each argument. + try: + decoded_args = converter.from_payloads(payloads, [LlmRequest]) + llm_request: LlmRequest = decoded_args[0] + except Exception as e: + activity.logger.error(f"Failed to decode arguments: {e}") + raise ValueError(f"Argument decoding failed: {e}") from e + + # 3. Model Initialization + llm = LLMRegistry.new_llm(llm_request.model) + if not llm: + raise ValueError(f"Failed to create LLM for model: {llm_request.model}") + + # 4. Execution + responses = [ + response + async for response in llm.generate_content_async(llm_request=llm_request) + ] + + # 5. Serialization + # Return dicts to avoid Pydantic strictness issues on rehydration + return [r.model_dump(mode="json", by_alias=True) for r in responses] + + def _configure_data_converter( + self, converter: DataConverter | None + ) -> DataConverter: + if converter is None: + return DataConverter( + payload_converter_class=_DefaultPydanticPayloadConverter + ) + elif converter.payload_converter_class is DefaultPayloadConverter: + return dataclasses.replace( + converter, payload_converter_class=_DefaultPydanticPayloadConverter + ) + return converter + + def _configure_workflow_runner( + self, runner: WorkflowRunner | None + ) -> WorkflowRunner: + from temporalio.worker import UnsandboxedWorkflowRunner + + # TODO: Not sure implications here. is this a good default an allow user override? + return UnsandboxedWorkflowRunner() diff --git a/tests/contrib/google_adk_agents/test_temporal_integration.py b/tests/contrib/google_adk_agents/test_temporal_integration.py new file mode 100644 index 000000000..8ea2eba8f --- /dev/null +++ b/tests/contrib/google_adk_agents/test_temporal_integration.py @@ -0,0 +1,245 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Integration tests for ADK Temporal support.""" + +import dataclasses +import logging +import os +import uuid +from datetime import timedelta +from typing import AsyncGenerator + +import pytest +from google.adk import Agent, Runner, runtime +from google.adk.agents import LlmAgent +from google.adk.events import Event +from google.adk.models import LLMRegistry, LlmRequest, LlmResponse +from google.adk.sessions import InMemorySessionService +from google.adk.tools import AgentTool +from google.adk.utils.context_utils import Aclosing +from google.genai import types + +from temporalio import activity, workflow +from temporalio.client import Client +from temporalio.contrib.google_adk_agents import AgentPlugin, WorkerPlugin +from temporalio.contrib.pydantic import ( + PydanticPayloadConverter, + pydantic_data_converter, +) +from temporalio.converter import DataConverter, DefaultPayloadConverter +from temporalio.plugin import SimplePlugin +from temporalio.worker import Worker, WorkflowRunner +from temporalio.worker.workflow_sandbox import ( + SandboxedWorkflowRunner, + SandboxRestrictions, +) + +# Required Environment Variables for this test: +# in this folder update .env.example to be .env and have the following vars: +# GOOGLE_GENAI_USE_VERTEXAI=1 +# GOOGLE_CLOUD_PROJECT="" +# GOOGLE_CLOUD_LOCATION="" +# TEST_BACKEND=VERTEX_ONLY +# then: +# start temporal: temporal server start-dev +# then: +# uv run pytest tests/integration/manual_test_temporal_integration.py + + +logger = logging.getLogger(__name__) + + +@activity.defn +async def get_weather(city: str) -> str: + """Activity that gets weather for a given city.""" + return "Warm and sunny. 17 degrees." + + +@workflow.defn +class WeatherAgent: + @workflow.run + async def run(self, prompt: str) -> Event | None: + logger.info("Workflow started.") + + # 1. Define Agent using Temporal Helpers + # Note: AgentPlugin in the Runner automatically handles Runtime setup + # and Model Activity interception. We use standard ADK models now. + + # Wraps 'get_weather' activity as a Tool + weather_tool = AgentPlugin.activity_tool( + get_weather, start_to_close_timeout=timedelta(seconds=60) + ) + + agent = Agent( + name="test_agent", + model="gemini-2.5-pro", # Standard model string + tools=[weather_tool], + ) + + # 2. Create Session (uses runtime.new_uuid() -> workflow.uuid4()) + session_service = InMemorySessionService() + logger.info("Create session.") + session = await session_service.create_session( + app_name="test_app", user_id="test" + ) + + logger.info(f"Session created with ID: {session.id}") + + # 3. Run Agent with AgentPlugin + runner = Runner( + agent=agent, + app_name="test_app", + session_service=session_service, + plugins=[ + AgentPlugin( + activity_options={"start_to_close_timeout": timedelta(minutes=2)} + ) + ], + ) + + logger.info("Starting runner.") + last_event = None + async with Aclosing( + runner.run_async( + user_id="test", + session_id=session.id, + new_message=types.Content(role="user", parts=[types.Part(text=prompt)]), + ) + ) as agen: + async for event in agen: + logger.info(f"Event: {event}") + last_event = event + + return last_event + + +@workflow.defn +class MultiAgentWorkflow: + @workflow.run + async def run(self, topic: str) -> str: + # Example of multi-turn/multi-agent orchestration + # This is where Temporal shines - orchestrating complex agent flows + + # 0. Deterministic Runtime is now auto-configured by AdkInterceptor! + + # 1. Setup Session Service + session_service = InMemorySessionService() + session = await session_service.create_session( + app_name="multi_agent_app", user_id="test_user" + ) + + # 2. Define Agents + # Sub-agent: Researcher + researcher = LlmAgent( + name="researcher", + model="gemini-2.5-pro", + instruction="You are a researcher. Find information about the topic.", + ) + + # Sub-agent: Writer + writer = LlmAgent( + name="writer", + model="gemini-2.5-pro", + instruction="You are a poet. Write a haiku based on the research.", + ) + + # Root Agent: Coordinator + coordinator = LlmAgent( + name="coordinator", + model="gemini-2.5-pro", + instruction="You are a coordinator. Delegate to researcher then writer.", + sub_agents=[researcher, writer], + ) + + # 3. Initialize Runner with required args + runner = Runner( + agent=coordinator, + app_name="multi_agent_app", + session_service=session_service, + plugins=[ + AgentPlugin( + activity_options={"start_to_close_timeout": timedelta(minutes=2)} + ) + ], + ) + + # 4. Run + # Note: In a real temporal app, we might signal the workflow or use queries. + # Here we just run a single turn for the test. + final_content = "" + user_msg = types.Content( + role="user", + parts=[ + types.Part( + text=f"Write a haiku about {topic}. First research it, then write it." + ) + ], + ) + async for event in runner.run_async( + user_id="test_user", session_id=session.id, new_message=user_msg + ): + if event.content and event.content.parts: + final_content = event.content.parts[0].text + + return final_content + + +@pytest.mark.asyncio +async def test_temporal_integration(): + """Manual integration test requiring a running Temporal server.""" + + # 1. Start a Worker (in a real app, this would be a separate process) + # We run it here for the test. + + try: + # Connect to Temporal Server + # We must configure the data converter to handle Pydantic models (like Event) + client = await Client.connect( + "localhost:7233", + data_converter=DataConverter( + payload_converter_class=PydanticPayloadConverter + ), + ) + except RuntimeError: + pytest.skip("Could not connect to Temporal server. Is it running?") + + # Run Worker with the ADK plugin + async with Worker( + client, + task_queue="adk-task-queue", + activities=[ + get_weather, + ], + workflows=[WeatherAgent, MultiAgentWorkflow], + plugins=[WorkerPlugin()], + ): + print("Worker started.") + # Test Weather Agent + result = await client.execute_workflow( + WeatherAgent.run, + "What is the weather in New York?", + id=f"weather-agent-workflow-{uuid.uuid4()}", + task_queue="adk-task-queue", + ) + print(f"Workflow result: {result}") + + # Test Multi Agent + result_multi = await client.execute_workflow( + MultiAgentWorkflow.run, + "Run mult-agent flow", + id=f"multi-agent-workflow-{uuid.uuid4()}", + task_queue="adk-task-queue", + ) + print(f"Multi-Agent Workflow result: {result_multi}") diff --git a/tests/contrib/google_adk_agents/test_temporal_unit.py b/tests/contrib/google_adk_agents/test_temporal_unit.py new file mode 100644 index 000000000..41447b09b --- /dev/null +++ b/tests/contrib/google_adk_agents/test_temporal_unit.py @@ -0,0 +1,177 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Unit tests for Temporal integration helpers.""" + +import asyncio +import sys +import unittest +from typing import Any +from unittest.mock import AsyncMock, MagicMock, patch + +from google.genai import types + +# Configure Mocks globally +# We create fresh mocks here. +mock_workflow = MagicMock() +mock_activity = MagicMock() +mock_worker = MagicMock() +mock_client = MagicMock() +mock_converter = MagicMock() + +# Important: execute_activity must be awaitable +mock_workflow.execute_activity = AsyncMock(return_value="mock_result") +mock_workflow.in_workflow = MagicMock(return_value=False) +mock_workflow.now = MagicMock() +mock_workflow.uuid4 = MagicMock() + +# Mock the parent package +mock_temporalio = MagicMock() +mock_temporalio.workflow = mock_workflow +mock_temporalio.activity = mock_activity +mock_temporalio.worker = mock_worker +mock_temporalio.client = mock_client +mock_temporalio.converter = mock_converter + + +class FakeSimplePlugin: + def __init__(self, **kwargs): + pass + + +mock_temporalio.plugin = MagicMock() +mock_temporalio.plugin.SimplePlugin = FakeSimplePlugin +mock_temporalio.worker.workflow_sandbox = MagicMock() +mock_temporalio.contrib = MagicMock() +mock_temporalio.contrib.pydantic = MagicMock() + +# Mock sys.modules +# Mock sys.modules +# We must ensure we get a fresh import of 'google.adk.integrations.temporal' +# that uses our MOCKED 'temporalio'. +# If it was already loaded, we remove it. +for mod in list(sys.modules.keys()): + if mod.startswith("google.adk") or mod == "temporalio": + del sys.modules[mod] + +with patch.dict( + sys.modules, + { + "temporalio": mock_temporalio, + "temporalio.workflow": mock_workflow, + "temporalio.activity": mock_activity, + "temporalio.worker": mock_worker, + "temporalio.client": mock_client, + "temporalio.converter": mock_converter, + "temporalio.common": MagicMock(), + "temporalio.plugin": mock_temporalio.plugin, + "temporalio.worker.workflow_sandbox": mock_temporalio.worker.workflow_sandbox, + "temporalio.contrib": mock_temporalio.contrib, + "temporalio.contrib.pydantic": mock_temporalio.contrib.pydantic, + }, +): + from google.adk import runtime + from google.adk.agents.callback_context import CallbackContext + from google.adk.agents.invocation_context import InvocationContext + from google.adk.models import LlmRequest, LlmResponse + + from temporalio.contrib import google_adk_agents as temporal + + +class TestTemporalIntegration(unittest.TestCase): + def test_activity_as_tool_wrapper(self): + # Reset mocks + mock_workflow.reset_mock() + mock_workflow.execute_activity = AsyncMock(return_value="mock_result") + + # Verify mock setup + assert temporal.workflow.execute_activity is mock_workflow.execute_activity + + # Define a fake activity + async def my_activity(arg: str) -> str: + """My Docstring.""" + return f"Hello {arg}" + + # Wrap it + tool = temporal.AgentPlugin.activity_tool( + my_activity, start_to_close_timeout=100 + ) + + # Check metadata + self.assertEqual(tool.__name__, "my_activity") # Matches function name + self.assertEqual(tool.__doc__, "My Docstring.") + + # Run tool (wrapper) + loop = asyncio.new_event_loop() + try: + asyncio.set_event_loop(loop) + loop.run_until_complete(tool(arg="World")) + finally: + loop.close() + + # Verify call + mock_workflow.execute_activity.assert_called_once() + args, kwargs = mock_workflow.execute_activity.call_args + self.assertEqual(args[1], "World") + self.assertEqual(kwargs["start_to_close_timeout"], 100) + + def test_temporal_plugin_before_model(self): + plugin = temporal.AgentPlugin(activity_options={"start_to_close_timeout": 60}) + + # Setup mocks + mock_workflow.reset_mock() + mock_workflow.in_workflow.return_value = True + response_content = types.Content(parts=[types.Part(text="plugin_resp")]) + llm_response = LlmResponse(content=response_content) + # The plugin now expects the activity to return dicts (model_dump(mode='json')) + # to ensure safe deserialization across process boundaries. + response_dict = llm_response.model_dump(mode="json", by_alias=True) + # Ensure 'content' key is present and correct (pydantic dump might be complex) + # For the test simple case, the dump is sufficient. + + mock_workflow.execute_activity = AsyncMock(return_value=[response_dict]) + + # callback_context = MagicMock(spec=CallbackContext) + # Using spec might hide dynamic attributes or properties if not fully mocked + callback_context = MagicMock() + callback_context.agent_name = "test-agent" + callback_context.invocation_context.agent.model = "test-agent-model" + + llm_request = LlmRequest(model="test-agent-model", prompt="hi") + + # Run callback + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + try: + result = loop.run_until_complete( + plugin.before_model_callback( + callback_context=callback_context, llm_request=llm_request + ) + ) + finally: + loop.close() + + # Verify execution + mock_workflow.execute_activity.assert_called_once() + args, kwargs = mock_workflow.execute_activity.call_args + self.assertEqual(kwargs["start_to_close_timeout"], 60) + + # Check dynamic activity name + self.assertEqual(args[0], "test-agent.generate_content") + self.assertEqual(kwargs["args"][0].model, "test-agent-model") + + # Verify result merge + self.assertIsNotNone(result) + # Result is re-hydrated LlmResponse + self.assertEqual(result.content.parts[0].text, "plugin_resp") From 2cf6808344da6a4f009cb2f87fef420e75bbd7dc Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Thu, 22 Jan 2026 13:20:56 -0800 Subject: [PATCH 2/6] Update with dev dependency and some cleanup --- pyproject.toml | 1 + .../contrib/google_adk_agents/__init__.py | 151 +- .../test_temporal_integration.py | 20 +- uv.lock | 1298 ++++++++++++++++- 4 files changed, 1352 insertions(+), 118 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d660bfb46..b04f60ffe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ Documentation = "https://docs.temporal.io/docs/python" dev = [ "basedpyright==1.34.0", "cibuildwheel>=2.22.0,<3", + "google-adk @ git+https://github.com/marcusmotill/adk-python-temporal.git@motill/durable-support", "grpcio-tools>=1.48.2,<2", "mypy==1.18.2", "mypy-protobuf>=3.3.0,<4", diff --git a/temporalio/contrib/google_adk_agents/__init__.py b/temporalio/contrib/google_adk_agents/__init__.py index 123aac4bd..faa97967b 100644 --- a/temporalio/contrib/google_adk_agents/__init__.py +++ b/temporalio/contrib/google_adk_agents/__init__.py @@ -26,8 +26,9 @@ import time import uuid from collections.abc import Sequence +from contextlib import asynccontextmanager from datetime import timedelta -from typing import Any, AsyncGenerator, Callable, List, Optional +from typing import Any, AsyncGenerator, Callable, List, Optional, AsyncIterator from google.adk.agents.callback_context import CallbackContext from google.adk.agents.invocation_context import InvocationContext @@ -50,6 +51,7 @@ WorkflowInterceptorClassInput, WorkflowRunner, ) +from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner def setup_deterministic_runtime(): @@ -80,20 +82,6 @@ def _deterministic_id_provider() -> str: print(f"Warning: Failed to set deterministic runtime providers: {e}") -class AdkWorkflowInboundInterceptor(WorkflowInboundInterceptor): - async def execute_workflow(self, input: ExecuteWorkflowInput) -> Any: - # Global runtime setup before ANY user code runs - setup_deterministic_runtime() - return await super().execute_workflow(input) - - -class AdkInterceptor(Interceptor): - def workflow_interceptor_class( - self, input: WorkflowInterceptorClassInput - ) -> type[WorkflowInboundInterceptor] | None: - return AdkWorkflowInboundInterceptor - - class AgentPlugin(BasePlugin): """ADK Plugin for Temporal integration. @@ -144,30 +132,43 @@ async def wrapper(*args, **kw): async def before_model_callback( self, *, callback_context: CallbackContext, llm_request: LlmRequest ) -> LlmResponse | None: - # Construct dynamic activity name for visibility - agent_name = callback_context.agent_name - activity_name = f"{agent_name}.generate_content" - - # Execute with dynamic name - response_dicts = await workflow.execute_activity( - activity_name, args=[llm_request], **self.activity_options + responses = await workflow.execute_activity( + invoke_model, args=[llm_request], summary=callback_context.agent_name, **self.activity_options ) - # Rehydrate LlmResponse objects safely - responses = [] - for d in response_dicts: - try: - responses.append(LlmResponse.model_validate(d)) - except Exception as e: - raise RuntimeError( - f"Failed to deserialized LlmResponse from activity result: {e}" - ) from e + # # Rehydrate LlmResponse objects safely + # responses = [] + # for d in response_dicts: + # try: + # responses.append(LlmResponse.model_validate(d)) + # except Exception as e: + # raise RuntimeError( + # f"Failed to deserialized LlmResponse from activity result: {e}" + # ) from e # Simple consolidation: return the last complete response return responses[-1] if responses else None -class WorkerPlugin(SimplePlugin): +@activity.defn +async def invoke_model(llm_request: LlmRequest) -> list[LlmResponse]: + + # 3. Model Initialization + llm = LLMRegistry.new_llm(llm_request.model) + if not llm: + raise ValueError(f"Failed to create LLM for model: {llm_request.model}") + + # 4. Execution + responses = [ + response + async for response in llm.generate_content_async(llm_request=llm_request) + ] + + # 5. Serialization + # Return dicts to avoid Pydantic strictness issues on rehydration + return responses + +class GoogleAdkPlugin(SimplePlugin): """A Temporal Worker Plugin configured for ADK. This plugin configures: @@ -176,68 +177,31 @@ class WorkerPlugin(SimplePlugin): """ def __init__(self): - super().__init__( - name="adk_worker_plugin", - data_converter=self._configure_data_converter, - workflow_runner=self._configure_workflow_runner, - activities=[self.dynamic_activity], - worker_interceptors=[AdkInterceptor()], - ) - @staticmethod - @activity.defn(dynamic=True) - async def dynamic_activity(args: Sequence[RawValue]) -> Any: - """Handles dynamic ADK activities (e.g. 'AgentName.generate_content').""" - activity_type = activity.info().activity_type + @asynccontextmanager + async def run_context() -> AsyncIterator[None]: + setup_deterministic_runtime() + yield - # Check if this is a generate_content call - if ( - activity_type.endswith(".generate_content") - or activity_type == "google.adk.generate_content" - ): - return await WorkerPlugin._handle_generate_content(args) + def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: + if not runner: + raise ValueError("No WorkflowRunner provided to the OpenAI plugin.") - raise ValueError(f"Unknown dynamic activity: {activity_type}") + # If in sandbox, add additional passthrough + if isinstance(runner, SandboxedWorkflowRunner): + return dataclasses.replace( + runner, + restrictions=runner.restrictions.with_passthrough_modules("google.adk", "google.genai"), + ) + return runner - @staticmethod - async def _handle_generate_content(args: List[Any]) -> list[dict[str, Any]]: - """Implementation of content generation.""" - # 1. Decode Arguments - # Dynamic activities receive RawValue wrappers (which host the Payload). - # We must manually decode them using the activity's configured data converter. - converter = activity.payload_converter() - - # We expect a single argument: LlmRequest - if not args: - raise ValueError("Missing llm_request argument for generate_content") - - # Extract payloads from RawValue wrappers - payloads = [arg.payload for arg in args] - - # Decode - # from_payloads returns a list of decoded objects. - # We specify the types we expect for each argument. - try: - decoded_args = converter.from_payloads(payloads, [LlmRequest]) - llm_request: LlmRequest = decoded_args[0] - except Exception as e: - activity.logger.error(f"Failed to decode arguments: {e}") - raise ValueError(f"Argument decoding failed: {e}") from e - - # 3. Model Initialization - llm = LLMRegistry.new_llm(llm_request.model) - if not llm: - raise ValueError(f"Failed to create LLM for model: {llm_request.model}") - - # 4. Execution - responses = [ - response - async for response in llm.generate_content_async(llm_request=llm_request) - ] - - # 5. Serialization - # Return dicts to avoid Pydantic strictness issues on rehydration - return [r.model_dump(mode="json", by_alias=True) for r in responses] + super().__init__( + name="google_adk_plugin", + data_converter=self._configure_data_converter, + activities=[invoke_model], + run_context=lambda: run_context(), + workflow_runner=workflow_runner + ) def _configure_data_converter( self, converter: DataConverter | None @@ -252,10 +216,3 @@ def _configure_data_converter( ) return converter - def _configure_workflow_runner( - self, runner: WorkflowRunner | None - ) -> WorkflowRunner: - from temporalio.worker import UnsandboxedWorkflowRunner - - # TODO: Not sure implications here. is this a good default an allow user override? - return UnsandboxedWorkflowRunner() diff --git a/tests/contrib/google_adk_agents/test_temporal_integration.py b/tests/contrib/google_adk_agents/test_temporal_integration.py index 8ea2eba8f..361e08b1a 100644 --- a/tests/contrib/google_adk_agents/test_temporal_integration.py +++ b/tests/contrib/google_adk_agents/test_temporal_integration.py @@ -16,35 +16,25 @@ import dataclasses import logging -import os import uuid from datetime import timedelta -from typing import AsyncGenerator import pytest -from google.adk import Agent, Runner, runtime +from google.adk import Agent, Runner from google.adk.agents import LlmAgent from google.adk.events import Event -from google.adk.models import LLMRegistry, LlmRequest, LlmResponse from google.adk.sessions import InMemorySessionService -from google.adk.tools import AgentTool from google.adk.utils.context_utils import Aclosing from google.genai import types from temporalio import activity, workflow from temporalio.client import Client -from temporalio.contrib.google_adk_agents import AgentPlugin, WorkerPlugin +from temporalio.contrib.google_adk_agents import AgentPlugin, GoogleAdkPlugin from temporalio.contrib.pydantic import ( PydanticPayloadConverter, - pydantic_data_converter, -) -from temporalio.converter import DataConverter, DefaultPayloadConverter -from temporalio.plugin import SimplePlugin -from temporalio.worker import Worker, WorkflowRunner -from temporalio.worker.workflow_sandbox import ( - SandboxedWorkflowRunner, - SandboxRestrictions, ) +from temporalio.converter import DataConverter +from temporalio.worker import Worker # Required Environment Variables for this test: # in this folder update .env.example to be .env and have the following vars: @@ -223,7 +213,7 @@ async def test_temporal_integration(): get_weather, ], workflows=[WeatherAgent, MultiAgentWorkflow], - plugins=[WorkerPlugin()], + plugins=[GoogleAdkPlugin()], ): print("Worker started.") # Test Weather Agent diff --git a/uv.lock b/uv.lock index e29cf27db..cacea9110 100644 --- a/uv.lock +++ b/uv.lock @@ -3,7 +3,9 @@ revision = 3 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.14'", - "python_full_version < '3.14'", + "python_full_version == '3.13.*'", + "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version < '3.11'", ] [[package]] @@ -148,6 +150,39 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, ] +[[package]] +name = "aiosqlite" +version = "0.22.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/8a/64761f4005f17809769d23e518d915db74e6310474e733e3593cfc854ef1/aiosqlite-0.22.1.tar.gz", hash = "sha256:043e0bd78d32888c0a9ca90fc788b38796843360c855a7262a532813133a0650", size = 14821, upload-time = "2025-12-23T19:25:43.997Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/b7/e3bf5133d697a08128598c8d0abc5e16377b51465a33756de24fa7dee953/aiosqlite-0.22.1-py3-none-any.whl", hash = "sha256:21c002eb13823fad740196c5a2e9d8e62f6243bd9e7e4a1f87fb5e44ecb4fceb", size = 17405, upload-time = "2025-12-23T19:25:42.139Z" }, +] + +[[package]] +name = "alembic" +version = "1.18.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mako" }, + { name = "sqlalchemy" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/cc/aca263693b2ece99fa99a09b6d092acb89973eb2bb575faef1777e04f8b4/alembic-1.18.1.tar.gz", hash = "sha256:83ac6b81359596816fb3b893099841a0862f2117b2963258e965d70dc62fb866", size = 2044319, upload-time = "2026-01-14T18:53:14.907Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/36/cd9cb6101e81e39076b2fbe303bfa3c85ca34e55142b0324fcbf22c5c6e2/alembic-1.18.1-py3-none-any.whl", hash = "sha256:f1c3b0920b87134e851c25f1f7f236d8a332c34b75416802d06971df5d1b7810", size = 260973, upload-time = "2026-01-14T18:53:17.533Z" }, +] + +[[package]] +name = "annotated-doc" +version = "0.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, +] + [[package]] name = "annotated-types" version = "0.7.0" @@ -190,6 +225,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, ] +[[package]] +name = "authlib" +version = "1.6.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bb/9b/b1661026ff24bc641b76b78c5222d614776b0c085bcfdac9bd15a1cb4b35/authlib-1.6.6.tar.gz", hash = "sha256:45770e8e056d0f283451d9996fbb59b70d45722b45d854d58f32878d0a40c38e", size = 164894, upload-time = "2025-12-12T08:01:41.464Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/51/321e821856452f7386c4e9df866f196720b1ad0c5ea1623ea7399969ae3b/authlib-1.6.6-py2.py3-none-any.whl", hash = "sha256:7d9e9bc535c13974313a87f53e8430eb6ea3d1cf6ae4f6efcd793f2e949143fd", size = 244005, upload-time = "2025-12-12T08:01:40.209Z" }, +] + [[package]] name = "automat" version = "25.4.16" @@ -274,6 +321,8 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44", size = 184283, upload-time = "2025-09-08T23:22:08.01Z" }, + { url = "https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49", size = 180504, upload-time = "2025-09-08T23:22:10.637Z" }, { url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" }, { url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" }, { url = "https://files.pythonhosted.org/packages/05/eb/b86f2a2645b62adcfff53b0dd97e8dfafb5c8aa864bd0d9a2c2049a0d551/cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", size = 203217, upload-time = "2025-09-08T23:22:14.596Z" }, @@ -282,6 +331,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" }, { url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" }, { url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" }, + { url = "https://files.pythonhosted.org/packages/e2/cc/027d7fb82e58c48ea717149b03bcadcbdc293553edb283af792bd4bcbb3f/cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", size = 172184, upload-time = "2025-09-08T23:22:23.328Z" }, + { url = "https://files.pythonhosted.org/packages/33/fa/072dd15ae27fbb4e06b437eb6e944e75b068deb09e2a2826039e49ee2045/cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", size = 182790, upload-time = "2025-09-08T23:22:24.752Z" }, + { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, + { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, @@ -290,6 +343,11 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" }, + { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, + { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, @@ -297,6 +355,11 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, @@ -304,18 +367,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, ] [[package]] @@ -439,6 +515,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295, upload-time = "2025-09-18T17:32:22.42Z" }, ] +[[package]] +name = "cloudpickle" +version = "3.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/27/fb/576f067976d320f5f0114a8d9fa1215425441bb35627b1993e5afd8111e5/cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414", size = 22330, upload-time = "2025-11-03T09:25:26.604Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a", size = 22228, upload-time = "2025-11-03T09:25:25.534Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -580,6 +665,7 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/4a/9b/e301418629f7bfdf72db9e80ad6ed9d1b83c487c471803eaa6464c511a01/cryptography-46.0.2.tar.gz", hash = "sha256:21b6fc8c71a3f9a604f028a329e5560009cc4a3a828bfea5fcba8eb7647d88fe", size = 749293, upload-time = "2025-10-01T00:29:11.856Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/98/7a8df8c19a335c8028414738490fc3955c0cecbfdd37fcc1b9c3d04bd561/cryptography-46.0.2-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:f3e32ab7dd1b1ef67b9232c4cf5e2ee4cd517d4316ea910acaaa9c5712a1c663", size = 7261255, upload-time = "2025-10-01T00:27:22.947Z" }, { url = "https://files.pythonhosted.org/packages/c6/38/b2adb2aa1baa6706adc3eb746691edd6f90a656a9a65c3509e274d15a2b8/cryptography-46.0.2-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1fd1a69086926b623ef8126b4c33d5399ce9e2f3fac07c9c734c2a4ec38b6d02", size = 4297596, upload-time = "2025-10-01T00:27:25.258Z" }, { url = "https://files.pythonhosted.org/packages/e4/27/0f190ada240003119488ae66c897b5e97149292988f556aef4a6a2a57595/cryptography-46.0.2-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb7fb9cd44c2582aa5990cf61a4183e6f54eea3172e54963787ba47287edd135", size = 4450899, upload-time = "2025-10-01T00:27:27.458Z" }, { url = "https://files.pythonhosted.org/packages/85/d5/e4744105ab02fdf6bb58ba9a816e23b7a633255987310b4187d6745533db/cryptography-46.0.2-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:9066cfd7f146f291869a9898b01df1c9b0e314bfa182cef432043f13fc462c92", size = 4300382, upload-time = "2025-10-01T00:27:29.091Z" }, @@ -591,6 +677,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/55/1d/42fda47b0111834b49e31590ae14fd020594d5e4dadd639bce89ad790fba/cryptography-46.0.2-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:be939b99d4e091eec9a2bcf41aaf8f351f312cd19ff74b5c83480f08a8a43e0b", size = 4482088, upload-time = "2025-10-01T00:27:42.668Z" }, { url = "https://files.pythonhosted.org/packages/17/50/60f583f69aa1602c2bdc7022dae86a0d2b837276182f8c1ec825feb9b874/cryptography-46.0.2-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f13b040649bc18e7eb37936009b24fd31ca095a5c647be8bb6aaf1761142bd1", size = 4425599, upload-time = "2025-10-01T00:27:44.616Z" }, { url = "https://files.pythonhosted.org/packages/d1/57/d8d4134cd27e6e94cf44adb3f3489f935bde85f3a5508e1b5b43095b917d/cryptography-46.0.2-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bdc25e4e01b261a8fda4e98618f1c9515febcecebc9566ddf4a70c63967043b", size = 4697458, upload-time = "2025-10-01T00:27:46.209Z" }, + { url = "https://files.pythonhosted.org/packages/d1/2b/531e37408573e1da33adfb4c58875013ee8ac7d548d1548967d94a0ae5c4/cryptography-46.0.2-cp311-abi3-win32.whl", hash = "sha256:8b9bf67b11ef9e28f4d78ff88b04ed0929fcd0e4f70bb0f704cfc32a5c6311ee", size = 3056077, upload-time = "2025-10-01T00:27:48.424Z" }, + { url = "https://files.pythonhosted.org/packages/a8/cd/2f83cafd47ed2dc5a3a9c783ff5d764e9e70d3a160e0df9a9dcd639414ce/cryptography-46.0.2-cp311-abi3-win_amd64.whl", hash = "sha256:758cfc7f4c38c5c5274b55a57ef1910107436f4ae842478c4989abbd24bd5acb", size = 3512585, upload-time = "2025-10-01T00:27:50.521Z" }, + { url = "https://files.pythonhosted.org/packages/00/36/676f94e10bfaa5c5b86c469ff46d3e0663c5dc89542f7afbadac241a3ee4/cryptography-46.0.2-cp311-abi3-win_arm64.whl", hash = "sha256:218abd64a2e72f8472c2102febb596793347a3e65fafbb4ad50519969da44470", size = 2927474, upload-time = "2025-10-01T00:27:52.91Z" }, + { url = "https://files.pythonhosted.org/packages/6f/cc/47fc6223a341f26d103cb6da2216805e08a37d3b52bee7f3b2aee8066f95/cryptography-46.0.2-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:bda55e8dbe8533937956c996beaa20266a8eca3570402e52ae52ed60de1faca8", size = 7198626, upload-time = "2025-10-01T00:27:54.8Z" }, { url = "https://files.pythonhosted.org/packages/93/22/d66a8591207c28bbe4ac7afa25c4656dc19dc0db29a219f9809205639ede/cryptography-46.0.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e7155c0b004e936d381b15425273aee1cebc94f879c0ce82b0d7fecbf755d53a", size = 4287584, upload-time = "2025-10-01T00:27:57.018Z" }, { url = "https://files.pythonhosted.org/packages/8c/3e/fac3ab6302b928e0398c269eddab5978e6c1c50b2b77bb5365ffa8633b37/cryptography-46.0.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a61c154cc5488272a6c4b86e8d5beff4639cdb173d75325ce464d723cda0052b", size = 4433796, upload-time = "2025-10-01T00:27:58.631Z" }, { url = "https://files.pythonhosted.org/packages/7d/d8/24392e5d3c58e2d83f98fe5a2322ae343360ec5b5b93fe18bc52e47298f5/cryptography-46.0.2-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:9ec3f2e2173f36a9679d3b06d3d01121ab9b57c979de1e6a244b98d51fea1b20", size = 4292126, upload-time = "2025-10-01T00:28:00.643Z" }, @@ -602,6 +692,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/eb/3c/9dfc778401a334db3b24435ee0733dd005aefb74afe036e2d154547cb917/cryptography-46.0.2-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:07c0eb6657c0e9cca5891f4e35081dbf985c8131825e21d99b4f440a8f496f36", size = 4464738, upload-time = "2025-10-01T00:28:12.491Z" }, { url = "https://files.pythonhosted.org/packages/dc/b1/abcde62072b8f3fd414e191a6238ce55a0050e9738090dc6cded24c12036/cryptography-46.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:48b983089378f50cba258f7f7aa28198c3f6e13e607eaf10472c26320332ca9a", size = 4419305, upload-time = "2025-10-01T00:28:14.145Z" }, { url = "https://files.pythonhosted.org/packages/c7/1f/3d2228492f9391395ca34c677e8f2571fb5370fe13dc48c1014f8c509864/cryptography-46.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e6f6775eaaa08c0eec73e301f7592f4367ccde5e4e4df8e58320f2ebf161ea2c", size = 4681201, upload-time = "2025-10-01T00:28:15.951Z" }, + { url = "https://files.pythonhosted.org/packages/de/77/b687745804a93a55054f391528fcfc76c3d6bfd082ce9fb62c12f0d29fc1/cryptography-46.0.2-cp314-cp314t-win32.whl", hash = "sha256:e8633996579961f9b5a3008683344c2558d38420029d3c0bc7ff77c17949a4e1", size = 3022492, upload-time = "2025-10-01T00:28:17.643Z" }, + { url = "https://files.pythonhosted.org/packages/60/a5/8d498ef2996e583de0bef1dcc5e70186376f00883ae27bf2133f490adf21/cryptography-46.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:48c01988ecbb32979bb98731f5c2b2f79042a6c58cc9a319c8c2f9987c7f68f9", size = 3496215, upload-time = "2025-10-01T00:28:19.272Z" }, + { url = "https://files.pythonhosted.org/packages/56/db/ee67aaef459a2706bc302b15889a1a8126ebe66877bab1487ae6ad00f33d/cryptography-46.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:8e2ad4d1a5899b7caa3a450e33ee2734be7cc0689010964703a7c4bcc8dd4fd0", size = 2919255, upload-time = "2025-10-01T00:28:21.115Z" }, + { url = "https://files.pythonhosted.org/packages/d5/bb/fa95abcf147a1b0bb94d95f53fbb09da77b24c776c5d87d36f3d94521d2c/cryptography-46.0.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a08e7401a94c002e79dc3bc5231b6558cd4b2280ee525c4673f650a37e2c7685", size = 7248090, upload-time = "2025-10-01T00:28:22.846Z" }, { url = "https://files.pythonhosted.org/packages/b7/66/f42071ce0e3ffbfa80a88feadb209c779fda92a23fbc1e14f74ebf72ef6b/cryptography-46.0.2-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d30bc11d35743bf4ddf76674a0a369ec8a21f87aaa09b0661b04c5f6c46e8d7b", size = 4293123, upload-time = "2025-10-01T00:28:25.072Z" }, { url = "https://files.pythonhosted.org/packages/a8/5d/1fdbd2e5c1ba822828d250e5a966622ef00185e476d1cd2726b6dd135e53/cryptography-46.0.2-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bca3f0ce67e5a2a2cf524e86f44697c4323a86e0fd7ba857de1c30d52c11ede1", size = 4439524, upload-time = "2025-10-01T00:28:26.808Z" }, { url = "https://files.pythonhosted.org/packages/c8/c1/5e4989a7d102d4306053770d60f978c7b6b1ea2ff8c06e0265e305b23516/cryptography-46.0.2-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ff798ad7a957a5021dcbab78dfff681f0cf15744d0e6af62bd6746984d9c9e9c", size = 4297264, upload-time = "2025-10-01T00:28:29.327Z" }, @@ -613,10 +707,17 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f6/9e/6507dc048c1b1530d372c483dfd34e7709fc542765015425f0442b08547f/cryptography-46.0.2-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:8b16c1ede6a937c291d41176934268e4ccac2c6521c69d3f5961c5a1e11e039e", size = 4471988, upload-time = "2025-10-01T00:28:41.822Z" }, { url = "https://files.pythonhosted.org/packages/b1/86/d025584a5f7d5c5ec8d3633dbcdce83a0cd579f1141ceada7817a4c26934/cryptography-46.0.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:747b6f4a4a23d5a215aadd1d0b12233b4119c4313df83ab4137631d43672cc90", size = 4422989, upload-time = "2025-10-01T00:28:43.608Z" }, { url = "https://files.pythonhosted.org/packages/4b/39/536370418b38a15a61bbe413006b79dfc3d2b4b0eafceb5581983f973c15/cryptography-46.0.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6b275e398ab3a7905e168c036aad54b5969d63d3d9099a0a66cc147a3cc983be", size = 4685578, upload-time = "2025-10-01T00:28:45.361Z" }, + { url = "https://files.pythonhosted.org/packages/15/52/ea7e2b1910f547baed566c866fbb86de2402e501a89ecb4871ea7f169a81/cryptography-46.0.2-cp38-abi3-win32.whl", hash = "sha256:0b507c8e033307e37af61cb9f7159b416173bdf5b41d11c4df2e499a1d8e007c", size = 3036711, upload-time = "2025-10-01T00:28:47.096Z" }, + { url = "https://files.pythonhosted.org/packages/71/9e/171f40f9c70a873e73c2efcdbe91e1d4b1777a03398fa1c4af3c56a2477a/cryptography-46.0.2-cp38-abi3-win_amd64.whl", hash = "sha256:f9b2dc7668418fb6f221e4bf701f716e05e8eadb4f1988a2487b11aedf8abe62", size = 3500007, upload-time = "2025-10-01T00:28:48.967Z" }, + { url = "https://files.pythonhosted.org/packages/3e/7c/15ad426257615f9be8caf7f97990cf3dcbb5b8dd7ed7e0db581a1c4759dd/cryptography-46.0.2-cp38-abi3-win_arm64.whl", hash = "sha256:91447f2b17e83c9e0c89f133119d83f94ce6e0fb55dd47da0a959316e6e9cfa1", size = 2918153, upload-time = "2025-10-01T00:28:51.003Z" }, + { url = "https://files.pythonhosted.org/packages/25/b2/067a7db693488f19777ecf73f925bcb6a3efa2eae42355bafaafa37a6588/cryptography-46.0.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f25a41f5b34b371a06dad3f01799706631331adc7d6c05253f5bca22068c7a34", size = 3701860, upload-time = "2025-10-01T00:28:53.003Z" }, + { url = "https://files.pythonhosted.org/packages/87/12/47c2aab2c285f97c71a791169529dbb89f48fc12e5f62bb6525c3927a1a2/cryptography-46.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e12b61e0b86611e3f4c1756686d9086c1d36e6fd15326f5658112ad1f1cc8807", size = 3429917, upload-time = "2025-10-01T00:28:55.03Z" }, + { url = "https://files.pythonhosted.org/packages/b7/8c/1aabe338149a7d0f52c3e30f2880b20027ca2a485316756ed6f000462db3/cryptography-46.0.2-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1d3b3edd145953832e09607986f2bd86f85d1dc9c48ced41808b18009d9f30e5", size = 3714495, upload-time = "2025-10-01T00:28:57.222Z" }, { url = "https://files.pythonhosted.org/packages/e3/0a/0d10eb970fe3e57da9e9ddcfd9464c76f42baf7b3d0db4a782d6746f788f/cryptography-46.0.2-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:fe245cf4a73c20592f0f48da39748b3513db114465be78f0a36da847221bd1b4", size = 4243379, upload-time = "2025-10-01T00:28:58.989Z" }, { url = "https://files.pythonhosted.org/packages/7d/60/e274b4d41a9eb82538b39950a74ef06e9e4d723cb998044635d9deb1b435/cryptography-46.0.2-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2b9cad9cf71d0c45566624ff76654e9bae5f8a25970c250a26ccfc73f8553e2d", size = 4409533, upload-time = "2025-10-01T00:29:00.785Z" }, { url = "https://files.pythonhosted.org/packages/19/9a/fb8548f762b4749aebd13b57b8f865de80258083fe814957f9b0619cfc56/cryptography-46.0.2-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:9bd26f2f75a925fdf5e0a446c0de2714f17819bf560b44b7480e4dd632ad6c46", size = 4243120, upload-time = "2025-10-01T00:29:02.515Z" }, { url = "https://files.pythonhosted.org/packages/71/60/883f24147fd4a0c5cab74ac7e36a1ff3094a54ba5c3a6253d2ff4b19255b/cryptography-46.0.2-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:7282d8f092b5be7172d6472f29b0631f39f18512a3642aefe52c3c0e0ccfad5a", size = 4408940, upload-time = "2025-10-01T00:29:04.42Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b5/c5e179772ec38adb1c072b3aa13937d2860509ba32b2462bf1dda153833b/cryptography-46.0.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c4b93af7920cdf80f71650769464ccf1fb49a4b56ae0024173c24c48eb6b1612", size = 3438518, upload-time = "2025-10-01T00:29:06.139Z" }, ] [[package]] @@ -641,6 +742,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, ] +[[package]] +name = "docstring-parser" +version = "0.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/9d/c3b43da9515bd270df0f80548d9944e389870713cc1fe2b8fb35fe2bcefd/docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", size = 27442, upload-time = "2025-07-21T07:35:01.868Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload-time = "2025-07-21T07:35:00.684Z" }, +] + [[package]] name = "docutils" version = "0.22.2" @@ -655,13 +765,28 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, ] +[[package]] +name = "fastapi" +version = "0.123.10" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/ff/e01087de891010089f1620c916c0c13130f3898177955c13e2b02d22ec4a/fastapi-0.123.10.tar.gz", hash = "sha256:624d384d7cda7c096449c889fc776a0571948ba14c3c929fa8e9a78cd0b0a6a8", size = 356360, upload-time = "2025-12-05T21:27:46.237Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/f0/7cb92c4a720def85240fd63fbbcf147ce19e7a731c8e1032376bb5a486ac/fastapi-0.123.10-py3-none-any.whl", hash = "sha256:0503b7b7bc71bc98f7c90c9117d21fdf6147c0d74703011b87936becc86985c1", size = 111774, upload-time = "2025-12-05T21:27:44.78Z" }, +] + [[package]] name = "fastuuid" version = "0.13.5" @@ -853,6 +978,498 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/71/70db47e4f6ce3e5c37a607355f80da8860a33226be640226ac52cb05ef2e/fsspec-2025.9.0-py3-none-any.whl", hash = "sha256:530dc2a2af60a414a832059574df4a6e10cce927f6f4a78209390fe38955cfb7", size = 199289, upload-time = "2025-09-02T19:10:47.708Z" }, ] +[[package]] +name = "google-adk" +version = "1.21.0" +source = { git = "https://github.com/marcusmotill/adk-python-temporal.git?rev=motill%2Fdurable-support#cc734162fe4f1e6604700399bf72cb3e7b7d4dc2" } +dependencies = [ + { name = "aiosqlite" }, + { name = "anyio" }, + { name = "authlib" }, + { name = "click" }, + { name = "fastapi" }, + { name = "google-api-python-client" }, + { name = "google-cloud-aiplatform", extra = ["agent-engines"] }, + { name = "google-cloud-bigquery" }, + { name = "google-cloud-bigquery-storage" }, + { name = "google-cloud-bigtable" }, + { name = "google-cloud-discoveryengine" }, + { name = "google-cloud-secret-manager" }, + { name = "google-cloud-spanner" }, + { name = "google-cloud-speech" }, + { name = "google-cloud-storage" }, + { name = "google-genai" }, + { name = "graphviz" }, + { name = "jsonschema" }, + { name = "mcp" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-gcp-logging" }, + { name = "opentelemetry-exporter-gcp-monitoring" }, + { name = "opentelemetry-exporter-gcp-trace" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, + { name = "opentelemetry-resourcedetector-gcp" }, + { name = "opentelemetry-sdk" }, + { name = "pyarrow" }, + { name = "pydantic" }, + { name = "python-dateutil" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "sqlalchemy" }, + { name = "sqlalchemy-spanner" }, + { name = "starlette" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "tzlocal" }, + { name = "uvicorn" }, + { name = "watchdog" }, + { name = "websockets" }, +] + +[[package]] +name = "google-api-core" +version = "2.29.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-auth" }, + { name = "googleapis-common-protos" }, + { name = "proto-plus" }, + { name = "protobuf" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0d/10/05572d33273292bac49c2d1785925f7bc3ff2fe50e3044cf1062c1dde32e/google_api_core-2.29.0.tar.gz", hash = "sha256:84181be0f8e6b04006df75ddfe728f24489f0af57c96a529ff7cf45bc28797f7", size = 177828, upload-time = "2026-01-08T22:21:39.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/b6/85c4d21067220b9a78cfb81f516f9725ea6befc1544ec9bd2c1acd97c324/google_api_core-2.29.0-py3-none-any.whl", hash = "sha256:d30bc60980daa36e314b5d5a3e5958b0200cb44ca8fa1be2b614e932b75a3ea9", size = 173906, upload-time = "2026-01-08T22:21:36.093Z" }, +] + +[package.optional-dependencies] +grpc = [ + { name = "grpcio" }, + { name = "grpcio-status" }, +] + +[[package]] +name = "google-api-python-client" +version = "2.188.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core" }, + { name = "google-auth" }, + { name = "google-auth-httplib2" }, + { name = "httplib2" }, + { name = "uritemplate" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/d7/14613c7efbab5b428b400961f5dbac46ad9e019c44e1f3fd14d67c33111c/google_api_python_client-2.188.0.tar.gz", hash = "sha256:5c469db6614f071009e3e5bb8b6aeeccae3beb3647fa9c6cd97f0d551edde0b6", size = 14302906, upload-time = "2026-01-13T22:15:13.747Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/67/a99a7d79d7a37a67cb8008f1d7dcedc46d29c6df5063aeb446112afd4aa4/google_api_python_client-2.188.0-py3-none-any.whl", hash = "sha256:3cad1b68f9d48b82b93d77927e8370a6f43f33d97848242601f14a93a1c70ef5", size = 14870005, upload-time = "2026-01-13T22:15:11.345Z" }, +] + +[[package]] +name = "google-auth" +version = "2.47.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1-modules" }, + { name = "rsa" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/3c/ec64b9a275ca22fa1cd3b6e77fefcf837b0732c890aa32d2bd21313d9b33/google_auth-2.47.0.tar.gz", hash = "sha256:833229070a9dfee1a353ae9877dcd2dec069a8281a4e72e72f77d4a70ff945da", size = 323719, upload-time = "2026-01-06T21:55:31.045Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/18/79e9008530b79527e0d5f79e7eef08d3b179b7f851cfd3a2f27822fbdfa9/google_auth-2.47.0-py3-none-any.whl", hash = "sha256:c516d68336bfde7cf0da26aab674a36fedcf04b37ac4edd59c597178760c3498", size = 234867, upload-time = "2026-01-06T21:55:28.6Z" }, +] + +[package.optional-dependencies] +requests = [ + { name = "requests" }, +] + +[[package]] +name = "google-auth-httplib2" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-auth" }, + { name = "httplib2" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d5/ad/c1f2b1175096a8d04cf202ad5ea6065f108d26be6fc7215876bde4a7981d/google_auth_httplib2-0.3.0.tar.gz", hash = "sha256:177898a0175252480d5ed916aeea183c2df87c1f9c26705d74ae6b951c268b0b", size = 11134, upload-time = "2025-12-15T22:13:51.825Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/d5/3c97526c8796d3caf5f4b3bed2b05e8a7102326f00a334e7a438237f3b22/google_auth_httplib2-0.3.0-py3-none-any.whl", hash = "sha256:426167e5df066e3f5a0fc7ea18768c08e7296046594ce4c8c409c2457dd1f776", size = 9529, upload-time = "2025-12-15T22:13:51.048Z" }, +] + +[[package]] +name = "google-cloud-aiplatform" +version = "1.134.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "docstring-parser" }, + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "google-cloud-bigquery" }, + { name = "google-cloud-resource-manager" }, + { name = "google-cloud-storage" }, + { name = "google-genai" }, + { name = "packaging" }, + { name = "proto-plus" }, + { name = "protobuf" }, + { name = "pydantic" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d3/24/de4f21d0728d640b57bf7bbcd7460827a4daf9eaca61cb5b91be608c40bc/google_cloud_aiplatform-1.134.0.tar.gz", hash = "sha256:964cea117ca1ffc71742970e1091985adac72dfe76e1a1614a02a8cda50d6992", size = 9931075, upload-time = "2026-01-20T19:19:58.867Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/f4/6863f3951eb07afd790fe6f8f1a5984224f7df836546a34ed29ab0cfe9af/google_cloud_aiplatform-1.134.0-py2.py3-none-any.whl", hash = "sha256:f249ae67d622deca486310e0021093764892ac357fb744b9e79548f490017ddc", size = 8189190, upload-time = "2026-01-20T19:19:55.997Z" }, +] + +[package.optional-dependencies] +agent-engines = [ + { name = "cloudpickle" }, + { name = "google-cloud-iam" }, + { name = "google-cloud-logging" }, + { name = "google-cloud-trace" }, + { name = "opentelemetry-exporter-gcp-logging" }, + { name = "opentelemetry-exporter-gcp-trace" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, + { name = "opentelemetry-sdk" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "typing-extensions" }, +] + +[[package]] +name = "google-cloud-appengine-logging" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "grpcio" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/65/38/89317773c64b5a7e9b56b9aecb2e39ac02d8d6d09fb5b276710c6892e690/google_cloud_appengine_logging-1.8.0.tar.gz", hash = "sha256:84b705a69e4109fc2f68dfe36ce3df6a34d5c3d989eee6d0ac1b024dda0ba6f5", size = 18071, upload-time = "2026-01-15T13:14:40.024Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/66/4a9be8afb1d0bf49472478cec20fefe4f4cb3a6e67be2231f097041e7339/google_cloud_appengine_logging-1.8.0-py3-none-any.whl", hash = "sha256:a4ce9ce94a9fd8c89ed07fa0b06fcf9ea3642f9532a1be1a8c7b5f82c0a70ec6", size = 18380, upload-time = "2026-01-09T14:52:58.154Z" }, +] + +[[package]] +name = "google-cloud-audit-log" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/d2/ad96950410f8a05e921a6da2e1a6ba4aeca674bbb5dda8200c3c7296d7ad/google_cloud_audit_log-0.4.0.tar.gz", hash = "sha256:8467d4dcca9f3e6160520c24d71592e49e874838f174762272ec10e7950b6feb", size = 44682, upload-time = "2025-10-17T02:33:44.641Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/25/532886995f11102ad6de290496de5db227bd3a73827702445928ad32edcb/google_cloud_audit_log-0.4.0-py3-none-any.whl", hash = "sha256:6b88e2349df45f8f4cc0993b687109b1388da1571c502dc1417efa4b66ec55e0", size = 44890, upload-time = "2025-10-17T02:30:55.11Z" }, +] + +[[package]] +name = "google-cloud-bigquery" +version = "3.40.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "google-cloud-core" }, + { name = "google-resumable-media" }, + { name = "packaging" }, + { name = "python-dateutil" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/94/0a/62438ca138a095945468968696d9cca75a4cfd059e810402e70b0236d8ba/google_cloud_bigquery-3.40.0.tar.gz", hash = "sha256:b3ccb11caf0029f15b29569518f667553fe08f6f1459b959020c83fbbd8f2e68", size = 509287, upload-time = "2026-01-08T01:07:26.065Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/6a/90a04270dd60cc70259b73744f6e610ae9a158b21ab50fb695cca0056a3d/google_cloud_bigquery-3.40.0-py3-none-any.whl", hash = "sha256:0469bcf9e3dad3cab65b67cce98180c8c0aacf3253d47f0f8e976f299b49b5ab", size = 261335, upload-time = "2026-01-08T01:07:23.761Z" }, +] + +[[package]] +name = "google-cloud-bigquery-storage" +version = "2.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "grpcio" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cf/72/b5dbf3487ea320a87c6d1ba8bb7680fafdb3147343a06d928b4209abcdba/google_cloud_bigquery_storage-2.36.0.tar.gz", hash = "sha256:d3c1ce9d2d3a4d7116259889dcbe3c7c70506f71f6ce6bbe54aa0a68bbba8f8f", size = 306959, upload-time = "2025-12-18T18:01:45.916Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/50/70e4bc2d52b52145b6e70008fbf806cef850e809dd3e30b4493d91c069ea/google_cloud_bigquery_storage-2.36.0-py3-none-any.whl", hash = "sha256:1769e568070db672302771d2aec18341de10712aa9c4a8c549f417503e0149f0", size = 303731, upload-time = "2025-12-18T18:01:44.598Z" }, +] + +[[package]] +name = "google-cloud-bigtable" +version = "2.35.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "google-cloud-core" }, + { name = "google-crc32c" }, + { name = "grpc-google-iam-v1" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/c9/aceae21411b1a77fb4d3cde6e6f461321ee33c65fb8dc53480d4e47e1a55/google_cloud_bigtable-2.35.0.tar.gz", hash = "sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b", size = 775613, upload-time = "2025-12-17T15:18:14.303Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/69/03eed134d71f6117ffd9efac2d1033bb2fa2522e9e82545a0828061d32f4/google_cloud_bigtable-2.35.0-py3-none-any.whl", hash = "sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50", size = 540341, upload-time = "2025-12-17T15:18:12.176Z" }, +] + +[[package]] +name = "google-cloud-core" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core" }, + { name = "google-auth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a6/03/ef0bc99d0e0faf4fdbe67ac445e18cdaa74824fd93cd069e7bb6548cb52d/google_cloud_core-2.5.0.tar.gz", hash = "sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963", size = 36027, upload-time = "2025-10-29T23:17:39.513Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/20/bfa472e327c8edee00f04beecc80baeddd2ab33ee0e86fd7654da49d45e9/google_cloud_core-2.5.0-py3-none-any.whl", hash = "sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc", size = 29469, upload-time = "2025-10-29T23:17:38.548Z" }, +] + +[[package]] +name = "google-cloud-discoveryengine" +version = "0.13.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8f/cd/b33bbc4b096d937abee5ebfad3908b2bdc65acd1582191aa33beaa2b70a5/google_cloud_discoveryengine-0.13.12.tar.gz", hash = "sha256:d6b9f8fadd8ad0d2f4438231c5eb7772a317e9f59cafbcbadc19b5d54c609419", size = 3582382, upload-time = "2025-09-22T16:51:14.052Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/70/607f6011648f603d35e60a16c34aee68a0b39510e4268d4859f3268684f9/google_cloud_discoveryengine-0.13.12-py3-none-any.whl", hash = "sha256:295f8c6df3fb26b90fb82c2cd6fbcf4b477661addcb19a94eea16463a5c4e041", size = 3337248, upload-time = "2025-09-22T16:50:57.375Z" }, +] + +[[package]] +name = "google-cloud-iam" +version = "2.21.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "grpc-google-iam-v1" }, + { name = "grpcio" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/aa/0b/037b1e1eb601646d6f49bc06d62094c1d0996b373dcbf70c426c6c51572e/google_cloud_iam-2.21.0.tar.gz", hash = "sha256:fc560527e22b97c6cbfba0797d867cf956c727ba687b586b9aa44d78e92281a3", size = 499038, upload-time = "2026-01-15T13:15:08.243Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/44/02ac4e147ea034a3d641c11b54c9d8d0b80fc1ea6a8b7d6c1588d208d42a/google_cloud_iam-2.21.0-py3-none-any.whl", hash = "sha256:1b4a21302b186a31f3a516ccff303779638308b7c801fb61a2406b6a0c6293c4", size = 458958, upload-time = "2026-01-15T13:13:40.671Z" }, +] + +[[package]] +name = "google-cloud-logging" +version = "3.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "google-cloud-appengine-logging" }, + { name = "google-cloud-audit-log" }, + { name = "google-cloud-core" }, + { name = "grpc-google-iam-v1" }, + { name = "opentelemetry-api" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7f/47/31ef0261802fe8b37c221392e1d6ff01d30b03dce5e20e77fc7d57ddf8a3/google_cloud_logging-3.13.0.tar.gz", hash = "sha256:3aae0573b1a1a4f59ecdf4571f4e7881b5823bd129fe469561c1c49a7fa8a4c1", size = 290169, upload-time = "2025-12-16T14:11:07.345Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/5a/778dca2e375171af4085554cb3bc643627717a7e4e1539842ced3afd6ec4/google_cloud_logging-3.13.0-py3-none-any.whl", hash = "sha256:f215e1c76ee29239c6cacf02443dffa985663c74bf47c9818854694805c6019f", size = 230518, upload-time = "2025-12-16T14:11:05.894Z" }, +] + +[[package]] +name = "google-cloud-monitoring" +version = "2.29.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "grpcio" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/a1/a1a0c678569f2a7b1fa65ef71ff528650231a298fc2b89ad49c9991eab94/google_cloud_monitoring-2.29.0.tar.gz", hash = "sha256:eedb8afd1c4e80e8c62435f05c448e9e65be907250a66d81e6af5909778267b6", size = 404769, upload-time = "2026-01-15T13:04:01.597Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/63/b1f6e86ddde8548a0cade2edf3c8ec2183e57f002ea4301b3890a6717190/google_cloud_monitoring-2.29.0-py3-none-any.whl", hash = "sha256:93aa264da0f57f3de2900b0250a37ca27068984f6d94e54175d27aea12a4637f", size = 387988, upload-time = "2026-01-15T13:03:23.528Z" }, +] + +[[package]] +name = "google-cloud-resource-manager" +version = "1.16.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "grpc-google-iam-v1" }, + { name = "grpcio" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4e/7f/db00b2820475793a52958dc55fe9ec2eb8e863546e05fcece9b921f86ebe/google_cloud_resource_manager-1.16.0.tar.gz", hash = "sha256:cc938f87cc36c2672f062b1e541650629e0d954c405a4dac35ceedee70c267c3", size = 459840, upload-time = "2026-01-15T13:04:07.726Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/ff/4b28bcc791d9d7e4ac8fea00fbd90ccb236afda56746a3b4564d2ae45df3/google_cloud_resource_manager-1.16.0-py3-none-any.whl", hash = "sha256:fb9a2ad2b5053c508e1c407ac31abfd1a22e91c32876c1892830724195819a28", size = 400218, upload-time = "2026-01-15T13:02:47.378Z" }, +] + +[[package]] +name = "google-cloud-secret-manager" +version = "2.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "grpc-google-iam-v1" }, + { name = "grpcio" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/9c/a6c7144bc96df77376ae3fcc916fb639c40814c2e4bba2051d31dc136cd0/google_cloud_secret_manager-2.26.0.tar.gz", hash = "sha256:0d1d6f76327685a0ed78a4cf50f289e1bfbbe56026ed0affa98663b86d6d50d6", size = 277603, upload-time = "2025-12-18T00:29:31.065Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/30/a58739dd12cec0f7f761ed1efb518aed2250a407d4ed14c5a0eeee7eaaf9/google_cloud_secret_manager-2.26.0-py3-none-any.whl", hash = "sha256:940a5447a6ec9951446fd1a0f22c81a4303fde164cd747aae152c5f5c8e6723e", size = 223623, upload-time = "2025-12-18T00:29:29.311Z" }, +] + +[[package]] +name = "google-cloud-spanner" +version = "3.62.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-cloud-core" }, + { name = "google-cloud-monitoring" }, + { name = "grpc-google-iam-v1" }, + { name = "grpc-interceptor" }, + { name = "mmh3" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-resourcedetector-gcp" }, + { name = "opentelemetry-sdk" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "proto-plus" }, + { name = "protobuf" }, + { name = "sqlparse" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d4/80/86e152f887cdddab5b8268c93d18c671a3653545be2ea2babab6b6ad635f/google_cloud_spanner-3.62.0.tar.gz", hash = "sha256:a25bdbfda84bc7a819f04e45473187d8670711fd5ec827cf442e3664661d1d23", size = 722967, upload-time = "2026-01-16T06:33:29.462Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/a3/27c0af7f4350757f449e601733d960fc6e2717fa25d3d826ad29b694de68/google_cloud_spanner-3.62.0-py3-none-any.whl", hash = "sha256:b59d7b731463ce998439c1998730760e36f3d699510608d896f2ca8bc57613a9", size = 516156, upload-time = "2026-01-16T06:33:28.173Z" }, +] + +[[package]] +name = "google-cloud-speech" +version = "2.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "grpcio" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/01/0bfe56e1f935285ac21908ddfb5574b09bf5829ad3441649e1403f9f1b34/google_cloud_speech-2.36.0.tar.gz", hash = "sha256:3a445a033cc7772f7d073c03142a7e80048415db42981372c6b81edc76a1e27a", size = 401922, upload-time = "2026-01-15T13:04:52.77Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/0e/29e5d7bfe636e7b7b2647d6f4d50ca07b84149ba9adba86c6be219ac8480/google_cloud_speech-2.36.0-py3-none-any.whl", hash = "sha256:bdd0047fe2961d42307bdb7393fe5c7c1491290b2e6d66bfc6e2b7bcdfb8794e", size = 342111, upload-time = "2026-01-15T13:02:59.482Z" }, +] + +[[package]] +name = "google-cloud-storage" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core" }, + { name = "google-auth" }, + { name = "google-cloud-core" }, + { name = "google-crc32c" }, + { name = "google-resumable-media" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/90/4398cecc2704cb066bc7dee6111a5c93c59bcd6fb751f0541315655774a8/google_cloud_storage-3.8.0.tar.gz", hash = "sha256:cc67952dce84ebc9d44970e24647a58260630b7b64d72360cedaf422d6727f28", size = 17273792, upload-time = "2026-01-14T00:45:31.289Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/db/326279870d349fb9592263343dca4ad76088c17c88ba97b0f64c1088276c/google_cloud_storage-3.8.0-py3-none-any.whl", hash = "sha256:78cfeae7cac2ca9441d0d0271c2eb4ebfa21aa4c6944dd0ccac0389e81d955a7", size = 312430, upload-time = "2026-01-14T00:45:28.689Z" }, +] + +[[package]] +name = "google-cloud-trace" +version = "1.18.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "grpcio" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/34/b1883f4682f1681941100df0e411cb0185013f7c349489ab1330348d7c5c/google_cloud_trace-1.18.0.tar.gz", hash = "sha256:46d42b90273da3bc4850bb0d6b9a205eb826a54561ff1b30ca33cc92174c3f37", size = 103347, upload-time = "2026-01-15T13:04:56.441Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/15/366fd8b028a50a9018c933270d220a4e53dca8022ce9086618b72978ab90/google_cloud_trace-1.18.0-py3-none-any.whl", hash = "sha256:52c002d8d3da802e031fee62cd49a1baf899932d4f548a150f685af6815b5554", size = 107488, upload-time = "2026-01-15T12:17:21.519Z" }, +] + +[[package]] +name = "google-crc32c" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/03/41/4b9c02f99e4c5fb477122cd5437403b552873f014616ac1d19ac8221a58d/google_crc32c-1.8.0.tar.gz", hash = "sha256:a428e25fb7691024de47fecfbff7ff957214da51eddded0da0ae0e0f03a2cf79", size = 14192, upload-time = "2025-12-16T00:35:25.142Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/ac/6f7bc93886a823ab545948c2dd48143027b2355ad1944c7cf852b338dc91/google_crc32c-1.8.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:0470b8c3d73b5f4e3300165498e4cf25221c7eb37f1159e221d1825b6df8a7ff", size = 31296, upload-time = "2025-12-16T00:19:07.261Z" }, + { url = "https://files.pythonhosted.org/packages/f7/97/a5accde175dee985311d949cfcb1249dcbb290f5ec83c994ea733311948f/google_crc32c-1.8.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:119fcd90c57c89f30040b47c211acee231b25a45d225e3225294386f5d258288", size = 30870, upload-time = "2025-12-16T00:29:17.669Z" }, + { url = "https://files.pythonhosted.org/packages/3d/63/bec827e70b7a0d4094e7476f863c0dbd6b5f0f1f91d9c9b32b76dcdfeb4e/google_crc32c-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6f35aaffc8ccd81ba3162443fabb920e65b1f20ab1952a31b13173a67811467d", size = 33214, upload-time = "2025-12-16T00:40:19.618Z" }, + { url = "https://files.pythonhosted.org/packages/63/bc/11b70614df04c289128d782efc084b9035ef8466b3d0a8757c1b6f5cf7ac/google_crc32c-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:864abafe7d6e2c4c66395c1eb0fe12dc891879769b52a3d56499612ca93b6092", size = 33589, upload-time = "2025-12-16T00:40:20.7Z" }, + { url = "https://files.pythonhosted.org/packages/3e/00/a08a4bc24f1261cc5b0f47312d8aebfbe4b53c2e6307f1b595605eed246b/google_crc32c-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:db3fe8eaf0612fc8b20fa21a5f25bd785bc3cd5be69f8f3412b0ac2ffd49e733", size = 34437, upload-time = "2025-12-16T00:35:19.437Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ef/21ccfaab3d5078d41efe8612e0ed0bfc9ce22475de074162a91a25f7980d/google_crc32c-1.8.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:014a7e68d623e9a4222d663931febc3033c5c7c9730785727de2a81f87d5bab8", size = 31298, upload-time = "2025-12-16T00:20:32.241Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b8/f8413d3f4b676136e965e764ceedec904fe38ae8de0cdc52a12d8eb1096e/google_crc32c-1.8.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:86cfc00fe45a0ac7359e5214a1704e51a99e757d0272554874f419f79838c5f7", size = 30872, upload-time = "2025-12-16T00:33:58.785Z" }, + { url = "https://files.pythonhosted.org/packages/f6/fd/33aa4ec62b290477181c55bb1c9302c9698c58c0ce9a6ab4874abc8b0d60/google_crc32c-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:19b40d637a54cb71e0829179f6cb41835f0fbd9e8eb60552152a8b52c36cbe15", size = 33243, upload-time = "2025-12-16T00:40:21.46Z" }, + { url = "https://files.pythonhosted.org/packages/71/03/4820b3bd99c9653d1a5210cb32f9ba4da9681619b4d35b6a052432df4773/google_crc32c-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:17446feb05abddc187e5441a45971b8394ea4c1b6efd88ab0af393fd9e0a156a", size = 33608, upload-time = "2025-12-16T00:40:22.204Z" }, + { url = "https://files.pythonhosted.org/packages/7c/43/acf61476a11437bf9733fb2f70599b1ced11ec7ed9ea760fdd9a77d0c619/google_crc32c-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:71734788a88f551fbd6a97be9668a0020698e07b2bf5b3aa26a36c10cdfb27b2", size = 34439, upload-time = "2025-12-16T00:35:20.458Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5f/7307325b1198b59324c0fa9807cafb551afb65e831699f2ce211ad5c8240/google_crc32c-1.8.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:4b8286b659c1335172e39563ab0a768b8015e88e08329fa5321f774275fc3113", size = 31300, upload-time = "2025-12-16T00:21:56.723Z" }, + { url = "https://files.pythonhosted.org/packages/21/8e/58c0d5d86e2220e6a37befe7e6a94dd2f6006044b1a33edf1ff6d9f7e319/google_crc32c-1.8.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:2a3dc3318507de089c5384cc74d54318401410f82aa65b2d9cdde9d297aca7cb", size = 30867, upload-time = "2025-12-16T00:38:31.302Z" }, + { url = "https://files.pythonhosted.org/packages/ce/a9/a780cc66f86335a6019f557a8aaca8fbb970728f0efd2430d15ff1beae0e/google_crc32c-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:14f87e04d613dfa218d6135e81b78272c3b904e2a7053b841481b38a7d901411", size = 33364, upload-time = "2025-12-16T00:40:22.96Z" }, + { url = "https://files.pythonhosted.org/packages/21/3f/3457ea803db0198c9aaca2dd373750972ce28a26f00544b6b85088811939/google_crc32c-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb5c869c2923d56cb0c8e6bcdd73c009c36ae39b652dbe46a05eb4ef0ad01454", size = 33740, upload-time = "2025-12-16T00:40:23.96Z" }, + { url = "https://files.pythonhosted.org/packages/df/c0/87c2073e0c72515bb8733d4eef7b21548e8d189f094b5dad20b0ecaf64f6/google_crc32c-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:3cc0c8912038065eafa603b238abf252e204accab2a704c63b9e14837a854962", size = 34437, upload-time = "2025-12-16T00:35:21.395Z" }, + { url = "https://files.pythonhosted.org/packages/d1/db/000f15b41724589b0e7bc24bc7a8967898d8d3bc8caf64c513d91ef1f6c0/google_crc32c-1.8.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:3ebb04528e83b2634857f43f9bb8ef5b2bbe7f10f140daeb01b58f972d04736b", size = 31297, upload-time = "2025-12-16T00:23:20.709Z" }, + { url = "https://files.pythonhosted.org/packages/d7/0d/8ebed0c39c53a7e838e2a486da8abb0e52de135f1b376ae2f0b160eb4c1a/google_crc32c-1.8.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:450dc98429d3e33ed2926fc99ee81001928d63460f8538f21a5d6060912a8e27", size = 30867, upload-time = "2025-12-16T00:43:14.628Z" }, + { url = "https://files.pythonhosted.org/packages/ce/42/b468aec74a0354b34c8cbf748db20d6e350a68a2b0912e128cabee49806c/google_crc32c-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3b9776774b24ba76831609ffbabce8cdf6fa2bd5e9df37b594221c7e333a81fa", size = 33344, upload-time = "2025-12-16T00:40:24.742Z" }, + { url = "https://files.pythonhosted.org/packages/1c/e8/b33784d6fc77fb5062a8a7854e43e1e618b87d5ddf610a88025e4de6226e/google_crc32c-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:89c17d53d75562edfff86679244830599ee0a48efc216200691de8b02ab6b2b8", size = 33694, upload-time = "2025-12-16T00:40:25.505Z" }, + { url = "https://files.pythonhosted.org/packages/92/b1/d3cbd4d988afb3d8e4db94ca953df429ed6db7282ed0e700d25e6c7bfc8d/google_crc32c-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:57a50a9035b75643996fbf224d6661e386c7162d1dfdab9bc4ca790947d1007f", size = 34435, upload-time = "2025-12-16T00:35:22.107Z" }, + { url = "https://files.pythonhosted.org/packages/21/88/8ecf3c2b864a490b9e7010c84fd203ec8cf3b280651106a3a74dd1b0ca72/google_crc32c-1.8.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:e6584b12cb06796d285d09e33f63309a09368b9d806a551d8036a4207ea43697", size = 31301, upload-time = "2025-12-16T00:24:48.527Z" }, + { url = "https://files.pythonhosted.org/packages/36/c6/f7ff6c11f5ca215d9f43d3629163727a272eabc356e5c9b2853df2bfe965/google_crc32c-1.8.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:f4b51844ef67d6cf2e9425983274da75f18b1597bb2c998e1c0a0e8d46f8f651", size = 30868, upload-time = "2025-12-16T00:48:12.163Z" }, + { url = "https://files.pythonhosted.org/packages/56/15/c25671c7aad70f8179d858c55a6ae8404902abe0cdcf32a29d581792b491/google_crc32c-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b0d1a7afc6e8e4635564ba8aa5c0548e3173e41b6384d7711a9123165f582de2", size = 33381, upload-time = "2025-12-16T00:40:26.268Z" }, + { url = "https://files.pythonhosted.org/packages/42/fa/f50f51260d7b0ef5d4898af122d8a7ec5a84e2984f676f746445f783705f/google_crc32c-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b3f68782f3cbd1bce027e48768293072813469af6a61a86f6bb4977a4380f21", size = 33734, upload-time = "2025-12-16T00:40:27.028Z" }, + { url = "https://files.pythonhosted.org/packages/08/a5/7b059810934a09fb3ccb657e0843813c1fee1183d3bc2c8041800374aa2c/google_crc32c-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:d511b3153e7011a27ab6ee6bb3a5404a55b994dc1a7322c0b87b29606d9790e2", size = 34878, upload-time = "2025-12-16T00:35:23.142Z" }, + { url = "https://files.pythonhosted.org/packages/52/c5/c171e4d8c44fec1422d801a6d2e5d7ddabd733eeda505c79730ee9607f07/google_crc32c-1.8.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:87fa445064e7db928226b2e6f0d5304ab4cd0339e664a4e9a25029f384d9bb93", size = 28615, upload-time = "2025-12-16T00:40:29.298Z" }, + { url = "https://files.pythonhosted.org/packages/9c/97/7d75fe37a7a6ed171a2cf17117177e7aab7e6e0d115858741b41e9dd4254/google_crc32c-1.8.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f639065ea2042d5c034bf258a9f085eaa7af0cd250667c0635a3118e8f92c69c", size = 28800, upload-time = "2025-12-16T00:40:30.322Z" }, +] + +[[package]] +name = "google-genai" +version = "1.60.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "google-auth", extra = ["requests"] }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "sniffio" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0a/3f/a753be0dcee352b7d63bc6d1ba14a72591d63b6391dac0cdff7ac168c530/google_genai-1.60.0.tar.gz", hash = "sha256:9768061775fddfaecfefb0d6d7a6cabefb3952ebd246cd5f65247151c07d33d1", size = 487721, upload-time = "2026-01-21T22:17:30.398Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/e5/384b1f383917b5f0ae92e28f47bc27b16e3d26cd9bacb25e9f8ecab3c8fe/google_genai-1.60.0-py3-none-any.whl", hash = "sha256:967338378ffecebec19a8ed90cf8797b26818bacbefd7846a9280beb1099f7f3", size = 719431, upload-time = "2026-01-21T22:17:28.086Z" }, +] + +[[package]] +name = "google-resumable-media" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-crc32c" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/64/d7/520b62a35b23038ff005e334dba3ffc75fcf583bee26723f1fd8fd4b6919/google_resumable_media-2.8.0.tar.gz", hash = "sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae", size = 2163265, upload-time = "2025-11-17T15:38:06.659Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/0b/93afde9cfe012260e9fe1522f35c9b72d6ee222f316586b1f23ecf44d518/google_resumable_media-2.8.0-py3-none-any.whl", hash = "sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582", size = 81340, upload-time = "2025-11-17T15:38:05.594Z" }, +] + [[package]] name = "googleapis-common-protos" version = "1.70.0" @@ -865,6 +1482,75 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/86/f1/62a193f0227cf15a920390abe675f386dec35f7ae3ffe6da582d3ade42c7/googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8", size = 294530, upload-time = "2025-04-14T10:17:01.271Z" }, ] +[package.optional-dependencies] +grpc = [ + { name = "grpcio" }, +] + +[[package]] +name = "graphviz" +version = "0.21" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b3/3ac91e9be6b761a4b30d66ff165e54439dcd48b83f4e20d644867215f6ca/graphviz-0.21.tar.gz", hash = "sha256:20743e7183be82aaaa8ad6c93f8893c923bd6658a04c32ee115edb3c8a835f78", size = 200434, upload-time = "2025-06-15T09:35:05.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl", hash = "sha256:54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42", size = 47300, upload-time = "2025-06-15T09:35:04.433Z" }, +] + +[[package]] +name = "greenlet" +version = "3.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/e5/40dbda2736893e3e53d25838e0f19a2b417dfc122b9989c91918db30b5d3/greenlet-3.3.0.tar.gz", hash = "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb", size = 190651, upload-time = "2025-12-04T14:49:44.05Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/6a/33d1702184d94106d3cdd7bfb788e19723206fce152e303473ca3b946c7b/greenlet-3.3.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:6f8496d434d5cb2dce025773ba5597f71f5410ae499d5dd9533e0653258cdb3d", size = 273658, upload-time = "2025-12-04T14:23:37.494Z" }, + { url = "https://files.pythonhosted.org/packages/d6/b7/2b5805bbf1907c26e434f4e448cd8b696a0b71725204fa21a211ff0c04a7/greenlet-3.3.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b96dc7eef78fd404e022e165ec55327f935b9b52ff355b067eb4a0267fc1cffb", size = 574810, upload-time = "2025-12-04T14:50:04.154Z" }, + { url = "https://files.pythonhosted.org/packages/94/38/343242ec12eddf3d8458c73f555c084359883d4ddc674240d9e61ec51fd6/greenlet-3.3.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73631cd5cccbcfe63e3f9492aaa664d278fda0ce5c3d43aeda8e77317e38efbd", size = 586248, upload-time = "2025-12-04T14:57:39.35Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d0/0ae86792fb212e4384041e0ef8e7bc66f59a54912ce407d26a966ed2914d/greenlet-3.3.0-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b299a0cb979f5d7197442dccc3aee67fce53500cd88951b7e6c35575701c980b", size = 597403, upload-time = "2025-12-04T15:07:10.831Z" }, + { url = "https://files.pythonhosted.org/packages/b6/a8/15d0aa26c0036a15d2659175af00954aaaa5d0d66ba538345bd88013b4d7/greenlet-3.3.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7dee147740789a4632cace364816046e43310b59ff8fb79833ab043aefa72fd5", size = 586910, upload-time = "2025-12-04T14:25:59.705Z" }, + { url = "https://files.pythonhosted.org/packages/e1/9b/68d5e3b7ccaba3907e5532cf8b9bf16f9ef5056a008f195a367db0ff32db/greenlet-3.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:39b28e339fc3c348427560494e28d8a6f3561c8d2bcf7d706e1c624ed8d822b9", size = 1547206, upload-time = "2025-12-04T15:04:21.027Z" }, + { url = "https://files.pythonhosted.org/packages/66/bd/e3086ccedc61e49f91e2cfb5ffad9d8d62e5dc85e512a6200f096875b60c/greenlet-3.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b3c374782c2935cc63b2a27ba8708471de4ad1abaa862ffdb1ef45a643ddbb7d", size = 1613359, upload-time = "2025-12-04T14:27:26.548Z" }, + { url = "https://files.pythonhosted.org/packages/f4/6b/d4e73f5dfa888364bbf02efa85616c6714ae7c631c201349782e5b428925/greenlet-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:b49e7ed51876b459bd645d83db257f0180e345d3f768a35a85437a24d5a49082", size = 300740, upload-time = "2025-12-04T14:47:52.773Z" }, + { url = "https://files.pythonhosted.org/packages/1f/cb/48e964c452ca2b92175a9b2dca037a553036cb053ba69e284650ce755f13/greenlet-3.3.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e29f3018580e8412d6aaf5641bb7745d38c85228dacf51a73bd4e26ddf2a6a8e", size = 274908, upload-time = "2025-12-04T14:23:26.435Z" }, + { url = "https://files.pythonhosted.org/packages/28/da/38d7bff4d0277b594ec557f479d65272a893f1f2a716cad91efeb8680953/greenlet-3.3.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a687205fb22794e838f947e2194c0566d3812966b41c78709554aa883183fb62", size = 577113, upload-time = "2025-12-04T14:50:05.493Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f2/89c5eb0faddc3ff014f1c04467d67dee0d1d334ab81fadbf3744847f8a8a/greenlet-3.3.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4243050a88ba61842186cb9e63c7dfa677ec146160b0efd73b855a3d9c7fcf32", size = 590338, upload-time = "2025-12-04T14:57:41.136Z" }, + { url = "https://files.pythonhosted.org/packages/80/d7/db0a5085035d05134f8c089643da2b44cc9b80647c39e93129c5ef170d8f/greenlet-3.3.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:670d0f94cd302d81796e37299bcd04b95d62403883b24225c6b5271466612f45", size = 601098, upload-time = "2025-12-04T15:07:11.898Z" }, + { url = "https://files.pythonhosted.org/packages/dc/a6/e959a127b630a58e23529972dbc868c107f9d583b5a9f878fb858c46bc1a/greenlet-3.3.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cb3a8ec3db4a3b0eb8a3c25436c2d49e3505821802074969db017b87bc6a948", size = 590206, upload-time = "2025-12-04T14:26:01.254Z" }, + { url = "https://files.pythonhosted.org/packages/48/60/29035719feb91798693023608447283b266b12efc576ed013dd9442364bb/greenlet-3.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2de5a0b09eab81fc6a382791b995b1ccf2b172a9fec934747a7a23d2ff291794", size = 1550668, upload-time = "2025-12-04T15:04:22.439Z" }, + { url = "https://files.pythonhosted.org/packages/0a/5f/783a23754b691bfa86bd72c3033aa107490deac9b2ef190837b860996c9f/greenlet-3.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4449a736606bd30f27f8e1ff4678ee193bc47f6ca810d705981cfffd6ce0d8c5", size = 1615483, upload-time = "2025-12-04T14:27:28.083Z" }, + { url = "https://files.pythonhosted.org/packages/1d/d5/c339b3b4bc8198b7caa4f2bd9fd685ac9f29795816d8db112da3d04175bb/greenlet-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:7652ee180d16d447a683c04e4c5f6441bae7ba7b17ffd9f6b3aff4605e9e6f71", size = 301164, upload-time = "2025-12-04T14:42:51.577Z" }, + { url = "https://files.pythonhosted.org/packages/f8/0a/a3871375c7b9727edaeeea994bfff7c63ff7804c9829c19309ba2e058807/greenlet-3.3.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb", size = 276379, upload-time = "2025-12-04T14:23:30.498Z" }, + { url = "https://files.pythonhosted.org/packages/43/ab/7ebfe34dce8b87be0d11dae91acbf76f7b8246bf9d6b319c741f99fa59c6/greenlet-3.3.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3", size = 597294, upload-time = "2025-12-04T14:50:06.847Z" }, + { url = "https://files.pythonhosted.org/packages/a4/39/f1c8da50024feecd0793dbd5e08f526809b8ab5609224a2da40aad3a7641/greenlet-3.3.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655", size = 607742, upload-time = "2025-12-04T14:57:42.349Z" }, + { url = "https://files.pythonhosted.org/packages/77/cb/43692bcd5f7a0da6ec0ec6d58ee7cddb606d055ce94a62ac9b1aa481e969/greenlet-3.3.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7", size = 622297, upload-time = "2025-12-04T15:07:13.552Z" }, + { url = "https://files.pythonhosted.org/packages/75/b0/6bde0b1011a60782108c01de5913c588cf51a839174538d266de15e4bf4d/greenlet-3.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b", size = 609885, upload-time = "2025-12-04T14:26:02.368Z" }, + { url = "https://files.pythonhosted.org/packages/49/0e/49b46ac39f931f59f987b7cd9f34bfec8ef81d2a1e6e00682f55be5de9f4/greenlet-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53", size = 1567424, upload-time = "2025-12-04T15:04:23.757Z" }, + { url = "https://files.pythonhosted.org/packages/05/f5/49a9ac2dff7f10091935def9165c90236d8f175afb27cbed38fb1d61ab6b/greenlet-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614", size = 1636017, upload-time = "2025-12-04T14:27:29.688Z" }, + { url = "https://files.pythonhosted.org/packages/6c/79/3912a94cf27ec503e51ba493692d6db1e3cd8ac7ac52b0b47c8e33d7f4f9/greenlet-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7a34b13d43a6b78abf828a6d0e87d3385680eaf830cd60d20d52f249faabf39", size = 301964, upload-time = "2025-12-04T14:36:58.316Z" }, + { url = "https://files.pythonhosted.org/packages/02/2f/28592176381b9ab2cafa12829ba7b472d177f3acc35d8fbcf3673d966fff/greenlet-3.3.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739", size = 275140, upload-time = "2025-12-04T14:23:01.282Z" }, + { url = "https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808", size = 599219, upload-time = "2025-12-04T14:50:08.309Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ff/7c985128f0514271b8268476af89aee6866df5eec04ac17dcfbc676213df/greenlet-3.3.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54", size = 610211, upload-time = "2025-12-04T14:57:43.968Z" }, + { url = "https://files.pythonhosted.org/packages/79/07/c47a82d881319ec18a4510bb30463ed6891f2ad2c1901ed5ec23d3de351f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30a6e28487a790417d036088b3bcb3f3ac7d8babaa7d0139edbaddebf3af9492", size = 624311, upload-time = "2025-12-04T15:07:14.697Z" }, + { url = "https://files.pythonhosted.org/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527", size = 612833, upload-time = "2025-12-04T14:26:03.669Z" }, + { url = "https://files.pythonhosted.org/packages/b5/ba/56699ff9b7c76ca12f1cdc27a886d0f81f2189c3455ff9f65246780f713d/greenlet-3.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab97cf74045343f6c60a39913fa59710e4bd26a536ce7ab2397adf8b27e67c39", size = 1567256, upload-time = "2025-12-04T15:04:25.276Z" }, + { url = "https://files.pythonhosted.org/packages/1e/37/f31136132967982d698c71a281a8901daf1a8fbab935dce7c0cf15f942cc/greenlet-3.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5375d2e23184629112ca1ea89a53389dddbffcf417dad40125713d88eb5f96e8", size = 1636483, upload-time = "2025-12-04T14:27:30.804Z" }, + { url = "https://files.pythonhosted.org/packages/7e/71/ba21c3fb8c5dce83b8c01f458a42e99ffdb1963aeec08fff5a18588d8fd7/greenlet-3.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:9ee1942ea19550094033c35d25d20726e4f1c40d59545815e1128ac58d416d38", size = 301833, upload-time = "2025-12-04T14:32:23.929Z" }, + { url = "https://files.pythonhosted.org/packages/d7/7c/f0a6d0ede2c7bf092d00bc83ad5bafb7e6ec9b4aab2fbdfa6f134dc73327/greenlet-3.3.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:60c2ef0f578afb3c8d92ea07ad327f9a062547137afe91f38408f08aacab667f", size = 275671, upload-time = "2025-12-04T14:23:05.267Z" }, + { url = "https://files.pythonhosted.org/packages/44/06/dac639ae1a50f5969d82d2e3dd9767d30d6dbdbab0e1a54010c8fe90263c/greenlet-3.3.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a5d554d0712ba1de0a6c94c640f7aeba3f85b3a6e1f2899c11c2c0428da9365", size = 646360, upload-time = "2025-12-04T14:50:10.026Z" }, + { url = "https://files.pythonhosted.org/packages/e0/94/0fb76fe6c5369fba9bf98529ada6f4c3a1adf19e406a47332245ef0eb357/greenlet-3.3.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3a898b1e9c5f7307ebbde4102908e6cbfcb9ea16284a3abe15cab996bee8b9b3", size = 658160, upload-time = "2025-12-04T14:57:45.41Z" }, + { url = "https://files.pythonhosted.org/packages/93/79/d2c70cae6e823fac36c3bbc9077962105052b7ef81db2f01ec3b9bf17e2b/greenlet-3.3.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dcd2bdbd444ff340e8d6bdf54d2f206ccddbb3ccfdcd3c25bf4afaa7b8f0cf45", size = 671388, upload-time = "2025-12-04T15:07:15.789Z" }, + { url = "https://files.pythonhosted.org/packages/b8/14/bab308fc2c1b5228c3224ec2bf928ce2e4d21d8046c161e44a2012b5203e/greenlet-3.3.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5773edda4dc00e173820722711d043799d3adb4f01731f40619e07ea2750b955", size = 660166, upload-time = "2025-12-04T14:26:05.099Z" }, + { url = "https://files.pythonhosted.org/packages/4b/d2/91465d39164eaa0085177f61983d80ffe746c5a1860f009811d498e7259c/greenlet-3.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ac0549373982b36d5fd5d30beb8a7a33ee541ff98d2b502714a09f1169f31b55", size = 1615193, upload-time = "2025-12-04T15:04:27.041Z" }, + { url = "https://files.pythonhosted.org/packages/42/1b/83d110a37044b92423084d52d5d5a3b3a73cafb51b547e6d7366ff62eff1/greenlet-3.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d198d2d977460358c3b3a4dc844f875d1adb33817f0613f663a656f463764ccc", size = 1683653, upload-time = "2025-12-04T14:27:32.366Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/9030e6f9aa8fd7808e9c31ba4c38f87c4f8ec324ee67431d181fe396d705/greenlet-3.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:73f51dd0e0bdb596fb0417e475fa3c5e32d4c83638296e560086b8d7da7c4170", size = 305387, upload-time = "2025-12-04T14:26:51.063Z" }, + { url = "https://files.pythonhosted.org/packages/a0/66/bd6317bc5932accf351fc19f177ffba53712a202f9df10587da8df257c7e/greenlet-3.3.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:d6ed6f85fae6cdfdb9ce04c9bf7a08d666cfcfb914e7d006f44f840b46741931", size = 282638, upload-time = "2025-12-04T14:25:20.941Z" }, + { url = "https://files.pythonhosted.org/packages/30/cf/cc81cb030b40e738d6e69502ccbd0dd1bced0588e958f9e757945de24404/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9125050fcf24554e69c4cacb086b87b3b55dc395a8b3ebe6487b045b2614388", size = 651145, upload-time = "2025-12-04T14:50:11.039Z" }, + { url = "https://files.pythonhosted.org/packages/9c/ea/1020037b5ecfe95ca7df8d8549959baceb8186031da83d5ecceff8b08cd2/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:87e63ccfa13c0a0f6234ed0add552af24cc67dd886731f2261e46e241608bee3", size = 654236, upload-time = "2025-12-04T14:57:47.007Z" }, + { url = "https://files.pythonhosted.org/packages/69/cc/1e4bae2e45ca2fa55299f4e85854606a78ecc37fead20d69322f96000504/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2662433acbca297c9153a4023fe2161c8dcfdcc91f10433171cf7e7d94ba2221", size = 662506, upload-time = "2025-12-04T15:07:16.906Z" }, + { url = "https://files.pythonhosted.org/packages/57/b9/f8025d71a6085c441a7eaff0fd928bbb275a6633773667023d19179fe815/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c6e9b9c1527a78520357de498b0e709fb9e2f49c3a513afd5a249007261911b", size = 653783, upload-time = "2025-12-04T14:26:06.225Z" }, + { url = "https://files.pythonhosted.org/packages/f6/c7/876a8c7a7485d5d6b5c6821201d542ef28be645aa024cfe1145b35c120c1/greenlet-3.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:286d093f95ec98fdd92fcb955003b8a3d054b4e2cab3e2707a5039e7b50520fd", size = 1614857, upload-time = "2025-12-04T15:04:28.484Z" }, + { url = "https://files.pythonhosted.org/packages/4f/dc/041be1dff9f23dac5f48a43323cd0789cb798342011c19a248d9c9335536/greenlet-3.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c10513330af5b8ae16f023e8ddbfb486ab355d04467c4679c5cfe4659975dd9", size = 1676034, upload-time = "2025-12-04T14:27:33.531Z" }, +] + [[package]] name = "griffe" version = "1.14.0" @@ -877,6 +1563,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/b1/9ff6578d789a89812ff21e4e0f80ffae20a65d5dd84e7a17873fe3b365be/griffe-1.14.0-py3-none-any.whl", hash = "sha256:0e9d52832cccf0f7188cfe585ba962d2674b241c01916d780925df34873bceb0", size = 144439, upload-time = "2025-09-05T15:02:27.511Z" }, ] +[[package]] +name = "grpc-google-iam-v1" +version = "0.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos", extra = ["grpc"] }, + { name = "grpcio" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/1e/1011451679a983f2f5c6771a1682542ecb027776762ad031fd0d7129164b/grpc_google_iam_v1-0.14.3.tar.gz", hash = "sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389", size = 23745, upload-time = "2025-10-15T21:14:53.318Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/bd/330a1bbdb1afe0b96311249e699b6dc9cfc17916394fd4503ac5aca2514b/grpc_google_iam_v1-0.14.3-py3-none-any.whl", hash = "sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6", size = 32690, upload-time = "2025-10-15T21:14:51.72Z" }, +] + +[[package]] +name = "grpc-interceptor" +version = "0.15.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "grpcio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/28/57449d5567adf4c1d3e216aaca545913fbc21a915f2da6790d6734aac76e/grpc-interceptor-0.15.4.tar.gz", hash = "sha256:1f45c0bcb58b6f332f37c637632247c9b02bc6af0fdceb7ba7ce8d2ebbfb0926", size = 19322, upload-time = "2023-11-16T02:05:42.459Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/ac/8d53f230a7443401ce81791ec50a3b0e54924bf615ad287654fa4a2f5cdc/grpc_interceptor-0.15.4-py3-none-any.whl", hash = "sha256:0035f33228693ed3767ee49d937bac424318db173fef4d2d0170b3215f254d9d", size = 20848, upload-time = "2023-11-16T02:05:40.913Z" }, +] + [[package]] name = "grpcio" version = "1.75.1" @@ -938,6 +1650,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f9/df/e2e6e9fc1c985cd1a59e6996a05647c720fe8a03b92f5ec2d60d366c531e/grpcio-1.75.1-cp314-cp314-win_amd64.whl", hash = "sha256:f86e92275710bea3000cb79feca1762dc0ad3b27830dd1a74e82ab321d4ee464", size = 4772475, upload-time = "2025-09-26T09:03:07.661Z" }, ] +[[package]] +name = "grpcio-status" +version = "1.75.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "grpcio" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/5b/1ce0e3eedcdc08b4739b3da5836f31142ec8bee1a9ae0ad8dc0dc39a14bf/grpcio_status-1.75.1.tar.gz", hash = "sha256:8162afa21833a2085c91089cc395ad880fac1378a1d60233d976649ed724cbf8", size = 13671, upload-time = "2025-09-26T09:13:16.412Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d8/ad/6f414bb0b36eee20d93af6907256f208ffcda992ae6d3d7b6a778afe31e6/grpcio_status-1.75.1-py3-none-any.whl", hash = "sha256:f681b301be26dcf7abf5c765d4a22e4098765e1a65cbdfa3efca384edf8e4e3c", size = 14428, upload-time = "2025-09-26T09:12:55.516Z" }, +] + [[package]] name = "grpcio-tools" version = "1.75.1" @@ -1038,6 +1764,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, ] +[[package]] +name = "httplib2" +version = "0.31.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyparsing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/df/6eb1d485a513776bbdbb1c919b72e59b5acc51c5e7ef28ad1cd444e252a3/httplib2-0.31.1.tar.gz", hash = "sha256:21591655ac54953624c6ab8d587c71675e379e31e2cfe3147c83c11e9ef41f92", size = 250746, upload-time = "2026-01-13T12:14:14.365Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/d8/1b05076441c2f01e4b64f59e5255edc2f0384a711b6d618845c023dc269b/httplib2-0.31.1-py3-none-any.whl", hash = "sha256:d520d22fa7e50c746a7ed856bac298c4300105d01bc2d8c2580a9b57fb9ed617", size = 91101, upload-time = "2026-01-13T12:14:12.676Z" }, +] + [[package]] name = "httpx" version = "0.28.1" @@ -1343,6 +2081,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/6c/9209b793fc98f9211846f3b2ec63e0780d30c26b9a0f2985100430dcd238/lunr-0.7.0.post1-py3-none-any.whl", hash = "sha256:77cce585d195d412cff362698799c9571ff3e285fc6bd8816ecbc9ec82dbb368", size = 35209, upload-time = "2023-08-16T16:51:31.589Z" }, ] +[[package]] +name = "mako" +version = "1.3.10" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/38/bd5b78a920a64d708fe6bc8e0a2c075e1389d53bef8413725c63ba041535/mako-1.3.10.tar.gz", hash = "sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28", size = 392474, upload-time = "2025-04-10T12:44:31.16Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl", hash = "sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59", size = 78509, upload-time = "2025-04-10T12:50:53.297Z" }, +] + [[package]] name = "markdown-it-py" version = "4.0.0" @@ -1495,6 +2245,118 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] +[[package]] +name = "mmh3" +version = "5.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/af/f28c2c2f51f31abb4725f9a64bc7863d5f491f6539bd26aee2a1d21a649e/mmh3-5.2.0.tar.gz", hash = "sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8", size = 33582, upload-time = "2025-07-29T07:43:48.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/2b/870f0ff5ecf312c58500f45950751f214b7068665e66e9bfd8bc2595587c/mmh3-5.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc", size = 56119, upload-time = "2025-07-29T07:41:39.117Z" }, + { url = "https://files.pythonhosted.org/packages/3b/88/eb9a55b3f3cf43a74d6bfa8db0e2e209f966007777a1dc897c52c008314c/mmh3-5.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328", size = 40634, upload-time = "2025-07-29T07:41:40.626Z" }, + { url = "https://files.pythonhosted.org/packages/d1/4c/8e4b3878bf8435c697d7ce99940a3784eb864521768069feaccaff884a17/mmh3-5.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d", size = 40080, upload-time = "2025-07-29T07:41:41.791Z" }, + { url = "https://files.pythonhosted.org/packages/45/ac/0a254402c8c5ca424a0a9ebfe870f5665922f932830f0a11a517b6390a09/mmh3-5.2.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e", size = 95321, upload-time = "2025-07-29T07:41:42.659Z" }, + { url = "https://files.pythonhosted.org/packages/39/8e/29306d5eca6dfda4b899d22c95b5420db4e0ffb7e0b6389b17379654ece5/mmh3-5.2.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515", size = 101220, upload-time = "2025-07-29T07:41:43.572Z" }, + { url = "https://files.pythonhosted.org/packages/49/f7/0dd1368e531e52a17b5b8dd2f379cce813bff2d0978a7748a506f1231152/mmh3-5.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3", size = 103991, upload-time = "2025-07-29T07:41:44.914Z" }, + { url = "https://files.pythonhosted.org/packages/35/06/abc7122c40f4abbfcef01d2dac6ec0b77ede9757e5be8b8a40a6265b1274/mmh3-5.2.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e", size = 110894, upload-time = "2025-07-29T07:41:45.849Z" }, + { url = "https://files.pythonhosted.org/packages/f4/2f/837885759afa4baccb8e40456e1cf76a4f3eac835b878c727ae1286c5f82/mmh3-5.2.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d", size = 118327, upload-time = "2025-07-29T07:41:47.224Z" }, + { url = "https://files.pythonhosted.org/packages/40/cc/5683ba20a21bcfb3f1605b1c474f46d30354f728a7412201f59f453d405a/mmh3-5.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772", size = 101701, upload-time = "2025-07-29T07:41:48.259Z" }, + { url = "https://files.pythonhosted.org/packages/0e/24/99ab3fb940150aec8a26dbdfc39b200b5592f6aeb293ec268df93e054c30/mmh3-5.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89", size = 96712, upload-time = "2025-07-29T07:41:49.467Z" }, + { url = "https://files.pythonhosted.org/packages/61/04/d7c4cb18f1f001ede2e8aed0f9dbbfad03d161c9eea4fffb03f14f4523e5/mmh3-5.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2", size = 110302, upload-time = "2025-07-29T07:41:50.387Z" }, + { url = "https://files.pythonhosted.org/packages/d8/bf/4dac37580cfda74425a4547500c36fa13ef581c8a756727c37af45e11e9a/mmh3-5.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc", size = 111929, upload-time = "2025-07-29T07:41:51.348Z" }, + { url = "https://files.pythonhosted.org/packages/eb/b1/49f0a582c7a942fb71ddd1ec52b7d21d2544b37d2b2d994551346a15b4f6/mmh3-5.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106", size = 100111, upload-time = "2025-07-29T07:41:53.139Z" }, + { url = "https://files.pythonhosted.org/packages/dc/94/ccec09f438caeb2506f4c63bb3b99aa08a9e09880f8fc047295154756210/mmh3-5.2.0-cp310-cp310-win32.whl", hash = "sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d", size = 40783, upload-time = "2025-07-29T07:41:54.463Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f4/8d39a32c8203c1cdae88fdb04d1ea4aa178c20f159df97f4c5a2eaec702c/mmh3-5.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb", size = 41549, upload-time = "2025-07-29T07:41:55.295Z" }, + { url = "https://files.pythonhosted.org/packages/cc/a1/30efb1cd945e193f62574144dd92a0c9ee6463435e4e8ffce9b9e9f032f0/mmh3-5.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8", size = 39335, upload-time = "2025-07-29T07:41:56.194Z" }, + { url = "https://files.pythonhosted.org/packages/f7/87/399567b3796e134352e11a8b973cd470c06b2ecfad5468fe580833be442b/mmh3-5.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1", size = 56107, upload-time = "2025-07-29T07:41:57.07Z" }, + { url = "https://files.pythonhosted.org/packages/c3/09/830af30adf8678955b247d97d3d9543dd2fd95684f3cd41c0cd9d291da9f/mmh3-5.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051", size = 40635, upload-time = "2025-07-29T07:41:57.903Z" }, + { url = "https://files.pythonhosted.org/packages/07/14/eaba79eef55b40d653321765ac5e8f6c9ac38780b8a7c2a2f8df8ee0fb72/mmh3-5.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10", size = 40078, upload-time = "2025-07-29T07:41:58.772Z" }, + { url = "https://files.pythonhosted.org/packages/bb/26/83a0f852e763f81b2265d446b13ed6d49ee49e1fc0c47b9655977e6f3d81/mmh3-5.2.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c", size = 97262, upload-time = "2025-07-29T07:41:59.678Z" }, + { url = "https://files.pythonhosted.org/packages/00/7d/b7133b10d12239aeaebf6878d7eaf0bf7d3738c44b4aba3c564588f6d802/mmh3-5.2.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762", size = 103118, upload-time = "2025-07-29T07:42:01.197Z" }, + { url = "https://files.pythonhosted.org/packages/7b/3e/62f0b5dce2e22fd5b7d092aba285abd7959ea2b17148641e029f2eab1ffa/mmh3-5.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4", size = 106072, upload-time = "2025-07-29T07:42:02.601Z" }, + { url = "https://files.pythonhosted.org/packages/66/84/ea88bb816edfe65052c757a1c3408d65c4201ddbd769d4a287b0f1a628b2/mmh3-5.2.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363", size = 112925, upload-time = "2025-07-29T07:42:03.632Z" }, + { url = "https://files.pythonhosted.org/packages/2e/13/c9b1c022807db575fe4db806f442d5b5784547e2e82cff36133e58ea31c7/mmh3-5.2.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8", size = 120583, upload-time = "2025-07-29T07:42:04.991Z" }, + { url = "https://files.pythonhosted.org/packages/8a/5f/0e2dfe1a38f6a78788b7eb2b23432cee24623aeabbc907fed07fc17d6935/mmh3-5.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed", size = 99127, upload-time = "2025-07-29T07:42:05.929Z" }, + { url = "https://files.pythonhosted.org/packages/77/27/aefb7d663b67e6a0c4d61a513c83e39ba2237e8e4557fa7122a742a23de5/mmh3-5.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646", size = 98544, upload-time = "2025-07-29T07:42:06.87Z" }, + { url = "https://files.pythonhosted.org/packages/ab/97/a21cc9b1a7c6e92205a1b5fa030cdf62277d177570c06a239eca7bd6dd32/mmh3-5.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b", size = 106262, upload-time = "2025-07-29T07:42:07.804Z" }, + { url = "https://files.pythonhosted.org/packages/43/18/db19ae82ea63c8922a880e1498a75342311f8aa0c581c4dd07711473b5f7/mmh3-5.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779", size = 109824, upload-time = "2025-07-29T07:42:08.735Z" }, + { url = "https://files.pythonhosted.org/packages/9f/f5/41dcf0d1969125fc6f61d8618b107c79130b5af50b18a4651210ea52ab40/mmh3-5.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2", size = 97255, upload-time = "2025-07-29T07:42:09.706Z" }, + { url = "https://files.pythonhosted.org/packages/32/b3/cce9eaa0efac1f0e735bb178ef9d1d2887b4927fe0ec16609d5acd492dda/mmh3-5.2.0-cp311-cp311-win32.whl", hash = "sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28", size = 40779, upload-time = "2025-07-29T07:42:10.546Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e9/3fa0290122e6d5a7041b50ae500b8a9f4932478a51e48f209a3879fe0b9b/mmh3-5.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee", size = 41549, upload-time = "2025-07-29T07:42:11.399Z" }, + { url = "https://files.pythonhosted.org/packages/3a/54/c277475b4102588e6f06b2e9095ee758dfe31a149312cdbf62d39a9f5c30/mmh3-5.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9", size = 39336, upload-time = "2025-07-29T07:42:12.209Z" }, + { url = "https://files.pythonhosted.org/packages/bf/6a/d5aa7edb5c08e0bd24286c7d08341a0446f9a2fbbb97d96a8a6dd81935ee/mmh3-5.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be", size = 56141, upload-time = "2025-07-29T07:42:13.456Z" }, + { url = "https://files.pythonhosted.org/packages/08/49/131d0fae6447bc4a7299ebdb1a6fb9d08c9f8dcf97d75ea93e8152ddf7ab/mmh3-5.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd", size = 40681, upload-time = "2025-07-29T07:42:14.306Z" }, + { url = "https://files.pythonhosted.org/packages/8f/6f/9221445a6bcc962b7f5ff3ba18ad55bba624bacdc7aa3fc0a518db7da8ec/mmh3-5.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96", size = 40062, upload-time = "2025-07-29T07:42:15.08Z" }, + { url = "https://files.pythonhosted.org/packages/1e/d4/6bb2d0fef81401e0bb4c297d1eb568b767de4ce6fc00890bc14d7b51ecc4/mmh3-5.2.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094", size = 97333, upload-time = "2025-07-29T07:42:16.436Z" }, + { url = "https://files.pythonhosted.org/packages/44/e0/ccf0daff8134efbb4fbc10a945ab53302e358c4b016ada9bf97a6bdd50c1/mmh3-5.2.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037", size = 103310, upload-time = "2025-07-29T07:42:17.796Z" }, + { url = "https://files.pythonhosted.org/packages/02/63/1965cb08a46533faca0e420e06aff8bbaf9690a6f0ac6ae6e5b2e4544687/mmh3-5.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773", size = 106178, upload-time = "2025-07-29T07:42:19.281Z" }, + { url = "https://files.pythonhosted.org/packages/c2/41/c883ad8e2c234013f27f92061200afc11554ea55edd1bcf5e1accd803a85/mmh3-5.2.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5", size = 113035, upload-time = "2025-07-29T07:42:20.356Z" }, + { url = "https://files.pythonhosted.org/packages/df/b5/1ccade8b1fa625d634a18bab7bf08a87457e09d5ec8cf83ca07cbea9d400/mmh3-5.2.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50", size = 120784, upload-time = "2025-07-29T07:42:21.377Z" }, + { url = "https://files.pythonhosted.org/packages/77/1c/919d9171fcbdcdab242e06394464ccf546f7d0f3b31e0d1e3a630398782e/mmh3-5.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765", size = 99137, upload-time = "2025-07-29T07:42:22.344Z" }, + { url = "https://files.pythonhosted.org/packages/66/8a/1eebef5bd6633d36281d9fc83cf2e9ba1ba0e1a77dff92aacab83001cee4/mmh3-5.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43", size = 98664, upload-time = "2025-07-29T07:42:23.269Z" }, + { url = "https://files.pythonhosted.org/packages/13/41/a5d981563e2ee682b21fb65e29cc0f517a6734a02b581359edd67f9d0360/mmh3-5.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4", size = 106459, upload-time = "2025-07-29T07:42:24.238Z" }, + { url = "https://files.pythonhosted.org/packages/24/31/342494cd6ab792d81e083680875a2c50fa0c5df475ebf0b67784f13e4647/mmh3-5.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3", size = 110038, upload-time = "2025-07-29T07:42:25.629Z" }, + { url = "https://files.pythonhosted.org/packages/28/44/efda282170a46bb4f19c3e2b90536513b1d821c414c28469a227ca5a1789/mmh3-5.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c", size = 97545, upload-time = "2025-07-29T07:42:27.04Z" }, + { url = "https://files.pythonhosted.org/packages/68/8f/534ae319c6e05d714f437e7206f78c17e66daca88164dff70286b0e8ea0c/mmh3-5.2.0-cp312-cp312-win32.whl", hash = "sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49", size = 40805, upload-time = "2025-07-29T07:42:28.032Z" }, + { url = "https://files.pythonhosted.org/packages/b8/f6/f6abdcfefcedab3c964868048cfe472764ed358c2bf6819a70dd4ed4ed3a/mmh3-5.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3", size = 41597, upload-time = "2025-07-29T07:42:28.894Z" }, + { url = "https://files.pythonhosted.org/packages/15/fd/f7420e8cbce45c259c770cac5718badf907b302d3a99ec587ba5ce030237/mmh3-5.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0", size = 39350, upload-time = "2025-07-29T07:42:29.794Z" }, + { url = "https://files.pythonhosted.org/packages/d8/fa/27f6ab93995ef6ad9f940e96593c5dd24744d61a7389532b0fec03745607/mmh3-5.2.0-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065", size = 40874, upload-time = "2025-07-29T07:42:30.662Z" }, + { url = "https://files.pythonhosted.org/packages/11/9c/03d13bcb6a03438bc8cac3d2e50f80908d159b31a4367c2e1a7a077ded32/mmh3-5.2.0-cp313-cp313-android_21_x86_64.whl", hash = "sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de", size = 42012, upload-time = "2025-07-29T07:42:31.539Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/0865d9765408a7d504f1789944e678f74e0888b96a766d578cb80b040999/mmh3-5.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044", size = 39197, upload-time = "2025-07-29T07:42:32.374Z" }, + { url = "https://files.pythonhosted.org/packages/3e/12/76c3207bd186f98b908b6706c2317abb73756d23a4e68ea2bc94825b9015/mmh3-5.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73", size = 39840, upload-time = "2025-07-29T07:42:33.227Z" }, + { url = "https://files.pythonhosted.org/packages/5d/0d/574b6cce5555c9f2b31ea189ad44986755eb14e8862db28c8b834b8b64dc/mmh3-5.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504", size = 40644, upload-time = "2025-07-29T07:42:34.099Z" }, + { url = "https://files.pythonhosted.org/packages/52/82/3731f8640b79c46707f53ed72034a58baad400be908c87b0088f1f89f986/mmh3-5.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b", size = 56153, upload-time = "2025-07-29T07:42:35.031Z" }, + { url = "https://files.pythonhosted.org/packages/4f/34/e02dca1d4727fd9fdeaff9e2ad6983e1552804ce1d92cc796e5b052159bb/mmh3-5.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05", size = 40684, upload-time = "2025-07-29T07:42:35.914Z" }, + { url = "https://files.pythonhosted.org/packages/8f/36/3dee40767356e104967e6ed6d102ba47b0b1ce2a89432239b95a94de1b89/mmh3-5.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814", size = 40057, upload-time = "2025-07-29T07:42:36.755Z" }, + { url = "https://files.pythonhosted.org/packages/31/58/228c402fccf76eb39a0a01b8fc470fecf21965584e66453b477050ee0e99/mmh3-5.2.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093", size = 97344, upload-time = "2025-07-29T07:42:37.675Z" }, + { url = "https://files.pythonhosted.org/packages/34/82/fc5ce89006389a6426ef28e326fc065b0fbaaed230373b62d14c889f47ea/mmh3-5.2.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54", size = 103325, upload-time = "2025-07-29T07:42:38.591Z" }, + { url = "https://files.pythonhosted.org/packages/09/8c/261e85777c6aee1ebd53f2f17e210e7481d5b0846cd0b4a5c45f1e3761b8/mmh3-5.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a", size = 106240, upload-time = "2025-07-29T07:42:39.563Z" }, + { url = "https://files.pythonhosted.org/packages/70/73/2f76b3ad8a3d431824e9934403df36c0ddacc7831acf82114bce3c4309c8/mmh3-5.2.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908", size = 113060, upload-time = "2025-07-29T07:42:40.585Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b9/7ea61a34e90e50a79a9d87aa1c0b8139a7eaf4125782b34b7d7383472633/mmh3-5.2.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5", size = 120781, upload-time = "2025-07-29T07:42:41.618Z" }, + { url = "https://files.pythonhosted.org/packages/0f/5b/ae1a717db98c7894a37aeedbd94b3f99e6472a836488f36b6849d003485b/mmh3-5.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a", size = 99174, upload-time = "2025-07-29T07:42:42.587Z" }, + { url = "https://files.pythonhosted.org/packages/e3/de/000cce1d799fceebb6d4487ae29175dd8e81b48e314cba7b4da90bcf55d7/mmh3-5.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266", size = 98734, upload-time = "2025-07-29T07:42:43.996Z" }, + { url = "https://files.pythonhosted.org/packages/79/19/0dc364391a792b72fbb22becfdeacc5add85cc043cd16986e82152141883/mmh3-5.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5", size = 106493, upload-time = "2025-07-29T07:42:45.07Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b1/bc8c28e4d6e807bbb051fefe78e1156d7f104b89948742ad310612ce240d/mmh3-5.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9", size = 110089, upload-time = "2025-07-29T07:42:46.122Z" }, + { url = "https://files.pythonhosted.org/packages/3b/a2/d20f3f5c95e9c511806686c70d0a15479cc3941c5f322061697af1c1ff70/mmh3-5.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290", size = 97571, upload-time = "2025-07-29T07:42:47.18Z" }, + { url = "https://files.pythonhosted.org/packages/7b/23/665296fce4f33488deec39a750ffd245cfc07aafb0e3ef37835f91775d14/mmh3-5.2.0-cp313-cp313-win32.whl", hash = "sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051", size = 40806, upload-time = "2025-07-29T07:42:48.166Z" }, + { url = "https://files.pythonhosted.org/packages/59/b0/92e7103f3b20646e255b699e2d0327ce53a3f250e44367a99dc8be0b7c7a/mmh3-5.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081", size = 41600, upload-time = "2025-07-29T07:42:49.371Z" }, + { url = "https://files.pythonhosted.org/packages/99/22/0b2bd679a84574647de538c5b07ccaa435dbccc37815067fe15b90fe8dad/mmh3-5.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b", size = 39349, upload-time = "2025-07-29T07:42:50.268Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ca/a20db059a8a47048aaf550da14a145b56e9c7386fb8280d3ce2962dcebf7/mmh3-5.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078", size = 39209, upload-time = "2025-07-29T07:42:51.559Z" }, + { url = "https://files.pythonhosted.org/packages/98/dd/e5094799d55c7482d814b979a0fd608027d0af1b274bfb4c3ea3e950bfd5/mmh3-5.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501", size = 39843, upload-time = "2025-07-29T07:42:52.536Z" }, + { url = "https://files.pythonhosted.org/packages/f4/6b/7844d7f832c85400e7cc89a1348e4e1fdd38c5a38415bb5726bbb8fcdb6c/mmh3-5.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b", size = 40648, upload-time = "2025-07-29T07:42:53.392Z" }, + { url = "https://files.pythonhosted.org/packages/1f/bf/71f791f48a21ff3190ba5225807cbe4f7223360e96862c376e6e3fb7efa7/mmh3-5.2.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770", size = 56164, upload-time = "2025-07-29T07:42:54.267Z" }, + { url = "https://files.pythonhosted.org/packages/70/1f/f87e3d34d83032b4f3f0f528c6d95a98290fcacf019da61343a49dccfd51/mmh3-5.2.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110", size = 40692, upload-time = "2025-07-29T07:42:55.234Z" }, + { url = "https://files.pythonhosted.org/packages/a6/e2/db849eaed07117086f3452feca8c839d30d38b830ac59fe1ce65af8be5ad/mmh3-5.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647", size = 40068, upload-time = "2025-07-29T07:42:56.158Z" }, + { url = "https://files.pythonhosted.org/packages/df/6b/209af927207af77425b044e32f77f49105a0b05d82ff88af6971d8da4e19/mmh3-5.2.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63", size = 97367, upload-time = "2025-07-29T07:42:57.037Z" }, + { url = "https://files.pythonhosted.org/packages/ca/e0/78adf4104c425606a9ce33fb351f790c76a6c2314969c4a517d1ffc92196/mmh3-5.2.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12", size = 103306, upload-time = "2025-07-29T07:42:58.522Z" }, + { url = "https://files.pythonhosted.org/packages/a3/79/c2b89f91b962658b890104745b1b6c9ce38d50a889f000b469b91eeb1b9e/mmh3-5.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22", size = 106312, upload-time = "2025-07-29T07:42:59.552Z" }, + { url = "https://files.pythonhosted.org/packages/4b/14/659d4095528b1a209be90934778c5ffe312177d51e365ddcbca2cac2ec7c/mmh3-5.2.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5", size = 113135, upload-time = "2025-07-29T07:43:00.745Z" }, + { url = "https://files.pythonhosted.org/packages/8d/6f/cd7734a779389a8a467b5c89a48ff476d6f2576e78216a37551a97e9e42a/mmh3-5.2.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07", size = 120775, upload-time = "2025-07-29T07:43:02.124Z" }, + { url = "https://files.pythonhosted.org/packages/1d/ca/8256e3b96944408940de3f9291d7e38a283b5761fe9614d4808fcf27bd62/mmh3-5.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935", size = 99178, upload-time = "2025-07-29T07:43:03.182Z" }, + { url = "https://files.pythonhosted.org/packages/8a/32/39e2b3cf06b6e2eb042c984dab8680841ac2a0d3ca6e0bea30db1f27b565/mmh3-5.2.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7", size = 98738, upload-time = "2025-07-29T07:43:04.207Z" }, + { url = "https://files.pythonhosted.org/packages/61/d3/7bbc8e0e8cf65ebbe1b893ffa0467b7ecd1bd07c3bbf6c9db4308ada22ec/mmh3-5.2.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5", size = 106510, upload-time = "2025-07-29T07:43:05.656Z" }, + { url = "https://files.pythonhosted.org/packages/10/99/b97e53724b52374e2f3859046f0eb2425192da356cb19784d64bc17bb1cf/mmh3-5.2.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384", size = 110053, upload-time = "2025-07-29T07:43:07.204Z" }, + { url = "https://files.pythonhosted.org/packages/ac/62/3688c7d975ed195155671df68788c83fed6f7909b6ec4951724c6860cb97/mmh3-5.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e", size = 97546, upload-time = "2025-07-29T07:43:08.226Z" }, + { url = "https://files.pythonhosted.org/packages/ca/3b/c6153250f03f71a8b7634cded82939546cdfba02e32f124ff51d52c6f991/mmh3-5.2.0-cp314-cp314-win32.whl", hash = "sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0", size = 41422, upload-time = "2025-07-29T07:43:09.216Z" }, + { url = "https://files.pythonhosted.org/packages/74/01/a27d98bab083a435c4c07e9d1d720d4c8a578bf4c270bae373760b1022be/mmh3-5.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b", size = 42135, upload-time = "2025-07-29T07:43:10.183Z" }, + { url = "https://files.pythonhosted.org/packages/cb/c9/dbba5507e95429b8b380e2ba091eff5c20a70a59560934dff0ad8392b8c8/mmh3-5.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115", size = 39879, upload-time = "2025-07-29T07:43:11.106Z" }, + { url = "https://files.pythonhosted.org/packages/b5/d1/c8c0ef839c17258b9de41b84f663574fabcf8ac2007b7416575e0f65ff6e/mmh3-5.2.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932", size = 57696, upload-time = "2025-07-29T07:43:11.989Z" }, + { url = "https://files.pythonhosted.org/packages/2f/55/95e2b9ff201e89f9fe37036037ab61a6c941942b25cdb7b6a9df9b931993/mmh3-5.2.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c", size = 41421, upload-time = "2025-07-29T07:43:13.269Z" }, + { url = "https://files.pythonhosted.org/packages/77/79/9be23ad0b7001a4b22752e7693be232428ecc0a35068a4ff5c2f14ef8b20/mmh3-5.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be", size = 40853, upload-time = "2025-07-29T07:43:14.888Z" }, + { url = "https://files.pythonhosted.org/packages/ac/1b/96b32058eda1c1dee8264900c37c359a7325c1f11f5ff14fd2be8e24eff9/mmh3-5.2.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb", size = 109694, upload-time = "2025-07-29T07:43:15.816Z" }, + { url = "https://files.pythonhosted.org/packages/8d/6f/a2ae44cd7dad697b6dea48390cbc977b1e5ca58fda09628cbcb2275af064/mmh3-5.2.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65", size = 117438, upload-time = "2025-07-29T07:43:16.865Z" }, + { url = "https://files.pythonhosted.org/packages/a0/08/bfb75451c83f05224a28afeaf3950c7b793c0b71440d571f8e819cfb149a/mmh3-5.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991", size = 120409, upload-time = "2025-07-29T07:43:18.207Z" }, + { url = "https://files.pythonhosted.org/packages/9f/ea/8b118b69b2ff8df568f742387d1a159bc654a0f78741b31437dd047ea28e/mmh3-5.2.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645", size = 125909, upload-time = "2025-07-29T07:43:19.39Z" }, + { url = "https://files.pythonhosted.org/packages/3e/11/168cc0b6a30650032e351a3b89b8a47382da541993a03af91e1ba2501234/mmh3-5.2.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3", size = 135331, upload-time = "2025-07-29T07:43:20.435Z" }, + { url = "https://files.pythonhosted.org/packages/31/05/e3a9849b1c18a7934c64e831492c99e67daebe84a8c2f2c39a7096a830e3/mmh3-5.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279", size = 110085, upload-time = "2025-07-29T07:43:21.92Z" }, + { url = "https://files.pythonhosted.org/packages/d9/d5/a96bcc306e3404601418b2a9a370baec92af84204528ba659fdfe34c242f/mmh3-5.2.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513", size = 111195, upload-time = "2025-07-29T07:43:23.066Z" }, + { url = "https://files.pythonhosted.org/packages/af/29/0fd49801fec5bff37198684e0849b58e0dab3a2a68382a357cfffb0fafc3/mmh3-5.2.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db", size = 116919, upload-time = "2025-07-29T07:43:24.178Z" }, + { url = "https://files.pythonhosted.org/packages/2d/04/4f3c32b0a2ed762edca45d8b46568fc3668e34f00fb1e0a3b5451ec1281c/mmh3-5.2.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667", size = 123160, upload-time = "2025-07-29T07:43:25.26Z" }, + { url = "https://files.pythonhosted.org/packages/91/76/3d29eaa38821730633d6a240d36fa8ad2807e9dfd432c12e1a472ed211eb/mmh3-5.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5", size = 110206, upload-time = "2025-07-29T07:43:26.699Z" }, + { url = "https://files.pythonhosted.org/packages/44/1c/ccf35892684d3a408202e296e56843743e0b4fb1629e59432ea88cdb3909/mmh3-5.2.0-cp314-cp314t-win32.whl", hash = "sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7", size = 41970, upload-time = "2025-07-29T07:43:27.666Z" }, + { url = "https://files.pythonhosted.org/packages/75/b2/b9e4f1e5adb5e21eb104588fcee2cd1eaa8308255173481427d5ecc4284e/mmh3-5.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d", size = 43063, upload-time = "2025-07-29T07:43:28.582Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fc/0e61d9a4e29c8679356795a40e48f647b4aad58d71bfc969f0f8f56fb912/mmh3-5.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9", size = 40455, upload-time = "2025-07-29T07:43:29.563Z" }, +] + [[package]] name = "more-itertools" version = "10.8.0" @@ -1895,6 +2757,108 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/91/48/28ed9e55dcf2f453128df738210a980e09f4e468a456fa3c763dbc8be70a/opentelemetry_api-1.37.0-py3-none-any.whl", hash = "sha256:accf2024d3e89faec14302213bc39550ec0f4095d1cf5ca688e1bfb1c8612f47", size = 65732, upload-time = "2025-09-11T10:28:41.826Z" }, ] +[[package]] +name = "opentelemetry-exporter-gcp-logging" +version = "1.11.0a0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-cloud-logging" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-resourcedetector-gcp" }, + { name = "opentelemetry-sdk" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/2d/6aa7063b009768d8f9415b36a29ae9b3eb1e2c5eff70f58ca15e104c245f/opentelemetry_exporter_gcp_logging-1.11.0a0.tar.gz", hash = "sha256:58496f11b930c84570060ffbd4343cd0b597ea13c7bc5c879df01163dd552f14", size = 22400, upload-time = "2025-11-04T19:32:13.812Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/b7/2d3df53fa39bfd52f88c78a60367d45a7b1adbf8a756cce62d6ac149d49a/opentelemetry_exporter_gcp_logging-1.11.0a0-py3-none-any.whl", hash = "sha256:f8357c552947cb9c0101c4575a7702b8d3268e28bdeefdd1405cf838e128c6ef", size = 14168, upload-time = "2025-11-04T19:32:07.073Z" }, +] + +[[package]] +name = "opentelemetry-exporter-gcp-monitoring" +version = "1.11.0a0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-cloud-monitoring" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-resourcedetector-gcp" }, + { name = "opentelemetry-sdk" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3f/48/d1c7d2380bb1754d1eb6a011a2e0de08c6868cb6c0f34bcda0444fa0d614/opentelemetry_exporter_gcp_monitoring-1.11.0a0.tar.gz", hash = "sha256:386276eddbbd978a6f30fafd3397975beeb02a1302bdad554185242a8e2c343c", size = 20828, upload-time = "2025-11-04T19:32:14.522Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/8c/03a6e73e270a9c890dbd6cc1c47c83d86b8a8a974a9168d92e043c6277cc/opentelemetry_exporter_gcp_monitoring-1.11.0a0-py3-none-any.whl", hash = "sha256:b6740cba61b2f9555274829fe87a58447b64d0378f1067a4faebb4f5b364ca22", size = 13611, upload-time = "2025-11-04T19:32:08.212Z" }, +] + +[[package]] +name = "opentelemetry-exporter-gcp-trace" +version = "1.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-cloud-trace" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-resourcedetector-gcp" }, + { name = "opentelemetry-sdk" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/9c/4c3b26e5494f8b53c7873732a2317df905abe2b8ab33e9edfcbd5a8ff79b/opentelemetry_exporter_gcp_trace-1.11.0.tar.gz", hash = "sha256:c947ab4ab53e16517ade23d6fe71fe88cf7ca3f57a42c9f0e4162d2b929fecb6", size = 18770, upload-time = "2025-11-04T19:32:15.109Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/4a/876703e8c5845198d95cd4006c8d1b2e3b129a9e288558e33133360f8d5d/opentelemetry_exporter_gcp_trace-1.11.0-py3-none-any.whl", hash = "sha256:b3dcb314e1a9985e9185cb7720b693eb393886fde98ae4c095ffc0893de6cefa", size = 14016, upload-time = "2025-11-04T19:32:09.009Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-proto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dc/6c/10018cbcc1e6fff23aac67d7fd977c3d692dbe5f9ef9bb4db5c1268726cc/opentelemetry_exporter_otlp_proto_common-1.37.0.tar.gz", hash = "sha256:c87a1bdd9f41fdc408d9cc9367bb53f8d2602829659f2b90be9f9d79d0bfe62c", size = 20430, upload-time = "2025-09-11T10:29:03.605Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/13/b4ef09837409a777f3c0af2a5b4ba9b7af34872bc43609dda0c209e4060d/opentelemetry_exporter_otlp_proto_common-1.37.0-py3-none-any.whl", hash = "sha256:53038428449c559b0c564b8d718df3314da387109c4d36bd1b94c9a641b0292e", size = 18359, upload-time = "2025-09-11T10:28:44.939Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5d/e3/6e320aeb24f951449e73867e53c55542bebbaf24faeee7623ef677d66736/opentelemetry_exporter_otlp_proto_http-1.37.0.tar.gz", hash = "sha256:e52e8600f1720d6de298419a802108a8f5afa63c96809ff83becb03f874e44ac", size = 17281, upload-time = "2025-09-11T10:29:04.844Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/e9/70d74a664d83976556cec395d6bfedd9b85ec1498b778367d5f93e373397/opentelemetry_exporter_otlp_proto_http-1.37.0-py3-none-any.whl", hash = "sha256:54c42b39945a6cc9d9a2a33decb876eabb9547e0dcb49df090122773447f1aef", size = 19576, upload-time = "2025-09-11T10:28:46.726Z" }, +] + +[[package]] +name = "opentelemetry-proto" +version = "1.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/ea/a75f36b463a36f3c5a10c0b5292c58b31dbdde74f6f905d3d0ab2313987b/opentelemetry_proto-1.37.0.tar.gz", hash = "sha256:30f5c494faf66f77faeaefa35ed4443c5edb3b0aa46dad073ed7210e1a789538", size = 46151, upload-time = "2025-09-11T10:29:11.04Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/25/f89ea66c59bd7687e218361826c969443c4fa15dfe89733f3bf1e2a9e971/opentelemetry_proto-1.37.0-py3-none-any.whl", hash = "sha256:8ed8c066ae8828bbf0c39229979bdf583a126981142378a9cbe9d6fd5701c6e2", size = 72534, upload-time = "2025-09-11T10:28:56.831Z" }, +] + +[[package]] +name = "opentelemetry-resourcedetector-gcp" +version = "1.11.0a0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-sdk" }, + { name = "requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c1/5d/2b3240d914b87b6dd9cd5ca2ef1ccaf1d0626b897d4c06877e22c8c10fcf/opentelemetry_resourcedetector_gcp-1.11.0a0.tar.gz", hash = "sha256:915a1d6fd15daca9eedd3fc52b0f705375054f2ef140e2e7a6b4cca95a47cdb1", size = 18796, upload-time = "2025-11-04T19:32:16.59Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/6c/1e13fe142a7ca3dc6489167203a1209d32430cca12775e1df9c9a41c54b2/opentelemetry_resourcedetector_gcp-1.11.0a0-py3-none-any.whl", hash = "sha256:5d65a2a039b1d40c6f41421dbb08d5f441368275ac6de6e76a8fccd1f6acb67e", size = 18798, upload-time = "2025-11-04T19:32:10.915Z" }, +] + [[package]] name = "opentelemetry-sdk" version = "1.37.0" @@ -2081,6 +3045,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, ] +[[package]] +name = "proto-plus" +version = "1.27.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/89/9cbe2f4bba860e149108b683bc2efec21f14d5f7ed6e25562ad86acbc373/proto_plus-1.27.0.tar.gz", hash = "sha256:873af56dd0d7e91836aee871e5799e1c6f1bda86ac9a983e0bb9f0c266a568c4", size = 56158, upload-time = "2025-12-16T13:46:25.729Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/24/3b7a0818484df9c28172857af32c2397b6d8fcd99d9468bd4684f98ebf0a/proto_plus-1.27.0-py3-none-any.whl", hash = "sha256:1baa7f81cf0f8acb8bc1f6d085008ba4171eaf669629d1b6d1673b21ed1c0a82", size = 50205, upload-time = "2025-12-16T13:46:24.76Z" }, +] + [[package]] name = "protobuf" version = "6.33.0" @@ -2110,6 +3086,84 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/05/33/2d74d588408caedd065c2497bdb5ef83ce6082db01289a1e1147f6639802/psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8", size = 249898, upload-time = "2024-01-19T20:47:59.238Z" }, ] +[[package]] +name = "pyarrow" +version = "23.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/33/ffd9c3eb087fa41dd79c3cf20c4c0ae3cdb877c4f8e1107a446006344924/pyarrow-23.0.0.tar.gz", hash = "sha256:180e3150e7edfcd182d3d9afba72f7cf19839a497cc76555a8dce998a8f67615", size = 1167185, upload-time = "2026-01-18T16:19:42.218Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/2f/23e042a5aa99bcb15e794e14030e8d065e00827e846e53a66faec73c7cd6/pyarrow-23.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:cbdc2bf5947aa4d462adcf8453cf04aee2f7932653cb67a27acd96e5e8528a67", size = 34281861, upload-time = "2026-01-18T16:13:34.332Z" }, + { url = "https://files.pythonhosted.org/packages/8b/65/1651933f504b335ec9cd8f99463718421eb08d883ed84f0abd2835a16cad/pyarrow-23.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:4d38c836930ce15cd31dce20114b21ba082da231c884bdc0a7b53e1477fe7f07", size = 35825067, upload-time = "2026-01-18T16:13:42.549Z" }, + { url = "https://files.pythonhosted.org/packages/84/ec/d6fceaec050c893f4e35c0556b77d4cc9973fcc24b0a358a5781b1234582/pyarrow-23.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:4222ff8f76919ecf6c716175a0e5fddb5599faeed4c56d9ea41a2c42be4998b2", size = 44458539, upload-time = "2026-01-18T16:13:52.975Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d9/369f134d652b21db62fe3ec1c5c2357e695f79eb67394b8a93f3a2b2cffa/pyarrow-23.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:87f06159cbe38125852657716889296c83c37b4d09a5e58f3d10245fd1f69795", size = 47535889, upload-time = "2026-01-18T16:14:03.693Z" }, + { url = "https://files.pythonhosted.org/packages/a3/95/f37b6a252fdbf247a67a78fb3f61a529fe0600e304c4d07741763d3522b1/pyarrow-23.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1675c374570d8b91ea6d4edd4608fa55951acd44e0c31bd146e091b4005de24f", size = 48157777, upload-time = "2026-01-18T16:14:12.483Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ab/fb94923108c9c6415dab677cf1f066d3307798eafc03f9a65ab4abc61056/pyarrow-23.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:247374428fde4f668f138b04031a7e7077ba5fa0b5b1722fdf89a017bf0b7ee0", size = 50580441, upload-time = "2026-01-18T16:14:20.187Z" }, + { url = "https://files.pythonhosted.org/packages/ae/78/897ba6337b517fc8e914891e1bd918da1c4eb8e936a553e95862e67b80f6/pyarrow-23.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:de53b1bd3b88a2ee93c9af412c903e57e738c083be4f6392288294513cd8b2c1", size = 27530028, upload-time = "2026-01-18T16:14:27.353Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c0/57fe251102ca834fee0ef69a84ad33cc0ff9d5dfc50f50b466846356ecd7/pyarrow-23.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5574d541923efcbfdf1294a2746ae3b8c2498a2dc6cd477882f6f4e7b1ac08d3", size = 34276762, upload-time = "2026-01-18T16:14:34.128Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4e/24130286548a5bc250cbed0b6bbf289a2775378a6e0e6f086ae8c68fc098/pyarrow-23.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:2ef0075c2488932e9d3c2eb3482f9459c4be629aa673b725d5e3cf18f777f8e4", size = 35821420, upload-time = "2026-01-18T16:14:40.699Z" }, + { url = "https://files.pythonhosted.org/packages/ee/55/a869e8529d487aa2e842d6c8865eb1e2c9ec33ce2786eb91104d2c3e3f10/pyarrow-23.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:65666fc269669af1ef1c14478c52222a2aa5c907f28b68fb50a203c777e4f60c", size = 44457412, upload-time = "2026-01-18T16:14:49.051Z" }, + { url = "https://files.pythonhosted.org/packages/36/81/1de4f0edfa9a483bbdf0082a05790bd6a20ed2169ea12a65039753be3a01/pyarrow-23.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:4d85cb6177198f3812db4788e394b757223f60d9a9f5ad6634b3e32be1525803", size = 47534285, upload-time = "2026-01-18T16:14:56.748Z" }, + { url = "https://files.pythonhosted.org/packages/f2/04/464a052d673b5ece074518f27377861662449f3c1fdb39ce740d646fd098/pyarrow-23.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1a9ff6fa4141c24a03a1a434c63c8fa97ce70f8f36bccabc18ebba905ddf0f17", size = 48157913, upload-time = "2026-01-18T16:15:05.114Z" }, + { url = "https://files.pythonhosted.org/packages/f4/1b/32a4de9856ee6688c670ca2def588382e573cce45241a965af04c2f61687/pyarrow-23.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:84839d060a54ae734eb60a756aeacb62885244aaa282f3c968f5972ecc7b1ecc", size = 50582529, upload-time = "2026-01-18T16:15:12.846Z" }, + { url = "https://files.pythonhosted.org/packages/db/c7/d6581f03e9b9e44ea60b52d1750ee1a7678c484c06f939f45365a45f7eef/pyarrow-23.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:a149a647dbfe928ce8830a713612aa0b16e22c64feac9d1761529778e4d4eaa5", size = 27542646, upload-time = "2026-01-18T16:15:18.89Z" }, + { url = "https://files.pythonhosted.org/packages/3d/bd/c861d020831ee57609b73ea721a617985ece817684dc82415b0bc3e03ac3/pyarrow-23.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:5961a9f646c232697c24f54d3419e69b4261ba8a8b66b0ac54a1851faffcbab8", size = 34189116, upload-time = "2026-01-18T16:15:28.054Z" }, + { url = "https://files.pythonhosted.org/packages/8c/23/7725ad6cdcbaf6346221391e7b3eecd113684c805b0a95f32014e6fa0736/pyarrow-23.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:632b3e7c3d232f41d64e1a4a043fb82d44f8a349f339a1188c6a0dd9d2d47d8a", size = 35803831, upload-time = "2026-01-18T16:15:33.798Z" }, + { url = "https://files.pythonhosted.org/packages/57/06/684a421543455cdc2944d6a0c2cc3425b028a4c6b90e34b35580c4899743/pyarrow-23.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:76242c846db1411f1d6c2cc3823be6b86b40567ee24493344f8226ba34a81333", size = 44436452, upload-time = "2026-01-18T16:15:41.598Z" }, + { url = "https://files.pythonhosted.org/packages/c6/6f/8f9eb40c2328d66e8b097777ddcf38494115ff9f1b5bc9754ba46991191e/pyarrow-23.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b73519f8b52ae28127000986bf228fda781e81d3095cd2d3ece76eb5cf760e1b", size = 47557396, upload-time = "2026-01-18T16:15:51.252Z" }, + { url = "https://files.pythonhosted.org/packages/10/6e/f08075f1472e5159553501fde2cc7bc6700944bdabe49a03f8a035ee6ccd/pyarrow-23.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:068701f6823449b1b6469120f399a1239766b117d211c5d2519d4ed5861f75de", size = 48147129, upload-time = "2026-01-18T16:16:00.299Z" }, + { url = "https://files.pythonhosted.org/packages/7d/82/d5a680cd507deed62d141cc7f07f7944a6766fc51019f7f118e4d8ad0fb8/pyarrow-23.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1801ba947015d10e23bca9dd6ef5d0e9064a81569a89b6e9a63b59224fd060df", size = 50596642, upload-time = "2026-01-18T16:16:08.502Z" }, + { url = "https://files.pythonhosted.org/packages/a9/26/4f29c61b3dce9fa7780303b86895ec6a0917c9af927101daaaf118fbe462/pyarrow-23.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:52265266201ec25b6839bf6bd4ea918ca6d50f31d13e1cf200b4261cd11dc25c", size = 27660628, upload-time = "2026-01-18T16:16:15.28Z" }, + { url = "https://files.pythonhosted.org/packages/66/34/564db447d083ec7ff93e0a883a597d2f214e552823bfc178a2d0b1f2c257/pyarrow-23.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:ad96a597547af7827342ffb3c503c8316e5043bb09b47a84885ce39394c96e00", size = 34184630, upload-time = "2026-01-18T16:16:22.141Z" }, + { url = "https://files.pythonhosted.org/packages/aa/3a/3999daebcb5e6119690c92a621c4d78eef2ffba7a0a1b56386d2875fcd77/pyarrow-23.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:b9edf990df77c2901e79608f08c13fbde60202334a4fcadb15c1f57bf7afee43", size = 35796820, upload-time = "2026-01-18T16:16:29.441Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ee/39195233056c6a8d0976d7d1ac1cd4fe21fb0ec534eca76bc23ef3f60e11/pyarrow-23.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:36d1b5bc6ddcaff0083ceec7e2561ed61a51f49cce8be079ee8ed406acb6fdef", size = 44438735, upload-time = "2026-01-18T16:16:38.79Z" }, + { url = "https://files.pythonhosted.org/packages/2c/41/6a7328ee493527e7afc0c88d105ecca69a3580e29f2faaeac29308369fd7/pyarrow-23.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4292b889cd224f403304ddda8b63a36e60f92911f89927ec8d98021845ea21be", size = 47557263, upload-time = "2026-01-18T16:16:46.248Z" }, + { url = "https://files.pythonhosted.org/packages/c6/ee/34e95b21ee84db494eae60083ddb4383477b31fb1fd19fd866d794881696/pyarrow-23.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dfd9e133e60eaa847fd80530a1b89a052f09f695d0b9c34c235ea6b2e0924cf7", size = 48153529, upload-time = "2026-01-18T16:16:53.412Z" }, + { url = "https://files.pythonhosted.org/packages/52/88/8a8d83cea30f4563efa1b7bf51d241331ee5cd1b185a7e063f5634eca415/pyarrow-23.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832141cc09fac6aab1cd3719951d23301396968de87080c57c9a7634e0ecd068", size = 50598851, upload-time = "2026-01-18T16:17:01.133Z" }, + { url = "https://files.pythonhosted.org/packages/c6/4c/2929c4be88723ba025e7b3453047dc67e491c9422965c141d24bab6b5962/pyarrow-23.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:7a7d067c9a88faca655c71bcc30ee2782038d59c802d57950826a07f60d83c4c", size = 27577747, upload-time = "2026-01-18T16:18:02.413Z" }, + { url = "https://files.pythonhosted.org/packages/64/52/564a61b0b82d72bd68ec3aef1adda1e3eba776f89134b9ebcb5af4b13cb6/pyarrow-23.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:ce9486e0535a843cf85d990e2ec5820a47918235183a5c7b8b97ed7e92c2d47d", size = 34446038, upload-time = "2026-01-18T16:17:07.861Z" }, + { url = "https://files.pythonhosted.org/packages/cc/c9/232d4f9855fd1de0067c8a7808a363230d223c83aeee75e0fe6eab851ba9/pyarrow-23.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:075c29aeaa685fd1182992a9ed2499c66f084ee54eea47da3eb76e125e06064c", size = 35921142, upload-time = "2026-01-18T16:17:15.401Z" }, + { url = "https://files.pythonhosted.org/packages/96/f2/60af606a3748367b906bb82d41f0032e059f075444445d47e32a7ff1df62/pyarrow-23.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:799965a5379589510d888be3094c2296efd186a17ca1cef5b77703d4d5121f53", size = 44490374, upload-time = "2026-01-18T16:17:23.93Z" }, + { url = "https://files.pythonhosted.org/packages/ff/2d/7731543050a678ea3a413955a2d5d80d2a642f270aa57a3cb7d5a86e3f46/pyarrow-23.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ef7cac8fe6fccd8b9e7617bfac785b0371a7fe26af59463074e4882747145d40", size = 47527896, upload-time = "2026-01-18T16:17:33.393Z" }, + { url = "https://files.pythonhosted.org/packages/5a/90/f3342553b7ac9879413aed46500f1637296f3c8222107523a43a1c08b42a/pyarrow-23.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15a414f710dc927132dd67c361f78c194447479555af57317066ee5116b90e9e", size = 48210401, upload-time = "2026-01-18T16:17:42.012Z" }, + { url = "https://files.pythonhosted.org/packages/f3/da/9862ade205ecc46c172b6ce5038a74b5151c7401e36255f15975a45878b2/pyarrow-23.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e0d2e6915eca7d786be6a77bf227fbc06d825a75b5b5fe9bcbef121dec32685", size = 50579677, upload-time = "2026-01-18T16:17:50.241Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4c/f11f371f5d4740a5dafc2e11c76bcf42d03dfdb2d68696da97de420b6963/pyarrow-23.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4b317ea6e800b5704e5e5929acb6e2dc13e9276b708ea97a39eb8b345aa2658b", size = 27631889, upload-time = "2026-01-18T16:17:56.55Z" }, + { url = "https://files.pythonhosted.org/packages/97/bb/15aec78bcf43a0c004067bd33eb5352836a29a49db8581fc56f2b6ca88b7/pyarrow-23.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:20b187ed9550d233a872074159f765f52f9d92973191cd4b93f293a19efbe377", size = 34213265, upload-time = "2026-01-18T16:18:07.904Z" }, + { url = "https://files.pythonhosted.org/packages/f6/6c/deb2c594bbba41c37c5d9aa82f510376998352aa69dfcb886cb4b18ad80f/pyarrow-23.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:18ec84e839b493c3886b9b5e06861962ab4adfaeb79b81c76afbd8d84c7d5fda", size = 35819211, upload-time = "2026-01-18T16:18:13.94Z" }, + { url = "https://files.pythonhosted.org/packages/e0/e5/ee82af693cb7b5b2b74f6524cdfede0e6ace779d7720ebca24d68b57c36b/pyarrow-23.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:e438dd3f33894e34fd02b26bd12a32d30d006f5852315f611aa4add6c7fab4bc", size = 44502313, upload-time = "2026-01-18T16:18:20.367Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/95c61ad82236495f3c31987e85135926ba3ec7f3819296b70a68d8066b49/pyarrow-23.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:a244279f240c81f135631be91146d7fa0e9e840e1dfed2aba8483eba25cd98e6", size = 47585886, upload-time = "2026-01-18T16:18:27.544Z" }, + { url = "https://files.pythonhosted.org/packages/bb/6e/a72d901f305201802f016d015de1e05def7706fff68a1dedefef5dc7eff7/pyarrow-23.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c4692e83e42438dba512a570c6eaa42be2f8b6c0f492aea27dec54bdc495103a", size = 48207055, upload-time = "2026-01-18T16:18:35.425Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e5/5de029c537630ca18828db45c30e2a78da03675a70ac6c3528203c416fe3/pyarrow-23.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae7f30f898dfe44ea69654a35c93e8da4cef6606dc4c72394068fd95f8e9f54a", size = 50619812, upload-time = "2026-01-18T16:18:43.553Z" }, + { url = "https://files.pythonhosted.org/packages/59/8d/2af846cd2412e67a087f5bda4a8e23dfd4ebd570f777db2e8686615dafc1/pyarrow-23.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:5b86bb649e4112fb0614294b7d0a175c7513738876b89655605ebb87c804f861", size = 28263851, upload-time = "2026-01-18T16:19:38.567Z" }, + { url = "https://files.pythonhosted.org/packages/7b/7f/caab863e587041156f6786c52e64151b7386742c8c27140f637176e9230e/pyarrow-23.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:ebc017d765d71d80a3f8584ca0566b53e40464586585ac64176115baa0ada7d3", size = 34463240, upload-time = "2026-01-18T16:18:49.755Z" }, + { url = "https://files.pythonhosted.org/packages/c9/fa/3a5b8c86c958e83622b40865e11af0857c48ec763c11d472c87cd518283d/pyarrow-23.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:0800cc58a6d17d159df823f87ad66cefebf105b982493d4bad03ee7fab84b993", size = 35935712, upload-time = "2026-01-18T16:18:55.626Z" }, + { url = "https://files.pythonhosted.org/packages/c5/08/17a62078fc1a53decb34a9aa79cf9009efc74d63d2422e5ade9fed2f99e3/pyarrow-23.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:3a7c68c722da9bb5b0f8c10e3eae71d9825a4b429b40b32709df5d1fa55beb3d", size = 44503523, upload-time = "2026-01-18T16:19:03.958Z" }, + { url = "https://files.pythonhosted.org/packages/cc/70/84d45c74341e798aae0323d33b7c39194e23b1abc439ceaf60a68a7a969a/pyarrow-23.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:bd5556c24622df90551063ea41f559b714aa63ca953db884cfb958559087a14e", size = 47542490, upload-time = "2026-01-18T16:19:11.208Z" }, + { url = "https://files.pythonhosted.org/packages/61/d9/d1274b0e6f19e235de17441e53224f4716574b2ca837022d55702f24d71d/pyarrow-23.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54810f6e6afc4ffee7c2e0051b61722fbea9a4961b46192dcfae8ea12fa09059", size = 48233605, upload-time = "2026-01-18T16:19:19.544Z" }, + { url = "https://files.pythonhosted.org/packages/39/07/e4e2d568cb57543d84482f61e510732820cddb0f47c4bb7df629abfed852/pyarrow-23.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:14de7d48052cf4b0ed174533eafa3cfe0711b8076ad70bede32cf59f744f0d7c", size = 50603979, upload-time = "2026-01-18T16:19:26.717Z" }, + { url = "https://files.pythonhosted.org/packages/72/9c/47693463894b610f8439b2e970b82ef81e9599c757bf2049365e40ff963c/pyarrow-23.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:427deac1f535830a744a4f04a6ac183a64fcac4341b3f618e693c41b7b98d2b0", size = 28338905, upload-time = "2026-01-18T16:19:32.93Z" }, +] + +[[package]] +name = "pyasn1" +version = "0.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/b6/6e630dff89739fcd427e3f72b3d905ce0acb85a45d4ec3e2678718a3487f/pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b", size = 146586, upload-time = "2026-01-16T18:04:18.534Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/b5/a96872e5184f354da9c84ae119971a0a4c221fe9b27a4d94bd43f2596727/pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf", size = 83371, upload-time = "2026-01-16T18:04:17.174Z" }, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, +] + [[package]] name = "pycparser" version = "2.23" @@ -2308,6 +3362,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, ] +[[package]] +name = "pyparsing" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, +] + [[package]] name = "pyright" version = "1.1.403" @@ -2407,7 +3470,7 @@ name = "python-dateutil" version = "2.9.0.post0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "six", marker = "python_full_version < '3.14'" }, + { name = "six" }, ] sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } wheels = [ @@ -2846,6 +3909,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ce/08/4349bdd5c64d9d193c360aa9db89adeee6f6682ab8825dca0a3f535f434f/rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dc23e6820e3b40847e2f4a7726462ba0cf53089512abe9ee16318c366494c17a", size = 556523, upload-time = "2025-08-27T12:16:12.188Z" }, ] +[[package]] +name = "rsa" +version = "4.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, +] + [[package]] name = "ruff" version = "0.5.7" @@ -2920,6 +3995,85 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, ] +[[package]] +name = "sqlalchemy" +version = "2.0.46" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/aa/9ce0f3e7a9829ead5c8ce549392f33a12c4555a6c0609bb27d882e9c7ddf/sqlalchemy-2.0.46.tar.gz", hash = "sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7", size = 9865393, upload-time = "2026-01-21T18:03:45.119Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/26/66ba59328dc25e523bfcb0f8db48bdebe2035e0159d600e1f01c0fc93967/sqlalchemy-2.0.46-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735", size = 2155051, upload-time = "2026-01-21T18:27:28.965Z" }, + { url = "https://files.pythonhosted.org/packages/21/cd/9336732941df972fbbfa394db9caa8bb0cf9fe03656ec728d12e9cbd6edc/sqlalchemy-2.0.46-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39", size = 3234666, upload-time = "2026-01-21T18:32:28.72Z" }, + { url = "https://files.pythonhosted.org/packages/38/62/865ae8b739930ec433cd4123760bee7f8dafdc10abefd725a025604fb0de/sqlalchemy-2.0.46-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f", size = 3232917, upload-time = "2026-01-21T18:44:54.064Z" }, + { url = "https://files.pythonhosted.org/packages/24/38/805904b911857f2b5e00fdea44e9570df62110f834378706939825579296/sqlalchemy-2.0.46-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5", size = 3185790, upload-time = "2026-01-21T18:32:30.581Z" }, + { url = "https://files.pythonhosted.org/packages/69/4f/3260bb53aabd2d274856337456ea52f6a7eccf6cce208e558f870cec766b/sqlalchemy-2.0.46-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e", size = 3207206, upload-time = "2026-01-21T18:44:55.93Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b3/67c432d7f9d88bb1a61909b67e29f6354d59186c168fb5d381cf438d3b73/sqlalchemy-2.0.46-cp310-cp310-win32.whl", hash = "sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047", size = 2115296, upload-time = "2026-01-21T18:33:12.498Z" }, + { url = "https://files.pythonhosted.org/packages/4a/8c/25fb284f570f9d48e6c240f0269a50cec9cf009a7e08be4c0aaaf0654972/sqlalchemy-2.0.46-cp310-cp310-win_amd64.whl", hash = "sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061", size = 2138540, upload-time = "2026-01-21T18:33:14.22Z" }, + { url = "https://files.pythonhosted.org/packages/69/ac/b42ad16800d0885105b59380ad69aad0cce5a65276e269ce2729a2343b6a/sqlalchemy-2.0.46-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684", size = 2154851, upload-time = "2026-01-21T18:27:30.54Z" }, + { url = "https://files.pythonhosted.org/packages/a0/60/d8710068cb79f64d002ebed62a7263c00c8fd95f4ebd4b5be8f7ca93f2bc/sqlalchemy-2.0.46-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62", size = 3311241, upload-time = "2026-01-21T18:32:33.45Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/20c71487c7219ab3aa7421c7c62d93824c97c1460f2e8bb72404b0192d13/sqlalchemy-2.0.46-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f", size = 3310741, upload-time = "2026-01-21T18:44:57.887Z" }, + { url = "https://files.pythonhosted.org/packages/65/80/d26d00b3b249ae000eee4db206fcfc564bf6ca5030e4747adf451f4b5108/sqlalchemy-2.0.46-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01", size = 3263116, upload-time = "2026-01-21T18:32:35.044Z" }, + { url = "https://files.pythonhosted.org/packages/da/ee/74dda7506640923821340541e8e45bd3edd8df78664f1f2e0aae8077192b/sqlalchemy-2.0.46-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999", size = 3285327, upload-time = "2026-01-21T18:44:59.254Z" }, + { url = "https://files.pythonhosted.org/packages/9f/25/6dcf8abafff1389a21c7185364de145107b7394ecdcb05233815b236330d/sqlalchemy-2.0.46-cp311-cp311-win32.whl", hash = "sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d", size = 2114564, upload-time = "2026-01-21T18:33:15.85Z" }, + { url = "https://files.pythonhosted.org/packages/93/5f/e081490f8523adc0088f777e4ebad3cac21e498ec8a3d4067074e21447a1/sqlalchemy-2.0.46-cp311-cp311-win_amd64.whl", hash = "sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597", size = 2139233, upload-time = "2026-01-21T18:33:17.528Z" }, + { url = "https://files.pythonhosted.org/packages/b6/35/d16bfa235c8b7caba3730bba43e20b1e376d2224f407c178fbf59559f23e/sqlalchemy-2.0.46-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c", size = 2153405, upload-time = "2026-01-21T19:05:54.143Z" }, + { url = "https://files.pythonhosted.org/packages/06/6c/3192e24486749862f495ddc6584ed730c0c994a67550ec395d872a2ad650/sqlalchemy-2.0.46-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9", size = 3334702, upload-time = "2026-01-21T18:46:45.384Z" }, + { url = "https://files.pythonhosted.org/packages/ea/a2/b9f33c8d68a3747d972a0bb758c6b63691f8fb8a49014bc3379ba15d4274/sqlalchemy-2.0.46-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b", size = 3347664, upload-time = "2026-01-21T18:40:09.979Z" }, + { url = "https://files.pythonhosted.org/packages/aa/d2/3e59e2a91eaec9db7e8dc6b37b91489b5caeb054f670f32c95bcba98940f/sqlalchemy-2.0.46-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53", size = 3277372, upload-time = "2026-01-21T18:46:47.168Z" }, + { url = "https://files.pythonhosted.org/packages/dd/dd/67bc2e368b524e2192c3927b423798deda72c003e73a1e94c21e74b20a85/sqlalchemy-2.0.46-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e", size = 3312425, upload-time = "2026-01-21T18:40:11.548Z" }, + { url = "https://files.pythonhosted.org/packages/43/82/0ecd68e172bfe62247e96cb47867c2d68752566811a4e8c9d8f6e7c38a65/sqlalchemy-2.0.46-cp312-cp312-win32.whl", hash = "sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb", size = 2113155, upload-time = "2026-01-21T18:42:49.748Z" }, + { url = "https://files.pythonhosted.org/packages/bc/2a/2821a45742073fc0331dc132552b30de68ba9563230853437cac54b2b53e/sqlalchemy-2.0.46-cp312-cp312-win_amd64.whl", hash = "sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff", size = 2140078, upload-time = "2026-01-21T18:42:51.197Z" }, + { url = "https://files.pythonhosted.org/packages/b3/4b/fa7838fe20bb752810feed60e45625a9a8b0102c0c09971e2d1d95362992/sqlalchemy-2.0.46-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00", size = 2150268, upload-time = "2026-01-21T19:05:56.621Z" }, + { url = "https://files.pythonhosted.org/packages/46/c1/b34dccd712e8ea846edf396e00973dda82d598cb93762e55e43e6835eba9/sqlalchemy-2.0.46-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2", size = 3276511, upload-time = "2026-01-21T18:46:49.022Z" }, + { url = "https://files.pythonhosted.org/packages/96/48/a04d9c94753e5d5d096c628c82a98c4793b9c08ca0e7155c3eb7d7db9f24/sqlalchemy-2.0.46-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee", size = 3292881, upload-time = "2026-01-21T18:40:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/be/f4/06eda6e91476f90a7d8058f74311cb65a2fb68d988171aced81707189131/sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad", size = 3224559, upload-time = "2026-01-21T18:46:50.974Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a2/d2af04095412ca6345ac22b33b89fe8d6f32a481e613ffcb2377d931d8d0/sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e", size = 3262728, upload-time = "2026-01-21T18:40:14.883Z" }, + { url = "https://files.pythonhosted.org/packages/31/48/1980c7caa5978a3b8225b4d230e69a2a6538a3562b8b31cea679b6933c83/sqlalchemy-2.0.46-cp313-cp313-win32.whl", hash = "sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f", size = 2111295, upload-time = "2026-01-21T18:42:52.366Z" }, + { url = "https://files.pythonhosted.org/packages/2d/54/f8d65bbde3d877617c4720f3c9f60e99bb7266df0d5d78b6e25e7c149f35/sqlalchemy-2.0.46-cp313-cp313-win_amd64.whl", hash = "sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef", size = 2137076, upload-time = "2026-01-21T18:42:53.924Z" }, + { url = "https://files.pythonhosted.org/packages/56/ba/9be4f97c7eb2b9d5544f2624adfc2853e796ed51d2bb8aec90bc94b7137e/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10", size = 3556533, upload-time = "2026-01-21T18:33:06.636Z" }, + { url = "https://files.pythonhosted.org/packages/20/a6/b1fc6634564dbb4415b7ed6419cdfeaadefd2c39cdab1e3aa07a5f2474c2/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764", size = 3523208, upload-time = "2026-01-21T18:45:08.436Z" }, + { url = "https://files.pythonhosted.org/packages/a1/d8/41e0bdfc0f930ff236f86fccd12962d8fa03713f17ed57332d38af6a3782/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b", size = 3464292, upload-time = "2026-01-21T18:33:08.208Z" }, + { url = "https://files.pythonhosted.org/packages/f0/8b/9dcbec62d95bea85f5ecad9b8d65b78cc30fb0ffceeb3597961f3712549b/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447", size = 3473497, upload-time = "2026-01-21T18:45:10.552Z" }, + { url = "https://files.pythonhosted.org/packages/e9/f8/5ecdfc73383ec496de038ed1614de9e740a82db9ad67e6e4514ebc0708a3/sqlalchemy-2.0.46-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada", size = 2152079, upload-time = "2026-01-21T19:05:58.477Z" }, + { url = "https://files.pythonhosted.org/packages/e5/bf/eba3036be7663ce4d9c050bc3d63794dc29fbe01691f2bf5ccb64e048d20/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366", size = 3272216, upload-time = "2026-01-21T18:46:52.634Z" }, + { url = "https://files.pythonhosted.org/packages/05/45/1256fb597bb83b58a01ddb600c59fe6fdf0e5afe333f0456ed75c0f8d7bd/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d", size = 3277208, upload-time = "2026-01-21T18:40:16.38Z" }, + { url = "https://files.pythonhosted.org/packages/d9/a0/2053b39e4e63b5d7ceb3372cface0859a067c1ddbd575ea7e9985716f771/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e", size = 3221994, upload-time = "2026-01-21T18:46:54.622Z" }, + { url = "https://files.pythonhosted.org/packages/1e/87/97713497d9502553c68f105a1cb62786ba1ee91dea3852ae4067ed956a50/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf", size = 3243990, upload-time = "2026-01-21T18:40:18.253Z" }, + { url = "https://files.pythonhosted.org/packages/a8/87/5d1b23548f420ff823c236f8bea36b1a997250fd2f892e44a3838ca424f4/sqlalchemy-2.0.46-cp314-cp314-win32.whl", hash = "sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908", size = 2114215, upload-time = "2026-01-21T18:42:55.232Z" }, + { url = "https://files.pythonhosted.org/packages/3a/20/555f39cbcf0c10cf452988b6a93c2a12495035f68b3dbd1a408531049d31/sqlalchemy-2.0.46-cp314-cp314-win_amd64.whl", hash = "sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b", size = 2139867, upload-time = "2026-01-21T18:42:56.474Z" }, + { url = "https://files.pythonhosted.org/packages/3e/f0/f96c8057c982d9d8a7a68f45d69c674bc6f78cad401099692fe16521640a/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa", size = 3561202, upload-time = "2026-01-21T18:33:10.337Z" }, + { url = "https://files.pythonhosted.org/packages/d7/53/3b37dda0a5b137f21ef608d8dfc77b08477bab0fe2ac9d3e0a66eaeab6fc/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863", size = 3526296, upload-time = "2026-01-21T18:45:12.657Z" }, + { url = "https://files.pythonhosted.org/packages/33/75/f28622ba6dde79cd545055ea7bd4062dc934e0621f7b3be2891f8563f8de/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede", size = 3470008, upload-time = "2026-01-21T18:33:11.725Z" }, + { url = "https://files.pythonhosted.org/packages/a9/42/4afecbbc38d5e99b18acef446453c76eec6fbd03db0a457a12a056836e22/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330", size = 3476137, upload-time = "2026-01-21T18:45:15.001Z" }, + { url = "https://files.pythonhosted.org/packages/fc/a1/9c4efa03300926601c19c18582531b45aededfb961ab3c3585f1e24f120b/sqlalchemy-2.0.46-py3-none-any.whl", hash = "sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e", size = 1937882, upload-time = "2026-01-21T18:22:10.456Z" }, +] + +[[package]] +name = "sqlalchemy-spanner" +version = "1.17.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "alembic" }, + { name = "google-cloud-spanner" }, + { name = "sqlalchemy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/29/21698bb83e542f32e3581886671f39d94b1f7e8b190c24a8bfa994e62fd6/sqlalchemy_spanner-1.17.2.tar.gz", hash = "sha256:56ce4da7168a27442d80ffd71c29ed639b5056d7e69b1e69bb9c1e10190b67c4", size = 82745, upload-time = "2025-12-15T23:30:08.622Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/87/05be45a086116cea32cfa00fa0059d31b5345360dba7902ee640a1db793b/sqlalchemy_spanner-1.17.2-py3-none-any.whl", hash = "sha256:18713d4d78e0bf048eda0f7a5c80733e08a7b678b34349496415f37652efb12f", size = 31917, upload-time = "2025-12-15T23:30:07.356Z" }, +] + +[[package]] +name = "sqlparse" +version = "0.5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/90/76/437d71068094df0726366574cf3432a4ed754217b436eb7429415cf2d480/sqlparse-0.5.5.tar.gz", hash = "sha256:e20d4a9b0b8585fdf63b10d30066c7c94c5d7a7ec47c889a2d83a3caa93ff28e", size = 120815, upload-time = "2025-12-19T07:17:45.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/4b/359f28a903c13438ef59ebeee215fb25da53066db67b305c125f1c6d2a25/sqlparse-0.5.5-py3-none-any.whl", hash = "sha256:12a08b3bf3eec877c519589833aed092e2444e68240a3577e8e26148acc7b1ba", size = 46138, upload-time = "2025-12-19T07:17:46.573Z" }, +] + [[package]] name = "sse-starlette" version = "3.0.2" @@ -2934,15 +4088,15 @@ wheels = [ [[package]] name = "starlette" -version = "0.48.0" +version = "0.50.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a7/a5/d6f429d43394057b67a6b5bbe6eae2f77a6bf7459d961fdb224bf206eee6/starlette-0.48.0.tar.gz", hash = "sha256:7e8cee469a8ab2352911528110ce9088fdc6a37d9876926e73da7ce4aa4c7a46", size = 2652949, upload-time = "2025-09-13T08:41:05.699Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/b8/73a0e6a6e079a9d9cfa64113d771e421640b6f679a52eeb9b32f72d871a1/starlette-0.50.0.tar.gz", hash = "sha256:a2a17b22203254bcbc2e1f926d2d55f3f9497f769416b3190768befe598fa3ca", size = 2646985, upload-time = "2025-11-01T15:25:27.516Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/72/2db2f49247d0a18b4f1bb9a5a39a0162869acf235f3a96418363947b3d46/starlette-0.48.0-py3-none-any.whl", hash = "sha256:0764ca97b097582558ecb498132ed0c7d942f233f365b86ba37770e026510659", size = 73736, upload-time = "2025-09-13T08:41:03.869Z" }, + { url = "https://files.pythonhosted.org/packages/d9/52/1064f510b141bd54025f9b55105e26d1fa970b9be67ad766380a3c9b74b0/starlette-0.50.0-py3-none-any.whl", hash = "sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca", size = 74033, upload-time = "2025-11-01T15:25:25.461Z" }, ] [[package]] @@ -2977,6 +4131,7 @@ pydantic = [ dev = [ { name = "basedpyright" }, { name = "cibuildwheel" }, + { name = "google-adk" }, { name = "googleapis-common-protos" }, { name = "grpcio-tools" }, { name = "httpx" }, @@ -3020,6 +4175,7 @@ provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents"] dev = [ { name = "basedpyright", specifier = "==1.34.0" }, { name = "cibuildwheel", specifier = ">=2.22.0,<3" }, + { name = "google-adk", git = "https://github.com/marcusmotill/adk-python-temporal.git?rev=motill%2Fdurable-support" }, { name = "googleapis-common-protos", specifier = "==1.70.0" }, { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, @@ -3043,6 +4199,15 @@ dev = [ { name = "twine", specifier = ">=4.0.1,<5" }, ] +[[package]] +name = "tenacity" +version = "9.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, +] + [[package]] name = "tiktoken" version = "0.12.0" @@ -3279,6 +4444,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] +[[package]] +name = "tzdata" +version = "2025.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, +] + +[[package]] +name = "tzlocal" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/2e/c14812d3d4d9cd1773c6be938f89e5735a1f11a9f184ac3639b93cef35d5/tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd", size = 30761, upload-time = "2025-03-05T21:17:41.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/14/e2a54fabd4f08cd7af1c07030603c3356b74da07f7cc056e600436edfa17/tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d", size = 18026, upload-time = "2025-03-05T21:17:39.857Z" }, +] + +[[package]] +name = "uritemplate" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/60/f174043244c5306c9988380d2cb10009f91563fc4b31293d27e17201af56/uritemplate-4.2.0.tar.gz", hash = "sha256:480c2ed180878955863323eea31b0ede668795de182617fef9c6ca09e6ec9d0e", size = 33267, upload-time = "2025-06-02T15:12:06.318Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/99/3ae339466c9183ea5b8ae87b34c0b897eda475d2aec2307cae60e5cd4f29/uritemplate-4.2.0-py3-none-any.whl", hash = "sha256:962201ba1c4edcab02e60f9a0d3821e82dfc5d2d6662a21abd533879bdb8a686", size = 11488, upload-time = "2025-06-02T15:12:03.405Z" }, +] + [[package]] name = "urllib3" version = "2.5.0" @@ -3302,6 +4497,97 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/85/cd/584a2ceb5532af99dd09e50919e3615ba99aa127e9850eafe5f31ddfdb9a/uvicorn-0.37.0-py3-none-any.whl", hash = "sha256:913b2b88672343739927ce381ff9e2ad62541f9f8289664fa1d1d3803fa2ce6c", size = 67976, upload-time = "2025-09-23T13:33:45.842Z" }, ] +[[package]] +name = "watchdog" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/56/90994d789c61df619bfc5ce2ecdabd5eeff564e1eb47512bd01b5e019569/watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26", size = 96390, upload-time = "2024-11-01T14:06:24.793Z" }, + { url = "https://files.pythonhosted.org/packages/55/46/9a67ee697342ddf3c6daa97e3a587a56d6c4052f881ed926a849fcf7371c/watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112", size = 88389, upload-time = "2024-11-01T14:06:27.112Z" }, + { url = "https://files.pythonhosted.org/packages/44/65/91b0985747c52064d8701e1075eb96f8c40a79df889e59a399453adfb882/watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3", size = 89020, upload-time = "2024-11-01T14:06:29.876Z" }, + { url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393, upload-time = "2024-11-01T14:06:31.756Z" }, + { url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392, upload-time = "2024-11-01T14:06:32.99Z" }, + { url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019, upload-time = "2024-11-01T14:06:34.963Z" }, + { url = "https://files.pythonhosted.org/packages/39/ea/3930d07dafc9e286ed356a679aa02d777c06e9bfd1164fa7c19c288a5483/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948", size = 96471, upload-time = "2024-11-01T14:06:37.745Z" }, + { url = "https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860", size = 88449, upload-time = "2024-11-01T14:06:39.748Z" }, + { url = "https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0", size = 89054, upload-time = "2024-11-01T14:06:41.009Z" }, + { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" }, + { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" }, + { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" }, + { url = "https://files.pythonhosted.org/packages/30/ad/d17b5d42e28a8b91f8ed01cb949da092827afb9995d4559fd448d0472763/watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881", size = 87902, upload-time = "2024-11-01T14:06:53.119Z" }, + { url = "https://files.pythonhosted.org/packages/5c/ca/c3649991d140ff6ab67bfc85ab42b165ead119c9e12211e08089d763ece5/watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11", size = 88380, upload-time = "2024-11-01T14:06:55.19Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" }, + { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" }, + { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" }, + { url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077, upload-time = "2024-11-01T14:07:03.893Z" }, + { url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078, upload-time = "2024-11-01T14:07:05.189Z" }, + { url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077, upload-time = "2024-11-01T14:07:06.376Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078, upload-time = "2024-11-01T14:07:07.547Z" }, + { url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065, upload-time = "2024-11-01T14:07:09.525Z" }, + { url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070, upload-time = "2024-11-01T14:07:10.686Z" }, + { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, +] + +[[package]] +name = "websockets" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/da/6462a9f510c0c49837bbc9345aca92d767a56c1fb2939e1579df1e1cdcf7/websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b", size = 175423, upload-time = "2025-03-05T20:01:35.363Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9f/9d11c1a4eb046a9e106483b9ff69bce7ac880443f00e5ce64261b47b07e7/websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205", size = 173080, upload-time = "2025-03-05T20:01:37.304Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4f/b462242432d93ea45f297b6179c7333dd0402b855a912a04e7fc61c0d71f/websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a", size = 173329, upload-time = "2025-03-05T20:01:39.668Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0c/6afa1f4644d7ed50284ac59cc70ef8abd44ccf7d45850d989ea7310538d0/websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e", size = 182312, upload-time = "2025-03-05T20:01:41.815Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d4/ffc8bd1350b229ca7a4db2a3e1c482cf87cea1baccd0ef3e72bc720caeec/websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf", size = 181319, upload-time = "2025-03-05T20:01:43.967Z" }, + { url = "https://files.pythonhosted.org/packages/97/3a/5323a6bb94917af13bbb34009fac01e55c51dfde354f63692bf2533ffbc2/websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb", size = 181631, upload-time = "2025-03-05T20:01:46.104Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cc/1aeb0f7cee59ef065724041bb7ed667b6ab1eeffe5141696cccec2687b66/websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d", size = 182016, upload-time = "2025-03-05T20:01:47.603Z" }, + { url = "https://files.pythonhosted.org/packages/79/f9/c86f8f7af208e4161a7f7e02774e9d0a81c632ae76db2ff22549e1718a51/websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9", size = 181426, upload-time = "2025-03-05T20:01:48.949Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b9/828b0bc6753db905b91df6ae477c0b14a141090df64fb17f8a9d7e3516cf/websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c", size = 181360, upload-time = "2025-03-05T20:01:50.938Z" }, + { url = "https://files.pythonhosted.org/packages/89/fb/250f5533ec468ba6327055b7d98b9df056fb1ce623b8b6aaafb30b55d02e/websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256", size = 176388, upload-time = "2025-03-05T20:01:52.213Z" }, + { url = "https://files.pythonhosted.org/packages/1c/46/aca7082012768bb98e5608f01658ff3ac8437e563eca41cf068bd5849a5e/websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41", size = 176830, upload-time = "2025-03-05T20:01:53.922Z" }, + { url = "https://files.pythonhosted.org/packages/9f/32/18fcd5919c293a398db67443acd33fde142f283853076049824fc58e6f75/websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431", size = 175423, upload-time = "2025-03-05T20:01:56.276Z" }, + { url = "https://files.pythonhosted.org/packages/76/70/ba1ad96b07869275ef42e2ce21f07a5b0148936688c2baf7e4a1f60d5058/websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57", size = 173082, upload-time = "2025-03-05T20:01:57.563Z" }, + { url = "https://files.pythonhosted.org/packages/86/f2/10b55821dd40eb696ce4704a87d57774696f9451108cff0d2824c97e0f97/websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905", size = 173330, upload-time = "2025-03-05T20:01:59.063Z" }, + { url = "https://files.pythonhosted.org/packages/a5/90/1c37ae8b8a113d3daf1065222b6af61cc44102da95388ac0018fcb7d93d9/websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562", size = 182878, upload-time = "2025-03-05T20:02:00.305Z" }, + { url = "https://files.pythonhosted.org/packages/8e/8d/96e8e288b2a41dffafb78e8904ea7367ee4f891dafc2ab8d87e2124cb3d3/websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792", size = 181883, upload-time = "2025-03-05T20:02:03.148Z" }, + { url = "https://files.pythonhosted.org/packages/93/1f/5d6dbf551766308f6f50f8baf8e9860be6182911e8106da7a7f73785f4c4/websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413", size = 182252, upload-time = "2025-03-05T20:02:05.29Z" }, + { url = "https://files.pythonhosted.org/packages/d4/78/2d4fed9123e6620cbf1706c0de8a1632e1a28e7774d94346d7de1bba2ca3/websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8", size = 182521, upload-time = "2025-03-05T20:02:07.458Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3b/66d4c1b444dd1a9823c4a81f50231b921bab54eee2f69e70319b4e21f1ca/websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3", size = 181958, upload-time = "2025-03-05T20:02:09.842Z" }, + { url = "https://files.pythonhosted.org/packages/08/ff/e9eed2ee5fed6f76fdd6032ca5cd38c57ca9661430bb3d5fb2872dc8703c/websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf", size = 181918, upload-time = "2025-03-05T20:02:11.968Z" }, + { url = "https://files.pythonhosted.org/packages/d8/75/994634a49b7e12532be6a42103597b71098fd25900f7437d6055ed39930a/websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85", size = 176388, upload-time = "2025-03-05T20:02:13.32Z" }, + { url = "https://files.pythonhosted.org/packages/98/93/e36c73f78400a65f5e236cd376713c34182e6663f6889cd45a4a04d8f203/websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065", size = 176828, upload-time = "2025-03-05T20:02:14.585Z" }, + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440, upload-time = "2025-03-05T20:02:36.695Z" }, + { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098, upload-time = "2025-03-05T20:02:37.985Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329, upload-time = "2025-03-05T20:02:39.298Z" }, + { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111, upload-time = "2025-03-05T20:02:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054, upload-time = "2025-03-05T20:02:41.926Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496, upload-time = "2025-03-05T20:02:43.304Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829, upload-time = "2025-03-05T20:02:48.812Z" }, + { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217, upload-time = "2025-03-05T20:02:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/d40f779fa16f74d3468357197af8d6ad07e7c5a27ea1ca74ceb38986f77a/websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3", size = 173109, upload-time = "2025-03-05T20:03:17.769Z" }, + { url = "https://files.pythonhosted.org/packages/bc/cd/5b887b8585a593073fd92f7c23ecd3985cd2c3175025a91b0d69b0551372/websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1", size = 173343, upload-time = "2025-03-05T20:03:19.094Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ae/d34f7556890341e900a95acf4886833646306269f899d58ad62f588bf410/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475", size = 174599, upload-time = "2025-03-05T20:03:21.1Z" }, + { url = "https://files.pythonhosted.org/packages/71/e6/5fd43993a87db364ec60fc1d608273a1a465c0caba69176dd160e197ce42/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9", size = 174207, upload-time = "2025-03-05T20:03:23.221Z" }, + { url = "https://files.pythonhosted.org/packages/2b/fb/c492d6daa5ec067c2988ac80c61359ace5c4c674c532985ac5a123436cec/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04", size = 174155, upload-time = "2025-03-05T20:03:25.321Z" }, + { url = "https://files.pythonhosted.org/packages/68/a1/dcb68430b1d00b698ae7a7e0194433bce4f07ded185f0ee5fb21e2a2e91e/websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122", size = 176884, upload-time = "2025-03-05T20:03:27.934Z" }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +] + [[package]] name = "yarl" version = "1.22.0" From dbf35b2bce4c7cc8877f575d35e629631548f10b Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Mon, 26 Jan 2026 09:07:43 -0800 Subject: [PATCH 3/6] Fix copy paste error string --- temporalio/contrib/google_adk_agents/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/temporalio/contrib/google_adk_agents/__init__.py b/temporalio/contrib/google_adk_agents/__init__.py index faa97967b..b4358dabe 100644 --- a/temporalio/contrib/google_adk_agents/__init__.py +++ b/temporalio/contrib/google_adk_agents/__init__.py @@ -185,7 +185,7 @@ async def run_context() -> AsyncIterator[None]: def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: if not runner: - raise ValueError("No WorkflowRunner provided to the OpenAI plugin.") + raise ValueError("No WorkflowRunner provided to the ADK plugin.") # If in sandbox, add additional passthrough if isinstance(runner, SandboxedWorkflowRunner): From 1f534abebd126bda56ccb8eb750f9042e0982597 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Mon, 26 Jan 2026 13:12:50 -0800 Subject: [PATCH 4/6] Add replay validation and local model validation --- .../contrib/google_adk_agents/__init__.py | 52 +- .../histories/multi_agent.json | 499 ++++++++++++++++++ .../histories/single_agent.json | 491 +++++++++++++++++ ...tegration.py => test_google_adk_agents.py} | 198 +++++-- .../test_google_adk_agents_replay.py | 33 ++ .../google_adk_agents/test_temporal_unit.py | 177 ------- 6 files changed, 1189 insertions(+), 261 deletions(-) create mode 100644 tests/contrib/google_adk_agents/histories/multi_agent.json create mode 100644 tests/contrib/google_adk_agents/histories/single_agent.json rename tests/contrib/google_adk_agents/{test_temporal_integration.py => test_google_adk_agents.py} (54%) create mode 100644 tests/contrib/google_adk_agents/test_google_adk_agents_replay.py delete mode 100644 tests/contrib/google_adk_agents/test_temporal_unit.py diff --git a/temporalio/contrib/google_adk_agents/__init__.py b/temporalio/contrib/google_adk_agents/__init__.py index b4358dabe..2e094fe3d 100644 --- a/temporalio/contrib/google_adk_agents/__init__.py +++ b/temporalio/contrib/google_adk_agents/__init__.py @@ -19,36 +19,26 @@ from __future__ import annotations -import asyncio import dataclasses -import functools import inspect import time import uuid -from collections.abc import Sequence from contextlib import asynccontextmanager -from datetime import timedelta -from typing import Any, AsyncGenerator, Callable, List, Optional, AsyncIterator +from typing import Any, AsyncIterator, Callable, Optional from google.adk.agents.callback_context import CallbackContext -from google.adk.agents.invocation_context import InvocationContext -from google.adk.models import BaseLlm, LLMRegistry, LlmRequest, LlmResponse +from google.adk.models import LLMRegistry +from google.adk.models.llm_request import LlmRequest +from google.adk.models.llm_response import LlmResponse from google.adk.plugins import BasePlugin -from google.genai import types from temporalio import activity, workflow -from temporalio.common import RawValue, RetryPolicy from temporalio.contrib.pydantic import ( PydanticPayloadConverter as _DefaultPydanticPayloadConverter, ) from temporalio.converter import DataConverter, DefaultPayloadConverter from temporalio.plugin import SimplePlugin from temporalio.worker import ( - ExecuteWorkflowInput, - Interceptor, - UnsandboxedWorkflowRunner, - WorkflowInboundInterceptor, - WorkflowInterceptorClassInput, WorkflowRunner, ) from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner @@ -125,7 +115,7 @@ async def wrapper(*args, **kw): # Copy metadata wrapper.__name__ = activity_def.__name__ wrapper.__doc__ = activity_def.__doc__ - wrapper.__signature__ = inspect.signature(activity_def) + setattr(wrapper, "__signature__", inspect.signature(activity_def)) return wrapper @@ -133,40 +123,30 @@ async def before_model_callback( self, *, callback_context: CallbackContext, llm_request: LlmRequest ) -> LlmResponse | None: responses = await workflow.execute_activity( - invoke_model, args=[llm_request], summary=callback_context.agent_name, **self.activity_options + invoke_model, + args=[llm_request], + summary=callback_context.agent_name, + **self.activity_options, ) - # # Rehydrate LlmResponse objects safely - # responses = [] - # for d in response_dicts: - # try: - # responses.append(LlmResponse.model_validate(d)) - # except Exception as e: - # raise RuntimeError( - # f"Failed to deserialized LlmResponse from activity result: {e}" - # ) from e - # Simple consolidation: return the last complete response return responses[-1] if responses else None @activity.defn async def invoke_model(llm_request: LlmRequest) -> list[LlmResponse]: + if llm_request.model is None: + raise ValueError(f"No model name provided, could not create LLM.") - # 3. Model Initialization llm = LLMRegistry.new_llm(llm_request.model) if not llm: raise ValueError(f"Failed to create LLM for model: {llm_request.model}") - # 4. Execution - responses = [ + return [ response async for response in llm.generate_content_async(llm_request=llm_request) ] - # 5. Serialization - # Return dicts to avoid Pydantic strictness issues on rehydration - return responses class GoogleAdkPlugin(SimplePlugin): """A Temporal Worker Plugin configured for ADK. @@ -177,7 +157,6 @@ class GoogleAdkPlugin(SimplePlugin): """ def __init__(self): - @asynccontextmanager async def run_context() -> AsyncIterator[None]: setup_deterministic_runtime() @@ -191,7 +170,9 @@ def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: if isinstance(runner, SandboxedWorkflowRunner): return dataclasses.replace( runner, - restrictions=runner.restrictions.with_passthrough_modules("google.adk", "google.genai"), + restrictions=runner.restrictions.with_passthrough_modules( + "google.adk", "google.genai" + ), ) return runner @@ -200,7 +181,7 @@ def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: data_converter=self._configure_data_converter, activities=[invoke_model], run_context=lambda: run_context(), - workflow_runner=workflow_runner + workflow_runner=workflow_runner, ) def _configure_data_converter( @@ -215,4 +196,3 @@ def _configure_data_converter( converter, payload_converter_class=_DefaultPydanticPayloadConverter ) return converter - diff --git a/tests/contrib/google_adk_agents/histories/multi_agent.json b/tests/contrib/google_adk_agents/histories/multi_agent.json new file mode 100644 index 000000000..7323575d9 --- /dev/null +++ b/tests/contrib/google_adk_agents/histories/multi_agent.json @@ -0,0 +1,499 @@ +{ + "events": [ + { + "eventId": "1", + "eventTime": "2026-01-26T21:08:54.450497Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_STARTED", + "taskId": "1103693", + "workflowExecutionStartedEventAttributes": { + "workflowType": { + "name": "MultiAgentWorkflow" + }, + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IlJ1biBtdWx0LWFnZW50IGZsb3ci" + }, + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "InJlc2VhcmNoX21vZGVsIg==" + } + ] + }, + "workflowTaskTimeout": "10s", + "originalExecutionRunId": "019bfc23-5c32-7791-ae30-aa4b590df541", + "identity": "69823@Tims-MacBook-Pro.local", + "firstExecutionRunId": "019bfc23-5c32-7791-ae30-aa4b590df541", + "attempt": 1, + "firstWorkflowTaskBackoff": "0s", + "workflowId": "multi-agent-workflow-a0d23123-4773-479e-849e-e66e529cd9aa", + "priority": {} + } + }, + { + "eventId": "2", + "eventTime": "2026-01-26T21:08:54.450553Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1103694", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "3", + "eventTime": "2026-01-26T21:08:54.451648Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1103699", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "2", + "identity": "69823@Tims-MacBook-Pro.local", + "requestId": "35fb116a-4647-4936-9f56-688f623a4a1f", + "historySizeBytes": "397", + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + } + } + }, + { + "eventId": "4", + "eventTime": "2026-01-26T21:08:54.511359Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1103703", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "2", + "startedEventId": "3", + "identity": "69823@Tims-MacBook-Pro.local", + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + }, + "sdkMetadata": { + "coreUsedFlags": [ + 2, + 3, + 1 + ], + "sdkName": "temporal-python", + "sdkVersion": "1.21.1" + }, + "meteringMetadata": {} + } + }, + { + "eventId": "5", + "eventTime": "2026-01-26T21:08:54.511391Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "1103704", + "activityTaskScheduledEventAttributes": { + "activityId": "1", + "activityType": { + "name": "invoke_model" + }, + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "eyJtb2RlbCI6InJlc2VhcmNoX21vZGVsIiwiY29udGVudHMiOlt7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjpudWxsLCJmdW5jdGlvblJlc3BvbnNlIjpudWxsLCJpbmxpbmVEYXRhIjpudWxsLCJ0ZXh0IjoiV3JpdGUgYSBoYWlrdSBhYm91dCBSdW4gbXVsdC1hZ2VudCBmbG93LiBGaXJzdCByZXNlYXJjaCBpdCwgdGhlbiB3cml0ZSBpdC4iLCJ0aG91Z2h0IjpudWxsLCJ0aG91Z2h0U2lnbmF0dXJlIjpudWxsLCJ2aWRlb01ldGFkYXRhIjpudWxsfV0sInJvbGUiOiJ1c2VyIn1dLCJjb25maWciOnsiaHR0cE9wdGlvbnMiOm51bGwsInNob3VsZFJldHVybkh0dHBSZXNwb25zZSI6bnVsbCwic3lzdGVtSW5zdHJ1Y3Rpb24iOiJZb3UgYXJlIGEgY29vcmRpbmF0b3IuIERlbGVnYXRlIHRvIHJlc2VhcmNoZXIgdGhlbiB3cml0ZXIuXG5cbllvdSBhcmUgYW4gYWdlbnQuIFlvdXIgaW50ZXJuYWwgbmFtZSBpcyBcImNvb3JkaW5hdG9yXCIuXG5cblxuWW91IGhhdmUgYSBsaXN0IG9mIG90aGVyIGFnZW50cyB0byB0cmFuc2ZlciB0bzpcblxuXG5BZ2VudCBuYW1lOiByZXNlYXJjaGVyXG5BZ2VudCBkZXNjcmlwdGlvbjogXG5cblxuQWdlbnQgbmFtZTogd3JpdGVyXG5BZ2VudCBkZXNjcmlwdGlvbjogXG5cblxuSWYgeW91IGFyZSB0aGUgYmVzdCB0byBhbnN3ZXIgdGhlIHF1ZXN0aW9uIGFjY29yZGluZyB0byB5b3VyIGRlc2NyaXB0aW9uLFxueW91IGNhbiBhbnN3ZXIgaXQuXG5cbklmIGFub3RoZXIgYWdlbnQgaXMgYmV0dGVyIGZvciBhbnN3ZXJpbmcgdGhlIHF1ZXN0aW9uIGFjY29yZGluZyB0byBpdHNcbmRlc2NyaXB0aW9uLCBjYWxsIGB0cmFuc2Zlcl90b19hZ2VudGAgZnVuY3Rpb24gdG8gdHJhbnNmZXIgdGhlIHF1ZXN0aW9uIHRvIHRoYXRcbmFnZW50LiBXaGVuIHRyYW5zZmVycmluZywgZG8gbm90IGdlbmVyYXRlIGFueSB0ZXh0IG90aGVyIHRoYW4gdGhlIGZ1bmN0aW9uXG5jYWxsLlxuXG4qKk5PVEUqKjogdGhlIG9ubHkgYXZhaWxhYmxlIGFnZW50cyBmb3IgYHRyYW5zZmVyX3RvX2FnZW50YCBmdW5jdGlvbiBhcmVcbmByZXNlYXJjaGVyYCwgYHdyaXRlcmAuXG4iLCJ0ZW1wZXJhdHVyZSI6bnVsbCwidG9wUCI6bnVsbCwidG9wSyI6bnVsbCwiY2FuZGlkYXRlQ291bnQiOm51bGwsIm1heE91dHB1dFRva2VucyI6bnVsbCwic3RvcFNlcXVlbmNlcyI6bnVsbCwicmVzcG9uc2VMb2dwcm9icyI6bnVsbCwibG9ncHJvYnMiOm51bGwsInByZXNlbmNlUGVuYWx0eSI6bnVsbCwiZnJlcXVlbmN5UGVuYWx0eSI6bnVsbCwic2VlZCI6bnVsbCwicmVzcG9uc2VNaW1lVHlwZSI6bnVsbCwicmVzcG9uc2VTY2hlbWEiOm51bGwsInJlc3BvbnNlSnNvblNjaGVtYSI6bnVsbCwicm91dGluZ0NvbmZpZyI6bnVsbCwibW9kZWxTZWxlY3Rpb25Db25maWciOm51bGwsInNhZmV0eVNldHRpbmdzIjpudWxsLCJ0b29scyI6W3sicmV0cmlldmFsIjpudWxsLCJjb21wdXRlclVzZSI6bnVsbCwiZmlsZVNlYXJjaCI6bnVsbCwiY29kZUV4ZWN1dGlvbiI6bnVsbCwiZW50ZXJwcmlzZVdlYlNlYXJjaCI6bnVsbCwiZnVuY3Rpb25EZWNsYXJhdGlvbnMiOlt7ImRlc2NyaXB0aW9uIjoiVHJhbnNmZXIgdGhlIHF1ZXN0aW9uIHRvIGFub3RoZXIgYWdlbnQuXG5cblRoaXMgdG9vbCBoYW5kcyBvZmYgY29udHJvbCB0byBhbm90aGVyIGFnZW50IHdoZW4gaXQncyBtb3JlIHN1aXRhYmxlIHRvXG5hbnN3ZXIgdGhlIHVzZXIncyBxdWVzdGlvbiBhY2NvcmRpbmcgdG8gdGhlIGFnZW50J3MgZGVzY3JpcHRpb24uXG5cbk5vdGU6XG4gIEZvciBtb3N0IHVzZSBjYXNlcywgeW91IHNob3VsZCB1c2UgVHJhbnNmZXJUb0FnZW50VG9vbCBpbnN0ZWFkIG9mIHRoaXNcbiAgZnVuY3Rpb24gZGlyZWN0bHkuIFRyYW5zZmVyVG9BZ2VudFRvb2wgcHJvdmlkZXMgYWRkaXRpb25hbCBlbnVtIGNvbnN0cmFpbnRzXG4gIHRoYXQgcHJldmVudCBMTE1zIGZyb20gaGFsbHVjaW5hdGluZyBpbnZhbGlkIGFnZW50IG5hbWVzLlxuXG5BcmdzOlxuICBhZ2VudF9uYW1lOiB0aGUgYWdlbnQgbmFtZSB0byB0cmFuc2ZlciB0by5cbiIsIm5hbWUiOiJ0cmFuc2Zlcl90b19hZ2VudCIsInBhcmFtZXRlcnMiOnsiYWRkaXRpb25hbFByb3BlcnRpZXMiOm51bGwsImRlZnMiOm51bGwsInJlZiI6bnVsbCwiYW55T2YiOm51bGwsImRlZmF1bHQiOm51bGwsImRlc2NyaXB0aW9uIjpudWxsLCJlbnVtIjpudWxsLCJleGFtcGxlIjpudWxsLCJmb3JtYXQiOm51bGwsIml0ZW1zIjpudWxsLCJtYXhJdGVtcyI6bnVsbCwibWF4TGVuZ3RoIjpudWxsLCJtYXhQcm9wZXJ0aWVzIjpudWxsLCJtYXhpbXVtIjpudWxsLCJtaW5JdGVtcyI6bnVsbCwibWluTGVuZ3RoIjpudWxsLCJtaW5Qcm9wZXJ0aWVzIjpudWxsLCJtaW5pbXVtIjpudWxsLCJudWxsYWJsZSI6bnVsbCwicGF0dGVybiI6bnVsbCwicHJvcGVydGllcyI6eyJhZ2VudF9uYW1lIjp7ImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjpudWxsLCJkZWZzIjpudWxsLCJyZWYiOm51bGwsImFueU9mIjpudWxsLCJkZWZhdWx0IjpudWxsLCJkZXNjcmlwdGlvbiI6bnVsbCwiZW51bSI6WyJyZXNlYXJjaGVyIiwid3JpdGVyIl0sImV4YW1wbGUiOm51bGwsImZvcm1hdCI6bnVsbCwiaXRlbXMiOm51bGwsIm1heEl0ZW1zIjpudWxsLCJtYXhMZW5ndGgiOm51bGwsIm1heFByb3BlcnRpZXMiOm51bGwsIm1heGltdW0iOm51bGwsIm1pbkl0ZW1zIjpudWxsLCJtaW5MZW5ndGgiOm51bGwsIm1pblByb3BlcnRpZXMiOm51bGwsIm1pbmltdW0iOm51bGwsIm51bGxhYmxlIjpudWxsLCJwYXR0ZXJuIjpudWxsLCJwcm9wZXJ0aWVzIjpudWxsLCJwcm9wZXJ0eU9yZGVyaW5nIjpudWxsLCJyZXF1aXJlZCI6bnVsbCwidGl0bGUiOm51bGwsInR5cGUiOiJTVFJJTkcifX0sInByb3BlcnR5T3JkZXJpbmciOm51bGwsInJlcXVpcmVkIjpbImFnZW50X25hbWUiXSwidGl0bGUiOm51bGwsInR5cGUiOiJPQkpFQ1QifSwicGFyYW1ldGVyc0pzb25TY2hlbWEiOm51bGwsInJlc3BvbnNlIjpudWxsLCJyZXNwb25zZUpzb25TY2hlbWEiOm51bGwsImJlaGF2aW9yIjpudWxsfV0sImdvb2dsZU1hcHMiOm51bGwsImdvb2dsZVNlYXJjaCI6bnVsbCwiZ29vZ2xlU2VhcmNoUmV0cmlldmFsIjpudWxsLCJ1cmxDb250ZXh0IjpudWxsfV0sInRvb2xDb25maWciOm51bGwsImxhYmVscyI6bnVsbCwiY2FjaGVkQ29udGVudCI6bnVsbCwicmVzcG9uc2VNb2RhbGl0aWVzIjpudWxsLCJtZWRpYVJlc29sdXRpb24iOm51bGwsInNwZWVjaENvbmZpZyI6bnVsbCwiYXVkaW9UaW1lc3RhbXAiOm51bGwsImF1dG9tYXRpY0Z1bmN0aW9uQ2FsbGluZyI6bnVsbCwidGhpbmtpbmdDb25maWciOm51bGwsImltYWdlQ29uZmlnIjpudWxsLCJlbmFibGVFbmhhbmNlZENpdmljQW5zd2VycyI6bnVsbCwibW9kZWxBcm1vckNvbmZpZyI6bnVsbH0sImxpdmVfY29ubmVjdF9jb25maWciOnsiaHR0cE9wdGlvbnMiOm51bGwsImdlbmVyYXRpb25Db25maWciOm51bGwsInJlc3BvbnNlTW9kYWxpdGllcyI6bnVsbCwidGVtcGVyYXR1cmUiOm51bGwsInRvcFAiOm51bGwsInRvcEsiOm51bGwsIm1heE91dHB1dFRva2VucyI6bnVsbCwibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJzZWVkIjpudWxsLCJzcGVlY2hDb25maWciOm51bGwsInRoaW5raW5nQ29uZmlnIjpudWxsLCJlbmFibGVBZmZlY3RpdmVEaWFsb2ciOm51bGwsInN5c3RlbUluc3RydWN0aW9uIjpudWxsLCJ0b29scyI6bnVsbCwic2Vzc2lvblJlc3VtcHRpb24iOm51bGwsImlucHV0QXVkaW9UcmFuc2NyaXB0aW9uIjp7fSwib3V0cHV0QXVkaW9UcmFuc2NyaXB0aW9uIjp7fSwicmVhbHRpbWVJbnB1dENvbmZpZyI6bnVsbCwiY29udGV4dFdpbmRvd0NvbXByZXNzaW9uIjpudWxsLCJwcm9hY3Rpdml0eSI6bnVsbCwiZXhwbGljaXRWYWRTaWduYWwiOm51bGx9LCJjYWNoZV9jb25maWciOm51bGwsImNhY2hlX21ldGFkYXRhIjpudWxsLCJjYWNoZWFibGVfY29udGVudHNfdG9rZW5fY291bnQiOm51bGwsInByZXZpb3VzX2ludGVyYWN0aW9uX2lkIjpudWxsfQ==" + } + ] + }, + "scheduleToCloseTimeout": "0s", + "scheduleToStartTimeout": "0s", + "startToCloseTimeout": "120s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "4", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + }, + "userMetadata": { + "summary": { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "ImNvb3JkaW5hdG9yIg==" + } + } + }, + { + "eventId": "6", + "eventTime": "2026-01-26T21:08:54.512495Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "1103710", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "5", + "identity": "69823@Tims-MacBook-Pro.local", + "requestId": "c9cbbe3d-3e1b-4631-b323-7e43ad2b3b11", + "attempt": 1, + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + } + } + }, + { + "eventId": "7", + "eventTime": "2026-01-26T21:08:54.514972Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "1103711", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "W3sibW9kZWxWZXJzaW9uIjpudWxsLCJjb250ZW50Ijp7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjp7ImlkIjpudWxsLCJhcmdzIjp7ImFnZW50X25hbWUiOiJyZXNlYXJjaGVyIn0sIm5hbWUiOiJ0cmFuc2Zlcl90b19hZ2VudCIsInBhcnRpYWxBcmdzIjpudWxsLCJ3aWxsQ29udGludWUiOm51bGx9LCJmdW5jdGlvblJlc3BvbnNlIjpudWxsLCJpbmxpbmVEYXRhIjpudWxsLCJ0ZXh0IjpudWxsLCJ0aG91Z2h0IjpudWxsLCJ0aG91Z2h0U2lnbmF0dXJlIjpudWxsLCJ2aWRlb01ldGFkYXRhIjpudWxsfV0sInJvbGUiOiJtb2RlbCJ9LCJncm91bmRpbmdNZXRhZGF0YSI6bnVsbCwicGFydGlhbCI6bnVsbCwidHVybkNvbXBsZXRlIjpudWxsLCJmaW5pc2hSZWFzb24iOm51bGwsImVycm9yQ29kZSI6bnVsbCwiZXJyb3JNZXNzYWdlIjpudWxsLCJpbnRlcnJ1cHRlZCI6bnVsbCwiY3VzdG9tTWV0YWRhdGEiOm51bGwsInVzYWdlTWV0YWRhdGEiOm51bGwsImxpdmVTZXNzaW9uUmVzdW1wdGlvblVwZGF0ZSI6bnVsbCwiaW5wdXRUcmFuc2NyaXB0aW9uIjpudWxsLCJvdXRwdXRUcmFuc2NyaXB0aW9uIjpudWxsLCJhdmdMb2dwcm9icyI6bnVsbCwibG9ncHJvYnNSZXN1bHQiOm51bGwsImNhY2hlTWV0YWRhdGEiOm51bGwsImNpdGF0aW9uTWV0YWRhdGEiOm51bGwsImludGVyYWN0aW9uSWQiOm51bGx9XQ==" + } + ] + }, + "scheduledEventId": "5", + "startedEventId": "6", + "identity": "69823@Tims-MacBook-Pro.local" + } + }, + { + "eventId": "8", + "eventTime": "2026-01-26T21:08:54.514974Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1103712", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "9", + "eventTime": "2026-01-26T21:08:54.515493Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1103715", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "8", + "identity": "69823@Tims-MacBook-Pro.local", + "requestId": "11d5c461-029c-4bd8-aae4-2646fb9c9f2c", + "historySizeBytes": "5961", + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + } + } + }, + { + "eventId": "10", + "eventTime": "2026-01-26T21:08:54.547494Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1103719", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "8", + "startedEventId": "9", + "identity": "69823@Tims-MacBook-Pro.local", + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "11", + "eventTime": "2026-01-26T21:08:54.547517Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "1103720", + "activityTaskScheduledEventAttributes": { + "activityId": "2", + "activityType": { + "name": "invoke_model" + }, + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "eyJtb2RlbCI6InJlc2VhcmNoX21vZGVsIiwiY29udGVudHMiOlt7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjpudWxsLCJmdW5jdGlvblJlc3BvbnNlIjpudWxsLCJpbmxpbmVEYXRhIjpudWxsLCJ0ZXh0IjoiV3JpdGUgYSBoYWlrdSBhYm91dCBSdW4gbXVsdC1hZ2VudCBmbG93LiBGaXJzdCByZXNlYXJjaCBpdCwgdGhlbiB3cml0ZSBpdC4iLCJ0aG91Z2h0IjpudWxsLCJ0aG91Z2h0U2lnbmF0dXJlIjpudWxsLCJ2aWRlb01ldGFkYXRhIjpudWxsfV0sInJvbGUiOiJ1c2VyIn0seyJwYXJ0cyI6W3sibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJjb2RlRXhlY3V0aW9uUmVzdWx0IjpudWxsLCJleGVjdXRhYmxlQ29kZSI6bnVsbCwiZmlsZURhdGEiOm51bGwsImZ1bmN0aW9uQ2FsbCI6bnVsbCwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6IkZvciBjb250ZXh0OiIsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9LHsibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJjb2RlRXhlY3V0aW9uUmVzdWx0IjpudWxsLCJleGVjdXRhYmxlQ29kZSI6bnVsbCwiZmlsZURhdGEiOm51bGwsImZ1bmN0aW9uQ2FsbCI6bnVsbCwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6Iltjb29yZGluYXRvcl0gY2FsbGVkIHRvb2wgYHRyYW5zZmVyX3RvX2FnZW50YCB3aXRoIHBhcmFtZXRlcnM6IHsnYWdlbnRfbmFtZSc6ICdyZXNlYXJjaGVyJ30iLCJ0aG91Z2h0IjpudWxsLCJ0aG91Z2h0U2lnbmF0dXJlIjpudWxsLCJ2aWRlb01ldGFkYXRhIjpudWxsfV0sInJvbGUiOiJ1c2VyIn0seyJwYXJ0cyI6W3sibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJjb2RlRXhlY3V0aW9uUmVzdWx0IjpudWxsLCJleGVjdXRhYmxlQ29kZSI6bnVsbCwiZmlsZURhdGEiOm51bGwsImZ1bmN0aW9uQ2FsbCI6bnVsbCwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6IkZvciBjb250ZXh0OiIsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9LHsibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJjb2RlRXhlY3V0aW9uUmVzdWx0IjpudWxsLCJleGVjdXRhYmxlQ29kZSI6bnVsbCwiZmlsZURhdGEiOm51bGwsImZ1bmN0aW9uQ2FsbCI6bnVsbCwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6Iltjb29yZGluYXRvcl0gYHRyYW5zZmVyX3RvX2FnZW50YCB0b29sIHJldHVybmVkIHJlc3VsdDogeydyZXN1bHQnOiBOb25lfSIsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9XSwicm9sZSI6InVzZXIifV0sImNvbmZpZyI6eyJodHRwT3B0aW9ucyI6bnVsbCwic2hvdWxkUmV0dXJuSHR0cFJlc3BvbnNlIjpudWxsLCJzeXN0ZW1JbnN0cnVjdGlvbiI6IllvdSBhcmUgYSByZXNlYXJjaGVyLiBGaW5kIGluZm9ybWF0aW9uIGFib3V0IHRoZSB0b3BpYy5cblxuWW91IGFyZSBhbiBhZ2VudC4gWW91ciBpbnRlcm5hbCBuYW1lIGlzIFwicmVzZWFyY2hlclwiLlxuXG5cbllvdSBoYXZlIGEgbGlzdCBvZiBvdGhlciBhZ2VudHMgdG8gdHJhbnNmZXIgdG86XG5cblxuQWdlbnQgbmFtZTogY29vcmRpbmF0b3JcbkFnZW50IGRlc2NyaXB0aW9uOiBcblxuXG5BZ2VudCBuYW1lOiB3cml0ZXJcbkFnZW50IGRlc2NyaXB0aW9uOiBcblxuXG5JZiB5b3UgYXJlIHRoZSBiZXN0IHRvIGFuc3dlciB0aGUgcXVlc3Rpb24gYWNjb3JkaW5nIHRvIHlvdXIgZGVzY3JpcHRpb24sXG55b3UgY2FuIGFuc3dlciBpdC5cblxuSWYgYW5vdGhlciBhZ2VudCBpcyBiZXR0ZXIgZm9yIGFuc3dlcmluZyB0aGUgcXVlc3Rpb24gYWNjb3JkaW5nIHRvIGl0c1xuZGVzY3JpcHRpb24sIGNhbGwgYHRyYW5zZmVyX3RvX2FnZW50YCBmdW5jdGlvbiB0byB0cmFuc2ZlciB0aGUgcXVlc3Rpb24gdG8gdGhhdFxuYWdlbnQuIFdoZW4gdHJhbnNmZXJyaW5nLCBkbyBub3QgZ2VuZXJhdGUgYW55IHRleHQgb3RoZXIgdGhhbiB0aGUgZnVuY3Rpb25cbmNhbGwuXG5cbioqTk9URSoqOiB0aGUgb25seSBhdmFpbGFibGUgYWdlbnRzIGZvciBgdHJhbnNmZXJfdG9fYWdlbnRgIGZ1bmN0aW9uIGFyZVxuYGNvb3JkaW5hdG9yYCwgYHdyaXRlcmAuXG5cbklmIG5laXRoZXIgeW91IG5vciB0aGUgb3RoZXIgYWdlbnRzIGFyZSBiZXN0IGZvciB0aGUgcXVlc3Rpb24sIHRyYW5zZmVyIHRvIHlvdXIgcGFyZW50IGFnZW50IGNvb3JkaW5hdG9yLlxuIiwidGVtcGVyYXR1cmUiOm51bGwsInRvcFAiOm51bGwsInRvcEsiOm51bGwsImNhbmRpZGF0ZUNvdW50IjpudWxsLCJtYXhPdXRwdXRUb2tlbnMiOm51bGwsInN0b3BTZXF1ZW5jZXMiOm51bGwsInJlc3BvbnNlTG9ncHJvYnMiOm51bGwsImxvZ3Byb2JzIjpudWxsLCJwcmVzZW5jZVBlbmFsdHkiOm51bGwsImZyZXF1ZW5jeVBlbmFsdHkiOm51bGwsInNlZWQiOm51bGwsInJlc3BvbnNlTWltZVR5cGUiOm51bGwsInJlc3BvbnNlU2NoZW1hIjpudWxsLCJyZXNwb25zZUpzb25TY2hlbWEiOm51bGwsInJvdXRpbmdDb25maWciOm51bGwsIm1vZGVsU2VsZWN0aW9uQ29uZmlnIjpudWxsLCJzYWZldHlTZXR0aW5ncyI6bnVsbCwidG9vbHMiOlt7InJldHJpZXZhbCI6bnVsbCwiY29tcHV0ZXJVc2UiOm51bGwsImZpbGVTZWFyY2giOm51bGwsImNvZGVFeGVjdXRpb24iOm51bGwsImVudGVycHJpc2VXZWJTZWFyY2giOm51bGwsImZ1bmN0aW9uRGVjbGFyYXRpb25zIjpbeyJkZXNjcmlwdGlvbiI6IlRyYW5zZmVyIHRoZSBxdWVzdGlvbiB0byBhbm90aGVyIGFnZW50LlxuXG5UaGlzIHRvb2wgaGFuZHMgb2ZmIGNvbnRyb2wgdG8gYW5vdGhlciBhZ2VudCB3aGVuIGl0J3MgbW9yZSBzdWl0YWJsZSB0b1xuYW5zd2VyIHRoZSB1c2VyJ3MgcXVlc3Rpb24gYWNjb3JkaW5nIHRvIHRoZSBhZ2VudCdzIGRlc2NyaXB0aW9uLlxuXG5Ob3RlOlxuICBGb3IgbW9zdCB1c2UgY2FzZXMsIHlvdSBzaG91bGQgdXNlIFRyYW5zZmVyVG9BZ2VudFRvb2wgaW5zdGVhZCBvZiB0aGlzXG4gIGZ1bmN0aW9uIGRpcmVjdGx5LiBUcmFuc2ZlclRvQWdlbnRUb29sIHByb3ZpZGVzIGFkZGl0aW9uYWwgZW51bSBjb25zdHJhaW50c1xuICB0aGF0IHByZXZlbnQgTExNcyBmcm9tIGhhbGx1Y2luYXRpbmcgaW52YWxpZCBhZ2VudCBuYW1lcy5cblxuQXJnczpcbiAgYWdlbnRfbmFtZTogdGhlIGFnZW50IG5hbWUgdG8gdHJhbnNmZXIgdG8uXG4iLCJuYW1lIjoidHJhbnNmZXJfdG9fYWdlbnQiLCJwYXJhbWV0ZXJzIjp7ImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjpudWxsLCJkZWZzIjpudWxsLCJyZWYiOm51bGwsImFueU9mIjpudWxsLCJkZWZhdWx0IjpudWxsLCJkZXNjcmlwdGlvbiI6bnVsbCwiZW51bSI6bnVsbCwiZXhhbXBsZSI6bnVsbCwiZm9ybWF0IjpudWxsLCJpdGVtcyI6bnVsbCwibWF4SXRlbXMiOm51bGwsIm1heExlbmd0aCI6bnVsbCwibWF4UHJvcGVydGllcyI6bnVsbCwibWF4aW11bSI6bnVsbCwibWluSXRlbXMiOm51bGwsIm1pbkxlbmd0aCI6bnVsbCwibWluUHJvcGVydGllcyI6bnVsbCwibWluaW11bSI6bnVsbCwibnVsbGFibGUiOm51bGwsInBhdHRlcm4iOm51bGwsInByb3BlcnRpZXMiOnsiYWdlbnRfbmFtZSI6eyJhZGRpdGlvbmFsUHJvcGVydGllcyI6bnVsbCwiZGVmcyI6bnVsbCwicmVmIjpudWxsLCJhbnlPZiI6bnVsbCwiZGVmYXVsdCI6bnVsbCwiZGVzY3JpcHRpb24iOm51bGwsImVudW0iOlsiY29vcmRpbmF0b3IiLCJ3cml0ZXIiXSwiZXhhbXBsZSI6bnVsbCwiZm9ybWF0IjpudWxsLCJpdGVtcyI6bnVsbCwibWF4SXRlbXMiOm51bGwsIm1heExlbmd0aCI6bnVsbCwibWF4UHJvcGVydGllcyI6bnVsbCwibWF4aW11bSI6bnVsbCwibWluSXRlbXMiOm51bGwsIm1pbkxlbmd0aCI6bnVsbCwibWluUHJvcGVydGllcyI6bnVsbCwibWluaW11bSI6bnVsbCwibnVsbGFibGUiOm51bGwsInBhdHRlcm4iOm51bGwsInByb3BlcnRpZXMiOm51bGwsInByb3BlcnR5T3JkZXJpbmciOm51bGwsInJlcXVpcmVkIjpudWxsLCJ0aXRsZSI6bnVsbCwidHlwZSI6IlNUUklORyJ9fSwicHJvcGVydHlPcmRlcmluZyI6bnVsbCwicmVxdWlyZWQiOlsiYWdlbnRfbmFtZSJdLCJ0aXRsZSI6bnVsbCwidHlwZSI6Ik9CSkVDVCJ9LCJwYXJhbWV0ZXJzSnNvblNjaGVtYSI6bnVsbCwicmVzcG9uc2UiOm51bGwsInJlc3BvbnNlSnNvblNjaGVtYSI6bnVsbCwiYmVoYXZpb3IiOm51bGx9XSwiZ29vZ2xlTWFwcyI6bnVsbCwiZ29vZ2xlU2VhcmNoIjpudWxsLCJnb29nbGVTZWFyY2hSZXRyaWV2YWwiOm51bGwsInVybENvbnRleHQiOm51bGx9XSwidG9vbENvbmZpZyI6bnVsbCwibGFiZWxzIjpudWxsLCJjYWNoZWRDb250ZW50IjpudWxsLCJyZXNwb25zZU1vZGFsaXRpZXMiOm51bGwsIm1lZGlhUmVzb2x1dGlvbiI6bnVsbCwic3BlZWNoQ29uZmlnIjpudWxsLCJhdWRpb1RpbWVzdGFtcCI6bnVsbCwiYXV0b21hdGljRnVuY3Rpb25DYWxsaW5nIjpudWxsLCJ0aGlua2luZ0NvbmZpZyI6bnVsbCwiaW1hZ2VDb25maWciOm51bGwsImVuYWJsZUVuaGFuY2VkQ2l2aWNBbnN3ZXJzIjpudWxsLCJtb2RlbEFybW9yQ29uZmlnIjpudWxsfSwibGl2ZV9jb25uZWN0X2NvbmZpZyI6eyJodHRwT3B0aW9ucyI6bnVsbCwiZ2VuZXJhdGlvbkNvbmZpZyI6bnVsbCwicmVzcG9uc2VNb2RhbGl0aWVzIjpudWxsLCJ0ZW1wZXJhdHVyZSI6bnVsbCwidG9wUCI6bnVsbCwidG9wSyI6bnVsbCwibWF4T3V0cHV0VG9rZW5zIjpudWxsLCJtZWRpYVJlc29sdXRpb24iOm51bGwsInNlZWQiOm51bGwsInNwZWVjaENvbmZpZyI6bnVsbCwidGhpbmtpbmdDb25maWciOm51bGwsImVuYWJsZUFmZmVjdGl2ZURpYWxvZyI6bnVsbCwic3lzdGVtSW5zdHJ1Y3Rpb24iOm51bGwsInRvb2xzIjpudWxsLCJzZXNzaW9uUmVzdW1wdGlvbiI6bnVsbCwiaW5wdXRBdWRpb1RyYW5zY3JpcHRpb24iOnt9LCJvdXRwdXRBdWRpb1RyYW5zY3JpcHRpb24iOnt9LCJyZWFsdGltZUlucHV0Q29uZmlnIjpudWxsLCJjb250ZXh0V2luZG93Q29tcHJlc3Npb24iOm51bGwsInByb2FjdGl2aXR5IjpudWxsLCJleHBsaWNpdFZhZFNpZ25hbCI6bnVsbH0sImNhY2hlX2NvbmZpZyI6bnVsbCwiY2FjaGVfbWV0YWRhdGEiOm51bGwsImNhY2hlYWJsZV9jb250ZW50c190b2tlbl9jb3VudCI6bnVsbCwicHJldmlvdXNfaW50ZXJhY3Rpb25faWQiOm51bGx9" + } + ] + }, + "scheduleToCloseTimeout": "0s", + "scheduleToStartTimeout": "0s", + "startToCloseTimeout": "120s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "10", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + }, + "userMetadata": { + "summary": { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "InJlc2VhcmNoZXIi" + } + } + }, + { + "eventId": "12", + "eventTime": "2026-01-26T21:08:54.548338Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "1103725", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "11", + "identity": "69823@Tims-MacBook-Pro.local", + "requestId": "99a0aa4a-e3b2-4e6a-bd2a-85ab2814b094", + "attempt": 1, + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + } + } + }, + { + "eventId": "13", + "eventTime": "2026-01-26T21:08:54.550067Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "1103726", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "W3sibW9kZWxWZXJzaW9uIjpudWxsLCJjb250ZW50Ijp7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjp7ImlkIjpudWxsLCJhcmdzIjp7ImFnZW50X25hbWUiOiJ3cml0ZXIifSwibmFtZSI6InRyYW5zZmVyX3RvX2FnZW50IiwicGFydGlhbEFyZ3MiOm51bGwsIndpbGxDb250aW51ZSI6bnVsbH0sImZ1bmN0aW9uUmVzcG9uc2UiOm51bGwsImlubGluZURhdGEiOm51bGwsInRleHQiOm51bGwsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9XSwicm9sZSI6Im1vZGVsIn0sImdyb3VuZGluZ01ldGFkYXRhIjpudWxsLCJwYXJ0aWFsIjpudWxsLCJ0dXJuQ29tcGxldGUiOm51bGwsImZpbmlzaFJlYXNvbiI6bnVsbCwiZXJyb3JDb2RlIjpudWxsLCJlcnJvck1lc3NhZ2UiOm51bGwsImludGVycnVwdGVkIjpudWxsLCJjdXN0b21NZXRhZGF0YSI6bnVsbCwidXNhZ2VNZXRhZGF0YSI6bnVsbCwibGl2ZVNlc3Npb25SZXN1bXB0aW9uVXBkYXRlIjpudWxsLCJpbnB1dFRyYW5zY3JpcHRpb24iOm51bGwsIm91dHB1dFRyYW5zY3JpcHRpb24iOm51bGwsImF2Z0xvZ3Byb2JzIjpudWxsLCJsb2dwcm9ic1Jlc3VsdCI6bnVsbCwiY2FjaGVNZXRhZGF0YSI6bnVsbCwiY2l0YXRpb25NZXRhZGF0YSI6bnVsbCwiaW50ZXJhY3Rpb25JZCI6bnVsbH1d" + } + ] + }, + "scheduledEventId": "11", + "startedEventId": "12", + "identity": "69823@Tims-MacBook-Pro.local" + } + }, + { + "eventId": "14", + "eventTime": "2026-01-26T21:08:54.550070Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1103727", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "15", + "eventTime": "2026-01-26T21:08:54.550644Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1103730", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "14", + "identity": "69823@Tims-MacBook-Pro.local", + "requestId": "3bfc29c0-857f-460b-aafa-19e6e1667dad", + "historySizeBytes": "12724", + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + } + } + }, + { + "eventId": "16", + "eventTime": "2026-01-26T21:08:54.582213Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1103734", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "14", + "startedEventId": "15", + "identity": "69823@Tims-MacBook-Pro.local", + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "17", + "eventTime": "2026-01-26T21:08:54.582242Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "1103735", + "activityTaskScheduledEventAttributes": { + "activityId": "3", + "activityType": { + "name": "invoke_model" + }, + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "eyJtb2RlbCI6InJlc2VhcmNoX21vZGVsIiwiY29udGVudHMiOlt7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjpudWxsLCJmdW5jdGlvblJlc3BvbnNlIjpudWxsLCJpbmxpbmVEYXRhIjpudWxsLCJ0ZXh0IjoiV3JpdGUgYSBoYWlrdSBhYm91dCBSdW4gbXVsdC1hZ2VudCBmbG93LiBGaXJzdCByZXNlYXJjaCBpdCwgdGhlbiB3cml0ZSBpdC4iLCJ0aG91Z2h0IjpudWxsLCJ0aG91Z2h0U2lnbmF0dXJlIjpudWxsLCJ2aWRlb01ldGFkYXRhIjpudWxsfV0sInJvbGUiOiJ1c2VyIn0seyJwYXJ0cyI6W3sibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJjb2RlRXhlY3V0aW9uUmVzdWx0IjpudWxsLCJleGVjdXRhYmxlQ29kZSI6bnVsbCwiZmlsZURhdGEiOm51bGwsImZ1bmN0aW9uQ2FsbCI6bnVsbCwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6IkZvciBjb250ZXh0OiIsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9LHsibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJjb2RlRXhlY3V0aW9uUmVzdWx0IjpudWxsLCJleGVjdXRhYmxlQ29kZSI6bnVsbCwiZmlsZURhdGEiOm51bGwsImZ1bmN0aW9uQ2FsbCI6bnVsbCwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6Iltjb29yZGluYXRvcl0gY2FsbGVkIHRvb2wgYHRyYW5zZmVyX3RvX2FnZW50YCB3aXRoIHBhcmFtZXRlcnM6IHsnYWdlbnRfbmFtZSc6ICdyZXNlYXJjaGVyJ30iLCJ0aG91Z2h0IjpudWxsLCJ0aG91Z2h0U2lnbmF0dXJlIjpudWxsLCJ2aWRlb01ldGFkYXRhIjpudWxsfV0sInJvbGUiOiJ1c2VyIn0seyJwYXJ0cyI6W3sibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJjb2RlRXhlY3V0aW9uUmVzdWx0IjpudWxsLCJleGVjdXRhYmxlQ29kZSI6bnVsbCwiZmlsZURhdGEiOm51bGwsImZ1bmN0aW9uQ2FsbCI6bnVsbCwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6IkZvciBjb250ZXh0OiIsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9LHsibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJjb2RlRXhlY3V0aW9uUmVzdWx0IjpudWxsLCJleGVjdXRhYmxlQ29kZSI6bnVsbCwiZmlsZURhdGEiOm51bGwsImZ1bmN0aW9uQ2FsbCI6bnVsbCwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6Iltjb29yZGluYXRvcl0gYHRyYW5zZmVyX3RvX2FnZW50YCB0b29sIHJldHVybmVkIHJlc3VsdDogeydyZXN1bHQnOiBOb25lfSIsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9XSwicm9sZSI6InVzZXIifSx7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjpudWxsLCJmdW5jdGlvblJlc3BvbnNlIjpudWxsLCJpbmxpbmVEYXRhIjpudWxsLCJ0ZXh0IjoiRm9yIGNvbnRleHQ6IiwidGhvdWdodCI6bnVsbCwidGhvdWdodFNpZ25hdHVyZSI6bnVsbCwidmlkZW9NZXRhZGF0YSI6bnVsbH0seyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjpudWxsLCJmdW5jdGlvblJlc3BvbnNlIjpudWxsLCJpbmxpbmVEYXRhIjpudWxsLCJ0ZXh0IjoiW3Jlc2VhcmNoZXJdIGNhbGxlZCB0b29sIGB0cmFuc2Zlcl90b19hZ2VudGAgd2l0aCBwYXJhbWV0ZXJzOiB7J2FnZW50X25hbWUnOiAnd3JpdGVyJ30iLCJ0aG91Z2h0IjpudWxsLCJ0aG91Z2h0U2lnbmF0dXJlIjpudWxsLCJ2aWRlb01ldGFkYXRhIjpudWxsfV0sInJvbGUiOiJ1c2VyIn0seyJwYXJ0cyI6W3sibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJjb2RlRXhlY3V0aW9uUmVzdWx0IjpudWxsLCJleGVjdXRhYmxlQ29kZSI6bnVsbCwiZmlsZURhdGEiOm51bGwsImZ1bmN0aW9uQ2FsbCI6bnVsbCwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6IkZvciBjb250ZXh0OiIsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9LHsibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJjb2RlRXhlY3V0aW9uUmVzdWx0IjpudWxsLCJleGVjdXRhYmxlQ29kZSI6bnVsbCwiZmlsZURhdGEiOm51bGwsImZ1bmN0aW9uQ2FsbCI6bnVsbCwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6IltyZXNlYXJjaGVyXSBgdHJhbnNmZXJfdG9fYWdlbnRgIHRvb2wgcmV0dXJuZWQgcmVzdWx0OiB7J3Jlc3VsdCc6IE5vbmV9IiwidGhvdWdodCI6bnVsbCwidGhvdWdodFNpZ25hdHVyZSI6bnVsbCwidmlkZW9NZXRhZGF0YSI6bnVsbH1dLCJyb2xlIjoidXNlciJ9XSwiY29uZmlnIjp7Imh0dHBPcHRpb25zIjpudWxsLCJzaG91bGRSZXR1cm5IdHRwUmVzcG9uc2UiOm51bGwsInN5c3RlbUluc3RydWN0aW9uIjoiWW91IGFyZSBhIHBvZXQuIFdyaXRlIGEgaGFpa3UgYmFzZWQgb24gdGhlIHJlc2VhcmNoLlxuXG5Zb3UgYXJlIGFuIGFnZW50LiBZb3VyIGludGVybmFsIG5hbWUgaXMgXCJ3cml0ZXJcIi5cblxuXG5Zb3UgaGF2ZSBhIGxpc3Qgb2Ygb3RoZXIgYWdlbnRzIHRvIHRyYW5zZmVyIHRvOlxuXG5cbkFnZW50IG5hbWU6IGNvb3JkaW5hdG9yXG5BZ2VudCBkZXNjcmlwdGlvbjogXG5cblxuQWdlbnQgbmFtZTogcmVzZWFyY2hlclxuQWdlbnQgZGVzY3JpcHRpb246IFxuXG5cbklmIHlvdSBhcmUgdGhlIGJlc3QgdG8gYW5zd2VyIHRoZSBxdWVzdGlvbiBhY2NvcmRpbmcgdG8geW91ciBkZXNjcmlwdGlvbixcbnlvdSBjYW4gYW5zd2VyIGl0LlxuXG5JZiBhbm90aGVyIGFnZW50IGlzIGJldHRlciBmb3IgYW5zd2VyaW5nIHRoZSBxdWVzdGlvbiBhY2NvcmRpbmcgdG8gaXRzXG5kZXNjcmlwdGlvbiwgY2FsbCBgdHJhbnNmZXJfdG9fYWdlbnRgIGZ1bmN0aW9uIHRvIHRyYW5zZmVyIHRoZSBxdWVzdGlvbiB0byB0aGF0XG5hZ2VudC4gV2hlbiB0cmFuc2ZlcnJpbmcsIGRvIG5vdCBnZW5lcmF0ZSBhbnkgdGV4dCBvdGhlciB0aGFuIHRoZSBmdW5jdGlvblxuY2FsbC5cblxuKipOT1RFKio6IHRoZSBvbmx5IGF2YWlsYWJsZSBhZ2VudHMgZm9yIGB0cmFuc2Zlcl90b19hZ2VudGAgZnVuY3Rpb24gYXJlXG5gY29vcmRpbmF0b3JgLCBgcmVzZWFyY2hlcmAuXG5cbklmIG5laXRoZXIgeW91IG5vciB0aGUgb3RoZXIgYWdlbnRzIGFyZSBiZXN0IGZvciB0aGUgcXVlc3Rpb24sIHRyYW5zZmVyIHRvIHlvdXIgcGFyZW50IGFnZW50IGNvb3JkaW5hdG9yLlxuIiwidGVtcGVyYXR1cmUiOm51bGwsInRvcFAiOm51bGwsInRvcEsiOm51bGwsImNhbmRpZGF0ZUNvdW50IjpudWxsLCJtYXhPdXRwdXRUb2tlbnMiOm51bGwsInN0b3BTZXF1ZW5jZXMiOm51bGwsInJlc3BvbnNlTG9ncHJvYnMiOm51bGwsImxvZ3Byb2JzIjpudWxsLCJwcmVzZW5jZVBlbmFsdHkiOm51bGwsImZyZXF1ZW5jeVBlbmFsdHkiOm51bGwsInNlZWQiOm51bGwsInJlc3BvbnNlTWltZVR5cGUiOm51bGwsInJlc3BvbnNlU2NoZW1hIjpudWxsLCJyZXNwb25zZUpzb25TY2hlbWEiOm51bGwsInJvdXRpbmdDb25maWciOm51bGwsIm1vZGVsU2VsZWN0aW9uQ29uZmlnIjpudWxsLCJzYWZldHlTZXR0aW5ncyI6bnVsbCwidG9vbHMiOlt7InJldHJpZXZhbCI6bnVsbCwiY29tcHV0ZXJVc2UiOm51bGwsImZpbGVTZWFyY2giOm51bGwsImNvZGVFeGVjdXRpb24iOm51bGwsImVudGVycHJpc2VXZWJTZWFyY2giOm51bGwsImZ1bmN0aW9uRGVjbGFyYXRpb25zIjpbeyJkZXNjcmlwdGlvbiI6IlRyYW5zZmVyIHRoZSBxdWVzdGlvbiB0byBhbm90aGVyIGFnZW50LlxuXG5UaGlzIHRvb2wgaGFuZHMgb2ZmIGNvbnRyb2wgdG8gYW5vdGhlciBhZ2VudCB3aGVuIGl0J3MgbW9yZSBzdWl0YWJsZSB0b1xuYW5zd2VyIHRoZSB1c2VyJ3MgcXVlc3Rpb24gYWNjb3JkaW5nIHRvIHRoZSBhZ2VudCdzIGRlc2NyaXB0aW9uLlxuXG5Ob3RlOlxuICBGb3IgbW9zdCB1c2UgY2FzZXMsIHlvdSBzaG91bGQgdXNlIFRyYW5zZmVyVG9BZ2VudFRvb2wgaW5zdGVhZCBvZiB0aGlzXG4gIGZ1bmN0aW9uIGRpcmVjdGx5LiBUcmFuc2ZlclRvQWdlbnRUb29sIHByb3ZpZGVzIGFkZGl0aW9uYWwgZW51bSBjb25zdHJhaW50c1xuICB0aGF0IHByZXZlbnQgTExNcyBmcm9tIGhhbGx1Y2luYXRpbmcgaW52YWxpZCBhZ2VudCBuYW1lcy5cblxuQXJnczpcbiAgYWdlbnRfbmFtZTogdGhlIGFnZW50IG5hbWUgdG8gdHJhbnNmZXIgdG8uXG4iLCJuYW1lIjoidHJhbnNmZXJfdG9fYWdlbnQiLCJwYXJhbWV0ZXJzIjp7ImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjpudWxsLCJkZWZzIjpudWxsLCJyZWYiOm51bGwsImFueU9mIjpudWxsLCJkZWZhdWx0IjpudWxsLCJkZXNjcmlwdGlvbiI6bnVsbCwiZW51bSI6bnVsbCwiZXhhbXBsZSI6bnVsbCwiZm9ybWF0IjpudWxsLCJpdGVtcyI6bnVsbCwibWF4SXRlbXMiOm51bGwsIm1heExlbmd0aCI6bnVsbCwibWF4UHJvcGVydGllcyI6bnVsbCwibWF4aW11bSI6bnVsbCwibWluSXRlbXMiOm51bGwsIm1pbkxlbmd0aCI6bnVsbCwibWluUHJvcGVydGllcyI6bnVsbCwibWluaW11bSI6bnVsbCwibnVsbGFibGUiOm51bGwsInBhdHRlcm4iOm51bGwsInByb3BlcnRpZXMiOnsiYWdlbnRfbmFtZSI6eyJhZGRpdGlvbmFsUHJvcGVydGllcyI6bnVsbCwiZGVmcyI6bnVsbCwicmVmIjpudWxsLCJhbnlPZiI6bnVsbCwiZGVmYXVsdCI6bnVsbCwiZGVzY3JpcHRpb24iOm51bGwsImVudW0iOlsiY29vcmRpbmF0b3IiLCJyZXNlYXJjaGVyIl0sImV4YW1wbGUiOm51bGwsImZvcm1hdCI6bnVsbCwiaXRlbXMiOm51bGwsIm1heEl0ZW1zIjpudWxsLCJtYXhMZW5ndGgiOm51bGwsIm1heFByb3BlcnRpZXMiOm51bGwsIm1heGltdW0iOm51bGwsIm1pbkl0ZW1zIjpudWxsLCJtaW5MZW5ndGgiOm51bGwsIm1pblByb3BlcnRpZXMiOm51bGwsIm1pbmltdW0iOm51bGwsIm51bGxhYmxlIjpudWxsLCJwYXR0ZXJuIjpudWxsLCJwcm9wZXJ0aWVzIjpudWxsLCJwcm9wZXJ0eU9yZGVyaW5nIjpudWxsLCJyZXF1aXJlZCI6bnVsbCwidGl0bGUiOm51bGwsInR5cGUiOiJTVFJJTkcifX0sInByb3BlcnR5T3JkZXJpbmciOm51bGwsInJlcXVpcmVkIjpbImFnZW50X25hbWUiXSwidGl0bGUiOm51bGwsInR5cGUiOiJPQkpFQ1QifSwicGFyYW1ldGVyc0pzb25TY2hlbWEiOm51bGwsInJlc3BvbnNlIjpudWxsLCJyZXNwb25zZUpzb25TY2hlbWEiOm51bGwsImJlaGF2aW9yIjpudWxsfV0sImdvb2dsZU1hcHMiOm51bGwsImdvb2dsZVNlYXJjaCI6bnVsbCwiZ29vZ2xlU2VhcmNoUmV0cmlldmFsIjpudWxsLCJ1cmxDb250ZXh0IjpudWxsfV0sInRvb2xDb25maWciOm51bGwsImxhYmVscyI6bnVsbCwiY2FjaGVkQ29udGVudCI6bnVsbCwicmVzcG9uc2VNb2RhbGl0aWVzIjpudWxsLCJtZWRpYVJlc29sdXRpb24iOm51bGwsInNwZWVjaENvbmZpZyI6bnVsbCwiYXVkaW9UaW1lc3RhbXAiOm51bGwsImF1dG9tYXRpY0Z1bmN0aW9uQ2FsbGluZyI6bnVsbCwidGhpbmtpbmdDb25maWciOm51bGwsImltYWdlQ29uZmlnIjpudWxsLCJlbmFibGVFbmhhbmNlZENpdmljQW5zd2VycyI6bnVsbCwibW9kZWxBcm1vckNvbmZpZyI6bnVsbH0sImxpdmVfY29ubmVjdF9jb25maWciOnsiaHR0cE9wdGlvbnMiOm51bGwsImdlbmVyYXRpb25Db25maWciOm51bGwsInJlc3BvbnNlTW9kYWxpdGllcyI6bnVsbCwidGVtcGVyYXR1cmUiOm51bGwsInRvcFAiOm51bGwsInRvcEsiOm51bGwsIm1heE91dHB1dFRva2VucyI6bnVsbCwibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJzZWVkIjpudWxsLCJzcGVlY2hDb25maWciOm51bGwsInRoaW5raW5nQ29uZmlnIjpudWxsLCJlbmFibGVBZmZlY3RpdmVEaWFsb2ciOm51bGwsInN5c3RlbUluc3RydWN0aW9uIjpudWxsLCJ0b29scyI6bnVsbCwic2Vzc2lvblJlc3VtcHRpb24iOm51bGwsImlucHV0QXVkaW9UcmFuc2NyaXB0aW9uIjp7fSwib3V0cHV0QXVkaW9UcmFuc2NyaXB0aW9uIjp7fSwicmVhbHRpbWVJbnB1dENvbmZpZyI6bnVsbCwiY29udGV4dFdpbmRvd0NvbXByZXNzaW9uIjpudWxsLCJwcm9hY3Rpdml0eSI6bnVsbCwiZXhwbGljaXRWYWRTaWduYWwiOm51bGx9LCJjYWNoZV9jb25maWciOm51bGwsImNhY2hlX21ldGFkYXRhIjpudWxsLCJjYWNoZWFibGVfY29udGVudHNfdG9rZW5fY291bnQiOm51bGwsInByZXZpb3VzX2ludGVyYWN0aW9uX2lkIjpudWxsfQ==" + } + ] + }, + "scheduleToCloseTimeout": "0s", + "scheduleToStartTimeout": "0s", + "startToCloseTimeout": "120s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "16", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + }, + "userMetadata": { + "summary": { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IndyaXRlciI=" + } + } + }, + { + "eventId": "18", + "eventTime": "2026-01-26T21:08:54.583085Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "1103740", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "17", + "identity": "69823@Tims-MacBook-Pro.local", + "requestId": "a880f966-0e32-4c24-a531-ae7a427847b5", + "attempt": 1, + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + } + } + }, + { + "eventId": "19", + "eventTime": "2026-01-26T21:08:54.584874Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "1103741", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "W3sibW9kZWxWZXJzaW9uIjpudWxsLCJjb250ZW50Ijp7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjpudWxsLCJmdW5jdGlvblJlc3BvbnNlIjpudWxsLCJpbmxpbmVEYXRhIjpudWxsLCJ0ZXh0IjoiaGFpa3UiLCJ0aG91Z2h0IjpudWxsLCJ0aG91Z2h0U2lnbmF0dXJlIjpudWxsLCJ2aWRlb01ldGFkYXRhIjpudWxsfV0sInJvbGUiOiJtb2RlbCJ9LCJncm91bmRpbmdNZXRhZGF0YSI6bnVsbCwicGFydGlhbCI6bnVsbCwidHVybkNvbXBsZXRlIjpudWxsLCJmaW5pc2hSZWFzb24iOm51bGwsImVycm9yQ29kZSI6bnVsbCwiZXJyb3JNZXNzYWdlIjpudWxsLCJpbnRlcnJ1cHRlZCI6bnVsbCwiY3VzdG9tTWV0YWRhdGEiOm51bGwsInVzYWdlTWV0YWRhdGEiOm51bGwsImxpdmVTZXNzaW9uUmVzdW1wdGlvblVwZGF0ZSI6bnVsbCwiaW5wdXRUcmFuc2NyaXB0aW9uIjpudWxsLCJvdXRwdXRUcmFuc2NyaXB0aW9uIjpudWxsLCJhdmdMb2dwcm9icyI6bnVsbCwibG9ncHJvYnNSZXN1bHQiOm51bGwsImNhY2hlTWV0YWRhdGEiOm51bGwsImNpdGF0aW9uTWV0YWRhdGEiOm51bGwsImludGVyYWN0aW9uSWQiOm51bGx9XQ==" + } + ] + }, + "scheduledEventId": "17", + "startedEventId": "18", + "identity": "69823@Tims-MacBook-Pro.local" + } + }, + { + "eventId": "20", + "eventTime": "2026-01-26T21:08:54.584876Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1103742", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "21", + "eventTime": "2026-01-26T21:08:54.585780Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1103745", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "20", + "identity": "69823@Tims-MacBook-Pro.local", + "requestId": "5a954014-8c9b-4759-a859-6785b3d33967", + "historySizeBytes": "20508", + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + } + } + }, + { + "eventId": "22", + "eventTime": "2026-01-26T21:08:54.617825Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1103749", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "20", + "startedEventId": "21", + "identity": "69823@Tims-MacBook-Pro.local", + "workerVersion": { + "buildId": "2f45d1deb022376ac8b03fdcb17f8e5c" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "23", + "eventTime": "2026-01-26T21:08:54.617846Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED", + "taskId": "1103750", + "workflowExecutionCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "ImhhaWt1Ig==" + } + ] + }, + "workflowTaskCompletedEventId": "22" + } + } + ] +} \ No newline at end of file diff --git a/tests/contrib/google_adk_agents/histories/single_agent.json b/tests/contrib/google_adk_agents/histories/single_agent.json new file mode 100644 index 000000000..c6eb1f45a --- /dev/null +++ b/tests/contrib/google_adk_agents/histories/single_agent.json @@ -0,0 +1,491 @@ +{ + "events": [ + { + "eventId": "1", + "eventTime": "2026-01-26T21:11:30.080188Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_STARTED", + "taskId": "1104115", + "workflowExecutionStartedEventAttributes": { + "workflowType": { + "name": "WeatherAgent" + }, + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IldoYXQgaXMgdGhlIHdlYXRoZXIgaW4gTmV3IFlvcms/Ig==" + }, + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "IndlYXRoZXJfbW9kZWwi" + } + ] + }, + "workflowTaskTimeout": "10s", + "originalExecutionRunId": "019bfc25-bc20-72da-8597-e94f48dc9057", + "identity": "70127@Tims-MacBook-Pro.local", + "firstExecutionRunId": "019bfc25-bc20-72da-8597-e94f48dc9057", + "attempt": 1, + "firstWorkflowTaskBackoff": "0s", + "workflowId": "weather-agent-workflow-b9d42dfd-2318-45d8-b952-650a79362a09", + "priority": {} + } + }, + { + "eventId": "2", + "eventTime": "2026-01-26T21:11:30.083361Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1104116", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "3", + "eventTime": "2026-01-26T21:11:30.094782Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1104121", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "2", + "identity": "70127@Tims-MacBook-Pro.local", + "requestId": "e605155e-5b3a-4a72-b539-e53710562fae", + "historySizeBytes": "403", + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + } + } + }, + { + "eventId": "4", + "eventTime": "2026-01-26T21:11:30.184056Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1104125", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "2", + "startedEventId": "3", + "identity": "70127@Tims-MacBook-Pro.local", + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + }, + "sdkMetadata": { + "coreUsedFlags": [ + 3, + 2, + 1 + ], + "sdkName": "temporal-python", + "sdkVersion": "1.21.1" + }, + "meteringMetadata": {} + } + }, + { + "eventId": "5", + "eventTime": "2026-01-26T21:11:30.184120Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "1104126", + "activityTaskScheduledEventAttributes": { + "activityId": "1", + "activityType": { + "name": "invoke_model" + }, + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "eyJtb2RlbCI6IndlYXRoZXJfbW9kZWwiLCJjb250ZW50cyI6W3sicGFydHMiOlt7Im1lZGlhUmVzb2x1dGlvbiI6bnVsbCwiY29kZUV4ZWN1dGlvblJlc3VsdCI6bnVsbCwiZXhlY3V0YWJsZUNvZGUiOm51bGwsImZpbGVEYXRhIjpudWxsLCJmdW5jdGlvbkNhbGwiOm51bGwsImZ1bmN0aW9uUmVzcG9uc2UiOm51bGwsImlubGluZURhdGEiOm51bGwsInRleHQiOiJXaGF0IGlzIHRoZSB3ZWF0aGVyIGluIE5ldyBZb3JrPyIsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9XSwicm9sZSI6InVzZXIifV0sImNvbmZpZyI6eyJodHRwT3B0aW9ucyI6bnVsbCwic2hvdWxkUmV0dXJuSHR0cFJlc3BvbnNlIjpudWxsLCJzeXN0ZW1JbnN0cnVjdGlvbiI6IllvdSBhcmUgYW4gYWdlbnQuIFlvdXIgaW50ZXJuYWwgbmFtZSBpcyBcInRlc3RfYWdlbnRcIi4iLCJ0ZW1wZXJhdHVyZSI6bnVsbCwidG9wUCI6bnVsbCwidG9wSyI6bnVsbCwiY2FuZGlkYXRlQ291bnQiOm51bGwsIm1heE91dHB1dFRva2VucyI6bnVsbCwic3RvcFNlcXVlbmNlcyI6bnVsbCwicmVzcG9uc2VMb2dwcm9icyI6bnVsbCwibG9ncHJvYnMiOm51bGwsInByZXNlbmNlUGVuYWx0eSI6bnVsbCwiZnJlcXVlbmN5UGVuYWx0eSI6bnVsbCwic2VlZCI6bnVsbCwicmVzcG9uc2VNaW1lVHlwZSI6bnVsbCwicmVzcG9uc2VTY2hlbWEiOm51bGwsInJlc3BvbnNlSnNvblNjaGVtYSI6bnVsbCwicm91dGluZ0NvbmZpZyI6bnVsbCwibW9kZWxTZWxlY3Rpb25Db25maWciOm51bGwsInNhZmV0eVNldHRpbmdzIjpudWxsLCJ0b29scyI6W3sicmV0cmlldmFsIjpudWxsLCJjb21wdXRlclVzZSI6bnVsbCwiZmlsZVNlYXJjaCI6bnVsbCwiY29kZUV4ZWN1dGlvbiI6bnVsbCwiZW50ZXJwcmlzZVdlYlNlYXJjaCI6bnVsbCwiZnVuY3Rpb25EZWNsYXJhdGlvbnMiOlt7ImRlc2NyaXB0aW9uIjoiQWN0aXZpdHkgdGhhdCBnZXRzIHdlYXRoZXIgZm9yIGEgZ2l2ZW4gY2l0eS4iLCJuYW1lIjoiZ2V0X3dlYXRoZXIiLCJwYXJhbWV0ZXJzIjp7ImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjpudWxsLCJkZWZzIjpudWxsLCJyZWYiOm51bGwsImFueU9mIjpudWxsLCJkZWZhdWx0IjpudWxsLCJkZXNjcmlwdGlvbiI6bnVsbCwiZW51bSI6bnVsbCwiZXhhbXBsZSI6bnVsbCwiZm9ybWF0IjpudWxsLCJpdGVtcyI6bnVsbCwibWF4SXRlbXMiOm51bGwsIm1heExlbmd0aCI6bnVsbCwibWF4UHJvcGVydGllcyI6bnVsbCwibWF4aW11bSI6bnVsbCwibWluSXRlbXMiOm51bGwsIm1pbkxlbmd0aCI6bnVsbCwibWluUHJvcGVydGllcyI6bnVsbCwibWluaW11bSI6bnVsbCwibnVsbGFibGUiOm51bGwsInBhdHRlcm4iOm51bGwsInByb3BlcnRpZXMiOnsiY2l0eSI6eyJhZGRpdGlvbmFsUHJvcGVydGllcyI6bnVsbCwiZGVmcyI6bnVsbCwicmVmIjpudWxsLCJhbnlPZiI6bnVsbCwiZGVmYXVsdCI6bnVsbCwiZGVzY3JpcHRpb24iOm51bGwsImVudW0iOm51bGwsImV4YW1wbGUiOm51bGwsImZvcm1hdCI6bnVsbCwiaXRlbXMiOm51bGwsIm1heEl0ZW1zIjpudWxsLCJtYXhMZW5ndGgiOm51bGwsIm1heFByb3BlcnRpZXMiOm51bGwsIm1heGltdW0iOm51bGwsIm1pbkl0ZW1zIjpudWxsLCJtaW5MZW5ndGgiOm51bGwsIm1pblByb3BlcnRpZXMiOm51bGwsIm1pbmltdW0iOm51bGwsIm51bGxhYmxlIjpudWxsLCJwYXR0ZXJuIjpudWxsLCJwcm9wZXJ0aWVzIjpudWxsLCJwcm9wZXJ0eU9yZGVyaW5nIjpudWxsLCJyZXF1aXJlZCI6bnVsbCwidGl0bGUiOm51bGwsInR5cGUiOiJTVFJJTkcifX0sInByb3BlcnR5T3JkZXJpbmciOm51bGwsInJlcXVpcmVkIjpbImNpdHkiXSwidGl0bGUiOm51bGwsInR5cGUiOiJPQkpFQ1QifSwicGFyYW1ldGVyc0pzb25TY2hlbWEiOm51bGwsInJlc3BvbnNlIjpudWxsLCJyZXNwb25zZUpzb25TY2hlbWEiOm51bGwsImJlaGF2aW9yIjpudWxsfV0sImdvb2dsZU1hcHMiOm51bGwsImdvb2dsZVNlYXJjaCI6bnVsbCwiZ29vZ2xlU2VhcmNoUmV0cmlldmFsIjpudWxsLCJ1cmxDb250ZXh0IjpudWxsfV0sInRvb2xDb25maWciOm51bGwsImxhYmVscyI6bnVsbCwiY2FjaGVkQ29udGVudCI6bnVsbCwicmVzcG9uc2VNb2RhbGl0aWVzIjpudWxsLCJtZWRpYVJlc29sdXRpb24iOm51bGwsInNwZWVjaENvbmZpZyI6bnVsbCwiYXVkaW9UaW1lc3RhbXAiOm51bGwsImF1dG9tYXRpY0Z1bmN0aW9uQ2FsbGluZyI6bnVsbCwidGhpbmtpbmdDb25maWciOm51bGwsImltYWdlQ29uZmlnIjpudWxsLCJlbmFibGVFbmhhbmNlZENpdmljQW5zd2VycyI6bnVsbCwibW9kZWxBcm1vckNvbmZpZyI6bnVsbH0sImxpdmVfY29ubmVjdF9jb25maWciOnsiaHR0cE9wdGlvbnMiOm51bGwsImdlbmVyYXRpb25Db25maWciOm51bGwsInJlc3BvbnNlTW9kYWxpdGllcyI6bnVsbCwidGVtcGVyYXR1cmUiOm51bGwsInRvcFAiOm51bGwsInRvcEsiOm51bGwsIm1heE91dHB1dFRva2VucyI6bnVsbCwibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJzZWVkIjpudWxsLCJzcGVlY2hDb25maWciOm51bGwsInRoaW5raW5nQ29uZmlnIjpudWxsLCJlbmFibGVBZmZlY3RpdmVEaWFsb2ciOm51bGwsInN5c3RlbUluc3RydWN0aW9uIjpudWxsLCJ0b29scyI6bnVsbCwic2Vzc2lvblJlc3VtcHRpb24iOm51bGwsImlucHV0QXVkaW9UcmFuc2NyaXB0aW9uIjp7fSwib3V0cHV0QXVkaW9UcmFuc2NyaXB0aW9uIjp7fSwicmVhbHRpbWVJbnB1dENvbmZpZyI6bnVsbCwiY29udGV4dFdpbmRvd0NvbXByZXNzaW9uIjpudWxsLCJwcm9hY3Rpdml0eSI6bnVsbCwiZXhwbGljaXRWYWRTaWduYWwiOm51bGx9LCJjYWNoZV9jb25maWciOm51bGwsImNhY2hlX21ldGFkYXRhIjpudWxsLCJjYWNoZWFibGVfY29udGVudHNfdG9rZW5fY291bnQiOm51bGwsInByZXZpb3VzX2ludGVyYWN0aW9uX2lkIjpudWxsfQ==" + } + ] + }, + "scheduleToCloseTimeout": "0s", + "scheduleToStartTimeout": "0s", + "startToCloseTimeout": "120s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "4", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + }, + "userMetadata": { + "summary": { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "InRlc3RfYWdlbnQi" + } + } + }, + { + "eventId": "6", + "eventTime": "2026-01-26T21:11:30.185095Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "1104132", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "5", + "identity": "70127@Tims-MacBook-Pro.local", + "requestId": "affae0ec-873d-4c27-85c3-cbbd6cec61f6", + "attempt": 1, + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + } + } + }, + { + "eventId": "7", + "eventTime": "2026-01-26T21:11:30.188610Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "1104133", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "W3sibW9kZWxWZXJzaW9uIjpudWxsLCJjb250ZW50Ijp7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjp7ImlkIjpudWxsLCJhcmdzIjp7ImNpdHkiOiJOZXcgWW9yayJ9LCJuYW1lIjoiZ2V0X3dlYXRoZXIiLCJwYXJ0aWFsQXJncyI6bnVsbCwid2lsbENvbnRpbnVlIjpudWxsfSwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6bnVsbCwidGhvdWdodCI6bnVsbCwidGhvdWdodFNpZ25hdHVyZSI6bnVsbCwidmlkZW9NZXRhZGF0YSI6bnVsbH1dLCJyb2xlIjoibW9kZWwifSwiZ3JvdW5kaW5nTWV0YWRhdGEiOm51bGwsInBhcnRpYWwiOm51bGwsInR1cm5Db21wbGV0ZSI6bnVsbCwiZmluaXNoUmVhc29uIjpudWxsLCJlcnJvckNvZGUiOm51bGwsImVycm9yTWVzc2FnZSI6bnVsbCwiaW50ZXJydXB0ZWQiOm51bGwsImN1c3RvbU1ldGFkYXRhIjpudWxsLCJ1c2FnZU1ldGFkYXRhIjpudWxsLCJsaXZlU2Vzc2lvblJlc3VtcHRpb25VcGRhdGUiOm51bGwsImlucHV0VHJhbnNjcmlwdGlvbiI6bnVsbCwib3V0cHV0VHJhbnNjcmlwdGlvbiI6bnVsbCwiYXZnTG9ncHJvYnMiOm51bGwsImxvZ3Byb2JzUmVzdWx0IjpudWxsLCJjYWNoZU1ldGFkYXRhIjpudWxsLCJjaXRhdGlvbk1ldGFkYXRhIjpudWxsLCJpbnRlcmFjdGlvbklkIjpudWxsfV0=" + } + ] + }, + "scheduledEventId": "5", + "startedEventId": "6", + "identity": "70127@Tims-MacBook-Pro.local" + } + }, + { + "eventId": "8", + "eventTime": "2026-01-26T21:11:30.188613Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1104134", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "9", + "eventTime": "2026-01-26T21:11:30.189631Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1104137", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "8", + "identity": "70127@Tims-MacBook-Pro.local", + "requestId": "755e188a-9cdd-4818-b328-4d40f4627910", + "historySizeBytes": "4799", + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + } + } + }, + { + "eventId": "10", + "eventTime": "2026-01-26T21:11:30.221995Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1104141", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "8", + "startedEventId": "9", + "identity": "70127@Tims-MacBook-Pro.local", + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "11", + "eventTime": "2026-01-26T21:11:30.222027Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "1104142", + "activityTaskScheduledEventAttributes": { + "activityId": "2", + "activityType": { + "name": "get_weather" + }, + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "Ik5ldyBZb3JrIg==" + } + ] + }, + "scheduleToCloseTimeout": "0s", + "scheduleToStartTimeout": "0s", + "startToCloseTimeout": "60s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "10", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + } + }, + { + "eventId": "12", + "eventTime": "2026-01-26T21:11:30.223081Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "1104147", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "11", + "identity": "70127@Tims-MacBook-Pro.local", + "requestId": "be038a7a-79fc-4e78-bae2-798c1d77b9e4", + "attempt": 1, + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + } + } + }, + { + "eventId": "13", + "eventTime": "2026-01-26T21:11:30.225066Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "1104148", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "Ildhcm0gYW5kIHN1bm55LiAxNyBkZWdyZWVzLiI=" + } + ] + }, + "scheduledEventId": "11", + "startedEventId": "12", + "identity": "70127@Tims-MacBook-Pro.local" + } + }, + { + "eventId": "14", + "eventTime": "2026-01-26T21:11:30.225069Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1104149", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "15", + "eventTime": "2026-01-26T21:11:30.225814Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1104152", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "14", + "identity": "70127@Tims-MacBook-Pro.local", + "requestId": "ab62b9fc-373f-4157-a891-87c6ecc47405", + "historySizeBytes": "5479", + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + } + } + }, + { + "eventId": "16", + "eventTime": "2026-01-26T21:11:30.258759Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1104156", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "14", + "startedEventId": "15", + "identity": "70127@Tims-MacBook-Pro.local", + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "17", + "eventTime": "2026-01-26T21:11:30.258787Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED", + "taskId": "1104157", + "activityTaskScheduledEventAttributes": { + "activityId": "3", + "activityType": { + "name": "invoke_model" + }, + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "header": {}, + "input": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "eyJtb2RlbCI6IndlYXRoZXJfbW9kZWwiLCJjb250ZW50cyI6W3sicGFydHMiOlt7Im1lZGlhUmVzb2x1dGlvbiI6bnVsbCwiY29kZUV4ZWN1dGlvblJlc3VsdCI6bnVsbCwiZXhlY3V0YWJsZUNvZGUiOm51bGwsImZpbGVEYXRhIjpudWxsLCJmdW5jdGlvbkNhbGwiOm51bGwsImZ1bmN0aW9uUmVzcG9uc2UiOm51bGwsImlubGluZURhdGEiOm51bGwsInRleHQiOiJXaGF0IGlzIHRoZSB3ZWF0aGVyIGluIE5ldyBZb3JrPyIsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9XSwicm9sZSI6InVzZXIifSx7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjp7ImlkIjpudWxsLCJhcmdzIjp7ImNpdHkiOiJOZXcgWW9yayJ9LCJuYW1lIjoiZ2V0X3dlYXRoZXIiLCJwYXJ0aWFsQXJncyI6bnVsbCwid2lsbENvbnRpbnVlIjpudWxsfSwiZnVuY3Rpb25SZXNwb25zZSI6bnVsbCwiaW5saW5lRGF0YSI6bnVsbCwidGV4dCI6bnVsbCwidGhvdWdodCI6bnVsbCwidGhvdWdodFNpZ25hdHVyZSI6bnVsbCwidmlkZW9NZXRhZGF0YSI6bnVsbH1dLCJyb2xlIjoibW9kZWwifSx7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjpudWxsLCJmdW5jdGlvblJlc3BvbnNlIjp7IndpbGxDb250aW51ZSI6bnVsbCwic2NoZWR1bGluZyI6bnVsbCwicGFydHMiOm51bGwsImlkIjpudWxsLCJuYW1lIjoiZ2V0X3dlYXRoZXIiLCJyZXNwb25zZSI6eyJyZXN1bHQiOiJXYXJtIGFuZCBzdW5ueS4gMTcgZGVncmVlcy4ifX0sImlubGluZURhdGEiOm51bGwsInRleHQiOm51bGwsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9XSwicm9sZSI6InVzZXIifV0sImNvbmZpZyI6eyJodHRwT3B0aW9ucyI6bnVsbCwic2hvdWxkUmV0dXJuSHR0cFJlc3BvbnNlIjpudWxsLCJzeXN0ZW1JbnN0cnVjdGlvbiI6IllvdSBhcmUgYW4gYWdlbnQuIFlvdXIgaW50ZXJuYWwgbmFtZSBpcyBcInRlc3RfYWdlbnRcIi4iLCJ0ZW1wZXJhdHVyZSI6bnVsbCwidG9wUCI6bnVsbCwidG9wSyI6bnVsbCwiY2FuZGlkYXRlQ291bnQiOm51bGwsIm1heE91dHB1dFRva2VucyI6bnVsbCwic3RvcFNlcXVlbmNlcyI6bnVsbCwicmVzcG9uc2VMb2dwcm9icyI6bnVsbCwibG9ncHJvYnMiOm51bGwsInByZXNlbmNlUGVuYWx0eSI6bnVsbCwiZnJlcXVlbmN5UGVuYWx0eSI6bnVsbCwic2VlZCI6bnVsbCwicmVzcG9uc2VNaW1lVHlwZSI6bnVsbCwicmVzcG9uc2VTY2hlbWEiOm51bGwsInJlc3BvbnNlSnNvblNjaGVtYSI6bnVsbCwicm91dGluZ0NvbmZpZyI6bnVsbCwibW9kZWxTZWxlY3Rpb25Db25maWciOm51bGwsInNhZmV0eVNldHRpbmdzIjpudWxsLCJ0b29scyI6W3sicmV0cmlldmFsIjpudWxsLCJjb21wdXRlclVzZSI6bnVsbCwiZmlsZVNlYXJjaCI6bnVsbCwiY29kZUV4ZWN1dGlvbiI6bnVsbCwiZW50ZXJwcmlzZVdlYlNlYXJjaCI6bnVsbCwiZnVuY3Rpb25EZWNsYXJhdGlvbnMiOlt7ImRlc2NyaXB0aW9uIjoiQWN0aXZpdHkgdGhhdCBnZXRzIHdlYXRoZXIgZm9yIGEgZ2l2ZW4gY2l0eS4iLCJuYW1lIjoiZ2V0X3dlYXRoZXIiLCJwYXJhbWV0ZXJzIjp7ImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjpudWxsLCJkZWZzIjpudWxsLCJyZWYiOm51bGwsImFueU9mIjpudWxsLCJkZWZhdWx0IjpudWxsLCJkZXNjcmlwdGlvbiI6bnVsbCwiZW51bSI6bnVsbCwiZXhhbXBsZSI6bnVsbCwiZm9ybWF0IjpudWxsLCJpdGVtcyI6bnVsbCwibWF4SXRlbXMiOm51bGwsIm1heExlbmd0aCI6bnVsbCwibWF4UHJvcGVydGllcyI6bnVsbCwibWF4aW11bSI6bnVsbCwibWluSXRlbXMiOm51bGwsIm1pbkxlbmd0aCI6bnVsbCwibWluUHJvcGVydGllcyI6bnVsbCwibWluaW11bSI6bnVsbCwibnVsbGFibGUiOm51bGwsInBhdHRlcm4iOm51bGwsInByb3BlcnRpZXMiOnsiY2l0eSI6eyJhZGRpdGlvbmFsUHJvcGVydGllcyI6bnVsbCwiZGVmcyI6bnVsbCwicmVmIjpudWxsLCJhbnlPZiI6bnVsbCwiZGVmYXVsdCI6bnVsbCwiZGVzY3JpcHRpb24iOm51bGwsImVudW0iOm51bGwsImV4YW1wbGUiOm51bGwsImZvcm1hdCI6bnVsbCwiaXRlbXMiOm51bGwsIm1heEl0ZW1zIjpudWxsLCJtYXhMZW5ndGgiOm51bGwsIm1heFByb3BlcnRpZXMiOm51bGwsIm1heGltdW0iOm51bGwsIm1pbkl0ZW1zIjpudWxsLCJtaW5MZW5ndGgiOm51bGwsIm1pblByb3BlcnRpZXMiOm51bGwsIm1pbmltdW0iOm51bGwsIm51bGxhYmxlIjpudWxsLCJwYXR0ZXJuIjpudWxsLCJwcm9wZXJ0aWVzIjpudWxsLCJwcm9wZXJ0eU9yZGVyaW5nIjpudWxsLCJyZXF1aXJlZCI6bnVsbCwidGl0bGUiOm51bGwsInR5cGUiOiJTVFJJTkcifX0sInByb3BlcnR5T3JkZXJpbmciOm51bGwsInJlcXVpcmVkIjpbImNpdHkiXSwidGl0bGUiOm51bGwsInR5cGUiOiJPQkpFQ1QifSwicGFyYW1ldGVyc0pzb25TY2hlbWEiOm51bGwsInJlc3BvbnNlIjpudWxsLCJyZXNwb25zZUpzb25TY2hlbWEiOm51bGwsImJlaGF2aW9yIjpudWxsfV0sImdvb2dsZU1hcHMiOm51bGwsImdvb2dsZVNlYXJjaCI6bnVsbCwiZ29vZ2xlU2VhcmNoUmV0cmlldmFsIjpudWxsLCJ1cmxDb250ZXh0IjpudWxsfV0sInRvb2xDb25maWciOm51bGwsImxhYmVscyI6bnVsbCwiY2FjaGVkQ29udGVudCI6bnVsbCwicmVzcG9uc2VNb2RhbGl0aWVzIjpudWxsLCJtZWRpYVJlc29sdXRpb24iOm51bGwsInNwZWVjaENvbmZpZyI6bnVsbCwiYXVkaW9UaW1lc3RhbXAiOm51bGwsImF1dG9tYXRpY0Z1bmN0aW9uQ2FsbGluZyI6bnVsbCwidGhpbmtpbmdDb25maWciOm51bGwsImltYWdlQ29uZmlnIjpudWxsLCJlbmFibGVFbmhhbmNlZENpdmljQW5zd2VycyI6bnVsbCwibW9kZWxBcm1vckNvbmZpZyI6bnVsbH0sImxpdmVfY29ubmVjdF9jb25maWciOnsiaHR0cE9wdGlvbnMiOm51bGwsImdlbmVyYXRpb25Db25maWciOm51bGwsInJlc3BvbnNlTW9kYWxpdGllcyI6bnVsbCwidGVtcGVyYXR1cmUiOm51bGwsInRvcFAiOm51bGwsInRvcEsiOm51bGwsIm1heE91dHB1dFRva2VucyI6bnVsbCwibWVkaWFSZXNvbHV0aW9uIjpudWxsLCJzZWVkIjpudWxsLCJzcGVlY2hDb25maWciOm51bGwsInRoaW5raW5nQ29uZmlnIjpudWxsLCJlbmFibGVBZmZlY3RpdmVEaWFsb2ciOm51bGwsInN5c3RlbUluc3RydWN0aW9uIjpudWxsLCJ0b29scyI6bnVsbCwic2Vzc2lvblJlc3VtcHRpb24iOm51bGwsImlucHV0QXVkaW9UcmFuc2NyaXB0aW9uIjp7fSwib3V0cHV0QXVkaW9UcmFuc2NyaXB0aW9uIjp7fSwicmVhbHRpbWVJbnB1dENvbmZpZyI6bnVsbCwiY29udGV4dFdpbmRvd0NvbXByZXNzaW9uIjpudWxsLCJwcm9hY3Rpdml0eSI6bnVsbCwiZXhwbGljaXRWYWRTaWduYWwiOm51bGx9LCJjYWNoZV9jb25maWciOm51bGwsImNhY2hlX21ldGFkYXRhIjpudWxsLCJjYWNoZWFibGVfY29udGVudHNfdG9rZW5fY291bnQiOm51bGwsInByZXZpb3VzX2ludGVyYWN0aW9uX2lkIjpudWxsfQ==" + } + ] + }, + "scheduleToCloseTimeout": "0s", + "scheduleToStartTimeout": "0s", + "startToCloseTimeout": "120s", + "heartbeatTimeout": "0s", + "workflowTaskCompletedEventId": "16", + "retryPolicy": { + "initialInterval": "1s", + "backoffCoefficient": 2.0, + "maximumInterval": "100s" + }, + "useWorkflowBuildId": true, + "priority": {} + }, + "userMetadata": { + "summary": { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "InRlc3RfYWdlbnQi" + } + } + }, + { + "eventId": "18", + "eventTime": "2026-01-26T21:11:30.259830Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_STARTED", + "taskId": "1104162", + "activityTaskStartedEventAttributes": { + "scheduledEventId": "17", + "identity": "70127@Tims-MacBook-Pro.local", + "requestId": "0e5bef66-5e35-4c0c-86eb-f2110a843377", + "attempt": 1, + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + } + } + }, + { + "eventId": "19", + "eventTime": "2026-01-26T21:11:30.261889Z", + "eventType": "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", + "taskId": "1104163", + "activityTaskCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "W3sibW9kZWxWZXJzaW9uIjpudWxsLCJjb250ZW50Ijp7InBhcnRzIjpbeyJtZWRpYVJlc29sdXRpb24iOm51bGwsImNvZGVFeGVjdXRpb25SZXN1bHQiOm51bGwsImV4ZWN1dGFibGVDb2RlIjpudWxsLCJmaWxlRGF0YSI6bnVsbCwiZnVuY3Rpb25DYWxsIjpudWxsLCJmdW5jdGlvblJlc3BvbnNlIjpudWxsLCJpbmxpbmVEYXRhIjpudWxsLCJ0ZXh0Ijoid2FybSBhbmQgc3VubnkiLCJ0aG91Z2h0IjpudWxsLCJ0aG91Z2h0U2lnbmF0dXJlIjpudWxsLCJ2aWRlb01ldGFkYXRhIjpudWxsfV0sInJvbGUiOiJtb2RlbCJ9LCJncm91bmRpbmdNZXRhZGF0YSI6bnVsbCwicGFydGlhbCI6bnVsbCwidHVybkNvbXBsZXRlIjpudWxsLCJmaW5pc2hSZWFzb24iOm51bGwsImVycm9yQ29kZSI6bnVsbCwiZXJyb3JNZXNzYWdlIjpudWxsLCJpbnRlcnJ1cHRlZCI6bnVsbCwiY3VzdG9tTWV0YWRhdGEiOm51bGwsInVzYWdlTWV0YWRhdGEiOm51bGwsImxpdmVTZXNzaW9uUmVzdW1wdGlvblVwZGF0ZSI6bnVsbCwiaW5wdXRUcmFuc2NyaXB0aW9uIjpudWxsLCJvdXRwdXRUcmFuc2NyaXB0aW9uIjpudWxsLCJhdmdMb2dwcm9icyI6bnVsbCwibG9ncHJvYnNSZXN1bHQiOm51bGwsImNhY2hlTWV0YWRhdGEiOm51bGwsImNpdGF0aW9uTWV0YWRhdGEiOm51bGwsImludGVyYWN0aW9uSWQiOm51bGx9XQ==" + } + ] + }, + "scheduledEventId": "17", + "startedEventId": "18", + "identity": "70127@Tims-MacBook-Pro.local" + } + }, + { + "eventId": "20", + "eventTime": "2026-01-26T21:11:30.261891Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED", + "taskId": "1104164", + "workflowTaskScheduledEventAttributes": { + "taskQueue": { + "name": "adk-task-queue", + "kind": "TASK_QUEUE_KIND_NORMAL" + }, + "startToCloseTimeout": "10s", + "attempt": 1 + } + }, + { + "eventId": "21", + "eventTime": "2026-01-26T21:11:30.262662Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED", + "taskId": "1104167", + "workflowTaskStartedEventAttributes": { + "scheduledEventId": "20", + "identity": "70127@Tims-MacBook-Pro.local", + "requestId": "b23c5065-a19d-4fe0-b13b-37a67e21d355", + "historySizeBytes": "10489", + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + } + } + }, + { + "eventId": "22", + "eventTime": "2026-01-26T21:11:30.298088Z", + "eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED", + "taskId": "1104171", + "workflowTaskCompletedEventAttributes": { + "scheduledEventId": "20", + "startedEventId": "21", + "identity": "70127@Tims-MacBook-Pro.local", + "workerVersion": { + "buildId": "33d06b1c69b2db724aa60c7d3ac4fea9" + }, + "sdkMetadata": {}, + "meteringMetadata": {} + } + }, + { + "eventId": "23", + "eventTime": "2026-01-26T21:11:30.298110Z", + "eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED", + "taskId": "1104172", + "workflowExecutionCompletedEventAttributes": { + "result": { + "payloads": [ + { + "metadata": { + "encoding": "anNvbi9wbGFpbg==" + }, + "data": "eyJtb2RlbFZlcnNpb24iOm51bGwsImNvbnRlbnQiOnsicGFydHMiOlt7Im1lZGlhUmVzb2x1dGlvbiI6bnVsbCwiY29kZUV4ZWN1dGlvblJlc3VsdCI6bnVsbCwiZXhlY3V0YWJsZUNvZGUiOm51bGwsImZpbGVEYXRhIjpudWxsLCJmdW5jdGlvbkNhbGwiOm51bGwsImZ1bmN0aW9uUmVzcG9uc2UiOm51bGwsImlubGluZURhdGEiOm51bGwsInRleHQiOiJ3YXJtIGFuZCBzdW5ueSIsInRob3VnaHQiOm51bGwsInRob3VnaHRTaWduYXR1cmUiOm51bGwsInZpZGVvTWV0YWRhdGEiOm51bGx9XSwicm9sZSI6Im1vZGVsIn0sImdyb3VuZGluZ01ldGFkYXRhIjpudWxsLCJwYXJ0aWFsIjpudWxsLCJ0dXJuQ29tcGxldGUiOm51bGwsImZpbmlzaFJlYXNvbiI6bnVsbCwiZXJyb3JDb2RlIjpudWxsLCJlcnJvck1lc3NhZ2UiOm51bGwsImludGVycnVwdGVkIjpudWxsLCJjdXN0b21NZXRhZGF0YSI6bnVsbCwidXNhZ2VNZXRhZGF0YSI6bnVsbCwibGl2ZVNlc3Npb25SZXN1bXB0aW9uVXBkYXRlIjpudWxsLCJpbnB1dFRyYW5zY3JpcHRpb24iOm51bGwsIm91dHB1dFRyYW5zY3JpcHRpb24iOm51bGwsImF2Z0xvZ3Byb2JzIjpudWxsLCJsb2dwcm9ic1Jlc3VsdCI6bnVsbCwiY2FjaGVNZXRhZGF0YSI6bnVsbCwiY2l0YXRpb25NZXRhZGF0YSI6bnVsbCwiaW50ZXJhY3Rpb25JZCI6bnVsbCwiaW52b2NhdGlvbklkIjoiZS1mMDdiNjJmOS03NzUwLTQ5YjctYmYwYi1jZDkwM2M2YTM0MGYiLCJhdXRob3IiOiJ0ZXN0X2FnZW50IiwiYWN0aW9ucyI6eyJza2lwU3VtbWFyaXphdGlvbiI6bnVsbCwic3RhdGVEZWx0YSI6e30sImFydGlmYWN0RGVsdGEiOnt9LCJ0cmFuc2ZlclRvQWdlbnQiOm51bGwsImVzY2FsYXRlIjpudWxsLCJyZXF1ZXN0ZWRBdXRoQ29uZmlncyI6e30sInJlcXVlc3RlZFRvb2xDb25maXJtYXRpb25zIjp7fSwiY29tcGFjdGlvbiI6bnVsbCwiZW5kT2ZBZ2VudCI6bnVsbCwiYWdlbnRTdGF0ZSI6bnVsbCwicmV3aW5kQmVmb3JlSW52b2NhdGlvbklkIjpudWxsfSwibG9uZ1J1bm5pbmdUb29sSWRzIjpudWxsLCJicmFuY2giOm51bGwsImlkIjoiZmViZmMyMGEtOTM1OS00YWY1LTliMGEtNGI2ODAyNjAyZTdhIiwidGltZXN0YW1wIjoxNzY5NDYxODkwLjIyNTgxNH0=" + } + ] + }, + "workflowTaskCompletedEventId": "22" + } + } + ] +} \ No newline at end of file diff --git a/tests/contrib/google_adk_agents/test_temporal_integration.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py similarity index 54% rename from tests/contrib/google_adk_agents/test_temporal_integration.py rename to tests/contrib/google_adk_agents/test_google_adk_agents.py index 361e08b1a..ad5c1c525 100644 --- a/tests/contrib/google_adk_agents/test_temporal_integration.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -14,40 +14,30 @@ """Integration tests for ADK Temporal support.""" -import dataclasses import logging +import os import uuid from datetime import timedelta +from pathlib import Path +from typing import AsyncGenerator, Iterator import pytest from google.adk import Agent, Runner from google.adk.agents import LlmAgent from google.adk.events import Event +from google.adk.models import BaseLlm, LLMRegistry +from google.adk.models.llm_request import LlmRequest +from google.adk.models.llm_response import LlmResponse from google.adk.sessions import InMemorySessionService from google.adk.utils.context_utils import Aclosing from google.genai import types +from google.genai.types import Content, FunctionCall, Part from temporalio import activity, workflow from temporalio.client import Client from temporalio.contrib.google_adk_agents import AgentPlugin, GoogleAdkPlugin -from temporalio.contrib.pydantic import ( - PydanticPayloadConverter, -) -from temporalio.converter import DataConverter from temporalio.worker import Worker -# Required Environment Variables for this test: -# in this folder update .env.example to be .env and have the following vars: -# GOOGLE_GENAI_USE_VERTEXAI=1 -# GOOGLE_CLOUD_PROJECT="" -# GOOGLE_CLOUD_LOCATION="" -# TEST_BACKEND=VERTEX_ONLY -# then: -# start temporal: temporal server start-dev -# then: -# uv run pytest tests/integration/manual_test_temporal_integration.py - - logger = logging.getLogger(__name__) @@ -60,7 +50,7 @@ async def get_weather(city: str) -> str: @workflow.defn class WeatherAgent: @workflow.run - async def run(self, prompt: str) -> Event | None: + async def run(self, prompt: str, model_name: str) -> Event | None: logger.info("Workflow started.") # 1. Define Agent using Temporal Helpers @@ -74,7 +64,7 @@ async def run(self, prompt: str) -> Event | None: agent = Agent( name="test_agent", - model="gemini-2.5-pro", # Standard model string + model=model_name, tools=[weather_tool], ) @@ -118,7 +108,7 @@ async def run(self, prompt: str) -> Event | None: @workflow.defn class MultiAgentWorkflow: @workflow.run - async def run(self, topic: str) -> str: + async def run(self, topic: str, model_name: str) -> str | None: # Example of multi-turn/multi-agent orchestration # This is where Temporal shines - orchestrating complex agent flows @@ -134,21 +124,21 @@ async def run(self, topic: str) -> str: # Sub-agent: Researcher researcher = LlmAgent( name="researcher", - model="gemini-2.5-pro", + model=model_name, instruction="You are a researcher. Find information about the topic.", ) # Sub-agent: Writer writer = LlmAgent( name="writer", - model="gemini-2.5-pro", + model=model_name, instruction="You are a poet. Write a haiku based on the research.", ) # Root Agent: Coordinator coordinator = LlmAgent( name="coordinator", - model="gemini-2.5-pro", + model=model_name, instruction="You are a coordinator. Delegate to researcher then writer.", sub_agents=[researcher, writer], ) @@ -186,24 +176,48 @@ async def run(self, topic: str) -> str: return final_content +class WeatherModel(BaseLlm): + responses: list[LlmResponse] = [ + LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + args={"city": "New York"}, name="get_weather" + ) + ) + ], + ) + ), + LlmResponse( + content=Content( + role="model", + parts=[Part(text="warm and sunny")], + ) + ), + ] + response_iter: Iterator[LlmResponse] = iter(responses) + + @classmethod + def supported_models(cls) -> list[str]: + return ["weather_model"] + + async def generate_content_async( + self, llm_request: LlmRequest, stream: bool = False + ) -> AsyncGenerator[LlmResponse, None]: + yield next(self.response_iter) + + +@pytest.mark.parametrize("use_local_model", [True, False]) @pytest.mark.asyncio -async def test_temporal_integration(): - """Manual integration test requiring a running Temporal server.""" - - # 1. Start a Worker (in a real app, this would be a separate process) - # We run it here for the test. - - try: - # Connect to Temporal Server - # We must configure the data converter to handle Pydantic models (like Event) - client = await Client.connect( - "localhost:7233", - data_converter=DataConverter( - payload_converter_class=PydanticPayloadConverter - ), - ) - except RuntimeError: - pytest.skip("Could not connect to Temporal server. Is it running?") +async def test_single_agent(client: Client, use_local_model: bool): + if not use_local_model and not os.environ.get("GOOGLE_API_KEY"): + pytest.skip("No google API key") + + new_config = client.config() + new_config["plugins"] = [GoogleAdkPlugin()] + client = Client(**new_config) # Run Worker with the ADK plugin async with Worker( @@ -212,24 +226,112 @@ async def test_temporal_integration(): activities=[ get_weather, ], - workflows=[WeatherAgent, MultiAgentWorkflow], - plugins=[GoogleAdkPlugin()], + workflows=[WeatherAgent], + max_cached_workflows=0, ): - print("Worker started.") + if use_local_model: + LLMRegistry.register(WeatherModel) + # Test Weather Agent - result = await client.execute_workflow( + handle = await client.start_workflow( WeatherAgent.run, - "What is the weather in New York?", + args=[ + "What is the weather in New York?", + "weather_model" if use_local_model else "gemini-2.5-pro", + ], id=f"weather-agent-workflow-{uuid.uuid4()}", task_queue="adk-task-queue", ) + result = await handle.result() print(f"Workflow result: {result}") + if use_local_model: + assert result is not None + assert result.content is not None + assert result.content.parts is not None + assert result.content.parts[0].text == "warm and sunny" + + with (Path(__file__).with_name("histories") / "single_agent.json").open( + "w" + ) as f: + f.write((await handle.fetch_history()).to_json()) + + +class ResearchModel(BaseLlm): + responses: list[LlmResponse] = [ + LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + args={"agent_name": "researcher"}, name="transfer_to_agent" + ) + ) + ], + ) + ), + LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + args={"agent_name": "writer"}, name="transfer_to_agent" + ) + ) + ], + ) + ), + LlmResponse( + content=Content( + role="model", + parts=[Part(text="haiku")], + ) + ), + ] + response_iter: Iterator[LlmResponse] = iter(responses) + + @classmethod + def supported_models(cls) -> list[str]: + return ["research_model"] + + async def generate_content_async( + self, llm_request: LlmRequest, stream: bool = False + ) -> AsyncGenerator[LlmResponse, None]: + yield next(self.response_iter) + + +@pytest.mark.parametrize("use_local_model", [True, False]) +@pytest.mark.asyncio +async def test_multi_agent(client: Client, use_local_model: bool): + if not use_local_model and not os.environ.get("GOOGLE_API_KEY"): + pytest.skip("No google API key") + + new_config = client.config() + new_config["plugins"] = [GoogleAdkPlugin()] + client = Client(**new_config) + + # Run Worker with the ADK plugin + async with Worker( + client, + task_queue="adk-task-queue", + workflows=[MultiAgentWorkflow], + max_cached_workflows=0, + ): + if use_local_model: + LLMRegistry.register(ResearchModel) # Test Multi Agent - result_multi = await client.execute_workflow( + handle = await client.start_workflow( MultiAgentWorkflow.run, - "Run mult-agent flow", + args=[ + "Run mult-agent flow", + "research_model" if use_local_model else "gemini-2.5-pro", + ], id=f"multi-agent-workflow-{uuid.uuid4()}", task_queue="adk-task-queue", ) - print(f"Multi-Agent Workflow result: {result_multi}") + result = await handle.result() + print(f"Multi-Agent Workflow result: {result}") + if use_local_model: + assert result == "haiku" diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents_replay.py b/tests/contrib/google_adk_agents/test_google_adk_agents_replay.py new file mode 100644 index 000000000..810ca95f0 --- /dev/null +++ b/tests/contrib/google_adk_agents/test_google_adk_agents_replay.py @@ -0,0 +1,33 @@ +from pathlib import Path + +import pytest +from google.adk.models import LLMRegistry + +from temporalio.client import WorkflowHistory +from temporalio.contrib.google_adk_agents import GoogleAdkPlugin +from temporalio.worker import Replayer +from tests.contrib.google_adk_agents.test_google_adk_agents import ( + MultiAgentWorkflow, + ResearchModel, + WeatherAgent, + WeatherModel, +) + + +@pytest.mark.parametrize( + "file_name", + [ + "multi_agent.json", + "single_agent.json", + ], +) +async def test_replay(file_name: str) -> None: + with (Path(__file__).with_name("histories") / file_name).open("r") as f: + history_json = f.read() + + LLMRegistry.register(ResearchModel) + LLMRegistry.register(WeatherModel) + await Replayer( + workflows=[MultiAgentWorkflow, WeatherAgent], + plugins=[GoogleAdkPlugin()], + ).replay_workflow(WorkflowHistory.from_json("fake", history_json)) diff --git a/tests/contrib/google_adk_agents/test_temporal_unit.py b/tests/contrib/google_adk_agents/test_temporal_unit.py deleted file mode 100644 index 41447b09b..000000000 --- a/tests/contrib/google_adk_agents/test_temporal_unit.py +++ /dev/null @@ -1,177 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Unit tests for Temporal integration helpers.""" - -import asyncio -import sys -import unittest -from typing import Any -from unittest.mock import AsyncMock, MagicMock, patch - -from google.genai import types - -# Configure Mocks globally -# We create fresh mocks here. -mock_workflow = MagicMock() -mock_activity = MagicMock() -mock_worker = MagicMock() -mock_client = MagicMock() -mock_converter = MagicMock() - -# Important: execute_activity must be awaitable -mock_workflow.execute_activity = AsyncMock(return_value="mock_result") -mock_workflow.in_workflow = MagicMock(return_value=False) -mock_workflow.now = MagicMock() -mock_workflow.uuid4 = MagicMock() - -# Mock the parent package -mock_temporalio = MagicMock() -mock_temporalio.workflow = mock_workflow -mock_temporalio.activity = mock_activity -mock_temporalio.worker = mock_worker -mock_temporalio.client = mock_client -mock_temporalio.converter = mock_converter - - -class FakeSimplePlugin: - def __init__(self, **kwargs): - pass - - -mock_temporalio.plugin = MagicMock() -mock_temporalio.plugin.SimplePlugin = FakeSimplePlugin -mock_temporalio.worker.workflow_sandbox = MagicMock() -mock_temporalio.contrib = MagicMock() -mock_temporalio.contrib.pydantic = MagicMock() - -# Mock sys.modules -# Mock sys.modules -# We must ensure we get a fresh import of 'google.adk.integrations.temporal' -# that uses our MOCKED 'temporalio'. -# If it was already loaded, we remove it. -for mod in list(sys.modules.keys()): - if mod.startswith("google.adk") or mod == "temporalio": - del sys.modules[mod] - -with patch.dict( - sys.modules, - { - "temporalio": mock_temporalio, - "temporalio.workflow": mock_workflow, - "temporalio.activity": mock_activity, - "temporalio.worker": mock_worker, - "temporalio.client": mock_client, - "temporalio.converter": mock_converter, - "temporalio.common": MagicMock(), - "temporalio.plugin": mock_temporalio.plugin, - "temporalio.worker.workflow_sandbox": mock_temporalio.worker.workflow_sandbox, - "temporalio.contrib": mock_temporalio.contrib, - "temporalio.contrib.pydantic": mock_temporalio.contrib.pydantic, - }, -): - from google.adk import runtime - from google.adk.agents.callback_context import CallbackContext - from google.adk.agents.invocation_context import InvocationContext - from google.adk.models import LlmRequest, LlmResponse - - from temporalio.contrib import google_adk_agents as temporal - - -class TestTemporalIntegration(unittest.TestCase): - def test_activity_as_tool_wrapper(self): - # Reset mocks - mock_workflow.reset_mock() - mock_workflow.execute_activity = AsyncMock(return_value="mock_result") - - # Verify mock setup - assert temporal.workflow.execute_activity is mock_workflow.execute_activity - - # Define a fake activity - async def my_activity(arg: str) -> str: - """My Docstring.""" - return f"Hello {arg}" - - # Wrap it - tool = temporal.AgentPlugin.activity_tool( - my_activity, start_to_close_timeout=100 - ) - - # Check metadata - self.assertEqual(tool.__name__, "my_activity") # Matches function name - self.assertEqual(tool.__doc__, "My Docstring.") - - # Run tool (wrapper) - loop = asyncio.new_event_loop() - try: - asyncio.set_event_loop(loop) - loop.run_until_complete(tool(arg="World")) - finally: - loop.close() - - # Verify call - mock_workflow.execute_activity.assert_called_once() - args, kwargs = mock_workflow.execute_activity.call_args - self.assertEqual(args[1], "World") - self.assertEqual(kwargs["start_to_close_timeout"], 100) - - def test_temporal_plugin_before_model(self): - plugin = temporal.AgentPlugin(activity_options={"start_to_close_timeout": 60}) - - # Setup mocks - mock_workflow.reset_mock() - mock_workflow.in_workflow.return_value = True - response_content = types.Content(parts=[types.Part(text="plugin_resp")]) - llm_response = LlmResponse(content=response_content) - # The plugin now expects the activity to return dicts (model_dump(mode='json')) - # to ensure safe deserialization across process boundaries. - response_dict = llm_response.model_dump(mode="json", by_alias=True) - # Ensure 'content' key is present and correct (pydantic dump might be complex) - # For the test simple case, the dump is sufficient. - - mock_workflow.execute_activity = AsyncMock(return_value=[response_dict]) - - # callback_context = MagicMock(spec=CallbackContext) - # Using spec might hide dynamic attributes or properties if not fully mocked - callback_context = MagicMock() - callback_context.agent_name = "test-agent" - callback_context.invocation_context.agent.model = "test-agent-model" - - llm_request = LlmRequest(model="test-agent-model", prompt="hi") - - # Run callback - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - try: - result = loop.run_until_complete( - plugin.before_model_callback( - callback_context=callback_context, llm_request=llm_request - ) - ) - finally: - loop.close() - - # Verify execution - mock_workflow.execute_activity.assert_called_once() - args, kwargs = mock_workflow.execute_activity.call_args - self.assertEqual(kwargs["start_to_close_timeout"], 60) - - # Check dynamic activity name - self.assertEqual(args[0], "test-agent.generate_content") - self.assertEqual(kwargs["args"][0].model, "test-agent-model") - - # Verify result merge - self.assertIsNotNone(result) - # Result is re-hydrated LlmResponse - self.assertEqual(result.content.parts[0].text, "plugin_resp") From a04b1093fb8f867d9f315e8df75909cbd0b5d26e Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Thu, 29 Jan 2026 08:25:08 -0800 Subject: [PATCH 5/6] Work in progress mcp support --- .../contrib/google_adk_agents/__init__.py | 202 +--------------- temporalio/contrib/google_adk_agents/_mcp.py | 215 ++++++++++++++++++ .../contrib/google_adk_agents/_plugin.py | 184 +++++++++++++++ .../test_google_adk_agents.py | 162 ++++++++++++- .../test_google_adk_agents_replay.py | 4 +- 5 files changed, 569 insertions(+), 198 deletions(-) create mode 100644 temporalio/contrib/google_adk_agents/_mcp.py create mode 100644 temporalio/contrib/google_adk_agents/_plugin.py diff --git a/temporalio/contrib/google_adk_agents/__init__.py b/temporalio/contrib/google_adk_agents/__init__.py index 2e094fe3d..47e71da36 100644 --- a/temporalio/contrib/google_adk_agents/__init__.py +++ b/temporalio/contrib/google_adk_agents/__init__.py @@ -1,198 +1,20 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - """Temporal Integration for ADK. This module provides the necessary components to run ADK Agents within Temporal Workflows. """ -from __future__ import annotations - -import dataclasses -import inspect -import time -import uuid -from contextlib import asynccontextmanager -from typing import Any, AsyncIterator, Callable, Optional - -from google.adk.agents.callback_context import CallbackContext -from google.adk.models import LLMRegistry -from google.adk.models.llm_request import LlmRequest -from google.adk.models.llm_response import LlmResponse -from google.adk.plugins import BasePlugin - -from temporalio import activity, workflow -from temporalio.contrib.pydantic import ( - PydanticPayloadConverter as _DefaultPydanticPayloadConverter, +from temporalio.contrib.google_adk_agents._mcp import ( + TemporalToolSet, + TemporalToolSetProvider, ) -from temporalio.converter import DataConverter, DefaultPayloadConverter -from temporalio.plugin import SimplePlugin -from temporalio.worker import ( - WorkflowRunner, +from temporalio.contrib.google_adk_agents._plugin import ( + AdkAgentPlugin, + TemporalAdkPlugin, ) -from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner - - -def setup_deterministic_runtime(): - """Configures ADK runtime for Temporal determinism. - - This should be called at the start of a Temporal Workflow before any ADK components - (like SessionService) are used, if they rely on runtime.get_time() or runtime.new_uuid(). - """ - try: - from google.adk import runtime - - # Define safer, context-aware providers - def _deterministic_time_provider() -> float: - if workflow.in_workflow(): - return workflow.now().timestamp() - return time.time() - - def _deterministic_id_provider() -> str: - if workflow.in_workflow(): - return str(workflow.uuid4()) - return str(uuid.uuid4()) - - runtime.set_time_provider(_deterministic_time_provider) - runtime.set_id_provider(_deterministic_id_provider) - except ImportError: - pass - except Exception as e: - print(f"Warning: Failed to set deterministic runtime providers: {e}") - - -class AgentPlugin(BasePlugin): - """ADK Plugin for Temporal integration. - - This plugin automatically configures the ADK runtime to be deterministic when running - inside a Temporal workflow, and intercepts model calls to execute them as Temporal Activities. - """ - - def __init__(self, activity_options: Optional[dict[str, Any]] = None): - """Initializes the Temporal Plugin. - - Args: - activity_options: Default options for model activities (e.g. start_to_close_timeout). - """ - super().__init__(name="temporal_plugin") - self.activity_options = activity_options or {} - - @staticmethod - def activity_tool(activity_def: Callable, **kwargs: Any) -> Callable: - """Decorator/Wrapper to wrap a Temporal Activity as an ADK Tool. - - This ensures the activity's signature is preserved for ADK's tool schema generation - while marking it as a tool that executes via 'workflow.execute_activity'. - """ - - async def wrapper(*args, **kw): - # Inspect signature to bind arguments - sig = inspect.signature(activity_def) - bound = sig.bind(*args, **kw) - bound.apply_defaults() - - # Convert to positional args for Temporal - activity_args = list(bound.arguments.values()) - - # Decorator kwargs are defaults. - options = kwargs.copy() - - return await workflow.execute_activity( - activity_def, *activity_args, **options - ) - - # Copy metadata - wrapper.__name__ = activity_def.__name__ - wrapper.__doc__ = activity_def.__doc__ - setattr(wrapper, "__signature__", inspect.signature(activity_def)) - - return wrapper - - async def before_model_callback( - self, *, callback_context: CallbackContext, llm_request: LlmRequest - ) -> LlmResponse | None: - responses = await workflow.execute_activity( - invoke_model, - args=[llm_request], - summary=callback_context.agent_name, - **self.activity_options, - ) - - # Simple consolidation: return the last complete response - return responses[-1] if responses else None - - -@activity.defn -async def invoke_model(llm_request: LlmRequest) -> list[LlmResponse]: - if llm_request.model is None: - raise ValueError(f"No model name provided, could not create LLM.") - - llm = LLMRegistry.new_llm(llm_request.model) - if not llm: - raise ValueError(f"Failed to create LLM for model: {llm_request.model}") - - return [ - response - async for response in llm.generate_content_async(llm_request=llm_request) - ] - - -class GoogleAdkPlugin(SimplePlugin): - """A Temporal Worker Plugin configured for ADK. - - This plugin configures: - 1. Pydantic Payload Converter (required for ADK objects). - 2. Sandbox Passthrough for `google.adk` and `google.genai`. - """ - - def __init__(self): - @asynccontextmanager - async def run_context() -> AsyncIterator[None]: - setup_deterministic_runtime() - yield - - def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: - if not runner: - raise ValueError("No WorkflowRunner provided to the ADK plugin.") - - # If in sandbox, add additional passthrough - if isinstance(runner, SandboxedWorkflowRunner): - return dataclasses.replace( - runner, - restrictions=runner.restrictions.with_passthrough_modules( - "google.adk", "google.genai" - ), - ) - return runner - - super().__init__( - name="google_adk_plugin", - data_converter=self._configure_data_converter, - activities=[invoke_model], - run_context=lambda: run_context(), - workflow_runner=workflow_runner, - ) - def _configure_data_converter( - self, converter: DataConverter | None - ) -> DataConverter: - if converter is None: - return DataConverter( - payload_converter_class=_DefaultPydanticPayloadConverter - ) - elif converter.payload_converter_class is DefaultPayloadConverter: - return dataclasses.replace( - converter, payload_converter_class=_DefaultPydanticPayloadConverter - ) - return converter +__all__ = [ + "AdkAgentPlugin", + "TemporalAdkPlugin", + "TemporalToolSet", + "TemporalToolSetProvider", +] diff --git a/temporalio/contrib/google_adk_agents/_mcp.py b/temporalio/contrib/google_adk_agents/_mcp.py new file mode 100644 index 000000000..0a195072e --- /dev/null +++ b/temporalio/contrib/google_adk_agents/_mcp.py @@ -0,0 +1,215 @@ +from collections.abc import Sequence +from dataclasses import dataclass +from datetime import timedelta +from typing import Any, Callable + +from google.adk.agents.readonly_context import ReadonlyContext +from google.adk.events import EventActions +from google.adk.tools import ToolContext +from google.adk.tools.base_tool import BaseTool +from google.adk.tools.base_toolset import BaseToolset +from google.adk.tools.tool_confirmation import ToolConfirmation +from google.genai import types +from google.genai.types import FunctionDeclaration + +from temporalio import activity, workflow +from temporalio.exceptions import ApplicationError +from temporalio.workflow import ActivityConfig + + +@dataclass +class _GetToolsArguments: + factory_argument: Any | None + + +@dataclass +class _ToolResult: + name: str + description: str + is_long_running: bool + custom_metadata: dict[str, Any] | None + function_declaration: FunctionDeclaration | None + + +@dataclass +class TemporalToolContext: + tool_confirmation: ToolConfirmation | None + function_call_id: str | None + event_actions: EventActions | None + + def request_confirmation( + self, + *, + hint: str | None = None, + payload: Any | None = None, + ) -> None: + """Requests confirmation for the given function call. + + Args: + hint: A hint to the user on how to confirm the tool call. + payload: The payload used to confirm the tool call. + """ + if not self.function_call_id: + raise ValueError('function_call_id is not set.') + self.event_actions.requested_tool_confirmations[self.function_call_id] = ( + ToolConfirmation( + hint=hint, + payload=payload, + ) + ) + + +@dataclass +class _CallToolResult: + result: Any + tool_context: TemporalToolContext + +@dataclass +class _CallToolArguments: + factory_argument: Any | None + name: str + arguments: dict[str, Any] + tool_context: TemporalToolContext + +class TemporalToolSetProvider: + def __init__( + self, name: str, toolset_factory: Callable[[Any | None], BaseToolset] + ): + super().__init__() + self._name = name + self._toolset_factory = toolset_factory + + def _get_activities(self) -> Sequence[Callable]: + @activity.defn(name=self._name + "-list-tools") + async def get_tools( + args: _GetToolsArguments, + ) -> list[_ToolResult]: + toolset = self._toolset_factory(args.factory_argument) + tools = await toolset.get_tools() + return [ + _ToolResult( + tool.name, + tool.description, + tool.is_long_running, + tool.custom_metadata, + tool._get_declaration(), + ) + for tool in tools + ] + + @activity.defn(name=self._name + "-call-tool") + async def call_tool( + args: _CallToolArguments, + ) -> _CallToolResult: + toolset = self._toolset_factory(args.factory_argument) + tools = await toolset.get_tools() + tool_match = [tool for tool in tools if tool.name == args.name] + if len(tool_match) == 0: + raise ApplicationError( + f"Unable to find matching mcp tool by name: {args.name}" + ) + if len(tool_match) > 1: + raise ApplicationError( + f"Unable too many matching mcp tools by name: {args.name}" + ) + tool = tool_match[0] + + # We cannot provide a full-fledged ToolContext so we need to provide only what is needed by the tool + result = await tool.run_async( + args=args.arguments, + tool_context=args.tool_context, # type:ignore + ) + return _CallToolResult(result=result, tool_context=args.tool_context) + + return get_tools, call_tool + + +class _TemporalTool(BaseTool): + def __init__( + self, + set_name: str, + factory_argument: Any | None, + config: ActivityConfig | None, + declaration: FunctionDeclaration | None, + *, + name: str, + description: str, + is_long_running: bool = False, + custom_metadata: dict[str, Any] | None = None, + ): + super().__init__( + name=name, + description=description, + is_long_running=is_long_running, + custom_metadata=custom_metadata, + ) + self._set_name = set_name + self._factory_argument = factory_argument + self._config = config or ActivityConfig( + start_to_close_timeout=timedelta(minutes=1) + ) + self._declaration = declaration + + def _get_declaration(self) -> types.FunctionDeclaration | None: + return self._declaration + + async def run_async( + self, *, args: dict[str, Any], tool_context: ToolContext + ) -> Any: + result: _CallToolResult = await workflow.execute_activity( + self._set_name + "-call-tool", + _CallToolArguments( + self._factory_argument, + self.name, + arguments=args, + tool_context=TemporalToolContext( + tool_confirmation=tool_context.tool_confirmation, + function_call_id=tool_context.function_call_id, + event_actions=tool_context._event_actions, + ), + ), + result_type=_CallToolResult, + **self._config, + ) + + # We need to propagate any event actions back to the main context + tool_context._event_actions = result.tool_context.event_actions + return result.result + + +class TemporalToolSet(BaseToolset): + def __init__( + self, + name: str, + config: ActivityConfig | None = None, + factory_argument: Any | None = None, + ): + super().__init__() + self._name = name + self._factory_argument = factory_argument + self._config = config or ActivityConfig( + start_to_close_timeout=timedelta(minutes=1) + ) + + async def get_tools( + self, readonly_context: ReadonlyContext | None = None + ) -> list[BaseTool]: + tool_results: list[_ToolResult] = await workflow.execute_activity( + self._name + "-list-tools", + _GetToolsArguments(self._factory_argument), + result_type=list[_ToolResult], + **self._config, + ) + return [ + _TemporalTool( + set_name=self._name, + factory_argument=self._factory_argument, + config=self._config, + declaration=tool_result.function_declaration, + name=tool_result.name, + description=tool_result.description, + is_long_running=tool_result.is_long_running, + custom_metadata=tool_result.custom_metadata, + ) + for tool_result in tool_results + ] diff --git a/temporalio/contrib/google_adk_agents/_plugin.py b/temporalio/contrib/google_adk_agents/_plugin.py new file mode 100644 index 000000000..31ae29808 --- /dev/null +++ b/temporalio/contrib/google_adk_agents/_plugin.py @@ -0,0 +1,184 @@ +from __future__ import annotations + +import dataclasses +import inspect +import time +import uuid +from contextlib import asynccontextmanager +from typing import Any, AsyncIterator, Callable, Optional + +from google.adk.agents.callback_context import CallbackContext +from google.adk.models import LLMRegistry +from google.adk.models.llm_request import LlmRequest +from google.adk.models.llm_response import LlmResponse +from google.adk.plugins import BasePlugin + +from temporalio import activity, workflow +from temporalio.contrib.google_adk_agents._mcp import TemporalToolSetProvider +from temporalio.contrib.pydantic import ( + PydanticPayloadConverter as _DefaultPydanticPayloadConverter, +) +from temporalio.converter import DataConverter, DefaultPayloadConverter +from temporalio.plugin import SimplePlugin +from temporalio.worker import ( + WorkflowRunner, +) +from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner + + +def setup_deterministic_runtime(): + """Configures ADK runtime for Temporal determinism. + + This should be called at the start of a Temporal Workflow before any ADK components + (like SessionService) are used, if they rely on runtime.get_time() or runtime.new_uuid(). + """ + try: + from google.adk import runtime + + # Define safer, context-aware providers + def _deterministic_time_provider() -> float: + if workflow.in_workflow(): + return workflow.now().timestamp() + return time.time() + + def _deterministic_id_provider() -> str: + if workflow.in_workflow(): + return str(workflow.uuid4()) + return str(uuid.uuid4()) + + runtime.set_time_provider(_deterministic_time_provider) + runtime.set_id_provider(_deterministic_id_provider) + except ImportError: + pass + except Exception as e: + print(f"Warning: Failed to set deterministic runtime providers: {e}") + + +class AdkAgentPlugin(BasePlugin): + """ADK Plugin for Temporal integration. + + This plugin automatically configures the ADK runtime to be deterministic when running + inside a Temporal workflow, and intercepts model calls to execute them as Temporal Activities. + """ + + def __init__(self, activity_options: Optional[dict[str, Any]] = None): + """Initializes the Temporal Plugin. + + Args: + activity_options: Default options for model activities (e.g. start_to_close_timeout). + """ + super().__init__(name="temporal_plugin") + self.activity_options = activity_options or {} + + @staticmethod + def activity_tool(activity_def: Callable, **kwargs: Any) -> Callable: + """Decorator/Wrapper to wrap a Temporal Activity as an ADK Tool. + + This ensures the activity's signature is preserved for ADK's tool schema generation + while marking it as a tool that executes via 'workflow.execute_activity'. + """ + + async def wrapper(*args, **kw): + # Inspect signature to bind arguments + sig = inspect.signature(activity_def) + bound = sig.bind(*args, **kw) + bound.apply_defaults() + + # Convert to positional args for Temporal + activity_args = list(bound.arguments.values()) + + # Decorator kwargs are defaults. + options = kwargs.copy() + + return await workflow.execute_activity( + activity_def, *activity_args, **options + ) + + # Copy metadata + wrapper.__name__ = activity_def.__name__ + wrapper.__doc__ = activity_def.__doc__ + setattr(wrapper, "__signature__", inspect.signature(activity_def)) + + return wrapper + + async def before_model_callback( + self, *, callback_context: CallbackContext, llm_request: LlmRequest + ) -> LlmResponse | None: + responses = await workflow.execute_activity( + invoke_model, + args=[llm_request], + summary=callback_context.agent_name, + **self.activity_options, + ) + + # Simple consolidation: return the last complete response + return responses[-1] if responses else None + + +@activity.defn +async def invoke_model(llm_request: LlmRequest) -> list[LlmResponse]: + if llm_request.model is None: + raise ValueError(f"No model name provided, could not create LLM.") + + llm = LLMRegistry.new_llm(llm_request.model) + if not llm: + raise ValueError(f"Failed to create LLM for model: {llm_request.model}") + + return [ + response + async for response in llm.generate_content_async(llm_request=llm_request) + ] + + +class TemporalAdkPlugin(SimplePlugin): + """A Temporal Worker Plugin configured for ADK. + + This plugin configures: + 1. Pydantic Payload Converter (required for ADK objects). + 2. Sandbox Passthrough for `google.adk` and `google.genai`. + """ + + def __init__(self, toolset_providers: list[TemporalToolSetProvider] = ()): + @asynccontextmanager + async def run_context() -> AsyncIterator[None]: + setup_deterministic_runtime() + yield + + def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: + if not runner: + raise ValueError("No WorkflowRunner provided to the ADK plugin.") + + # If in sandbox, add additional passthrough + if isinstance(runner, SandboxedWorkflowRunner): + return dataclasses.replace( + runner, + restrictions=runner.restrictions.with_passthrough_modules( + "google.adk", "google.genai", "mcp" + ), + ) + return runner + + new_activities = [invoke_model] + for toolset_provider in toolset_providers: + new_activities.extend(toolset_provider._get_activities()) + + super().__init__( + name="google_adk_plugin", + data_converter=self._configure_data_converter, + activities=new_activities, + run_context=lambda: run_context(), + workflow_runner=workflow_runner, + ) + + def _configure_data_converter( + self, converter: DataConverter | None + ) -> DataConverter: + if converter is None: + return DataConverter( + payload_converter_class=_DefaultPydanticPayloadConverter + ) + elif converter.payload_converter_class is DefaultPayloadConverter: + return dataclasses.replace( + converter, payload_converter_class=_DefaultPydanticPayloadConverter + ) + return converter diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index ad5c1c525..9dbc49357 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -29,13 +29,21 @@ from google.adk.models.llm_request import LlmRequest from google.adk.models.llm_response import LlmResponse from google.adk.sessions import InMemorySessionService +from google.adk.tools.mcp_tool import McpToolset +from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams from google.adk.utils.context_utils import Aclosing from google.genai import types from google.genai.types import Content, FunctionCall, Part +from mcp import StdioServerParameters from temporalio import activity, workflow from temporalio.client import Client -from temporalio.contrib.google_adk_agents import AgentPlugin, GoogleAdkPlugin +from temporalio.contrib.google_adk_agents import ( + AdkAgentPlugin, + TemporalAdkPlugin, + TemporalToolSet, + TemporalToolSetProvider, +) from temporalio.worker import Worker logger = logging.getLogger(__name__) @@ -58,7 +66,7 @@ async def run(self, prompt: str, model_name: str) -> Event | None: # and Model Activity interception. We use standard ADK models now. # Wraps 'get_weather' activity as a Tool - weather_tool = AgentPlugin.activity_tool( + weather_tool = AdkAgentPlugin.activity_tool( get_weather, start_to_close_timeout=timedelta(seconds=60) ) @@ -83,7 +91,7 @@ async def run(self, prompt: str, model_name: str) -> Event | None: app_name="test_app", session_service=session_service, plugins=[ - AgentPlugin( + AdkAgentPlugin( activity_options={"start_to_close_timeout": timedelta(minutes=2)} ) ], @@ -149,7 +157,7 @@ async def run(self, topic: str, model_name: str) -> str | None: app_name="multi_agent_app", session_service=session_service, plugins=[ - AgentPlugin( + AdkAgentPlugin( activity_options={"start_to_close_timeout": timedelta(minutes=2)} ) ], @@ -216,7 +224,7 @@ async def test_single_agent(client: Client, use_local_model: bool): pytest.skip("No google API key") new_config = client.config() - new_config["plugins"] = [GoogleAdkPlugin()] + new_config["plugins"] = [TemporalAdkPlugin()] client = Client(**new_config) # Run Worker with the ADK plugin @@ -308,7 +316,7 @@ async def test_multi_agent(client: Client, use_local_model: bool): pytest.skip("No google API key") new_config = client.config() - new_config["plugins"] = [GoogleAdkPlugin()] + new_config["plugins"] = [TemporalAdkPlugin()] client = Client(**new_config) # Run Worker with the ADK plugin @@ -335,3 +343,145 @@ async def test_multi_agent(client: Client, use_local_model: bool): print(f"Multi-Agent Workflow result: {result}") if use_local_model: assert result == "haiku" + + +@workflow.defn +class McpAgent: + @workflow.run + async def run(self, prompt: str, model_name: str) -> Event | None: + logger.info("Workflow started.") + + # 1. Define Agent using Temporal Helpers + # Note: AgentPlugin in the Runner automatically handles Runtime setup + # and Model Activity interception. We use standard ADK models now. + agent = Agent( + name="test_agent", + # instruction="Always use your tools to answer questions.", + model=model_name, + tools=[TemporalToolSet("test_set")], + ) + + # 2. Create Session (uses runtime.new_uuid() -> workflow.uuid4()) + session_service = InMemorySessionService() + logger.info("Create session.") + session = await session_service.create_session( + app_name="test_app", user_id="test" + ) + + logger.info(f"Session created with ID: {session.id}") + + # 3. Run Agent with AgentPlugin + runner = Runner( + agent=agent, + app_name="test_app", + session_service=session_service, + plugins=[ + AdkAgentPlugin( + activity_options={"start_to_close_timeout": timedelta(minutes=2)} + ) + ], + ) + + last_event = None + async with Aclosing( + runner.run_async( + user_id="test", + session_id=session.id, + new_message=types.Content(role="user", parts=[types.Part(text=prompt)]), + ) + ) as agen: + async for event in agen: + logger.info(f"Event: {event}") + last_event = event + + return last_event + + +class McpModel(BaseLlm): + responses: list[LlmResponse] = [ + LlmResponse( + content=Content( + role="model", + parts=[ + Part( + function_call=FunctionCall( + args={"city": "New York"}, name="get_weather" + ) + ) + ], + ) + ), + LlmResponse( + content=Content( + role="model", + parts=[Part(text="warm and sunny")], + ) + ), + ] + response_iter: Iterator[LlmResponse] = iter(responses) + + @classmethod + def supported_models(cls) -> list[str]: + return ["weather_model"] + + async def generate_content_async( + self, llm_request: LlmRequest, stream: bool = False + ) -> AsyncGenerator[LlmResponse, None]: + yield next(self.response_iter) + + +@pytest.mark.parametrize("use_local_model", [True, False]) +@pytest.mark.asyncio +async def test_mcp_agent(client: Client, use_local_model: bool): + if not use_local_model and not os.environ.get("GOOGLE_API_KEY"): + pytest.skip("No google API key") + + new_config = client.config() + new_config["plugins"] = [ + TemporalAdkPlugin( + toolset_providers=[ + TemporalToolSetProvider( + "test_set", + lambda _: McpToolset( + connection_params=StdioConnectionParams( + server_params=StdioServerParameters( + command="npx", + args=[ + "-y", + "@modelcontextprotocol/server-filesystem", + os.path.dirname(os.path.abspath(__file__)), + ], + ), + ), + require_confirmation=True, + ), + ) + ] + ) + ] + client = Client(**new_config) + + # Run Worker with the ADK plugin + async with Worker( + client, + task_queue="adk-task-queue", + workflows=[McpAgent], + max_cached_workflows=0, + ): + if use_local_model: + LLMRegistry.register(ResearchModel) + + # Test Multi Agent + handle = await client.start_workflow( + McpAgent.run, + args=[ + "What files are in the current directory?", + "research_model" if use_local_model else "gemini-2.5-pro", + ], + id=f"mcp-agent-workflow-{uuid.uuid4()}", + task_queue="adk-task-queue", + ) + result = await handle.result() + print(f"MCP-Agent Workflow result: {result}") + if use_local_model: + assert result == "haiku" diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents_replay.py b/tests/contrib/google_adk_agents/test_google_adk_agents_replay.py index 810ca95f0..2c635d6ee 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents_replay.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents_replay.py @@ -4,7 +4,7 @@ from google.adk.models import LLMRegistry from temporalio.client import WorkflowHistory -from temporalio.contrib.google_adk_agents import GoogleAdkPlugin +from temporalio.contrib.google_adk_agents import TemporalAdkPlugin from temporalio.worker import Replayer from tests.contrib.google_adk_agents.test_google_adk_agents import ( MultiAgentWorkflow, @@ -29,5 +29,5 @@ async def test_replay(file_name: str) -> None: LLMRegistry.register(WeatherModel) await Replayer( workflows=[MultiAgentWorkflow, WeatherAgent], - plugins=[GoogleAdkPlugin()], + plugins=[TemporalAdkPlugin()], ).replay_workflow(WorkflowHistory.from_json("fake", history_json)) From 6dd1b7773889526d5bd194fe3a6db0941fb60c93 Mon Sep 17 00:00:00 2001 From: Tim Conley Date: Thu, 29 Jan 2026 10:05:04 -0800 Subject: [PATCH 6/6] Fix linting errors --- .../contrib/google_adk_agents/__init__.py | 8 +-- temporalio/contrib/google_adk_agents/_mcp.py | 56 +++++++++++++++---- .../contrib/google_adk_agents/_plugin.py | 41 +++++++++++--- .../test_google_adk_agents.py | 25 ++++----- 4 files changed, 95 insertions(+), 35 deletions(-) diff --git a/temporalio/contrib/google_adk_agents/__init__.py b/temporalio/contrib/google_adk_agents/__init__.py index 47e71da36..b56b4ba0c 100644 --- a/temporalio/contrib/google_adk_agents/__init__.py +++ b/temporalio/contrib/google_adk_agents/__init__.py @@ -4,8 +4,8 @@ """ from temporalio.contrib.google_adk_agents._mcp import ( - TemporalToolSet, - TemporalToolSetProvider, + TemporalMcpToolSet, + TemporalMcpToolSetProvider, ) from temporalio.contrib.google_adk_agents._plugin import ( AdkAgentPlugin, @@ -15,6 +15,6 @@ __all__ = [ "AdkAgentPlugin", "TemporalAdkPlugin", - "TemporalToolSet", - "TemporalToolSetProvider", + "TemporalMcpToolSet", + "TemporalMcpToolSetProvider", ] diff --git a/temporalio/contrib/google_adk_agents/_mcp.py b/temporalio/contrib/google_adk_agents/_mcp.py index 0a195072e..4dfb58725 100644 --- a/temporalio/contrib/google_adk_agents/_mcp.py +++ b/temporalio/contrib/google_adk_agents/_mcp.py @@ -5,10 +5,11 @@ from google.adk.agents.readonly_context import ReadonlyContext from google.adk.events import EventActions -from google.adk.tools import ToolContext from google.adk.tools.base_tool import BaseTool from google.adk.tools.base_toolset import BaseToolset +from google.adk.tools.mcp_tool import McpToolset from google.adk.tools.tool_confirmation import ToolConfirmation +from google.adk.tools.tool_context import ToolContext from google.genai import types from google.genai.types import FunctionDeclaration @@ -33,9 +34,13 @@ class _ToolResult: @dataclass class TemporalToolContext: + """Context for tools running within Temporal workflows. + + Provides access to tool confirmation and event actions for ADK integration. + """ tool_confirmation: ToolConfirmation | None function_call_id: str | None - event_actions: EventActions | None + event_actions: EventActions def request_confirmation( self, @@ -50,10 +55,10 @@ def request_confirmation( payload: The payload used to confirm the tool call. """ if not self.function_call_id: - raise ValueError('function_call_id is not set.') + raise ValueError("function_call_id is not set.") self.event_actions.requested_tool_confirmations[self.function_call_id] = ( ToolConfirmation( - hint=hint, + hint=hint or "", payload=payload, ) ) @@ -64,6 +69,7 @@ class _CallToolResult: result: Any tool_context: TemporalToolContext + @dataclass class _CallToolArguments: factory_argument: Any | None @@ -71,10 +77,20 @@ class _CallToolArguments: arguments: dict[str, Any] tool_context: TemporalToolContext -class TemporalToolSetProvider: - def __init__( - self, name: str, toolset_factory: Callable[[Any | None], BaseToolset] - ): + +class TemporalMcpToolSetProvider: + """Provider for creating Temporal-aware MCP toolsets. + + Manages the creation of toolset activities and handles tool execution + within Temporal workflows. + """ + def __init__(self, name: str, toolset_factory: Callable[[Any | None], McpToolset]): + """Initializes the toolset provider. + + Args: + name: Name prefix for the generated activities. + toolset_factory: Factory function that creates McpToolset instances. + """ super().__init__() self._name = name self._toolset_factory = toolset_factory @@ -117,7 +133,7 @@ async def call_tool( # We cannot provide a full-fledged ToolContext so we need to provide only what is needed by the tool result = await tool.run_async( args=args.arguments, - tool_context=args.tool_context, # type:ignore + tool_context=args.tool_context, # type:ignore ) return _CallToolResult(result=result, tool_context=args.tool_context) @@ -177,13 +193,25 @@ async def run_async( return result.result -class TemporalToolSet(BaseToolset): +class TemporalMcpToolSet(BaseToolset): + """Temporal-aware MCP toolset implementation. + + Executes MCP tools as Temporal activities, providing proper isolation + and execution guarantees within workflows. + """ def __init__( self, name: str, config: ActivityConfig | None = None, factory_argument: Any | None = None, ): + """Initializes the Temporal MCP toolset. + + Args: + name: Name of the toolset (used for activity naming). + config: Optional activity configuration. + factory_argument: Optional argument passed to toolset factory. + """ super().__init__() self._name = name self._factory_argument = factory_argument @@ -194,6 +222,14 @@ def __init__( async def get_tools( self, readonly_context: ReadonlyContext | None = None ) -> list[BaseTool]: + """Retrieves available tools from the MCP toolset. + + Args: + readonly_context: Optional readonly context (unused in this implementation). + + Returns: + List of available tools wrapped as Temporal activities. + """ tool_results: list[_ToolResult] = await workflow.execute_activity( self._name + "-list-tools", _GetToolsArguments(self._factory_argument), diff --git a/temporalio/contrib/google_adk_agents/_plugin.py b/temporalio/contrib/google_adk_agents/_plugin.py index 31ae29808..b43c418d5 100644 --- a/temporalio/contrib/google_adk_agents/_plugin.py +++ b/temporalio/contrib/google_adk_agents/_plugin.py @@ -4,8 +4,9 @@ import inspect import time import uuid +from collections.abc import AsyncIterator from contextlib import asynccontextmanager -from typing import Any, AsyncIterator, Callable, Optional +from typing import Any, Callable from google.adk.agents.callback_context import CallbackContext from google.adk.models import LLMRegistry @@ -14,7 +15,7 @@ from google.adk.plugins import BasePlugin from temporalio import activity, workflow -from temporalio.contrib.google_adk_agents._mcp import TemporalToolSetProvider +from temporalio.contrib.google_adk_agents._mcp import TemporalMcpToolSetProvider from temporalio.contrib.pydantic import ( PydanticPayloadConverter as _DefaultPydanticPayloadConverter, ) @@ -61,7 +62,7 @@ class AdkAgentPlugin(BasePlugin): inside a Temporal workflow, and intercepts model calls to execute them as Temporal Activities. """ - def __init__(self, activity_options: Optional[dict[str, Any]] = None): + def __init__(self, activity_options: dict[str, Any] | None = None): """Initializes the Temporal Plugin. Args: @@ -78,7 +79,7 @@ def activity_tool(activity_def: Callable, **kwargs: Any) -> Callable: while marking it as a tool that executes via 'workflow.execute_activity'. """ - async def wrapper(*args, **kw): + async def wrapper(*args: Any, **kw: Any): # Inspect signature to bind arguments sig = inspect.signature(activity_def) bound = sig.bind(*args, **kw) @@ -104,6 +105,15 @@ async def wrapper(*args, **kw): async def before_model_callback( self, *, callback_context: CallbackContext, llm_request: LlmRequest ) -> LlmResponse | None: + """Intercepts model calls to execute them as Temporal Activities. + + Args: + callback_context: The ADK callback context. + llm_request: The LLM request to process. + + Returns: + The last complete LLM response or None if no responses. + """ responses = await workflow.execute_activity( invoke_model, args=[llm_request], @@ -117,6 +127,17 @@ async def before_model_callback( @activity.defn async def invoke_model(llm_request: LlmRequest) -> list[LlmResponse]: + """Activity that invokes an LLM model. + + Args: + llm_request: The LLM request containing model name and parameters. + + Returns: + List of LLM responses from the model. + + Raises: + ValueError: If model name is not provided or LLM creation fails. + """ if llm_request.model is None: raise ValueError(f"No model name provided, could not create LLM.") @@ -138,7 +159,12 @@ class TemporalAdkPlugin(SimplePlugin): 2. Sandbox Passthrough for `google.adk` and `google.genai`. """ - def __init__(self, toolset_providers: list[TemporalToolSetProvider] = ()): + def __init__(self, toolset_providers: list[TemporalMcpToolSetProvider] | None = None): + """Initializes the Temporal ADK Plugin. + + Args: + toolset_providers: Optional list of toolset providers for MCP integration. + """ @asynccontextmanager async def run_context() -> AsyncIterator[None]: setup_deterministic_runtime() @@ -159,8 +185,9 @@ def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: return runner new_activities = [invoke_model] - for toolset_provider in toolset_providers: - new_activities.extend(toolset_provider._get_activities()) + if toolset_providers is not None: + for toolset_provider in toolset_providers: + new_activities.extend(toolset_provider._get_activities()) super().__init__( name="google_adk_plugin", diff --git a/tests/contrib/google_adk_agents/test_google_adk_agents.py b/tests/contrib/google_adk_agents/test_google_adk_agents.py index 9dbc49357..798a09626 100644 --- a/tests/contrib/google_adk_agents/test_google_adk_agents.py +++ b/tests/contrib/google_adk_agents/test_google_adk_agents.py @@ -17,9 +17,9 @@ import logging import os import uuid +from collections.abc import AsyncGenerator, Iterator from datetime import timedelta from pathlib import Path -from typing import AsyncGenerator, Iterator import pytest from google.adk import Agent, Runner @@ -41,8 +41,8 @@ from temporalio.contrib.google_adk_agents import ( AdkAgentPlugin, TemporalAdkPlugin, - TemporalToolSet, - TemporalToolSetProvider, + TemporalMcpToolSet, + TemporalMcpToolSetProvider, ) from temporalio.worker import Worker @@ -50,7 +50,7 @@ @activity.defn -async def get_weather(city: str) -> str: +async def get_weather(city: str) -> str: # type: ignore[reportUnusedParameter] """Activity that gets weather for a given city.""" return "Warm and sunny. 17 degrees." @@ -117,11 +117,6 @@ async def run(self, prompt: str, model_name: str) -> Event | None: class MultiAgentWorkflow: @workflow.run async def run(self, topic: str, model_name: str) -> str | None: - # Example of multi-turn/multi-agent orchestration - # This is where Temporal shines - orchestrating complex agent flows - - # 0. Deterministic Runtime is now auto-configured by AdkInterceptor! - # 1. Setup Session Service session_service = InMemorySessionService() session = await session_service.create_session( @@ -164,8 +159,6 @@ async def run(self, topic: str, model_name: str) -> str | None: ) # 4. Run - # Note: In a real temporal app, we might signal the workflow or use queries. - # Here we just run a single turn for the test. final_content = "" user_msg = types.Content( role="user", @@ -178,7 +171,11 @@ async def run(self, topic: str, model_name: str) -> str | None: async for event in runner.run_async( user_id="test_user", session_id=session.id, new_message=user_msg ): - if event.content and event.content.parts: + if ( + event.content + and event.content.parts + and event.content.parts[0].text is not None + ): final_content = event.content.parts[0].text return final_content @@ -358,7 +355,7 @@ async def run(self, prompt: str, model_name: str) -> Event | None: name="test_agent", # instruction="Always use your tools to answer questions.", model=model_name, - tools=[TemporalToolSet("test_set")], + tools=[TemporalMcpToolSet("test_set")], ) # 2. Create Session (uses runtime.new_uuid() -> workflow.uuid4()) @@ -440,7 +437,7 @@ async def test_mcp_agent(client: Client, use_local_model: bool): new_config["plugins"] = [ TemporalAdkPlugin( toolset_providers=[ - TemporalToolSetProvider( + TemporalMcpToolSetProvider( "test_set", lambda _: McpToolset( connection_params=StdioConnectionParams(