diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 403c731de..6a63fd29c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,5 +1,4 @@ * @temporalio/sdk -/langgraph_plugin/ @temporalio/sdk @temporalio/ai-sdk # SDK & Nexus own the README, pyproject.toml, and uv.lock /README.md @temporalio/sdk @temporalio/nexus @@ -16,11 +15,13 @@ # The AI SDK team owns the AI integration samples and their tests. We add # @temporalio/sdk too, so the SDK team can continue to manage repo-wide concerns. /google_adk_agents/ @temporalio/sdk @temporalio/ai-sdk +/google_genai/ @temporalio/sdk @temporalio/ai-sdk /langgraph_plugin/ @temporalio/sdk @temporalio/ai-sdk /langsmith_tracing/ @temporalio/sdk @temporalio/ai-sdk /openai_agents/ @temporalio/sdk @temporalio/ai-sdk /strands_plugin/ @temporalio/sdk @temporalio/ai-sdk /tests/google_adk_agents/ @temporalio/sdk @temporalio/ai-sdk +/tests/google_genai/ @temporalio/sdk @temporalio/ai-sdk /tests/langgraph_plugin/ @temporalio/sdk @temporalio/ai-sdk /tests/langsmith_tracing/ @temporalio/sdk @temporalio/ai-sdk /tests/strands_plugin/ @temporalio/sdk @temporalio/ai-sdk diff --git a/README.md b/README.md index d39428dc7..f62df8c60 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ Some examples require extra dependencies. See each sample's directory for specif * [external_storage_redis](external_storage_redis) - Redis driver for external storage * [gevent_async](gevent_async) - Combine gevent and Temporal. * [google_adk_agents](google_adk_agents) - Run Google ADK agents as durable Temporal workflows (model calls, tools, multi-agent, MCP, streaming). +* [google_genai](google_genai) - Run the Google Gemini SDK inside durable Temporal workflows (generate_content, tools/AFC, streaming, chat, structured output, MCP, files, interactions, agents, Vertex AI). * [hello_nexus](hello_nexus) - Define a Nexus service, implement operation handlers, and call them from a workflow. * [hello_standalone_nexus](hello_standalone_nexus) - Use Nexus Operations without using a workflow. * [hello_standalone_activity](hello_standalone_activity) - Use activities without using a workflow. diff --git a/google_genai/README.md b/google_genai/README.md new file mode 100644 index 000000000..4b49b0e96 --- /dev/null +++ b/google_genai/README.md @@ -0,0 +1,76 @@ +# Google GenAI Samples + +These samples demonstrate the [Temporal Google GenAI plugin](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/google_genai), which runs the [Google Gemini SDK](https://googleapis.github.io/python-genai/) inside Temporal Workflows. Workflows construct a `TemporalAsyncClient`, and every Gemini API call — `generate_content`, tool calls, streaming, files, interactions, agents — runs as a Temporal Activity. You get durable execution, Temporal-managed retries and timeouts, and your credentials never enter the workflow or its event history. + +## Samples + +| Sample | Description | +|--------|-------------| +| [hello_world](hello_world) | Minimal `generate_content` call. Start here. | +| [tools](tools) | Automatic function calling: an `activity_as_tool`-wrapped activity and a plain workflow-method tool on one call. | +| [streaming](streaming) | Forward `generate_content_stream` chunks to an external subscriber via `streaming_topic` + `WorkflowStream`. | +| [chat](chat) | Multi-turn conversation with `client.chats`. | +| [structured_output](structured_output) | Typed JSON output via `response_schema` and a Pydantic model. | +| [mcp](mcp) | Give Gemini an MCP server's tools via `TemporalMcpClientSession`. | +| [files](files) | Upload a file with `client.files` and reference it in a call. *(needs a live API key)* | +| [interactions](interactions) | Stateful server-side conversations via `client.interactions`. *(needs a live API key)* | +| [agents](agents) | Managed-agent CRUD via `client.agents`. *(needs a live API key)* | +| [vertex_ai](vertex_ai) | The hello-world flow against Vertex AI (`vertexai=True`). *(needs GCP credentials)* | + +## Prerequisites + +1. Install dependencies: + + ```bash + uv sync --group google-genai + ``` + +2. Configure credentials. Most samples use the Gemini Developer API and read an API key from the environment: + + ```bash + export GOOGLE_API_KEY=... + ``` + + The [vertex_ai](vertex_ai) sample instead uses Vertex AI with Google Cloud Application Default Credentials — see its README. You can authenticate with `gcloud auth application-default login` and set `GOOGLE_CLOUD_PROJECT` (and optionally `GOOGLE_CLOUD_LOCATION`). + +3. Start a [Temporal dev server](https://docs.temporal.io/cli#start-dev-server): + + ```bash + temporal server start-dev + ``` + +## Running a Sample + +Each sample has two scripts. Start the Worker first, then the Workflow starter in a separate terminal: + +```bash +# Terminal 1: start the Worker +uv run google_genai//run_worker.py + +# Terminal 2: start the Workflow +uv run google_genai//run_workflow.py +``` + +For example, to run the tools sample: + +```bash +# Terminal 1 +uv run google_genai/tools/run_worker.py + +# Terminal 2 +uv run google_genai/tools/run_workflow.py +``` + +## Key Features Demonstrated + +- **Durable API calls** — every Gemini call runs as an activity with configurable timeouts and retries; no credentials enter workflow history. +- **Automatic function calling** — the SDK's AFC loop runs in-workflow; tools can be durable activities (`activity_as_tool`) or plain workflow methods. +- **Streaming** — forward model chunks live to external subscribers via `WorkflowStream`. +- **Structured output** — Pydantic-typed results through the plugin's Pydantic data converter. +- **MCP integration** — register MCP servers on the worker; tool calls dispatched through per-server activities. +- **Full API surface** — chat, the Files API, the Interactions API, managed agents, and Vertex AI. + +## Related + +- [Temporal Google GenAI plugin docs](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/google_genai) +- [Google Gemini SDK (`google-genai`)](https://googleapis.github.io/python-genai/) diff --git a/google_genai/__init__.py b/google_genai/__init__.py new file mode 100644 index 000000000..4cd479869 --- /dev/null +++ b/google_genai/__init__.py @@ -0,0 +1 @@ +"""Temporal Google GenAI plugin samples.""" diff --git a/google_genai/agents/README.md b/google_genai/agents/README.md new file mode 100644 index 000000000..2ef7ebe5d --- /dev/null +++ b/google_genai/agents/README.md @@ -0,0 +1,35 @@ +# Managed Agents + +Managed agents (`client.agents`) are server-side resources you can create, fetch, +list, and delete. This sample runs the full CRUD cycle, each operation as a +Temporal activity. + +> **Requires a live Gemini API key.** The Agents API talks to a real backend that +> the plugin's test server does not mock, so this sample has no automated test — +> run it against a real `GOOGLE_API_KEY`. + +## What This Sample Demonstrates + +- `client.agents.create(id=..., system_instruction=...)` +- `client.agents.get(id)`, `client.agents.list(page_size=...)`, `client.agents.delete(id)` + +## Running the Sample + +Prerequisites: install dependencies, set `GOOGLE_API_KEY`, and start a Temporal +dev server. See the [suite README](../README.md). + +```bash +# Terminal 1 +uv run google_genai/agents/run_worker.py + +# Terminal 2 +uv run google_genai/agents/run_workflow.py +``` + +## Files + +| File | Description | +|------|-------------| +| `workflow.py` | `AgentsWorkflow` — create, get, list, delete a managed agent | +| `run_worker.py` | Registers `GoogleGenAIPlugin`, starts the worker | +| `run_workflow.py` | Executes the workflow and prints the result | diff --git a/google_genai/agents/__init__.py b/google_genai/agents/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/google_genai/agents/run_worker.py b/google_genai/agents/run_worker.py new file mode 100644 index 000000000..1bd294ba1 --- /dev/null +++ b/google_genai/agents/run_worker.py @@ -0,0 +1,35 @@ +"""Worker for the agents sample.""" + +# @@@SNIPSTART python-google-genai-agents-worker +import asyncio +import os + +from google import genai +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.worker import Worker + +from google_genai.agents.workflow import AgentsWorkflow + + +async def main() -> None: + genai_client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(genai_client) + + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + plugins=[plugin], + ) + + worker = Worker( + client, + task_queue="google-genai-agents", + workflows=[AgentsWorkflow], + ) + print("Worker started. Ctrl+C to exit.") + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/agents/run_workflow.py b/google_genai/agents/run_workflow.py new file mode 100644 index 000000000..63307b9c1 --- /dev/null +++ b/google_genai/agents/run_workflow.py @@ -0,0 +1,27 @@ +"""Start the agents workflow.""" + +# @@@SNIPSTART python-google-genai-agents-run-workflow +import asyncio +import os + +from temporalio.client import Client + +from google_genai.agents.workflow import AgentsWorkflow + + +async def main() -> None: + client = await Client.connect(os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")) + + result = await client.execute_workflow( + AgentsWorkflow.run, + "samples-demo-agent", + id="google-genai-agents", + task_queue="google-genai-agents", + ) + + print(f"Result: {result}") + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/agents/workflow.py b/google_genai/agents/workflow.py new file mode 100644 index 000000000..0210fa95e --- /dev/null +++ b/google_genai/agents/workflow.py @@ -0,0 +1,35 @@ +"""Managed agents CRUD via client.agents. + +Managed agents are server-side resources you create, fetch, list, and delete. +Each operation runs as a Temporal activity. +""" + +# @@@SNIPSTART python-google-genai-agents-workflow +from typing import Any + +from temporalio import workflow +from temporalio.contrib.google_genai import TemporalAsyncClient + + +@workflow.defn +class AgentsWorkflow: + @workflow.run + async def run(self, agent_id: str) -> dict[str, Any]: + client = TemporalAsyncClient() + + created = await client.agents.create( + id=agent_id, + system_instruction="You are a helpful assistant.", + ) + fetched = await client.agents.get(agent_id) + listing = await client.agents.list(page_size=10) + await client.agents.delete(agent_id) + + return { + "created_id": created.id, + "fetched_id": fetched.id, + "listed_ids": [a.id for a in (listing.agents or [])], + } + + +# @@@SNIPEND diff --git a/google_genai/chat/README.md b/google_genai/chat/README.md new file mode 100644 index 000000000..2275f51e4 --- /dev/null +++ b/google_genai/chat/README.md @@ -0,0 +1,31 @@ +# Chat + +A multi-turn conversation using `client.chats`. The chat session carries history +across turns, and each `send_message` call runs as a durable Temporal activity. + +## What This Sample Demonstrates + +- Creating a chat session with `client.chats.create(...)` +- Sending multiple turns with `await chat.send_message(...)` +- Conversation state persisting across durable activity calls + +## Running the Sample + +Prerequisites: install dependencies, set `GOOGLE_API_KEY`, and start a Temporal +dev server. See the [suite README](../README.md). + +```bash +# Terminal 1 +uv run google_genai/chat/run_worker.py + +# Terminal 2 +uv run google_genai/chat/run_workflow.py +``` + +## Files + +| File | Description | +|------|-------------| +| `workflow.py` | `ChatWorkflow` — sends a list of prompts over one chat session | +| `run_worker.py` | Registers `GoogleGenAIPlugin`, starts the worker | +| `run_workflow.py` | Executes the workflow and prints each turn's reply | diff --git a/google_genai/chat/__init__.py b/google_genai/chat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/google_genai/chat/run_worker.py b/google_genai/chat/run_worker.py new file mode 100644 index 000000000..3bd56f679 --- /dev/null +++ b/google_genai/chat/run_worker.py @@ -0,0 +1,35 @@ +"""Worker for the chat sample.""" + +# @@@SNIPSTART python-google-genai-chat-worker +import asyncio +import os + +from google import genai +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.worker import Worker + +from google_genai.chat.workflow import ChatWorkflow + + +async def main() -> None: + genai_client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(genai_client) + + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + plugins=[plugin], + ) + + worker = Worker( + client, + task_queue="google-genai-chat", + workflows=[ChatWorkflow], + ) + print("Worker started. Ctrl+C to exit.") + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/chat/run_workflow.py b/google_genai/chat/run_workflow.py new file mode 100644 index 000000000..15ac4281a --- /dev/null +++ b/google_genai/chat/run_workflow.py @@ -0,0 +1,31 @@ +"""Start the chat workflow with a multi-turn conversation.""" + +# @@@SNIPSTART python-google-genai-chat-run-workflow +import asyncio +import os + +from temporalio.client import Client + +from google_genai.chat.workflow import ChatWorkflow + + +async def main() -> None: + client = await Client.connect(os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")) + + result = await client.execute_workflow( + ChatWorkflow.run, + [ + "My favorite color is teal. Remember that.", + "What is my favorite color?", + ], + id="google-genai-chat", + task_queue="google-genai-chat", + ) + + for turn, reply in enumerate(result, start=1): + print(f"Turn {turn}: {reply}") + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/chat/workflow.py b/google_genai/chat/workflow.py new file mode 100644 index 000000000..666d4c8a3 --- /dev/null +++ b/google_genai/chat/workflow.py @@ -0,0 +1,26 @@ +"""Multi-turn chat using client.chats. + +A chat session keeps conversation history across turns. Each ``send_message`` +call runs as a durable Temporal activity, and the SDK threads prior turns into +each request automatically. +""" + +# @@@SNIPSTART python-google-genai-chat-workflow +from temporalio import workflow +from temporalio.contrib.google_genai import TemporalAsyncClient + + +@workflow.defn +class ChatWorkflow: + @workflow.run + async def run(self, prompts: list[str]) -> list[str]: + client = TemporalAsyncClient() + chat = client.chats.create(model="gemini-2.5-flash") + replies: list[str] = [] + for prompt in prompts: + response = await chat.send_message(prompt) + replies.append(response.text or "") + return replies + + +# @@@SNIPEND diff --git a/google_genai/files/README.md b/google_genai/files/README.md new file mode 100644 index 000000000..64cffeae3 --- /dev/null +++ b/google_genai/files/README.md @@ -0,0 +1,38 @@ +# Files + +Upload a file with the Gemini Files API, then ask the model about it. +`client.files.upload` runs as a Temporal activity on the worker (the file is +read there), and the returned file handle is referenced in a `generate_content` +call. + +> **Requires a live Gemini API key.** The Files API talks to a real backend that +> the plugin's test server does not mock, so this sample has no automated test — +> run it against a real `GOOGLE_API_KEY`. The file path is resolved on the +> worker, so `sample.txt` must be reachable by the worker process. + +## What This Sample Demonstrates + +- `client.files.upload(file=..., config=UploadFileConfig(...))` as a durable activity +- Referencing the uploaded file handle in `generate_content` `contents` + +## Running the Sample + +Prerequisites: install dependencies, set `GOOGLE_API_KEY`, and start a Temporal +dev server. See the [suite README](../README.md). + +```bash +# Terminal 1 +uv run google_genai/files/run_worker.py + +# Terminal 2 +uv run google_genai/files/run_workflow.py +``` + +## Files + +| File | Description | +|------|-------------| +| `sample.txt` | The document uploaded and summarized | +| `workflow.py` | `FilesWorkflow` — uploads a file, then summarizes it | +| `run_worker.py` | Registers `GoogleGenAIPlugin`, starts the worker | +| `run_workflow.py` | Executes the workflow with the sample file path | diff --git a/google_genai/files/__init__.py b/google_genai/files/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/google_genai/files/run_worker.py b/google_genai/files/run_worker.py new file mode 100644 index 000000000..5e843ed4b --- /dev/null +++ b/google_genai/files/run_worker.py @@ -0,0 +1,35 @@ +"""Worker for the files sample.""" + +# @@@SNIPSTART python-google-genai-files-worker +import asyncio +import os + +from google import genai +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.worker import Worker + +from google_genai.files.workflow import FilesWorkflow + + +async def main() -> None: + genai_client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(genai_client) + + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + plugins=[plugin], + ) + + worker = Worker( + client, + task_queue="google-genai-files", + workflows=[FilesWorkflow], + ) + print("Worker started. Ctrl+C to exit.") + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/files/run_workflow.py b/google_genai/files/run_workflow.py new file mode 100644 index 000000000..c66129964 --- /dev/null +++ b/google_genai/files/run_workflow.py @@ -0,0 +1,34 @@ +"""Start the files workflow. + +The file is read on the worker, so ``sample.txt`` must be on a path the worker +process can access (here it ships alongside this sample). +""" + +# @@@SNIPSTART python-google-genai-files-run-workflow +import asyncio +import os +from pathlib import Path + +from temporalio.client import Client + +from google_genai.files.workflow import FilesWorkflow + +SAMPLE_FILE = str(Path(__file__).parent / "sample.txt") + + +async def main() -> None: + client = await Client.connect(os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")) + + result = await client.execute_workflow( + FilesWorkflow.run, + args=[SAMPLE_FILE, "Summarize this document in one sentence."], + id="google-genai-files", + task_queue="google-genai-files", + ) + + print(f"Result: {result}") + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/files/sample.txt b/google_genai/files/sample.txt new file mode 100644 index 000000000..d192614a1 --- /dev/null +++ b/google_genai/files/sample.txt @@ -0,0 +1,6 @@ +Temporal is a durable execution platform. Workflows written with the Temporal +SDK run as ordinary code, but their state is persisted by the Temporal service, +so they survive process crashes, machine restarts, and deploys. Activities +encapsulate side effects like network calls; Temporal handles their retries and +timeouts. The Google GenAI plugin builds on this by running every Gemini API +call as a durable activity. diff --git a/google_genai/files/workflow.py b/google_genai/files/workflow.py new file mode 100644 index 000000000..098a91115 --- /dev/null +++ b/google_genai/files/workflow.py @@ -0,0 +1,33 @@ +"""Upload a file with the Files API, then ask Gemini about it. + +``client.files.upload`` runs as an activity on the worker — the file is read +there, not in the workflow — and the returned file handle is then referenced in +a ``generate_content`` call. +""" + +# @@@SNIPSTART python-google-genai-files-workflow +from typing import cast + +from google.genai import types +from temporalio import workflow +from temporalio.contrib.google_genai import TemporalAsyncClient + + +@workflow.defn +class FilesWorkflow: + @workflow.run + async def run(self, file_path: str, prompt: str) -> str: + client = TemporalAsyncClient() + uploaded = await client.files.upload( + file=file_path, + config=types.UploadFileConfig(mime_type="text/plain"), + ) + contents = cast(types.ContentListUnion, [prompt, uploaded]) + response = await client.models.generate_content( + model="gemini-2.5-flash", + contents=contents, + ) + return response.text or "" + + +# @@@SNIPEND diff --git a/google_genai/hello_world/README.md b/google_genai/hello_world/README.md new file mode 100644 index 000000000..5f6dd8b66 --- /dev/null +++ b/google_genai/hello_world/README.md @@ -0,0 +1,33 @@ +# Hello World + +The simplest Google GenAI + Temporal sample: one `generate_content` call. The +call runs as a Temporal activity, so it gets durable retries, timeouts, and +crash recovery, and the Gemini credentials never enter the workflow. + +## What This Sample Demonstrates + +- Wiring `GoogleGenAIPlugin` onto the worker with a real `genai.Client` +- Constructing a `TemporalAsyncClient` inside a `@workflow.defn` +- Calling `client.models.generate_content(...)` durably + +## Running the Sample + +Prerequisites: install dependencies, set `GOOGLE_API_KEY`, and start a Temporal +dev server (`temporal server start-dev`). See the +[suite README](../README.md) for details. + +```bash +# Terminal 1 +uv run google_genai/hello_world/run_worker.py + +# Terminal 2 +uv run google_genai/hello_world/run_workflow.py +``` + +## Files + +| File | Description | +|------|-------------| +| `workflow.py` | `HelloWorldWorkflow` with a single `generate_content` call | +| `run_worker.py` | Registers `GoogleGenAIPlugin`, starts the worker | +| `run_workflow.py` | Executes the workflow and prints the result | diff --git a/google_genai/hello_world/__init__.py b/google_genai/hello_world/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/google_genai/hello_world/run_worker.py b/google_genai/hello_world/run_worker.py new file mode 100644 index 000000000..422a1b541 --- /dev/null +++ b/google_genai/hello_world/run_worker.py @@ -0,0 +1,36 @@ +"""Worker for the hello world sample.""" + +# @@@SNIPSTART python-google-genai-hello-world-worker +import asyncio +import os + +from google import genai +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.worker import Worker + +from google_genai.hello_world.workflow import HelloWorldWorkflow + + +async def main() -> None: + # The real genai.Client (with credentials) lives only on the worker. + genai_client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(genai_client) + + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + plugins=[plugin], + ) + + worker = Worker( + client, + task_queue="google-genai-hello-world", + workflows=[HelloWorldWorkflow], + ) + print("Worker started. Ctrl+C to exit.") + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/hello_world/run_workflow.py b/google_genai/hello_world/run_workflow.py new file mode 100644 index 000000000..89d93e45b --- /dev/null +++ b/google_genai/hello_world/run_workflow.py @@ -0,0 +1,27 @@ +"""Start the hello world workflow.""" + +# @@@SNIPSTART python-google-genai-hello-world-run-workflow +import asyncio +import os + +from temporalio.client import Client + +from google_genai.hello_world.workflow import HelloWorldWorkflow + + +async def main() -> None: + client = await Client.connect(os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")) + + result = await client.execute_workflow( + HelloWorldWorkflow.run, + "Write a haiku about durable execution.", + id="google-genai-hello-world", + task_queue="google-genai-hello-world", + ) + + print(f"Result: {result}") + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/hello_world/workflow.py b/google_genai/hello_world/workflow.py new file mode 100644 index 000000000..d962e91a9 --- /dev/null +++ b/google_genai/hello_world/workflow.py @@ -0,0 +1,25 @@ +"""Minimal Temporal + Google GenAI workflow: one prompt, one response. + +Every Gemini API call made through ``TemporalAsyncClient`` runs as a durable +Temporal activity, so it gets retries, timeouts, and crash recovery for free — +and no credentials ever enter the workflow. +""" + +# @@@SNIPSTART python-google-genai-hello-world-workflow +from temporalio import workflow +from temporalio.contrib.google_genai import TemporalAsyncClient + + +@workflow.defn +class HelloWorldWorkflow: + @workflow.run + async def run(self, prompt: str) -> str: + client = TemporalAsyncClient() + response = await client.models.generate_content( + model="gemini-2.5-flash", + contents=prompt, + ) + return response.text or "" + + +# @@@SNIPEND diff --git a/google_genai/interactions/README.md b/google_genai/interactions/README.md new file mode 100644 index 000000000..34d28b024 --- /dev/null +++ b/google_genai/interactions/README.md @@ -0,0 +1,40 @@ +# Interactions + +The Interactions API (`client.interactions`) is a server-managed, stateful +conversation API: state lives on Google's backend, addressed by an interaction +id. This sample creates an interaction, fetches it, and deletes it — each +operation running as a Temporal activity. + +> **Requires a live Gemini API key.** The Interactions API talks to a real +> backend that the plugin's test server does not mock, so this sample has no +> automated test — run it against a real `GOOGLE_API_KEY`. + +Note: unlike `client.models`, the Interactions API has no automatic function +calling. To use tools, declare them as `{"type": "function", ...}` dicts and +drive the tool loop yourself. + +## What This Sample Demonstrates + +- `client.interactions.create(model=..., input=...)` as a durable activity +- `client.interactions.get(id)` and `client.interactions.delete(id)` + +## Running the Sample + +Prerequisites: install dependencies, set `GOOGLE_API_KEY`, and start a Temporal +dev server. See the [suite README](../README.md). + +```bash +# Terminal 1 +uv run google_genai/interactions/run_worker.py + +# Terminal 2 +uv run google_genai/interactions/run_workflow.py +``` + +## Files + +| File | Description | +|------|-------------| +| `workflow.py` | `InteractionsWorkflow` — create, get, delete an interaction | +| `run_worker.py` | Registers `GoogleGenAIPlugin`, starts the worker | +| `run_workflow.py` | Executes the workflow and prints the result | diff --git a/google_genai/interactions/__init__.py b/google_genai/interactions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/google_genai/interactions/run_worker.py b/google_genai/interactions/run_worker.py new file mode 100644 index 000000000..36539f29f --- /dev/null +++ b/google_genai/interactions/run_worker.py @@ -0,0 +1,35 @@ +"""Worker for the interactions sample.""" + +# @@@SNIPSTART python-google-genai-interactions-worker +import asyncio +import os + +from google import genai +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.worker import Worker + +from google_genai.interactions.workflow import InteractionsWorkflow + + +async def main() -> None: + genai_client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(genai_client) + + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + plugins=[plugin], + ) + + worker = Worker( + client, + task_queue="google-genai-interactions", + workflows=[InteractionsWorkflow], + ) + print("Worker started. Ctrl+C to exit.") + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/interactions/run_workflow.py b/google_genai/interactions/run_workflow.py new file mode 100644 index 000000000..b0413fe3d --- /dev/null +++ b/google_genai/interactions/run_workflow.py @@ -0,0 +1,27 @@ +"""Start the interactions workflow.""" + +# @@@SNIPSTART python-google-genai-interactions-run-workflow +import asyncio +import os + +from temporalio.client import Client + +from google_genai.interactions.workflow import InteractionsWorkflow + + +async def main() -> None: + client = await Client.connect(os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")) + + result = await client.execute_workflow( + InteractionsWorkflow.run, + "What is durable execution?", + id="google-genai-interactions", + task_queue="google-genai-interactions", + ) + + print(f"Result: {result}") + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/interactions/workflow.py b/google_genai/interactions/workflow.py new file mode 100644 index 000000000..f3ef33792 --- /dev/null +++ b/google_genai/interactions/workflow.py @@ -0,0 +1,34 @@ +"""Stateful server-side conversations via the Interactions API. + +``client.interactions`` is a server-managed API: the conversation state lives on +Google's backend, addressed by an interaction id. Each operation — create, get, +delete — runs as a Temporal activity. Unlike ``client.models``, this API has no +automatic function calling. +""" + +# @@@SNIPSTART python-google-genai-interactions-workflow +from typing import Any + +from temporalio import workflow +from temporalio.contrib.google_genai import TemporalAsyncClient + + +@workflow.defn +class InteractionsWorkflow: + @workflow.run + async def run(self, prompt: str) -> dict[str, Any]: + client = TemporalAsyncClient() + + # create/get return either an Interaction or a streaming response; without + # stream=True the result is always an Interaction. + interaction: Any = await client.interactions.create( + model="gemini-2.5-flash", + input=prompt, + ) + fetched: Any = await client.interactions.get(interaction.id) + await client.interactions.delete(interaction.id) + + return {"id": interaction.id, "status": str(fetched.status)} + + +# @@@SNIPEND diff --git a/google_genai/mcp/README.md b/google_genai/mcp/README.md new file mode 100644 index 000000000..da4a10b55 --- /dev/null +++ b/google_genai/mcp/README.md @@ -0,0 +1,37 @@ +# MCP + +Give Gemini access to an [MCP](https://modelcontextprotocol.io/) server's tools. +The worker launches the `echo_mcp_server.py` stdio server and registers it with +the plugin under the name `echo`. Inside the workflow, a +`TemporalMcpClientSession("echo")` is passed as a tool — Gemini's AFC loop +discovers and calls its tools, and `list_tools` / `call_tool` run as Temporal +activities against a pooled worker-side connection. + +## What This Sample Demonstrates + +- Registering an MCP server with `GoogleGenAIPlugin(mcp_servers={...})` +- Passing `TemporalMcpClientSession(name)` as a `generate_content` tool +- `cache_tools=True` to discover the tool list once and reuse it (replay-safe) +- MCP tool calls dispatched through per-server Temporal activities + +## Running the Sample + +Prerequisites: install dependencies, set `GOOGLE_API_KEY`, and start a Temporal +dev server. See the [suite README](../README.md). + +```bash +# Terminal 1 +uv run google_genai/mcp/run_worker.py + +# Terminal 2 +uv run google_genai/mcp/run_workflow.py +``` + +## Files + +| File | Description | +|------|-------------| +| `echo_mcp_server.py` | A minimal `FastMCP` stdio server exposing an `echo` tool | +| `workflow.py` | `McpWorkflow` — passes `TemporalMcpClientSession("echo")` as a tool | +| `run_worker.py` | Registers the `echo` MCP server with the plugin, starts the worker | +| `run_workflow.py` | Executes the workflow and prints the result | diff --git a/google_genai/mcp/__init__.py b/google_genai/mcp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/google_genai/mcp/echo_mcp_server.py b/google_genai/mcp/echo_mcp_server.py new file mode 100644 index 000000000..d75f82cd7 --- /dev/null +++ b/google_genai/mcp/echo_mcp_server.py @@ -0,0 +1,15 @@ +"""A minimal stdio MCP server used by the MCP sample.""" + +from mcp.server.fastmcp import FastMCP + +mcp = FastMCP("echo-server") + + +@mcp.tool() +def echo(message: str) -> str: + """Return the input message unchanged.""" + return message + + +if __name__ == "__main__": + mcp.run() diff --git a/google_genai/mcp/run_worker.py b/google_genai/mcp/run_worker.py new file mode 100644 index 000000000..5098c0e8e --- /dev/null +++ b/google_genai/mcp/run_worker.py @@ -0,0 +1,58 @@ +"""Worker for the MCP sample. + +Registers an ``echo`` MCP server (the ``echo_mcp_server.py`` stdio script) with +the plugin. The plugin opens a pooled MCP connection on the worker and runs +``list_tools`` / ``call_tool`` as activities. +""" + +# @@@SNIPSTART python-google-genai-mcp-worker +import asyncio +import os +import sys +from collections.abc import AsyncIterator +from contextlib import asynccontextmanager +from pathlib import Path + +from google import genai +from mcp import ClientSession, StdioServerParameters +from mcp.client.stdio import stdio_client +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.worker import Worker + +from google_genai.mcp.workflow import McpWorkflow + +ECHO_SERVER = str(Path(__file__).parent / "echo_mcp_server.py") + + +@asynccontextmanager +async def echo_session() -> AsyncIterator[ClientSession]: + """Yield a connected, initialized session to the stdio echo MCP server.""" + params = StdioServerParameters(command=sys.executable, args=[ECHO_SERVER]) + async with stdio_client(params) as (read, write): + async with ClientSession(read, write) as session: + await session.initialize() + yield session + + +async def main() -> None: + genai_client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(genai_client, mcp_servers={"echo": echo_session}) + + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + plugins=[plugin], + ) + + worker = Worker( + client, + task_queue="google-genai-mcp", + workflows=[McpWorkflow], + ) + print("Worker started. Ctrl+C to exit.") + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/mcp/run_workflow.py b/google_genai/mcp/run_workflow.py new file mode 100644 index 000000000..b817c77ea --- /dev/null +++ b/google_genai/mcp/run_workflow.py @@ -0,0 +1,27 @@ +"""Start the MCP workflow.""" + +# @@@SNIPSTART python-google-genai-mcp-run-workflow +import asyncio +import os + +from temporalio.client import Client + +from google_genai.mcp.workflow import McpWorkflow + + +async def main() -> None: + client = await Client.connect(os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")) + + result = await client.execute_workflow( + McpWorkflow.run, + "Use the echo tool to echo back the phrase: durable execution.", + id="google-genai-mcp", + task_queue="google-genai-mcp", + ) + + print(f"Result: {result}") + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/mcp/workflow.py b/google_genai/mcp/workflow.py new file mode 100644 index 000000000..7cd5e5d2b --- /dev/null +++ b/google_genai/mcp/workflow.py @@ -0,0 +1,41 @@ +"""Use an MCP server's tools from a Gemini call via TemporalMcpClientSession. + +The worker registers an ``echo`` MCP server with the plugin. Inside the +workflow, ``TemporalMcpClientSession("echo")`` is passed as a tool; Gemini's AFC +loop discovers and calls the MCP tools, with ``list_tools`` / ``call_tool`` +running as Temporal activities against a pooled worker-side connection. +""" + +# @@@SNIPSTART python-google-genai-mcp-workflow +from datetime import timedelta + +from google.genai import types +from temporalio import workflow +from temporalio.contrib.google_genai import ( + TemporalAsyncClient, + TemporalMcpClientSession, +) +from temporalio.workflow import ActivityConfig + + +@workflow.defn +class McpWorkflow: + @workflow.run + async def run(self, prompt: str) -> str: + client = TemporalAsyncClient() + session = TemporalMcpClientSession( + "echo", + cache_tools=True, + activity_config=ActivityConfig( + start_to_close_timeout=timedelta(seconds=30), + ), + ) + response = await client.models.generate_content( + model="gemini-2.5-flash", + contents=prompt, + config=types.GenerateContentConfig(tools=[session]), + ) + return response.text or "" + + +# @@@SNIPEND diff --git a/google_genai/streaming/README.md b/google_genai/streaming/README.md new file mode 100644 index 000000000..ba8a5bd7c --- /dev/null +++ b/google_genai/streaming/README.md @@ -0,0 +1,35 @@ +# Streaming + +Forward Gemini model output to an external subscriber in real time. +`TemporalAsyncClient(streaming_topic="gemini")` publishes each +`generate_content_stream` chunk onto a workflow-hosted `WorkflowStream` as it +arrives. A subscriber connects with `WorkflowStreamClient` and reads the topic +live while the workflow runs durably. + +## What This Sample Demonstrates + +- `TemporalAsyncClient(streaming_topic=...)` publishing chunks to a topic +- Hosting a `WorkflowStream` in `@workflow.init` (required for streaming) +- Consuming the stream externally via `WorkflowStreamClient.subscribe(...)` +- Holding the workflow open on a signal so the subscriber can drain the stream + +## Running the Sample + +Prerequisites: install dependencies, set `GOOGLE_API_KEY`, and start a Temporal +dev server. See the [suite README](../README.md). + +```bash +# Terminal 1 +uv run google_genai/streaming/run_worker.py + +# Terminal 2 +uv run google_genai/streaming/run_workflow.py +``` + +## Files + +| File | Description | +|------|-------------| +| `workflow.py` | `StreamingWorkflow` — streams chunks to the `gemini` topic | +| `run_worker.py` | Registers `GoogleGenAIPlugin`, starts the worker | +| `run_workflow.py` | Starts the workflow and consumes the stream live | diff --git a/google_genai/streaming/__init__.py b/google_genai/streaming/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/google_genai/streaming/run_worker.py b/google_genai/streaming/run_worker.py new file mode 100644 index 000000000..399242c14 --- /dev/null +++ b/google_genai/streaming/run_worker.py @@ -0,0 +1,35 @@ +"""Worker for the streaming sample.""" + +# @@@SNIPSTART python-google-genai-streaming-worker +import asyncio +import os + +from google import genai +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.worker import Worker + +from google_genai.streaming.workflow import StreamingWorkflow + + +async def main() -> None: + genai_client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(genai_client) + + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + plugins=[plugin], + ) + + worker = Worker( + client, + task_queue="google-genai-streaming", + workflows=[StreamingWorkflow], + ) + print("Worker started. Ctrl+C to exit.") + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/streaming/run_workflow.py b/google_genai/streaming/run_workflow.py new file mode 100644 index 000000000..ce173524e --- /dev/null +++ b/google_genai/streaming/run_workflow.py @@ -0,0 +1,55 @@ +"""Start the streaming workflow and consume model chunks live.""" + +# @@@SNIPSTART python-google-genai-streaming-run-workflow +import asyncio +import os +from datetime import timedelta + +from google.genai import types +from temporalio.client import Client +from temporalio.contrib.pydantic import pydantic_data_converter +from temporalio.contrib.workflow_streams import WorkflowStreamClient + +from google_genai.streaming.workflow import StreamingWorkflow + + +async def main() -> None: + # The stream publishes Pydantic GenerateContentResponse chunks, so the + # consumer needs the Pydantic data converter to decode them. + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + data_converter=pydantic_data_converter, + ) + workflow_id = "google-genai-streaming" + + handle = await client.start_workflow( + StreamingWorkflow.run, + "Count from 1 to 5, one number per sentence.", + id=workflow_id, + task_queue="google-genai-streaming", + ) + + # Subscribe to the "gemini" topic and print chunks as the model produces them. + stream = WorkflowStreamClient.create(client, workflow_id) + async for item in stream.subscribe( + ["gemini"], + from_offset=0, + result_type=types.GenerateContentResponse, + poll_cooldown=timedelta(milliseconds=50), + ): + chunk: types.GenerateContentResponse = item.data + if chunk.text: + print(chunk.text, end="", flush=True) + if chunk.candidates and chunk.candidates[0].finish_reason: + print() + break + + # Release the workflow now that we've consumed the stream. + await handle.signal(StreamingWorkflow.finish) + result = await handle.result() + print(f"Final result: {result}") + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/streaming/workflow.py b/google_genai/streaming/workflow.py new file mode 100644 index 000000000..90c766b2b --- /dev/null +++ b/google_genai/streaming/workflow.py @@ -0,0 +1,41 @@ +"""Stream Gemini output to an external subscriber via WorkflowStream. + +``TemporalAsyncClient(streaming_topic="gemini")`` publishes each +``generate_content_stream`` chunk onto a workflow-hosted ``WorkflowStream`` as +it arrives, so external consumers can watch the model produce text in real time +while the workflow runs durably. The workflow holds itself open on a ``finish`` +signal so a subscriber can reliably read the stream before the run completes. +""" + +# @@@SNIPSTART python-google-genai-streaming-workflow +from temporalio import workflow +from temporalio.contrib.google_genai import TemporalAsyncClient +from temporalio.contrib.workflow_streams import WorkflowStream + + +@workflow.defn +class StreamingWorkflow: + @workflow.init + def __init__(self, prompt: str) -> None: + # Hosting a WorkflowStream is required when streaming_topic is set. + self.stream = WorkflowStream() + self._done = False + + @workflow.run + async def run(self, prompt: str) -> str: + client = TemporalAsyncClient(streaming_topic="gemini") + chunks: list[str] = [] + async for chunk in await client.models.generate_content_stream( + model="gemini-2.5-flash", + contents=prompt, + ): + chunks.append(chunk.text or "") + await workflow.wait_condition(lambda: self._done) + return "".join(chunks) + + @workflow.signal + def finish(self) -> None: + self._done = True + + +# @@@SNIPEND diff --git a/google_genai/structured_output/README.md b/google_genai/structured_output/README.md new file mode 100644 index 000000000..5b19ed945 --- /dev/null +++ b/google_genai/structured_output/README.md @@ -0,0 +1,32 @@ +# Structured Output + +Get typed JSON back from Gemini by passing a Pydantic model as `response_schema`. +The plugin installs a `PydanticPayloadConverter`, so the model serializes cleanly +through Temporal payloads — the workflow returns a real `Recipe` instance. + +## What This Sample Demonstrates + +- `GenerateContentConfig(response_mime_type="application/json", response_schema=Recipe)` +- Reading the parsed model from `response.parsed` +- Returning a Pydantic model as a workflow result via the plugin's Pydantic converter + +## Running the Sample + +Prerequisites: install dependencies, set `GOOGLE_API_KEY`, and start a Temporal +dev server. See the [suite README](../README.md). + +```bash +# Terminal 1 +uv run google_genai/structured_output/run_worker.py + +# Terminal 2 +uv run google_genai/structured_output/run_workflow.py +``` + +## Files + +| File | Description | +|------|-------------| +| `workflow.py` | The `Recipe` model and `StructuredOutputWorkflow` | +| `run_worker.py` | Registers `GoogleGenAIPlugin`, starts the worker | +| `run_workflow.py` | Executes the workflow and prints the typed recipe | diff --git a/google_genai/structured_output/__init__.py b/google_genai/structured_output/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/google_genai/structured_output/run_worker.py b/google_genai/structured_output/run_worker.py new file mode 100644 index 000000000..3b0b2f2fb --- /dev/null +++ b/google_genai/structured_output/run_worker.py @@ -0,0 +1,35 @@ +"""Worker for the structured output sample.""" + +# @@@SNIPSTART python-google-genai-structured-output-worker +import asyncio +import os + +from google import genai +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.worker import Worker + +from google_genai.structured_output.workflow import StructuredOutputWorkflow + + +async def main() -> None: + genai_client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(genai_client) + + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + plugins=[plugin], + ) + + worker = Worker( + client, + task_queue="google-genai-structured-output", + workflows=[StructuredOutputWorkflow], + ) + print("Worker started. Ctrl+C to exit.") + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/structured_output/run_workflow.py b/google_genai/structured_output/run_workflow.py new file mode 100644 index 000000000..e661ab78a --- /dev/null +++ b/google_genai/structured_output/run_workflow.py @@ -0,0 +1,31 @@ +"""Start the structured output workflow.""" + +# @@@SNIPSTART python-google-genai-structured-output-run-workflow +import asyncio +import os + +from temporalio.client import Client + +from google_genai.structured_output.workflow import StructuredOutputWorkflow + + +async def main() -> None: + client = await Client.connect(os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")) + + recipe = await client.execute_workflow( + StructuredOutputWorkflow.run, + "Give me a simple recipe for avocado toast.", + id="google-genai-structured-output", + task_queue="google-genai-structured-output", + ) + + print(f"Recipe: {recipe.name}") + print(f"Ingredients: {', '.join(recipe.ingredients)}") + print("Steps:") + for i, step in enumerate(recipe.steps, start=1): + print(f" {i}. {step}") + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/structured_output/workflow.py b/google_genai/structured_output/workflow.py new file mode 100644 index 000000000..5383cdae8 --- /dev/null +++ b/google_genai/structured_output/workflow.py @@ -0,0 +1,40 @@ +"""Typed JSON output via response_schema + a Pydantic model. + +The plugin installs a ``PydanticPayloadConverter``, so a Pydantic model flows +through Temporal payloads cleanly. Passing the model as ``response_schema`` +makes Gemini return matching JSON, which the SDK parses into the model on +``response.parsed``. +""" + +# @@@SNIPSTART python-google-genai-structured-output-workflow +from google.genai import types +from pydantic import BaseModel +from temporalio import workflow +from temporalio.contrib.google_genai import TemporalAsyncClient + + +class Recipe(BaseModel): + name: str + ingredients: list[str] + steps: list[str] + + +@workflow.defn +class StructuredOutputWorkflow: + @workflow.run + async def run(self, prompt: str) -> Recipe: + client = TemporalAsyncClient() + response = await client.models.generate_content( + model="gemini-2.5-flash", + contents=prompt, + config=types.GenerateContentConfig( + response_mime_type="application/json", + response_schema=Recipe, + ), + ) + recipe = response.parsed + assert isinstance(recipe, Recipe) + return recipe + + +# @@@SNIPEND diff --git a/google_genai/tools/README.md b/google_genai/tools/README.md new file mode 100644 index 000000000..726c39954 --- /dev/null +++ b/google_genai/tools/README.md @@ -0,0 +1,39 @@ +# Tools + +Two tool surfaces wired into one Gemini `generate_content` call, both driven by +the SDK's automatic function-calling (AFC) loop: + +| Pattern | When to use it | +|---------|----------------| +| `@activity.defn` wrapped via `activity_as_tool` | Anything with I/O or non-determinism — runs as a durable activity. | +| Plain workflow method | Pure, deterministic logic — runs in-workflow with no activity dispatch. | + +A single prompt exercises both: the model calls `get_weather` (an activity), +then `recommend_activity` (a workflow method). + +## What This Sample Demonstrates + +- `activity_as_tool` carrying per-tool `ActivityConfig` (timeouts, retries) +- Passing a plain workflow method as a tool alongside an activity-backed one +- The AFC loop running inside the workflow, dispatching tool calls durably + +## Running the Sample + +Prerequisites: install dependencies, set `GOOGLE_API_KEY`, and start a Temporal +dev server. See the [suite README](../README.md). + +```bash +# Terminal 1 +uv run google_genai/tools/run_worker.py + +# Terminal 2 +uv run google_genai/tools/run_workflow.py +``` + +## Files + +| File | Description | +|------|-------------| +| `workflow.py` | `get_weather` activity, `recommend_activity` method, and `ToolsWorkflow` | +| `run_worker.py` | Registers `GoogleGenAIPlugin` + the `get_weather` activity | +| `run_workflow.py` | Executes the workflow and prints the result | diff --git a/google_genai/tools/__init__.py b/google_genai/tools/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/google_genai/tools/run_worker.py b/google_genai/tools/run_worker.py new file mode 100644 index 000000000..f251542b2 --- /dev/null +++ b/google_genai/tools/run_worker.py @@ -0,0 +1,36 @@ +"""Worker for the tools sample.""" + +# @@@SNIPSTART python-google-genai-tools-worker +import asyncio +import os + +from google import genai +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.worker import Worker + +from google_genai.tools.workflow import ToolsWorkflow, get_weather + + +async def main() -> None: + genai_client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"]) + plugin = GoogleGenAIPlugin(genai_client) + + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + plugins=[plugin], + ) + + worker = Worker( + client, + task_queue="google-genai-tools", + workflows=[ToolsWorkflow], + activities=[get_weather], + ) + print("Worker started. Ctrl+C to exit.") + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/tools/run_workflow.py b/google_genai/tools/run_workflow.py new file mode 100644 index 000000000..649ce0ffe --- /dev/null +++ b/google_genai/tools/run_workflow.py @@ -0,0 +1,27 @@ +"""Start the tools workflow.""" + +# @@@SNIPSTART python-google-genai-tools-run-workflow +import asyncio +import os + +from temporalio.client import Client + +from google_genai.tools.workflow import ToolsWorkflow + + +async def main() -> None: + client = await Client.connect(os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")) + + result = await client.execute_workflow( + ToolsWorkflow.run, + "What's the weather in Tokyo, and what should I do there?", + id="google-genai-tools", + task_queue="google-genai-tools", + ) + + print(f"Result: {result}") + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/tools/workflow.py b/google_genai/tools/workflow.py new file mode 100644 index 000000000..10f4d68f8 --- /dev/null +++ b/google_genai/tools/workflow.py @@ -0,0 +1,57 @@ +"""Two tool surfaces on one Gemini call, both driven by automatic function calling. + +1. ``@activity.defn get_weather`` wrapped via ``activity_as_tool`` — runs as a + durable Temporal activity. Use this for I/O or non-deterministic work. +2. ``recommend_activity`` — a plain workflow method passed directly as a tool. + It runs deterministically in-workflow with no activity dispatch. + +Gemini's automatic function-calling (AFC) loop runs inside the workflow and +invokes both as needed. +""" + +# @@@SNIPSTART python-google-genai-tools-workflow +from datetime import timedelta + +from google.genai import types +from temporalio import activity, workflow +from temporalio.contrib.google_genai import TemporalAsyncClient, activity_as_tool +from temporalio.workflow import ActivityConfig + + +@activity.defn +async def get_weather(city: str) -> str: + """Look up the current weather for a city.""" + # Stub — replace with a real HTTP call in production. + return f"It's 72F and sunny in {city}." + + +@workflow.defn +class ToolsWorkflow: + @workflow.run + async def run(self, prompt: str) -> str: + client = TemporalAsyncClient() + response = await client.models.generate_content( + model="gemini-2.5-flash", + contents=prompt, + config=types.GenerateContentConfig( + tools=[ + activity_as_tool( + get_weather, + activity_config=ActivityConfig( + start_to_close_timeout=timedelta(seconds=30), + ), + ), + self.recommend_activity, + ], + ), + ) + return response.text or "" + + async def recommend_activity(self, weather: str) -> str: + """Recommend something to do given a weather description.""" + if "sunny" in weather.lower(): + return "Go for a hike." + return "Visit a museum." + + +# @@@SNIPEND diff --git a/google_genai/vertex_ai/README.md b/google_genai/vertex_ai/README.md new file mode 100644 index 000000000..45bee97a4 --- /dev/null +++ b/google_genai/vertex_ai/README.md @@ -0,0 +1,47 @@ +# Vertex AI + +The same hello-world flow as [`hello_world`](../hello_world), but pointed at +**Vertex AI** instead of the Gemini Developer API. The only difference is +configuration: both the worker's `genai.Client` and the workflow's +`TemporalAsyncClient` set `vertexai=True` with a Google Cloud project and +location. The `vertexai` setting must match on both sides. + +> **Requires Google Cloud credentials**, not a Gemini API key. Authenticate with +> Application Default Credentials (`gcloud auth application-default login`) or a +> service-account key (`GOOGLE_APPLICATION_CREDENTIALS`). This sample has no +> automated test. + +## Configuration + +| Variable | Description | +|----------|-------------| +| `GOOGLE_CLOUD_PROJECT` | Your Google Cloud project ID (required) | +| `GOOGLE_CLOUD_LOCATION` | Region, e.g. `us-central1` (defaults to `us-central1`) | + +## What This Sample Demonstrates + +- `genai.Client(vertexai=True, project=..., location=...)` on the worker +- `TemporalAsyncClient(vertexai=True, project=..., location=...)` in the workflow +- Passing project/location as workflow arguments to keep the workflow deterministic + +## Running the Sample + +Prerequisites: install dependencies, configure GCP credentials, set +`GOOGLE_CLOUD_PROJECT`, and start a Temporal dev server. See the +[suite README](../README.md). + +```bash +# Terminal 1 +uv run google_genai/vertex_ai/run_worker.py + +# Terminal 2 +uv run google_genai/vertex_ai/run_workflow.py +``` + +## Files + +| File | Description | +|------|-------------| +| `workflow.py` | `VertexAIWorkflow` — generate_content via Vertex AI | +| `run_worker.py` | Registers a Vertex-configured `GoogleGenAIPlugin` | +| `run_workflow.py` | Reads project/location from env and executes the workflow | diff --git a/google_genai/vertex_ai/__init__.py b/google_genai/vertex_ai/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/google_genai/vertex_ai/run_worker.py b/google_genai/vertex_ai/run_worker.py new file mode 100644 index 000000000..ee2f77f92 --- /dev/null +++ b/google_genai/vertex_ai/run_worker.py @@ -0,0 +1,44 @@ +"""Worker for the Vertex AI sample. + +Uses ``genai.Client(vertexai=True, ...)`` with Application Default Credentials +(no API key). Run ``gcloud auth application-default login`` first, or set +``GOOGLE_APPLICATION_CREDENTIALS`` to a service-account key file. +""" + +# @@@SNIPSTART python-google-genai-vertex-ai-worker +import asyncio +import os + +from google import genai +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.worker import Worker + +from google_genai.vertex_ai.workflow import VertexAIWorkflow + + +async def main() -> None: + genai_client = genai.Client( + vertexai=True, + project=os.environ["GOOGLE_CLOUD_PROJECT"], + location=os.environ.get("GOOGLE_CLOUD_LOCATION", "us-central1"), + ) + plugin = GoogleGenAIPlugin(genai_client) + + client = await Client.connect( + os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"), + plugins=[plugin], + ) + + worker = Worker( + client, + task_queue="google-genai-vertex-ai", + workflows=[VertexAIWorkflow], + ) + print("Worker started. Ctrl+C to exit.") + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/vertex_ai/run_workflow.py b/google_genai/vertex_ai/run_workflow.py new file mode 100644 index 000000000..d06276833 --- /dev/null +++ b/google_genai/vertex_ai/run_workflow.py @@ -0,0 +1,30 @@ +"""Start the Vertex AI workflow.""" + +# @@@SNIPSTART python-google-genai-vertex-ai-run-workflow +import asyncio +import os + +from temporalio.client import Client + +from google_genai.vertex_ai.workflow import VertexAIWorkflow + + +async def main() -> None: + client = await Client.connect(os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")) + + project = os.environ["GOOGLE_CLOUD_PROJECT"] + location = os.environ.get("GOOGLE_CLOUD_LOCATION", "us-central1") + + result = await client.execute_workflow( + VertexAIWorkflow.run, + args=["Write a haiku about durable execution.", project, location], + id="google-genai-vertex-ai", + task_queue="google-genai-vertex-ai", + ) + + print(f"Result: {result}") + + +if __name__ == "__main__": + asyncio.run(main()) +# @@@SNIPEND diff --git a/google_genai/vertex_ai/workflow.py b/google_genai/vertex_ai/workflow.py new file mode 100644 index 000000000..33db84aa0 --- /dev/null +++ b/google_genai/vertex_ai/workflow.py @@ -0,0 +1,31 @@ +"""Hello world against Vertex AI instead of the Gemini Developer API. + +The only difference from the basic sample is configuration: both the workflow's +``TemporalAsyncClient`` and the worker's ``genai.Client`` use ``vertexai=True`` +with a Google Cloud project and location. The project and location are passed in +as workflow arguments (read from the environment by the starter) to keep the +workflow deterministic. +""" + +# @@@SNIPSTART python-google-genai-vertex-ai-workflow +from temporalio import workflow +from temporalio.contrib.google_genai import TemporalAsyncClient + + +@workflow.defn +class VertexAIWorkflow: + @workflow.run + async def run(self, prompt: str, project: str, location: str) -> str: + client = TemporalAsyncClient( + vertexai=True, + project=project, + location=location, + ) + response = await client.models.generate_content( + model="gemini-2.5-flash", + contents=prompt, + ) + return response.text or "" + + +# @@@SNIPEND diff --git a/pyproject.toml b/pyproject.toml index e8f3ebd87..c8ba8ab26 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ authors = [{ name = "Temporal Technologies Inc", email = "sdk@temporal.io" }] requires-python = ">=3.10" readme = "README.md" license = "MIT" -dependencies = ["temporalio>=1.30.0,<2", "protobuf>=5.29.6,<6"] +dependencies = ["temporalio>=1.31.0,<2", "protobuf>=5.29.6,<6"] [project.urls] Homepage = "https://github.com/temporalio/samples-python" @@ -38,17 +38,21 @@ external-storage = [ ] external-storage-redis = ["redis>=5.0.0,<8"] gevent = ["gevent>=25.4.2 ; python_version >= '3.8'"] -google-adk = ["temporalio[google-adk] >= 1.30.0", "google-adk>=1.27.0,<2"] +google-adk = ["temporalio[google-adk] >= 1.31.0", "google-adk>=2.2.0,<3"] +google-genai = [ + "mcp>=1.0.0", + "temporalio[google-genai,pydantic]>=1.31.0", +] langsmith-tracing = [ "openai>=1.4.0", "langsmith>=0.7.0", - "temporalio[pydantic,langsmith]>=1.30.0", + "temporalio[pydantic,langsmith]>=1.31.0", ] langgraph = [ "langgraph>=1.1.3", "langchain>=0.3.0", "langchain-anthropic>=0.3.0", - "temporalio[langgraph,langsmith]>=1.30.0", + "temporalio[langgraph,langsmith]>=1.31.0", ] nexus = ["nexus-rpc>=1.1.0,<2"] open-telemetry = [ @@ -57,7 +61,7 @@ open-telemetry = [ ] openai-agents = [ "openai-agents[litellm] >= 0.14.1", - "temporalio[openai-agents,opentelemetry] >= 1.30.0", + "temporalio[openai-agents,opentelemetry] >= 1.31.0", "requests>=2.32.0,<3", ] pydantic-converter = ["pydantic>=2.10.6,<3"] @@ -67,7 +71,7 @@ strands-agents = [ "strands-agents-tools>=0.5.2", "mcp>=1.0.0", "boto3>=1.34.92,<2", - "temporalio[strands-agents,pydantic]>=1.30.0", + "temporalio[strands-agents,pydantic]>=1.31.0", ] trio-async = ["trio>=0.28.0,<0.29", "trio-asyncio>=0.15.0,<0.16"] cloud-export-to-parquet = [ @@ -107,6 +111,7 @@ packages = [ "external_storage", "external_storage_redis", "gevent_async", + "google_genai", "hello", "langgraph_plugin", "langsmith_tracing", diff --git a/strands_plugin/README.md b/strands_plugin/README.md index d4eaf558a..d55a1acda 100644 --- a/strands_plugin/README.md +++ b/strands_plugin/README.md @@ -24,12 +24,6 @@ These samples demonstrate the [Temporal Strands plugin](https://github.com/tempo uv sync --group strands-agents ``` - > The `strands` extra of `temporalio` is shipping in an upcoming release. Until then, install the SDK from the strands branch: - > - > ```bash - > uv pip install -e ../sdk-python --extra strands-agents --extra pydantic - > ``` - 2. Configure AWS credentials. The samples use the plugin's default `BedrockModel()`, which picks up the standard AWS SDK credential chain. Make sure the credentials grant access to a Bedrock model in your selected region (e.g., `us-west-2`). ```bash diff --git a/tests/google_genai/__init__.py b/tests/google_genai/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/google_genai/chat_test.py b/tests/google_genai/chat_test.py new file mode 100644 index 000000000..504a630b4 --- /dev/null +++ b/tests/google_genai/chat_test.py @@ -0,0 +1,43 @@ +import uuid + +from temporalio.client import Client +from temporalio.contrib.google_genai.testing import GeminiTestServer, text_response +from temporalio.worker import Worker + +from google_genai.chat.workflow import ChatWorkflow + + +async def test_chat(client: Client) -> None: + server = GeminiTestServer( + [ + text_response("Got it — your favorite color is teal."), + text_response("Your favorite color is teal."), + ] + ) + + config = client.config() + config["plugins"] = [*config["plugins"], server.plugin()] + client = Client(**config) + + task_queue = f"google-genai-chat-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[ChatWorkflow], + max_cached_workflows=0, + ): + result = await client.execute_workflow( + ChatWorkflow.run, + [ + "My favorite color is teal. Remember that.", + "What is my favorite color?", + ], + id=f"google-genai-chat-{uuid.uuid4()}", + task_queue=task_queue, + ) + + assert result == [ + "Got it — your favorite color is teal.", + "Your favorite color is teal.", + ] + assert len(server.requests) == 2 diff --git a/tests/google_genai/hello_world_test.py b/tests/google_genai/hello_world_test.py new file mode 100644 index 000000000..c612885c1 --- /dev/null +++ b/tests/google_genai/hello_world_test.py @@ -0,0 +1,32 @@ +import uuid + +from temporalio.client import Client +from temporalio.contrib.google_genai.testing import GeminiTestServer, text_response +from temporalio.worker import Worker + +from google_genai.hello_world.workflow import HelloWorldWorkflow + + +async def test_hello_world(client: Client) -> None: + server = GeminiTestServer([text_response("A haiku, for you.")]) + + config = client.config() + config["plugins"] = [*config["plugins"], server.plugin()] + client = Client(**config) + + task_queue = f"google-genai-hello-world-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[HelloWorldWorkflow], + max_cached_workflows=0, + ): + result = await client.execute_workflow( + HelloWorldWorkflow.run, + "Write a haiku.", + id=f"google-genai-hello-world-{uuid.uuid4()}", + task_queue=task_queue, + ) + + assert result == "A haiku, for you." + assert len(server.requests) == 1 diff --git a/tests/google_genai/mcp_test.py b/tests/google_genai/mcp_test.py new file mode 100644 index 000000000..e5913ad1c --- /dev/null +++ b/tests/google_genai/mcp_test.py @@ -0,0 +1,81 @@ +import sys +import uuid +from collections.abc import AsyncIterator +from contextlib import asynccontextmanager +from pathlib import Path +from typing import Any + +from google import genai +from google.genai.types import HttpResponse as SdkHttpResponse +from mcp import ClientSession, StdioServerParameters +from mcp.client.stdio import stdio_client +from temporalio.client import Client +from temporalio.contrib.google_genai import GoogleGenAIPlugin +from temporalio.contrib.google_genai.testing import ( + function_call_response, + text_response, +) +from temporalio.worker import Worker + +from google_genai.mcp.workflow import McpWorkflow + +ECHO_SERVER = str( + Path(__file__).parents[2] / "google_genai" / "mcp" / "echo_mcp_server.py" +) + + +@asynccontextmanager +async def _echo_session() -> AsyncIterator[ClientSession]: + params = StdioServerParameters(command=sys.executable, args=[ECHO_SERVER]) + async with stdio_client(params) as (read, write): + async with ClientSession(read, write) as session: + await session.initialize() + yield session + + +def _mcp_plugin(responses: list[str]) -> GoogleGenAIPlugin: + """A plugin with scripted model HTTP plus a real echo MCP server. + + Mirrors what ``GeminiTestServer.plugin()`` does for the model HTTP layer, + but also registers an MCP server (which ``GeminiTestServer`` does not), so + the MCP ``list_tools`` / ``call_tool`` activities run for real. + """ + genai_client = genai.Client(api_key="fake-test-key") + index = {"i": 0} + + async def fake_async_request(*_args: Any, **_kwargs: Any) -> SdkHttpResponse: + body = responses[index["i"]] + index["i"] += 1 + return SdkHttpResponse(headers={"content-type": "application/json"}, body=body) + + genai_client._api_client.async_request = fake_async_request # type: ignore[assignment] + return GoogleGenAIPlugin(genai_client, mcp_servers={"echo": _echo_session}) + + +async def test_mcp(client: Client) -> None: + plugin = _mcp_plugin( + [ + function_call_response("echo", {"message": "durable execution"}), + text_response("The echo tool returned: durable execution"), + ] + ) + + config = client.config() + config["plugins"] = [*config["plugins"], plugin] + client = Client(**config) + + task_queue = f"google-genai-mcp-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[McpWorkflow], + max_cached_workflows=0, + ): + result = await client.execute_workflow( + McpWorkflow.run, + "Use the echo tool to echo back the phrase: durable execution.", + id=f"google-genai-mcp-{uuid.uuid4()}", + task_queue=task_queue, + ) + + assert "durable execution" in result diff --git a/tests/google_genai/streaming_test.py b/tests/google_genai/streaming_test.py new file mode 100644 index 000000000..dec695586 --- /dev/null +++ b/tests/google_genai/streaming_test.py @@ -0,0 +1,53 @@ +import uuid +from datetime import timedelta + +from google.genai import types +from temporalio.client import Client +from temporalio.contrib.google_genai.testing import GeminiTestServer, text_response +from temporalio.contrib.workflow_streams import WorkflowStreamClient +from temporalio.worker import Worker + +from google_genai.streaming.workflow import StreamingWorkflow + + +async def test_streaming_publishes_to_workflow_stream(client: Client) -> None: + server = GeminiTestServer([text_response("Hello from Gemini stream")]) + + config = client.config() + config["plugins"] = [*config["plugins"], server.plugin()] + client = Client(**config) + + task_queue = f"google-genai-streaming-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[StreamingWorkflow], + max_cached_workflows=0, + ): + wf_id = f"google-genai-streaming-{uuid.uuid4()}" + handle = await client.start_workflow( + StreamingWorkflow.run, + "say hi", + id=wf_id, + task_queue=task_queue, + execution_timeout=timedelta(seconds=15), + ) + + # Consume the published chunk from the "gemini" topic. + stream = WorkflowStreamClient.create(client, wf_id) + received: list[types.GenerateContentResponse] = [] + async for item in stream.subscribe( + ["gemini"], + from_offset=0, + result_type=types.GenerateContentResponse, + poll_cooldown=timedelta(milliseconds=20), + ): + received.append(item.data) + break # one scripted chunk + + await handle.signal(StreamingWorkflow.finish) + result = await handle.result() + + assert result == "Hello from Gemini stream" + assert len(received) == 1 + assert received[0].text == "Hello from Gemini stream" diff --git a/tests/google_genai/structured_output_test.py b/tests/google_genai/structured_output_test.py new file mode 100644 index 000000000..6e93c2ede --- /dev/null +++ b/tests/google_genai/structured_output_test.py @@ -0,0 +1,45 @@ +import json +import uuid + +from temporalio.client import Client +from temporalio.contrib.google_genai.testing import GeminiTestServer, text_response +from temporalio.worker import Worker + +from google_genai.structured_output.workflow import ( + Recipe, + StructuredOutputWorkflow, +) + + +async def test_structured_output(client: Client) -> None: + recipe_json = json.dumps( + { + "name": "Avocado Toast", + "ingredients": ["bread", "avocado", "salt"], + "steps": ["Toast the bread.", "Mash the avocado on top.", "Season."], + } + ) + server = GeminiTestServer([text_response(recipe_json)]) + + config = client.config() + config["plugins"] = [*config["plugins"], server.plugin()] + client = Client(**config) + + task_queue = f"google-genai-structured-output-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[StructuredOutputWorkflow], + max_cached_workflows=0, + ): + result = await client.execute_workflow( + StructuredOutputWorkflow.run, + "Give me a simple recipe for avocado toast.", + id=f"google-genai-structured-output-{uuid.uuid4()}", + task_queue=task_queue, + ) + + assert isinstance(result, Recipe) + assert result.name == "Avocado Toast" + assert result.ingredients == ["bread", "avocado", "salt"] + assert len(result.steps) == 3 diff --git a/tests/google_genai/tools_test.py b/tests/google_genai/tools_test.py new file mode 100644 index 000000000..7ca5e2bd7 --- /dev/null +++ b/tests/google_genai/tools_test.py @@ -0,0 +1,46 @@ +import uuid + +from temporalio.client import Client +from temporalio.contrib.google_genai.testing import ( + GeminiTestServer, + function_call_response, + text_response, +) +from temporalio.worker import Worker + +from google_genai.tools.workflow import ToolsWorkflow, get_weather + + +async def test_tools(client: Client) -> None: + server = GeminiTestServer( + [ + function_call_response("get_weather", {"city": "Tokyo"}), + function_call_response( + "recommend_activity", {"weather": "It's 72F and sunny in Tokyo."} + ), + text_response("It's sunny in Tokyo — go for a hike!"), + ] + ) + + config = client.config() + config["plugins"] = [*config["plugins"], server.plugin()] + client = Client(**config) + + task_queue = f"google-genai-tools-{uuid.uuid4()}" + async with Worker( + client, + task_queue=task_queue, + workflows=[ToolsWorkflow], + activities=[get_weather], + max_cached_workflows=0, + ): + result = await client.execute_workflow( + ToolsWorkflow.run, + "What's the weather in Tokyo, and what should I do there?", + id=f"google-genai-tools-{uuid.uuid4()}", + task_queue=task_queue, + ) + + assert result == "It's sunny in Tokyo — go for a hike!" + # One model turn per response: two tool calls and a final text answer. + assert len(server.requests) == 3 diff --git a/uv.lock b/uv.lock index 6063f75a3..6733ca10b 100644 --- a/uv.lock +++ b/uv.lock @@ -218,21 +218,6 @@ 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.4" -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/94/13/8b084e0f2efb0275a1d534838844926f798bd766566b1375174e2448cd31/alembic-1.18.4.tar.gz", hash = "sha256:cb6e1fd84b6174ab8dbb2329f86d631ba9559dd78df550b57804d607672cedbc", size = 2056725, upload-time = "2026-02-10T16:00:47.195Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/29/6533c317b74f707ea28f8d633734dbda2119bbadfc61b2f3640ba835d0f7/alembic-1.18.4-py3-none-any.whl", hash = "sha256:a5ed4adcf6d8a4cb575f3d759f071b03cd6e5c7618eb796cb52497be25bfe19a", size = 263893, upload-time = "2026-02-10T16:00:49.997Z" }, -] - [[package]] name = "annotated-doc" version = "0.0.4" @@ -640,15 +625,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ee/ae/8e92f8058baf87f6c7d86ee7e457668690195cc77efedb8d3797a06e3940/click-8.4.0-py3-none-any.whl", hash = "sha256:40c50b7c6c6adac2823d411041ec84f3f103f1b280d5e9ce0d7f998995832f81", size = 116147, upload-time = "2026-05-17T00:47:56.842Z" }, ] -[[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" @@ -736,7 +712,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1055,47 +1031,26 @@ wheels = [ [[package]] name = "google-adk" -version = "1.35.2" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiosqlite" }, - { name = "anyio" }, { name = "authlib" }, { name = "click" }, { name = "fastapi" }, - { name = "google-api-python-client" }, { name = "google-auth", extra = ["pyopenssl"] }, - { name = "google-cloud-aiplatform", extra = ["agent-engines"] }, - { name = "google-cloud-bigquery" }, - { name = "google-cloud-bigquery-storage" }, - { name = "google-cloud-bigtable" }, - { name = "google-cloud-dataplex" }, - { name = "google-cloud-discoveryengine" }, - { name = "google-cloud-pubsub" }, - { name = "google-cloud-secret-manager" }, - { name = "google-cloud-spanner" }, - { name = "google-cloud-speech" }, - { name = "google-cloud-storage" }, { name = "google-genai" }, { name = "graphviz" }, { name = "httpx" }, { 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 = "packaging" }, { name = "pydantic" }, - { name = "python-dateutil" }, { name = "python-dotenv" }, + { name = "python-multipart" }, { name = "pyyaml" }, { name = "requests" }, - { name = "sqlalchemy" }, - { name = "sqlalchemy-spanner" }, { name = "starlette" }, { name = "tenacity" }, { name = "typing-extensions" }, @@ -1104,47 +1059,9 @@ dependencies = [ { name = "watchdog" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ab/9b/6151ab3e5566b85008322605be7c3d27cc30b85946b7d026c8d56bdfc46c/google_adk-1.35.2.tar.gz", hash = "sha256:8ee69cc3ed2fb828664f761a50cc1351668d685506206eda6df2e2cb9f3f2147", size = 2431987, upload-time = "2026-06-17T20:43:04.974Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/6f/d472034f28c78a0f423d56e421284ab40a726b2311788abdce9a1c41689c/google_adk-1.35.2-py3-none-any.whl", hash = "sha256:58db7398a9b6513d0a045e3d25ac9138f58165fb25404b3765581776de4c3ce4", size = 2876762, upload-time = "2026-06-17T20:43:02.678Z" }, -] - -[[package]] -name = "google-api-core" -version = "2.25.2" -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/09/cd/63f1557235c2440fe0577acdbc32577c5c002684c58c7f4d770a92366a24/google_api_core-2.25.2.tar.gz", hash = "sha256:1c63aa6af0d0d5e37966f157a77f9396d820fba59f9e43e9415bc3dc5baff300", size = 166266, upload-time = "2025-10-03T00:07:34.778Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/8b/d014c98e987ed3a95ac3740d2b5c8e8e891bfd88c3ac2253fca9547f3b1f/google_adk-2.5.0.tar.gz", hash = "sha256:55b88cac9d5072d511fd3224e5f334e57fb2b0ae567507e531e03fdfb60c82c2", size = 3608134, upload-time = "2026-07-16T20:43:06.464Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/d8/894716a5423933f5c8d2d5f04b16f052a515f78e815dab0c2c6f1fd105dc/google_api_core-2.25.2-py3-none-any.whl", hash = "sha256:e9a8f62d363dc8424a8497f4c2a47d6bcda6c16514c935629c257ab5d10210e7", size = 162489, upload-time = "2025-10-03T00:07:32.924Z" }, -] - -[package.optional-dependencies] -grpc = [ - { name = "grpcio" }, - { name = "grpcio-status" }, -] - -[[package]] -name = "google-api-python-client" -version = "2.197.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/22/09/081d66357118bd260f8f182cb1b2dd5bd32ca88e3714d7c93896cab946fc/google_api_python_client-2.197.0.tar.gz", hash = "sha256:32e03977eda4a66eafc6ae58dc9ec46426b6025636d5ef019c5703013eddd4e5", size = 14707398, upload-time = "2026-05-28T20:23:12.498Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/e5/e9cc221fd75230974d4ef45eb72d2261feca3c110d5554215d516bfe6534/google_api_python_client-2.197.0-py3-none-any.whl", hash = "sha256:0f8b89aa75768161dd4f5092d6bcb386c13236b32e0d9a938c02f71342094d14", size = 15287302, upload-time = "2026-05-28T20:23:09.683Z" }, + { url = "https://files.pythonhosted.org/packages/52/fe/699d21edebd1305b6d23fd570140cf0cf921f34f66e4611d840684717c3a/google_adk-2.5.0-py3-none-any.whl", hash = "sha256:d247ca3639921a54a86feb797a88d08c1d2c9a60c3f5ff2805e49beb29a9cb8d", size = 4169976, upload-time = "2026-07-16T20:43:04.647Z" }, ] [[package]] @@ -1168,406 +1085,9 @@ requests = [ { name = "requests" }, ] -[[package]] -name = "google-auth-httplib2" -version = "0.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-auth" }, - { name = "httplib2" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1c/b3/f192c8bc7e41e0ebdbd95afcae4783417a34b6a6af62d22daf22c3fd38fc/google_auth_httplib2-0.4.0.tar.gz", hash = "sha256:d5b030a204b7a4b4d553ba9ca701b62481ee2b74419325580be70f7d85ffed35", size = 11161, upload-time = "2026-05-07T08:03:46.878Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/97/be/954c35a62b9e31de66b0a43c225c9b6bb9e0f98d6b1dc110a2308e3644f5/google_auth_httplib2-0.4.0-py3-none-any.whl", hash = "sha256:8e55cfafa3358cba85f6cad4a886138e88e158d71e7e5c9ee5936a5c1507fb91", size = 9529, upload-time = "2026-05-07T08:02:12.375Z" }, -] - -[[package]] -name = "google-cloud-aiplatform" -version = "1.148.1" -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/c9/f3/b2a9417014c93858a2e3266134f931eefd972c2d410b25d7b8782fc6f143/google_cloud_aiplatform-1.148.1.tar.gz", hash = "sha256:75d605fba34e68714bd08e1e482755d0a6e3ae972805f809d088e686c30879e7", size = 10278758, upload-time = "2026-04-17T23:45:26.738Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/56/5b/e3515d7bbba602c2b0f6a0da5431785e897252443682e4735d0e6873dc8f/google_cloud_aiplatform-1.148.1-py2.py3-none-any.whl", hash = "sha256:035101e2d8e65c6a706cc3930b2452de7ddcbde50dd130320fcea0d8b03b0c5a", size = 8434481, upload-time = "2026-04-17T23:45:22.919Z" }, -] - -[package.optional-dependencies] -agent-engines = [ - { name = "aiohttp" }, - { 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.10.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/7f/b9/fcafc8d2dc68975a65cdff74807547cff9b2a7b00e738d3f5ff0bd112867/google_cloud_appengine_logging-1.10.0.tar.gz", hash = "sha256:b5563e76010a36e6adf1cc489620c29ee4fb3b986b006d237e9a061eb0f0abb7", size = 17744, upload-time = "2026-06-03T14:52:40.298Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/b3/4eeb9f59c4e7e07e1f08704b6508249eea5760878810014e636026300416/google_cloud_appengine_logging-1.10.0-py3-none-any.whl", hash = "sha256:193675caaf062c41688a3e2c744b73614db82408bc7fb060353b6878d7134492", size = 18143, upload-time = "2026-06-03T14:51:55.174Z" }, -] - -[[package]] -name = "google-cloud-audit-log" -version = "0.6.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "googleapis-common-protos" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/01/46/b971191224557091cc865b47d527e61da180e33b9397904bdefdae1dcacd/google_cloud_audit_log-0.6.0.tar.gz", hash = "sha256:4dd343683c0bb31187ebef3426803f13159e950fbea3fe60a864855cfed959b8", size = 44674, upload-time = "2026-06-03T14:52:48.095Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/99/27c70286bfa3503e43f845578ed5c2ab30c0cc68e525c168286f05f9a51c/google_cloud_audit_log-0.6.0-py3-none-any.whl", hash = "sha256:8c5ecbc341ad3b3daf776981f6d7fd7ab5ff5a29c5dce3172c669b570e0f6717", size = 44853, upload-time = "2026-06-03T14:52:03.775Z" }, -] - -[[package]] -name = "google-cloud-bigquery" -version = "3.42.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-api-core", extra = ["grpc"] }, - { name = "google-auth", extra = ["pyopenssl"] }, - { name = "google-cloud-core" }, - { name = "google-resumable-media" }, - { name = "packaging" }, - { name = "python-dateutil" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/97/a6/3d40767763061323d70ecf1870d9d5f428ee6a7e66f7b6e7297ee17f8b30/google_cloud_bigquery-3.42.0.tar.gz", hash = "sha256:4491a75f82d905101e75b690ca4c6791984bf4f50653706747537b05baa90213", size = 514647, upload-time = "2026-06-15T22:55:34.21Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/27/6ab5688744a08c15770ad10a4e430b16365f3ff95d9a59e565d47ce27175/google_cloud_bigquery-3.42.0-py3-none-any.whl", hash = "sha256:9df6a73043363cad17000c29591ed829be5f630ec30b85b29bc29062ab8b19a4", size = 263751, upload-time = "2026-06-15T22:55:32.352Z" }, -] - -[[package]] -name = "google-cloud-bigquery-storage" -version = "2.39.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/1b/85/c998751fb4182b84872df7eafcdd2f68e325c791102b65d416975c020020/google_cloud_bigquery_storage-2.39.0.tar.gz", hash = "sha256:d5afd90ad06cf24d9167316cca70ab5b344e880fc13031d7392aa78ee76b8bb6", size = 309852, upload-time = "2026-06-03T15:13:01.874Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/f6/4157466c10181907d07786fb41df5d0a9ff339c1770b9e2a15cfe483e845/google_cloud_bigquery_storage-2.39.0-py3-none-any.whl", hash = "sha256:8c192b6263804f7bdd6f57a17e763ba7f03fa4e53d7ecafca0187e0fd6467d48", size = 305958, upload-time = "2026-06-03T15:12:15.889Z" }, -] - -[[package]] -name = "google-cloud-bigtable" -version = "2.38.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 = "grpcio" }, - { name = "proto-plus" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f7/2c/a62b2108459518914d75b8455dd69bac838d6bf276fe902320f5f16cf9cb/google_cloud_bigtable-2.38.0.tar.gz", hash = "sha256:0ad24f0106c2eb0f38e278b1641052e65882a4da0141d1f9ad78ea691724aaa3", size = 800955, upload-time = "2026-05-07T19:32:53.737Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/46/9d/9c0a81aa9cf6c058b02d3be194d70bcd7e4bd82f631c8110560c3908dbc4/google_cloud_bigtable-2.38.0-py3-none-any.whl", hash = "sha256:9f6a4bdbefb34d0420f41c574d9805d8a63d080d10be5a176205e3b322c122a1", size = 556168, upload-time = "2026-05-07T19:32:51.48Z" }, -] - -[[package]] -name = "google-cloud-core" -version = "2.6.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-api-core" }, - { name = "google-auth" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a8/dd/1eef226e470369b26824a505c34482c0b493bc35fe8e0c6b003b5feca21a/google_cloud_core-2.6.0.tar.gz", hash = "sha256:e76149739f90fac1fc6757c09f47eaccb3145b54adbd7759b0f7c4b235f46c83", size = 36001, upload-time = "2026-05-07T08:04:04.124Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/84/4a/98da8930ab109c73d9a5d13782a9ebb81ea8c111f6d534a567b71d23e52b/google_cloud_core-2.6.0-py3-none-any.whl", hash = "sha256:6d63ac8e5eca6d9e4319d0a1e2265fadcd7f1049904378caecfa01cf52dd869e", size = 29390, upload-time = "2026-05-07T08:02:34.672Z" }, -] - -[[package]] -name = "google-cloud-dataplex" -version = "2.20.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/96/41/695b333dad5c3bda1df09c0744b574d14ed1cc5f8d933863723d95476ea5/google_cloud_dataplex-2.20.0.tar.gz", hash = "sha256:cbdc55ec184a58c6d444f6d37fcc9070664a345a8e110f34dd7233ed37f92047", size = 894255, upload-time = "2026-06-03T15:28:01.155Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/9f/ca0ca400de2a1a1dbf264a5c7b1c67deb17ddf0e941598a90da759c97751/google_cloud_dataplex-2.20.0-py3-none-any.whl", hash = "sha256:920bbc466eea3ce0168f9fefc4a16fd33e6ddb70537588666ce8e6609f1e1553", size = 691436, upload-time = "2026-06-03T15:27:10.355Z" }, -] - -[[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.23.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/0d/5f/128a1462354e0f8f0b7baff34b5a1a4e5cd7aee100d8db0eb39843b43d1d/google_cloud_iam-2.23.0.tar.gz", hash = "sha256:49246f6221026d381cff4f8d804daf1bb6416153f2504bf5ef54d4af2450b828", size = 561685, upload-time = "2026-05-07T08:04:16.253Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/ee/470f0c337a235b12c6a880df25809b8b11b33986510d66450cb5ef540a83/google_cloud_iam-2.23.0-py3-none-any.whl", hash = "sha256:a123ac45080a5c1735218a6b3db4c6e6ea12a1cdc86feec1c30ad1ede6c91fc6", size = 515952, upload-time = "2026-05-07T08:02:48.144Z" }, -] - -[[package]] -name = "google-cloud-logging" -version = "3.16.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 = "grpcio" }, - { name = "opentelemetry-api" }, - { name = "proto-plus" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9b/ba/e749846f13c8d1c6c01eb6317e8b09abc130fe67b5d72081a48d1bf96971/google_cloud_logging-3.16.0.tar.gz", hash = "sha256:08a3076b8f0f724219d6f73b2a242ef69d51e8bce226133aebe41a25f23f5400", size = 293703, upload-time = "2026-06-03T15:28:23.862Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/d5/91035dd77e0033dfb00d52b2bcad1e4f7408eb931981f86a1584301670a8/google_cloud_logging-3.16.0-py3-none-any.whl", hash = "sha256:9e5bfbdfe7b5315ece00e1703a2ea25fe42ca35e0b4750127b019f50d069b01b", size = 234188, upload-time = "2026-06-03T15:27:37.407Z" }, -] - -[[package]] -name = "google-cloud-monitoring" -version = "2.31.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/84/9d/9522e169db3887e7f354bb9aa544a6e26c435ce19337e32432598db18c6f/google_cloud_monitoring-2.31.0.tar.gz", hash = "sha256:b4c9d3528c8643d4eb4b9d688cbb3c5914bc5f69b314ff7c5e1b47bdc073a9ae", size = 404747, upload-time = "2026-06-03T15:28:24.938Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/55/30/aa6635296da9c1c14d2e64f64e1cacd4f4debf8ab7e646c0559545f0f70d/google_cloud_monitoring-2.31.0-py3-none-any.whl", hash = "sha256:64f3d56ead48f0a0674f650cb2828c47b936582a02a27c55f2836681a86281c3", size = 391010, upload-time = "2026-06-03T15:27:39.536Z" }, -] - -[[package]] -name = "google-cloud-pubsub" -version = "2.39.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 = "grpcio-status" }, - { name = "opentelemetry-api" }, - { name = "opentelemetry-sdk" }, - { name = "proto-plus" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/11/2b/4bf2c17e319ff65340389565b0e1b4d72696d87802b2f5f94390fbefa73c/google_cloud_pubsub-2.39.0.tar.gz", hash = "sha256:eed65e25f57f95bf3e02d96d7ee171688b23922471f9f21b5a91ed90e1282c0f", size = 402096, upload-time = "2026-06-03T15:28:26.396Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/93/20/dd0b27d4ad4577c062e77ff968ca3e2d404186cd78c8a2a53a0ef5fe5389/google_cloud_pubsub-2.39.0-py3-none-any.whl", hash = "sha256:7210d691a46d7a66559696899ebe6eb731e63de29b624964b3be4dd2d12d3e19", size = 324665, upload-time = "2026-06-03T15:27:41.119Z" }, -] - -[[package]] -name = "google-cloud-resource-manager" -version = "1.17.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/b2/1a/13060cabf553d52d151d2afc26b39561e82853380d499dd525a0d422d9f0/google_cloud_resource_manager-1.17.0.tar.gz", hash = "sha256:0f486b62e2c58ff992a3a50fa0f4a96eef7750aa6c971bb373398ccb91828660", size = 464971, upload-time = "2026-03-26T22:17:29.204Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/f7/661d7a9023e877a226b5683429c3662f75a29ef45cb1464cf39adb689218/google_cloud_resource_manager-1.17.0-py3-none-any.whl", hash = "sha256:e479baf4b014a57f298e01b8279e3290b032e3476d69c8e5e1427af8f82739a5", size = 404403, upload-time = "2026-03-26T22:15:26.57Z" }, -] - -[[package]] -name = "google-cloud-secret-manager" -version = "2.29.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/d2/7c/5c88cdde9664f6c75fb68aa11e0af4309a92bef38dd38df0456ffb0f469b/google_cloud_secret_manager-2.29.0.tar.gz", hash = "sha256:ee64133af8fdb3780affb65ec6ccf10ab15a0113d8edeba388665f4be87ce1be", size = 278437, upload-time = "2026-06-03T16:13:43.149Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/c2/fc3275bc42a522757cb5141d7dae51f048b93d2f5fe4574fcee5392cef03/google_cloud_secret_manager-2.29.0-py3-none-any.whl", hash = "sha256:21bac2d0adb0bb3c13c346d7223832f197c2266534528a1bf1402774e06395a3", size = 225042, upload-time = "2026-06-03T16:12:20.162Z" }, -] - -[[package]] -name = "google-cloud-spanner" -version = "3.68.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-api-core", extra = ["grpc"] }, - { name = "google-auth" }, - { name = "google-cloud-core" }, - { name = "google-cloud-monitoring" }, - { name = "grpc-google-iam-v1" }, - { name = "grpc-interceptor" }, - { name = "grpcio" }, - { 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/a4/2d/b857929745f57bb5b90f44970c02fdfbfb1184505ce4aa6e6c32550afb5f/google_cloud_spanner-3.68.0.tar.gz", hash = "sha256:90c55751cfc35bd58554c5715eab8be544095e21e40a805eb4d0c61a2bf07091", size = 904630, upload-time = "2026-06-12T18:03:27.665Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/df/f4/02ff12ebd23bb5af763b2b165deffe0dc78f933921903eb394a6ce4e0ed3/google_cloud_spanner-3.68.0-py3-none-any.whl", hash = "sha256:ad4aaf15e718fe0c54effbf510e1d9c7259f1252194c7192107848b06d8d2af8", size = 620018, upload-time = "2026-06-12T18:03:10.159Z" }, -] - -[[package]] -name = "google-cloud-speech" -version = "2.40.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/5a/c1/5dc9795314f4aefea0b01b02e9f5486a198341ecc15fe47f89a61c68df63/google_cloud_speech-2.40.0.tar.gz", hash = "sha256:e89e688e4ce0b926754038bf992d0d0f065c5f1c3503bb20e6c46d08b63658fc", size = 404366, upload-time = "2026-06-03T16:13:59.506Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/78/afeca8d597fab54bdd823f857aad15d6f9c4628ff3cb72aa237d01700721/google_cloud_speech-2.40.0-py3-none-any.whl", hash = "sha256:7cc0302b3b9ca33d2eae9669da94a44316601a240942895362ac70e765b9f39c", size = 345427, upload-time = "2026-06-03T16:12:40.909Z" }, -] - -[[package]] -name = "google-cloud-storage" -version = "3.4.1" -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/bd/ef/7cefdca67a6c8b3af0ec38612f9e78e5a9f6179dd91352772ae1a9849246/google_cloud_storage-3.4.1.tar.gz", hash = "sha256:6f041a297e23a4b485fad8c305a7a6e6831855c208bcbe74d00332a909f82268", size = 17238203, upload-time = "2025-10-08T18:43:39.665Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/6e/b47d83d3a35231c6232566341b0355cce78fd4e6988a7343725408547b2c/google_cloud_storage-3.4.1-py3-none-any.whl", hash = "sha256:972764cc0392aa097be8f49a5354e22eb47c3f62370067fb1571ffff4a1c1189", size = 290142, upload-time = "2025-10-08T18:43:37.524Z" }, -] - -[[package]] -name = "google-cloud-trace" -version = "1.19.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/89/7b/c2a5848c4722373c92b500b65e6308ad89ca0c7c01054e0d948c58c107f2/google_cloud_trace-1.19.0.tar.gz", hash = "sha256:58293c6efcee6c74bb854ff01b008823bef66845c14f15ffa5209d545098a65d", size = 103875, upload-time = "2026-03-26T22:18:18.123Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/91/0090acafa7d2caf1bf0d7222d42935e118164a539f9f9a00a814afa63fa1/google_cloud_trace-1.19.0-py3-none-any.whl", hash = "sha256:59604c4c775c40af31b367df6bada0af34518cc35ac8cfedecd43898a120c51d", size = 108454, upload-time = "2026-03-26T22:14:32.631Z" }, -] - -[[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.75.0" +version = "2.12.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1581,21 +1101,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9d/59/3ed61240ef20b3ae6ed54e82c6f8b6d1f194947bc6679679dd6cdb037594/google_genai-1.75.0.tar.gz", hash = "sha256:56bac3991b311c93f980c0a2abcd287b672146905df1fbd71c92ed633d5a07cf", size = 539039, upload-time = "2026-05-04T22:48:54.857Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/b6/552d40e96da22921eb1fead7c14b00b5b5473a20e45959488660fab35ee2/google_genai-1.75.0-py3-none-any.whl", hash = "sha256:8dc4c096e7d6288c3087f6893f582fe52468932464781edb8193bd92b9fefb2c", size = 793726, upload-time = "2026-05-04T22:48:53.033Z" }, -] - -[[package]] -name = "google-resumable-media" -version = "2.10.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-crc32c" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/48/f8/1ca5781d6be9cb9f73f7d40f4958c4bd1226a60598e3e39e1d6aaf838c4b/google_resumable_media-2.10.0.tar.gz", hash = "sha256:e324bc9d0fdae4c52a08ae90456edc4e71ece858399e1217ac0eb3a51d6bc6ee", size = 2164570, upload-time = "2026-06-03T16:14:26.103Z" } +sdist = { url = "https://files.pythonhosted.org/packages/96/59/9ea84cbeb8f09694564d3b0ee9dd59003551b308d47b61f251415df93982/google_genai-2.12.1.tar.gz", hash = "sha256:78c25217885d63dc430ca7c4526853512b164a25a93a8a0d0af5b85971aa1db0", size = 636710, upload-time = "2026-07-16T16:15:02.035Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/d8/00c6854ac1512bb9eaf13bd3f8f28222f7674947fc510a4ff7616f2efc80/google_resumable_media-2.10.0-py3-none-any.whl", hash = "sha256:88152884bee37b2bf36a0ab81ad8c7fd12212c9803dd981d77c1b35b02d34e7c", size = 81533, upload-time = "2026-06-03T16:13:12.51Z" }, + { url = "https://files.pythonhosted.org/packages/b6/b4/1369fb413fc2ba7f78acace5590b6e9990c52ab5d1d166aafaa1ae2c28c8/google_genai-2.12.1-py3-none-any.whl", hash = "sha256:686d5ec39bda345151d3ed1bac3915f01f49138b1ea519af2eb98f11cc55ebc4", size = 1023403, upload-time = "2026-07-16T16:14:59.79Z" }, ] [[package]] @@ -1610,11 +1118,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e7/c8/e2645aa8ed02fd4c7a2f59d68783b65b1f3cbdfe39a6308e156509d1fee8/googleapis_common_protos-1.75.0-py3-none-any.whl", hash = "sha256:961ed60399c457ceb0ee8f285a84c870aabc9c6a832b9d37bb281b5bebde43ed", size = 300631, upload-time = "2026-05-07T08:03:30.345Z" }, ] -[package.optional-dependencies] -grpc = [ - { name = "grpcio" }, -] - [[package]] name = "graphql-core" version = "3.2.8" @@ -1708,32 +1211,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl", hash = "sha256:925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1", size = 142357, upload-time = "2026-03-27T11:34:46.275Z" }, ] -[[package]] -name = "grpc-google-iam-v1" -version = "0.14.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "googleapis-common-protos", extra = ["grpc"] }, - { name = "grpcio" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/44/4f/d098419ad0bfc06c9ce440575f05aa22d8973b6c276e86ac7890093d3c37/grpc_google_iam_v1-0.14.4.tar.gz", hash = "sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038", size = 23706, upload-time = "2026-04-01T01:57:49.813Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/89/22/c2dd50c09bf679bd38173656cd4402d2511e563b33bc88f90009cf50613c/grpc_google_iam_v1-0.14.4-py3-none-any.whl", hash = "sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964", size = 32675, upload-time = "2026-04-01T01:57:47.69Z" }, -] - -[[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.80.0" @@ -1795,20 +1272,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e5/8c/bbe6baf2557262834f2070cf668515fa308b2d38a4bbf771f8f7872a7036/grpcio-1.80.0-cp314-cp314-win_amd64.whl", hash = "sha256:3b01e1f5464c583d2f567b2e46ff0d516ef979978f72091fd81f5ab7fa6e2e7f", size = 5019457, upload-time = "2026-03-30T08:48:37.308Z" }, ] -[[package]] -name = "grpcio-status" -version = "1.71.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "googleapis-common-protos" }, - { name = "grpcio" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fd/d1/b6e9877fedae3add1afdeae1f89d1927d296da9cf977eca0eb08fb8a460e/grpcio_status-1.71.2.tar.gz", hash = "sha256:c7a97e176df71cdc2c179cd1847d7fc86cca5832ad12e9798d7fed6b7a1aab50", size = 13677, upload-time = "2025-06-28T04:24:05.426Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/67/58/317b0134129b556a93a3b0afe00ee675b5657f0155509e22fcb853bafe2d/grpcio_status-1.71.2-py3-none-any.whl", hash = "sha256:803c98cb6a8b7dc6dbb785b1111aed739f241ab5e9da0bba96888aa74704cfd3", size = 14424, upload-time = "2025-06-28T04:23:42.136Z" }, -] - [[package]] name = "h11" version = "0.16.0" @@ -1863,18 +1326,6 @@ 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.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pyparsing" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c1/1f/e86365613582c027dda5ddb64e1010e57a3d53e99ab8a72093fa13d565ec/httplib2-0.31.2.tar.gz", hash = "sha256:385e0869d7397484f4eab426197a4c020b606edd43372492337c0b4010ae5d24", size = 250800, upload-time = "2026-01-23T11:04:44.165Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/90/fd509079dfcab01102c0fdd87f3a9506894bc70afcf9e9785ef6b2b3aff6/httplib2-0.31.2-py3-none-any.whl", hash = "sha256:dbf0c2fa3862acf3c55c078ea9c0bc4481d7dc5117cae71be9514912cf9f8349", size = 91099, upload-time = "2026-01-23T11:04:42.78Z" }, -] - [[package]] name = "httpx" version = "0.28.1" @@ -2455,18 +1906,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1c/38/e6a4abb062e039d18d59538cc4e6fc370c2c10cd2bff4a2e546acb69dcb9/litellm-1.85.0-py3-none-any.whl", hash = "sha256:2bb449153610691faffd76f5b94a8c29e4b66fc5394156ebf54fd4fe92759b1a", size = 16978229, upload-time = "2026-05-17T01:59:11.902Z" }, ] -[[package]] -name = "mako" -version = "1.3.12" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markupsafe" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/00/62/791b31e69ae182791ec67f04850f2f062716bbd205483d63a215f3e062d3/mako-1.3.12.tar.gz", hash = "sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a", size = 400219, upload-time = "2026-04-28T19:01:08.512Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/b1/a0ec7a5a9db730a08daef1fdfb8090435b82465abbf758a596f0ea88727e/mako-1.3.12-py3-none-any.whl", hash = "sha256:8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9", size = 78521, upload-time = "2026-04-28T19:01:10.393Z" }, -] - [[package]] name = "markdown-it-py" version = "4.2.0" @@ -2611,120 +2050,6 @@ 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.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/91/1a/edb23803a168f070ded7a3014c6d706f63b90c84ccc024f89d794a3b7a6d/mmh3-5.2.1.tar.gz", hash = "sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad", size = 33775, upload-time = "2026-03-05T15:55:57.716Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/bb/88ee54afa5644b0f35ab5b435f208394feb963e5bb47c4e404deb625ffa4/mmh3-5.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f", size = 56080, upload-time = "2026-03-05T15:53:40.452Z" }, - { url = "https://files.pythonhosted.org/packages/cc/bf/5404c2fd6ac84819e8ff1b7e34437b37cf55a2b11318894909e7bb88de3f/mmh3-5.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb", size = 40462, upload-time = "2026-03-05T15:53:41.751Z" }, - { url = "https://files.pythonhosted.org/packages/de/0b/52bffad0b52ae4ea53e222b594bd38c08ecac1fc410323220a7202e43da5/mmh3-5.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c", size = 40077, upload-time = "2026-03-05T15:53:42.753Z" }, - { url = "https://files.pythonhosted.org/packages/a0/9e/326c93d425b9fa4cbcdc71bc32aaba520db37577d632a24d25d927594eca/mmh3-5.2.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045", size = 95302, upload-time = "2026-03-05T15:53:43.867Z" }, - { url = "https://files.pythonhosted.org/packages/c6/b1/e20d5f0d19c4c0f3df213fa7dcfa0942c4fb127d38e11f398ae8ddf6cccc/mmh3-5.2.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f", size = 101174, upload-time = "2026-03-05T15:53:45.194Z" }, - { url = "https://files.pythonhosted.org/packages/7f/4a/1a9bb3e33c18b1e1cee2c249a3053c4d4d9c93ecb30738f39a62249a7e86/mmh3-5.2.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386", size = 103979, upload-time = "2026-03-05T15:53:46.334Z" }, - { url = "https://files.pythonhosted.org/packages/ff/8d/dab9ee7545429e7acdd38d23d0104471d31de09a0c695f1b751e0ff34532/mmh3-5.2.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a", size = 110898, upload-time = "2026-03-05T15:53:47.443Z" }, - { url = "https://files.pythonhosted.org/packages/72/08/408f11af7fe9e76b883142bb06536007cc7f237be2a5e9ad4e837716e627/mmh3-5.2.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0", size = 118308, upload-time = "2026-03-05T15:53:49.1Z" }, - { url = "https://files.pythonhosted.org/packages/86/2d/0551be7fe0000736d9ad12ffa1f130d7a0c17b49193d6dc41c82bd9404c6/mmh3-5.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb", size = 101671, upload-time = "2026-03-05T15:53:50.317Z" }, - { url = "https://files.pythonhosted.org/packages/44/17/6e4f80c4e6ad590139fa2017c3aeca54e7cc9ef68e08aa142a0c90f40a97/mmh3-5.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890", size = 96682, upload-time = "2026-03-05T15:53:51.48Z" }, - { url = "https://files.pythonhosted.org/packages/ad/a7/b82fccd38c1fa815de72e94ebe9874562964a10e21e6c1bc3b01d3f15a0e/mmh3-5.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a", size = 110287, upload-time = "2026-03-05T15:53:52.68Z" }, - { url = "https://files.pythonhosted.org/packages/a8/a1/2644069031c8cec0be46f0346f568a53f42fddd843f03cc890306699c1e2/mmh3-5.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5", size = 111899, upload-time = "2026-03-05T15:53:53.791Z" }, - { url = "https://files.pythonhosted.org/packages/51/7b/6614f3eb8fb33f931fa7616c6d477247e48ec6c5082b02eeeee998cffa94/mmh3-5.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57", size = 100078, upload-time = "2026-03-05T15:53:55.234Z" }, - { url = "https://files.pythonhosted.org/packages/27/9a/dd4d5a5fb893e64f71b42b69ecae97dd78db35075412488b24036bc5599c/mmh3-5.2.1-cp310-cp310-win32.whl", hash = "sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518", size = 40756, upload-time = "2026-03-05T15:53:56.319Z" }, - { url = "https://files.pythonhosted.org/packages/c9/34/0b25889450f8aeffcec840aa73251e853f059c1b72ed1d1c027b956f95f5/mmh3-5.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f", size = 41519, upload-time = "2026-03-05T15:53:57.41Z" }, - { url = "https://files.pythonhosted.org/packages/fd/31/8fd42e3c526d0bcb1db7f569c0de6729e180860a0495e387a53af33c2043/mmh3-5.2.1-cp310-cp310-win_arm64.whl", hash = "sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0", size = 39285, upload-time = "2026-03-05T15:53:58.697Z" }, - { url = "https://files.pythonhosted.org/packages/65/d7/3312a59df3c1cdd783f4cf0c4ee8e9decff9c5466937182e4cc7dbbfe6c5/mmh3-5.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450", size = 56082, upload-time = "2026-03-05T15:53:59.702Z" }, - { url = "https://files.pythonhosted.org/packages/61/96/6f617baa098ca0d2989bfec6d28b5719532cd8d8848782662f5b755f657f/mmh3-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0", size = 40458, upload-time = "2026-03-05T15:54:01.548Z" }, - { url = "https://files.pythonhosted.org/packages/c1/b4/9cd284bd6062d711e13d26c04d4778ab3f690c1c38a4563e3c767ec8802e/mmh3-5.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082", size = 40079, upload-time = "2026-03-05T15:54:02.743Z" }, - { url = "https://files.pythonhosted.org/packages/f6/09/a806334ce1d3d50bf782b95fcee8b3648e1e170327d4bb7b4bad2ad7d956/mmh3-5.2.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997", size = 97242, upload-time = "2026-03-05T15:54:04.536Z" }, - { url = "https://files.pythonhosted.org/packages/ee/93/723e317dd9e041c4dc4566a2eb53b01ad94de31750e0b834f1643905e97c/mmh3-5.2.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d", size = 103082, upload-time = "2026-03-05T15:54:06.387Z" }, - { url = "https://files.pythonhosted.org/packages/61/b5/f96121e69cc48696075071531cf574f112e1ffd08059f4bffb41210e6fc5/mmh3-5.2.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e", size = 106054, upload-time = "2026-03-05T15:54:07.506Z" }, - { url = "https://files.pythonhosted.org/packages/82/49/192b987ec48d0b2aecf8ac285a9b11fbc00030f6b9c694664ae923458dde/mmh3-5.2.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d", size = 112910, upload-time = "2026-03-05T15:54:09.403Z" }, - { url = "https://files.pythonhosted.org/packages/cf/a1/03e91fd334ed0144b83343a76eb11f17434cd08f746401488cfeafb2d241/mmh3-5.2.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4", size = 120551, upload-time = "2026-03-05T15:54:10.587Z" }, - { url = "https://files.pythonhosted.org/packages/93/b9/b89a71d2ff35c3a764d1c066c7313fc62c7cc48fa48a4b3b0304a4a0146f/mmh3-5.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15", size = 99096, upload-time = "2026-03-05T15:54:11.76Z" }, - { url = "https://files.pythonhosted.org/packages/36/b5/613772c1c6ed5f7b63df55eb131e887cc43720fec392777b95a79d34e640/mmh3-5.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503", size = 98524, upload-time = "2026-03-05T15:54:13.122Z" }, - { url = "https://files.pythonhosted.org/packages/5e/0e/1524566fe8eaf871e4f7bc44095929fcd2620488f402822d848df19d679c/mmh3-5.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2", size = 106239, upload-time = "2026-03-05T15:54:14.601Z" }, - { url = "https://files.pythonhosted.org/packages/04/94/21adfa7d90a7a697137ad6de33eeff6445420ca55e433a5d4919c79bc3b5/mmh3-5.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1", size = 109797, upload-time = "2026-03-05T15:54:15.819Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e6/1aacc3a219e1aa62fa65669995d4a3562b35be5200ec03680c7e4bec9676/mmh3-5.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38", size = 97228, upload-time = "2026-03-05T15:54:16.992Z" }, - { url = "https://files.pythonhosted.org/packages/f1/b9/5e4cca8dcccf298add0a27f3c357bc8cf8baf821d35cdc6165e4bd5a48b0/mmh3-5.2.1-cp311-cp311-win32.whl", hash = "sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728", size = 40751, upload-time = "2026-03-05T15:54:18.714Z" }, - { url = "https://files.pythonhosted.org/packages/72/fc/5b11d49247f499bcda591171e9cf3b6ee422b19e70aa2cef2e0ae65ca3b9/mmh3-5.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a", size = 41517, upload-time = "2026-03-05T15:54:19.764Z" }, - { url = "https://files.pythonhosted.org/packages/8a/5f/2a511ee8a1c2a527c77726d5231685b72312c5a1a1b7639ad66a9652aa84/mmh3-5.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f", size = 39287, upload-time = "2026-03-05T15:54:20.904Z" }, - { url = "https://files.pythonhosted.org/packages/92/94/bc5c3b573b40a328c4d141c20e399039ada95e5e2a661df3425c5165fd84/mmh3-5.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1", size = 56087, upload-time = "2026-03-05T15:54:21.92Z" }, - { url = "https://files.pythonhosted.org/packages/f6/80/64a02cc3e95c3af0aaa2590849d9ed24a9f14bb93537addde688e039b7c3/mmh3-5.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00", size = 40500, upload-time = "2026-03-05T15:54:22.953Z" }, - { url = "https://files.pythonhosted.org/packages/8b/72/e6d6602ce18adf4ddcd0e48f2e13590cc92a536199e52109f46f259d3c46/mmh3-5.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7", size = 40034, upload-time = "2026-03-05T15:54:23.943Z" }, - { url = "https://files.pythonhosted.org/packages/59/c2/bf4537a8e58e21886ef16477041238cab5095c836496e19fafc34b7445d2/mmh3-5.2.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b", size = 97292, upload-time = "2026-03-05T15:54:25.335Z" }, - { url = "https://files.pythonhosted.org/packages/e5/e2/51ed62063b44d10b06d975ac87af287729eeb5e3ed9772f7584a17983e90/mmh3-5.2.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006", size = 103274, upload-time = "2026-03-05T15:54:26.44Z" }, - { url = "https://files.pythonhosted.org/packages/75/ce/12a7524dca59eec92e5b31fdb13ede1e98eda277cf2b786cf73bfbc24e81/mmh3-5.2.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825", size = 106158, upload-time = "2026-03-05T15:54:28.578Z" }, - { url = "https://files.pythonhosted.org/packages/86/1f/d3ba6dd322d01ab5d44c46c8f0c38ab6bbbf9b5e20e666dfc05bf4a23604/mmh3-5.2.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a", size = 113005, upload-time = "2026-03-05T15:54:29.767Z" }, - { url = "https://files.pythonhosted.org/packages/b6/a9/15d6b6f913294ea41b44d901741298e3718e1cb89ee626b3694625826a43/mmh3-5.2.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b", size = 120744, upload-time = "2026-03-05T15:54:30.931Z" }, - { url = "https://files.pythonhosted.org/packages/76/b3/70b73923fd0284c439860ff5c871b20210dfdbe9a6b9dd0ee6496d77f174/mmh3-5.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166", size = 99111, upload-time = "2026-03-05T15:54:32.353Z" }, - { url = "https://files.pythonhosted.org/packages/dd/38/99f7f75cd27d10d8b899a1caafb9d531f3903e4d54d572220e3d8ac35e89/mmh3-5.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16", size = 98623, upload-time = "2026-03-05T15:54:33.801Z" }, - { url = "https://files.pythonhosted.org/packages/fd/68/6e292c0853e204c44d2f03ea5f090be3317a0e2d9417ecb62c9eb27687df/mmh3-5.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211", size = 106437, upload-time = "2026-03-05T15:54:35.177Z" }, - { url = "https://files.pythonhosted.org/packages/dd/c6/fedd7284c459cfb58721d461fcf5607a4c1f5d9ab195d113d51d10164d16/mmh3-5.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000", size = 110002, upload-time = "2026-03-05T15:54:36.673Z" }, - { url = "https://files.pythonhosted.org/packages/3b/ac/ca8e0c19a34f5b71390171d2ff0b9f7f187550d66801a731bb68925126a4/mmh3-5.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5", size = 97507, upload-time = "2026-03-05T15:54:37.804Z" }, - { url = "https://files.pythonhosted.org/packages/df/94/6ebb9094cfc7ac5e7950776b9d13a66bb4a34f83814f32ba2abc9494fc68/mmh3-5.2.1-cp312-cp312-win32.whl", hash = "sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025", size = 40773, upload-time = "2026-03-05T15:54:40.077Z" }, - { url = "https://files.pythonhosted.org/packages/5b/3c/cd3527198cf159495966551c84a5f36805a10ac17b294f41f67b83f6a4d6/mmh3-5.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00", size = 41560, upload-time = "2026-03-05T15:54:41.148Z" }, - { url = "https://files.pythonhosted.org/packages/15/96/6fe5ebd0f970a076e3ed5512871ce7569447b962e96c125528a2f9724470/mmh3-5.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc", size = 39313, upload-time = "2026-03-05T15:54:42.171Z" }, - { url = "https://files.pythonhosted.org/packages/25/a5/9daa0508a1569a54130f6198d5462a92deda870043624aa3ea72721aa765/mmh3-5.2.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e", size = 40832, upload-time = "2026-03-05T15:54:43.212Z" }, - { url = "https://files.pythonhosted.org/packages/0a/6b/3230c6d80c1f4b766dedf280a92c2241e99f87c1504ff74205ec8cebe451/mmh3-5.2.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d", size = 41964, upload-time = "2026-03-05T15:54:44.204Z" }, - { url = "https://files.pythonhosted.org/packages/62/fb/648bfddb74a872004b6ee751551bfdda783fe6d70d2e9723bad84dbe5311/mmh3-5.2.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6", size = 39114, upload-time = "2026-03-05T15:54:45.205Z" }, - { url = "https://files.pythonhosted.org/packages/95/c2/ab7901f87af438468b496728d11264cb397b3574d41506e71b92128e0373/mmh3-5.2.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f", size = 39819, upload-time = "2026-03-05T15:54:46.509Z" }, - { url = "https://files.pythonhosted.org/packages/2f/ed/6f88dda0df67de1612f2e130ffea34cf84aaee5bff5b0aff4dbff2babe34/mmh3-5.2.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8", size = 40330, upload-time = "2026-03-05T15:54:47.864Z" }, - { url = "https://files.pythonhosted.org/packages/3d/66/7516d23f53cdf90f43fce24ab80c28f45e6851d78b46bef8c02084edf583/mmh3-5.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6", size = 56078, upload-time = "2026-03-05T15:54:48.9Z" }, - { url = "https://files.pythonhosted.org/packages/bc/34/4d152fdf4a91a132cb226b671f11c6b796eada9ab78080fb5ce1e95adaab/mmh3-5.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9", size = 40498, upload-time = "2026-03-05T15:54:49.942Z" }, - { url = "https://files.pythonhosted.org/packages/d4/4c/8e3af1b6d85a299767ec97bd923f12b06267089c1472c27c1696870d1175/mmh3-5.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03", size = 40033, upload-time = "2026-03-05T15:54:50.994Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f2/966ea560e32578d453c9e9db53d602cbb1d0da27317e232afa7c38ceba11/mmh3-5.2.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b", size = 97320, upload-time = "2026-03-05T15:54:52.072Z" }, - { url = "https://files.pythonhosted.org/packages/bb/0d/2c5f9893b38aeb6b034d1a44ecd55a010148054f6a516abe53b5e4057297/mmh3-5.2.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5", size = 103299, upload-time = "2026-03-05T15:54:53.569Z" }, - { url = "https://files.pythonhosted.org/packages/1c/fc/2ebaef4a4d4376f89761274dc274035ffd96006ab496b4ee5af9b08f21a9/mmh3-5.2.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593", size = 106222, upload-time = "2026-03-05T15:54:55.092Z" }, - { url = "https://files.pythonhosted.org/packages/57/09/ea7ffe126d0ba0406622602a2d05e1e1a6841cc92fc322eb576c95b27fad/mmh3-5.2.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4", size = 113048, upload-time = "2026-03-05T15:54:56.305Z" }, - { url = "https://files.pythonhosted.org/packages/85/57/9447032edf93a64aa9bef4d9aa596400b1756f40411890f77a284f6293ca/mmh3-5.2.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1", size = 120742, upload-time = "2026-03-05T15:54:57.453Z" }, - { url = "https://files.pythonhosted.org/packages/53/82/a86cc87cc88c92e9e1a598fee509f0409435b57879a6129bf3b3e40513c7/mmh3-5.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104", size = 99132, upload-time = "2026-03-05T15:54:58.583Z" }, - { url = "https://files.pythonhosted.org/packages/54/f7/6b16eb1b40ee89bb740698735574536bc20d6cdafc65ae702ea235578e05/mmh3-5.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d", size = 98686, upload-time = "2026-03-05T15:55:00.078Z" }, - { url = "https://files.pythonhosted.org/packages/e8/88/a601e9f32ad1410f438a6d0544298ea621f989bd34a0731a7190f7dec799/mmh3-5.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f", size = 106479, upload-time = "2026-03-05T15:55:01.532Z" }, - { url = "https://files.pythonhosted.org/packages/d6/5c/ce29ae3dfc4feec4007a437a1b7435fb9507532a25147602cd5b52be86db/mmh3-5.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2", size = 110030, upload-time = "2026-03-05T15:55:02.934Z" }, - { url = "https://files.pythonhosted.org/packages/13/30/ae444ef2ff87c805d525da4fa63d27cda4fe8a48e77003a036b8461cfd5c/mmh3-5.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a", size = 97536, upload-time = "2026-03-05T15:55:04.135Z" }, - { url = "https://files.pythonhosted.org/packages/4b/f9/dc3787ee5c813cc27fe79f45ad4500d9b5437f23a7402435cc34e07c7718/mmh3-5.2.1-cp313-cp313-win32.whl", hash = "sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b", size = 40769, upload-time = "2026-03-05T15:55:05.277Z" }, - { url = "https://files.pythonhosted.org/packages/43/67/850e0b5a1e97799822ebfc4ca0e8c6ece3ed8baf7dcdf64de817dfdda2ca/mmh3-5.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229", size = 41563, upload-time = "2026-03-05T15:55:06.283Z" }, - { url = "https://files.pythonhosted.org/packages/c0/cc/98c90b28e1da5458e19fbfaf4adb5289208d3bfccd45dd14eab216a2f0bb/mmh3-5.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d", size = 39310, upload-time = "2026-03-05T15:55:07.323Z" }, - { url = "https://files.pythonhosted.org/packages/63/b4/65bc1fb2bb7f83e91c30865023b1847cf89a5f237165575e8c83aa536584/mmh3-5.2.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227", size = 40794, upload-time = "2026-03-05T15:55:09.773Z" }, - { url = "https://files.pythonhosted.org/packages/c4/86/7168b3d83be8eb553897b1fac9da8bbb06568e5cfe555ffc329ebb46f59d/mmh3-5.2.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0", size = 41923, upload-time = "2026-03-05T15:55:10.924Z" }, - { url = "https://files.pythonhosted.org/packages/bf/9b/b653ab611c9060ce8ff0ba25c0226757755725e789292f3ca138a58082cd/mmh3-5.2.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b", size = 39131, upload-time = "2026-03-05T15:55:11.961Z" }, - { url = "https://files.pythonhosted.org/packages/9b/b4/5a2e0d34ab4d33543f01121e832395ea510132ea8e52cdf63926d9d81754/mmh3-5.2.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966", size = 39825, upload-time = "2026-03-05T15:55:13.013Z" }, - { url = "https://files.pythonhosted.org/packages/bd/69/81699a8f39a3f8d368bec6443435c0c392df0d200ad915bf0d222b588e03/mmh3-5.2.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b", size = 40344, upload-time = "2026-03-05T15:55:14.026Z" }, - { url = "https://files.pythonhosted.org/packages/0c/b3/71c8c775807606e8fd8acc5c69016e1caf3200d50b50b6dd4b40ce10b76c/mmh3-5.2.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8", size = 56291, upload-time = "2026-03-05T15:55:15.137Z" }, - { url = "https://files.pythonhosted.org/packages/6f/75/2c24517d4b2ce9e4917362d24f274d3d541346af764430249ddcc4cb3a08/mmh3-5.2.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7", size = 40575, upload-time = "2026-03-05T15:55:16.518Z" }, - { url = "https://files.pythonhosted.org/packages/bf/b9/e4a360164365ac9f07a25f0f7928e3a66eb9ecc989384060747aa170e6aa/mmh3-5.2.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e", size = 40052, upload-time = "2026-03-05T15:55:17.735Z" }, - { url = "https://files.pythonhosted.org/packages/97/ca/120d92223a7546131bbbc31c9174168ee7a73b1366f5463ffe69d9e691fe/mmh3-5.2.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74", size = 97311, upload-time = "2026-03-05T15:55:18.959Z" }, - { url = "https://files.pythonhosted.org/packages/b6/71/c1a60c1652b8813ef9de6d289784847355417ee0f2980bca002fe87f4ae5/mmh3-5.2.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc", size = 103279, upload-time = "2026-03-05T15:55:20.448Z" }, - { url = "https://files.pythonhosted.org/packages/48/29/ad97f4be1509cdcb28ae32c15593ce7c415db47ace37f8fad35b493faa9a/mmh3-5.2.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617", size = 106290, upload-time = "2026-03-05T15:55:21.6Z" }, - { url = "https://files.pythonhosted.org/packages/77/29/1f86d22e281bd8827ba373600a4a8b0c0eae5ca6aa55b9a8c26d2a34decc/mmh3-5.2.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2", size = 113116, upload-time = "2026-03-05T15:55:22.826Z" }, - { url = "https://files.pythonhosted.org/packages/a7/7c/339971ea7ed4c12d98f421f13db3ea576a9114082ccb59d2d1a0f00ccac1/mmh3-5.2.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312", size = 120740, upload-time = "2026-03-05T15:55:24.3Z" }, - { url = "https://files.pythonhosted.org/packages/e4/92/3c7c4bdb8e926bb3c972d1e2907d77960c1c4b250b41e8366cf20c6e4373/mmh3-5.2.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb", size = 99143, upload-time = "2026-03-05T15:55:25.456Z" }, - { url = "https://files.pythonhosted.org/packages/df/0a/33dd8706e732458c8375eae63c981292de07a406bad4ec03e5269654aa2c/mmh3-5.2.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a", size = 98703, upload-time = "2026-03-05T15:55:26.723Z" }, - { url = "https://files.pythonhosted.org/packages/51/04/76bbce05df76cbc3d396f13b2ea5b1578ef02b6a5187e132c6c33f99d596/mmh3-5.2.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105", size = 106484, upload-time = "2026-03-05T15:55:28.214Z" }, - { url = "https://files.pythonhosted.org/packages/d3/8f/c6e204a2c70b719c1f62ffd9da27aef2dddcba875ea9c31ca0e87b975a46/mmh3-5.2.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a", size = 110012, upload-time = "2026-03-05T15:55:29.532Z" }, - { url = "https://files.pythonhosted.org/packages/e3/37/7181efd8e39db386c1ebc3e6b7d1f702a09d7c1197a6f2742ed6b5c16597/mmh3-5.2.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd", size = 97508, upload-time = "2026-03-05T15:55:31.01Z" }, - { url = "https://files.pythonhosted.org/packages/42/0f/afa7ca2615fd85e1469474bb860e381443d0b868c083b62b41cb1d7ca32f/mmh3-5.2.1-cp314-cp314-win32.whl", hash = "sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4", size = 41387, upload-time = "2026-03-05T15:55:32.403Z" }, - { url = "https://files.pythonhosted.org/packages/71/0d/46d42a260ee1357db3d486e6c7a692e303c017968e14865e00efa10d09fc/mmh3-5.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb", size = 42101, upload-time = "2026-03-05T15:55:33.646Z" }, - { url = "https://files.pythonhosted.org/packages/a4/7b/848a8378059d96501a41159fca90d6a99e89736b0afbe8e8edffeac8c74b/mmh3-5.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe", size = 39836, upload-time = "2026-03-05T15:55:35.026Z" }, - { url = "https://files.pythonhosted.org/packages/27/61/1dabea76c011ba8547c25d30c91c0ec22544487a8750997a27a0c9e1180b/mmh3-5.2.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba", size = 57727, upload-time = "2026-03-05T15:55:36.162Z" }, - { url = "https://files.pythonhosted.org/packages/b7/32/731185950d1cf2d5e28979cc8593016ba1619a295faba10dda664a4931b5/mmh3-5.2.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00", size = 41308, upload-time = "2026-03-05T15:55:37.254Z" }, - { url = "https://files.pythonhosted.org/packages/76/aa/66c76801c24b8c9418b4edde9b5e57c75e72c94e29c48f707e3962534f18/mmh3-5.2.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8", size = 40758, upload-time = "2026-03-05T15:55:38.61Z" }, - { url = "https://files.pythonhosted.org/packages/9e/bb/79a1f638a02f0ae389f706d13891e2fbf7d8c0a22ecde67ba828951bb60a/mmh3-5.2.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc", size = 109670, upload-time = "2026-03-05T15:55:40.13Z" }, - { url = "https://files.pythonhosted.org/packages/26/94/8cd0e187a288985bcfc79bf5144d1d712df9dee74365f59d26e3a1865be6/mmh3-5.2.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f", size = 117399, upload-time = "2026-03-05T15:55:42.076Z" }, - { url = "https://files.pythonhosted.org/packages/42/94/dfea6059bd5c5beda565f58a4096e43f4858fb6d2862806b8bbd12cbb284/mmh3-5.2.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44", size = 120386, upload-time = "2026-03-05T15:55:43.481Z" }, - { url = "https://files.pythonhosted.org/packages/47/cb/f9c45e62aaa67220179f487772461d891bb582bb2f9783c944832c60efd9/mmh3-5.2.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7", size = 125924, upload-time = "2026-03-05T15:55:44.638Z" }, - { url = "https://files.pythonhosted.org/packages/a5/83/fe54a4a7c11bc9f623dfc1707decd034245602b076dfc1dcc771a4163170/mmh3-5.2.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c", size = 135280, upload-time = "2026-03-05T15:55:45.866Z" }, - { url = "https://files.pythonhosted.org/packages/97/67/fe7e9e9c143daddd210cd22aef89cbc425d58ecf238d2b7d9eb0da974105/mmh3-5.2.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac", size = 110050, upload-time = "2026-03-05T15:55:47.074Z" }, - { url = "https://files.pythonhosted.org/packages/43/c4/6d4b09fcbef80794de447c9378e39eefc047156b290fa3dd2d5257ca8227/mmh3-5.2.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912", size = 111158, upload-time = "2026-03-05T15:55:48.239Z" }, - { url = "https://files.pythonhosted.org/packages/81/a6/ca51c864bdb30524beb055a6d8826db3906af0834ec8c41d097a6e8573d5/mmh3-5.2.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf", size = 116890, upload-time = "2026-03-05T15:55:49.405Z" }, - { url = "https://files.pythonhosted.org/packages/cc/04/5a1fe2e2ad843d03e89af25238cbc4f6840a8bb6c4329a98ab694c71deda/mmh3-5.2.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d", size = 123121, upload-time = "2026-03-05T15:55:50.61Z" }, - { url = "https://files.pythonhosted.org/packages/af/4d/3c820c6f4897afd25905270a9f2330a23f77a207ea7356f7aadace7273c0/mmh3-5.2.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18", size = 110187, upload-time = "2026-03-05T15:55:52.143Z" }, - { url = "https://files.pythonhosted.org/packages/21/54/1d71cd143752361c0aebef16ad3f55926a6faf7b112d355745c1f8a25f7f/mmh3-5.2.1-cp314-cp314t-win32.whl", hash = "sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82", size = 41934, upload-time = "2026-03-05T15:55:53.564Z" }, - { url = "https://files.pythonhosted.org/packages/9d/e4/63a2a88f31d93dea03947cccc2a076946857e799ea4f7acdecbf43b324aa/mmh3-5.2.1-cp314-cp314t-win_amd64.whl", hash = "sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb", size = 43036, upload-time = "2026-03-05T15:55:55.252Z" }, - { url = "https://files.pythonhosted.org/packages/a0/0f/59204bf136d1201f8d7884cfbaf7498c5b4674e87a4c693f9bde63741ce1/mmh3-5.2.1-cp314-cp314t-win_arm64.whl", hash = "sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b", size = 40391, upload-time = "2026-03-05T15:55:56.697Z" }, -] - [[package]] name = "moto" version = "5.2.1" @@ -3145,51 +2470,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/29/59/3e7118ed140f76b0982ba4321bdaed1997a0473f9720de2d10788a577033/opentelemetry_api-1.41.1-py3-none-any.whl", hash = "sha256:a22df900e75c76dc08440710e51f52f1aa6b451b429298896023e60db5b3139f", size = 69007, upload-time = "2026-04-24T13:15:15.662Z" }, ] -[[package]] -name = "opentelemetry-exporter-gcp-logging" -version = "1.12.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/77/e4/95ecebaa1c5134adaa0d0374028b25e3b3c5c08535d29a66d39d372a3d11/opentelemetry_exporter_gcp_logging-1.12.0a0.tar.gz", hash = "sha256:586529dbbcae5e22b880f7c121fde3f0fe8ae997aba1bad53f13c20eeb27cb3a", size = 22521, upload-time = "2026-04-28T20:59:40.237Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/55/93/3a0a9a62db0b90029a8160774e791044c0566aa94d5160ce7bbce8abf242/opentelemetry_exporter_gcp_logging-1.12.0a0-py3-none-any.whl", hash = "sha256:2aca9b01b3248c2fa95d38d01aa71aca8e22f640c44dba36ca6b883930762971", size = 14207, upload-time = "2026-04-28T20:59:35.109Z" }, -] - -[[package]] -name = "opentelemetry-exporter-gcp-monitoring" -version = "1.12.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/ff/5d/f82b2858d00be6f91b917dc67ccf71688fa822448b2d26ace69b809f5835/opentelemetry_exporter_gcp_monitoring-1.12.0a0.tar.gz", hash = "sha256:2b285078cddd4af78a363a55b5478e89f7df6f15bba9139d3f484099e534df4c", size = 20839, upload-time = "2026-04-28T20:59:40.982Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/b5/1623886d049095bb5abcec0cd67a0e40c00ff1672a25f82ed9867f88c1e7/opentelemetry_exporter_gcp_monitoring-1.12.0a0-py3-none-any.whl", hash = "sha256:1a7daf8c9350d55010fa33d2c2f646655a03a81d0d8073a2ae0e066791d6177d", size = 13608, upload-time = "2026-04-28T20:59:36.315Z" }, -] - -[[package]] -name = "opentelemetry-exporter-gcp-trace" -version = "1.12.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/bf/55/32922e72d88421505383dfdba9c1ee6ad67253f94f2358f6e9dbc4ac3749/opentelemetry_exporter_gcp_trace-1.12.0.tar.gz", hash = "sha256:18c6e56fe123eed020d5005fdd819b196d64f651545bce1ca7e2e2cbaf9d343b", size = 18779, upload-time = "2026-04-28T20:59:41.974Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8c/68/c60e79992918eecb6de167e782c86946fdd5492bb163fe320f1a18959c3d/opentelemetry_exporter_gcp_trace-1.12.0-py3-none-any.whl", hash = "sha256:1538dab654bcb25e757ed34c94f27a2e30d90dc7deb3630f8d46d1111fcb3bad", size = 14013, upload-time = "2026-04-28T20:59:37.518Z" }, -] - [[package]] name = "opentelemetry-exporter-otlp-proto-common" version = "1.41.1" @@ -3220,24 +2500,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ac/f2/c54f33c92443d087703e57e52e55f22f111373a5c4c4aa349ea60efe512e/opentelemetry_exporter_otlp_proto_grpc-1.41.1-py3-none-any.whl", hash = "sha256:537926dcef951136992479af1d9cd88f25e33d56c530e9f020ed57774dca2f94", size = 20297, upload-time = "2026-04-24T13:15:20.212Z" }, ] -[[package]] -name = "opentelemetry-exporter-otlp-proto-http" -version = "1.41.1" -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/33/5b/9d3c7f70cca10136ba82a81e738dee626c8e7fc61c6887ea9a58bf34c606/opentelemetry_exporter_otlp_proto_http-1.41.1.tar.gz", hash = "sha256:4747a9604c8550ab38c6fd6180e2fcb80de3267060bef2c306bad3cb443302bc", size = 24139, upload-time = "2026-04-24T13:15:42.977Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/4d/ef07ff2fc630849f2080ae0ae73a61f67257905b7ac79066640bfa0c5739/opentelemetry_exporter_otlp_proto_http-1.41.1-py3-none-any.whl", hash = "sha256:1a21e8f49c7a946d935551e90947d6c3eb39236723c6624401da0f33d68edcb4", size = 22673, upload-time = "2026-04-24T13:15:21.313Z" }, -] - [[package]] name = "opentelemetry-instrumentation" version = "0.62b1" @@ -3279,21 +2541,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e4/1e/5cd77035e3e82070e2265a63a760f715aacd3cb16dddc7efee913f297fcc/opentelemetry_proto-1.41.1-py3-none-any.whl", hash = "sha256:0496713b804d127a4147e32849fbaf5683fac8ee98550e8e7679cd706c289720", size = 72076, upload-time = "2026-04-24T13:15:32.542Z" }, ] -[[package]] -name = "opentelemetry-resourcedetector-gcp" -version = "1.12.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/21/ae/b62c5e986c9c7f908a15682ea173bcfcdc00403c0c85243ccbd30eca7fc2/opentelemetry_resourcedetector_gcp-1.12.0a0.tar.gz", hash = "sha256:d5e3f78283a272eb92547e00bbeff45b7332a34ae791a70ab4eba81af9bc3baf", size = 18797, upload-time = "2026-04-28T20:59:43.195Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/df/84/9db2999adbc41505af3e6717e8d958746778cbfc9e07ed9c670bf9d1e6db/opentelemetry_resourcedetector_gcp-1.12.0a0-py3-none-any.whl", hash = "sha256:e803688d14e2969fe816077be81f7b034368314d485863f12ce49daba7c81919", size = 18798, upload-time = "2026-04-28T20:59:39.257Z" }, -] - [[package]] name = "opentelemetry-sdk" version = "1.41.1" @@ -3828,18 +3075,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3a/ed/1cdcab6ba3d6ab7feca11fc14f0eeea80755bb53ef4e892079f31b10a25f/propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe", size = 14036, upload-time = "2026-05-08T21:02:10.673Z" }, ] -[[package]] -name = "proto-plus" -version = "1.28.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/56/e647b0c675392d2da368da7b6f158f7368b18542fd6f7d7400a2f39de000/proto_plus-1.28.0.tar.gz", hash = "sha256:38e5696342835b08fc116f30a25665b29531cda9d5d5643e9b81fc312385abd9", size = 57221, upload-time = "2026-05-07T08:04:50.811Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/20/b122d4626976acb81132036d2ad1bb35a1a8775fceb837ec30964622516a/proto_plus-1.28.0-py3-none-any.whl", hash = "sha256:a630604310899e73c59ec302e5765c058d412b2f090b9c79c8822589f14955b8", size = 50410, upload-time = "2026-05-07T08:03:31.962Z" }, -] - [[package]] name = "protobuf" version = "5.29.6" @@ -4783,84 +4018,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5e/f5/0c41cb68dcae6b7de4fac4188a3a9589e21fb31df21ea3a2e888db95e6c9/soupsieve-2.8.4-py3-none-any.whl", hash = "sha256:e7e6b0769c8f51ed59acab6e994b00621096cfb1c640a7509295987388fbaf65", size = 37304, upload-time = "2026-05-24T13:55:55.406Z" }, ] -[[package]] -name = "sqlalchemy" -version = "2.0.51" -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/02/f1/a7a892f18d4d224e6b26f706531eafccc41e37594d37d304786969ee13cb/sqlalchemy-2.0.51.tar.gz", hash = "sha256:804dccd8a4a6242c4e30ad961e540e18a588f6527202f2d6791b01845d59fdc9", size = 9912201, upload-time = "2026-06-15T15:41:20.012Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/71/76/b3ea1d8842e7b62c718a88d302809003d65ed82011460ca48907dde658c4/sqlalchemy-2.0.51-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e8203d2fbd5c6254692ef0a72c740d75b2f3c7ca345404f4c1a4604813c77c0", size = 2162087, upload-time = "2026-06-15T16:05:15.795Z" }, - { url = "https://files.pythonhosted.org/packages/6c/22/f19552eb7876774d50cfd025337ef5d67acc10cd8f29adab7716cf47c352/sqlalchemy-2.0.51-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1af05726b3d0cdba1c55284bf408fd3b792e690fe2399bfb8304565551cda652", size = 3244579, upload-time = "2026-06-15T16:10:36.165Z" }, - { url = "https://files.pythonhosted.org/packages/fc/97/e4a2eb5a8ec5cd3c2a0615a2f15f0afca89ac039229599b9ed0c0ed28e5e/sqlalchemy-2.0.51-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e54ff2dd657f2e3e0fbf2b097db1182f7bfea263eca4353f00065bae2a67c3d", size = 3243515, upload-time = "2026-06-15T16:12:22.627Z" }, - { url = "https://files.pythonhosted.org/packages/74/c6/5900ec624fab3360aa2ec59b99bb2046dd79799e310bb78a0514eaa4038e/sqlalchemy-2.0.51-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1e47b1199c2e832e325eacabc8d32d2487f58c9358f97e9a00f5eb93c5680d84", size = 3195492, upload-time = "2026-06-15T16:10:38.097Z" }, - { url = "https://files.pythonhosted.org/packages/8f/41/2ee3c4e1ac4fd22309349823fe13f33febeab1a71db1d7e9d60293a07dcb/sqlalchemy-2.0.51-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c68568f3facf8f66fa76c60e0ced69b67666ffa9941d1d0a3756fda196049080", size = 3215782, upload-time = "2026-06-15T16:12:24.051Z" }, - { url = "https://files.pythonhosted.org/packages/ce/1c/3bd72c341f1cb5faed5a7457ea840228a46be51cfbaf31a9db72fc963f11/sqlalchemy-2.0.51-cp310-cp310-win32.whl", hash = "sha256:0592bdadf86ddcabfd72d9ab66ea8a5d8d2cc6be1cc51fa7e66c03868ac5eac1", size = 2122119, upload-time = "2026-06-15T16:13:26.915Z" }, - { url = "https://files.pythonhosted.org/packages/2a/63/b6dfdd646abf91c3bedb13727226a5e765e5f8365e898d43818e6672fa46/sqlalchemy-2.0.51-cp310-cp310-win_amd64.whl", hash = "sha256:740cf6f35351b1ac3d82369152acf1d51d37e3dcf85d4dc0a22ca01410eabe2a", size = 2145158, upload-time = "2026-06-15T16:13:28.386Z" }, - { url = "https://files.pythonhosted.org/packages/3a/69/a67c69e5f28fc9c99d6f7bd60bd50e91f2fed2423e3b30fb228fa00e51f3/sqlalchemy-2.0.51-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1aa10c0daee6705294d181daadaa793221e1a59ed55000a3fab1d42b088ce4ba", size = 2161838, upload-time = "2026-06-15T16:05:17.144Z" }, - { url = "https://files.pythonhosted.org/packages/9a/a4/c8c22b8438bddc0a030157c6ec0f6ef97b3c38effa444bdab2a27af04090/sqlalchemy-2.0.51-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5b2ed6d828f1f09bd812861f4f59ca3bc3803f9df871f4555187f0faf018604", size = 3319402, upload-time = "2026-06-15T16:10:40.002Z" }, - { url = "https://files.pythonhosted.org/packages/90/54/44012d32fd77d991256d2ff793ba3807c51d40cb27a85b4796224f6744df/sqlalchemy-2.0.51-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:436728ce18a80f6951a1e11cc6112c2ede9faf20766f1a26195a7c441ca12dbd", size = 3319675, upload-time = "2026-06-15T16:12:25.658Z" }, - { url = "https://files.pythonhosted.org/packages/29/a5/de0592acaf5906cd7430874392d6f7e8b4a7c8437610953ee2d1501c0b44/sqlalchemy-2.0.51-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dc261707bf5739aea8a541593f3cc1d463c2701fb05fbcbba0ce031b69a21260", size = 3270777, upload-time = "2026-06-15T16:10:42.125Z" }, - { url = "https://files.pythonhosted.org/packages/cb/14/a44c90739c780b362238e4ac3cb19dd0ca40d13e6ddc5daa112166ddab4f/sqlalchemy-2.0.51-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a6d26094615306d116dd5e4a51b0304c99dd2356fc569eed6922a80a6bd3b265", size = 3293940, upload-time = "2026-06-15T16:12:27.156Z" }, - { url = "https://files.pythonhosted.org/packages/65/eb/fbd0f206a330e66f8c602a99c37c4e731f107faed62954b41b01f16dd9d9/sqlalchemy-2.0.51-cp311-cp311-win32.whl", hash = "sha256:ca8435d13829b92f4a97362d91975154a4015db3a2634154e1754e9a915e6b86", size = 2121183, upload-time = "2026-06-15T16:13:29.905Z" }, - { url = "https://files.pythonhosted.org/packages/ad/fd/005bf80f3cf6e5c62b5dd68616280f51cd012c60840fa74781b3ed7b1623/sqlalchemy-2.0.51-cp311-cp311-win_amd64.whl", hash = "sha256:4a011ea4510683319ce4ed274b56ee05194b39b6da9d09ca7a39388f0fa84dcc", size = 2145796, upload-time = "2026-06-15T16:13:31.283Z" }, - { url = "https://files.pythonhosted.org/packages/d5/70/e868bc5412acd101a8280f25c95f10eeae0771c4eb806b02491142810ee8/sqlalchemy-2.0.51-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d78702b26ba1c18b2d0fb2ea940ba7f17a9581b42e8361ff93920ebbee1235a", size = 2160291, upload-time = "2026-06-15T16:08:48.918Z" }, - { url = "https://files.pythonhosted.org/packages/e5/1c/71ee0f8a6b9d7316a1ccd30430b4c62b6c2e36adc96017a4e3a72dce49d6/sqlalchemy-2.0.51-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581921d849d6e6f994d560389192955e80e2950e18fcdfe2ccea863e01158e6e", size = 3343835, upload-time = "2026-06-15T16:19:42.613Z" }, - { url = "https://files.pythonhosted.org/packages/2b/7c/7ab9f9aadc5944fdd06612484ed7918fe376ad871a5f50404dc1536e0194/sqlalchemy-2.0.51-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1d21ce524ab86c23046e992a5b81cb54c21079c6df6e78b8fc77d77cac70a6b9", size = 3358470, upload-time = "2026-06-15T16:26:38.011Z" }, - { url = "https://files.pythonhosted.org/packages/d0/7d/ff77169fee6186de145a7f2b87006c39638391130abbab2b1f63ac6ea583/sqlalchemy-2.0.51-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c5d98a2709840027f5a347c3af0a7c3d5f6c1ff93af2ca1c54494e23cba8f389", size = 3289874, upload-time = "2026-06-15T16:19:45.212Z" }, - { url = "https://files.pythonhosted.org/packages/6f/3b/6c505903710d781b55bc3141ee34a062bf9745a6b5bc7333305b9ed63b33/sqlalchemy-2.0.51-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1181256e0f16479691b5616d36375dc2620ad8332b25978763c3d206ad3f3f1d", size = 3321692, upload-time = "2026-06-15T16:26:39.747Z" }, - { url = "https://files.pythonhosted.org/packages/3c/b7/c5ffe50aa2f4d947c9250e1519d939260329a07fe6272edfccd784b3d007/sqlalchemy-2.0.51-cp312-cp312-win32.whl", hash = "sha256:9f380393be5abeb6815f68fd39271b95127173511b6706b0a630a9995d53f8f5", size = 2119674, upload-time = "2026-06-15T16:23:09.543Z" }, - { url = "https://files.pythonhosted.org/packages/25/dc/46a65916af68a06ef6b972c6050ba4c8f97070fe3fb33097d34229d9bef6/sqlalchemy-2.0.51-cp312-cp312-win_amd64.whl", hash = "sha256:2cf39aabdf48e87c1c2c2ed6d20d33ffa0733b3071ce9c5f66357947dd009080", size = 2146670, upload-time = "2026-06-15T16:23:11.048Z" }, - { url = "https://files.pythonhosted.org/packages/54/fe/a210d52fd1a90ecfae8a78e9d8b27e18d733d60818a8bf250ff690b75120/sqlalchemy-2.0.51-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7c2056838b6685b72fdb36c99996cf862753461a62f2e84f4196371d3b2d6a07", size = 2157184, upload-time = "2026-06-15T16:08:50.374Z" }, - { url = "https://files.pythonhosted.org/packages/17/6b/2dce8369b199cb855110e056032f94a9f66dacc2237d3d39c115a86eac56/sqlalchemy-2.0.51-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:483b11bd46bf35fc14c52faf338b04300c9e6ce554bce9b11be85bfec3bc3195", size = 3284735, upload-time = "2026-06-15T16:19:46.934Z" }, - { url = "https://files.pythonhosted.org/packages/53/ff/dbc495b8a14da840faffb353857a72d4190113cac33727906fb997047f0f/sqlalchemy-2.0.51-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1bed1ee8b01da6088210aa9412023326fb98a599ba502e6118308601dcbef77f", size = 3302756, upload-time = "2026-06-15T16:26:41.336Z" }, - { url = "https://files.pythonhosted.org/packages/cf/d5/fde8f4dddcf518ee15ab35a7c6a28acc32c8ba548d1d2aa451f96e6dbb0b/sqlalchemy-2.0.51-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:72ca54c952107ba5cd58854b67a5a6268631289d21651a1235396f3b98b47400", size = 3232055, upload-time = "2026-06-15T16:19:49.286Z" }, - { url = "https://files.pythonhosted.org/packages/67/d1/43d3a0ac955a58601c24fa23038b1c55ee3a1ec02c0f96ebb1eae2bcf614/sqlalchemy-2.0.51-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b3e693d15533a45cd5906f0589f9c35090bef6ef45bf1e8195c424aa0ae06a8d", size = 3269850, upload-time = "2026-06-15T16:26:43.017Z" }, - { url = "https://files.pythonhosted.org/packages/94/df/de669c7054cd47c4439ac34b1b2ee8b804a794791fbb10720e997a2c87c7/sqlalchemy-2.0.51-cp313-cp313-win32.whl", hash = "sha256:b93ab07b5292dbe7e6b8da89475275e7042744283921344b56105f3eeb0f828b", size = 2117721, upload-time = "2026-06-15T16:23:12.36Z" }, - { url = "https://files.pythonhosted.org/packages/d0/8a/403c51d064196bae20a0bc2476577f83a3f8dd299719a97417086b7f2ec5/sqlalchemy-2.0.51-cp313-cp313-win_amd64.whl", hash = "sha256:0f053118c30e53161857a953e4de667d90e274980dccbe5dd3829bbbeece72a5", size = 2143615, upload-time = "2026-06-15T16:23:13.906Z" }, - { url = "https://files.pythonhosted.org/packages/b1/49/a739be2e1d02a96a658eb71ab45d921c874249252358ad24a5bffdd02525/sqlalchemy-2.0.51-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6ea306caaae6bd5afd0a46050003c88f6bf33227377a49298c498c3cb88ff491", size = 2158999, upload-time = "2026-06-15T16:08:51.759Z" }, - { url = "https://files.pythonhosted.org/packages/23/6b/2e0e38cf75c8780eca78d9b2e78164f8bcfd70125e5caa588ff5cbb9c9f4/sqlalchemy-2.0.51-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c45a496d6bc05dec41dcd4c3a2b183723f47473255c159cd80b503c8f246424d", size = 3282539, upload-time = "2026-06-15T16:19:51.065Z" }, - { url = "https://files.pythonhosted.org/packages/dd/a1/e77854cb5336fd37dc3c6ae3b71de242c98caac5725120be0b526b31cbd0/sqlalchemy-2.0.51-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4004ada0aafe8ae1991b2cd1d99c6d9146126e123bd6f883c260d974aa012e54", size = 3287545, upload-time = "2026-06-15T16:26:44.735Z" }, - { url = "https://files.pythonhosted.org/packages/f6/ab/9e17272fd4dac8df3b83c4fbe52b998a1c9d89a843c8c35ff29b74ff7364/sqlalchemy-2.0.51-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0f6bcad487aee1c638d707235682fc96f741de00663619881ab235400d03289e", size = 3230929, upload-time = "2026-06-15T16:19:52.625Z" }, - { url = "https://files.pythonhosted.org/packages/02/3c/52f408ea701781caee975606beccc48845f2aee8711ac29843d612c0306c/sqlalchemy-2.0.51-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:39a76529db6305693d8d4affa58ad5b5e2e18edd62daea628b29b97930b3513d", size = 3252888, upload-time = "2026-06-15T16:26:46.454Z" }, - { url = "https://files.pythonhosted.org/packages/24/16/3efd2ee6bc4ca4693a30a1dd17a91b606cae15d517d2a4746611d9b73ce8/sqlalchemy-2.0.51-cp314-cp314-win32.whl", hash = "sha256:08a204d8b5638717c26a24df18fcf40af45a6b22e35b70b1d62f0113c2e278e8", size = 2120551, upload-time = "2026-06-15T16:23:15.629Z" }, - { url = "https://files.pythonhosted.org/packages/7b/78/55b12e70f45bccc40d9e483925c065027b3b98ea4cbbdf6f8c2546feaf6c/sqlalchemy-2.0.51-cp314-cp314-win_amd64.whl", hash = "sha256:96747bfbadb055466e5b46d572618170046b45ce5a4879167f50d70a5319a499", size = 2146318, upload-time = "2026-06-15T16:23:17.108Z" }, - { url = "https://files.pythonhosted.org/packages/21/db/a9574ed40fed418924b1b1a3e54f47ee3963053b3d3d325a0d36b41f2c08/sqlalchemy-2.0.51-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e5ea1a213be1fcd5e49d9904c3b9939211ded90bc2a64e93f4c01963474285de", size = 2178920, upload-time = "2026-06-15T15:59:56.285Z" }, - { url = "https://files.pythonhosted.org/packages/bf/90/a1bb5c7cbba76b7bc1fbd586d0a5479a7bc9c27b4a8298f22ec9423b2bb3/sqlalchemy-2.0.51-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c6b36ed71f41942bdcd2ad2522be46bfce09d5705be5640ecf19bbc7660e4b7", size = 3566534, upload-time = "2026-06-15T15:58:35.024Z" }, - { url = "https://files.pythonhosted.org/packages/15/4b/481f1fed30e0e9e8dd24aecbb49f29eb57fe7657ece5cf06ee9b84bb97d8/sqlalchemy-2.0.51-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c2c62877097e1a0db401fba5cb4debee33265e5b2a55c4ccb489c02c53b4f72", size = 3535844, upload-time = "2026-06-15T16:02:43.973Z" }, - { url = "https://files.pythonhosted.org/packages/02/71/0aa64aeda645510af0a43f7d9ee70932f0d1dc4263aed34c50ee891d9df3/sqlalchemy-2.0.51-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0378d055e9e8cd6ce4d8dff683bdd3d7d413533c4ee51d67a2b1e0f9eacc0f23", size = 3475355, upload-time = "2026-06-15T15:58:36.592Z" }, - { url = "https://files.pythonhosted.org/packages/05/db/6061db32316446135a3abae5f308d144ab988a34234726042da3e58b1c63/sqlalchemy-2.0.51-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6e46fc36029eff666391e0531e5387b62ce6c4f1d8e50b3fb3099eaca1b42522", size = 3486591, upload-time = "2026-06-15T16:02:45.346Z" }, - { url = "https://files.pythonhosted.org/packages/0d/c9/f14fdf71bb8957e0c7e39db69bbdf12b5c80f4ef775fdfa127bf4e0d6760/sqlalchemy-2.0.51-cp314-cp314t-win32.whl", hash = "sha256:9161cfc9efce70d1715f47d6ff40f79c6778c00d53be4fbc09d70301e4b83ba7", size = 2151313, upload-time = "2026-06-15T16:03:39.127Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c6/673e618e6f4f297e126d9b56ea2f6478708f6c1af4e3223835c22e2c3697/sqlalchemy-2.0.51-cp314-cp314t-win_amd64.whl", hash = "sha256:159bb6ba32059f57ad7375a8f50d844dd2f19d14954ecf820cd33e20debd46b2", size = 2186280, upload-time = "2026-06-15T16:03:40.569Z" }, - { url = "https://files.pythonhosted.org/packages/e2/22/dbf013a12ec759e54a34a119e9e217435b3f71b2dd5c61a7ade0a25dae87/sqlalchemy-2.0.51-py3-none-any.whl", hash = "sha256:bb024d8b621d0be75f4f44ecc7c950450026e76d66dc8f791bb5331d7fed59d5", size = 1944334, upload-time = "2026-06-15T16:09:22.418Z" }, -] - -[[package]] -name = "sqlalchemy-spanner" -version = "1.19.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "alembic" }, - { name = "google-cloud-spanner" }, - { name = "sqlalchemy" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/af/b6/ce05f1b8a9c486bbac26d7348625c78ba6e751decc25009f28880504c29d/sqlalchemy_spanner-1.19.0.tar.gz", hash = "sha256:834cec66fb418e5085a44c68cee570c594c66dd8535b67dd5e8be3571d172136", size = 82914, upload-time = "2026-06-03T16:14:49.721Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/38/8150a0022174d02956b0f6b586777006af2fc794b1baa72748a11fde039f/sqlalchemy_spanner-1.19.0-py3-none-any.whl", hash = "sha256:3367a89388d9b7106111fc48c7fac441163602c414ad157f62e18b5705cc760e", size = 31919, upload-time = "2026-06-03T16:13:39.522Z" }, -] - -[[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.4.4" @@ -4876,15 +4033,15 @@ wheels = [ [[package]] name = "starlette" -version = "0.52.1" +version = "1.3.1" 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/c4/68/79977123bb7be889ad680d79a40f339082c1978b5cfcf62c2d8d196873ac/starlette-0.52.1.tar.gz", hash = "sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933", size = 2653702, upload-time = "2026-01-18T13:34:11.062Z" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" }, + { url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" }, ] [[package]] @@ -4952,7 +4109,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.30.0" +version = "1.31.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "nexus-rpc" }, @@ -4961,19 +4118,24 @@ dependencies = [ { name = "types-protobuf" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/00/b0/ad8fc3cd7425c6551a637bf23c798e8fdd8eb7a3ec4fee4f46f7678ba8d2/temporalio-1.30.0.tar.gz", hash = "sha256:7c025919511bb465392d547e48ccb85fd560a995db4ebcc82fdb43cddf088e6f", size = 2686876, upload-time = "2026-07-02T21:04:46.713Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3c/43/676b56efaa64def06d4a9282cfc08d5a5b1c89de0ded47b692f8eaa30ca8/temporalio-1.31.0.tar.gz", hash = "sha256:2993f4b880170825414116dec7d7159a5d199efc279f29570be6b5c4a9f6edd5", size = 2785306, upload-time = "2026-07-29T17:55:10.995Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/39/842fdffe93388dd30ac12a53a698f71cbfb68b3bc938f30f3e5d6a36d4ad/temporalio-1.30.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:6773a6b708dee7675fcbb681bf28e48337ce43b8467ceba8f903e78ae68909f8", size = 14520026, upload-time = "2026-07-02T21:04:31.384Z" }, - { url = "https://files.pythonhosted.org/packages/40/f3/a2237d5265eb29de591abeac7610a48616b590a1b923b4919f60ee81adfa/temporalio-1.30.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:4038c3ce2d9acc12fef31dd16ef9be8cc7f721672da5662aa05e3942d0b5c9d1", size = 14018523, upload-time = "2026-07-02T21:04:34.405Z" }, - { url = "https://files.pythonhosted.org/packages/e6/57/dc648d812f4c688bd246a616f0d65c5f03b33675df2effb1b480e1df6d21/temporalio-1.30.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:108d1a56e174eabc18add58316084cdead230e239d3df22bbe999d6954986591", size = 14330502, upload-time = "2026-07-02T21:04:37.39Z" }, - { url = "https://files.pythonhosted.org/packages/1c/e1/dbd57de0f5090891850c2ee5490319834a12b704076b11f32a4a149998d4/temporalio-1.30.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47b156138de30c2cd6723d5bfc06a30abcf680344c5481abb31f2a98a9b1f809", size = 14833364, upload-time = "2026-07-02T21:04:40.454Z" }, - { url = "https://files.pythonhosted.org/packages/30/2a/6d41289c11465ba276a8b417f31d2e469f0fe4b8afacd61d5244151c5fce/temporalio-1.30.0-cp310-abi3-win_amd64.whl", hash = "sha256:3adee28d5ec47bd6309a5eeef7b00126373f119bc5c1b058a34de098542f4da7", size = 15181893, upload-time = "2026-07-02T21:04:43.609Z" }, + { url = "https://files.pythonhosted.org/packages/c2/7c/b91d831df50651a26562285de7c434a14243504eed853513da6e6afa3f19/temporalio-1.31.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:5f9aaf06000768eb80cf5774457d227379dae455a3099aa0a18c4dca631c0d27", size = 14505266, upload-time = "2026-07-29T17:54:52.932Z" }, + { url = "https://files.pythonhosted.org/packages/d6/d9/4655fc5d7ea662aac2af972e114ffeae45800bcded5ca3d31b2bcd99179d/temporalio-1.31.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:abbfb486ba00053ccfa57c9c38b38f80f5dbfd08c67beb7a621515a57a9b9e9b", size = 14037187, upload-time = "2026-07-29T17:54:55.771Z" }, + { url = "https://files.pythonhosted.org/packages/52/8e/52bd6a90cba3d4b257d7aa7426598e622cf05ab39a174b477535eba59c14/temporalio-1.31.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e840b462125274cb0d4748e7cedc386c303b2a51bf76bab30b96f1ebbc657ae", size = 14445065, upload-time = "2026-07-29T17:54:58.254Z" }, + { url = "https://files.pythonhosted.org/packages/d9/91/b644c2122943939e02c0e0ff1902b9c6ff7d5e0d6eec334abbfd4ee6bb17/temporalio-1.31.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04d26f0f634f5325f6a19a45cd67cc5a2da4bd35268d27997f6723134d38c8be", size = 14831115, upload-time = "2026-07-29T17:55:00.923Z" }, + { url = "https://files.pythonhosted.org/packages/8f/42/abc82a89323234026753ac801a1dbc36b4322dcdec5f1e38bee6405f3493/temporalio-1.31.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f23f36d0e5d2e67f2129fc1cb876cf1e4e614f791a717d692f7c15fb732abe41", size = 14542828, upload-time = "2026-07-29T17:55:03.378Z" }, + { url = "https://files.pythonhosted.org/packages/8d/67/9260f4544eb5d44867ef58e4a0e63dd3d643e26b2a94e21e027ceaeb0059/temporalio-1.31.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:52f8cc7f0b5a19d49f0c2d748420267aaacc2be0bb614743de8d10faf77a57c9", size = 15019517, upload-time = "2026-07-29T17:55:05.758Z" }, + { url = "https://files.pythonhosted.org/packages/ce/96/b71e66a1921906f072038286e30946098531fd3363029f3d08c1723aa39a/temporalio-1.31.0-cp310-abi3-win_amd64.whl", hash = "sha256:aa6e9602829584b22037da6ccf99d2e089f02cec86ee7178206b1afb115cf092", size = 15527552, upload-time = "2026-07-29T17:55:08.287Z" }, ] [package.optional-dependencies] google-adk = [ { name = "google-adk" }, ] +google-genai = [ + { name = "google-genai" }, +] langgraph = [ { name = "langgraph" }, ] @@ -5051,6 +4213,10 @@ google-adk = [ { name = "google-adk" }, { name = "temporalio", extra = ["google-adk"] }, ] +google-genai = [ + { name = "mcp" }, + { name = "temporalio", extra = ["google-genai", "pydantic"] }, +] langgraph = [ { name = "langchain" }, { name = "langchain-anthropic" }, @@ -5095,7 +4261,7 @@ trio-async = [ [package.metadata] requires-dist = [ { name = "protobuf", specifier = ">=5.29.6,<6" }, - { name = "temporalio", specifier = ">=1.30.0,<2" }, + { name = "temporalio", specifier = ">=1.31.0,<2" }, ] [package.metadata.requires-dev] @@ -5136,19 +4302,23 @@ external-storage = [ external-storage-redis = [{ name = "redis", specifier = ">=5.0.0,<8" }] gevent = [{ name = "gevent", marker = "python_full_version >= '3.8'", specifier = ">=25.4.2" }] google-adk = [ - { name = "google-adk", specifier = ">=1.27.0,<2" }, - { name = "temporalio", extras = ["google-adk"], specifier = ">=1.30.0" }, + { name = "google-adk", specifier = ">=2.2.0,<3" }, + { name = "temporalio", extras = ["google-adk"], specifier = ">=1.31.0" }, +] +google-genai = [ + { name = "mcp", specifier = ">=1.0.0" }, + { name = "temporalio", extras = ["google-genai", "pydantic"], specifier = ">=1.31.0" }, ] langgraph = [ { name = "langchain", specifier = ">=0.3.0" }, { name = "langchain-anthropic", specifier = ">=0.3.0" }, { name = "langgraph", specifier = ">=1.1.3" }, - { name = "temporalio", extras = ["langgraph", "langsmith"], specifier = ">=1.30.0" }, + { name = "temporalio", extras = ["langgraph", "langsmith"], specifier = ">=1.31.0" }, ] langsmith-tracing = [ { name = "langsmith", specifier = ">=0.7.0" }, { name = "openai", specifier = ">=1.4.0" }, - { name = "temporalio", extras = ["pydantic", "langsmith"], specifier = ">=1.30.0" }, + { name = "temporalio", extras = ["pydantic", "langsmith"], specifier = ">=1.31.0" }, ] nexus = [{ name = "nexus-rpc", specifier = ">=1.1.0,<2" }] open-telemetry = [ @@ -5158,7 +4328,7 @@ open-telemetry = [ openai-agents = [ { name = "openai-agents", extras = ["litellm"], specifier = ">=0.14.1" }, { name = "requests", specifier = ">=2.32.0,<3" }, - { name = "temporalio", extras = ["openai-agents", "opentelemetry"], specifier = ">=1.30.0" }, + { name = "temporalio", extras = ["openai-agents", "opentelemetry"], specifier = ">=1.31.0" }, ] pydantic-converter = [{ name = "pydantic", specifier = ">=2.10.6,<3" }] sentry = [{ name = "sentry-sdk", specifier = ">=2.13.0" }] @@ -5167,7 +4337,7 @@ strands-agents = [ { name = "mcp", specifier = ">=1.0.0" }, { name = "strands-agents", specifier = ">=1.39.0" }, { name = "strands-agents-tools", specifier = ">=0.5.2" }, - { name = "temporalio", extras = ["strands-agents", "pydantic"], specifier = ">=1.30.0" }, + { name = "temporalio", extras = ["strands-agents", "pydantic"], specifier = ">=1.31.0" }, ] trio-async = [ { name = "trio", specifier = ">=0.28.0,<0.29" }, @@ -5458,15 +4628,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/42/28/fc144409c71569e928585f8f3c629d80d1ca3ef40175e9222f01588f98c9/tzlocal-5.4.3-py3-none-any.whl", hash = "sha256:24ce97bb58e2a973f7640ec2553ab4e6f6d5a0d0d1aa9dc43bca21d89e1feb82", size = 18039, upload-time = "2026-06-17T04:17:40.027Z" }, ] -[[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.7.0"